2 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
3 * Copyright (c) 2005, 2006 Voltaire Inc. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directorY of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 #include <linux/module.h>
36 #include <linux/device.h>
37 #include <linux/err.h>
39 #include <rdma/ib_mad.h>
40 #include <rdma/ib_smi.h>
41 #include <rdma/ib_sa.h>
43 MODULE_AUTHOR("Sean Hefty");
44 MODULE_DESCRIPTION("InfiniBand MAD viewer");
45 MODULE_LICENSE("Dual BSD/GPL");
47 static void madeye_remove_one(struct ib_device *device);
48 static void madeye_add_one(struct ib_device *device);
50 static struct ib_client madeye_client = {
52 .add = madeye_add_one,
53 .remove = madeye_remove_one
57 struct ib_mad_agent *smi_agent;
58 struct ib_mad_agent *gsi_agent;
63 static int mgmt_class = 0;
64 static int attr_id = 0;
67 module_param(smp, int, 0444);
68 module_param(gmp, int, 0444);
69 module_param(mgmt_class, int, 0444);
70 module_param(attr_id, int, 0444);
71 module_param(data, int, 0444);
73 MODULE_PARM_DESC(smp, "Display all SMPs (default=1)");
74 MODULE_PARM_DESC(gmp, "Display all GMPs (default=1)");
75 MODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)");
76 MODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)");
77 MODULE_PARM_DESC(data, "Display data area of MADs (default=0)");
79 static char * get_class_name(u8 mgmt_class)
82 case IB_MGMT_CLASS_SUBN_LID_ROUTED:
83 return "LID routed SMP";
84 case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
85 return "Directed route SMP";
86 case IB_MGMT_CLASS_SUBN_ADM:
87 return "Subnet admin.";
88 case IB_MGMT_CLASS_PERF_MGMT:
90 case IB_MGMT_CLASS_BM:
91 return "Baseboard mgmt.";
92 case IB_MGMT_CLASS_DEVICE_MGMT:
93 return "Device mgmt.";
94 case IB_MGMT_CLASS_CM:
96 case IB_MGMT_CLASS_SNMP:
99 return "Unknown vendor/application";
103 static char * get_method_name(u8 mgmt_class, u8 method)
106 case IB_MGMT_METHOD_GET:
108 case IB_MGMT_METHOD_SET:
110 case IB_MGMT_METHOD_GET_RESP:
111 return "Get response";
112 case IB_MGMT_METHOD_SEND:
114 case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:
115 return "Send response";
116 case IB_MGMT_METHOD_TRAP:
118 case IB_MGMT_METHOD_REPORT:
120 case IB_MGMT_METHOD_REPORT_RESP:
121 return "Report response";
122 case IB_MGMT_METHOD_TRAP_REPRESS:
123 return "Trap repress";
128 switch (mgmt_class) {
129 case IB_MGMT_CLASS_SUBN_ADM:
131 case IB_SA_METHOD_GET_TABLE:
133 case IB_SA_METHOD_GET_TABLE_RESP:
134 return "Get table response";
135 case IB_SA_METHOD_DELETE:
137 case IB_SA_METHOD_DELETE_RESP:
138 return "Delete response";
139 case IB_SA_METHOD_GET_MULTI:
141 case IB_SA_METHOD_GET_MULTI_RESP:
142 return "Get Multi response";
143 case IB_SA_METHOD_GET_TRACE_TBL:
144 return "Get Trace Table response";
155 static void print_status_details(u16 status)
160 printk(" redirection required\n");
161 switch((status & 0x001C) >> 2) {
163 printk(" bad version\n");
166 printk(" method not supported\n");
169 printk(" method/attribute combo not supported\n");
172 printk(" invalid attribute/modifier value\n");
177 static char * get_sa_attr(__be16 attr)
180 case IB_SA_ATTR_CLASS_PORTINFO:
181 return "Class Port Info";
182 case IB_SA_ATTR_NOTICE:
184 case IB_SA_ATTR_INFORM_INFO:
185 return "Inform Info";
186 case IB_SA_ATTR_NODE_REC:
187 return "Node Record";
188 case IB_SA_ATTR_PORT_INFO_REC:
189 return "PortInfo Record";
190 case IB_SA_ATTR_SL2VL_REC:
191 return "SL to VL Record";
192 case IB_SA_ATTR_SWITCH_REC:
193 return "Switch Record";
194 case IB_SA_ATTR_LINEAR_FDB_REC:
195 return "Linear FDB Record";
196 case IB_SA_ATTR_RANDOM_FDB_REC:
197 return "Random FDB Record";
198 case IB_SA_ATTR_MCAST_FDB_REC:
199 return "Multicast FDB Record";
200 case IB_SA_ATTR_SM_INFO_REC:
201 return "SM Info Record";
202 case IB_SA_ATTR_LINK_REC:
203 return "Link Record";
204 case IB_SA_ATTR_GUID_INFO_REC:
205 return "Guid Info Record";
206 case IB_SA_ATTR_SERVICE_REC:
207 return "Service Record";
208 case IB_SA_ATTR_PARTITION_REC:
209 return "Partition Record";
210 case IB_SA_ATTR_PATH_REC:
211 return "Path Record";
212 case IB_SA_ATTR_VL_ARB_REC:
213 return "VL Arb Record";
214 case IB_SA_ATTR_MC_MEMBER_REC:
215 return "MC Member Record";
216 case IB_SA_ATTR_TRACE_REC:
217 return "Trace Record";
218 case IB_SA_ATTR_MULTI_PATH_REC:
219 return "Multi Path Record";
220 case IB_SA_ATTR_SERVICE_ASSOC_REC:
221 return "Service Assoc Record";
222 case IB_SA_ATTR_INFORM_INFO_REC:
223 return "Inform Info Record";
229 static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)
231 printk("MAD version....0x%01x\n", mad_hdr->base_version);
232 printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class,
233 get_class_name(mad_hdr->mgmt_class));
234 printk("Class version..0x%01x\n", mad_hdr->class_version);
235 printk("Method.........0x%01x (%s)\n", mad_hdr->method,
236 get_method_name(mad_hdr->mgmt_class, mad_hdr->method));
237 printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status));
239 print_status_details(be16_to_cpu(mad_hdr->status));
240 printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific));
241 printk("Trans ID.......0x%llx\n",
242 (unsigned long long)be64_to_cpu(mad_hdr->tid));
243 if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
244 printk("Attr ID........0x%02x (%s)\n",
245 be16_to_cpu(mad_hdr->attr_id),
246 get_sa_attr(be16_to_cpu(mad_hdr->attr_id)));
248 printk("Attr ID........0x%02x\n",
249 be16_to_cpu(mad_hdr->attr_id));
250 printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod));
253 static char * get_rmpp_type(u8 rmpp_type)
256 case IB_MGMT_RMPP_TYPE_DATA:
258 case IB_MGMT_RMPP_TYPE_ACK:
260 case IB_MGMT_RMPP_TYPE_STOP:
262 case IB_MGMT_RMPP_TYPE_ABORT:
269 static char * get_rmpp_flags(u8 rmpp_flags)
271 if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE)
272 if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST)
273 if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
274 return "Active - First & Last";
276 return "Active - First";
278 if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
279 return "Active - Last";
286 static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)
288 printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);
289 printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,
290 get_rmpp_type(rmpp_hdr->rmpp_type));
291 printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr));
292 printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr),
293 get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr)));
294 printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);
295 printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num));
296 switch (rmpp_hdr->rmpp_type) {
297 case IB_MGMT_RMPP_TYPE_DATA:
298 printk("Payload len....0x%04x\n",
299 be32_to_cpu(rmpp_hdr->paylen_newwin));
301 case IB_MGMT_RMPP_TYPE_ACK:
302 printk("New window.....0x%04x\n",
303 be32_to_cpu(rmpp_hdr->paylen_newwin));
306 printk("Data 2.........0x%04x\n",
307 be32_to_cpu(rmpp_hdr->paylen_newwin));
312 static char * get_smp_attr(__be16 attr)
315 case IB_SMP_ATTR_NOTICE:
317 case IB_SMP_ATTR_NODE_DESC:
318 return "node description";
319 case IB_SMP_ATTR_NODE_INFO:
321 case IB_SMP_ATTR_SWITCH_INFO:
322 return "switch info";
323 case IB_SMP_ATTR_GUID_INFO:
325 case IB_SMP_ATTR_PORT_INFO:
327 case IB_SMP_ATTR_PKEY_TABLE:
329 case IB_SMP_ATTR_SL_TO_VL_TABLE:
330 return "SL to VL table";
331 case IB_SMP_ATTR_VL_ARB_TABLE:
332 return "VL arbitration table";
333 case IB_SMP_ATTR_LINEAR_FORWARD_TABLE:
334 return "linear forwarding table";
335 case IB_SMP_ATTR_RANDOM_FORWARD_TABLE:
336 return "random forward table";
337 case IB_SMP_ATTR_MCAST_FORWARD_TABLE:
338 return "multicast forward table";
339 case IB_SMP_ATTR_SM_INFO:
341 case IB_SMP_ATTR_VENDOR_DIAG:
342 return "vendor diags";
343 case IB_SMP_ATTR_LED_INFO:
350 static void print_smp(struct ib_smp *smp)
354 printk("MAD version....0x%01x\n", smp->base_version);
355 printk("Class..........0x%01x (%s)\n", smp->mgmt_class,
356 get_class_name(smp->mgmt_class));
357 printk("Class version..0x%01x\n", smp->class_version);
358 printk("Method.........0x%01x (%s)\n", smp->method,
359 get_method_name(smp->mgmt_class, smp->method));
360 printk("Status.........0x%02x\n", be16_to_cpu(smp->status));
362 print_status_details(be16_to_cpu(smp->status));
363 printk("Hop pointer....0x%01x\n", smp->hop_ptr);
364 printk("Hop counter....0x%01x\n", smp->hop_cnt);
365 printk("Trans ID.......0x%llx\n",
366 (unsigned long long)be64_to_cpu(smp->tid));
367 printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id),
368 get_smp_attr(smp->attr_id));
369 printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod));
371 printk("Mkey...........0x%llx\n",
372 (unsigned long long)be64_to_cpu(smp->mkey));
373 printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid));
374 printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid));
377 for (i = 0; i < IB_SMP_DATA_SIZE; i++) {
379 printk("\nSMP Data.......");
380 printk("%01x ", smp->data[i]);
382 for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
384 printk("\nInitial path...");
385 printk("%01x ", smp->initial_path[i]);
387 for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
389 printk("\nReturn path....");
390 printk("%01x ", smp->return_path[i]);
396 static void snoop_smi_handler(struct ib_mad_agent *mad_agent,
397 struct ib_mad_send_buf *send_buf,
398 struct ib_mad_send_wc *mad_send_wc)
400 struct ib_mad_hdr *hdr = send_buf->mad;
402 if (!smp && hdr->mgmt_class != mgmt_class)
404 if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
407 printk("Madeye:sent SMP\n");
408 print_smp(send_buf->mad);
411 static void recv_smi_handler(struct ib_mad_agent *mad_agent,
412 struct ib_mad_recv_wc *mad_recv_wc)
414 if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)
416 if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
419 printk("Madeye:recv SMP\n");
420 print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);
423 static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)
425 if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
426 switch (mad_hdr->method) {
427 case IB_SA_METHOD_GET_TABLE:
428 case IB_SA_METHOD_GET_TABLE_RESP:
429 case IB_SA_METHOD_GET_MULTI_RESP:
434 } else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
435 (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
441 static void snoop_gsi_handler(struct ib_mad_agent *mad_agent,
442 struct ib_mad_send_buf *send_buf,
443 struct ib_mad_send_wc *mad_send_wc)
445 struct ib_mad_hdr *hdr = send_buf->mad;
447 if (!gmp && hdr->mgmt_class != mgmt_class)
449 if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
452 printk("Madeye:sent GMP\n");
455 if (is_rmpp_mad(hdr))
456 print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);
459 static void recv_gsi_handler(struct ib_mad_agent *mad_agent,
460 struct ib_mad_recv_wc *mad_recv_wc)
462 struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
463 struct ib_rmpp_mad *mad = NULL;
464 struct ib_sa_mad *sa_mad;
465 struct ib_vendor_mad *vendor_mad;
469 if (!gmp && hdr->mgmt_class != mgmt_class)
471 if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
474 printk("Madeye:recv GMP\n");
477 if (is_rmpp_mad(hdr)) {
478 mad = (struct ib_rmpp_mad *) hdr;
479 print_rmpp_hdr(&mad->rmpp_hdr);
483 if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
485 /* Display SA header */
486 if (is_rmpp_mad(hdr) &&
487 mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
489 sa_mad = (struct ib_sa_mad *)
490 &mad_recv_wc->recv_buf.mad;
491 mad_data = sa_mad->data;
493 if (is_rmpp_mad(hdr)) {
494 j = IB_MGMT_VENDOR_DATA;
496 vendor_mad = (struct ib_vendor_mad *)
497 &mad_recv_wc->recv_buf.mad;
498 printk("Vendor OUI......%01x %01x %01x\n",
502 mad_data = vendor_mad->data;
504 j = IB_MGMT_MAD_DATA;
505 mad_data = mad_recv_wc->recv_buf.mad->data;
508 for (i = 0; i < j; i++) {
510 printk("\nData...........");
511 printk("%01x ", mad_data[i]);
517 static void madeye_add_one(struct ib_device *device)
519 struct madeye_port *port;
523 if (device->node_type == RDMA_NODE_IB_SWITCH) {
528 e = device->phys_port_cnt;
531 port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);
535 reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS;
536 for (i = 0; i <= e - s; i++) {
537 port[i].smi_agent = ib_register_mad_snoop(device, i + s,
543 port[i].gsi_agent = ib_register_mad_snoop(device, i + s,
552 ib_set_client_data(device, &madeye_client, port);
555 static void madeye_remove_one(struct ib_device *device)
557 struct madeye_port *port;
560 port = (struct madeye_port *)
561 ib_get_client_data(device, &madeye_client);
565 if (device->node_type == RDMA_NODE_IB_SWITCH) {
570 e = device->phys_port_cnt;
573 for (i = 0; i <= e - s; i++) {
574 if (!IS_ERR(port[i].smi_agent))
575 ib_unregister_mad_agent(port[i].smi_agent);
576 if (!IS_ERR(port[i].gsi_agent))
577 ib_unregister_mad_agent(port[i].gsi_agent);
582 static int __init ib_madeye_init(void)
584 return ib_register_client(&madeye_client);
587 static void __exit ib_madeye_cleanup(void)
589 ib_unregister_client(&madeye_client);
592 module_init(ib_madeye_init);
593 module_exit(ib_madeye_cleanup);