xref: /freebsd/contrib/ofed/infiniband-diags/src/ibmirror.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
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