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