1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3321936Shselasky * 4321936Shselasky * This software is available to you under a choice of one of two 5321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 6321936Shselasky * General Public License (GPL) Version 2, available from the file 7321936Shselasky * COPYING in the main directory of this source tree, or the 8321936Shselasky * OpenIB.org BSD license below: 9321936Shselasky * 10321936Shselasky * Redistribution and use in source and binary forms, with or 11321936Shselasky * without modification, are permitted provided that the following 12321936Shselasky * conditions are met: 13321936Shselasky * 14321936Shselasky * - Redistributions of source code must retain the above 15321936Shselasky * copyright notice, this list of conditions and the following 16321936Shselasky * disclaimer. 17321936Shselasky * 18321936Shselasky * - Redistributions in binary form must reproduce the above 19321936Shselasky * copyright notice, this list of conditions and the following 20321936Shselasky * disclaimer in the documentation and/or other materials 21321936Shselasky * provided with the distribution. 22321936Shselasky * 23321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30321936Shselasky * SOFTWARE. 31321936Shselasky * 32321936Shselasky */ 33321936Shselasky 34321936Shselasky#if HAVE_CONFIG_H 35321936Shselasky# include <config.h> 36321936Shselasky#endif /* HAVE_CONFIG_H */ 37321936Shselasky 38321936Shselasky#include <stdio.h> 39321936Shselasky#include <stdlib.h> 40321936Shselasky#include <unistd.h> 41321936Shselasky#include <getopt.h> 42321936Shselasky#include <netinet/in.h> 43321936Shselasky 44321936Shselasky#include <infiniband/umad.h> 45321936Shselasky#include <infiniband/mad.h> 46321936Shselasky 47321936Shselasky#include "ibdiag_common.h" 48321936Shselasky 49321936Shselasky#define IB_MLX_VENDOR_CLASS 10 50321936Shselasky 51321936Shselasky/* Vendor specific Attribute IDs */ 52321936Shselasky#define IB_MLX_IS3_GENERAL_INFO 0x17 53321936Shselasky 54321936Shselasky#define MAX_SWITCH_PORTS (36+1) 55321936Shselaskystatic char mtx_ports[MAX_SWITCH_PORTS] = {0}; 56321936Shselaskystatic char mrx_ports[MAX_SWITCH_PORTS] = {0}; 57321936Shselaskystatic char str[4096]; 58321936Shselaskystatic uint8_t buf[256]; 59321936Shselasky 60321936Shselasky#define ATTRID_PM_ROUTE 0xff30 61321936Shselasky#define ATTRID_PM_FILTER 0xff31 62321936Shselasky#define ATTRID_PM_PORTS 0xff32 63321936Shselasky#define ATTRID_LOSSY_CFG 0xff80 64321936Shselasky 65321936Shselaskyenum mirror_type { 66321936Shselasky MT_DISABLED = 0, 67321936Shselasky MT_MIRROR_NATIVE = 2, 68321936Shselasky MT_DROP = 5, 69321936Shselasky MT_MIRROR_ENCAP = 6, 70321936Shselasky MT_MIRROR_DROP = 7 71321936Shselasky}; 72321936Shselasky 73321936Shselaskyenum mirror_port { 74321936Shselasky MP_DISABLED = 0, 75321936Shselasky MP_MIRROR_FILTER = 1, 76321936Shselasky MP_MIRROR_ALWAYS = 2, 77321936Shselasky MP_MIRROR_FILTER_NOT = 3, 78321936Shselasky MT_MIRROR_AS_RX = 1 79321936Shselasky}; 80321936Shselasky 81321936Shselasky#define PM_ENCAP_ETHERTYPE 0x1123 82321936Shselasky 83321936Shselaskystruct ibmad_port *srcport; 84321936Shselasky 85321936Shselaskytypedef struct { 86321936Shselasky uint16_t hw_revision; 87321936Shselasky uint16_t device_id; 88321936Shselasky uint8_t reserved[24]; 89321936Shselasky uint32_t uptime; 90321936Shselasky} is3_hw_info_t; 91321936Shselasky 92321936Shselaskytypedef struct { 93321936Shselasky uint8_t resv1; 94321936Shselasky uint8_t major; 95321936Shselasky uint8_t minor; 96321936Shselasky uint8_t sub_minor; 97321936Shselasky uint32_t build_id; 98321936Shselasky uint8_t month; 99321936Shselasky uint8_t day; 100321936Shselasky uint16_t year; 101321936Shselasky uint16_t resv2; 102321936Shselasky uint16_t hour; 103321936Shselasky uint8_t psid[16]; 104321936Shselasky uint32_t ini_file_version; 105321936Shselasky} is3_fw_info_t; 106321936Shselasky 107321936Shselaskytypedef struct { 108321936Shselasky uint8_t resv1; 109321936Shselasky uint8_t major; 110321936Shselasky uint8_t minor; 111321936Shselasky uint8_t sub_minor; 112321936Shselasky uint8_t resv2[28]; 113321936Shselasky} is3_sw_info_t; 114321936Shselasky 115321936Shselaskytypedef struct { 116321936Shselasky uint8_t reserved[8]; 117321936Shselasky is3_hw_info_t hw_info; 118321936Shselasky is3_fw_info_t fw_info; 119321936Shselasky is3_sw_info_t sw_info; 120321936Shselasky} is3_general_info_t; 121321936Shselasky 122321936Shselaskytypedef struct { 123321936Shselasky uint16_t ignore_buffer_mask; 124321936Shselasky uint16_t ignore_credit_mask; 125321936Shselasky} lossy_config_t; 126321936Shselasky 127321936Shselaskystatic int mirror_query, mirror_dport, mirror_dlid, mirror_clear, mirror_sl, lossy_set; 128321936Shselaskystatic int set_mtx, set_mrx, packet_size = 0xfff; 129321936Shselasky 130321936Shselaskystatic int parse_ports(char *ports_str, char *ports_array) 131321936Shselasky{ 132321936Shselasky int num, i; 133321936Shselasky char *str = strdup(ports_str); 134321936Shselasky char *token = strtok(str, ","); 135321936Shselasky for (i = 0; i < MAX_SWITCH_PORTS && token; i++) { 136321936Shselasky num = strtoul(token, NULL, 0); 137321936Shselasky if (num > 0 && num < MAX_SWITCH_PORTS) 138321936Shselasky ports_array[num] = 1; 139321936Shselasky 140321936Shselasky token = strtok(NULL, ","); 141321936Shselasky } 142321936Shselasky free(str); 143321936Shselasky return 0; 144321936Shselasky} 145321936Shselasky 146321936Shselaskyvoid port_mirror_route(ib_portid_t * portid, int query, int clear) 147321936Shselasky{ 148321936Shselasky int mirror_type; 149321936Shselasky 150321936Shselasky memset(&buf, 0, sizeof(buf)); 151321936Shselasky 152321936Shselasky if (clear) { 153321936Shselasky if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 154321936Shselasky IBEXIT("Clear port mirror route set failed"); 155321936Shselasky return; 156321936Shselasky } 157321936Shselasky 158321936Shselasky if (query) { 159321936Shselasky if (!smp_query_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 160321936Shselasky IBEXIT("Read port mirror route get failed"); 161321936Shselasky mad_decode_field(buf, IB_PMR_MT_F, &mirror_type); 162321936Shselasky if (mirror_type == MT_MIRROR_ENCAP && mirror_dlid == 0) 163321936Shselasky mad_decode_field(buf, IB_PMR_LRH_DLID_F, &mirror_dlid); 164321936Shselasky if (mirror_type == MT_MIRROR_NATIVE && mirror_dport == 0) 165321936Shselasky mad_decode_field(buf, IB_PMR_NM_PORT_F, &mirror_dport); 166321936Shselasky goto Exit; 167321936Shselasky } 168321936Shselasky 169321936Shselasky /* Port Mirror Route */ 170321936Shselasky mad_set_field(buf, 0, IB_PMR_ENCAP_RAW_ETH_TYPE_F, PM_ENCAP_ETHERTYPE); 171321936Shselasky 172321936Shselasky if (mirror_dlid == 0) { 173321936Shselasky /* Can not truncate mirrored packets in local mode */ 174321936Shselasky mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, 0xfff); 175321936Shselasky mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_NATIVE); 176321936Shselasky mad_set_field(buf, 0, IB_PMR_NM_PORT_F, mirror_dport); 177321936Shselasky } 178321936Shselasky else { /* remote mirror */ 179321936Shselasky /* convert size to dwords */ 180321936Shselasky packet_size = packet_size / 4 + 1; 181321936Shselasky mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, packet_size); 182321936Shselasky mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_ENCAP); 183321936Shselasky mad_set_field(buf, 0, IB_PMR_LRH_SL_F, mirror_sl); 184321936Shselasky mad_set_field(buf, 0, IB_PMR_LRH_DLID_F, mirror_dlid); 185321936Shselasky mad_set_field(buf, 0, IB_PMR_LRH_SLID_F, portid->lid); 186321936Shselasky } 187321936Shselasky 188321936Shselasky if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport)) 189321936Shselasky IBEXIT("port mirror route set failed"); 190321936Shselasky 191321936ShselaskyExit: 192321936Shselasky mad_dump_portmirror_route(str, sizeof str, buf, sizeof buf); 193321936Shselasky printf("Port Mirror Route\n%s", str); 194321936Shselasky} 195321936Shselasky 196321936Shselaskyvoid port_mirror_ports(ib_portid_t * portid, int query, int clear) 197321936Shselasky{ 198321936Shselasky int p, rqf, tqf, rqv, tqv; 199321936Shselasky 200321936Shselasky memset(&buf, 0, sizeof(buf)); 201321936Shselasky 202321936Shselasky if (clear) { 203321936Shselasky if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 204321936Shselasky IBEXIT("Clear port mirror ports set failed"); 205321936Shselasky return; 206321936Shselasky } 207321936Shselasky 208321936Shselasky if (query) { 209321936Shselasky if (!smp_query_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 210321936Shselasky IBEXIT("Read port mirror ports get failed"); 211321936Shselasky goto Exit; 212321936Shselasky } 213321936Shselasky 214321936Shselasky /* Port Mirror Ports */ 215321936Shselasky rqf = IB_PMP_RQ_1_F; 216321936Shselasky tqf = IB_PMP_TQ_1_F; 217321936Shselasky 218321936Shselasky for (p = 1; p < MAX_SWITCH_PORTS; p++) { 219321936Shselasky rqv = mrx_ports[p] ? MP_MIRROR_ALWAYS : MP_DISABLED; 220321936Shselasky tqv = mtx_ports[p] ? MP_MIRROR_ALWAYS : MT_MIRROR_AS_RX; 221321936Shselasky mad_set_field(buf, 0, rqf, rqv); 222321936Shselasky mad_set_field(buf, 0, tqf, tqv); 223321936Shselasky rqf += 2; 224321936Shselasky tqf += 2; 225321936Shselasky } 226321936Shselasky 227321936Shselasky if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport)) 228321936Shselasky IBEXIT("port mirror ports set failed"); 229321936Shselasky 230321936ShselaskyExit: 231321936Shselasky mad_dump_portmirror_ports(str, sizeof str, buf, sizeof buf); 232321936Shselasky printf("Port Mirror Ports\n%s", str); 233321936Shselasky} 234321936Shselasky 235321936Shselaskyint get_out_port(ib_portid_t* portid) 236321936Shselasky{ 237321936Shselasky int block; 238321936Shselasky int offset; 239321936Shselasky 240321936Shselasky if (mirror_dlid) { 241321936Shselasky block = mirror_dlid / IB_SMP_DATA_SIZE; 242321936Shselasky offset = mirror_dlid - block * IB_SMP_DATA_SIZE; 243321936Shselasky /* get out port from lft */ 244321936Shselasky if (!smp_query_via(buf, portid, IB_ATTR_LINEARFORWTBL, block, 0, srcport)) 245321936Shselasky IBEXIT("linear forwarding table get failed"); 246321936Shselasky block = mirror_dlid / IB_SMP_DATA_SIZE; 247321936Shselasky offset = mirror_dlid - block * IB_SMP_DATA_SIZE; 248321936Shselasky return buf[offset]; 249321936Shselasky } 250321936Shselasky else 251321936Shselasky return mirror_dport; 252321936Shselasky} 253321936Shselasky 254321936Shselaskyint get_peer(ib_portid_t* portid, int outport, int* peerlid, int* peerport) 255321936Shselasky{ 256321936Shselasky ib_portid_t selfportid = { 0 }; 257321936Shselasky ib_portid_t peerportid = { 0 }; 258321936Shselasky int selfport = 0; 259321936Shselasky 260321936Shselasky /* set peerportid for peer port */ 261321936Shselasky memcpy(&peerportid, portid, sizeof(peerportid)); 262321936Shselasky peerportid.drpath.cnt = 1; 263321936Shselasky peerportid.drpath.p[1] = outport; 264321936Shselasky if (ib_resolve_self_via(&selfportid, &selfport, 0, srcport) < 0) 265321936Shselasky IBEXIT("failed to resolve self portid"); 266321936Shselasky peerportid.drpath.drslid = (uint16_t) selfportid.lid; 267321936Shselasky peerportid.drpath.drdlid = 0xffff; 268321936Shselasky if (!smp_query_via(buf, &peerportid, IB_ATTR_PORT_INFO, 0, 0, srcport)) 269321936Shselasky IBEXIT("get peer portinfo failed - unable to configure lossy\n"); 270321936Shselasky 271321936Shselasky mad_decode_field(buf, IB_PORT_LID_F, peerlid); 272321936Shselasky mad_decode_field(buf, IB_PORT_LOCAL_PORT_F, peerport); 273321936Shselasky 274321936Shselasky return 0; 275321936Shselasky} 276321936Shselasky 277321936Shselaskyint get_mirror_vl(ib_portid_t* portid, int outport) 278321936Shselasky{ 279321936Shselasky ib_slvl_table_t * p_slvl_tbl; 280321936Shselasky int portnum; 281321936Shselasky int vl; 282321936Shselasky 283321936Shselasky /* hack; assume all sl2vl mappings are the same for any in port and outport */ 284321936Shselasky portnum = (1 << 8) | outport; 285321936Shselasky 286321936Shselasky /* get sl2vl mapping */ 287321936Shselasky if (!smp_query_via(buf, portid, IB_ATTR_SLVL_TABLE, portnum, 0, srcport)) 288321936Shselasky IBEXIT("slvl query failed"); 289321936Shselasky 290321936Shselasky p_slvl_tbl = (ib_slvl_table_t *) buf; 291321936Shselasky vl = ib_slvl_table_get(p_slvl_tbl, mirror_sl); 292321936Shselasky printf("mirror_sl %d, mirror_vl %d\n", mirror_sl, vl); 293321936Shselasky return vl; 294321936Shselasky} 295321936Shselasky 296321936Shselaskyint lossy_config(ib_portid_t* portid, int query, int clear) 297321936Shselasky{ 298321936Shselasky int outport; 299321936Shselasky int peerport; 300321936Shselasky int attr_mod; 301321936Shselasky uint8_t mirror_vl; 302321936Shselasky ib_portid_t peerportid = { 0 }; 303321936Shselasky ib_portid_t * p_portid; 304321936Shselasky lossy_config_t local_lossy_cfg; 305321936Shselasky lossy_config_t peer_lossy_cfg; 306321936Shselasky lossy_config_t lossy_cfg; 307321936Shselasky 308321936Shselasky outport = get_out_port(portid); 309321936Shselasky if (outport == 0) 310321936Shselasky IBEXIT("get_out_port failed, mirror_dlid and mirror_dport are 0"); 311321936Shselasky 312321936Shselasky get_peer(portid, outport, &peerportid.lid, &peerport); 313321936Shselasky 314321936Shselasky printf("local lid %d / port %d\n", portid->lid, outport); 315321936Shselasky printf("peer lid %d / port %d\n", peerportid.lid, peerport); 316321936Shselasky 317321936Shselasky mirror_vl = get_mirror_vl(portid, outport); 318321936Shselasky 319321936Shselasky /* read local lossy configuration */ 320321936Shselasky if (!smp_query_via(buf, portid, ATTRID_LOSSY_CFG, outport, 0, srcport)) 321321936Shselasky IBEXIT("get lossy config from lid %d port %d failed - not supported\n", 322321936Shselasky portid->lid, outport); 323321936Shselasky memcpy(&local_lossy_cfg, buf, sizeof(local_lossy_cfg)); 324321936Shselasky 325321936Shselasky /* read peer lossy configuration */ 326321936Shselasky if (!smp_query_via(buf, &peerportid, ATTRID_LOSSY_CFG, peerport, 0, srcport)) 327321936Shselasky IBEXIT("get lossy config from lid %d port %d failed - not supported\n", 328321936Shselasky peerportid.lid, peerport); 329321936Shselasky memcpy(&peer_lossy_cfg, buf, sizeof(peer_lossy_cfg)); 330321936Shselasky 331321936Shselasky if (query) { 332321936Shselasky printf("local port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n", 333321936Shselasky portid->lid, outport, 334321936Shselasky ntohs(local_lossy_cfg.ignore_buffer_mask), ntohs(local_lossy_cfg.ignore_credit_mask)); 335321936Shselasky printf("peer port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n", 336321936Shselasky peerportid.lid, peerport, 337321936Shselasky ntohs(peer_lossy_cfg.ignore_buffer_mask), ntohs(peer_lossy_cfg.ignore_credit_mask)); 338321936Shselasky return 0; 339321936Shselasky } 340321936Shselasky 341321936Shselasky /* 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 */ 342321936Shselasky /* ignore Buf Overrun ignore Credits */ 343321936Shselasky /* when mirror activated set ignore buffer overrun on peer port */ 344321936Shselasky /* when mirror is de-activated clear ignore credits on local port */ 345321936Shselasky memset(&buf, 0, sizeof(buf)); 346321936Shselasky if (clear) { 347321936Shselasky p_portid = portid; 348321936Shselasky attr_mod = outport; 349321936Shselasky } else { 350321936Shselasky /* set buffer overrun on peer port */ 351321936Shselasky p_portid = &peerportid; 352321936Shselasky attr_mod = peerport; 353321936Shselasky lossy_cfg.ignore_buffer_mask = htons(1<<mirror_vl); 354321936Shselasky lossy_cfg.ignore_credit_mask = 0; 355321936Shselasky memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg)); 356321936Shselasky } 357321936Shselasky if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport)) 358321936Shselasky IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid); 359321936Shselasky 360321936Shselasky /* when mirror activated set ignore credit on local port */ 361321936Shselasky /* when mirror de-activated clear buffer overrun on peer */ 362321936Shselasky memset(&buf, 0, sizeof(buf)); 363321936Shselasky if (clear) { 364321936Shselasky p_portid = &peerportid; 365321936Shselasky attr_mod = peerport; 366321936Shselasky } else { 367321936Shselasky /* set ignore credit on local port */ 368321936Shselasky p_portid = portid; 369321936Shselasky attr_mod = outport; 370321936Shselasky lossy_cfg.ignore_credit_mask = htons(1<<mirror_vl); 371321936Shselasky lossy_cfg.ignore_buffer_mask = 0; 372321936Shselasky memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg)); 373321936Shselasky } 374321936Shselasky if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport)) 375321936Shselasky IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid); 376321936Shselasky 377321936Shselasky return 0; 378321936Shselasky} 379321936Shselasky 380321936Shselaskyint mirror_config(ib_portid_t* portid, int query, int clear) 381321936Shselasky{ 382321936Shselasky port_mirror_route(portid, query, clear); 383321936Shselasky /* port_mirror_filter(portid, query, clear); */ 384321936Shselasky port_mirror_ports(portid, query, clear); 385321936Shselasky 386321936Shselasky return 0; 387321936Shselasky} 388321936Shselasky 389321936Shselaskystatic int process_opt(void *context, int ch, char *optarg) 390321936Shselasky{ 391321936Shselasky switch (ch) { 392321936Shselasky case 'p': 393321936Shselasky mirror_dport = strtoul(optarg, NULL, 0); 394321936Shselasky break; 395321936Shselasky case 'S': 396321936Shselasky packet_size = strtoul(optarg, NULL, 0); 397321936Shselasky break; 398321936Shselasky case 'l': 399321936Shselasky mirror_sl = strtoul(optarg, NULL, 0); 400321936Shselasky break; 401321936Shselasky case 'L': 402321936Shselasky mirror_dlid = strtoul(optarg, NULL, 0); 403321936Shselasky break; 404321936Shselasky case 'R': 405321936Shselasky set_mrx = 1; 406321936Shselasky if (-1 == parse_ports(optarg, mrx_ports)) 407321936Shselasky return -1; 408321936Shselasky break; 409321936Shselasky case 'T': 410321936Shselasky set_mtx = 1; 411321936Shselasky if (-1 == parse_ports(optarg, mtx_ports)) 412321936Shselasky return -1; 413321936Shselasky break; 414321936Shselasky case 'D': 415321936Shselasky mirror_clear = 1; 416321936Shselasky break; 417321936Shselasky case 'Q': 418321936Shselasky mirror_query = 1; 419321936Shselasky break; 420321936Shselasky case 'y': 421321936Shselasky lossy_set = 1; 422321936Shselasky break; 423321936Shselasky default: 424321936Shselasky return -1; 425321936Shselasky } 426321936Shselasky return 0; 427321936Shselasky} 428321936Shselasky 429321936Shselaskyint main(int argc, char **argv) 430321936Shselasky{ 431321936Shselasky int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, 432321936Shselasky IB_MLX_VENDOR_CLASS 433321936Shselasky }; 434321936Shselasky ib_portid_t portid = { 0 }; 435321936Shselasky int port = 0; 436321936Shselasky ib_vendor_call_t call; 437321936Shselasky is3_general_info_t *gi; 438321936Shselasky uint32_t fw_ver; 439321936Shselasky char op_str[32]; 440321936Shselasky 441321936Shselasky const struct ibdiag_opt opts[] = { 442321936Shselasky {"dport", 'p', 1, "<port>", "set mirror destination port"}, 443321936Shselasky {"dlid", 'L', 1, "<dlid>", "set mirror destination LID"}, 444321936Shselasky {"sl", 'l', 1, "<sl>", "set mirror SL"}, 445321936Shselasky {"size", 'S', 1, "<size>", "set packet size"}, 446321936Shselasky {"rxports", 'R', 1, NULL, "mirror receive port list"}, 447321936Shselasky {"txports", 'T', 1, NULL, "mirror transmit port list"}, 448321936Shselasky {"clear", 'D', 0, NULL, "clear ports mirroring"}, 449321936Shselasky {"query", 'Q', 0, NULL, "read mirror configuration"}, 450321936Shselasky {"lossy", 'y', 0, NULL, "set lossy configuration on out port"}, 451321936Shselasky {0} 452321936Shselasky }; 453321936Shselasky 454321936Shselasky char usage_args[] = "<lid>"; 455321936Shselasky const char *usage_examples[] = { 456321936Shselasky "-R 1,2,3 -T 2,5 -l1 -L25 -S100 <lid>\t# configure mirror ports", 457321936Shselasky "-D <lid> \t# clear mirror configuration", 458321936Shselasky "-Q <lid>\t# read mirror configuration", 459321936Shselasky NULL 460321936Shselasky }; 461321936Shselasky 462321936Shselasky ibdiag_process_opts(argc, argv, NULL, "GDLs", opts, process_opt, 463321936Shselasky usage_args, usage_examples); 464321936Shselasky 465321936Shselasky argc -= optind; 466321936Shselasky argv += optind; 467321936Shselasky 468321936Shselasky if (argc == 0) 469321936Shselasky ibdiag_show_usage(); 470321936Shselasky 471321936Shselasky srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4); 472321936Shselasky if (!srcport) 473321936Shselasky IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port); 474321936Shselasky 475321936Shselasky if (argc) { 476321936Shselasky if (ib_resolve_portid_str_via(&portid, argv[0], ibd_dest_type, 477321936Shselasky ibd_sm_id, srcport) < 0) 478321936Shselasky IBEXIT("can't resolve destination port %s", argv[0]); 479321936Shselasky } 480321936Shselasky 481321936Shselasky 482321936Shselasky memset(&buf, 0, sizeof(buf)); 483321936Shselasky memset(&call, 0, sizeof(call)); 484321936Shselasky call.mgmt_class = IB_MLX_VENDOR_CLASS; 485321936Shselasky call.method = IB_MAD_METHOD_GET; 486321936Shselasky call.timeout = ibd_timeout; 487321936Shselasky call.attrid = IB_MLX_IS3_GENERAL_INFO; 488321936Shselasky if (!ib_vendor_call_via(&buf, &portid, &call, srcport)) 489321936Shselasky IBEXIT("failed to read vendor info"); 490321936Shselasky gi = (is3_general_info_t *) & buf; 491321936Shselasky if (ntohs(gi->hw_info.device_id) != 0x1b3) 492321936Shselasky IBEXIT("device id 0x%x does not support mirroring", ntohs(gi->hw_info.device_id)); 493321936Shselasky 494321936Shselasky fw_ver = gi->fw_info.major * 100000 + gi->fw_info.minor * 1000 + gi->fw_info.sub_minor; 495321936Shselasky printf("FW version %08d\n", fw_ver); 496321936Shselasky if (lossy_set && fw_ver < 704000) 497321936Shselasky IBEXIT("FW version %d.%d.%d does not support lossy config", 498321936Shselasky gi->fw_info.major, gi->fw_info.minor, gi->fw_info.sub_minor); 499321936Shselasky 500321936Shselasky if (ibdebug) { 501321936Shselasky printf( "switch_lid = %d\n" 502321936Shselasky "mirror_clear = %d\n" 503321936Shselasky "mirror_dlid = %d\n" 504321936Shselasky "mirror_sl = %d\n" 505321936Shselasky "mirror_port = %d\n", 506321936Shselasky portid.lid, mirror_clear, mirror_dlid, 507321936Shselasky mirror_sl, mirror_dport); 508321936Shselasky 509321936Shselasky for (port = 1; port < MAX_SWITCH_PORTS; port++) { 510321936Shselasky if (mtx_ports[port]) 511321936Shselasky printf("TX: %d\n",port); 512321936Shselasky else if(mrx_ports[port]) 513321936Shselasky printf("RX: %d\n",port); 514321936Shselasky } 515321936Shselasky } 516321936Shselasky 517321936Shselasky if (mirror_clear) 518321936Shselasky strcpy(op_str, "Clear"); 519321936Shselasky else if (mirror_query) 520321936Shselasky strcpy(op_str, "Read"); 521321936Shselasky else if (!mirror_dport && !mirror_dlid) 522321936Shselasky IBEXIT("Mirror remote LID and local port are zero"); 523321936Shselasky else if (!set_mtx && !set_mrx) 524321936Shselasky IBEXIT("Mirror Rx and Tx ports not selected"); 525321936Shselasky else 526321936Shselasky strcpy(op_str, "Set"); 527321936Shselasky 528321936Shselasky printf("\n%s Mirror Configuration\n", op_str); 529321936Shselasky mirror_config(&portid, mirror_query, mirror_clear); 530321936Shselasky 531321936Shselasky if (lossy_set) { 532321936Shselasky printf("%s Lossy Configuration\n", op_str); 533321936Shselasky lossy_config(&portid, mirror_query, mirror_clear); 534321936Shselasky } 535321936Shselasky 536321936Shselasky mad_rpc_close_port(srcport); 537321936Shselasky exit(0); 538321936Shselasky} 539