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