Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/ofed/drivers/infiniband/util/madeye.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0
3
*
4
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
5
* Copyright (c) 2005, 2006 Voltaire Inc. All rights reserved.
6
*
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:
12
*
13
* Redistribution and use in source and binary forms, with or
14
* without modification, are permitted provided that the following
15
* conditions are met:
16
*
17
* - Redistributions of source code must retain the above
18
* copyright notice, this list of conditions and the following
19
* disclaimer.
20
*
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.
25
*
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
33
* SOFTWARE.
34
*
35
* $Id$
36
*/
37
38
#define LINUXKPI_PARAM_PREFIX ib_madeye_
39
40
#include <linux/module.h>
41
#include <linux/device.h>
42
#include <linux/err.h>
43
44
#include <rdma/ib_mad.h>
45
#include <rdma/ib_smi.h>
46
#include <rdma/ib_sa.h>
47
48
MODULE_AUTHOR("Sean Hefty");
49
MODULE_DESCRIPTION("InfiniBand MAD viewer");
50
MODULE_LICENSE("Dual BSD/GPL");
51
52
static void madeye_remove_one(struct ib_device *device);
53
static void madeye_add_one(struct ib_device *device);
54
55
static struct ib_client madeye_client = {
56
.name = "madeye",
57
.add = madeye_add_one,
58
.remove = madeye_remove_one
59
};
60
61
struct madeye_port {
62
struct ib_mad_agent *smi_agent;
63
struct ib_mad_agent *gsi_agent;
64
};
65
66
static int smp = 1;
67
static int gmp = 1;
68
static int mgmt_class = 0;
69
static int attr_id = 0;
70
static int data = 0;
71
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);
77
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)");
83
84
static char * get_class_name(u8 mgmt_class)
85
{
86
switch(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:
94
return "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:
102
return "SNMP";
103
default:
104
return "Unknown vendor/application";
105
}
106
}
107
108
static char * get_method_name(u8 mgmt_class, u8 method)
109
{
110
switch(method) {
111
case IB_MGMT_METHOD_GET:
112
return "Get";
113
case IB_MGMT_METHOD_SET:
114
return "Set";
115
case IB_MGMT_METHOD_GET_RESP:
116
return "Get response";
117
case IB_MGMT_METHOD_SEND:
118
return "Send";
119
case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:
120
return "Send response";
121
case IB_MGMT_METHOD_TRAP:
122
return "Trap";
123
case IB_MGMT_METHOD_REPORT:
124
return "Report";
125
case IB_MGMT_METHOD_REPORT_RESP:
126
return "Report response";
127
case IB_MGMT_METHOD_TRAP_REPRESS:
128
return "Trap repress";
129
default:
130
break;
131
}
132
133
switch (mgmt_class) {
134
case IB_MGMT_CLASS_SUBN_ADM:
135
switch (method) {
136
case IB_SA_METHOD_GET_TABLE:
137
return "Get table";
138
case IB_SA_METHOD_GET_TABLE_RESP:
139
return "Get table response";
140
case IB_SA_METHOD_DELETE:
141
return "Delete";
142
case IB_SA_METHOD_DELETE_RESP:
143
return "Delete response";
144
case IB_SA_METHOD_GET_MULTI:
145
return "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";
150
default:
151
break;
152
}
153
default:
154
break;
155
}
156
157
return "Unknown";
158
}
159
160
static void print_status_details(u16 status)
161
{
162
if (status & 0x0001)
163
printk(" busy\n");
164
if (status & 0x0002)
165
printk(" redirection required\n");
166
switch((status & 0x001C) >> 2) {
167
case 1:
168
printk(" bad version\n");
169
break;
170
case 2:
171
printk(" method not supported\n");
172
break;
173
case 3:
174
printk(" method/attribute combo not supported\n");
175
break;
176
case 7:
177
printk(" invalid attribute/modifier value\n");
178
break;
179
}
180
}
181
182
static char * get_sa_attr(__be16 attr)
183
{
184
switch(attr) {
185
case IB_SA_ATTR_CLASS_PORTINFO:
186
return "Class Port Info";
187
case IB_SA_ATTR_NOTICE:
188
return "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";
229
default:
230
return "";
231
}
232
}
233
234
static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)
235
{
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));
243
if (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)));
252
else
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));
256
}
257
258
static char * get_rmpp_type(u8 rmpp_type)
259
{
260
switch (rmpp_type) {
261
case IB_MGMT_RMPP_TYPE_DATA:
262
return "Data";
263
case IB_MGMT_RMPP_TYPE_ACK:
264
return "Ack";
265
case IB_MGMT_RMPP_TYPE_STOP:
266
return "Stop";
267
case IB_MGMT_RMPP_TYPE_ABORT:
268
return "Abort";
269
default:
270
return "Unknown";
271
}
272
}
273
274
static char * get_rmpp_flags(u8 rmpp_flags)
275
{
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";
280
else
281
return "Active - First";
282
else
283
if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)
284
return "Active - Last";
285
else
286
return "Active";
287
else
288
return "Inactive";
289
}
290
291
static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)
292
{
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));
305
break;
306
case IB_MGMT_RMPP_TYPE_ACK:
307
printk("New window.....0x%04x\n",
308
be32_to_cpu(rmpp_hdr->paylen_newwin));
309
break;
310
default:
311
printk("Data 2.........0x%04x\n",
312
be32_to_cpu(rmpp_hdr->paylen_newwin));
313
break;
314
}
315
}
316
317
static char * get_smp_attr(__be16 attr)
318
{
319
switch (attr) {
320
case IB_SMP_ATTR_NOTICE:
321
return "notice";
322
case IB_SMP_ATTR_NODE_DESC:
323
return "node description";
324
case IB_SMP_ATTR_NODE_INFO:
325
return "node info";
326
case IB_SMP_ATTR_SWITCH_INFO:
327
return "switch info";
328
case IB_SMP_ATTR_GUID_INFO:
329
return "GUID info";
330
case IB_SMP_ATTR_PORT_INFO:
331
return "port info";
332
case IB_SMP_ATTR_PKEY_TABLE:
333
return "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:
345
return "SM info";
346
case IB_SMP_ATTR_VENDOR_DIAG:
347
return "vendor diags";
348
case IB_SMP_ATTR_LED_INFO:
349
return "LED info";
350
default:
351
return "";
352
}
353
}
354
355
static void print_smp(struct ib_smp *smp)
356
{
357
int i;
358
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));
366
if (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));
375
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));
380
381
if (data) {
382
for (i = 0; i < IB_SMP_DATA_SIZE; i++) {
383
if (i % 16 == 0)
384
printk("\nSMP Data.......");
385
printk("%01x ", smp->data[i]);
386
}
387
for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
388
if (i % 16 == 0)
389
printk("\nInitial path...");
390
printk("%01x ", smp->initial_path[i]);
391
}
392
for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {
393
if (i % 16 == 0)
394
printk("\nReturn path....");
395
printk("%01x ", smp->return_path[i]);
396
}
397
}
398
printk("\n");
399
}
400
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)
404
{
405
struct ib_mad_hdr *hdr = send_buf->mad;
406
407
if (!smp && hdr->mgmt_class != mgmt_class)
408
return;
409
if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
410
return;
411
412
printk("Madeye:sent SMP\n");
413
print_smp(send_buf->mad);
414
}
415
416
static void recv_smi_handler(struct ib_mad_agent *mad_agent,
417
struct ib_mad_recv_wc *mad_recv_wc)
418
{
419
if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)
420
return;
421
if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
422
return;
423
424
printk("Madeye:recv SMP\n");
425
print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);
426
}
427
428
static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)
429
{
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:
435
return 1;
436
default:
437
break;
438
}
439
} else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&
440
(mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))
441
return 1;
442
443
return 0;
444
}
445
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)
449
{
450
struct ib_mad_hdr *hdr = send_buf->mad;
451
452
if (!gmp && hdr->mgmt_class != mgmt_class)
453
return;
454
if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)
455
return;
456
457
printk("Madeye:sent GMP\n");
458
print_mad_hdr(hdr);
459
460
if (is_rmpp_mad(hdr))
461
print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);
462
}
463
464
static void recv_gsi_handler(struct ib_mad_agent *mad_agent,
465
struct ib_mad_recv_wc *mad_recv_wc)
466
{
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;
471
u8 *mad_data;
472
int i, j;
473
474
if (!gmp && hdr->mgmt_class != mgmt_class)
475
return;
476
if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)
477
return;
478
479
printk("Madeye:recv GMP\n");
480
print_mad_hdr(hdr);
481
482
if (is_rmpp_mad(hdr)) {
483
mad = (struct ib_rmpp_mad *) hdr;
484
print_rmpp_hdr(&mad->rmpp_hdr);
485
}
486
487
if (data) {
488
if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {
489
j = IB_MGMT_SA_DATA;
490
/* Display SA header */
491
if (is_rmpp_mad(hdr) &&
492
mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)
493
return;
494
sa_mad = (struct ib_sa_mad *)
495
&mad_recv_wc->recv_buf.mad;
496
mad_data = sa_mad->data;
497
} else {
498
if (is_rmpp_mad(hdr)) {
499
j = IB_MGMT_VENDOR_DATA;
500
/* Display OUI */
501
vendor_mad = (struct ib_vendor_mad *)
502
&mad_recv_wc->recv_buf.mad;
503
printk("Vendor OUI......%01x %01x %01x\n",
504
vendor_mad->oui[0],
505
vendor_mad->oui[1],
506
vendor_mad->oui[2]);
507
mad_data = vendor_mad->data;
508
} else {
509
j = IB_MGMT_MAD_DATA;
510
mad_data = mad_recv_wc->recv_buf.mad->data;
511
}
512
}
513
for (i = 0; i < j; i++) {
514
if (i % 16 == 0)
515
printk("\nData...........");
516
printk("%01x ", mad_data[i]);
517
}
518
printk("\n");
519
}
520
}
521
522
static void madeye_add_one(struct ib_device *device)
523
{
524
struct madeye_port *port;
525
int reg_flags;
526
u8 i, s, e;
527
528
if (device->node_type == RDMA_NODE_IB_SWITCH) {
529
s = 0;
530
e = 0;
531
} else {
532
s = 1;
533
e = device->phys_port_cnt;
534
}
535
536
port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);
537
if (!port)
538
goto out;
539
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,
543
IB_QPT_SMI,
544
reg_flags,
545
snoop_smi_handler,
546
recv_smi_handler,
547
&port[i]);
548
port[i].gsi_agent = ib_register_mad_snoop(device, i + s,
549
IB_QPT_GSI,
550
reg_flags,
551
snoop_gsi_handler,
552
recv_gsi_handler,
553
&port[i]);
554
}
555
556
out:
557
ib_set_client_data(device, &madeye_client, port);
558
}
559
560
static void madeye_remove_one(struct ib_device *device)
561
{
562
struct madeye_port *port;
563
int i, s, e;
564
565
port = (struct madeye_port *)
566
ib_get_client_data(device, &madeye_client);
567
if (!port)
568
return;
569
570
if (device->node_type == RDMA_NODE_IB_SWITCH) {
571
s = 0;
572
e = 0;
573
} else {
574
s = 1;
575
e = device->phys_port_cnt;
576
}
577
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);
583
}
584
kfree(port);
585
}
586
587
static int __init ib_madeye_init(void)
588
{
589
return ib_register_client(&madeye_client);
590
}
591
592
static void __exit ib_madeye_cleanup(void)
593
{
594
ib_unregister_client(&madeye_client);
595
}
596
597
module_init_order(ib_madeye_init, SI_ORDER_THIRD);
598
module_exit_order(ib_madeye_cleanup, SI_ORDER_THIRD);
599
600