1/*
2 * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36#ifdef OSM_VENDOR_INTF_MTL
37/*
38 * Abstract:
39 *    Implementation of InformInfo testing flow..
40 *    Top level is osmt_run_inform_info_flow:
41 *     osmt_bind_inform_qp
42 *     osmt_reg_unreg_inform_info
43 *     osmt_send_trap_wait_for_forward
44 *
45 */
46
47#include <unistd.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <complib/cl_debug.h>
52#include <vendor/osm_vendor_mlx_hca.h>
53#include "osmtest.h"
54#include "osmt_inform.h"
55
56/*
57 * Prepare an asynchronous QP (rcv) for sending inform info and
58 * handling the incoming reports.
59 *
60 */
61ib_api_status_t
62osmt_bind_inform_qp(IN osmtest_t * const p_osmt, OUT osmt_qp_ctx_t * p_qp_ctx)
63{
64	ib_net64_t port_guid;
65	VAPI_hca_hndl_t hca_hndl;
66	VAPI_hca_id_t hca_id;
67	uint32_t port_num;
68	VAPI_ret_t vapi_ret;
69	IB_MGT_ret_t mgt_ret;
70	uint8_t hca_index;
71	osm_log_t *p_log = &p_osmt->log;
72	ib_api_status_t status = IB_SUCCESS;
73
74	OSM_LOG_ENTER(p_log);
75
76	port_guid = p_osmt->local_port.port_guid;
77
78	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n",
79		cl_ntoh64(port_guid));
80
81	/* obtain the hca name and port num from the guid */
82	OSM_LOG(p_log, OSM_LOG_DEBUG,
83		"Finding CA and Port that owns port guid 0x%" PRIx64 "\n",
84		port_guid);
85
86	mgt_ret =
87	    osm_vendor_get_guid_ca_and_port(p_osmt->p_vendor,
88					    port_guid,
89					    &hca_hndl,
90					    &hca_id[0], &hca_index, &port_num);
91	if (mgt_ret != IB_MGT_OK) {
92		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0109: "
93			"Unable to obtain CA and port (%d).\n");
94		status = IB_ERROR;
95		goto Exit;
96	}
97#define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000
98
99	strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id));
100	p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl;
101	p_qp_ctx->qp_bind_hndl.port_num = port_num;
102	p_qp_ctx->qp_bind_hndl.max_outs_sq = 10;
103	p_qp_ctx->qp_bind_hndl.max_outs_rq = 10;
104	p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY;
105
106	vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl);
107	if (vapi_ret != VAPI_OK) {
108		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0114: "
109			"Error initializing QP.\n");
110		status = IB_ERROR;
111		goto Exit;
112	}
113
114	/* we use the pre-allocated buffers for send and receive :
115	   send from buf[0]
116	   receive from buf[2]
117	 */
118	p_qp_ctx->p_send_buf =
119	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN;
120	p_qp_ctx->p_recv_buf =
121	    (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN +
122							      MAD_BLOCK_SIZE);
123
124	/* Need to clear assigned memory of p_send_buf - before using it to send any data */
125	memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE);
126
127	status = IB_SUCCESS;
128	OSM_LOG(p_log, OSM_LOG_DEBUG, "Initialized QP:0x%X in VAPI Mode\n",
129		p_qp_ctx->qp_bind_hndl.qp_id);
130
131	OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to IB_MGT SMI\n");
132
133	/* we also need a QP0 handle for sending packets */
134	mgt_ret = IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI,
135				    &(p_qp_ctx->ib_mgt_qp0_handle));
136	if (IB_MGT_OK != mgt_ret) {
137		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0115: "
138			"Error obtaining IB_MGT handle to SMI\n");
139		status = IB_ERROR;
140		goto Exit;
141	}
142
143Exit:
144	OSM_LOG_EXIT(p_log);
145	return status;
146}
147
148/*
149 * Close the QP
150 */
151void
152osmt_unbind_inform_qp(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
153{
154	osm_log_t *p_log = &p_osmt->log;
155
156	OSM_LOG_ENTER(p_log);
157
158	osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl);
159
160	IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle);
161
162	OSM_LOG(p_log, OSM_LOG_DEBUG, "Unbind QP handles\n");
163	OSM_LOG_EXIT(&p_osmt->log);
164}
165
166/*
167 * Register/Unregister to receive the given InformInfo
168 *
169 * Uses the qp context to send the inform info mad.
170 * Wait for GetResp(InformInfoResp)
171 *
172 */
173ib_api_status_t
174osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
175			   IN osmt_qp_ctx_t * p_qp_ctx,
176			   IN ib_inform_info_t * p_inform_info,
177			   IN uint8_t reg_flag)
178{
179	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
180	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
181	VAPI_ret_t vapi_ret;
182	VAPI_wc_desc_t wc_desc;
183	VAPI_ud_av_hndl_t avh;
184	static VAPI_wr_id_t wrid = 16198;
185	osm_log_t *p_log = &p_osmt->log;
186	ib_api_status_t status = IB_SUCCESS;
187
188	OSM_LOG_ENTER(&p_osmt->log);
189
190	/* init the MAD */
191	ib_mad_init_new((ib_mad_t *) p_sa_mad,
192			IB_MCLASS_SUBN_ADM,
193			(uint8_t) 2,
194			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
195	wrid++;
196	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;
197
198	/* copy the reference inform info */
199	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));
200
201	if (reg_flag) {
202		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
203			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
204			p_ii->lid_range_begin, p_ii->lid_range_end,
205			p_ii->g_or_v.generic.trap_num);
206	} else {
207		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
208			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
209			p_ii->lid_range_begin, p_ii->lid_range_end);
210	}
211
212	/* set the subscribe bit */
213	if (reg_flag) {
214		p_ii->subscribe = 1;
215	} else {
216		p_ii->subscribe = 0;
217		/*
218		 * we need to set the QPN on the mad if we unsubscribe:
219		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
220		 */
221		ib_inform_info_set_qpn(p_ii,
222				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
223						 qp_num));
224	}
225
226	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);
227
228	/* --------------------- PREP ------------------------- */
229	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 */
230					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
231		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
232			"Error posting recv bufs\n");
233		status = IB_ERROR;
234		goto Exit;
235	}
236	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
237
238	vapi_ret =
239	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
240			       p_osmt->local_port.sm_lid, &avh);
241	if (vapi_ret != VAPI_OK) {
242		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
243			"Error Preparing AVH (%s)\n",
244			VAPI_strerror_sym(vapi_ret));
245		status = IB_ERROR;
246		goto Exit;
247	}
248	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
249
250	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
251		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
252				OSM_LOG_DEBUG);
253#if 0
254		for (i = 56; i < 253; i++) {
255			if (i % 8 == 0) {
256				printf("\n %d : ", i);
257			}
258			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
259		}
260#endif
261		printf("\n");
262	}
263
264	/* --------------------- SEND ------------------------- */
265	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
266				     0,	/*  SL is 0 */
267				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
268				     avh);
269	if (vapi_ret != VAPI_OK) {
270		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
271			"Error sending mad (%s)\n",
272			VAPI_strerror_sym(vapi_ret));
273		status = IB_ERROR;
274		goto Exit;
275	}
276
277	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
278					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
279					 &wc_desc, 20, 10000, NULL);
280	if (vapi_ret != VAPI_OK) {
281		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
282			"Error getting send completion (%s)\n",
283			VAPI_strerror_sym(vapi_ret));
284		status = IB_ERROR;
285		goto Exit;
286	}
287
288	if (wc_desc.status != VAPI_SUCCESS) {
289		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
290			"Error on send completion (%s) (%d)\n",
291			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
292		status = IB_ERROR;
293		goto Exit;
294	}
295	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");
296
297	/* --------------------- RECV ------------------------- */
298	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
299					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
300					 &wc_desc, 20, 10000, &avh);
301	if (vapi_ret != VAPI_SUCCESS) {
302		if (vapi_ret == VAPI_CQ_EMPTY) {
303			status = IB_TIMEOUT;
304		} else {
305			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
306				"Error receiving mad (%s)\n",
307				VAPI_strerror_sym(vapi_ret));
308			status = IB_ERROR;
309		}
310		goto Exit;
311	}
312
313	/* check to see if successful - by examination of the subscribe bit */
314	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
315
316	if (p_sa_mad->status != IB_SUCCESS) {
317		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
318			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
319		status = IB_REMOTE_ERROR;
320		goto Exit;
321	}
322
323	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
324		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
325			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
326			p_sa_mad->method);
327		status = IB_REMOTE_ERROR;
328		goto Exit;
329	}
330
331	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
332		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
333			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
334			cl_ntoh16(p_sa_mad->attr_id));
335		status = IB_REMOTE_ERROR;
336		goto Exit;
337	}
338
339	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
340	if (!p_ii->subscribe) {
341		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
342			"Subscribe/Unsubscribe Failed\n");
343		status = IB_REMOTE_ERROR;
344	}
345
346Exit:
347	OSM_LOG_EXIT(&p_osmt->log);
348	return status;
349}
350
351/*
352 * Send a trap (Subn LID Route) Trap(Notice) through the regular
353 * connection QP connection (targeted at QP0)
354 *
355 * Wait for the trap repress
356 */
357ib_api_status_t
358osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,
359				IN osmt_qp_ctx_t * p_qp_ctx)
360{
361	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
362	ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp);
363	ib_sa_mad_t *p_sa_mad;
364	IB_MGT_ret_t mgt_res;
365	VAPI_ret_t vapi_ret;
366	VAPI_wc_desc_t wc_desc;
367	VAPI_ud_av_hndl_t avh;
368	IB_ud_av_t av;
369	static VAPI_wr_id_t wrid = 2222;
370	osm_log_t *p_log = &p_osmt->log;
371	ib_api_status_t status = IB_SUCCESS;
372
373	OSM_LOG_ENTER(p_log);
374
375	OSM_LOG(p_log, OSM_LOG_INFO,
376		"Sending Traps to QP0 of SA LID:0x%X\n",
377		p_osmt->local_port.sm_lid);
378
379	/* init the MAD */
380	memset(p_smp, 0, sizeof(ib_smp_t));
381	ib_mad_init_new((ib_mad_t *) p_smp,
382			IB_MCLASS_SUBN_LID,
383			(uint8_t) 2,
384			IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0);
385
386	wrid++;
387	p_smp->attr_id = IB_MAD_ATTR_NOTICE;
388
389	/* prepare the notice */
390	p_ntc->generic_type = 0x82;	/*  generic, type = 2 */
391	ib_notice_set_prod_type_ho(p_ntc, 1);
392	p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26);
393	p_ntc->issuer_lid = cl_hton16(2);
394
395	/* --------------------- PREP ------------------------- */
396	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 */
397					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
398		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: "
399			"Error posting recv bufs\n");
400		status = IB_ERROR;
401		goto Exit;
402	}
403	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");
404
405	av.dlid = p_osmt->local_port.sm_lid;
406	av.grh_flag = FALSE;
407
408	/*  EZ: returned in HACK: use constants */
409	av.static_rate = 0;	/*  p_mad_addr->static_rate; */
410	av.src_path_bits = 1;	/*  p_mad_addr->path_bits; */
411	av.sl = 0;		/*  p_mad_addr->addr_type.gsi.service_level; */
412
413	OSM_LOG(p_log, OSM_LOG_DEBUG,
414		"av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n",
415		cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits);
416
417	/* send it */
418	mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp,	/*  actual payload */
419				  &av,	/*  address vector */
420				  wrid,	/*  casting the mad wrapper pointer for err cb */
421				  p_osmt->opt.transaction_timeout);
422	if (mgt_res != IB_MGT_OK) {
423		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: "
424			"Error sending mad (%d)\n", mgt_res);
425		status = IB_ERROR;
426		goto Exit;
427	}
428
429	vapi_ret =
430	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
431			       p_osmt->local_port.sm_lid, &avh);
432	if (vapi_ret != VAPI_OK) {
433		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: "
434			"Error Preparing AVH (%s)\n",
435			VAPI_strerror_sym(vapi_ret));
436		status = IB_ERROR;
437		goto Exit;
438	}
439	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");
440
441	OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n");
442
443	/* --------------------- RECV ------------------------- */
444	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
445					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
446					 &wc_desc, 200, 10000, &avh);
447	if (vapi_ret != VAPI_SUCCESS) {
448		if (vapi_ret == VAPI_CQ_EMPTY) {
449			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
450				"Timeout receiving mad (%s)\n",
451				VAPI_strerror_sym(vapi_ret));
452			status = IB_TIMEOUT;
453		} else {
454			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
455				"Error receiving mad (%s)\n",
456				VAPI_strerror_sym(vapi_ret));
457			status = IB_ERROR;
458		}
459		goto Exit;
460	}
461
462	/* check to see if successful - by examination of the subscribe bit */
463	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
464
465	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
466		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
467			OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n");
468			status = IB_SUCCESS;
469		} else {
470			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
471				"Did not receive a Report(Notice) but attr:%d\n",
472				cl_ntoh16(p_sa_mad->attr_id));
473			status = IB_ERROR;
474		}
475	} else {
476		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020"
477			"Received an Unexpected Method:%d\n", p_smp->method);
478		status = IB_ERROR;
479	}
480
481Exit:
482	OSM_LOG_EXIT(p_log);
483	return status;
484}
485
486/*
487 * Wait for a trap on QPn
488 *
489 */
490ib_api_status_t
491osmt_trap_wait(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx)
492{
493	ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf);
494	ib_sa_mad_t *p_sa_mad;
495	VAPI_ret_t vapi_ret;
496	VAPI_wc_desc_t wc_desc;
497	osm_log_t *p_log = &p_osmt->log;
498	ib_api_status_t status = IB_SUCCESS;
499
500	OSM_LOG_ENTER(p_log);
501
502	OSM_LOG(p_log, OSM_LOG_INFO,
503		"Waiting for Traps under QP:0x%X of SA LID:0x%X\n",
504		cl_ntoh16(p_osmt->local_port.sm_lid));
505
506	/* --------------------- RECV ------------------------- */
507	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
508					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
509					 &wc_desc,
510					 // 200,
511					 p_osmt->opt.wait_time * 100,
512					 10000, NULL);
513	if (vapi_ret != VAPI_SUCCESS) {
514		if (vapi_ret == VAPI_CQ_EMPTY) {
515			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: "
516				"Timeout receiving mad (%s)\n",
517				VAPI_strerror_sym(vapi_ret));
518			status = IB_TIMEOUT;
519		} else {
520			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: "
521				"Error receiving mad (%s)\n",
522				VAPI_strerror_sym(vapi_ret));
523			status = IB_ERROR;
524		}
525		goto Exit;
526	}
527
528	/* check to see if successful - by examination of the subscribe bit */
529	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);
530
531	if (p_sa_mad->method == IB_MAD_METHOD_REPORT) {
532		if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) {
533			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
534				"Received the Report!\n");
535			status = IB_SUCCESS;
536		} else {
537			OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
538				"Did not receive a Report(Notice) but attr:%d\n",
539				cl_ntoh16(p_sa_mad->attr_id));
540			status = IB_ERROR;
541		}
542	} else {
543		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020"
544			"Received an Unexpected Method:%d\n", p_smp->method);
545		status = IB_ERROR;
546	}
547
548Exit:
549	OSM_LOG_EXIT(p_log);
550	return status;
551}
552
553/*
554 * Initialize an inform info attribute:
555 * Catch all traps in the lid range of the p_osmt
556 *
557 */
558ib_api_status_t
559osmt_init_inform_info(IN osmtest_t * const p_osmt, OUT ib_inform_info_t * p_ii)
560{
561
562	memset(p_ii, 0, sizeof(ib_inform_info_t));
563	/*  p_ii->lid_range_begin = cl_hton16(1); */
564	p_ii->lid_range_begin = 0xFFFF;
565	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
566	p_ii->is_generic = 1;	/*  have to choose */
567	p_ii->trap_type = 0xFFFF;	/*  ALL */
568	p_ii->g_or_v.generic.trap_num = 0xFFFF;	/*  ALL */
569	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
570	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
571	return IB_SUCCESS;
572}
573
574ib_api_status_t
575osmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt,
576			      IN ib_net16_t trap_num,
577			      OUT ib_inform_info_t * p_ii)
578{
579
580	memset(p_ii, 0, sizeof(ib_inform_info_t));
581	/*  p_ii->lid_range_begin = cl_hton16(1); */
582	p_ii->lid_range_begin = 0xFFFF;
583	p_ii->lid_range_end = cl_hton16(p_osmt->max_lid);
584	p_ii->is_generic = 1;	/*  have to choose */
585	p_ii->trap_type = 0xFFFF;	/*  ALL */
586	p_ii->g_or_v.generic.trap_num = trap_num;	/*  ALL */
587	p_ii->g_or_v.generic.node_type_lsb = 0xFFFF;	/*  ALL */
588	p_ii->g_or_v.generic.node_type_msb = 0xFF;	/*  ALL */
589	return IB_SUCCESS;
590}
591
592/*
593 * Run a complete inform info test flow:
594 * - try to unregister inform info (should fail)
595 * - register an inform info
596 * - try to unregister inform info (should succeed)
597 * - register an inform info
598 * - send a trap - sleep
599 * - check that a Report(Notice) arrived that match the sent one
600 *
601 */
602ib_api_status_t osmt_run_inform_info_flow(IN osmtest_t * const p_osmt)
603{
604	ib_inform_info_t inform_info;
605	ib_api_status_t status;
606	osmt_qp_ctx_t qp_ctx;
607
608	OSM_LOG_ENTER(&p_osmt->log);
609
610	/* bind the QP */
611	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
612	if (status != IB_SUCCESS) {
613		goto Exit;
614	}
615
616	/* init the inform info */
617	osmt_init_inform_info(p_osmt, &inform_info);
618
619	/* first try to unsubscribe */
620	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
621	/* WAS IB_REMOTE_ERROR */
622	if (status != IB_REMOTE_ERROR) {
623		if (status != IB_SUCCESS) {
624			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
625				"Error during UnSubscribe: (%s)\n",
626				ib_get_err_str(status));
627			goto Exit;
628		} else {
629			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
630				"Expected Failure to UnSubscribe non existing InformInfo\n");
631			status = IB_ERROR;
632			goto Exit;
633		}
634	}
635
636	/* send the inform info registration */
637	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
638	if (status != IB_SUCCESS) {
639		goto Exit;
640	}
641
642	/* send a trap through QP0 and wait on QPN */
643	status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
644	if (status != IB_SUCCESS) {
645		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
646			"Error during Send Trap and Wait For Report: (%s)\n",
647			ib_get_err_str(status));
648		goto Exit;
649	}
650
651	/* try to unsubscribe for cleanup */
652	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
653
654	if (status != IB_SUCCESS) {
655		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
656			"Error during UnSubscribe: (%s)\n",
657			ib_get_err_str(status));
658		goto Exit;
659	} else {
660		if (status == IB_REMOTE_ERROR) {
661			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
662				"Remote Error during UnSubscribe\n");
663			status = IB_ERROR;
664			goto Exit;
665		}
666	}
667
668Exit:
669	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
670	OSM_LOG_EXIT(&p_osmt->log);
671	return status;
672}
673
674/*
675 * Run a complete inform info test flow:
676 * - try to unregister inform info (should fail)
677 * - register an inform info
678 * - try to unregister inform info (should succeed)
679 * - register an inform info
680 * - send a trap - sleep
681 * - check that a Report(Notice) arrived that match the sent one
682 *
683 */
684ib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt)
685{
686	ib_inform_info_t inform_info;
687	ib_api_status_t status;
688	osmt_qp_ctx_t qp_ctx;
689
690	OSM_LOG_ENTER(&p_osmt->log);
691
692	/* bind the QP */
693	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
694	if (status != IB_SUCCESS) {
695		goto Exit;
696	}
697
698	/* init the inform info */
699	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(64), &inform_info);
700
701	/* send the inform info registration */
702	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
703	if (status != IB_SUCCESS) {
704		goto Exit;
705	}
706
707  /*--------------------- PREP -------------------------*/
708	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to receive the report */
709					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
710		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
711			"Error posting recv bufs for trap 64\n");
712		status = IB_ERROR;
713		goto Exit;
714	}
715
716	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 64\n");
717
718	/* init the inform info */
719	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(65), &inform_info);
720
721	/* send the inform info registration */
722	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
723	if (status != IB_SUCCESS) {
724		goto Exit;
725	}
726
727  /*--------------------- PREP -------------------------*/
728	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to reveive the report */
729					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
730		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
731			"Error posting recv bufs for trap 65\n");
732		status = IB_ERROR;
733		goto Exit;
734	}
735	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 65\n");
736
737	/* Sleep for x seconds in order to allow external script trap generation */
738#if 0
739	sleep(p_osmt->opt.wait_time);
740#endif
741
742	/* wait for a trap on QPN */
743	status = osmt_trap_wait(p_osmt, &qp_ctx);
744	if (status != IB_SUCCESS) {
745		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
746			"Error during Send Trap and Wait For Report: (%s)\n",
747			ib_get_err_str(status));
748		goto Exit;
749	}
750
751	/* try to unsubscribe for cleanup */
752	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
753
754	if (status != IB_SUCCESS) {
755		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
756			"Error during UnSubscribe: (%s)\n",
757			ib_get_err_str(status));
758		goto Exit;
759	}
760
761Exit:
762	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
763	OSM_LOG_EXIT(&p_osmt->log);
764	return status;
765}
766
767#endif				/*  OSM_VENDOR_INTF_MTL */
768