1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3d6b92ffaSHans Petter Selasky * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
4d6b92ffaSHans Petter Selasky *
5d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
6d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
7d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
8d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
9d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
10d6b92ffaSHans Petter Selasky *
11d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
12d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
13d6b92ffaSHans Petter Selasky * conditions are met:
14d6b92ffaSHans Petter Selasky *
15d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
16d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
17d6b92ffaSHans Petter Selasky * disclaimer.
18d6b92ffaSHans Petter Selasky *
19d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
20d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
21d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
22d6b92ffaSHans Petter Selasky * provided with the distribution.
23d6b92ffaSHans Petter Selasky *
24d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31d6b92ffaSHans Petter Selasky * SOFTWARE.
32d6b92ffaSHans Petter Selasky *
33d6b92ffaSHans Petter Selasky */
34d6b92ffaSHans Petter Selasky
35d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
36d6b92ffaSHans Petter Selasky
37d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
38d6b92ffaSHans Petter Selasky # include <config.h>
39d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
40d6b92ffaSHans Petter Selasky
41d6b92ffaSHans Petter Selasky #include <inttypes.h>
42d6b92ffaSHans Petter Selasky #include <string.h>
43d6b92ffaSHans Petter Selasky #include <stdio.h>
44d6b92ffaSHans Petter Selasky #include <stdlib.h>
45d6b92ffaSHans Petter Selasky #include <getopt.h>
46d6b92ffaSHans Petter Selasky #include <netinet/in.h>
47d6b92ffaSHans Petter Selasky #include <sys/types.h>
48d6b92ffaSHans Petter Selasky #include <sys/stat.h>
49d6b92ffaSHans Petter Selasky #include <fcntl.h>
50d6b92ffaSHans Petter Selasky #include <errno.h>
51*16fa3dcbSHans Petter Selasky #include <sys/sysctl.h>
52d6b92ffaSHans Petter Selasky
53d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
54d6b92ffaSHans Petter Selasky
55d6b92ffaSHans Petter Selasky #include <ibdiag_common.h>
56d6b92ffaSHans Petter Selasky
57d6b92ffaSHans Petter Selasky static char *node_type_str[] = {
58d6b92ffaSHans Petter Selasky "???",
59d6b92ffaSHans Petter Selasky "CA",
60d6b92ffaSHans Petter Selasky "Switch",
61d6b92ffaSHans Petter Selasky "Router",
62d6b92ffaSHans Petter Selasky "iWARP RNIC"
63d6b92ffaSHans Petter Selasky };
64d6b92ffaSHans Petter Selasky
ca_dump(umad_ca_t * ca)65d6b92ffaSHans Petter Selasky static void ca_dump(umad_ca_t * ca)
66d6b92ffaSHans Petter Selasky {
67d6b92ffaSHans Petter Selasky if (!ca->node_type)
68d6b92ffaSHans Petter Selasky return;
69d6b92ffaSHans Petter Selasky printf("%s '%s'\n",
70d6b92ffaSHans Petter Selasky ((unsigned)ca->node_type <=
71d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),
72d6b92ffaSHans Petter Selasky ca->ca_name);
73d6b92ffaSHans Petter Selasky printf("\t%s type: %s\n",
74d6b92ffaSHans Petter Selasky ((unsigned)ca->node_type <=
75d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),
76d6b92ffaSHans Petter Selasky ca->ca_type);
77d6b92ffaSHans Petter Selasky printf("\tNumber of ports: %d\n", ca->numports);
78d6b92ffaSHans Petter Selasky printf("\tFirmware version: %s\n", ca->fw_ver);
79d6b92ffaSHans Petter Selasky printf("\tHardware version: %s\n", ca->hw_ver);
80d6b92ffaSHans Petter Selasky printf("\tNode GUID: 0x%016" PRIx64 "\n", ntohll(ca->node_guid));
81d6b92ffaSHans Petter Selasky printf("\tSystem image GUID: 0x%016" PRIx64 "\n",
82d6b92ffaSHans Petter Selasky ntohll(ca->system_guid));
83d6b92ffaSHans Petter Selasky }
84d6b92ffaSHans Petter Selasky
85d6b92ffaSHans Petter Selasky static char *port_state_str[] = {
86d6b92ffaSHans Petter Selasky "???",
87d6b92ffaSHans Petter Selasky "Down",
88d6b92ffaSHans Petter Selasky "Initializing",
89d6b92ffaSHans Petter Selasky "Armed",
90d6b92ffaSHans Petter Selasky "Active"
91d6b92ffaSHans Petter Selasky };
92d6b92ffaSHans Petter Selasky
93d6b92ffaSHans Petter Selasky static char *port_phy_state_str[] = {
94d6b92ffaSHans Petter Selasky "No state change",
95d6b92ffaSHans Petter Selasky "Sleep",
96d6b92ffaSHans Petter Selasky "Polling",
97d6b92ffaSHans Petter Selasky "Disabled",
98d6b92ffaSHans Petter Selasky "PortConfigurationTraining",
99d6b92ffaSHans Petter Selasky "LinkUp",
100d6b92ffaSHans Petter Selasky "LinkErrorRecovery",
101d6b92ffaSHans Petter Selasky "PhyTest"
102d6b92ffaSHans Petter Selasky };
103d6b92ffaSHans Petter Selasky
ret_code(void)104d6b92ffaSHans Petter Selasky static int ret_code(void)
105d6b92ffaSHans Petter Selasky {
106d6b92ffaSHans Petter Selasky int e = errno;
107d6b92ffaSHans Petter Selasky
108d6b92ffaSHans Petter Selasky if (e > 0)
109d6b92ffaSHans Petter Selasky return -e;
110d6b92ffaSHans Petter Selasky return e;
111d6b92ffaSHans Petter Selasky }
112d6b92ffaSHans Petter Selasky
sys_read_string(const char * dir_name,const char * file_name,char * str,int max_len)113d6b92ffaSHans Petter Selasky int sys_read_string(const char *dir_name, const char *file_name, char *str, int max_len)
114d6b92ffaSHans Petter Selasky {
115d6b92ffaSHans Petter Selasky char path[256], *s;
116d6b92ffaSHans Petter Selasky size_t len;
117d6b92ffaSHans Petter Selasky
118d6b92ffaSHans Petter Selasky snprintf(path, sizeof(path), "%s/%s", dir_name, file_name);
119d6b92ffaSHans Petter Selasky
120d6b92ffaSHans Petter Selasky for (s = &path[0]; *s != '\0'; s++)
121d6b92ffaSHans Petter Selasky if (*s == '/')
122d6b92ffaSHans Petter Selasky *s = '.';
123d6b92ffaSHans Petter Selasky
124d6b92ffaSHans Petter Selasky len = max_len;
125d6b92ffaSHans Petter Selasky if (sysctlbyname(&path[1], str, &len, NULL, 0) == -1)
126d6b92ffaSHans Petter Selasky return ret_code();
127d6b92ffaSHans Petter Selasky
128d6b92ffaSHans Petter Selasky str[(len < max_len) ? len : max_len - 1] = 0;
129d6b92ffaSHans Petter Selasky
130d6b92ffaSHans Petter Selasky if ((s = strrchr(str, '\n')))
131d6b92ffaSHans Petter Selasky *s = 0;
132d6b92ffaSHans Petter Selasky
133d6b92ffaSHans Petter Selasky return 0;
134d6b92ffaSHans Petter Selasky }
135d6b92ffaSHans Petter Selasky
is_fdr10(umad_port_t * port)136d6b92ffaSHans Petter Selasky static int is_fdr10(umad_port_t *port)
137d6b92ffaSHans Petter Selasky {
138d6b92ffaSHans Petter Selasky char port_dir[256];
139d6b92ffaSHans Petter Selasky char rate[32];
140d6b92ffaSHans Petter Selasky int len, fdr10 = 0;
141d6b92ffaSHans Petter Selasky char *p;
142d6b92ffaSHans Petter Selasky
143d6b92ffaSHans Petter Selasky len = snprintf(port_dir, sizeof(port_dir), "%s/%s/%s/%d",
144d6b92ffaSHans Petter Selasky SYS_INFINIBAND, port->ca_name, SYS_CA_PORTS_DIR,
145d6b92ffaSHans Petter Selasky port->portnum);
146d6b92ffaSHans Petter Selasky if (len < 0 || len > sizeof(port_dir))
147d6b92ffaSHans Petter Selasky goto done;
148d6b92ffaSHans Petter Selasky
149d6b92ffaSHans Petter Selasky if (sys_read_string(port_dir, SYS_PORT_RATE, rate, sizeof(rate)) == 0) {
150d6b92ffaSHans Petter Selasky if ((p = strchr(rate, ')'))) {
151d6b92ffaSHans Petter Selasky if (!strncasecmp(p - 5, "fdr10", 5))
152d6b92ffaSHans Petter Selasky fdr10 = 1;
153d6b92ffaSHans Petter Selasky }
154d6b92ffaSHans Petter Selasky }
155d6b92ffaSHans Petter Selasky
156d6b92ffaSHans Petter Selasky done:
157d6b92ffaSHans Petter Selasky return fdr10;
158d6b92ffaSHans Petter Selasky }
159d6b92ffaSHans Petter Selasky
port_dump(umad_port_t * port,int alone)160d6b92ffaSHans Petter Selasky static int port_dump(umad_port_t * port, int alone)
161d6b92ffaSHans Petter Selasky {
162d6b92ffaSHans Petter Selasky char *pre = "";
163d6b92ffaSHans Petter Selasky char *hdrpre = "";
164d6b92ffaSHans Petter Selasky
165d6b92ffaSHans Petter Selasky if (!port)
166d6b92ffaSHans Petter Selasky return -1;
167d6b92ffaSHans Petter Selasky
168d6b92ffaSHans Petter Selasky if (!alone) {
169d6b92ffaSHans Petter Selasky pre = " ";
170d6b92ffaSHans Petter Selasky hdrpre = " ";
171d6b92ffaSHans Petter Selasky }
172d6b92ffaSHans Petter Selasky
173d6b92ffaSHans Petter Selasky printf("%sPort %d:\n", hdrpre, port->portnum);
174d6b92ffaSHans Petter Selasky printf("%sState: %s\n", pre,
175d6b92ffaSHans Petter Selasky (unsigned)port->state <=
176d6b92ffaSHans Petter Selasky 4 ? port_state_str[port->state] : "???");
177d6b92ffaSHans Petter Selasky printf("%sPhysical state: %s\n", pre,
178d6b92ffaSHans Petter Selasky (unsigned)port->phys_state <=
179d6b92ffaSHans Petter Selasky 7 ? port_phy_state_str[port->phys_state] : "???");
180d6b92ffaSHans Petter Selasky if (is_fdr10(port))
181d6b92ffaSHans Petter Selasky printf("%sRate: %d (FDR10)\n", pre, port->rate);
182d6b92ffaSHans Petter Selasky else
183d6b92ffaSHans Petter Selasky if (port->rate != 2)
184d6b92ffaSHans Petter Selasky printf("%sRate: %d\n", pre, port->rate);
185d6b92ffaSHans Petter Selasky else
186d6b92ffaSHans Petter Selasky printf("%sRate: 2.5\n", pre);
187d6b92ffaSHans Petter Selasky printf("%sBase lid: %d\n", pre, port->base_lid);
188d6b92ffaSHans Petter Selasky printf("%sLMC: %d\n", pre, port->lmc);
189d6b92ffaSHans Petter Selasky printf("%sSM lid: %d\n", pre, port->sm_lid);
190d6b92ffaSHans Petter Selasky printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask));
191d6b92ffaSHans Petter Selasky printf("%sPort GUID: 0x%016" PRIx64 "\n", pre, ntohll(port->port_guid));
192d6b92ffaSHans Petter Selasky #ifdef HAVE_UMAD_PORT_LINK_LAYER
193d6b92ffaSHans Petter Selasky printf("%sLink layer: %s\n", pre, port->link_layer);
194d6b92ffaSHans Petter Selasky #endif
195d6b92ffaSHans Petter Selasky return 0;
196d6b92ffaSHans Petter Selasky }
197d6b92ffaSHans Petter Selasky
ca_stat(char * ca_name,int portnum,int no_ports)198d6b92ffaSHans Petter Selasky static int ca_stat(char *ca_name, int portnum, int no_ports)
199d6b92ffaSHans Petter Selasky {
200d6b92ffaSHans Petter Selasky umad_ca_t ca;
201d6b92ffaSHans Petter Selasky int r;
202d6b92ffaSHans Petter Selasky
203d6b92ffaSHans Petter Selasky if ((r = umad_get_ca(ca_name, &ca)) < 0)
204d6b92ffaSHans Petter Selasky return r;
205d6b92ffaSHans Petter Selasky
206d6b92ffaSHans Petter Selasky if (!ca.node_type)
207d6b92ffaSHans Petter Selasky return 0;
208d6b92ffaSHans Petter Selasky
209d6b92ffaSHans Petter Selasky if (!no_ports && portnum >= 0) {
210d6b92ffaSHans Petter Selasky if (portnum > ca.numports || !ca.ports[portnum]) {
211d6b92ffaSHans Petter Selasky IBWARN("%s: '%s' has no port number %d - max (%d)",
212d6b92ffaSHans Petter Selasky ((unsigned)ca.node_type <=
213d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca.node_type] :
214d6b92ffaSHans Petter Selasky "???"), ca_name, portnum, ca.numports);
215d6b92ffaSHans Petter Selasky return -1;
216d6b92ffaSHans Petter Selasky }
217d6b92ffaSHans Petter Selasky printf("%s: '%s'\n",
218d6b92ffaSHans Petter Selasky ((unsigned)ca.node_type <=
219d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca.node_type] : "???"),
220d6b92ffaSHans Petter Selasky ca.ca_name);
221d6b92ffaSHans Petter Selasky port_dump(ca.ports[portnum], 1);
222d6b92ffaSHans Petter Selasky return 0;
223d6b92ffaSHans Petter Selasky }
224d6b92ffaSHans Petter Selasky
225d6b92ffaSHans Petter Selasky /* print ca header */
226d6b92ffaSHans Petter Selasky ca_dump(&ca);
227d6b92ffaSHans Petter Selasky
228d6b92ffaSHans Petter Selasky if (no_ports)
229d6b92ffaSHans Petter Selasky return 0;
230d6b92ffaSHans Petter Selasky
231d6b92ffaSHans Petter Selasky for (portnum = 0; portnum <= ca.numports; portnum++)
232d6b92ffaSHans Petter Selasky port_dump(ca.ports[portnum], 0);
233d6b92ffaSHans Petter Selasky
234d6b92ffaSHans Petter Selasky return 0;
235d6b92ffaSHans Petter Selasky }
236d6b92ffaSHans Petter Selasky
ports_list(char names[][UMAD_CA_NAME_LEN],int n)237d6b92ffaSHans Petter Selasky static int ports_list(char names[][UMAD_CA_NAME_LEN], int n)
238d6b92ffaSHans Petter Selasky {
239d6b92ffaSHans Petter Selasky uint64_t guids[64];
240d6b92ffaSHans Petter Selasky int found, ports, i;
241d6b92ffaSHans Petter Selasky
242d6b92ffaSHans Petter Selasky for (i = 0, found = 0; i < n && found < 64; i++) {
243d6b92ffaSHans Petter Selasky if ((ports =
244d6b92ffaSHans Petter Selasky umad_get_ca_portguids(names[i], guids + found,
245d6b92ffaSHans Petter Selasky 64 - found)) < 0)
246d6b92ffaSHans Petter Selasky return -1;
247d6b92ffaSHans Petter Selasky found += ports;
248d6b92ffaSHans Petter Selasky }
249d6b92ffaSHans Petter Selasky
250d6b92ffaSHans Petter Selasky for (i = 0; i < found; i++)
251d6b92ffaSHans Petter Selasky if (guids[i])
252d6b92ffaSHans Petter Selasky printf("0x%016" PRIx64 "\n", ntohll(guids[i]));
253d6b92ffaSHans Petter Selasky return found;
254d6b92ffaSHans Petter Selasky }
255d6b92ffaSHans Petter Selasky
256d6b92ffaSHans Petter Selasky static int list_only, short_format, list_ports;
257d6b92ffaSHans Petter Selasky
process_opt(void * context,int ch,char * optarg)258d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
259d6b92ffaSHans Petter Selasky {
260d6b92ffaSHans Petter Selasky switch (ch) {
261d6b92ffaSHans Petter Selasky case 'l':
262d6b92ffaSHans Petter Selasky list_only++;
263d6b92ffaSHans Petter Selasky break;
264d6b92ffaSHans Petter Selasky case 's':
265d6b92ffaSHans Petter Selasky short_format++;
266d6b92ffaSHans Petter Selasky break;
267d6b92ffaSHans Petter Selasky case 'p':
268d6b92ffaSHans Petter Selasky list_ports++;
269d6b92ffaSHans Petter Selasky break;
270d6b92ffaSHans Petter Selasky default:
271d6b92ffaSHans Petter Selasky return -1;
272d6b92ffaSHans Petter Selasky }
273d6b92ffaSHans Petter Selasky return 0;
274d6b92ffaSHans Petter Selasky }
275d6b92ffaSHans Petter Selasky
main(int argc,char * argv[])276d6b92ffaSHans Petter Selasky int main(int argc, char *argv[])
277d6b92ffaSHans Petter Selasky {
278d6b92ffaSHans Petter Selasky char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN];
279d6b92ffaSHans Petter Selasky int dev_port = -1;
280d6b92ffaSHans Petter Selasky int n, i;
281d6b92ffaSHans Petter Selasky
282d6b92ffaSHans Petter Selasky const struct ibdiag_opt opts[] = {
283d6b92ffaSHans Petter Selasky {"list_of_cas", 'l', 0, NULL, "list all IB devices"},
284d6b92ffaSHans Petter Selasky {"short", 's', 0, NULL, "short output"},
285d6b92ffaSHans Petter Selasky {"port_list", 'p', 0, NULL, "show port list"},
286d6b92ffaSHans Petter Selasky {0}
287d6b92ffaSHans Petter Selasky };
288d6b92ffaSHans Petter Selasky char usage_args[] = "<ca_name> [portnum]";
289d6b92ffaSHans Petter Selasky const char *usage_examples[] = {
290d6b92ffaSHans Petter Selasky "-l # list all IB devices",
291d6b92ffaSHans Petter Selasky "mthca0 2 # stat port 2 of 'mthca0'",
292d6b92ffaSHans Petter Selasky NULL
293d6b92ffaSHans Petter Selasky };
294d6b92ffaSHans Petter Selasky
295d6b92ffaSHans Petter Selasky ibdiag_process_opts(argc, argv, NULL, "CDeGKLPsty", opts, process_opt,
296d6b92ffaSHans Petter Selasky usage_args, usage_examples);
297d6b92ffaSHans Petter Selasky
298d6b92ffaSHans Petter Selasky argc -= optind;
299d6b92ffaSHans Petter Selasky argv += optind;
300d6b92ffaSHans Petter Selasky
301d6b92ffaSHans Petter Selasky if (argc > 1)
302d6b92ffaSHans Petter Selasky dev_port = strtol(argv[1], 0, 0);
303d6b92ffaSHans Petter Selasky
304d6b92ffaSHans Petter Selasky if (umad_init() < 0)
305d6b92ffaSHans Petter Selasky IBPANIC("can't init UMAD library");
306d6b92ffaSHans Petter Selasky
307d6b92ffaSHans Petter Selasky if ((n = umad_get_cas_names(names, UMAD_MAX_DEVICES)) < 0)
308d6b92ffaSHans Petter Selasky IBPANIC("can't list IB device names");
309d6b92ffaSHans Petter Selasky
310d6b92ffaSHans Petter Selasky if (argc) {
311d6b92ffaSHans Petter Selasky for (i = 0; i < n; i++)
312d6b92ffaSHans Petter Selasky if (!strncmp(names[i], argv[0], sizeof names[i]))
313d6b92ffaSHans Petter Selasky break;
314d6b92ffaSHans Petter Selasky if (i >= n)
315d6b92ffaSHans Petter Selasky IBPANIC("'%s' IB device can't be found", argv[0]);
316d6b92ffaSHans Petter Selasky
317d6b92ffaSHans Petter Selasky strncpy(names[0], argv[0], sizeof(names[0])-1);
318d6b92ffaSHans Petter Selasky names[0][sizeof(names[0])-1] = '\0';
319d6b92ffaSHans Petter Selasky n = 1;
320d6b92ffaSHans Petter Selasky }
321d6b92ffaSHans Petter Selasky
322d6b92ffaSHans Petter Selasky if (list_ports) {
323d6b92ffaSHans Petter Selasky if (ports_list(names, n) < 0)
324d6b92ffaSHans Petter Selasky IBPANIC("can't list ports");
325d6b92ffaSHans Petter Selasky return 0;
326d6b92ffaSHans Petter Selasky }
327d6b92ffaSHans Petter Selasky
328d6b92ffaSHans Petter Selasky for (i = 0; i < n; i++) {
329d6b92ffaSHans Petter Selasky if (list_only)
330d6b92ffaSHans Petter Selasky printf("%s\n", names[i]);
331d6b92ffaSHans Petter Selasky else if (ca_stat(names[i], dev_port, short_format) < 0)
332d6b92ffaSHans Petter Selasky IBPANIC("stat of IB device '%s' failed", names[i]);
333d6b92ffaSHans Petter Selasky }
334d6b92ffaSHans Petter Selasky
335d6b92ffaSHans Petter Selasky return 0;
336d6b92ffaSHans Petter Selasky }
337