Whamcloud - gitweb
84da81489a8a32d153b3dfb4d49f95310922cda4
[fs/lustre-release.git] / lnet / tests / ping_srv.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
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>
8  *
9  *
10  * This file is part of Portals, http://www.sf.net/projects/lustre/
11  *
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.
15  *
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.
20  *
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.
24  */
25
26 #define DEBUG_SUBSYSTEM S_PINGER
27
28 #include <linux/kp30.h>
29 #include <portals/p30.h>
30 #include "ping.h"
31
32 #include <linux/module.h>
33 #include <linux/proc_fs.h>
34 #include <linux/init.h>
35 #include <linux/kernel.h>
36 #include <linux/sched.h>
37 #include <linux/version.h>
38 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
39 #include <linux/workqueue.h>
40 #else
41 #include <linux/tqueue.h>
42 #endif
43 #include <linux/wait.h>
44 #include <linux/smp_lock.h>
45
46 #include <asm/unistd.h>
47 #include <asm/semaphore.h>
48
49 #define STDSIZE (sizeof(int) + sizeof(int) + sizeof(struct timeval))
50 #define MAXSIZE (16*1024)
51
52 static unsigned ping_head_magic;
53 static unsigned ping_bulk_magic;
54 static int nal  = SOCKNAL;                            // Your NAL,
55 static unsigned long packets_valid = 0;         // Valid packets 
56 static int running = 1;
57 atomic_t pkt;
58        
59 static struct pingsrv_data *server=NULL;             // Our ping server
60
61 static void *pingsrv_shutdown(int err)
62 {
63         int rc;
64
65         /* Yes, we are intentionally allowing us to fall through each
66          * case in to the next.  This allows us to pass an error
67          * code to just clean up the right stuff.
68          */
69         switch (err) {
70                 case 1:
71                         /* Unlink any memory descriptors we may have used */
72                         if ((rc = PtlMDUnlink (server->mdin_h)))
73                                 PDEBUG ("PtlMDUnlink (out head buffer)", rc);
74                 case 2:
75                         /* Free the event queue */
76                         if ((rc = PtlEQFree (server->eq)))
77                                 PDEBUG ("PtlEQFree", rc);
78
79                         /* Unlink the client portal from the ME list */
80                         if ((rc = PtlMEUnlink (server->me)))
81                                         PDEBUG ("PtlMEUnlink", rc);
82
83                 case 3:
84                         PtlNIFini (server->ni);
85
86                 case 4:
87                         
88                 case 5:
89                         if (server->in_buf != NULL)
90                                 PORTAL_FREE (server->in_buf, MAXSIZE);
91                         
92                         if (server != NULL)
93                                 PORTAL_FREE (server, 
94                                              sizeof (struct pingsrv_data));
95                         
96         }
97
98         CDEBUG (D_OTHER, "ping sever resources released\n");
99         return NULL;
100 } /* pingsrv_shutdown() */
101
102
103 int pingsrv_thread(void *arg)
104 {
105         int rc;
106         unsigned long magic;
107         unsigned long ping_bulk_magic = 0xcafebabe;
108         
109         kportal_daemonize ("pingsrv");
110         server->tsk =  current;
111         
112         while (running) {
113                 set_current_state (TASK_INTERRUPTIBLE);
114                 if (atomic_read (&pkt) == 0) {
115                         schedule_timeout (MAX_SCHEDULE_TIMEOUT);
116                         continue;
117                 }
118                
119                 magic =  *((int *)(server->evnt.mem_desc.start 
120                                         + server->evnt.offset));
121                 
122                 
123                 if(magic != 0xdeadbeef) {
124                         printk("LustreError: Unexpected Packet to the server\n");
125                         
126                 } 
127                 memcpy (server->in_buf, &ping_bulk_magic, sizeof(ping_bulk_magic));
128                                 
129                 server->mdout.length    = server->evnt.rlength;
130                 server->mdout.start     = server->in_buf;
131                 server->mdout.threshold = 1; 
132                 server->mdout.options   = PTL_MD_EVENT_START_DISABLE | PTL_MD_OP_PUT;
133                 server->mdout.user_ptr  = NULL;
134                 server->mdout.eventq    = PTL_EQ_NONE;
135        
136                 /* Bind the outgoing buffer */
137                 if ((rc = PtlMDBind (server->ni, server->mdout, 
138                                      PTL_UNLINK, &server->mdout_h))) {
139                          PDEBUG ("PtlMDBind", rc);
140                          pingsrv_shutdown (1);
141                          return 1;
142                 }
143          
144                 
145                 server->mdin.start     = server->in_buf;
146                 server->mdin.length    = MAXSIZE;
147                 server->mdin.threshold = 1; 
148                 server->mdin.options   = PTL_MD_EVENT_START_DISABLE | PTL_MD_OP_PUT;
149                 server->mdin.user_ptr  = NULL;
150                 server->mdin.eventq    = server->eq;
151         
152                 if ((rc = PtlMDAttach (server->me, server->mdin,
153                         PTL_UNLINK, &server->mdin_h))) {
154                         PDEBUG ("PtlMDAttach (bulk)", rc);
155                         CDEBUG (D_OTHER, "ping server resources allocated\n");
156                 }
157                 
158                 if ((rc = PtlPut (server->mdout_h, PTL_NOACK_REQ,
159                          server->evnt.initiator, PTL_PING_CLIENT, 0, 0, 0, 0)))
160                          PDEBUG ("PtlPut", rc);
161                 
162                 atomic_dec (&pkt);
163                 
164         }
165         pingsrv_shutdown (1);
166         running = 1;
167         return 0;    
168 }
169
170 static void pingsrv_packet(ptl_event_t *ev)
171 {
172         atomic_inc (&pkt);
173         wake_up_process (server->tsk);
174 } /* pingsrv_head() */
175
176 static void pingsrv_callback(ptl_event_t *ev)
177 {
178         
179         if (ev == NULL) {
180                 CERROR ("null in callback, ev=%p\n", ev);
181                 return;
182         }
183         server->evnt = *ev;
184         
185         printk ("Lustre: received ping from nid "LPX64" "
186                "(off=%u rlen=%u mlen=%u head=%x seq=%d size=%d)\n",
187                ev->initiator.nid, ev->offset, ev->rlength, ev->mlength,
188                *((int *)(ev->mem_desc.start + ev->offset)),
189                *((int *)(ev->mem_desc.start + ev->offset + sizeof(unsigned))),
190                *((int *)(ev->mem_desc.start + ev->offset + 2 * 
191                                sizeof(unsigned))));
192         
193         packets_valid++;
194
195         pingsrv_packet(ev);
196         
197 } /* pingsrv_callback() */
198
199
200 static struct pingsrv_data *pingsrv_setup(void)
201 {
202         int rc;
203
204         server->ni = PTL_INVALID_HANDLE;
205
206        /* Aquire and initialize the proper nal for portals. */
207         rc = PtlNIInit(nal, 0, NULL, NULL, &server->ni);
208         if (!(rc == PTL_OK || rc == PTL_IFACE_DUP)) {
209                 CDEBUG (D_OTHER, "NAL %d not loaded\n", nal);
210                 return pingsrv_shutdown (4);
211         }
212
213
214         /* Based on the initialization aquire our unique portal ID. */
215         if ((rc = PtlGetId (server->ni, &server->my_id))) {
216                 PDEBUG ("PtlGetId", rc);
217                 return pingsrv_shutdown (2);
218         }
219
220         server->id_local.nid = PTL_NID_ANY;
221         server->id_local.pid = PTL_PID_ANY;
222
223         /* Attach a match entries for header packets */
224         if ((rc = PtlMEAttach (server->ni, PTL_PING_SERVER,
225             server->id_local,0, ~0,
226             PTL_RETAIN, PTL_INS_AFTER, &server->me))) {
227                 PDEBUG ("PtlMEAttach", rc);
228                 return pingsrv_shutdown (2);
229         }
230
231
232         if ((rc = PtlEQAlloc (server->ni, 1024, &pingsrv_callback,
233                                         &server->eq))) {
234                 PDEBUG ("PtlEQAlloc (callback)", rc);
235                 return pingsrv_shutdown (2);
236         }
237         
238         PORTAL_ALLOC (server->in_buf, MAXSIZE);
239         if(!server->in_buf){
240                 CDEBUG (D_OTHER,"Allocation error\n");
241                 return pingsrv_shutdown(2);
242         }
243         
244         /* Setup the incoming buffer */
245         server->mdin.start     = server->in_buf;
246         server->mdin.length    = MAXSIZE;
247         server->mdin.threshold = 1; 
248         server->mdin.options   = PTL_MD_EVENT_START_DISABLE | PTL_MD_OP_PUT;
249         server->mdin.user_ptr  = NULL;
250         server->mdin.eventq    = server->eq;
251         memset (server->in_buf, 0, STDSIZE);
252         
253         if ((rc = PtlMDAttach (server->me, server->mdin,
254                 PTL_UNLINK, &server->mdin_h))) {
255                     PDEBUG ("PtlMDAttach (bulk)", rc);
256                 CDEBUG (D_OTHER, "ping server resources allocated\n");
257        }
258  
259         /* Success! */
260         return server; 
261 } /* pingsrv_setup() */
262
263 static int pingsrv_start(void)
264 {
265         /* Setup our server */
266         if (!pingsrv_setup()) {
267                 CDEBUG (D_OTHER, "pingsrv_setup() failed, server stopped\n");
268                 return -ENOMEM;
269         }
270         kernel_thread (pingsrv_thread,NULL,0);
271         return 0;
272 } /* pingsrv_start() */
273
274
275
276 static int __init pingsrv_init(void)
277 {
278         ping_head_magic = PING_HEADER_MAGIC;
279         ping_bulk_magic = PING_BULK_MAGIC;
280         PORTAL_ALLOC (server, sizeof(struct pingsrv_data));  
281         return pingsrv_start ();
282 } /* pingsrv_init() */
283
284
285 static void /*__exit*/ pingsrv_cleanup(void)
286 {
287         remove_proc_entry ("net/pingsrv", NULL);
288         
289         running = 0;
290         wake_up_process (server->tsk);
291         while (running != 1) {
292                 set_current_state (TASK_UNINTERRUPTIBLE);
293                 schedule_timeout (HZ);
294         }
295         
296 } /* pingsrv_cleanup() */
297
298
299 MODULE_PARM(nal, "i");
300 MODULE_PARM_DESC(nal, "Use the specified NAL "
301                 "(6-kscimacnal, 2-ksocknal, 1-kqswnal)");
302  
303 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
304 MODULE_DESCRIPTION("A kernel space ping server for portals testing");
305 MODULE_LICENSE("GPL");
306
307 module_init(pingsrv_init);
308 module_exit(pingsrv_cleanup);