1*d6b92ffaSHans Petter Selasky /* 2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3*d6b92ffaSHans Petter Selasky * 4*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 5*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 6*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 7*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 8*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 9*d6b92ffaSHans Petter Selasky * 10*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 11*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 12*d6b92ffaSHans Petter Selasky * conditions are met: 13*d6b92ffaSHans Petter Selasky * 14*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 15*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 16*d6b92ffaSHans Petter Selasky * disclaimer. 17*d6b92ffaSHans Petter Selasky * 18*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 19*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 20*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 21*d6b92ffaSHans Petter Selasky * provided with the distribution. 22*d6b92ffaSHans Petter Selasky * 23*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30*d6b92ffaSHans Petter Selasky * SOFTWARE. 31*d6b92ffaSHans Petter Selasky * 32*d6b92ffaSHans Petter Selasky */ 33*d6b92ffaSHans Petter Selasky 34*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H 35*d6b92ffaSHans Petter Selasky # include <config.h> 36*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */ 37*d6b92ffaSHans Petter Selasky 38*d6b92ffaSHans Petter Selasky #include <stdio.h> 39*d6b92ffaSHans Petter Selasky #include <stdlib.h> 40*d6b92ffaSHans Petter Selasky #include <unistd.h> 41*d6b92ffaSHans Petter Selasky #include <getopt.h> 42*d6b92ffaSHans Petter Selasky #include <netinet/in.h> 43*d6b92ffaSHans Petter Selasky 44*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h> 45*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h> 46*d6b92ffaSHans Petter Selasky 47*d6b92ffaSHans Petter Selasky #include "ibdiag_common.h" 48*d6b92ffaSHans Petter Selasky 49*d6b92ffaSHans Petter Selasky #define IB_MLX_VENDOR_CLASS 10 50*d6b92ffaSHans Petter Selasky 51*d6b92ffaSHans Petter Selasky /* Vendor specific Attribute IDs */ 52*d6b92ffaSHans Petter Selasky #define IB_MLX_IS3_GENERAL_INFO 0x17 53*d6b92ffaSHans Petter Selasky 54*d6b92ffaSHans Petter Selasky #define MAX_SWITCH_PORTS (36+1) 55*d6b92ffaSHans Petter Selasky static char mtx_ports[MAX_SWITCH_PORTS] = {0}; 56*d6b92ffaSHans Petter Selasky static char mrx_ports[MAX_SWITCH_PORTS] = {0}; 57*d6b92ffaSHans Petter Selasky static char str[4096]; 58*d6b92ffaSHans Petter Selasky static uint8_t buf[256]; 59*d6b92ffaSHans Petter Selasky 60*d6b92ffaSHans Petter Selasky #define ATTRID_PM_ROUTE 0xff30 61*d6b92ffaSHans Petter Selasky #define ATTRID_PM_FILTER 0xff31 62*d6b92ffaSHans Petter Selasky #define ATTRID_PM_PORTS 0xff32 63*d6b92ffaSHans Petter Selasky #define ATTRID_LOSSY_CFG 0xff80 64*d6b92ffaSHans Petter Selasky 65*d6b92ffaSHans Petter Selasky enum mirror_type { 66*d6b92ffaSHans Petter Selasky MT_DISABLED = 0, 67*d6b92ffaSHans Petter Selasky MT_MIRROR_NATIVE = 2, 68*d6b92ffaSHans Petter Selasky MT_DROP = 5, 69*d6b92ffaSHans Petter Selasky MT_MIRROR_ENCAP = 6, 70*d6b92ffaSHans Petter Selasky MT_MIRROR_DROP = 7 71*d6b92ffaSHans Petter Selasky }; 72*d6b92ffaSHans Petter Selasky 73*d6b92ffaSHans Petter Selasky enum mirror_port { 74*d6b92ffaSHans Petter Selasky MP_DISABLED = 0, 75*d6b92ffaSHans Petter Selasky MP_MIRROR_FILTER = 1, 76*d6b92ffaSHans Petter Selasky MP_MIRROR_ALWAYS = 2, 77*d6b92ffaSHans Petter Selasky MP_MIRROR_FILTER_NOT = 3, 78*d6b92ffaSHans Petter Selasky MT_MIRROR_AS_RX = 1 79*d6b92ffaSHans Petter Selasky }; 80*d6b92ffaSHans Petter Selasky 81*d6b92ffaSHans Petter Selasky #define PM_ENCAP_ETHERTYPE 0x1123 82*d6b92ffaSHans Petter Selasky 83*d6b92ffaSHans Petter Selasky struct ibmad_port *srcport; 84*d6b92ffaSHans Petter Selasky 85*d6b92ffaSHans Petter Selasky typedef struct { 86*d6b92ffaSHans Petter Selasky uint16_t hw_revision; 87*d6b92ffaSHans Petter Selasky uint16_t device_id; 88*d6b92ffaSHans Petter Selasky uint8_t reserved[24]; 89*d6b92ffaSHans Petter Selasky uint32_t uptime; 90*d6b92ffaSHans Petter Selasky } is3_hw_info_t; 91*d6b92ffaSHans Petter Selasky 92*d6b92ffaSHans Petter Selasky typedef struct { 93*d6b92ffaSHans Petter Selasky uint8_t resv1; 94*d6b92ffaSHans Petter Selasky uint8_t major; 95*d6b92ffaSHans Petter Selasky uint8_t minor; 96*d6b92ffaSHans Petter Selasky uint8_t sub_minor; 97*d6b92ffaSHans Petter Selasky uint32_t build_id; 98*d6b92ffaSHans Petter Selasky uint8_t month; 99*d6b92ffaSHans Petter Selasky uint8_t day; 100*d6b92ffaSHans Petter Selasky uint16_t year; 101*d6b92ffaSHans Petter Selasky uint16_t resv2; 102*d6b92ffaSHans Petter Selasky uint16_t hour; 103*d6b92ffaSHans Petter Selasky uint8_t psid[16]; 104*d6b92ffaSHans Petter Selasky uint32_t ini_file_version; 105*d6b92ffaSHans Petter Selasky } is3_fw_info_t; 106*d6b92ffaSHans Petter Selasky 107*d6b92ffaSHans Petter Selasky typedef struct { 108*d6b92ffaSHans Petter Selasky uint8_t resv1; 109*d6b92ffaSHans Petter Selasky uint8_t major; 110*d6b92ffaSHans Petter Selasky uint8_t minor; 111*d6b92ffaSHans Petter Selasky uint8_t sub_minor; 112*d6b92ffaSHans Petter Selasky uint8_t resv2[28]; 113*d6b92ffaSHans Petter Selasky } is3_sw_info_t; 114*d6b92ffaSHans Petter Selasky 115*d6b92ffaSHans Petter Selasky typedef struct { 116*d6b92ffaSHans Petter Selasky uint8_t reserved[8]; 117*d6b92ffaSHans Petter Selasky is3_hw_info_t hw_info; 118*d6b92ffaSHans Petter Selasky is3_fw_info_t fw_info; 119*d6b92ffaSHans Petter Selasky is3_sw_info_t sw_info; 120*d6b92ffaSHans Petter Selasky } is3_general_info_t; 121*d6b92ffaSHans Petter Selasky 122*d6b92ffaSHans Petter Selasky typedef struct { 123*d6b92ffaSHans Petter Selasky uint16_t ignore_buffer_mask; 124*d6b92ffaSHans Petter Selasky uint16_t ignore_credit_mask; 125*d6b92ffaSHans Petter Selasky } lossy_config_t; 126*d6b92ffaSHans Petter Selasky 127*d6b92ffaSHans Petter Selasky static int mirror_query, mirror_dport, mirror_dlid, mirror_clear, mirror_sl, lossy_set; 128*d6b92ffaSHans Petter Selasky static int set_mtx, set_mrx, packet_size = 0xfff; 129*d6b92ffaSHans Petter Selasky 130*d6b92ffaSHans Petter Selasky static int parse_ports(char *ports_str, char *ports_array) 131*d6b92ffaSHans Petter Selasky { 132*d6b92ffaSHans Petter Selasky int num, i; 133*d6b92ffaSHans Petter Selasky char *str = strdup(ports_str); 134*d6b92ffaSHans Petter Selasky char *token = strtok(str, ","); 135*d6b92ffaSHans Petter Selasky for (i = 0; i < MAX_SWITCH_PORTS && token; i++) { 136*d6b92ffaSHans Petter Selasky num = strtoul(token, NULL, 0); 137*d6b92ffaSHans Petter Selasky if (num > 0 && num < MAX_SWITCH_PORTS) 138*d6b92ffaSHans Petter Selasky ports_array[num] = 1; 139*d6b92ffaSHans Petter Selasky 140*d6b92ffaSHans Petter Selasky token = strtok(NULL, ","); 141*d6b92ffaSHans Petter Selasky } 142*d6b92ffaSHans Petter Selasky free(str); 143*d6b92ffaSHans Petter Selasky return 0; 144*d6b92ffaSHans Petter Selasky } 145*d6b92ffaSHans Petter Selasky 146*d6b92ffaSHans Petter Selasky void port_mirror_route(ib_portid_t * portid, int query, int clear) 147*d6b92ffaSHans Petter Selasky { 148*d6b92ffaSHans Petter Selasky int mirror_type; 149*d6b92ffaSHans Petter Selasky 150*d6b92ffaSHans Petter Selasky memset(&buf, 0, sizeof(buf)); 151*d6b92ffaSHans Petter Selasky 152*d6b92ffaSHans Petter Selasky if (clear) { 153*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 154*d6b92ffaSHans Petter Selasky IBEXIT("Clear port mirror route set failed"); 155*d6b92ffaSHans Petter Selasky return; 156*d6b92ffaSHans Petter Selasky } 157*d6b92ffaSHans Petter Selasky 158*d6b92ffaSHans Petter Selasky if (query) { 159*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 160*d6b92ffaSHans Petter Selasky IBEXIT("Read port mirror route get failed"); 161*d6b92ffaSHans Petter Selasky mad_decode_field(buf, IB_PMR_MT_F, &mirror_type); 162*d6b92ffaSHans Petter Selasky if (mirror_type == MT_MIRROR_ENCAP && mirror_dlid == 0) 163*d6b92ffaSHans Petter Selasky mad_decode_field(buf, IB_PMR_LRH_DLID_F, &mirror_dlid); 164*d6b92ffaSHans Petter Selasky if (mirror_type == MT_MIRROR_NATIVE && mirror_dport == 0) 165*d6b92ffaSHans Petter Selasky mad_decode_field(buf, IB_PMR_NM_PORT_F, &mirror_dport); 166*d6b92ffaSHans Petter Selasky goto Exit; 167*d6b92ffaSHans Petter Selasky } 168*d6b92ffaSHans Petter Selasky 169*d6b92ffaSHans Petter Selasky /* Port Mirror Route */ 170*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_ENCAP_RAW_ETH_TYPE_F, PM_ENCAP_ETHERTYPE); 171*d6b92ffaSHans Petter Selasky 172*d6b92ffaSHans Petter Selasky if (mirror_dlid == 0) { 173*d6b92ffaSHans Petter Selasky /* Can not truncate mirrored packets in local mode */ 174*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, 0xfff); 175*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_NATIVE); 176*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_NM_PORT_F, mirror_dport); 177*d6b92ffaSHans Petter Selasky } 178*d6b92ffaSHans Petter Selasky else { /* remote mirror */ 179*d6b92ffaSHans Petter Selasky /* convert size to dwords */ 180*d6b92ffaSHans Petter Selasky packet_size = packet_size / 4 + 1; 181*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, packet_size); 182*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_ENCAP); 183*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_LRH_SL_F, mirror_sl); 184*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_LRH_DLID_F, mirror_dlid); 185*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, IB_PMR_LRH_SLID_F, portid->lid); 186*d6b92ffaSHans Petter Selasky } 187*d6b92ffaSHans Petter Selasky 188*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 189*d6b92ffaSHans Petter Selasky IBEXIT("port mirror route set failed"); 190*d6b92ffaSHans Petter Selasky 191*d6b92ffaSHans Petter Selasky Exit: 192*d6b92ffaSHans Petter Selasky mad_dump_portmirror_route(str, sizeof str, buf, sizeof buf); 193*d6b92ffaSHans Petter Selasky printf("Port Mirror Route\n%s", str); 194*d6b92ffaSHans Petter Selasky } 195*d6b92ffaSHans Petter Selasky 196*d6b92ffaSHans Petter Selasky void port_mirror_ports(ib_portid_t * portid, int query, int clear) 197*d6b92ffaSHans Petter Selasky { 198*d6b92ffaSHans Petter Selasky int p, rqf, tqf, rqv, tqv; 199*d6b92ffaSHans Petter Selasky 200*d6b92ffaSHans Petter Selasky memset(&buf, 0, sizeof(buf)); 201*d6b92ffaSHans Petter Selasky 202*d6b92ffaSHans Petter Selasky if (clear) { 203*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 204*d6b92ffaSHans Petter Selasky IBEXIT("Clear port mirror ports set failed"); 205*d6b92ffaSHans Petter Selasky return; 206*d6b92ffaSHans Petter Selasky } 207*d6b92ffaSHans Petter Selasky 208*d6b92ffaSHans Petter Selasky if (query) { 209*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 210*d6b92ffaSHans Petter Selasky IBEXIT("Read port mirror ports get failed"); 211*d6b92ffaSHans Petter Selasky goto Exit; 212*d6b92ffaSHans Petter Selasky } 213*d6b92ffaSHans Petter Selasky 214*d6b92ffaSHans Petter Selasky /* Port Mirror Ports */ 215*d6b92ffaSHans Petter Selasky rqf = IB_PMP_RQ_1_F; 216*d6b92ffaSHans Petter Selasky tqf = IB_PMP_TQ_1_F; 217*d6b92ffaSHans Petter Selasky 218*d6b92ffaSHans Petter Selasky for (p = 1; p < MAX_SWITCH_PORTS; p++) { 219*d6b92ffaSHans Petter Selasky rqv = mrx_ports[p] ? MP_MIRROR_ALWAYS : MP_DISABLED; 220*d6b92ffaSHans Petter Selasky tqv = mtx_ports[p] ? MP_MIRROR_ALWAYS : MT_MIRROR_AS_RX; 221*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, rqf, rqv); 222*d6b92ffaSHans Petter Selasky mad_set_field(buf, 0, tqf, tqv); 223*d6b92ffaSHans Petter Selasky rqf += 2; 224*d6b92ffaSHans Petter Selasky tqf += 2; 225*d6b92ffaSHans Petter Selasky } 226*d6b92ffaSHans Petter Selasky 227*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 228*d6b92ffaSHans Petter Selasky IBEXIT("port mirror ports set failed"); 229*d6b92ffaSHans Petter Selasky 230*d6b92ffaSHans Petter Selasky Exit: 231*d6b92ffaSHans Petter Selasky mad_dump_portmirror_ports(str, sizeof str, buf, sizeof buf); 232*d6b92ffaSHans Petter Selasky printf("Port Mirror Ports\n%s", str); 233*d6b92ffaSHans Petter Selasky } 234*d6b92ffaSHans Petter Selasky 235*d6b92ffaSHans Petter Selasky int get_out_port(ib_portid_t* portid) 236*d6b92ffaSHans Petter Selasky { 237*d6b92ffaSHans Petter Selasky int block; 238*d6b92ffaSHans Petter Selasky int offset; 239*d6b92ffaSHans Petter Selasky 240*d6b92ffaSHans Petter Selasky if (mirror_dlid) { 241*d6b92ffaSHans Petter Selasky block = mirror_dlid / IB_SMP_DATA_SIZE; 242*d6b92ffaSHans Petter Selasky offset = mirror_dlid - block * IB_SMP_DATA_SIZE; 243*d6b92ffaSHans Petter Selasky /* get out port from lft */ 244*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, portid, IB_ATTR_LINEARFORWTBL, block, 0, srcport)) 245*d6b92ffaSHans Petter Selasky IBEXIT("linear forwarding table get failed"); 246*d6b92ffaSHans Petter Selasky block = mirror_dlid / IB_SMP_DATA_SIZE; 247*d6b92ffaSHans Petter Selasky offset = mirror_dlid - block * IB_SMP_DATA_SIZE; 248*d6b92ffaSHans Petter Selasky return buf[offset]; 249*d6b92ffaSHans Petter Selasky } 250*d6b92ffaSHans Petter Selasky else 251*d6b92ffaSHans Petter Selasky return mirror_dport; 252*d6b92ffaSHans Petter Selasky } 253*d6b92ffaSHans Petter Selasky 254*d6b92ffaSHans Petter Selasky int get_peer(ib_portid_t* portid, int outport, int* peerlid, int* peerport) 255*d6b92ffaSHans Petter Selasky { 256*d6b92ffaSHans Petter Selasky ib_portid_t selfportid = { 0 }; 257*d6b92ffaSHans Petter Selasky ib_portid_t peerportid = { 0 }; 258*d6b92ffaSHans Petter Selasky int selfport = 0; 259*d6b92ffaSHans Petter Selasky 260*d6b92ffaSHans Petter Selasky /* set peerportid for peer port */ 261*d6b92ffaSHans Petter Selasky memcpy(&peerportid, portid, sizeof(peerportid)); 262*d6b92ffaSHans Petter Selasky peerportid.drpath.cnt = 1; 263*d6b92ffaSHans Petter Selasky peerportid.drpath.p[1] = outport; 264*d6b92ffaSHans Petter Selasky if (ib_resolve_self_via(&selfportid, &selfport, 0, srcport) < 0) 265*d6b92ffaSHans Petter Selasky IBEXIT("failed to resolve self portid"); 266*d6b92ffaSHans Petter Selasky peerportid.drpath.drslid = (uint16_t) selfportid.lid; 267*d6b92ffaSHans Petter Selasky peerportid.drpath.drdlid = 0xffff; 268*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, &peerportid, IB_ATTR_PORT_INFO, 0, 0, srcport)) 269*d6b92ffaSHans Petter Selasky IBEXIT("get peer portinfo failed - unable to configure lossy\n"); 270*d6b92ffaSHans Petter Selasky 271*d6b92ffaSHans Petter Selasky mad_decode_field(buf, IB_PORT_LID_F, peerlid); 272*d6b92ffaSHans Petter Selasky mad_decode_field(buf, IB_PORT_LOCAL_PORT_F, peerport); 273*d6b92ffaSHans Petter Selasky 274*d6b92ffaSHans Petter Selasky return 0; 275*d6b92ffaSHans Petter Selasky } 276*d6b92ffaSHans Petter Selasky 277*d6b92ffaSHans Petter Selasky int get_mirror_vl(ib_portid_t* portid, int outport) 278*d6b92ffaSHans Petter Selasky { 279*d6b92ffaSHans Petter Selasky ib_slvl_table_t * p_slvl_tbl; 280*d6b92ffaSHans Petter Selasky int portnum; 281*d6b92ffaSHans Petter Selasky int vl; 282*d6b92ffaSHans Petter Selasky 283*d6b92ffaSHans Petter Selasky /* hack; assume all sl2vl mappings are the same for any in port and outport */ 284*d6b92ffaSHans Petter Selasky portnum = (1 << 8) | outport; 285*d6b92ffaSHans Petter Selasky 286*d6b92ffaSHans Petter Selasky /* get sl2vl mapping */ 287*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, portid, IB_ATTR_SLVL_TABLE, portnum, 0, srcport)) 288*d6b92ffaSHans Petter Selasky IBEXIT("slvl query failed"); 289*d6b92ffaSHans Petter Selasky 290*d6b92ffaSHans Petter Selasky p_slvl_tbl = (ib_slvl_table_t *) buf; 291*d6b92ffaSHans Petter Selasky vl = ib_slvl_table_get(p_slvl_tbl, mirror_sl); 292*d6b92ffaSHans Petter Selasky printf("mirror_sl %d, mirror_vl %d\n", mirror_sl, vl); 293*d6b92ffaSHans Petter Selasky return vl; 294*d6b92ffaSHans Petter Selasky } 295*d6b92ffaSHans Petter Selasky 296*d6b92ffaSHans Petter Selasky int lossy_config(ib_portid_t* portid, int query, int clear) 297*d6b92ffaSHans Petter Selasky { 298*d6b92ffaSHans Petter Selasky int outport; 299*d6b92ffaSHans Petter Selasky int peerport; 300*d6b92ffaSHans Petter Selasky int attr_mod; 301*d6b92ffaSHans Petter Selasky uint8_t mirror_vl; 302*d6b92ffaSHans Petter Selasky ib_portid_t peerportid = { 0 }; 303*d6b92ffaSHans Petter Selasky ib_portid_t * p_portid; 304*d6b92ffaSHans Petter Selasky lossy_config_t local_lossy_cfg; 305*d6b92ffaSHans Petter Selasky lossy_config_t peer_lossy_cfg; 306*d6b92ffaSHans Petter Selasky lossy_config_t lossy_cfg; 307*d6b92ffaSHans Petter Selasky 308*d6b92ffaSHans Petter Selasky outport = get_out_port(portid); 309*d6b92ffaSHans Petter Selasky if (outport == 0) 310*d6b92ffaSHans Petter Selasky IBEXIT("get_out_port failed, mirror_dlid and mirror_dport are 0"); 311*d6b92ffaSHans Petter Selasky 312*d6b92ffaSHans Petter Selasky get_peer(portid, outport, &peerportid.lid, &peerport); 313*d6b92ffaSHans Petter Selasky 314*d6b92ffaSHans Petter Selasky printf("local lid %d / port %d\n", portid->lid, outport); 315*d6b92ffaSHans Petter Selasky printf("peer lid %d / port %d\n", peerportid.lid, peerport); 316*d6b92ffaSHans Petter Selasky 317*d6b92ffaSHans Petter Selasky mirror_vl = get_mirror_vl(portid, outport); 318*d6b92ffaSHans Petter Selasky 319*d6b92ffaSHans Petter Selasky /* read local lossy configuration */ 320*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, portid, ATTRID_LOSSY_CFG, outport, 0, srcport)) 321*d6b92ffaSHans Petter Selasky IBEXIT("get lossy config from lid %d port %d failed - not supported\n", 322*d6b92ffaSHans Petter Selasky portid->lid, outport); 323*d6b92ffaSHans Petter Selasky memcpy(&local_lossy_cfg, buf, sizeof(local_lossy_cfg)); 324*d6b92ffaSHans Petter Selasky 325*d6b92ffaSHans Petter Selasky /* read peer lossy configuration */ 326*d6b92ffaSHans Petter Selasky if (!smp_query_via(buf, &peerportid, ATTRID_LOSSY_CFG, peerport, 0, srcport)) 327*d6b92ffaSHans Petter Selasky IBEXIT("get lossy config from lid %d port %d failed - not supported\n", 328*d6b92ffaSHans Petter Selasky peerportid.lid, peerport); 329*d6b92ffaSHans Petter Selasky memcpy(&peer_lossy_cfg, buf, sizeof(peer_lossy_cfg)); 330*d6b92ffaSHans Petter Selasky 331*d6b92ffaSHans Petter Selasky if (query) { 332*d6b92ffaSHans Petter Selasky printf("local port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n", 333*d6b92ffaSHans Petter Selasky portid->lid, outport, 334*d6b92ffaSHans Petter Selasky ntohs(local_lossy_cfg.ignore_buffer_mask), ntohs(local_lossy_cfg.ignore_credit_mask)); 335*d6b92ffaSHans Petter Selasky printf("peer port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n", 336*d6b92ffaSHans Petter Selasky peerportid.lid, peerport, 337*d6b92ffaSHans Petter Selasky ntohs(peer_lossy_cfg.ignore_buffer_mask), ntohs(peer_lossy_cfg.ignore_credit_mask)); 338*d6b92ffaSHans Petter Selasky return 0; 339*d6b92ffaSHans Petter Selasky } 340*d6b92ffaSHans Petter Selasky 341*d6b92ffaSHans Petter Selasky /* VLs 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 */ 342*d6b92ffaSHans Petter Selasky /* ignore Buf Overrun ignore Credits */ 343*d6b92ffaSHans Petter Selasky /* when mirror activated set ignore buffer overrun on peer port */ 344*d6b92ffaSHans Petter Selasky /* when mirror is de-activated clear ignore credits on local port */ 345*d6b92ffaSHans Petter Selasky memset(&buf, 0, sizeof(buf)); 346*d6b92ffaSHans Petter Selasky if (clear) { 347*d6b92ffaSHans Petter Selasky p_portid = portid; 348*d6b92ffaSHans Petter Selasky attr_mod = outport; 349*d6b92ffaSHans Petter Selasky } else { 350*d6b92ffaSHans Petter Selasky /* set buffer overrun on peer port */ 351*d6b92ffaSHans Petter Selasky p_portid = &peerportid; 352*d6b92ffaSHans Petter Selasky attr_mod = peerport; 353*d6b92ffaSHans Petter Selasky lossy_cfg.ignore_buffer_mask = htons(1<<mirror_vl); 354*d6b92ffaSHans Petter Selasky lossy_cfg.ignore_credit_mask = 0; 355*d6b92ffaSHans Petter Selasky memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg)); 356*d6b92ffaSHans Petter Selasky } 357*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport)) 358*d6b92ffaSHans Petter Selasky IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid); 359*d6b92ffaSHans Petter Selasky 360*d6b92ffaSHans Petter Selasky /* when mirror activated set ignore credit on local port */ 361*d6b92ffaSHans Petter Selasky /* when mirror de-activated clear buffer overrun on peer */ 362*d6b92ffaSHans Petter Selasky memset(&buf, 0, sizeof(buf)); 363*d6b92ffaSHans Petter Selasky if (clear) { 364*d6b92ffaSHans Petter Selasky p_portid = &peerportid; 365*d6b92ffaSHans Petter Selasky attr_mod = peerport; 366*d6b92ffaSHans Petter Selasky } else { 367*d6b92ffaSHans Petter Selasky /* set ignore credit on local port */ 368*d6b92ffaSHans Petter Selasky p_portid = portid; 369*d6b92ffaSHans Petter Selasky attr_mod = outport; 370*d6b92ffaSHans Petter Selasky lossy_cfg.ignore_credit_mask = htons(1<<mirror_vl); 371*d6b92ffaSHans Petter Selasky lossy_cfg.ignore_buffer_mask = 0; 372*d6b92ffaSHans Petter Selasky memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg)); 373*d6b92ffaSHans Petter Selasky } 374*d6b92ffaSHans Petter Selasky if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport)) 375*d6b92ffaSHans Petter Selasky IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid); 376*d6b92ffaSHans Petter Selasky 377*d6b92ffaSHans Petter Selasky return 0; 378*d6b92ffaSHans Petter Selasky } 379*d6b92ffaSHans Petter Selasky 380*d6b92ffaSHans Petter Selasky int mirror_config(ib_portid_t* portid, int query, int clear) 381*d6b92ffaSHans Petter Selasky { 382*d6b92ffaSHans Petter Selasky port_mirror_route(portid, query, clear); 383*d6b92ffaSHans Petter Selasky /* port_mirror_filter(portid, query, clear); */ 384*d6b92ffaSHans Petter Selasky port_mirror_ports(portid, query, clear); 385*d6b92ffaSHans Petter Selasky 386*d6b92ffaSHans Petter Selasky return 0; 387*d6b92ffaSHans Petter Selasky } 388*d6b92ffaSHans Petter Selasky 389*d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg) 390*d6b92ffaSHans Petter Selasky { 391*d6b92ffaSHans Petter Selasky switch (ch) { 392*d6b92ffaSHans Petter Selasky case 'p': 393*d6b92ffaSHans Petter Selasky mirror_dport = strtoul(optarg, NULL, 0); 394*d6b92ffaSHans Petter Selasky break; 395*d6b92ffaSHans Petter Selasky case 'S': 396*d6b92ffaSHans Petter Selasky packet_size = strtoul(optarg, NULL, 0); 397*d6b92ffaSHans Petter Selasky break; 398*d6b92ffaSHans Petter Selasky case 'l': 399*d6b92ffaSHans Petter Selasky mirror_sl = strtoul(optarg, NULL, 0); 400*d6b92ffaSHans Petter Selasky break; 401*d6b92ffaSHans Petter Selasky case 'L': 402*d6b92ffaSHans Petter Selasky mirror_dlid = strtoul(optarg, NULL, 0); 403*d6b92ffaSHans Petter Selasky break; 404*d6b92ffaSHans Petter Selasky case 'R': 405*d6b92ffaSHans Petter Selasky set_mrx = 1; 406*d6b92ffaSHans Petter Selasky if (-1 == parse_ports(optarg, mrx_ports)) 407*d6b92ffaSHans Petter Selasky return -1; 408*d6b92ffaSHans Petter Selasky break; 409*d6b92ffaSHans Petter Selasky case 'T': 410*d6b92ffaSHans Petter Selasky set_mtx = 1; 411*d6b92ffaSHans Petter Selasky if (-1 == parse_ports(optarg, mtx_ports)) 412*d6b92ffaSHans Petter Selasky return -1; 413*d6b92ffaSHans Petter Selasky break; 414*d6b92ffaSHans Petter Selasky case 'D': 415*d6b92ffaSHans Petter Selasky mirror_clear = 1; 416*d6b92ffaSHans Petter Selasky break; 417*d6b92ffaSHans Petter Selasky case 'Q': 418*d6b92ffaSHans Petter Selasky mirror_query = 1; 419*d6b92ffaSHans Petter Selasky break; 420*d6b92ffaSHans Petter Selasky case 'y': 421*d6b92ffaSHans Petter Selasky lossy_set = 1; 422*d6b92ffaSHans Petter Selasky break; 423*d6b92ffaSHans Petter Selasky default: 424*d6b92ffaSHans Petter Selasky return -1; 425*d6b92ffaSHans Petter Selasky } 426*d6b92ffaSHans Petter Selasky return 0; 427*d6b92ffaSHans Petter Selasky } 428*d6b92ffaSHans Petter Selasky 429*d6b92ffaSHans Petter Selasky int main(int argc, char **argv) 430*d6b92ffaSHans Petter Selasky { 431*d6b92ffaSHans Petter Selasky int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, 432*d6b92ffaSHans Petter Selasky IB_MLX_VENDOR_CLASS 433*d6b92ffaSHans Petter Selasky }; 434*d6b92ffaSHans Petter Selasky ib_portid_t portid = { 0 }; 435*d6b92ffaSHans Petter Selasky int port = 0; 436*d6b92ffaSHans Petter Selasky ib_vendor_call_t call; 437*d6b92ffaSHans Petter Selasky is3_general_info_t *gi; 438*d6b92ffaSHans Petter Selasky uint32_t fw_ver; 439*d6b92ffaSHans Petter Selasky char op_str[32]; 440*d6b92ffaSHans Petter Selasky 441*d6b92ffaSHans Petter Selasky const struct ibdiag_opt opts[] = { 442*d6b92ffaSHans Petter Selasky {"dport", 'p', 1, "<port>", "set mirror destination port"}, 443*d6b92ffaSHans Petter Selasky {"dlid", 'L', 1, "<dlid>", "set mirror destination LID"}, 444*d6b92ffaSHans Petter Selasky {"sl", 'l', 1, "<sl>", "set mirror SL"}, 445*d6b92ffaSHans Petter Selasky {"size", 'S', 1, "<size>", "set packet size"}, 446*d6b92ffaSHans Petter Selasky {"rxports", 'R', 1, NULL, "mirror receive port list"}, 447*d6b92ffaSHans Petter Selasky {"txports", 'T', 1, NULL, "mirror transmit port list"}, 448*d6b92ffaSHans Petter Selasky {"clear", 'D', 0, NULL, "clear ports mirroring"}, 449*d6b92ffaSHans Petter Selasky {"query", 'Q', 0, NULL, "read mirror configuration"}, 450*d6b92ffaSHans Petter Selasky {"lossy", 'y', 0, NULL, "set lossy configuration on out port"}, 451*d6b92ffaSHans Petter Selasky {0} 452*d6b92ffaSHans Petter Selasky }; 453*d6b92ffaSHans Petter Selasky 454*d6b92ffaSHans Petter Selasky char usage_args[] = "<lid>"; 455*d6b92ffaSHans Petter Selasky const char *usage_examples[] = { 456*d6b92ffaSHans Petter Selasky "-R 1,2,3 -T 2,5 -l1 -L25 -S100 <lid>\t# configure mirror ports", 457*d6b92ffaSHans Petter Selasky "-D <lid> \t# clear mirror configuration", 458*d6b92ffaSHans Petter Selasky "-Q <lid>\t# read mirror configuration", 459*d6b92ffaSHans Petter Selasky NULL 460*d6b92ffaSHans Petter Selasky }; 461*d6b92ffaSHans Petter Selasky 462*d6b92ffaSHans Petter Selasky ibdiag_process_opts(argc, argv, NULL, "GDLs", opts, process_opt, 463*d6b92ffaSHans Petter Selasky usage_args, usage_examples); 464*d6b92ffaSHans Petter Selasky 465*d6b92ffaSHans Petter Selasky argc -= optind; 466*d6b92ffaSHans Petter Selasky argv += optind; 467*d6b92ffaSHans Petter Selasky 468*d6b92ffaSHans Petter Selasky if (argc == 0) 469*d6b92ffaSHans Petter Selasky ibdiag_show_usage(); 470*d6b92ffaSHans Petter Selasky 471*d6b92ffaSHans Petter Selasky srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4); 472*d6b92ffaSHans Petter Selasky if (!srcport) 473*d6b92ffaSHans Petter Selasky IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port); 474*d6b92ffaSHans Petter Selasky 475*d6b92ffaSHans Petter Selasky if (argc) { 476*d6b92ffaSHans Petter Selasky if (ib_resolve_portid_str_via(&portid, argv[0], ibd_dest_type, 477*d6b92ffaSHans Petter Selasky ibd_sm_id, srcport) < 0) 478*d6b92ffaSHans Petter Selasky IBEXIT("can't resolve destination port %s", argv[0]); 479*d6b92ffaSHans Petter Selasky } 480*d6b92ffaSHans Petter Selasky 481*d6b92ffaSHans Petter Selasky 482*d6b92ffaSHans Petter Selasky memset(&buf, 0, sizeof(buf)); 483*d6b92ffaSHans Petter Selasky memset(&call, 0, sizeof(call)); 484*d6b92ffaSHans Petter Selasky call.mgmt_class = IB_MLX_VENDOR_CLASS; 485*d6b92ffaSHans Petter Selasky call.method = IB_MAD_METHOD_GET; 486*d6b92ffaSHans Petter Selasky call.timeout = ibd_timeout; 487*d6b92ffaSHans Petter Selasky call.attrid = IB_MLX_IS3_GENERAL_INFO; 488*d6b92ffaSHans Petter Selasky if (!ib_vendor_call_via(&buf, &portid, &call, srcport)) 489*d6b92ffaSHans Petter Selasky IBEXIT("failed to read vendor info"); 490*d6b92ffaSHans Petter Selasky gi = (is3_general_info_t *) & buf; 491*d6b92ffaSHans Petter Selasky if (ntohs(gi->hw_info.device_id) != 0x1b3) 492*d6b92ffaSHans Petter Selasky IBEXIT("device id 0x%x does not support mirroring", ntohs(gi->hw_info.device_id)); 493*d6b92ffaSHans Petter Selasky 494*d6b92ffaSHans Petter Selasky fw_ver = gi->fw_info.major * 100000 + gi->fw_info.minor * 1000 + gi->fw_info.sub_minor; 495*d6b92ffaSHans Petter Selasky printf("FW version %08d\n", fw_ver); 496*d6b92ffaSHans Petter Selasky if (lossy_set && fw_ver < 704000) 497*d6b92ffaSHans Petter Selasky IBEXIT("FW version %d.%d.%d does not support lossy config", 498*d6b92ffaSHans Petter Selasky gi->fw_info.major, gi->fw_info.minor, gi->fw_info.sub_minor); 499*d6b92ffaSHans Petter Selasky 500*d6b92ffaSHans Petter Selasky if (ibdebug) { 501*d6b92ffaSHans Petter Selasky printf( "switch_lid = %d\n" 502*d6b92ffaSHans Petter Selasky "mirror_clear = %d\n" 503*d6b92ffaSHans Petter Selasky "mirror_dlid = %d\n" 504*d6b92ffaSHans Petter Selasky "mirror_sl = %d\n" 505*d6b92ffaSHans Petter Selasky "mirror_port = %d\n", 506*d6b92ffaSHans Petter Selasky portid.lid, mirror_clear, mirror_dlid, 507*d6b92ffaSHans Petter Selasky mirror_sl, mirror_dport); 508*d6b92ffaSHans Petter Selasky 509*d6b92ffaSHans Petter Selasky for (port = 1; port < MAX_SWITCH_PORTS; port++) { 510*d6b92ffaSHans Petter Selasky if (mtx_ports[port]) 511*d6b92ffaSHans Petter Selasky printf("TX: %d\n",port); 512*d6b92ffaSHans Petter Selasky else if(mrx_ports[port]) 513*d6b92ffaSHans Petter Selasky printf("RX: %d\n",port); 514*d6b92ffaSHans Petter Selasky } 515*d6b92ffaSHans Petter Selasky } 516*d6b92ffaSHans Petter Selasky 517*d6b92ffaSHans Petter Selasky if (mirror_clear) 518*d6b92ffaSHans Petter Selasky strcpy(op_str, "Clear"); 519*d6b92ffaSHans Petter Selasky else if (mirror_query) 520*d6b92ffaSHans Petter Selasky strcpy(op_str, "Read"); 521*d6b92ffaSHans Petter Selasky else if (!mirror_dport && !mirror_dlid) 522*d6b92ffaSHans Petter Selasky IBEXIT("Mirror remote LID and local port are zero"); 523*d6b92ffaSHans Petter Selasky else if (!set_mtx && !set_mrx) 524*d6b92ffaSHans Petter Selasky IBEXIT("Mirror Rx and Tx ports not selected"); 525*d6b92ffaSHans Petter Selasky else 526*d6b92ffaSHans Petter Selasky strcpy(op_str, "Set"); 527*d6b92ffaSHans Petter Selasky 528*d6b92ffaSHans Petter Selasky printf("\n%s Mirror Configuration\n", op_str); 529*d6b92ffaSHans Petter Selasky mirror_config(&portid, mirror_query, mirror_clear); 530*d6b92ffaSHans Petter Selasky 531*d6b92ffaSHans Petter Selasky if (lossy_set) { 532*d6b92ffaSHans Petter Selasky printf("%s Lossy Configuration\n", op_str); 533*d6b92ffaSHans Petter Selasky lossy_config(&portid, mirror_query, mirror_clear); 534*d6b92ffaSHans Petter Selasky } 535*d6b92ffaSHans Petter Selasky 536*d6b92ffaSHans Petter Selasky mad_rpc_close_port(srcport); 537*d6b92ffaSHans Petter Selasky exit(0); 538*d6b92ffaSHans Petter Selasky } 539