/* * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include static int mad_agent; static int drmad_tid = 0x123; typedef struct { char path[64]; int hop_cnt; } DRPath; struct drsmp { uint8_t base_version; uint8_t mgmt_class; uint8_t class_version; uint8_t method; __be16 status; uint8_t hop_ptr; uint8_t hop_cnt; __be64 tid; __be16 attr_id; uint16_t resv; __be32 attr_mod; __be64 mkey; __be16 dr_slid; __be16 dr_dlid; uint8_t reserved[28]; uint8_t data[64]; uint8_t initial_path[64]; uint8_t return_path[64]; }; static void drsmp_get_init(void *umad, DRPath * path, int attr, int mod) { struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); memset(smp, 0, sizeof(*smp)); smp->base_version = 1; smp->mgmt_class = IB_SMI_DIRECT_CLASS; smp->class_version = 1; smp->method = 1; smp->attr_id = htons(attr); smp->attr_mod = htonl(mod); smp->tid = htobe64(drmad_tid); drmad_tid++; smp->dr_slid = htobe16(0xffff); smp->dr_dlid = htobe16(0xffff); umad_set_addr(umad, 0xffff, 0, 0, 0); if (path) memcpy(smp->initial_path, path->path, path->hop_cnt + 1); smp->hop_cnt = (uint8_t) path->hop_cnt; } static void smp_get_init(void *umad, int lid, int attr, int mod) { struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); memset(smp, 0, sizeof(*smp)); smp->base_version = 1; smp->mgmt_class = IB_SMI_CLASS; smp->class_version = 1; smp->method = 1; smp->attr_id = htons(attr); smp->attr_mod = htonl(mod); smp->tid = htobe64(drmad_tid); drmad_tid++; umad_set_addr(umad, lid, 0, 0, 0); } static int str2DRPath(char *str, DRPath * path) { char *s; path->hop_cnt = -1; DEBUG("DR str: %s", str); while (str && *str) { if ((s = strchr(str, ','))) *s = 0; path->path[++path->hop_cnt] = (char)atoi(str); if (!s) break; str = s + 1; } #if 0 if (path->path[0] != 0 || (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) { DEBUG("hop 0 != 0 or hop 1 != dev_port"); return -1; } #endif return path->hop_cnt; } static int dump_char, mgmt_class = IB_SMI_CLASS; static int process_opt(void *context, int ch) { switch (ch) { case 's': dump_char++; break; case 'D': mgmt_class = IB_SMI_DIRECT_CLASS; break; case 'L': mgmt_class = IB_SMI_CLASS; break; default: return -1; } return 0; } int main(int argc, char *argv[]) { int dlid = 0; void *umad; struct drsmp *smp; int i, portid, mod = 0, attr; DRPath path; uint8_t *desc; int length; const struct ibdiag_opt opts[] = { {"string", 's', 0, NULL, ""}, {} }; char usage_args[] = " [mod]"; const char *usage_examples[] = { " -- DR routed examples:", "-D 0,1,2,3,5 16 # NODE DESC", "-D 0,1,2 0x15 2 # PORT INFO, port 2", " -- LID routed examples:", "3 0x15 2 # PORT INFO, lid 3 port 2", "0xa0 0x11 # NODE INFO, lid 0xa0", NULL }; ibd_timeout = 1000; ibdiag_process_opts(argc, argv, NULL, "GKs", opts, process_opt, usage_args, usage_examples); argc -= optind; argv += optind; if (argc < 2) ibdiag_show_usage(); if (mgmt_class == IB_SMI_DIRECT_CLASS && str2DRPath(strdupa(argv[0]), &path) < 0) IBPANIC("bad path str '%s'", argv[0]); if (mgmt_class == IB_SMI_CLASS) dlid = strtoul(argv[0], NULL, 0); attr = strtoul(argv[1], NULL, 0); if (argc > 2) mod = strtoul(argv[2], NULL, 0); if (umad_init() < 0) IBPANIC("can't init UMAD library"); if ((portid = umad_open_port(ibd_ca, ibd_ca_port)) < 0) IBPANIC("can't open UMAD port (%s:%d)", ibd_ca, ibd_ca_port); if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, NULL)) < 0) IBPANIC("Couldn't register agent for SMPs"); if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE))) IBPANIC("can't alloc MAD"); smp = umad_get_mad(umad); if (mgmt_class == IB_SMI_DIRECT_CLASS) drsmp_get_init(umad, &path, attr, mod); else smp_get_init(umad, dlid, attr, mod); if (ibdebug > 1) xdump(stderr, "before send:\n", smp, 256); length = IB_MAD_SIZE; if (umad_send(portid, mad_agent, umad, length, ibd_timeout, 0) < 0) IBPANIC("send failed"); if (umad_recv(portid, umad, &length, -1) != mad_agent) IBPANIC("recv error: %s", strerror(errno)); if (ibdebug) fprintf(stderr, "%d bytes received\n", length); if (!dump_char) { xdump(stdout, NULL, smp->data, 64); if (smp->status) fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status)); goto exit; } desc = smp->data; for (i = 0; i < 64; ++i) { if (!desc[i]) break; putchar(desc[i]); } putchar('\n'); if (smp->status) fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status)); exit: umad_free(umad); return 0; }