1219820Sjeff/*
2219820Sjeff * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff#ifdef OSM_VENDOR_INTF_MTL
37219820Sjeff/*
38219820Sjeff * Abstract:
39219820Sjeff *    Implementation of InformInfo testing flow..
40219820Sjeff *    Top level is osmt_run_inform_info_flow:
41219820Sjeff *     osmt_bind_inform_qp
42219820Sjeff *     osmt_reg_unreg_inform_info
43219820Sjeff *     osmt_send_trap_wait_for_forward
44219820Sjeff *
45219820Sjeff */
46219820Sjeff
47219820Sjeff#include <unistd.h>
48219820Sjeff#include <stdio.h>
49219820Sjeff#include <stdlib.h>
50219820Sjeff#include <string.h>
51219820Sjeff#include <complib/cl_debug.h>
52219820Sjeff#include <vendor/osm_vendor_mlx_hca.h>
53219820Sjeff#include "osmtest.h"
54219820Sjeff#include "osmt_inform.h"
55219820Sjeff
56219820Sjeff/*
57219820Sjeff * Prepare an asynchronous QP (rcv) for sending inform info and
58219820Sjeff * handling the incoming reports.
59219820Sjeff *
60219820Sjeff */
61219820Sjeffib_api_status_t
62219820Sjeffosmt_bind_inform_qp(IN osmtest_t * const p_osmt, OUT osmt_qp_ctx_t * p_qp_ctx)
63219820Sjeff{
64219820Sjeff	ib_net64_t port_guid;
65219820Sjeff	VAPI_hca_hndl_t hca_hndl;
66219820Sjeff	VAPI_hca_id_t hca_id;
67219820Sjeff	uint32_t port_num;
68219820Sjeff	VAPI_ret_t vapi_ret;
69219820Sjeff	IB_MGT_ret_t mgt_ret;
70219820Sjeff	uint8_t hca_index;
71219820Sjeff	osm_log_t *p_log = &p_osmt->log;
72219820Sjeff	ib_api_status_t status = IB_SUCCESS;
73219820Sjeff
74219820Sjeff	OSM_LOG_ENTER(p_log);
75219820Sjeff
76219820Sjeff	port_guid = p_osmt->local_port.port_guid;
77219820Sjeff
78219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n",
79219820Sjeff		cl_ntoh64(port_guid));
80219820Sjeff
81219820Sjeff	/* obtain the hca name and port num from the guid */
82219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG,
83219820Sjeff		"Finding CA and Port that owns port guid 0x%" PRIx64 "\n",
84219820Sjeff		port_guid);
85219820Sjeff
86219820Sjeff	mgt_ret =
87219820Sjeff	    osm_vendor_get_guid_ca_and_port(p_osmt->p_vendor,
88219820Sjeff					    port_guid,
89219820Sjeff					    &hca_hndl,
90219820Sjeff					    &hca_id[0], &hca_index, &port_num);
91219820Sjeff	if (mgt_ret != IB_MGT_OK) {
92219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0109: "
93219820Sjeff			"Unable to obtain CA and port (%d).\n");
94219820Sjeff		status = IB_ERROR;
95219820Sjeff		goto Exit;
96219820Sjeff	}
97219820Sjeff#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000
98219820Sjeff
99219820Sjeff	strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id));
100219820Sjeff	p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl;
101219820Sjeff	p_qp_ctx->qp_bind_hndl.port_num = port_num;
102219820Sjeff	p_qp_ctx->qp_bind_hndl.max_outs_sq = 10;
103219820Sjeff	p_qp_ctx->qp_bind_hndl.max_outs_rq = 10;
104219820Sjeff	p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY;
105219820Sjeff
106219820Sjeff	vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl);
107219820Sjeff	if (vapi_ret != VAPI_OK) {
108219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0114: "
109219820Sjeff			"Error initializing QP.\n");
110219820Sjeff		status = IB_ERROR;
111219820Sjeff		goto Exit;
112219820Sjeff	}
113219820Sjeff
114219820Sjeff	/* we use the pre-allocated buffers for send and receive :
115219820Sjeff	   send from buf[0]
116219820Sjeff	   receive from buf[2]
117219820Sjeff	 */
118219820Sjeff	p_qp_ctx->p_send_buf =
119219820Sjeff	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN;
120219820Sjeff	p_qp_ctx->p_recv_buf =
121219820Sjeff	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN +
122219820Sjeff							      MAD_BLOCK_SIZE);
123219820Sjeff
124219820Sjeff	/* Need to clear assigned memory of p_send_buf - before using it to send any data */
125219820Sjeff	memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE);
126219820Sjeff
127219820Sjeff	status = IB_SUCCESS;
128219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Initialized QP:0x%X in VAPI Mode\n",
129219820Sjeff		p_qp_ctx->qp_bind_hndl.qp_id);
130219820Sjeff
131219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to IB_MGT SMI\n");
132219820Sjeff
133219820Sjeff	/* we also need a QP0 handle for sending packets */
134219820Sjeff	mgt_ret = IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI,
135219820Sjeff				    &(p_qp_ctx->ib_mgt_qp0_handle));
136219820Sjeff	if (IB_MGT_OK != mgt_ret) {
137219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0115: "
138219820Sjeff			"Error obtaining IB_MGT handle to SMI\n");
139219820Sjeff		status = IB_ERROR;
140219820Sjeff		goto Exit;
141219820Sjeff	}
142219820Sjeff
143219820SjeffExit:
144219820Sjeff	OSM_LOG_EXIT(p_log);
145219820Sjeff	return status;
146219820Sjeff}
147219820Sjeff
148219820Sjeff/*
149219820Sjeff * Close the QP
150219820Sjeff */
151219820Sjeffvoid
152219820Sjeffosmt_unbind_inform_qp(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
153219820Sjeff{
154219820Sjeff	osm_log_t *p_log = &p_osmt->log;
155219820Sjeff
156219820Sjeff	OSM_LOG_ENTER(p_log);
157219820Sjeff
158219820Sjeff	osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl);
159219820Sjeff
160219820Sjeff	IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle);
161219820Sjeff
162219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Unbind QP handles\n");
163219820Sjeff	OSM_LOG_EXIT(&p_osmt->log);
164219820Sjeff}
165219820Sjeff
166219820Sjeff/*
167219820Sjeff * Register/Unregister to receive the given InformInfo
168219820Sjeff *
169219820Sjeff * Uses the qp context to send the inform info mad.
170219820Sjeff * Wait for GetResp(InformInfoResp)
171219820Sjeff *
172219820Sjeff */
173219820Sjeffib_api_status_t
174219820Sjeffosmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
175219820Sjeff			   IN osmt_qp_ctx_t * p_qp_ctx,
176219820Sjeff			   IN ib_inform_info_t * p_inform_info,
177219820Sjeff			   IN uint8_t reg_flag)
178219820Sjeff{
179219820Sjeff	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
180219820Sjeff	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
181219820Sjeff	VAPI_ret_t vapi_ret;
182219820Sjeff	VAPI_wc_desc_t wc_desc;
183219820Sjeff	VAPI_ud_av_hndl_t avh;
184219820Sjeff	static VAPI_wr_id_t wrid = 16198;
185219820Sjeff	osm_log_t *p_log = &p_osmt->log;
186219820Sjeff	ib_api_status_t status = IB_SUCCESS;
187219820Sjeff
188219820Sjeff	OSM_LOG_ENTER(&p_osmt->log);
189219820Sjeff
190219820Sjeff	/* init the MAD */
191219820Sjeff	ib_mad_init_new((ib_mad_t *) p_sa_mad,
192219820Sjeff			IB_MCLASS_SUBN_ADM,
193219820Sjeff			(uint8_t) 2,
194219820Sjeff			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
195219820Sjeff	wrid++;
196219820Sjeff	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;
197219820Sjeff
198219820Sjeff	/* copy the reference inform info */
199219820Sjeff	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));
200219820Sjeff
201219820Sjeff	if (reg_flag) {
202219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
203219820Sjeff			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
204219820Sjeff			p_ii->lid_range_begin, p_ii->lid_range_end,
205219820Sjeff			p_ii->g_or_v.generic.trap_num);
206219820Sjeff	} else {
207219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
208219820Sjeff			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
209219820Sjeff			p_ii->lid_range_begin, p_ii->lid_range_end);
210219820Sjeff	}
211219820Sjeff
212219820Sjeff	/* set the subscribe bit */
213219820Sjeff	if (reg_flag) {
214219820Sjeff		p_ii->subscribe = 1;
215219820Sjeff	} else {
216219820Sjeff		p_ii->subscribe = 0;
217219820Sjeff		/*
218219820Sjeff		 * we need to set the QPN on the mad if we unsubscribe:
219219820Sjeff		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
220219820Sjeff		 */
221219820Sjeff		ib_inform_info_set_qpn(p_ii,
222219820Sjeff				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
223219820Sjeff						 qp_num));
224219820Sjeff	}
225219820Sjeff
226219820Sjeff	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);
227219820Sjeff
228219820Sjeff	/* --------------------- PREP ------------------------- */
229219820Sjeff	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  but we need only one mad at a time */
230219820Sjeff					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
231219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
232219820Sjeff			"Error posting recv bufs\n");
233219820Sjeff		status = IB_ERROR;
234219820Sjeff		goto Exit;
235219820Sjeff	}
236219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
237219820Sjeff
238219820Sjeff	vapi_ret =
239219820Sjeff	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
240219820Sjeff			       p_osmt->local_port.sm_lid, &avh);
241219820Sjeff	if (vapi_ret != VAPI_OK) {
242219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
243219820Sjeff			"Error Preparing AVH (%s)\n",
244219820Sjeff			VAPI_strerror_sym(vapi_ret));
245219820Sjeff		status = IB_ERROR;
246219820Sjeff		goto Exit;
247219820Sjeff	}
248219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
249219820Sjeff
250219820Sjeff	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
251219820Sjeff		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
252219820Sjeff				OSM_LOG_DEBUG);
253219820Sjeff#if 0
254219820Sjeff		for (i = 56; i < 253; i++) {
255219820Sjeff			if (i % 8 == 0) {
256219820Sjeff				printf("\n %d : ", i);
257219820Sjeff			}
258219820Sjeff			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
259219820Sjeff		}
260219820Sjeff#endif
261219820Sjeff		printf("\n");
262219820Sjeff	}
263219820Sjeff
264219820Sjeff	/* --------------------- SEND ------------------------- */
265219820Sjeff	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
266219820Sjeff				     0,	/*  SL is 0 */
267219820Sjeff				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
268219820Sjeff				     avh);
269219820Sjeff	if (vapi_ret != VAPI_OK) {
270219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
271219820Sjeff			"Error sending mad (%s)\n",
272219820Sjeff			VAPI_strerror_sym(vapi_ret));
273219820Sjeff		status = IB_ERROR;
274219820Sjeff		goto Exit;
275219820Sjeff	}
276219820Sjeff
277219820Sjeff	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
278219820Sjeff					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
279219820Sjeff					 &wc_desc, 20, 10000, NULL);
280219820Sjeff	if (vapi_ret != VAPI_OK) {
281219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
282219820Sjeff			"Error getting send completion (%s)\n",
283219820Sjeff			VAPI_strerror_sym(vapi_ret));
284219820Sjeff		status = IB_ERROR;
285219820Sjeff		goto Exit;
286219820Sjeff	}
287219820Sjeff
288219820Sjeff	if (wc_desc.status != VAPI_SUCCESS) {
289219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
290219820Sjeff			"Error on send completion (%s) (%d)\n",
291219820Sjeff			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
292219820Sjeff		status = IB_ERROR;
293219820Sjeff		goto Exit;
294219820Sjeff	}
295219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");
296219820Sjeff
297219820Sjeff	/* --------------------- RECV ------------------------- */
298219820Sjeff	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
299219820Sjeff					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
300219820Sjeff					 &wc_desc, 20, 10000, &avh);
301219820Sjeff	if (vapi_ret != VAPI_SUCCESS) {
302219820Sjeff		if (vapi_ret == VAPI_CQ_EMPTY) {
303219820Sjeff			status = IB_TIMEOUT;
304219820Sjeff		} else {
305219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
306219820Sjeff				"Error receiving mad (%s)\n",
307219820Sjeff				VAPI_strerror_sym(vapi_ret));
308219820Sjeff			status = IB_ERROR;
309219820Sjeff		}
310219820Sjeff		goto Exit;
311219820Sjeff	}
312219820Sjeff
313219820Sjeff	/* check to see if successful - by examination of the subscribe bit */
314219820Sjeff	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
315219820Sjeff
316219820Sjeff	if (p_sa_mad->status != IB_SUCCESS) {
317219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
318219820Sjeff			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
319219820Sjeff		status = IB_REMOTE_ERROR;
320219820Sjeff		goto Exit;
321219820Sjeff	}
322219820Sjeff
323219820Sjeff	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
324219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
325219820Sjeff			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
326219820Sjeff			p_sa_mad->method);
327219820Sjeff		status = IB_REMOTE_ERROR;
328219820Sjeff		goto Exit;
329219820Sjeff	}
330219820Sjeff
331219820Sjeff	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
332219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
333219820Sjeff			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
334219820Sjeff			cl_ntoh16(p_sa_mad->attr_id));
335219820Sjeff		status = IB_REMOTE_ERROR;
336219820Sjeff		goto Exit;
337219820Sjeff	}
338219820Sjeff
339219820Sjeff	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
340219820Sjeff	if (!p_ii->subscribe) {
341219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
342219820Sjeff			"Subscribe/Unsubscribe Failed\n");
343219820Sjeff		status = IB_REMOTE_ERROR;
344219820Sjeff	}
345219820Sjeff
346219820SjeffExit:
347219820Sjeff	OSM_LOG_EXIT(&p_osmt->log);
348219820Sjeff	return status;
349219820Sjeff}
350219820Sjeff
351219820Sjeff/*
352219820Sjeff * Send a trap (Subn LID Route) Trap(Notice) through the regular
353219820Sjeff * connection QP connection (targeted at QP0)
354219820Sjeff *
355219820Sjeff * Wait for the trap repress
356219820Sjeff */
357219820Sjeffib_api_status_t
358219820Sjeffosmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,
359219820Sjeff				IN osmt_qp_ctx_t * p_qp_ctx)
360219820Sjeff{
361219820Sjeff	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
362219820Sjeff	ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
363219820Sjeff	ib_sa_mad_t *p_sa_mad;
364219820Sjeff	IB_MGT_ret_t mgt_res;
365219820Sjeff	VAPI_ret_t vapi_ret;
366219820Sjeff	VAPI_wc_desc_t wc_desc;
367219820Sjeff	VAPI_ud_av_hndl_t avh;
368219820Sjeff	IB_ud_av_t av;
369219820Sjeff	static VAPI_wr_id_t wrid = 2222;
370219820Sjeff	osm_log_t *p_log = &p_osmt->log;
371219820Sjeff	ib_api_status_t status = IB_SUCCESS;
372219820Sjeff
373219820Sjeff	OSM_LOG_ENTER(p_log);
374219820Sjeff
375219820Sjeff	OSM_LOG(p_log, OSM_LOG_INFO,
376219820Sjeff		"Sending Traps to QP0 of SA LID:0x%X\n",
377219820Sjeff		p_osmt->local_port.sm_lid);
378219820Sjeff
379219820Sjeff	/* init the MAD */
380219820Sjeff	memset(p_smp, 0, sizeof(ib_smp_t));
381219820Sjeff	ib_mad_init_new((ib_mad_t *) p_smp,
382219820Sjeff			IB_MCLASS_SUBN_LID,
383219820Sjeff			(uint8_t) 2,
384219820Sjeff			IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0);
385219820Sjeff
386219820Sjeff	wrid++;
387219820Sjeff	p_smp->attr_id = IB_MAD_ATTR_NOTICE;
388219820Sjeff
389219820Sjeff	/* prepare the notice */
390219820Sjeff	p_ntc->generic_type = 0x82;	/*  generic, type = 2 */
391219820Sjeff	ib_notice_set_prod_type_ho(p_ntc, 1);
392219820Sjeff	p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
393219820Sjeff	p_ntc->issuer_lid = cl_hton16(2);
394219820Sjeff
395219820Sjeff	/* --------------------- PREP ------------------------- */
396219820Sjeff	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  we need to receive both trap repress and report */
397219820Sjeff					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
398219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: "
399219820Sjeff			"Error posting recv bufs\n");
400219820Sjeff		status = IB_ERROR;
401219820Sjeff		goto Exit;
402219820Sjeff	}
403219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
404219820Sjeff
405219820Sjeff	av.dlid = p_osmt->local_port.sm_lid;
406219820Sjeff	av.grh_flag = FALSE;
407219820Sjeff
408219820Sjeff	/*  EZ: returned in HACK: use constants */
409219820Sjeff	av.static_rate = 0;	/*  p_mad_addr->static_rate; */
410219820Sjeff	av.src_path_bits = 1;	/*  p_mad_addr->path_bits; */
411219820Sjeff	av.sl = 0;		/*  p_mad_addr->addr_type.gsi.service_level; */
412219820Sjeff
413219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG,
414219820Sjeff		"av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n",
415219820Sjeff		cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits);
416219820Sjeff
417219820Sjeff	/* send it */
418219820Sjeff	mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp,	/*  actual payload */
419219820Sjeff				  &av,	/*  address vector */
420219820Sjeff				  wrid,	/*  casting the mad wrapper pointer for err cb */
421219820Sjeff				  p_osmt->opt.transaction_timeout);
422219820Sjeff	if (mgt_res != IB_MGT_OK) {
423219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: "
424219820Sjeff			"Error sending mad (%d)\n", mgt_res);
425219820Sjeff		status = IB_ERROR;
426219820Sjeff		goto Exit;
427219820Sjeff	}
428219820Sjeff
429219820Sjeff	vapi_ret =
430219820Sjeff	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
431219820Sjeff			       p_osmt->local_port.sm_lid, &avh);
432219820Sjeff	if (vapi_ret != VAPI_OK) {
433219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: "
434219820Sjeff			"Error Preparing AVH (%s)\n",
435219820Sjeff			VAPI_strerror_sym(vapi_ret));
436219820Sjeff		status = IB_ERROR;
437219820Sjeff		goto Exit;
438219820Sjeff	}
439219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
440219820Sjeff
441219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n");
442219820Sjeff
443219820Sjeff	/* --------------------- RECV ------------------------- */
444219820Sjeff	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
445219820Sjeff					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
446219820Sjeff					 &wc_desc, 200, 10000, &avh);
447219820Sjeff	if (vapi_ret != VAPI_SUCCESS) {
448219820Sjeff		if (vapi_ret == VAPI_CQ_EMPTY) {
449219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
450219820Sjeff				"Timeout receiving mad (%s)\n",
451219820Sjeff				VAPI_strerror_sym(vapi_ret));
452219820Sjeff			status = IB_TIMEOUT;
453219820Sjeff		} else {
454219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
455219820Sjeff				"Error receiving mad (%s)\n",
456219820Sjeff				VAPI_strerror_sym(vapi_ret));
457219820Sjeff			status = IB_ERROR;
458219820Sjeff		}
459219820Sjeff		goto Exit;
460219820Sjeff	}
461219820Sjeff
462219820Sjeff	/* check to see if successful - by examination of the subscribe bit */
463219820Sjeff	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
464219820Sjeff
465219820Sjeff	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
466219820Sjeff		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
467219820Sjeff			OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n");
468219820Sjeff			status = IB_SUCCESS;
469219820Sjeff		} else {
470219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
471219820Sjeff				"Did not receive a Report(Notice) but attr:%d\n",
472219820Sjeff				cl_ntoh16(p_sa_mad->attr_id));
473219820Sjeff			status = IB_ERROR;
474219820Sjeff		}
475219820Sjeff	} else {
476219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
477219820Sjeff			"Received an Unexpected Method:%d\n", p_smp->method);
478219820Sjeff		status = IB_ERROR;
479219820Sjeff	}
480219820Sjeff
481219820SjeffExit:
482219820Sjeff	OSM_LOG_EXIT(p_log);
483219820Sjeff	return status;
484219820Sjeff}
485219820Sjeff
486219820Sjeff/*
487219820Sjeff * Wait for a trap on QPn
488219820Sjeff *
489219820Sjeff */
490219820Sjeffib_api_status_t
491219820Sjeffosmt_trap_wait(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
492219820Sjeff{
493219820Sjeff	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
494219820Sjeff	ib_sa_mad_t *p_sa_mad;
495219820Sjeff	VAPI_ret_t vapi_ret;
496219820Sjeff	VAPI_wc_desc_t wc_desc;
497219820Sjeff	osm_log_t *p_log = &p_osmt->log;
498219820Sjeff	ib_api_status_t status = IB_SUCCESS;
499219820Sjeff
500219820Sjeff	OSM_LOG_ENTER(p_log);
501219820Sjeff
502219820Sjeff	OSM_LOG(p_log, OSM_LOG_INFO,
503219820Sjeff		"Waiting for Traps under QP:0x%X of SA LID:0x%X\n",
504219820Sjeff		cl_ntoh16(p_osmt->local_port.sm_lid));
505219820Sjeff
506219820Sjeff	/* --------------------- RECV ------------------------- */
507219820Sjeff	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
508219820Sjeff					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
509219820Sjeff					 &wc_desc,
510219820Sjeff					 // 200,
511219820Sjeff					 p_osmt->opt.wait_time * 100,
512219820Sjeff					 10000, NULL);
513219820Sjeff	if (vapi_ret != VAPI_SUCCESS) {
514219820Sjeff		if (vapi_ret == VAPI_CQ_EMPTY) {
515219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
516219820Sjeff				"Timeout receiving mad (%s)\n",
517219820Sjeff				VAPI_strerror_sym(vapi_ret));
518219820Sjeff			status = IB_TIMEOUT;
519219820Sjeff		} else {
520219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
521219820Sjeff				"Error receiving mad (%s)\n",
522219820Sjeff				VAPI_strerror_sym(vapi_ret));
523219820Sjeff			status = IB_ERROR;
524219820Sjeff		}
525219820Sjeff		goto Exit;
526219820Sjeff	}
527219820Sjeff
528219820Sjeff	/* check to see if successful - by examination of the subscribe bit */
529219820Sjeff	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
530219820Sjeff
531219820Sjeff	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
532219820Sjeff		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
533219820Sjeff			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
534219820Sjeff				"Received the Report!\n");
535219820Sjeff			status = IB_SUCCESS;
536219820Sjeff		} else {
537219820Sjeff			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
538219820Sjeff				"Did not receive a Report(Notice) but attr:%d\n",
539219820Sjeff				cl_ntoh16(p_sa_mad->attr_id));
540219820Sjeff			status = IB_ERROR;
541219820Sjeff		}
542219820Sjeff	} else {
543219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
544219820Sjeff			"Received an Unexpected Method:%d\n", p_smp->method);
545219820Sjeff		status = IB_ERROR;
546219820Sjeff	}
547219820Sjeff
548219820SjeffExit:
549219820Sjeff	OSM_LOG_EXIT(p_log);
550219820Sjeff	return status;
551219820Sjeff}
552219820Sjeff
553219820Sjeff/*
554219820Sjeff * Initialize an inform info attribute:
555219820Sjeff * Catch all traps in the lid range of the p_osmt
556219820Sjeff *
557219820Sjeff */
558219820Sjeffib_api_status_t
559219820Sjeffosmt_init_inform_info(IN osmtest_t * const p_osmt, OUT ib_inform_info_t * p_ii)
560219820Sjeff{
561219820Sjeff
562219820Sjeff	memset(p_ii, 0, sizeof(ib_inform_info_t));
563219820Sjeff	/*  p_ii->lid_range_begin = cl_hton16(1); */
564219820Sjeff	p_ii->lid_range_begin = 0xFFFF;
565219820Sjeff	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
566219820Sjeff	p_ii->is_generic = 1;	/*  have to choose */
567219820Sjeff	p_ii->trap_type = 0xFFFF;	/*  ALL */
568219820Sjeff	p_ii->g_or_v.generic.trap_num = 0xFFFF;	/*  ALL */
569219820Sjeff	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
570219820Sjeff	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
571219820Sjeff	return IB_SUCCESS;
572219820Sjeff}
573219820Sjeff
574219820Sjeffib_api_status_t
575219820Sjeffosmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt,
576219820Sjeff			      IN ib_net16_t trap_num,
577219820Sjeff			      OUT ib_inform_info_t * p_ii)
578219820Sjeff{
579219820Sjeff
580219820Sjeff	memset(p_ii, 0, sizeof(ib_inform_info_t));
581219820Sjeff	/*  p_ii->lid_range_begin = cl_hton16(1); */
582219820Sjeff	p_ii->lid_range_begin = 0xFFFF;
583219820Sjeff	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
584219820Sjeff	p_ii->is_generic = 1;	/*  have to choose */
585219820Sjeff	p_ii->trap_type = 0xFFFF;	/*  ALL */
586219820Sjeff	p_ii->g_or_v.generic.trap_num = trap_num;	/*  ALL */
587219820Sjeff	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
588219820Sjeff	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
589219820Sjeff	return IB_SUCCESS;
590219820Sjeff}
591219820Sjeff
592219820Sjeff/*
593219820Sjeff * Run a complete inform info test flow:
594219820Sjeff * - try to unregister inform info (should fail)
595219820Sjeff * - register an inform info
596219820Sjeff * - try to unregister inform info (should succeed)
597219820Sjeff * - register an inform info
598219820Sjeff * - send a trap - sleep
599219820Sjeff * - check that a Report(Notice) arrived that match the sent one
600219820Sjeff *
601219820Sjeff */
602219820Sjeffib_api_status_t osmt_run_inform_info_flow(IN osmtest_t * const p_osmt)
603219820Sjeff{
604219820Sjeff	ib_inform_info_t inform_info;
605219820Sjeff	ib_api_status_t status;
606219820Sjeff	osmt_qp_ctx_t qp_ctx;
607219820Sjeff
608219820Sjeff	OSM_LOG_ENTER(&p_osmt->log);
609219820Sjeff
610219820Sjeff	/* bind the QP */
611219820Sjeff	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
612219820Sjeff	if (status != IB_SUCCESS) {
613219820Sjeff		goto Exit;
614219820Sjeff	}
615219820Sjeff
616219820Sjeff	/* init the inform info */
617219820Sjeff	osmt_init_inform_info(p_osmt, &inform_info);
618219820Sjeff
619219820Sjeff	/* first try to unsubscribe */
620219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
621219820Sjeff	/* WAS IB_REMOTE_ERROR */
622219820Sjeff	if (status != IB_REMOTE_ERROR) {
623219820Sjeff		if (status != IB_SUCCESS) {
624219820Sjeff			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
625219820Sjeff				"Error during UnSubscribe: (%s)\n",
626219820Sjeff				ib_get_err_str(status));
627219820Sjeff			goto Exit;
628219820Sjeff		} else {
629219820Sjeff			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
630219820Sjeff				"Expected Failure to UnSubscribe non existing InformInfo\n");
631219820Sjeff			status = IB_ERROR;
632219820Sjeff			goto Exit;
633219820Sjeff		}
634219820Sjeff	}
635219820Sjeff
636219820Sjeff	/* send the inform info registration */
637219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
638219820Sjeff	if (status != IB_SUCCESS) {
639219820Sjeff		goto Exit;
640219820Sjeff	}
641219820Sjeff
642219820Sjeff	/* send a trap through QP0 and wait on QPN */
643219820Sjeff	status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
644219820Sjeff	if (status != IB_SUCCESS) {
645219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
646219820Sjeff			"Error during Send Trap and Wait For Report: (%s)\n",
647219820Sjeff			ib_get_err_str(status));
648219820Sjeff		goto Exit;
649219820Sjeff	}
650219820Sjeff
651219820Sjeff	/* try to unsubscribe for cleanup */
652219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
653219820Sjeff
654219820Sjeff	if (status != IB_SUCCESS) {
655219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
656219820Sjeff			"Error during UnSubscribe: (%s)\n",
657219820Sjeff			ib_get_err_str(status));
658219820Sjeff		goto Exit;
659219820Sjeff	} else {
660219820Sjeff		if (status == IB_REMOTE_ERROR) {
661219820Sjeff			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
662219820Sjeff				"Remote Error during UnSubscribe\n");
663219820Sjeff			status = IB_ERROR;
664219820Sjeff			goto Exit;
665219820Sjeff		}
666219820Sjeff	}
667219820Sjeff
668219820SjeffExit:
669219820Sjeff	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
670219820Sjeff	OSM_LOG_EXIT(&p_osmt->log);
671219820Sjeff	return status;
672219820Sjeff}
673219820Sjeff
674219820Sjeff/*
675219820Sjeff * Run a complete inform info test flow:
676219820Sjeff * - try to unregister inform info (should fail)
677219820Sjeff * - register an inform info
678219820Sjeff * - try to unregister inform info (should succeed)
679219820Sjeff * - register an inform info
680219820Sjeff * - send a trap - sleep
681219820Sjeff * - check that a Report(Notice) arrived that match the sent one
682219820Sjeff *
683219820Sjeff */
684219820Sjeffib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt)
685219820Sjeff{
686219820Sjeff	ib_inform_info_t inform_info;
687219820Sjeff	ib_api_status_t status;
688219820Sjeff	osmt_qp_ctx_t qp_ctx;
689219820Sjeff
690219820Sjeff	OSM_LOG_ENTER(&p_osmt->log);
691219820Sjeff
692219820Sjeff	/* bind the QP */
693219820Sjeff	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
694219820Sjeff	if (status != IB_SUCCESS) {
695219820Sjeff		goto Exit;
696219820Sjeff	}
697219820Sjeff
698219820Sjeff	/* init the inform info */
699219820Sjeff	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(64), &inform_info);
700219820Sjeff
701219820Sjeff	/* send the inform info registration */
702219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
703219820Sjeff	if (status != IB_SUCCESS) {
704219820Sjeff		goto Exit;
705219820Sjeff	}
706219820Sjeff
707219820Sjeff  /*--------------------- PREP -------------------------*/
708219820Sjeff	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to receive the report */
709219820Sjeff					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
710219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
711219820Sjeff			"Error posting recv bufs for trap 64\n");
712219820Sjeff		status = IB_ERROR;
713219820Sjeff		goto Exit;
714219820Sjeff	}
715219820Sjeff
716219820Sjeff	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 64\n");
717219820Sjeff
718219820Sjeff	/* init the inform info */
719219820Sjeff	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(65), &inform_info);
720219820Sjeff
721219820Sjeff	/* send the inform info registration */
722219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
723219820Sjeff	if (status != IB_SUCCESS) {
724219820Sjeff		goto Exit;
725219820Sjeff	}
726219820Sjeff
727219820Sjeff  /*--------------------- PREP -------------------------*/
728219820Sjeff	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to reveive the report */
729219820Sjeff					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
730219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
731219820Sjeff			"Error posting recv bufs for trap 65\n");
732219820Sjeff		status = IB_ERROR;
733219820Sjeff		goto Exit;
734219820Sjeff	}
735219820Sjeff	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 65\n");
736219820Sjeff
737219820Sjeff	/* Sleep for x seconds in order to allow external script trap generation */
738219820Sjeff#if 0
739219820Sjeff	sleep(p_osmt->opt.wait_time);
740219820Sjeff#endif
741219820Sjeff
742219820Sjeff	/* wait for a trap on QPN */
743219820Sjeff	status = osmt_trap_wait(p_osmt, &qp_ctx);
744219820Sjeff	if (status != IB_SUCCESS) {
745219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
746219820Sjeff			"Error during Send Trap and Wait For Report: (%s)\n",
747219820Sjeff			ib_get_err_str(status));
748219820Sjeff		goto Exit;
749219820Sjeff	}
750219820Sjeff
751219820Sjeff	/* try to unsubscribe for cleanup */
752219820Sjeff	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
753219820Sjeff
754219820Sjeff	if (status != IB_SUCCESS) {
755219820Sjeff		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
756219820Sjeff			"Error during UnSubscribe: (%s)\n",
757219820Sjeff			ib_get_err_str(status));
758219820Sjeff		goto Exit;
759219820Sjeff	}
760219820Sjeff
761219820SjeffExit:
762219820Sjeff	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
763219820Sjeff	OSM_LOG_EXIT(&p_osmt->log);
764219820Sjeff	return status;
765219820Sjeff}
766219820Sjeff
767219820Sjeff#endif				/*  OSM_VENDOR_INTF_MTL */
768