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