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