ib-mgmt: update to 518083dc46963eb5fb48855acbe2b351ce7361f8
[mirror/winof/.git] / tools / infiniband-diags / src / ibping.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  *
32  */
33
34 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #endif /* HAVE_CONFIG_H */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <signal.h>
43 #include <getopt.h>
44
45 #include <infiniband/umad.h>
46 #include <infiniband/mad.h>
47 #include <complib/cl_timer.h>
48
49 #include "ibdiag_common.h"
50
51 struct ibmad_port *srcport;
52
53 static char host_and_domain[IB_VENDOR_RANGE2_DATA_SIZE];
54 static char last_host[IB_VENDOR_RANGE2_DATA_SIZE];
55
56 static void
57 get_host_and_domain(char *data, int sz)
58 {
59         char *s = data;
60         int n;
61
62         if (gethostname(s, sz) < 0)
63                 snprintf(s, sz, "?hostname?");
64
65         s[sz-1] = 0;
66         if ((n = strlen(s)) >= sz)
67                 return;
68         s[n] = '.';
69         s += n + 1;
70         sz -= n + 1;
71
72         if (getdomainname(s, sz) < 0)
73                 snprintf(s, sz, "?domainname?");
74         if (strlen(s) == 0)
75                 s[-1] = 0;      /* no domain */
76 }
77
78 static char *
79 ibping_serv(void)
80 {
81         void *umad;
82         void *mad;
83         char *data;
84
85         DEBUG("starting to serve...");
86
87         while ((umad = mad_receive_via(0, -1, srcport))) {
88
89                 mad = umad_get_mad(umad);
90                 data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;
91
92                 memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);
93
94                 DEBUG("Pong: %s", data);
95
96                 if (mad_respond_via(umad, 0, 0, srcport) < 0)
97                         DEBUG("respond failed");
98
99                 mad_free(umad);
100         }
101
102         DEBUG("server out");
103         return 0;
104 }
105
106 static uint64_t
107 ibping(ib_portid_t *portid, int quiet)
108 {
109         char data[IB_VENDOR_RANGE2_DATA_SIZE] = {0};
110         ib_vendor_call_t call;
111         uint64_t start, rtt;
112
113         DEBUG("Ping..");
114
115         start = cl_get_time_stamp();
116
117         call.method = IB_MAD_METHOD_GET;
118         call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;
119         call.attrid = 0;
120         call.mod = 0;
121         call.oui = IB_OPENIB_OUI;
122         call.timeout = 0;
123         memset(&call.rmpp, 0, sizeof call.rmpp);
124
125         if (!ib_vendor_call_via(data, portid, &call, srcport))
126                 return ~0ull;
127
128         rtt = cl_get_time_stamp() - start;
129
130         if (!last_host[0])
131                 memcpy(last_host, data, sizeof last_host);
132
133         if (!quiet)
134                 printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",
135                         data, portid2str(portid), rtt/1000, rtt%1000);
136
137         return rtt;
138 }
139
140 static uint64_t minrtt = ~0ull, maxrtt, total_rtt;
141 static uint64_t start, total_time, replied, lost, ntrans;
142 static ib_portid_t portid = {0};
143
144 void report(int sig)
145 {
146         total_time = cl_get_time_stamp() - start;
147
148         DEBUG("out due signal %d", sig);
149
150         printf("\n--- %s (%s) ibping statistics ---\n", last_host, portid2str(&portid));
151         printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64 "%% packet loss, time %" PRIu64 " ms\n",
152                 ntrans, replied,
153                 (lost != 0) ?  lost * 100 / ntrans : 0, total_time / 1000);
154         printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n",
155                 minrtt == ~0ull ? 0 : minrtt/1000,
156                 minrtt == ~0ull ? 0 : minrtt%1000,
157                 replied ? total_rtt/replied/1000 : 0,
158                 replied ? (total_rtt/replied)%1000 : 0,
159                 maxrtt/1000, maxrtt%1000);
160
161         exit(0);
162 }
163
164 static int server = 0, flood = 0, oui = IB_OPENIB_OUI;
165 static unsigned count = ~0;
166
167 static int process_opt(void *context, int ch, char *optarg)
168 {
169         switch (ch) {
170         case 'c':
171                 count = strtoul(optarg, 0, 0);
172                 break;
173         case 'f':
174                 flood++;
175                 break;
176         case 'o':
177                 oui = strtoul(optarg, 0, 0);
178                 break;
179         case 'S':
180                 server++;
181                 break;
182         default:
183                 return -1;
184         }
185         return 0;
186 }
187
188 int main(int argc, char **argv)
189 {
190         int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};
191         int ping_class = IB_VENDOR_OPENIB_PING_CLASS;
192         uint64_t rtt;
193         char *err;
194
195         const struct ibdiag_opt opts[] = {
196                 { "count", 'c', 1, "<num>", "stop after count packets" },
197                 { "flood", 'f', 0, NULL, "flood destination" },
198                 { "oui", 'o', 1, NULL, "use specified OUI number" },
199                 { "Server", 'S', 0, NULL, "start in server mode" },
200                 { 0 }
201         };
202         char usage_args[] = "<dest lid|guid>";
203
204         ibdiag_process_opts(argc, argv, NULL, "D", opts, process_opt,
205                             usage_args, NULL);
206
207         argc -= optind;
208         argv += optind;
209
210         if (!argc && !server)
211                 ibdiag_show_usage();
212
213         srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
214         if (!srcport)
215                 IBERROR("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
216
217         if (server) {
218                 if (mad_register_server_via(ping_class, 0, 0, oui, srcport) < 0)
219                         IBERROR("can't serve class %d on this port", ping_class);
220
221                 get_host_and_domain(host_and_domain, sizeof host_and_domain);
222
223                 if ((err = ibping_serv()))
224                         IBERROR("ibping to %s: %s", portid2str(&portid), err);
225                 exit(0);
226         }
227
228         if (mad_register_client_via(ping_class, 0, srcport) < 0)
229                 IBERROR("can't register ping class %d on this port", ping_class);
230
231         if (ib_resolve_portid_str_via(&portid, argv[0], ibd_dest_type,
232                                         ibd_sm_id, srcport) < 0)
233                 IBERROR("can't resolve destination port %s", argv[0]);
234
235         signal(SIGINT, report);
236         signal(SIGTERM, report);
237
238         start = cl_get_time_stamp();
239
240         while (count-- > 0) {
241                 ntrans++;
242                 if ((rtt = ibping(&portid, flood)) == ~0ull) {
243                         DEBUG("ibping to %s failed", portid2str(&portid));
244                         lost++;
245                 } else {
246                         if (rtt < minrtt)
247                                 minrtt = rtt;
248                         if (rtt > maxrtt)
249                                 maxrtt = rtt;
250                         total_rtt += rtt;
251                         replied++;
252                 }
253
254                 if (!flood)
255                         sleep(1);
256         }
257
258         report(0);
259
260         mad_rpc_close_port(srcport);
261
262         exit(-1);
263 }