Whamcloud - gitweb
22eefbfec7eca1c8586bdd473d1c216cc6ede6a9
[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 <libcfs/kp30.h>
29 #include <lnet/lnet.h>
30 #include "ping.h"
31
32 #define STDSIZE (sizeof(int) + sizeof(int) + sizeof(struct timeval))
33 #define MAXSIZE (16*1024)
34
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;
39 atomic_t pkt;
40        
41 static struct pingsrv_data *server=NULL;             // Our ping server
42
43 static void *pingsrv_shutdown(int err)
44 {
45         int rc;
46
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.
50          */
51         switch (err) {
52                 case 1:
53                         /* Unlink any memory descriptors we may have used */
54                         if ((rc = LNetMDUnlink (server->mdin_h)))
55                                 PDEBUG ("LNetMDUnlink (out head buffer)", rc);
56                 case 2:
57                         /* Free the event queue */
58                         if ((rc = LNetEQFree (server->eq)))
59                                 PDEBUG ("LNetEQFree", rc);
60
61                         /* Unlink the client portal from the ME list */
62                         if ((rc = LNetMEUnlink (server->me)))
63                                         PDEBUG ("LNetMEUnlink", rc);
64
65                 case 3:
66                         LNetNIFini ();
67
68                 case 4:
69                         
70                 case 5:
71                         if (server->in_buf != NULL)
72                                 LIBCFS_FREE (server->in_buf, MAXSIZE);
73                         
74                         if (server != NULL)
75                                 LIBCFS_FREE (server, 
76                                              sizeof (struct pingsrv_data));
77                         
78         }
79
80         CDEBUG (D_OTHER, "ping sever resources released\n");
81         return NULL;
82 } /* pingsrv_shutdown() */
83
84
85 int pingsrv_thread(void *arg)
86 {
87         int rc;
88         unsigned long magic;
89         unsigned long ping_bulk_magic = __cpu_to_le32(0xcafebabe);
90         
91         cfs_daemonize ("pingsrv");
92         server->tsk =  cfs_current();
93         
94         while (running) {
95                 set_current_state (CFS_TASK_INTERRUPTIBLE);
96                 if (atomic_read (&pkt) == 0) {
97                         cfs_schedule_timeout (CFS_TASK_INTERRUPTIBLE, 
98                                               MAX_SCHEDULE_TIMEOUT);
99                         continue;
100                 }
101                
102                 magic =  __le32_to_cpu(*((int *)((char *)server->evnt.md.start 
103                                         + server->evnt.offset)));
104                 
105                 
106                 if(magic != 0xdeadbeef) {
107                         CERROR("Unexpected Packet to the server, magic: %lx %d\n", magic, server->evnt.offset);
108                         
109                 } 
110                 memcpy (server->in_buf, &ping_bulk_magic, sizeof(ping_bulk_magic));
111                                 
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;
118        
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);
124                          return 1;
125                 }
126          
127                 
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;
134         
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");
139                 }
140                 
141                 if ((rc = LNetPut (server->evnt.target.nid, server->mdout_h, 
142                                    LNET_NOACK_REQ,
143                                    server->evnt.initiator, PTL_PING_CLIENT, 
144                                    0, 0, 0)))
145                          PDEBUG ("LNetPut", rc);
146                 
147                 atomic_dec (&pkt);
148                 
149         }
150         pingsrv_shutdown (1);
151         running = 1;
152         return 0;    
153 }
154
155 static void pingsrv_packet(lnet_event_t *ev)
156 {
157         atomic_inc (&pkt);
158         wake_up_process (server->tsk);
159 } /* pingsrv_head() */
160
161 static void pingsrv_callback(lnet_event_t *ev)
162 {
163         
164         if (ev == NULL) {
165                 CERROR ("null in callback, ev=%p\n", ev);
166                 return;
167         }
168         server->evnt = *ev;
169         
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)))));
178         
179         packets_valid++;
180
181         pingsrv_packet(ev);
182         
183 } /* pingsrv_callback() */
184
185
186 static struct pingsrv_data *pingsrv_setup(void)
187 {
188         int rc;
189
190         /* Aquire and initialize the proper nal for portals. */
191         rc = LNetNIInit(0);
192         if (!(rc == 0 || rc == 1)) {
193                 CDEBUG (D_OTHER, "LNetNIInit: error %d\n", rc);
194                 return pingsrv_shutdown (4);
195         }
196
197
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);
202         }
203
204         server->id_local.nid = LNET_NID_ANY;
205         server->id_local.pid = LNET_PID_ANY;
206
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);
213         }
214
215
216         if ((rc = LNetEQAlloc (1024, &pingsrv_callback, &server->eq))) {
217                 PDEBUG ("LNetEQAlloc (callback)", rc);
218                 return pingsrv_shutdown (2);
219         }
220         
221         LIBCFS_ALLOC (server->in_buf, MAXSIZE);
222         if(!server->in_buf){
223                 CDEBUG (D_OTHER,"Allocation error\n");
224                 return pingsrv_shutdown(2);
225         }
226         
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);
235
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");
240        }
241
242         /* Success! */
243         return server;
244 } /* pingsrv_setup() */
245
246 static int pingsrv_start(void)
247 {
248         long pid;
249
250         /* Setup our server */
251         if (!pingsrv_setup()) {
252                 CDEBUG (D_OTHER, "pingsrv_setup() failed, server stopped\n");
253                 return -ENOMEM;
254         }
255         pid = cfs_kernel_thread (pingsrv_thread,NULL,0);
256         if (pid < 0) {
257                 CERROR("Can't start pingsrv thread: rc = %ld\n", pid);
258                 return (int)pid;
259         }
260
261         return 0;
262 } /* pingsrv_start() */
263
264 static int __init pingsrv_init(void)
265 {
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));  
269         atomic_set(&pkt, 0);
270         return pingsrv_start ();
271 } /* pingsrv_init() */
272
273 static void /*__exit*/ pingsrv_cleanup(void)
274 {
275         cfs_remove_proc_entry ("net/pingsrv", NULL);
276         
277         running = 0;
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));
282         }
283         
284 } /* pingsrv_cleanup() */
285
286
287 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
288 MODULE_DESCRIPTION("A kernel space ping server for portals testing");
289 MODULE_LICENSE("GPL");
290
291 cfs_module(ping_srv, "1.0.0", pingsrv_init, pingsrv_cleanup);