| /* |
| * 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 <inttypes.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <netinet/in.h> |
| #include <endian.h> |
| |
| #include <infiniband/mad.h> |
| #include <infiniband/umad.h> |
| |
| #include <ibdiag_common.h> |
| |
| 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[] = "<dlid|dr_path> <attr> [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; |
| } |