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
parse_ports(char * ports_str,char * ports_array)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
port_mirror_route(ib_portid_t * portid,int query,int clear)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
port_mirror_ports(ib_portid_t * portid,int query,int clear)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
get_out_port(ib_portid_t * portid)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
get_peer(ib_portid_t * portid,int outport,int * peerlid,int * peerport)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
get_mirror_vl(ib_portid_t * portid,int outport)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
lossy_config(ib_portid_t * portid,int query,int clear)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
mirror_config(ib_portid_t * portid,int query,int clear)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
process_opt(void * context,int ch,char * optarg)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
main(int argc,char ** argv)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