165686Smarkm/* 2255362Smarkm * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved. 365686Smarkm * 465686Smarkm * This software is available to you under a choice of one of two 565686Smarkm * licenses. You may choose to be licensed under the terms of the GNU 665686Smarkm * General Public License (GPL) Version 2, available from the file 765686Smarkm * COPYING in the main directory of this source tree, or the 865686Smarkm * OpenIB.org BSD license below: 965686Smarkm * 1065686Smarkm * Redistribution and use in source and binary forms, with or 1165686Smarkm * without modification, are permitted provided that the following 1265686Smarkm * conditions are met: 1365686Smarkm * 1465686Smarkm * - Redistributions of source code must retain the above 1565686Smarkm * copyright notice, this list of conditions and the following 1665686Smarkm * disclaimer. 1765686Smarkm * 1865686Smarkm * - Redistributions in binary form must reproduce the above 1965686Smarkm * copyright notice, this list of conditions and the following 2065686Smarkm * disclaimer in the documentation and/or other materials 2165686Smarkm * provided with the distribution. 2265686Smarkm * 2365686Smarkm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2465686Smarkm * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2565686Smarkm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2665686Smarkm * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2765686Smarkm * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 2865686Smarkm * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29256381Smarkm * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30256381Smarkm * SOFTWARE. 31256381Smarkm * 32255362Smarkm */ 33255362Smarkm 3465686Smarkm#if HAVE_CONFIG_H 35255362Smarkm# include <config.h> 36100082Smarkm#endif /* HAVE_CONFIG_H */ 3765686Smarkm 3865686Smarkm#include <stdio.h> 39255362Smarkm#include <stdlib.h> 4074072Smarkm#include <unistd.h> 4174072Smarkm#include <stdarg.h> 4265686Smarkm#include <time.h> 4365686Smarkm#include <string.h> 44255362Smarkm#include <getopt.h> 45255362Smarkm 46255362Smarkm#include <infiniband/common.h> 47255362Smarkm#include <infiniband/umad.h> 48255362Smarkm#include <infiniband/mad.h> 49256381Smarkm 50256381Smarkm#include "ibdiag_common.h" 51 52#undef DEBUG 53#define DEBUG if (verbose) IBWARN 54 55static int dest_type = IB_DEST_LID; 56static int verbose; 57 58#define MAX_CPUS 8 59 60enum ib_sysstat_attr_t { 61 IB_PING_ATTR = 0x10, 62 IB_HOSTINFO_ATTR = 0x11, 63 IB_CPUINFO_ATTR = 0x12, 64}; 65 66typedef struct cpu_info { 67 char *model; 68 char *mhz; 69} cpu_info; 70 71static cpu_info cpus[MAX_CPUS]; 72static int host_ncpu; 73 74char *argv0 = "ibsysstat"; 75 76static void 77mk_reply(int attr, void *data, int sz) 78{ 79 char *s = data; 80 int n, i; 81 82 switch (attr) { 83 case IB_PING_ATTR: 84 break; /* nothing to do here, just reply */ 85 case IB_HOSTINFO_ATTR: 86 if (gethostname(s, sz) < 0) 87 snprintf(s, sz, "?hostname?"); 88 s[sz-1] = 0; 89 if ((n = strlen(s)) >= sz) 90 break; 91 s[n] = '.'; 92 s += n+1; 93 sz -= n+1; 94 if (getdomainname(s, sz) < 0) 95 snprintf(s, sz, "?domainname?"); 96 if (strlen(s) == 0) 97 s[-1] = 0; /* no domain */ 98 break; 99 case IB_CPUINFO_ATTR: 100 for (i = 0; i < host_ncpu && sz > 0; i++) { 101 n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n", 102 i, cpus[i].model, cpus[i].mhz); 103 if (n >= sz) { 104 IBWARN("cpuinfo truncated"); 105 break; 106 } 107 sz -= n; 108 s += n; 109 } 110 break; 111 default: 112 DEBUG("unknown attr %d", attr); 113 } 114} 115 116static char * 117ibsystat_serv(void) 118{ 119 void *umad; 120 void *mad; 121 int attr, mod; 122 123 DEBUG("starting to serve..."); 124 125 while ((umad = mad_receive(0, -1))) { 126 127 mad = umad_get_mad(umad); 128 129 attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F); 130 mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F); 131 132 DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod); 133 134 mk_reply(attr, (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS, IB_VENDOR_RANGE2_DATA_SIZE); 135 136 if (mad_respond(umad, 0, 0) < 0) 137 DEBUG("respond failed"); 138 139 mad_free(umad); 140 } 141 142 DEBUG("server out"); 143 return 0; 144} 145 146static int 147match_attr(char *str) 148{ 149 if (!strcmp(str, "ping")) 150 return IB_PING_ATTR; 151 if (!strcmp(str, "host")) 152 return IB_HOSTINFO_ATTR; 153 if (!strcmp(str, "cpu")) 154 return IB_CPUINFO_ATTR; 155 return -1; 156} 157 158static char * 159ibsystat(ib_portid_t *portid, int attr) 160{ 161 char data[IB_VENDOR_RANGE2_DATA_SIZE] = {0}; 162 ib_vendor_call_t call; 163 164 DEBUG("Sysstat ping.."); 165 166 call.method = IB_MAD_METHOD_GET; 167 call.mgmt_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS; 168 call.attrid = attr; 169 call.mod = 0; 170 call.oui = IB_OPENIB_OUI; 171 call.timeout = 0; 172 memset(&call.rmpp, 0, sizeof call.rmpp); 173 174 if (!ib_vendor_call(data, portid, &call)) 175 return "vendor call failed"; 176 177 DEBUG("Got sysstat pong.."); 178 if (attr != IB_PING_ATTR) 179 puts(data); 180 else 181 printf("sysstat ping succeeded\n"); 182 return 0; 183} 184 185int 186build_cpuinfo(void) 187{ 188 char line[1024] = {0}, *s, *e; 189 FILE *f; 190 int ncpu = 0; 191 192 if (!(f = fopen("/proc/cpuinfo", "r"))) { 193 IBWARN("couldn't open /proc/cpuinfo"); 194 return 0; 195 } 196 197 while (fgets(line, sizeof(line) - 1, f)) { 198 if (!strncmp(line, "processor\t", 10)) { 199 ncpu++; 200 if (ncpu > MAX_CPUS) 201 return MAX_CPUS; 202 continue; 203 } 204 205 if (!ncpu || !(s = strchr(line, ':'))) 206 continue; 207 208 if ((e = strchr(s, '\n'))) 209 *e = 0; 210 if (!strncmp(line, "model name\t", 11)) 211 cpus[ncpu-1].model = strdup(s+1); 212 else if (!strncmp(line, "cpu MHz\t", 8)) 213 cpus[ncpu-1].mhz = strdup(s+1); 214 } 215 216 fclose(f); 217 218 DEBUG("ncpu %d", ncpu); 219 220 return ncpu; 221} 222 223static void 224usage(void) 225{ 226 char *basename; 227 228 if (!(basename = strrchr(argv0, '/'))) 229 basename = argv0; 230 else 231 basename++; 232 233 fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port " 234 "-t(imeout) timeout_ms -o oui -S(erver)] <dest lid|guid> [<op>]\n", 235 basename); 236 exit(-1); 237} 238 239int 240main(int argc, char **argv) 241{ 242 int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS}; 243 int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS; 244 ib_portid_t portid = {0}; 245 ib_portid_t *sm_id = 0, sm_portid = {0}; 246 int timeout = 0, udebug = 0, server = 0; 247 int oui = IB_OPENIB_OUI, attr = IB_PING_ATTR; 248 extern int ibdebug; 249 char *err; 250 char *ca = 0; 251 int ca_port = 0; 252 253 static char const str_opts[] = "C:P:t:s:o:devGSVhu"; 254 static const struct option long_opts[] = { 255 { "C", 1, 0, 'C'}, 256 { "P", 1, 0, 'P'}, 257 { "debug", 0, 0, 'd'}, 258 { "err_show", 0, 0, 'e'}, 259 { "verbose", 0, 0, 'v'}, 260 { "Guid", 0, 0, 'G'}, 261 { "timeout", 1, 0, 't'}, 262 { "s", 1, 0, 's'}, 263 { "o", 1, 0, 'o'}, 264 { "Server", 0, 0, 'S'}, 265 { "Version", 0, 0, 'V'}, 266 { "help", 0, 0, 'h'}, 267 { "usage", 0, 0, 'u'}, 268 { } 269 }; 270 271 argv0 = argv[0]; 272 273 while (1) { 274 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 275 if ( ch == -1 ) 276 break; 277 switch(ch) { 278 case 'C': 279 ca = optarg; 280 break; 281 case 'P': 282 ca_port = strtoul(optarg, 0, 0); 283 break; 284 case 'd': 285 ibdebug++; 286 madrpc_show_errors(1); 287 umad_debug(udebug); 288 udebug++; 289 break; 290 case 'e': 291 madrpc_show_errors(1); 292 break; 293 case 'G': 294 dest_type = IB_DEST_GUID; 295 break; 296 case 'o': 297 oui = strtoul(optarg, 0, 0); 298 break; 299 case 's': 300 if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0) 301 IBERROR("can't resolve SM destination port %s", optarg); 302 sm_id = &sm_portid; 303 break; 304 case 'S': 305 server++; 306 break; 307 case 't': 308 timeout = strtoul(optarg, 0, 0); 309 madrpc_set_timeout(timeout); 310 break; 311 case 'v': 312 verbose++; 313 break; 314 case 'V': 315 fprintf(stderr, "%s %s\n", argv0, get_build_version() ); 316 exit(-1); 317 default: 318 usage(); 319 break; 320 } 321 } 322 argc -= optind; 323 argv += optind; 324 325 if (!argc && !server) 326 usage(); 327 328 if (argc > 1 && (attr = match_attr(argv[1])) < 0) 329 usage(); 330 331 madrpc_init(ca, ca_port, mgmt_classes, 3); 332 333 if (server) { 334 if (mad_register_server(sysstat_class, 0, 0, oui) < 0) 335 IBERROR("can't serve class %d", sysstat_class); 336 337 host_ncpu = build_cpuinfo(); 338 339 if ((err = ibsystat_serv())) 340 IBERROR("ibssystat to %s: %s", portid2str(&portid), err); 341 exit(0); 342 } 343 344 if (mad_register_client(sysstat_class, 0) < 0) 345 IBERROR("can't register to sysstat class %d", sysstat_class); 346 347 if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0) 348 IBERROR("can't resolve destination port %s", argv[0]); 349 350 if ((err = ibsystat(&portid, attr))) 351 IBERROR("ibsystat to %s: %s", portid2str(&portid), err); 352 353 exit(0); 354} 355