1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
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)
9 * This file is part of Portals, http://www.sf.net/projects/lustre/
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.
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.
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.
26 #define DEBUG_SUBSYSTEM S_PINGER
28 #include <libcfs/kp30.h>
29 #include <lnet/lnet.h>
31 /* int libcfs_debug = D_PING_CLI; */
34 #define STDSIZE (sizeof(int) + sizeof(int) + sizeof(struct timeval))
36 #define MAX_TIME 100000
38 /* This should be enclosed in a structure */
40 static struct pingcli_data *client = NULL;
45 pingcli_shutdown(int err)
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.
55 /* Unlink any memory descriptors we may have used */
56 if ((rc = LNetMDUnlink (client->md_out_head_h)))
57 PDEBUG ("LNetMDUnlink", rc);
59 if ((rc = LNetMDUnlink (client->md_in_head_h)))
60 PDEBUG ("LNetMDUnlink", rc);
62 /* Free the event queue */
63 if ((rc = LNetEQFree (client->eq)))
64 PDEBUG ("LNetEQFree", rc);
66 if ((rc = LNetMEUnlink (client->me)))
67 PDEBUG ("LNetMEUnlink", rc);
72 /* Free our buffers */
73 if (client->outbuf != NULL)
74 LIBCFS_FREE (client->outbuf, STDSIZE + client->size);
76 if (client->inbuf != NULL)
77 LIBCFS_FREE (client->inbuf,
78 (client->size + STDSIZE) * client->count);
82 sizeof(struct pingcli_data));
86 CDEBUG (D_OTHER, "ping client released resources\n");
87 } /* pingcli_shutdown() */
89 static void pingcli_callback(lnet_event_t *ev)
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));
96 if(magic != 0xcafebabe) {
97 CERROR("Unexpected response %x\n", magic);
100 if((i == count) || !count)
101 wake_up_process (client->tsk);
103 CERROR("Received response after timeout for %d\n",i);
108 pingcli_start(struct libcfs_ioctl_data *args)
110 unsigned ping_head_magic = __cpu_to_le32(PING_HEADER_MAGIC);
112 struct timeval tv1, tv2;
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];
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);
127 LIBCFS_ALLOC (client->outbuf, STDSIZE + client->size) ;
128 if (client->outbuf == NULL)
130 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
131 pingcli_shutdown (4);
135 LIBCFS_ALLOC (client->inbuf,
136 (client->size + STDSIZE) * client->count);
137 if (client->inbuf == NULL)
139 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
140 pingcli_shutdown (4);
145 if (rc != 0 && rc != 1)
147 CERROR ("LNetNIInit: error %d\n", rc);
148 pingcli_shutdown (4);
152 /* Based on the initialization aquire our unique portal ID. */
153 if ((rc = LNetGetId (1, &client->myid)))
155 CERROR ("LNetGetId error %d\n", rc);
156 pingcli_shutdown (2);
160 /* Setup the local match entries */
161 client->id_local.nid = LNET_NID_ANY;
162 client->id_local.pid = LNET_PID_ANY;
164 /* Setup the remote match entries */
165 client->id_remote.nid = client->nid;
166 client->id_remote.pid = 0;
168 if ((rc = LNetMEAttach (PTL_PING_CLIENT,
169 client->id_local, 0, ~0, LNET_RETAIN,
170 LNET_INS_AFTER, &client->me)))
172 CERROR ("LNetMEAttach error %d\n", rc);
173 pingcli_shutdown (2);
177 /* Allocate the event queue for this network interface */
178 if ((rc = LNetEQAlloc (64, pingcli_callback, &client->eq)))
180 CERROR ("LNetEQAlloc error %d\n", rc);
181 pingcli_shutdown (2);
185 count = client->count;
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);
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);
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;
210 memcpy (client->outbuf, &ping_head_magic, sizeof(ping_head_magic));
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);
221 while ((client->count - count)) {
223 __count = __cpu_to_le32(count);
225 memcpy (client->outbuf + sizeof(unsigned),
226 &(__count), sizeof(unsigned));
227 /* Put the ping packet */
228 cfs_fs_timeval (&tv1);
230 memcpy(client->outbuf+sizeof(unsigned)+sizeof(unsigned),&tv1,
231 sizeof(struct timeval));
233 if((rc = LNetPut (LNET_NID_ANY, client->md_out_head_h,
235 client->id_remote, PTL_PING_SERVER,
237 PDEBUG ("LNetPut (header)", rc);
238 pingcli_shutdown (1);
241 CWARN ("Lustre: sent msg no %d.\n", count);
243 set_current_state (CFS_TASK_INTERRUPTIBLE);
244 rc = cfs_schedule_timeout (CFS_TASK_INTERRUPTIBLE,
245 cfs_time_seconds(client->timeout));
247 CERROR ("timeout .....\n");
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)));
257 pingcli_shutdown (2);
259 } /* pingcli_setup() */
263 /* called by the portals_ioctl for ping requests */
264 int kping_client(struct libcfs_ioctl_data *args)
266 LIBCFS_ALLOC (client, sizeof(struct pingcli_data));
269 CERROR ("Unable to allocate client structure\n");
272 memset (client, 0, sizeof(struct pingcli_data));
273 pingcli_start (args);
276 } /* kping_client() */
279 static int __init pingcli_init(void)
281 PORTAL_SYMBOL_REGISTER(kping_client);
283 } /* pingcli_init() */
286 static void /*__exit*/ pingcli_cleanup(void)
288 PORTAL_SYMBOL_UNREGISTER (kping_client);
289 } /* pingcli_cleanup() */
292 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
293 MODULE_DESCRIPTION("A simple kernel space ping client for portals testing");
294 MODULE_LICENSE("GPL");
296 cfs_module(ping_cli, "1.0.0", pingcli_init, pingcli_cleanup);
298 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
299 EXPORT_SYMBOL (kping_client);