|
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 |
|
|
Packit |
db064d |
#include <infiniband/umad.h>
|
|
Packit |
db064d |
#include <infiniband/mad.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include "ibdiag_common.h"
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#define MAX_CPUS 8
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static struct ibmad_port *srcport;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
enum ib_sysstat_attr_t {
|
|
Packit |
db064d |
IB_PING_ATTR = 0x10,
|
|
Packit |
db064d |
IB_HOSTINFO_ATTR = 0x11,
|
|
Packit |
db064d |
IB_CPUINFO_ATTR = 0x12,
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
typedef struct cpu_info {
|
|
Packit |
db064d |
char *model;
|
|
Packit |
db064d |
char *mhz;
|
|
Packit |
db064d |
} cpu_info;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static cpu_info cpus[MAX_CPUS];
|
|
Packit |
db064d |
static int host_ncpu;
|
|
Packit |
db064d |
static int server = 0, oui = IB_OPENIB_OUI;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int server_respond(void *umad, int size)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
ib_rpc_t rpc = { 0 };
|
|
Packit |
db064d |
ib_rmpp_hdr_t rmpp = { 0 };
|
|
Packit |
db064d |
ib_portid_t rport;
|
|
Packit |
db064d |
uint8_t *mad = umad_get_mad(umad);
|
|
Packit |
db064d |
ib_mad_addr_t *mad_addr;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(mad_addr = umad_get_mad_addr(umad)))
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(&rport, 0, sizeof(rport));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
rport.lid = ntohs(mad_addr->lid);
|
|
Packit |
db064d |
rport.qp = ntohl(mad_addr->qpn);
|
|
Packit |
db064d |
rport.qkey = ntohl(mad_addr->qkey);
|
|
Packit |
db064d |
rport.sl = mad_addr->sl;
|
|
Packit |
db064d |
if (!rport.qkey && rport.qp == 1)
|
|
Packit |
db064d |
rport.qkey = IB_DEFAULT_QP1_QKEY;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
rpc.mgtclass = mad_get_field(mad, 0, IB_MAD_MGMTCLASS_F);
|
|
Packit |
db064d |
rpc.method = IB_MAD_METHOD_GET | IB_MAD_RESPONSE;
|
|
Packit |
db064d |
rpc.attr.id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
|
|
Packit |
db064d |
rpc.attr.mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
|
|
Packit |
db064d |
rpc.oui = mad_get_field(mad, 0, IB_VEND2_OUI_F);
|
|
Packit |
db064d |
rpc.trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (size > IB_MAD_SIZE)
|
|
Packit |
db064d |
rmpp.flags = IB_RMPP_FLAG_ACTIVE;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("responding %d bytes to %s, attr 0x%x mod 0x%x qkey %x",
|
|
Packit |
db064d |
size, portid2str(&rport), rpc.attr.id, rpc.attr.mod, rport.qkey);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (mad_build_pkt(umad, &rpc, &rport, &rmpp, NULL) < 0)
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibdebug > 1)
|
|
Packit |
db064d |
xdump(stderr, "mad respond pkt\n", mad, IB_MAD_SIZE);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (umad_send(mad_rpc_portid(srcport),
|
|
Packit |
db064d |
mad_rpc_class_agent(srcport, rpc.mgtclass), umad, size,
|
|
Packit |
db064d |
rpc.timeout, 0) < 0) {
|
|
Packit |
db064d |
DEBUG("send failed; %m");
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int mk_reply(int attr, void *data, int sz)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char *s = data;
|
|
Packit |
db064d |
int n, i, ret = 0;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
switch (attr) {
|
|
Packit |
db064d |
case IB_PING_ATTR:
|
|
Packit |
db064d |
break; /* nothing to do here, just reply */
|
|
Packit |
db064d |
case IB_HOSTINFO_ATTR:
|
|
Packit |
db064d |
if (gethostname(s, sz) < 0)
|
|
Packit |
db064d |
snprintf(s, sz, "?hostname?");
|
|
Packit |
db064d |
s[sz - 1] = 0;
|
|
Packit |
db064d |
if ((n = strlen(s)) >= sz - 1) {
|
|
Packit |
db064d |
ret = sz;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
s[n] = '.';
|
|
Packit |
db064d |
s += n + 1;
|
|
Packit |
db064d |
sz -= n + 1;
|
|
Packit |
db064d |
ret += n + 1;
|
|
Packit |
db064d |
if (getdomainname(s, sz) < 0)
|
|
Packit |
db064d |
snprintf(s, sz, "?domainname?");
|
|
Packit |
db064d |
if ((n = strlen(s)) == 0)
|
|
Packit |
db064d |
s[-1] = 0; /* no domain */
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
ret += n;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
case IB_CPUINFO_ATTR:
|
|
Packit |
db064d |
s[0] = '\0';
|
|
Packit |
db064d |
for (i = 0; i < host_ncpu && sz > 0; i++) {
|
|
Packit |
db064d |
n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n",
|
|
Packit |
db064d |
i, cpus[i].model, cpus[i].mhz);
|
|
Packit |
db064d |
if (n >= sz) {
|
|
Packit |
db064d |
IBWARN("cpuinfo truncated");
|
|
Packit |
db064d |
ret = sz;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
sz -= n;
|
|
Packit |
db064d |
s += n;
|
|
Packit |
db064d |
ret += n;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
ret++;
|
|
Packit |
db064d |
break;
|
|
Packit |
db064d |
default:
|
|
Packit |
db064d |
DEBUG("unknown attr %d", attr);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
return ret;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static uint8_t buf[2048];
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static char *ibsystat_serv(void)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
void *umad;
|
|
Packit |
db064d |
void *mad;
|
|
Packit |
db064d |
int attr, mod, size;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("starting to serve...");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while ((umad = mad_receive_via(buf, -1, srcport))) {
|
|
Packit |
db064d |
if (umad_status(buf)) {
|
|
Packit |
db064d |
DEBUG("drop mad with status %x: %s", umad_status(buf),
|
|
Packit |
db064d |
strerror(umad_status(buf)));
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad = umad_get_mad(umad);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
|
|
Packit |
db064d |
mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
size =
|
|
Packit |
db064d |
mk_reply(attr, (uint8_t *) mad + IB_VENDOR_RANGE2_DATA_OFFS,
|
|
Packit |
db064d |
sizeof(buf) - umad_size() -
|
|
Packit |
db064d |
IB_VENDOR_RANGE2_DATA_OFFS);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (server_respond(umad, IB_VENDOR_RANGE2_DATA_OFFS + size) < 0)
|
|
Packit |
db064d |
DEBUG("respond failed");
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("server out");
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int match_attr(char *str)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (!strcmp(str, "ping"))
|
|
Packit |
db064d |
return IB_PING_ATTR;
|
|
Packit |
db064d |
if (!strcmp(str, "host"))
|
|
Packit |
db064d |
return IB_HOSTINFO_ATTR;
|
|
Packit |
db064d |
if (!strcmp(str, "cpu"))
|
|
Packit |
db064d |
return IB_CPUINFO_ATTR;
|
|
Packit |
db064d |
return -1;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static char *ibsystat(ib_portid_t * portid, int attr)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
ib_rpc_t rpc = { 0 };
|
|
Packit |
db064d |
int fd, agent, timeout, len;
|
|
Packit |
db064d |
void *data = (uint8_t *) umad_get_mad(buf) + IB_VENDOR_RANGE2_DATA_OFFS;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("Sysstat ping..");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
rpc.mgtclass = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
|
|
Packit |
db064d |
rpc.method = IB_MAD_METHOD_GET;
|
|
Packit |
db064d |
rpc.attr.id = attr;
|
|
Packit |
db064d |
rpc.attr.mod = 0;
|
|
Packit |
db064d |
rpc.oui = oui;
|
|
Packit |
db064d |
rpc.timeout = 0;
|
|
Packit |
db064d |
rpc.datasz = IB_VENDOR_RANGE2_DATA_SIZE;
|
|
Packit |
db064d |
rpc.dataoffs = IB_VENDOR_RANGE2_DATA_OFFS;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
portid->qp = 1;
|
|
Packit |
db064d |
if (!portid->qkey)
|
|
Packit |
db064d |
portid->qkey = IB_DEFAULT_QP1_QKEY;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((len = mad_build_pkt(buf, &rpc, portid, NULL, NULL)) < 0)
|
|
Packit |
db064d |
IBPANIC("cannot build packet.");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
fd = mad_rpc_portid(srcport);
|
|
Packit |
db064d |
agent = mad_rpc_class_agent(srcport, rpc.mgtclass);
|
|
Packit |
db064d |
timeout = ibd_timeout ? ibd_timeout : MAD_DEF_TIMEOUT_MS;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (umad_send(fd, agent, buf, len, timeout, 0) < 0)
|
|
Packit |
db064d |
IBPANIC("umad_send failed.");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
len = sizeof(buf) - umad_size();
|
|
Packit |
db064d |
if (umad_recv(fd, buf, &len, timeout) < 0)
|
|
Packit |
db064d |
IBPANIC("umad_recv failed.");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (umad_status(buf))
|
|
Packit |
db064d |
return strerror(umad_status(buf));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("Got sysstat pong..");
|
|
Packit |
db064d |
if (attr != IB_PING_ATTR)
|
|
Packit |
db064d |
puts(data);
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
printf("sysstat ping succeeded\n");
|
|
Packit |
db064d |
return NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int build_cpuinfo(void)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
char line[1024] = { 0 }, *s, *e;
|
|
Packit |
db064d |
FILE *f;
|
|
Packit |
db064d |
int ncpu = 0;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!(f = fopen("/proc/cpuinfo", "r"))) {
|
|
Packit |
db064d |
IBWARN("couldn't open /proc/cpuinfo");
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
while (fgets(line, sizeof(line) - 1, f)) {
|
|
Packit |
db064d |
if (!strncmp(line, "processor\t", 10)) {
|
|
Packit |
db064d |
ncpu++;
|
|
Packit |
db064d |
if (ncpu > MAX_CPUS) {
|
|
Packit |
db064d |
fclose(f);
|
|
Packit |
db064d |
return MAX_CPUS;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (!ncpu || !(s = strchr(line, ':')))
|
|
Packit |
db064d |
continue;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((e = strchr(s, '\n')))
|
|
Packit |
db064d |
*e = 0;
|
|
Packit |
db064d |
if (!strncmp(line, "model name\t", 11))
|
|
Packit |
db064d |
cpus[ncpu - 1].model = strdup(s + 1);
|
|
Packit |
db064d |
else if (!strncmp(line, "cpu MHz\t", 8))
|
|
Packit |
db064d |
cpus[ncpu - 1].mhz = strdup(s + 1);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
fclose(f);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
DEBUG("ncpu %d", ncpu);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return ncpu;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static int process_opt(void *context, int ch)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
switch (ch) {
|
|
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[3] =
|
|
Packit |
db064d |
{ IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
|
|
Packit |
db064d |
int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
|
|
Packit |
db064d |
ib_portid_t portid = { 0 };
|
|
Packit |
db064d |
int attr = IB_PING_ATTR;
|
|
Packit |
db064d |
char *err;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
const struct ibdiag_opt opts[] = {
|
|
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> [<op>]";
|
|
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 |
if (argc > 1 && (attr = match_attr(argv[1])) < 0)
|
|
Packit |
db064d |
ibdiag_show_usage();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
|
|
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(sysstat_class, 1, NULL, oui, srcport) <
|
|
Packit |
db064d |
0)
|
|
Packit |
db064d |
IBEXIT("can't serve class %d", sysstat_class);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
host_ncpu = build_cpuinfo();
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((err = ibsystat_serv()))
|
|
Packit |
db064d |
IBEXIT("ibssystat to %s: %s", portid2str(&portid),
|
|
Packit |
db064d |
err);
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (mad_register_client_via(sysstat_class, 1, srcport) < 0)
|
|
Packit |
db064d |
IBEXIT("can't register to sysstat class %d", sysstat_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 |
if ((err = ibsystat(&portid, attr)))
|
|
Packit |
db064d |
IBEXIT("ibsystat to %s: %s", portid2str(&portid), err);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_rpc_close_port(srcport);
|
|
Packit |
db064d |
exit(0);
|
|
Packit |
db064d |
}
|