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