2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
36 #endif /* HAVE_CONFIG_H */
45 #include <infiniband/umad.h>
46 #include <infiniband/mad.h>
47 #include <complib/cl_timer.h>
49 #include "ibdiag_common.h"
51 struct ibmad_port *srcport;
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;
58 static void get_host_and_domain(char *data, int sz)
63 if (gethostname(s, sz) < 0)
64 snprintf(s, sz, "?hostname?");
67 if ((n = strlen(s)) >= sz)
73 if (getdomainname(s, sz) < 0)
74 snprintf(s, sz, "?domainname?");
76 s[-1] = 0; /* no domain */
79 static char *ibping_serv(void)
85 DEBUG("starting to serve...");
87 while ((umad = mad_receive_via(0, -1, srcport))) {
89 if (umad_status(umad) == 0) {
90 mad = umad_get_mad(umad);
91 data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;
93 memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);
95 DEBUG("Pong: %s", data);
97 if (mad_respond_via(umad, 0, 0, srcport) < 0)
98 DEBUG("respond failed");
108 static int oui = IB_OPENIB_OUI;
110 static uint64_t ibping(ib_portid_t * portid, int quiet)
112 char data[IB_VENDOR_RANGE2_DATA_SIZE] = { 0 };
113 ib_vendor_call_t call;
118 start = cl_get_time_stamp();
120 call.method = IB_MAD_METHOD_GET;
121 call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;
126 memset(&call.rmpp, 0, sizeof call.rmpp);
128 if (!ib_vendor_call_via(data, portid, &call, srcport))
131 rtt = cl_get_time_stamp() - start;
134 memcpy(last_host, data, sizeof last_host);
137 printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",
138 data, portid2str(portid), rtt / 1000, rtt % 1000);
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 };
149 total_time = cl_get_time_stamp() - start;
151 DEBUG("out due signal %d", sig);
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,
169 static int server = 0, flood = 0;
170 static unsigned count = ~0;
172 static int process_opt(void *context, int ch, char *optarg)
176 count = strtoul(optarg, 0, 0);
182 oui = strtoul(optarg, 0, 0);
188 if (!inet_pton(AF_INET6, optarg, &dgid)) {
189 printf("dgid format is wrong!\n");
201 int main(int argc, char **argv)
203 int mgmt_classes[1] = { IB_SA_CLASS };
204 int ping_class = IB_VENDOR_OPENIB_PING_CLASS;
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)"},
216 char usage_args[] = "<dest lid|guid>";
218 ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
224 if (!argc && !server)
227 srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 1);
229 IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
232 if (mad_register_server_via(ping_class, 0, 0, oui, srcport) < 0)
233 IBEXIT("can't serve class %d on this port",
236 get_host_and_domain(host_and_domain, sizeof host_and_domain);
238 if ((err = ibping_serv()))
239 IBEXIT("ibping to %s: %s", portid2str(&portid), err);
243 if (mad_register_client_via(ping_class, 0, srcport) < 0)
244 IBEXIT("can't register ping class %d on this port",
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]);
254 portid.grh_present = 1;
255 memcpy(&portid.gid, &dgid, sizeof(portid.gid));
258 signal(SIGINT, report);
259 signal(SIGTERM, report);
261 start = cl_get_time_stamp();
263 while (count-- > 0) {
265 if ((rtt = ibping(&portid, flood)) == ~0ull) {
266 DEBUG("ibping to %s failed", portid2str(&portid));
283 mad_rpc_close_port(srcport);