Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / portals / tests / ping_cli.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  *         Kedar Sovani (kedar@calsoftinc.com)
7  *         Amey Inamdar (amey@calsoftinc.com)
8  *
9  * This file is part of Portals, http://www.sf.net/projects/lustre/
10  *
11  * Portals is free software; you can redistribute it and/or
12  * modify it under the terms of version 2 of the GNU General Public
13  * License as published by the Free Software Foundation.
14  *
15  * Portals is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Portals; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25
26 #define DEBUG_SUBSYSTEM S_PINGER
27
28 #include <linux/kp30.h>
29 #include <portals/p30.h>
30 #include <linux/module.h>
31 #include <linux/proc_fs.h>
32 #include <linux/init.h>
33 #include <linux/poll.h>
34 #include "ping.h"
35 /* int portal_debug = D_PING_CLI;  */
36
37
38 #define STDSIZE (sizeof(int) + sizeof(int) + sizeof(struct timeval))
39
40 #define MAX_TIME 100000
41
42 /* This should be enclosed in a structure */
43
44 static struct pingcli_data *client = NULL;
45
46 static int count = 0;
47
48 static void
49 pingcli_shutdown(ptl_handle_ni_t nih, int err)
50 {
51         int rc;
52
53         /* Yes, we are intentionally allowing us to fall through each
54          * case in to the next.  This allows us to pass an error
55          * code to just clean up the right stuff.
56          */
57         switch (err) {
58                 case 1:
59                         /* Unlink any memory descriptors we may have used */
60                         if ((rc = PtlMDUnlink (client->md_out_head_h)))
61                                 PDEBUG ("PtlMDUnlink", rc);
62                 case 2:
63                         if ((rc = PtlMDUnlink (client->md_in_head_h)))
64                                 PDEBUG ("PtlMDUnlink", rc);
65
66                         /* Free the event queue */
67                         if ((rc = PtlEQFree (client->eq)))
68                                 PDEBUG ("PtlEQFree", rc);
69
70                         if ((rc = PtlMEUnlink (client->me)))
71                                 PDEBUG ("PtlMEUnlink", rc);
72                 case 3:
73                         PtlNIFini(nih);
74
75                 case 4:
76                         /* Free our buffers */
77
78                         if (client != NULL)
79                                 PORTAL_FREE (client,
80                                                 sizeof(struct pingcli_data));
81         }
82
83
84         CDEBUG (D_OTHER, "ping client released resources\n");
85 } /* pingcli_shutdown() */
86
87 static void pingcli_callback(ptl_event_t *ev)
88 {
89         int i, magic;
90         i = *(int *)(ev->md.start + ev->offset + sizeof(unsigned));
91         magic = *(int *)(ev->md.start + ev->offset);
92
93         if(magic != 0xcafebabe) {
94                 CERROR("Unexpected response %x\n", magic);
95         }
96
97         if((i == count) || !count)
98                 wake_up_process (client->tsk);
99         else
100                 CERROR("Received response after timeout for %d\n",i);
101 }
102
103
104 static struct pingcli_data *
105 pingcli_start(struct portal_ioctl_data *args)
106 {
107         ptl_handle_ni_t nih = PTL_INVALID_HANDLE;
108         unsigned ping_head_magic = PING_HEADER_MAGIC;
109         unsigned ping_bulk_magic = PING_BULK_MAGIC;
110         int rc;
111         struct timeval tv1, tv2;
112         char str[PTL_NALFMT_SIZE];
113         
114         client->tsk = current;
115         client->args = args;
116         CDEBUG (D_OTHER, "pingcli_setup args: nid "LPX64" (%s),  \
117                         nal %d, size %u, count: %u, timeout: %u\n",
118                         args->ioc_nid,
119                         portals_nid2str(args->ioc_nal, args->ioc_nid, str),
120                         args->ioc_nal, args->ioc_size,
121                         args->ioc_count, args->ioc_timeout);
122
123
124         PORTAL_ALLOC (client->outbuf, STDSIZE + args->ioc_size) ;
125         if (client->outbuf == NULL)
126         {
127                 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
128                 pingcli_shutdown (nih, 4);
129                 return (NULL);
130         }
131
132         PORTAL_ALLOC (client->inbuf,
133                         (args->ioc_size + STDSIZE) * args->ioc_count);
134         if (client->inbuf == NULL)
135         {
136                 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
137                 pingcli_shutdown (nih, 4);
138                 return (NULL);
139         }
140
141         /* Aquire and initialize the proper nal for portals. */
142         rc = PtlNIInit(args->ioc_nal, 0, NULL, NULL, &nih);
143         if (rc != PTL_OK || rc != PTL_IFACE_DUP)
144         {
145                 CERROR ("NAL %d not loaded\n", args->ioc_nal);
146                 pingcli_shutdown (nih, 4);
147                 return (NULL);
148         }
149
150         /* Based on the initialization aquire our unique portal ID. */
151         if ((rc = PtlGetId (nih, &client->myid)))
152         {
153                 CERROR ("PtlGetId error %d\n", rc);
154                 pingcli_shutdown (nih, 2);
155                 return (NULL);
156         }
157
158         /* Setup the local match entries */
159         client->id_local.nid = PTL_NID_ANY;
160         client->id_local.pid = PTL_PID_ANY;
161
162         /* Setup the remote match entries */
163         client->id_remote.nid = args->ioc_nid;
164         client->id_remote.pid = 0;
165
166         if ((rc = PtlMEAttach (nih, PTL_PING_CLIENT,
167                    client->id_local, 0, ~0, PTL_RETAIN,
168                    PTL_INS_AFTER, &client->me)))
169         {
170                 CERROR ("PtlMEAttach error %d\n", rc);
171                 pingcli_shutdown (nih, 2);
172                 return (NULL);
173         }
174
175         /* Allocate the event queue for this network interface */
176         if ((rc = PtlEQAlloc (nih, 64, pingcli_callback, &client->eq)))
177         {
178                 CERROR ("PtlEQAlloc error %d\n", rc);
179                 pingcli_shutdown (nih, 2);
180                 return (NULL);
181         }
182
183         count = args->ioc_count;
184
185         client->md_in_head.start     = client->inbuf;
186         client->md_in_head.length    = (args->ioc_size + STDSIZE)
187                                                 * count;
188         client->md_in_head.threshold = PTL_MD_THRESH_INF;
189         client->md_in_head.options   = PTL_MD_EVENT_START_DISABLE | PTL_MD_OP_PUT;
190         client->md_in_head.user_ptr  = NULL;
191         client->md_in_head.eq_handle = client->eq;
192         memset (client->inbuf, 0, (args->ioc_size + STDSIZE) * count);
193
194         /* Attach the incoming buffer */
195         if ((rc = PtlMDAttach (client->me, client->md_in_head,
196                               PTL_UNLINK, &client->md_in_head_h))) {
197                 CERROR ("PtlMDAttach error %d\n", rc);
198                 pingcli_shutdown (nih, 1);
199                 return (NULL);
200         }
201         /* Setup the outgoing ping header */
202         client->md_out_head.start     = client->outbuf;
203         client->md_out_head.length    = STDSIZE + args->ioc_size;
204         client->md_out_head.threshold = args->ioc_count;
205         client->md_out_head.options   = PTL_MD_EVENT_START_DISABLE | PTL_MD_OP_PUT;
206         client->md_out_head.user_ptr  = NULL;
207         client->md_out_head.eq_handle = PTL_EQ_NONE;
208
209         memcpy (client->outbuf, &ping_head_magic, sizeof(ping_bulk_magic));
210
211         count = 0;
212
213         /* Bind the outgoing ping header */
214         if ((rc=PtlMDBind (nih, client->md_out_head,
215                            PTL_UNLINK, &client->md_out_head_h))) {
216                 CERROR ("PtlMDBind error %d\n", rc);
217                 pingcli_shutdown (nih, 1);
218                 return NULL;
219         }
220         while ((args->ioc_count - count)) {
221                 memcpy (client->outbuf + sizeof(unsigned),
222                        &(count), sizeof(unsigned));
223                  /* Put the ping packet */
224                 do_gettimeofday (&tv1);
225
226                 memcpy(client->outbuf+sizeof(unsigned)+sizeof(unsigned),&tv1,
227                        sizeof(struct timeval));
228
229                 if((rc = PtlPut (client->md_out_head_h, PTL_NOACK_REQ,
230                           client->id_remote, PTL_PING_SERVER, 0, 0, 0, 0))) {
231                          PDEBUG ("PtlPut (header)", rc);
232                          pingcli_shutdown (nih, 1);
233                          return NULL;
234                 }
235                 CWARN ("Lustre: sent msg no %d", count);
236
237                 set_current_state (TASK_INTERRUPTIBLE);
238                 rc = schedule_timeout (20 * args->ioc_timeout);
239                 if (rc == 0) {
240                         CERROR ("timeout .....\n");
241                 } else {
242                         do_gettimeofday (&tv2);
243                         CWARN("Reply in %u usec\n",
244                               (unsigned)((tv2.tv_sec - tv1.tv_sec)
245                                          * 1000000 +  (tv2.tv_usec - tv1.tv_usec)));
246                 }
247                 count++;
248         }
249
250         if (client->outbuf != NULL)
251                 PORTAL_FREE (client->outbuf, STDSIZE + args->ioc_size);
252
253         if (client->inbuf != NULL)
254                 PORTAL_FREE (client->inbuf,
255                                (args->ioc_size + STDSIZE) * args->ioc_count);
256
257         pingcli_shutdown (nih, 2);
258
259         /* Success! */
260         return NULL;
261 } /* pingcli_setup() */
262
263
264
265 /* called by the portals_ioctl for ping requests */
266 int kping_client(struct portal_ioctl_data *args)
267 {
268         PORTAL_ALLOC (client, sizeof(struct pingcli_data));
269         if (client == NULL)
270         {
271                 CERROR ("Unable to allocate client structure\n");
272                 return (0);
273         }
274         memset (client, 0, sizeof(struct pingcli_data));
275         pingcli_start (args);
276
277         return 0;
278 } /* kping_client() */
279
280
281 static int __init pingcli_init(void)
282 {
283         PORTAL_SYMBOL_REGISTER(kping_client);
284         return 0;
285 } /* pingcli_init() */
286
287
288 static void /*__exit*/ pingcli_cleanup(void)
289 {
290         PORTAL_SYMBOL_UNREGISTER (kping_client);
291 } /* pingcli_cleanup() */
292
293
294 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
295 MODULE_DESCRIPTION("A simple kernel space ping client for portals testing");
296 MODULE_LICENSE("GPL");
297
298 module_init(pingcli_init);
299 module_exit(pingcli_cleanup);
300
301 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
302 EXPORT_SYMBOL (kping_client);
303 #endif