2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
4 * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
5 * Copyright (c) 2005, 2006 Voltaire Inc. All rights reserved.
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directorY of this source tree, or the
11 * OpenIB.org BSD license below:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #define LINUXKPI_PARAM_PREFIX ib_madeye_
40 #include <linux/module.h>
41 #include <linux/device.h>
42 #include <linux/err.h>
44 #include <rdma/ib_mad.h>
45 #include <rdma/ib_smi.h>
46 #include <rdma/ib_sa.h>
48 MODULE_AUTHOR("Sean Hefty");
49 MODULE_DESCRIPTION("InfiniBand MAD viewer");
50 MODULE_LICENSE("Dual BSD/GPL");
52 static void madeye_remove_one(struct ib_device *device);
53 static void madeye_add_one(struct ib_device *device);
55 static struct ib_client madeye_client = {
57 .add = madeye_add_one,
58 .remove = madeye_remove_one
62 struct ib_mad_agent *smi_agent;
63 struct ib_mad_agent *gsi_agent;
68 static int mgmt_class = 0;
69 static int attr_id = 0;
72 module_param(smp, int, 0444);
73 module_param(gmp, int, 0444);
74 module_param(mgmt_class, int, 0444);
75 module_param(attr_id, int, 0444);
76 module_param(data, int, 0444);
78 MODULE_PARM_DESC(smp, "Display all SMPs (default=1)");
79 MODULE_PARM_DESC(gmp, "Display all GMPs (default=1)");
80 MODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)");
81 MODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)");
82 MODULE_PARM_DESC(data, "Display data area of MADs (default=0)");
84 static char * get_class_name(u8 mgmt_class)
87 case IB_MGMT_CLASS_SUBN_LID_ROUTED:
88 return "LID routed SMP";
89 case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
90 return "Directed route SMP";
91 case IB_MGMT_CLASS_SUBN_ADM:
92 return "Subnet admin.";
93 case IB_MGMT_CLASS_PERF_MGMT:
95 case IB_MGMT_CLASS_BM:
96 return "Baseboard mgmt.";
97 case IB_MGMT_CLASS_DEVICE_MGMT:
98 return "Device mgmt.";
99 case IB_MGMT_CLASS_CM:
100 return "Comm. mgmt.";
101 case IB_MGMT_CLASS_SNMP:
104 return "Unknown vendor/application";
108 static char * get_method_name(u8 mgmt_class, u8 method)
111 case IB_MGMT_METHOD_GET:
113 case IB_MGMT_METHOD_SET:
115 case IB_MGMT_METHOD_GET_RESP:
116 return "Get response";
117 case IB_MGMT_METHOD_SEND:
119 case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:
120 return "Send response";
121 case IB_MGMT_METHOD_TRAP:
123 case IB_MGMT_METHOD_REPORT:
125 case IB_MGMT_METHOD_REPORT_RESP:
126 return "Report response";
127 case IB_MGMT_METHOD_TRAP_REPRESS:
128 return "Trap repress";
133 switch (mgmt_class) {
134 case IB_MGMT_CLASS_SUBN_ADM:
136 case IB_SA_METHOD_GET_TABLE:
138 case IB_SA_METHOD_GET_TABLE_RESP:
139 return "Get table response";
140 case IB_SA_METHOD_DELETE:
142 case IB_SA_METHOD_DELETE_RESP:
143 return "Delete response";
144 case IB_SA_METHOD_GET_MULTI:
146 case IB_SA_METHOD_GET_MULTI_RESP:
147 return "Get Multi response";
148 case IB_SA_METHOD_GET_TRACE_TBL:
149 return "Get Trace Table response";
160 static void print_status_details(u16 status)
165 printk(" redirection required\n");
166 switch((status & 0x001C) >> 2) {
168 printk(" bad version\n");
171 printk(" method not supported\n");
174 printk(" method/attribute combo not supported\n");
177 printk(" invalid attribute/modifier value\n");
182 static char * get_sa_attr(__be16 attr)
185 case IB_SA_ATTR_CLASS_PORTINFO:
186 return "Class Port Info";
187 case IB_SA_ATTR_NOTICE:
189 case IB_SA_ATTR_INFORM_INFO:
190 return "Inform Info";
191 case IB_SA_ATTR_NODE_REC:
192 return "Node Record";
193 case IB_SA_ATTR_PORT_INFO_REC:
194 return "PortInfo Record";
195 case IB_SA_ATTR_SL2VL_REC:
196 return "SL to VL Record";
197 case IB_SA_ATTR_SWITCH_REC:
198 return "Switch Record";
199 case IB_SA_ATTR_LINEAR_FDB_REC:
200 return "Linear FDB Record";
201 case IB_SA_ATTR_RANDOM_FDB_REC:
202 return "Random FDB Record";
203 case IB_SA_ATTR_MCAST_FDB_REC:
204 return "Multicast FDB Record";
205 case IB_SA_ATTR_SM_INFO_REC:
206 return "SM Info Record";
207 case IB_SA_ATTR_LINK_REC:
208 return "Link Record";
209 case IB_SA_ATTR_GUID_INFO_REC:
210 return "Guid Info Record";
211 case IB_SA_ATTR_SERVICE_REC:
212 return "Service Record";
213 case IB_SA_ATTR_PARTITION_REC:
214 return "Partition Record";
215 case IB_SA_ATTR_PATH_REC:
216 return "Path Record";
217 case IB_SA_ATTR_VL_ARB_REC:
218 return "VL Arb Record";
219 case IB_SA_ATTR_MC_MEMBER_REC:
220 return "MC Member Record";
221 case IB_SA_ATTR_TRACE_REC:
222 return "Trace Record";
223 case IB_SA_ATTR_MULTI_PATH_REC:
224 return "Multi Path Record";
225 case IB_SA_ATTR_SERVICE_ASSOC_REC:
226 return "Service Assoc Record";
227 case IB_SA_ATTR_INFORM_INFO_REC:
228 return "Inform Info Record";
234 static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)
236 printk("MAD version....0x%01x\n", mad_hdr->base_version);
237 printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class,
238 get_class_name(mad_hdr->mgmt_class));
239 printk("Class version..0x%01x\n", mad_hdr->class_version);
240 printk("Method.........0x%01x (%s)\n", mad_hdr->method,
241 get_method_name(mad_hdr->mgmt_class, mad_hdr->method));
242 printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status));
244 print_status_details(be16_to_cpu(mad_hdr->status));
245 printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific));
246 printk("Trans ID.......0x%llx\n",
247 (unsigned long long)be64_to_cpu(mad_hdr->tid));
248 if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM)
249 printk("Attr ID........0x%02x (%s)\n",
250 be16_to_cpu(mad_hdr->attr_id),
251 get_sa_attr(be16_to_cpu(mad_hdr->attr_id)));
253 printk("Attr ID........0x%02x\n",
254 be16_to_cpu(mad_hdr->attr_id));
255 printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod));
258 static char * get_rmpp_type(u8 rmpp_type)
261 case IB_MGMT_RMPP_TYPE_DATA:
263 case IB_MGMT_RMPP_TYPE_ACK:
265 case IB_MGMT_RMPP_TYPE_STOP:
267 case IB_MGMT_RMPP_TYPE_ABORT:
274 static char * get_rmpp_flags(u8 rmpp_flags)
276 if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE)
277 if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST)
278 if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
279 return "Active - First & Last";
281 return "Active - First";
283 if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
284 return "Active - Last";
291 static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)
293 printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);
294 printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,
295 get_rmpp_type(rmpp_hdr->rmpp_type));
296 printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr));
297 printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr),
298 get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr)));
299 printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);
300 printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num));
301 switch (rmpp_hdr->rmpp_type) {
302 case IB_MGMT_RMPP_TYPE_DATA:
303 printk("Payload len....0x%04x\n",
304 be32_to_cpu(rmpp_hdr->paylen_newwin));
306 case IB_MGMT_RMPP_TYPE_ACK:
307 printk("New window.....0x%04x\n",
308 be32_to_cpu(rmpp_hdr->paylen_newwin));
311 printk("Data 2.........0x%04x\n",
312 be32_to_cpu(rmpp_hdr->paylen_newwin));
317 static char * get_smp_attr(__be16 attr)
320 case IB_SMP_ATTR_NOTICE:
322 case IB_SMP_ATTR_NODE_DESC:
323 return "node description";
324 case IB_SMP_ATTR_NODE_INFO:
326 case IB_SMP_ATTR_SWITCH_INFO:
327 return "switch info";
328 case IB_SMP_ATTR_GUID_INFO:
330 case IB_SMP_ATTR_PORT_INFO:
332 case IB_SMP_ATTR_PKEY_TABLE:
334 case IB_SMP_ATTR_SL_TO_VL_TABLE:
335 return "SL to VL table";
336 case IB_SMP_ATTR_VL_ARB_TABLE:
337 return "VL arbitration table";
338 case IB_SMP_ATTR_LINEAR_FORWARD_TABLE:
339 return "linear forwarding table";
340 case IB_SMP_ATTR_RANDOM_FORWARD_TABLE:
341 return "random forward table";
342 case IB_SMP_ATTR_MCAST_FORWARD_TABLE:
343 return "multicast forward table";
344 case IB_SMP_ATTR_SM_INFO:
346 case IB_SMP_ATTR_VENDOR_DIAG:
347 return "vendor diags";
348 case IB_SMP_ATTR_LED_INFO:
355 static void print_smp(struct ib_smp *smp)
359 printk("MAD version....0x%01x\n", smp->base_version);
360 printk("Class..........0x%01x (%s)\n", smp->mgmt_class,
361 get_class_name(smp->mgmt_class));
362 printk("Class version..0x%01x\n", smp->class_version);
363 printk("Method.........0x%01x (%s)\n", smp->method,
364 get_method_name(smp->mgmt_class, smp->method));
365 printk("Status.........0x%02x\n", be16_to_cpu(smp->status));
367 print_status_details(be16_to_cpu(smp->status));
368 printk("Hop pointer....0x%01x\n", smp->hop_ptr);
369 printk("Hop counter....0x%01x\n", smp->hop_cnt);
370 printk("Trans ID.......0x%llx\n",
371 (unsigned long long)be64_to_cpu(smp->tid));
372 printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id),
373 get_smp_attr(smp->attr_id));
374 printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod));
376 printk("Mkey...........0x%llx\n",
377 (unsigned long long)be64_to_cpu(smp->mkey));
378 printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid));
379 printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid));
382 for (i = 0; i < IB_SMP_DATA_SIZE; i++) {
384 printk("\nSMP Data.......");
385 printk("%01x ", smp->data[i]);
387 for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
389 printk("\nInitial path...");
390 printk("%01x ", smp->initial_path[i]);
392 for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
394 printk("\nReturn path....");
395 printk("%01x ", smp->return_path[i]);
401 static void snoop_smi_handler(struct ib_mad_agent *mad_agent,
402 struct ib_mad_send_buf *send_buf,
403 struct ib_mad_send_wc *mad_send_wc)
405 struct ib_mad_hdr *hdr = send_buf->mad;
407 if (!smp && hdr->mgmt_class != mgmt_class)
409 if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
412 printk("Madeye:sent SMP\n");
413 print_smp(send_buf->mad);
416 static void recv_smi_handler(struct ib_mad_agent *mad_agent,
417 struct ib_mad_recv_wc *mad_recv_wc)
419 if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)
421 if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
424 printk("Madeye:recv SMP\n");
425 print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);
428 static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)
430 if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
431 switch (mad_hdr->method) {
432 case IB_SA_METHOD_GET_TABLE:
433 case IB_SA_METHOD_GET_TABLE_RESP:
434 case IB_SA_METHOD_GET_MULTI_RESP:
439 } else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
440 (mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
446 static void snoop_gsi_handler(struct ib_mad_agent *mad_agent,
447 struct ib_mad_send_buf *send_buf,
448 struct ib_mad_send_wc *mad_send_wc)
450 struct ib_mad_hdr *hdr = send_buf->mad;
452 if (!gmp && hdr->mgmt_class != mgmt_class)
454 if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
457 printk("Madeye:sent GMP\n");
460 if (is_rmpp_mad(hdr))
461 print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);
464 static void recv_gsi_handler(struct ib_mad_agent *mad_agent,
465 struct ib_mad_recv_wc *mad_recv_wc)
467 struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
468 struct ib_rmpp_mad *mad = NULL;
469 struct ib_sa_mad *sa_mad;
470 struct ib_vendor_mad *vendor_mad;
474 if (!gmp && hdr->mgmt_class != mgmt_class)
476 if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
479 printk("Madeye:recv GMP\n");
482 if (is_rmpp_mad(hdr)) {
483 mad = (struct ib_rmpp_mad *) hdr;
484 print_rmpp_hdr(&mad->rmpp_hdr);
488 if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
490 /* Display SA header */
491 if (is_rmpp_mad(hdr) &&
492 mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
494 sa_mad = (struct ib_sa_mad *)
495 &mad_recv_wc->recv_buf.mad;
496 mad_data = sa_mad->data;
498 if (is_rmpp_mad(hdr)) {
499 j = IB_MGMT_VENDOR_DATA;
501 vendor_mad = (struct ib_vendor_mad *)
502 &mad_recv_wc->recv_buf.mad;
503 printk("Vendor OUI......%01x %01x %01x\n",
507 mad_data = vendor_mad->data;
509 j = IB_MGMT_MAD_DATA;
510 mad_data = mad_recv_wc->recv_buf.mad->data;
513 for (i = 0; i < j; i++) {
515 printk("\nData...........");
516 printk("%01x ", mad_data[i]);
522 static void madeye_add_one(struct ib_device *device)
524 struct madeye_port *port;
528 if (device->node_type == RDMA_NODE_IB_SWITCH) {
533 e = device->phys_port_cnt;
536 port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);
540 reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS;
541 for (i = 0; i <= e - s; i++) {
542 port[i].smi_agent = ib_register_mad_snoop(device, i + s,
548 port[i].gsi_agent = ib_register_mad_snoop(device, i + s,
557 ib_set_client_data(device, &madeye_client, port);
560 static void madeye_remove_one(struct ib_device *device)
562 struct madeye_port *port;
565 port = (struct madeye_port *)
566 ib_get_client_data(device, &madeye_client);
570 if (device->node_type == RDMA_NODE_IB_SWITCH) {
575 e = device->phys_port_cnt;
578 for (i = 0; i <= e - s; i++) {
579 if (!IS_ERR(port[i].smi_agent))
580 ib_unregister_mad_agent(port[i].smi_agent);
581 if (!IS_ERR(port[i].gsi_agent))
582 ib_unregister_mad_agent(port[i].gsi_agent);
587 static int __init ib_madeye_init(void)
589 return ib_register_client(&madeye_client);
592 static void __exit ib_madeye_cleanup(void)
594 ib_unregister_client(&madeye_client);
597 module_init(ib_madeye_init);
598 module_exit(ib_madeye_cleanup);