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 <portals/p30.h>
31 /* int portal_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(ptl_handle_ni_t nih, int err)
47 struct portal_ioctl_data *args = client->args;
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.
56 /* Unlink any memory descriptors we may have used */
57 if ((rc = PtlMDUnlink (client->md_out_head_h)))
58 PDEBUG ("PtlMDUnlink", rc);
60 if ((rc = PtlMDUnlink (client->md_in_head_h)))
61 PDEBUG ("PtlMDUnlink", rc);
63 /* Free the event queue */
64 if ((rc = PtlEQFree (client->eq)))
65 PDEBUG ("PtlEQFree", rc);
67 if ((rc = PtlMEUnlink (client->me)))
68 PDEBUG ("PtlMEUnlink", rc);
73 /* Free our buffers */
74 if (client->outbuf != NULL)
75 PORTAL_FREE (client->outbuf, STDSIZE + args->ioc_size);
77 if (client->inbuf != NULL)
78 PORTAL_FREE (client->inbuf,
79 (args->ioc_size + STDSIZE) * args->ioc_count);
83 sizeof(struct pingcli_data));
87 CDEBUG (D_OTHER, "ping client released resources\n");
88 } /* pingcli_shutdown() */
90 static void pingcli_callback(ptl_event_t *ev)
94 i = __le32_to_cpu(*(int *)(ev->md.start + ev->offset + sizeof(unsigned)));
95 magic = __le32_to_cpu(*(int *)(ev->md.start + ev->offset));
97 if(magic != 0xcafebabe) {
98 CERROR("Unexpected response %x\n", magic);
101 if((i == count) || !count)
102 wake_up_process (client->tsk);
104 CERROR("Received response after timeout for %d\n",i);
108 static struct pingcli_data *
109 pingcli_start(struct portal_ioctl_data *args)
111 ptl_handle_ni_t nih = PTL_INVALID_HANDLE;
112 unsigned ping_head_magic = __cpu_to_le32(PING_HEADER_MAGIC);
114 struct timeval tv1, tv2;
115 char str[PTL_NALFMT_SIZE];
117 client->tsk = cfs_current();
119 CDEBUG (D_OTHER, "pingcli_setup args: nid "LPX64" (%s), \
120 nal %x, size %u, count: %u, timeout: %u\n",
122 portals_nid2str(args->ioc_nal, args->ioc_nid, str),
123 args->ioc_nal, args->ioc_size,
124 args->ioc_count, args->ioc_timeout);
127 PORTAL_ALLOC (client->outbuf, STDSIZE + args->ioc_size) ;
128 if (client->outbuf == NULL)
130 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
131 pingcli_shutdown (nih, 4);
135 PORTAL_ALLOC (client->inbuf,
136 (args->ioc_size + STDSIZE) * args->ioc_count);
137 if (client->inbuf == NULL)
139 CERROR ("Unable to allocate out_buf ("LPSZ" bytes)\n", STDSIZE);
140 pingcli_shutdown (nih, 4);
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)
148 CERROR ("NAL %x not loaded\n", args->ioc_nal);
149 pingcli_shutdown (nih, 4);
153 /* Based on the initialization aquire our unique portal ID. */
154 if ((rc = PtlGetId (nih, &client->myid)))
156 CERROR ("PtlGetId error %d\n", rc);
157 pingcli_shutdown (nih, 2);
161 /* Setup the local match entries */
162 client->id_local.nid = PTL_NID_ANY;
163 client->id_local.pid = PTL_PID_ANY;
165 /* Setup the remote match entries */
166 client->id_remote.nid = args->ioc_nid;
167 client->id_remote.pid = 0;
169 if ((rc = PtlMEAttach (nih, PTL_PING_CLIENT,
170 client->id_local, 0, ~0, PTL_RETAIN,
171 PTL_INS_AFTER, &client->me)))
173 CERROR ("PtlMEAttach error %d\n", rc);
174 pingcli_shutdown (nih, 2);
178 /* Allocate the event queue for this network interface */
179 if ((rc = PtlEQAlloc (nih, 64, pingcli_callback, &client->eq)))
181 CERROR ("PtlEQAlloc error %d\n", rc);
182 pingcli_shutdown (nih, 2);
186 count = args->ioc_count;
188 client->md_in_head.start = client->inbuf;
189 client->md_in_head.length = (args->ioc_size + STDSIZE)
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);
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);
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;
212 memcpy (client->outbuf, &ping_head_magic, sizeof(ping_head_magic));
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);
223 while ((args->ioc_count - count)) {
225 __count = __cpu_to_le32(count);
227 memcpy (client->outbuf + sizeof(unsigned),
228 &(__count), sizeof(unsigned));
229 /* Put the ping packet */
230 cfs_fs_timeval (&tv1);
232 memcpy(client->outbuf+sizeof(unsigned)+sizeof(unsigned),&tv1,
233 sizeof(struct timeval));
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);
241 CWARN ("Lustre: sent msg no %d.\n", count);
243 set_current_state (TASK_INTERRUPTIBLE);
244 rc = schedule_timeout (cfs_time_seconds(args->ioc_timeout));
246 CERROR ("timeout .....\n");
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)));
256 pingcli_shutdown (nih, 2);
260 } /* pingcli_setup() */
264 /* called by the portals_ioctl for ping requests */
265 int kping_client(struct portal_ioctl_data *args)
267 PORTAL_ALLOC (client, sizeof(struct pingcli_data));
270 CERROR ("Unable to allocate client structure\n");
273 memset (client, 0, sizeof(struct pingcli_data));
274 pingcli_start (args);
277 } /* kping_client() */
280 static int __init pingcli_init(void)
282 PORTAL_SYMBOL_REGISTER(kping_client);
284 } /* pingcli_init() */
287 static void /*__exit*/ pingcli_cleanup(void)
289 PORTAL_SYMBOL_UNREGISTER (kping_client);
290 } /* pingcli_cleanup() */
293 MODULE_AUTHOR("Brian Behlendorf (LLNL)");
294 MODULE_DESCRIPTION("A simple kernel space ping client for portals testing");
295 MODULE_LICENSE("GPL");
297 cfs_module(ping_cli, "1.0.0", pingcli_init, pingcli_cleanup);
299 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
300 EXPORT_SYMBOL (kping_client);