]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/infiniband-diags/src/ibping.c
Merge ^/vendor/llvm/dist up to its last change, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / ofed / infiniband-diags / src / ibping.c
1 /*
2  * Copyright (c) 2004-2009 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 static ibmad_gid_t dgid;
56 static int with_grh;
57
58 static void get_host_and_domain(char *data, int sz)
59 {
60         char *s = data;
61         int n;
62
63         if (gethostname(s, sz) < 0)
64                 snprintf(s, sz, "?hostname?");
65
66         s[sz - 1] = 0;
67         if ((n = strlen(s)) >= sz)
68                 return;
69         s[n] = '.';
70         s += n + 1;
71         sz -= n + 1;
72
73         if (getdomainname(s, sz) < 0)
74                 snprintf(s, sz, "?domainname?");
75         if (strlen(s) == 0)
76                 s[-1] = 0;      /* no domain */
77 }
78
79 static char *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                 if (umad_status(umad) == 0) {
90                         mad = umad_get_mad(umad);
91                         data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;
92
93                         memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);
94
95                         DEBUG("Pong: %s", data);
96
97                         if (mad_respond_via(umad, 0, 0, srcport) < 0)
98                                 DEBUG("respond failed");
99
100                 }
101                 mad_free(umad);
102         }
103
104         DEBUG("server out");
105         return 0;
106 }
107
108 static int oui = IB_OPENIB_OUI;
109
110 static uint64_t ibping(ib_portid_t * portid, int quiet)
111 {
112         char data[IB_VENDOR_RANGE2_DATA_SIZE] = { 0 };
113         ib_vendor_call_t call;
114         uint64_t start, rtt;
115
116         DEBUG("Ping..");
117
118         start = cl_get_time_stamp();
119
120         call.method = IB_MAD_METHOD_GET;
121         call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;
122         call.attrid = 0;
123         call.mod = 0;
124         call.oui = oui;
125         call.timeout = 0;
126         memset(&call.rmpp, 0, sizeof call.rmpp);
127
128         if (!ib_vendor_call_via(data, portid, &call, srcport))
129                 return ~0ull;
130
131         rtt = cl_get_time_stamp() - start;
132
133         if (!last_host[0])
134                 memcpy(last_host, data, sizeof last_host);
135
136         if (!quiet)
137                 printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",
138                        data, portid2str(portid), rtt / 1000, rtt % 1000);
139
140         return rtt;
141 }
142
143 static uint64_t minrtt = ~0ull, maxrtt, total_rtt;
144 static uint64_t start, total_time, replied, lost, ntrans;
145 static ib_portid_t portid = { 0 };
146
147 void report(int sig)
148 {
149         total_time = cl_get_time_stamp() - start;
150
151         DEBUG("out due signal %d", sig);
152
153         printf("\n--- %s (%s) ibping statistics ---\n", last_host,
154                portid2str(&portid));
155         printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64
156                "%% packet loss, time %" PRIu64 " ms\n", ntrans, replied,
157                (lost != 0) ? lost * 100 / ntrans : 0, total_time / 1000);
158         printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03"
159                PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n",
160                minrtt == ~0ull ? 0 : minrtt / 1000,
161                minrtt == ~0ull ? 0 : minrtt % 1000,
162                replied ? total_rtt / replied / 1000 : 0,
163                replied ? (total_rtt / replied) % 1000 : 0, maxrtt / 1000,
164                maxrtt % 1000);
165
166         exit(0);
167 }
168
169 static int server = 0, flood = 0;
170 static unsigned count = ~0;
171
172 static int process_opt(void *context, int ch, char *optarg)
173 {
174         switch (ch) {
175         case 'c':
176                 count = strtoul(optarg, 0, 0);
177                 break;
178         case 'f':
179                 flood++;
180                 break;
181         case 'o':
182                 oui = strtoul(optarg, 0, 0);
183                 break;
184         case 'S':
185                 server++;
186                 break;
187         case 25:
188                 if (!inet_pton(AF_INET6, optarg, &dgid)) {
189                         printf("dgid format is wrong!\n");
190                         ibdiag_show_usage();
191                         return 1;
192                 }
193                 with_grh = 1;
194                 break;
195         default:
196                 return -1;
197         }
198         return 0;
199 }
200
201 int main(int argc, char **argv)
202 {
203         int mgmt_classes[1] = { IB_SA_CLASS };
204         int ping_class = IB_VENDOR_OPENIB_PING_CLASS;
205         uint64_t rtt;
206         char *err;
207
208         const struct ibdiag_opt opts[] = {
209                 {"count", 'c', 1, "<num>", "stop after count packets"},
210                 {"flood", 'f', 0, NULL, "flood destination"},
211                 {"oui", 'o', 1, NULL, "use specified OUI number"},
212                 {"Server", 'S', 0, NULL, "start in server mode"},
213                 {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
214                 {0}
215         };
216         char usage_args[] = "<dest lid|guid>";
217
218         ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
219                             usage_args, NULL);
220
221         argc -= optind;
222         argv += optind;
223
224         if (!argc && !server)
225                 ibdiag_show_usage();
226
227         srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 1);
228         if (!srcport)
229                 IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
230
231         if (server) {
232                 if (mad_register_server_via(ping_class, 0, 0, oui, srcport) < 0)
233                         IBEXIT("can't serve class %d on this port",
234                                 ping_class);
235
236                 get_host_and_domain(host_and_domain, sizeof host_and_domain);
237
238                 if ((err = ibping_serv()))
239                         IBEXIT("ibping to %s: %s", portid2str(&portid), err);
240                 exit(0);
241         }
242
243         if (mad_register_client_via(ping_class, 0, srcport) < 0)
244                 IBEXIT("can't register ping class %d on this port",
245                         ping_class);
246
247         if (with_grh && ibd_dest_type != IB_DEST_LID)
248                 IBEXIT("When using GRH, LID should be provided");
249         if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
250                                ibd_dest_type, ibd_sm_id, srcport) < 0)
251                 IBEXIT("can't resolve destination port %s", argv[0]);
252
253         if (with_grh) {
254                 portid.grh_present = 1;
255                 memcpy(&portid.gid, &dgid, sizeof(portid.gid));
256         }
257
258         signal(SIGINT, report);
259         signal(SIGTERM, report);
260
261         start = cl_get_time_stamp();
262
263         while (count-- > 0) {
264                 ntrans++;
265                 if ((rtt = ibping(&portid, flood)) == ~0ull) {
266                         DEBUG("ibping to %s failed", portid2str(&portid));
267                         lost++;
268                 } else {
269                         if (rtt < minrtt)
270                                 minrtt = rtt;
271                         if (rtt > maxrtt)
272                                 maxrtt = rtt;
273                         total_rtt += rtt;
274                         replied++;
275                 }
276
277                 if (!flood)
278                         sleep(1);
279         }
280
281         report(0);
282
283         mad_rpc_close_port(srcport);
284
285         exit(-1);
286 }