xref: /NextBSD/contrib/ofed/management/opensm/osmtest/osmt_inform.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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  */
61 ib_api_status_t
osmt_bind_inform_qp(IN osmtest_t * const p_osmt,OUT osmt_qp_ctx_t * p_qp_ctx)62 osmt_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 
143 Exit:
144 	OSM_LOG_EXIT(p_log);
145 	return status;
146 }
147 
148 /*
149  * Close the QP
150  */
151 void
osmt_unbind_inform_qp(IN osmtest_t * const p_osmt,IN osmt_qp_ctx_t * p_qp_ctx)152 osmt_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  */
173 ib_api_status_t
osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,IN osmt_qp_ctx_t * p_qp_ctx,IN ib_inform_info_t * p_inform_info,IN uint8_t reg_flag)174 osmt_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 
346 Exit:
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  */
357 ib_api_status_t
osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt,IN osmt_qp_ctx_t * p_qp_ctx)358 osmt_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 
481 Exit:
482 	OSM_LOG_EXIT(p_log);
483 	return status;
484 }
485 
486 /*
487  * Wait for a trap on QPn
488  *
489  */
490 ib_api_status_t
osmt_trap_wait(IN osmtest_t * const p_osmt,IN osmt_qp_ctx_t * p_qp_ctx)491 osmt_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 
548 Exit:
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  */
558 ib_api_status_t
osmt_init_inform_info(IN osmtest_t * const p_osmt,OUT ib_inform_info_t * p_ii)559 osmt_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 
574 ib_api_status_t
osmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt,IN ib_net16_t trap_num,OUT ib_inform_info_t * p_ii)575 osmt_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  */
osmt_run_inform_info_flow(IN osmtest_t * const p_osmt)602 ib_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 
668 Exit:
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  */
osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt)684 ib_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 
761 Exit:
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