Path: blob/main/sys/ofed/drivers/infiniband/util/madeye.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.02*3* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.4* Copyright (c) 2005, 2006 Voltaire Inc. All rights reserved.5*6* This software is available to you under a choice of one of two7* licenses. You may choose to be licensed under the terms of the GNU8* General Public License (GPL) Version 2, available from the file9* COPYING in the main directorY of this source tree, or the10* OpenIB.org BSD license below:11*12* Redistribution and use in source and binary forms, with or13* without modification, are permitted provided that the following14* conditions are met:15*16* - Redistributions of source code must retain the above17* copyright notice, this list of conditions and the following18* disclaimer.19*20* - Redistributions in binary form must reproduce the above21* copyright notice, this list of conditions and the following22* disclaimer in the documentation and/or other materials23* provided with the distribution.24*25* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32* SOFTWARE.33*34* $Id$35*/3637#define LINUXKPI_PARAM_PREFIX ib_madeye_3839#include <linux/module.h>40#include <linux/device.h>41#include <linux/err.h>4243#include <rdma/ib_mad.h>44#include <rdma/ib_smi.h>45#include <rdma/ib_sa.h>4647MODULE_AUTHOR("Sean Hefty");48MODULE_DESCRIPTION("InfiniBand MAD viewer");49MODULE_LICENSE("Dual BSD/GPL");5051static void madeye_remove_one(struct ib_device *device);52static void madeye_add_one(struct ib_device *device);5354static struct ib_client madeye_client = {55.name = "madeye",56.add = madeye_add_one,57.remove = madeye_remove_one58};5960struct madeye_port {61struct ib_mad_agent *smi_agent;62struct ib_mad_agent *gsi_agent;63};6465static int smp = 1;66static int gmp = 1;67static int mgmt_class = 0;68static int attr_id = 0;69static int data = 0;7071module_param(smp, int, 0444);72module_param(gmp, int, 0444);73module_param(mgmt_class, int, 0444);74module_param(attr_id, int, 0444);75module_param(data, int, 0444);7677MODULE_PARM_DESC(smp, "Display all SMPs (default=1)");78MODULE_PARM_DESC(gmp, "Display all GMPs (default=1)");79MODULE_PARM_DESC(mgmt_class, "Display all MADs of specified class (default=0)");80MODULE_PARM_DESC(attr_id, "Display add MADs of specified attribute ID (default=0)");81MODULE_PARM_DESC(data, "Display data area of MADs (default=0)");8283static char * get_class_name(u8 mgmt_class)84{85switch(mgmt_class) {86case IB_MGMT_CLASS_SUBN_LID_ROUTED:87return "LID routed SMP";88case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:89return "Directed route SMP";90case IB_MGMT_CLASS_SUBN_ADM:91return "Subnet admin.";92case IB_MGMT_CLASS_PERF_MGMT:93return "Perf. mgmt.";94case IB_MGMT_CLASS_BM:95return "Baseboard mgmt.";96case IB_MGMT_CLASS_DEVICE_MGMT:97return "Device mgmt.";98case IB_MGMT_CLASS_CM:99return "Comm. mgmt.";100case IB_MGMT_CLASS_SNMP:101return "SNMP";102default:103return "Unknown vendor/application";104}105}106107static char * get_method_name(u8 mgmt_class, u8 method)108{109switch(method) {110case IB_MGMT_METHOD_GET:111return "Get";112case IB_MGMT_METHOD_SET:113return "Set";114case IB_MGMT_METHOD_GET_RESP:115return "Get response";116case IB_MGMT_METHOD_SEND:117return "Send";118case IB_MGMT_METHOD_SEND | IB_MGMT_METHOD_RESP:119return "Send response";120case IB_MGMT_METHOD_TRAP:121return "Trap";122case IB_MGMT_METHOD_REPORT:123return "Report";124case IB_MGMT_METHOD_REPORT_RESP:125return "Report response";126case IB_MGMT_METHOD_TRAP_REPRESS:127return "Trap repress";128default:129break;130}131132switch (mgmt_class) {133case IB_MGMT_CLASS_SUBN_ADM:134switch (method) {135case IB_SA_METHOD_GET_TABLE:136return "Get table";137case IB_SA_METHOD_GET_TABLE_RESP:138return "Get table response";139case IB_SA_METHOD_DELETE:140return "Delete";141case IB_SA_METHOD_DELETE_RESP:142return "Delete response";143case IB_SA_METHOD_GET_MULTI:144return "Get Multi";145case IB_SA_METHOD_GET_MULTI_RESP:146return "Get Multi response";147case IB_SA_METHOD_GET_TRACE_TBL:148return "Get Trace Table response";149default:150break;151}152default:153break;154}155156return "Unknown";157}158159static void print_status_details(u16 status)160{161if (status & 0x0001)162printk(" busy\n");163if (status & 0x0002)164printk(" redirection required\n");165switch((status & 0x001C) >> 2) {166case 1:167printk(" bad version\n");168break;169case 2:170printk(" method not supported\n");171break;172case 3:173printk(" method/attribute combo not supported\n");174break;175case 7:176printk(" invalid attribute/modifier value\n");177break;178}179}180181static char * get_sa_attr(__be16 attr)182{183switch(attr) {184case IB_SA_ATTR_CLASS_PORTINFO:185return "Class Port Info";186case IB_SA_ATTR_NOTICE:187return "Notice";188case IB_SA_ATTR_INFORM_INFO:189return "Inform Info";190case IB_SA_ATTR_NODE_REC:191return "Node Record";192case IB_SA_ATTR_PORT_INFO_REC:193return "PortInfo Record";194case IB_SA_ATTR_SL2VL_REC:195return "SL to VL Record";196case IB_SA_ATTR_SWITCH_REC:197return "Switch Record";198case IB_SA_ATTR_LINEAR_FDB_REC:199return "Linear FDB Record";200case IB_SA_ATTR_RANDOM_FDB_REC:201return "Random FDB Record";202case IB_SA_ATTR_MCAST_FDB_REC:203return "Multicast FDB Record";204case IB_SA_ATTR_SM_INFO_REC:205return "SM Info Record";206case IB_SA_ATTR_LINK_REC:207return "Link Record";208case IB_SA_ATTR_GUID_INFO_REC:209return "Guid Info Record";210case IB_SA_ATTR_SERVICE_REC:211return "Service Record";212case IB_SA_ATTR_PARTITION_REC:213return "Partition Record";214case IB_SA_ATTR_PATH_REC:215return "Path Record";216case IB_SA_ATTR_VL_ARB_REC:217return "VL Arb Record";218case IB_SA_ATTR_MC_MEMBER_REC:219return "MC Member Record";220case IB_SA_ATTR_TRACE_REC:221return "Trace Record";222case IB_SA_ATTR_MULTI_PATH_REC:223return "Multi Path Record";224case IB_SA_ATTR_SERVICE_ASSOC_REC:225return "Service Assoc Record";226case IB_SA_ATTR_INFORM_INFO_REC:227return "Inform Info Record";228default:229return "";230}231}232233static void print_mad_hdr(struct ib_mad_hdr *mad_hdr)234{235printk("MAD version....0x%01x\n", mad_hdr->base_version);236printk("Class..........0x%01x (%s)\n", mad_hdr->mgmt_class,237get_class_name(mad_hdr->mgmt_class));238printk("Class version..0x%01x\n", mad_hdr->class_version);239printk("Method.........0x%01x (%s)\n", mad_hdr->method,240get_method_name(mad_hdr->mgmt_class, mad_hdr->method));241printk("Status.........0x%02x\n", be16_to_cpu(mad_hdr->status));242if (mad_hdr->status)243print_status_details(be16_to_cpu(mad_hdr->status));244printk("Class specific.0x%02x\n", be16_to_cpu(mad_hdr->class_specific));245printk("Trans ID.......0x%llx\n",246(unsigned long long)be64_to_cpu(mad_hdr->tid));247if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM)248printk("Attr ID........0x%02x (%s)\n",249be16_to_cpu(mad_hdr->attr_id),250get_sa_attr(be16_to_cpu(mad_hdr->attr_id)));251else252printk("Attr ID........0x%02x\n",253be16_to_cpu(mad_hdr->attr_id));254printk("Attr modifier..0x%04x\n", be32_to_cpu(mad_hdr->attr_mod));255}256257static char * get_rmpp_type(u8 rmpp_type)258{259switch (rmpp_type) {260case IB_MGMT_RMPP_TYPE_DATA:261return "Data";262case IB_MGMT_RMPP_TYPE_ACK:263return "Ack";264case IB_MGMT_RMPP_TYPE_STOP:265return "Stop";266case IB_MGMT_RMPP_TYPE_ABORT:267return "Abort";268default:269return "Unknown";270}271}272273static char * get_rmpp_flags(u8 rmpp_flags)274{275if (rmpp_flags & IB_MGMT_RMPP_FLAG_ACTIVE)276if (rmpp_flags & IB_MGMT_RMPP_FLAG_FIRST)277if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)278return "Active - First & Last";279else280return "Active - First";281else282if (rmpp_flags & IB_MGMT_RMPP_FLAG_LAST)283return "Active - Last";284else285return "Active";286else287return "Inactive";288}289290static void print_rmpp_hdr(struct ib_rmpp_hdr *rmpp_hdr)291{292printk("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);293printk("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,294get_rmpp_type(rmpp_hdr->rmpp_type));295printk("RMPP RRespTime.0x%01x\n", ib_get_rmpp_resptime(rmpp_hdr));296printk("RMPP flags.....0x%01x (%s)\n", ib_get_rmpp_flags(rmpp_hdr),297get_rmpp_flags(ib_get_rmpp_flags(rmpp_hdr)));298printk("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);299printk("Seg number.....0x%04x\n", be32_to_cpu(rmpp_hdr->seg_num));300switch (rmpp_hdr->rmpp_type) {301case IB_MGMT_RMPP_TYPE_DATA:302printk("Payload len....0x%04x\n",303be32_to_cpu(rmpp_hdr->paylen_newwin));304break;305case IB_MGMT_RMPP_TYPE_ACK:306printk("New window.....0x%04x\n",307be32_to_cpu(rmpp_hdr->paylen_newwin));308break;309default:310printk("Data 2.........0x%04x\n",311be32_to_cpu(rmpp_hdr->paylen_newwin));312break;313}314}315316static char * get_smp_attr(__be16 attr)317{318switch (attr) {319case IB_SMP_ATTR_NOTICE:320return "notice";321case IB_SMP_ATTR_NODE_DESC:322return "node description";323case IB_SMP_ATTR_NODE_INFO:324return "node info";325case IB_SMP_ATTR_SWITCH_INFO:326return "switch info";327case IB_SMP_ATTR_GUID_INFO:328return "GUID info";329case IB_SMP_ATTR_PORT_INFO:330return "port info";331case IB_SMP_ATTR_PKEY_TABLE:332return "pkey table";333case IB_SMP_ATTR_SL_TO_VL_TABLE:334return "SL to VL table";335case IB_SMP_ATTR_VL_ARB_TABLE:336return "VL arbitration table";337case IB_SMP_ATTR_LINEAR_FORWARD_TABLE:338return "linear forwarding table";339case IB_SMP_ATTR_RANDOM_FORWARD_TABLE:340return "random forward table";341case IB_SMP_ATTR_MCAST_FORWARD_TABLE:342return "multicast forward table";343case IB_SMP_ATTR_SM_INFO:344return "SM info";345case IB_SMP_ATTR_VENDOR_DIAG:346return "vendor diags";347case IB_SMP_ATTR_LED_INFO:348return "LED info";349default:350return "";351}352}353354static void print_smp(struct ib_smp *smp)355{356int i;357358printk("MAD version....0x%01x\n", smp->base_version);359printk("Class..........0x%01x (%s)\n", smp->mgmt_class,360get_class_name(smp->mgmt_class));361printk("Class version..0x%01x\n", smp->class_version);362printk("Method.........0x%01x (%s)\n", smp->method,363get_method_name(smp->mgmt_class, smp->method));364printk("Status.........0x%02x\n", be16_to_cpu(smp->status));365if (smp->status)366print_status_details(be16_to_cpu(smp->status));367printk("Hop pointer....0x%01x\n", smp->hop_ptr);368printk("Hop counter....0x%01x\n", smp->hop_cnt);369printk("Trans ID.......0x%llx\n",370(unsigned long long)be64_to_cpu(smp->tid));371printk("Attr ID........0x%02x (%s)\n", be16_to_cpu(smp->attr_id),372get_smp_attr(smp->attr_id));373printk("Attr modifier..0x%04x\n", be32_to_cpu(smp->attr_mod));374375printk("Mkey...........0x%llx\n",376(unsigned long long)be64_to_cpu(smp->mkey));377printk("DR SLID........0x%02x\n", be16_to_cpu(smp->dr_slid));378printk("DR DLID........0x%02x", be16_to_cpu(smp->dr_dlid));379380if (data) {381for (i = 0; i < IB_SMP_DATA_SIZE; i++) {382if (i % 16 == 0)383printk("\nSMP Data.......");384printk("%01x ", smp->data[i]);385}386for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {387if (i % 16 == 0)388printk("\nInitial path...");389printk("%01x ", smp->initial_path[i]);390}391for (i = 0; i < IB_SMP_MAX_PATH_HOPS; i++) {392if (i % 16 == 0)393printk("\nReturn path....");394printk("%01x ", smp->return_path[i]);395}396}397printk("\n");398}399400static void snoop_smi_handler(struct ib_mad_agent *mad_agent,401struct ib_mad_send_buf *send_buf,402struct ib_mad_send_wc *mad_send_wc)403{404struct ib_mad_hdr *hdr = send_buf->mad;405406if (!smp && hdr->mgmt_class != mgmt_class)407return;408if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)409return;410411printk("Madeye:sent SMP\n");412print_smp(send_buf->mad);413}414415static void recv_smi_handler(struct ib_mad_agent *mad_agent,416struct ib_mad_recv_wc *mad_recv_wc)417{418if (!smp && mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class != mgmt_class)419return;420if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)421return;422423printk("Madeye:recv SMP\n");424print_smp((struct ib_smp *)&mad_recv_wc->recv_buf.mad->mad_hdr);425}426427static int is_rmpp_mad(struct ib_mad_hdr *mad_hdr)428{429if (mad_hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {430switch (mad_hdr->method) {431case IB_SA_METHOD_GET_TABLE:432case IB_SA_METHOD_GET_TABLE_RESP:433case IB_SA_METHOD_GET_MULTI_RESP:434return 1;435default:436break;437}438} else if ((mad_hdr->mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) &&439(mad_hdr->mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END))440return 1;441442return 0;443}444445static void snoop_gsi_handler(struct ib_mad_agent *mad_agent,446struct ib_mad_send_buf *send_buf,447struct ib_mad_send_wc *mad_send_wc)448{449struct ib_mad_hdr *hdr = send_buf->mad;450451if (!gmp && hdr->mgmt_class != mgmt_class)452return;453if (attr_id && be16_to_cpu(hdr->attr_id) != attr_id)454return;455456printk("Madeye:sent GMP\n");457print_mad_hdr(hdr);458459if (is_rmpp_mad(hdr))460print_rmpp_hdr(&((struct ib_rmpp_mad *) hdr)->rmpp_hdr);461}462463static void recv_gsi_handler(struct ib_mad_agent *mad_agent,464struct ib_mad_recv_wc *mad_recv_wc)465{466struct ib_mad_hdr *hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;467struct ib_rmpp_mad *mad = NULL;468struct ib_sa_mad *sa_mad;469struct ib_vendor_mad *vendor_mad;470u8 *mad_data;471int i, j;472473if (!gmp && hdr->mgmt_class != mgmt_class)474return;475if (attr_id && be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) != attr_id)476return;477478printk("Madeye:recv GMP\n");479print_mad_hdr(hdr);480481if (is_rmpp_mad(hdr)) {482mad = (struct ib_rmpp_mad *) hdr;483print_rmpp_hdr(&mad->rmpp_hdr);484}485486if (data) {487if (hdr->mgmt_class == IB_MGMT_CLASS_SUBN_ADM) {488j = IB_MGMT_SA_DATA;489/* Display SA header */490if (is_rmpp_mad(hdr) &&491mad->rmpp_hdr.rmpp_type != IB_MGMT_RMPP_TYPE_DATA)492return;493sa_mad = (struct ib_sa_mad *)494&mad_recv_wc->recv_buf.mad;495mad_data = sa_mad->data;496} else {497if (is_rmpp_mad(hdr)) {498j = IB_MGMT_VENDOR_DATA;499/* Display OUI */500vendor_mad = (struct ib_vendor_mad *)501&mad_recv_wc->recv_buf.mad;502printk("Vendor OUI......%01x %01x %01x\n",503vendor_mad->oui[0],504vendor_mad->oui[1],505vendor_mad->oui[2]);506mad_data = vendor_mad->data;507} else {508j = IB_MGMT_MAD_DATA;509mad_data = mad_recv_wc->recv_buf.mad->data;510}511}512for (i = 0; i < j; i++) {513if (i % 16 == 0)514printk("\nData...........");515printk("%01x ", mad_data[i]);516}517printk("\n");518}519}520521static void madeye_add_one(struct ib_device *device)522{523struct madeye_port *port;524int reg_flags;525u8 i, s, e;526527if (device->node_type == RDMA_NODE_IB_SWITCH) {528s = 0;529e = 0;530} else {531s = 1;532e = device->phys_port_cnt;533}534535port = kmalloc(sizeof *port * (e - s + 1), GFP_KERNEL);536if (!port)537goto out;538539reg_flags = IB_MAD_SNOOP_SEND_COMPLETIONS | IB_MAD_SNOOP_RECVS;540for (i = 0; i <= e - s; i++) {541port[i].smi_agent = ib_register_mad_snoop(device, i + s,542IB_QPT_SMI,543reg_flags,544snoop_smi_handler,545recv_smi_handler,546&port[i]);547port[i].gsi_agent = ib_register_mad_snoop(device, i + s,548IB_QPT_GSI,549reg_flags,550snoop_gsi_handler,551recv_gsi_handler,552&port[i]);553}554555out:556ib_set_client_data(device, &madeye_client, port);557}558559static void madeye_remove_one(struct ib_device *device)560{561struct madeye_port *port;562int i, s, e;563564port = (struct madeye_port *)565ib_get_client_data(device, &madeye_client);566if (!port)567return;568569if (device->node_type == RDMA_NODE_IB_SWITCH) {570s = 0;571e = 0;572} else {573s = 1;574e = device->phys_port_cnt;575}576577for (i = 0; i <= e - s; i++) {578if (!IS_ERR(port[i].smi_agent))579ib_unregister_mad_agent(port[i].smi_agent);580if (!IS_ERR(port[i].gsi_agent))581ib_unregister_mad_agent(port[i].gsi_agent);582}583kfree(port);584}585586static int __init ib_madeye_init(void)587{588return ib_register_client(&madeye_client);589}590591static void __exit ib_madeye_cleanup(void)592{593ib_unregister_client(&madeye_client);594}595596module_init_order(ib_madeye_init, SI_ORDER_THIRD);597module_exit_order(ib_madeye_cleanup, SI_ORDER_THIRD);598599600