|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* This software is available to you under a choice of one of two
|
|
Packit |
db064d |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
db064d |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
db064d |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
db064d |
* OpenIB.org BSD license below:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
db064d |
* without modification, are permitted provided that the following
|
|
Packit |
db064d |
* conditions are met:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions of source code must retain the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer in the documentation and/or other materials
|
|
Packit |
db064d |
* provided with the distribution.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
db064d |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
db064d |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
db064d |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
db064d |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
db064d |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
db064d |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
db064d |
* SOFTWARE.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#if HAVE_CONFIG_H
|
|
Packit |
db064d |
# include <config.h>
|
|
Packit |
db064d |
#endif /* HAVE_CONFIG_H */
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include <stdio.h>
|
|
Packit |
db064d |
#include <stdlib.h>
|
|
Packit |
db064d |
#include <unistd.h>
|
|
Packit |
db064d |
#include <string.h>
|
|
Packit |
db064d |
#include <signal.h>
|
|
Packit |
db064d |
#include <time.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include <infiniband/umad.h>
|
|
Packit |
db064d |
#include <infiniband/mad.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include "ibdiag_common.h"
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static struct ibmad_port *srcport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t time_stamp(void)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
struct timespec ts;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
Packit |
db064d |
return ((uint64_t)ts.tv_sec * 1000000ULL) + ts.tv_nsec / 10000ULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static char host_and_domain[IB_VENDOR_RANGE2_DATA_SIZE];
|
|
Packit |
db064d |
static char last_host[IB_VENDOR_RANGE2_DATA_SIZE];
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void get_host_and_domain(char *data, int sz)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *s = data;
|
|
Packit |
db064d |
int n;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (gethostname(s, sz) < 0)
|
|
Packit |
db064d |
snprintf(s, sz, "?hostname?");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
s[sz - 1] = 0;
|
|
Packit |
db064d |
if ((n = strlen(s)) >= sz)
|
|
Packit |
db064d |
return;
|
|
Packit |
db064d |
s[n] = '.';
|
|
Packit |
db064d |
s += n + 1;
|
|
Packit |
db064d |
sz -= n + 1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (getdomainname(s, sz) < 0)
|
|
Packit |
db064d |
snprintf(s, sz, "?domainname?");
|
|
Packit |
db064d |
if (strlen(s) == 0)
|
|
Packit |
db064d |
s[-1] = 0; /* no domain */
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static char *ibping_serv(void)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
void *umad;
|
|
Packit |
db064d |
void *mad;
|
|
Packit |
db064d |
char *data;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("starting to serve...");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while ((umad = mad_receive_via(NULL, -1, srcport))) {
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (umad_status(umad) == 0) {
|
|
Packit |
db064d |
mad = umad_get_mad(umad);
|
|
Packit |
db064d |
data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("Pong: %s", data);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (mad_respond_via(umad, NULL, 0, srcport) < 0)
|
|
Packit |
db064d |
DEBUG("respond failed");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
mad_free(umad);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("server out");
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int oui = IB_OPENIB_OUI;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t ibping(ib_portid_t * portid, int quiet)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char data[IB_VENDOR_RANGE2_DATA_SIZE] = { 0 };
|
|
Packit |
db064d |
ib_vendor_call_t call;
|
|
Packit |
db064d |
uint64_t start, rtt;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("Ping..");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
start = time_stamp();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
call.method = IB_MAD_METHOD_GET;
|
|
Packit |
db064d |
call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;
|
|
Packit |
db064d |
call.attrid = 0;
|
|
Packit |
db064d |
call.mod = 0;
|
|
Packit |
db064d |
call.oui = oui;
|
|
Packit |
db064d |
call.timeout = 0;
|
|
Packit |
db064d |
memset(&call.rmpp, 0, sizeof call.rmpp);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!ib_vendor_call_via(data, portid, &call, srcport))
|
|
Packit |
db064d |
return ~0ull;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
rtt = time_stamp() - start;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!last_host[0])
|
|
Packit |
db064d |
memcpy(last_host, data, sizeof last_host);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!quiet)
|
|
Packit |
db064d |
printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",
|
|
Packit |
db064d |
data, portid2str(portid), rtt / 1000, rtt % 1000);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return rtt;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint64_t minrtt = ~0ull, maxrtt, total_rtt;
|
|
Packit |
db064d |
static uint64_t start, total_time, replied, lost, ntrans;
|
|
Packit |
db064d |
static ib_portid_t portid = { 0 };
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static void report(int sig)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
total_time = time_stamp() - start;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("out due signal %d", sig);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
printf("\n--- %s (%s) ibping statistics ---\n", last_host,
|
|
Packit |
db064d |
portid2str(&portid));
|
|
Packit |
db064d |
printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64
|
|
Packit |
db064d |
"%% packet loss, time %" PRIu64 " ms\n", ntrans, replied,
|
|
Packit |
db064d |
(lost != 0) ? lost * 100 / ntrans : 0, total_time / 1000);
|
|
Packit |
db064d |
printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03"
|
|
Packit |
db064d |
PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n",
|
|
Packit |
db064d |
minrtt == ~0ull ? 0 : minrtt / 1000,
|
|
Packit |
db064d |
minrtt == ~0ull ? 0 : minrtt % 1000,
|
|
Packit |
db064d |
replied ? total_rtt / replied / 1000 : 0,
|
|
Packit |
db064d |
replied ? (total_rtt / replied) % 1000 : 0, maxrtt / 1000,
|
|
Packit |
db064d |
maxrtt % 1000);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int server = 0, flood = 0;
|
|
Packit |
db064d |
static unsigned count = ~0;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int process_opt(void *context, int ch)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
switch (ch) {
|
|
Packit |
db064d |
case 'c':
|
|
Packit |
db064d |
count = strtoul(optarg, NULL, 0);
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'f':
|
|
Packit |
db064d |
flood++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'o':
|
|
Packit |
db064d |
oui = strtoul(optarg, NULL, 0);
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case 'S':
|
|
Packit |
db064d |
server++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
default:
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
int main(int argc, char **argv)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
int mgmt_classes[1] = { IB_SA_CLASS };
|
|
Packit |
db064d |
int ping_class = IB_VENDOR_OPENIB_PING_CLASS;
|
|
Packit |
db064d |
uint64_t rtt;
|
|
Packit |
db064d |
char *err;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
const struct ibdiag_opt opts[] = {
|
|
Packit |
db064d |
{"count", 'c', 1, "<num>", "stop after count packets"},
|
|
Packit |
db064d |
{"flood", 'f', 0, NULL, "flood destination"},
|
|
Packit |
db064d |
{"oui", 'o', 1, NULL, "use specified OUI number"},
|
|
Packit |
db064d |
{"Server", 'S', 0, NULL, "start in server mode"},
|
|
Packit |
db064d |
{}
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
char usage_args[] = "<dest lid|guid>";
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
|
|
Packit |
db064d |
usage_args, NULL);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
argc -= optind;
|
|
Packit |
db064d |
argv += optind;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!argc && !server)
|
|
Packit |
db064d |
ibdiag_show_usage();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 1);
|
|
Packit |
db064d |
if (!srcport)
|
|
Packit |
db064d |
IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (server) {
|
|
Packit |
db064d |
if (mad_register_server_via(ping_class, 0, NULL, oui, srcport) < 0)
|
|
Packit |
db064d |
IBEXIT("can't serve class %d on this port",
|
|
Packit |
db064d |
ping_class);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
get_host_and_domain(host_and_domain, sizeof host_and_domain);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((err = ibping_serv()))
|
|
Packit |
db064d |
IBEXIT("ibping to %s: %s", portid2str(&portid), err);
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (mad_register_client_via(ping_class, 0, srcport) < 0)
|
|
Packit |
db064d |
IBEXIT("can't register ping class %d on this port",
|
|
Packit |
db064d |
ping_class);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
|
|
Packit |
db064d |
ibd_dest_type, ibd_sm_id, srcport) < 0)
|
|
Packit |
db064d |
IBEXIT("can't resolve destination port %s", argv[0]);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
signal(SIGINT, report);
|
|
Packit |
db064d |
signal(SIGTERM, report);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
start = time_stamp();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while (count-- > 0) {
|
|
Packit |
db064d |
ntrans++;
|
|
Packit |
db064d |
if ((rtt = ibping(&portid, flood)) == ~0ull) {
|
|
Packit |
db064d |
DEBUG("ibping to %s failed", portid2str(&portid));
|
|
Packit |
db064d |
lost++;
|
|
Packit |
db064d |
} else {
|
|
Packit |
db064d |
if (rtt < minrtt)
|
|
Packit |
db064d |
minrtt = rtt;
|
|
Packit |
db064d |
if (rtt > maxrtt)
|
|
Packit |
db064d |
maxrtt = rtt;
|
|
Packit |
db064d |
total_rtt += rtt;
|
|
Packit |
db064d |
replied++;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!flood)
|
|
Packit |
db064d |
sleep(1);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
report(0);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_rpc_close_port(srcport);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
exit(-1);
|
|
Packit |
db064d |
}
|