xref: /trueos/contrib/ofed/management/opensm/opensm/osm_sminfo_rcv.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
2  * Copyright (c) 2004-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 /*
37  * Abstract:
38  *    Implementation of osm_sminfo_rcv_t.
39  * This object represents the SMInfo Receiver object.
40  * This object is part of the opensm family of objects.
41  */
42 
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif				/* HAVE_CONFIG_H */
46 
47 #include <stdlib.h>
48 #include <string.h>
49 #include <iba/ib_types.h>
50 #include <complib/cl_qmap.h>
51 #include <complib/cl_passivelock.h>
52 #include <complib/cl_debug.h>
53 #include <opensm/osm_madw.h>
54 #include <opensm/osm_log.h>
55 #include <opensm/osm_node.h>
56 #include <opensm/osm_helper.h>
57 #include <opensm/osm_subnet.h>
58 #include <opensm/osm_sm.h>
59 #include <opensm/osm_opensm.h>
60 
61 /**********************************************************************
62  Return TRUE if the remote sm given (by ib_sm_info_t) is higher,
63  return FALSE otherwise.
64  By higher - we mean: SM with higher priority or with same priority
65  and lower GUID.
66 **********************************************************************/
67 static inline boolean_t
__osm_sminfo_rcv_remote_sm_is_higher(IN osm_sm_t * sm,IN const ib_sm_info_t * p_remote_smi)68 __osm_sminfo_rcv_remote_sm_is_higher(IN osm_sm_t * sm,
69 				     IN const ib_sm_info_t * p_remote_smi)
70 {
71 	return (osm_sm_is_greater_than(ib_sminfo_get_priority(p_remote_smi),
72 				       p_remote_smi->guid,
73 				       sm->p_subn->opt.sm_priority,
74 				       sm->p_subn->sm_port_guid));
75 
76 }
77 
78 /**********************************************************************
79  **********************************************************************/
80 static void
__osm_sminfo_rcv_process_get_request(IN osm_sm_t * sm,IN const osm_madw_t * const p_madw)81 __osm_sminfo_rcv_process_get_request(IN osm_sm_t * sm,
82 				     IN const osm_madw_t * const p_madw)
83 {
84 	uint8_t payload[IB_SMP_DATA_SIZE];
85 	ib_smp_t *p_smp;
86 	ib_sm_info_t *p_smi = (ib_sm_info_t *) payload;
87 	ib_api_status_t status;
88 	ib_sm_info_t *p_remote_smi;
89 
90 	OSM_LOG_ENTER(sm->p_log);
91 
92 	CL_ASSERT(p_madw);
93 
94 	/* No real need to grab the lock for this function. */
95 	memset(payload, 0, sizeof(payload));
96 
97 	p_smp = osm_madw_get_smp_ptr(p_madw);
98 
99 	CL_ASSERT(p_smp->method == IB_MAD_METHOD_GET);
100 
101 	p_smi->guid = sm->p_subn->sm_port_guid;
102 	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
103 	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
104 				      sm->p_subn->opt.sm_priority << 4);
105 	/*
106 	   p.840 line 20 - Return 0 for the SM key unless we authenticate the
107 	   requester as the master SM.
108 	 */
109 	p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw));
110 	if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) {
111 		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
112 			"Responding to master SM with real sm_key\n");
113 		p_smi->sm_key = sm->p_subn->opt.sm_key;
114 	} else {
115 		/* The requester is not authenticated as master - set sm_key to zero. */
116 		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
117 			"Responding to SM not master with zero sm_key\n");
118 		p_smi->sm_key = 0;
119 	}
120 
121 	status = osm_resp_send(sm, p_madw, 0, payload);
122 	if (status != IB_SUCCESS) {
123 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F02: "
124 			"Error sending response (%s)\n",
125 			ib_get_err_str(status));
126 		goto Exit;
127 	}
128 
129 Exit:
130 	OSM_LOG_EXIT(sm->p_log);
131 }
132 
133 /**********************************************************************
134  * Check if the p_smp received is legal.
135  * Current checks:
136  *   MADHeader:AttributeModifier of ACKNOWLEDGE that was not sent by a
137  *             Standby SM.
138  *   MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER
139  *             that was not sent by a Master SM.
140  * FUTURE - TO DO:
141  *   Check that the SM_Key matches.
142  **********************************************************************/
143 static ib_api_status_t
__osm_sminfo_rcv_check_set_req_legality(IN const ib_smp_t * const p_smp)144 __osm_sminfo_rcv_check_set_req_legality(IN const ib_smp_t * const p_smp)
145 {
146 	ib_sm_info_t *p_smi;
147 
148 	p_smi = ib_smp_get_payload_ptr(p_smp);
149 
150 	if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE) {
151 		if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_STANDBY)
152 			return (IB_SUCCESS);
153 	} else if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER ||
154 		   p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE ||
155 		   p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY ||
156 		   p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER) {
157 		if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_MASTER)
158 			return (IB_SUCCESS);
159 	}
160 
161 	return (IB_INVALID_PARAMETER);
162 }
163 
164 /**********************************************************************
165  **********************************************************************/
166 static void
__osm_sminfo_rcv_process_set_request(IN osm_sm_t * sm,IN const osm_madw_t * const p_madw)167 __osm_sminfo_rcv_process_set_request(IN osm_sm_t * sm,
168 				     IN const osm_madw_t * const p_madw)
169 {
170 	uint8_t payload[IB_SMP_DATA_SIZE];
171 	ib_smp_t *p_smp;
172 	ib_sm_info_t *p_smi = (ib_sm_info_t *) payload;
173 	ib_sm_info_t *sm_smi;
174 	ib_api_status_t status;
175 	osm_sm_signal_t sm_signal;
176 	ib_sm_info_t *p_remote_smi;
177 
178 	OSM_LOG_ENTER(sm->p_log);
179 
180 	CL_ASSERT(p_madw);
181 
182 	memset(payload, 0, sizeof(payload));
183 
184 	p_smp = osm_madw_get_smp_ptr(p_madw);
185 	sm_smi = ib_smp_get_payload_ptr(p_smp);
186 
187 	if (p_smp->method != IB_MAD_METHOD_SET) {
188 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F03: "
189 			"Unsupported method 0x%X\n", p_smp->method);
190 		goto Exit;
191 	}
192 
193 	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
194 
195 	p_smi->guid = sm->p_subn->sm_port_guid;
196 	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
197 	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
198 				      sm->p_subn->opt.sm_priority << 4);
199 	/*
200 	   p.840 line 20 - Return 0 for the SM key unless we authenticate the
201 	   requester as the master SM.
202 	 */
203 	p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw));
204 	if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) {
205 		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
206 			"Responding to master SM with real sm_key\n");
207 		p_smi->sm_key = sm->p_subn->opt.sm_key;
208 	} else {
209 		/* The requester is not authenticated as master - set sm_key to zero. */
210 		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
211 			"Responding to SM not master with zero sm_key\n");
212 		p_smi->sm_key = 0;
213 	}
214 
215 	/* Check the legality of the packet */
216 	status = __osm_sminfo_rcv_check_set_req_legality(p_smp);
217 	if (status != IB_SUCCESS) {
218 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F04: "
219 			"Check legality failed. AttributeModifier:0x%X RemoteState:%s\n",
220 			p_smp->attr_mod,
221 			osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi)));
222 		status = osm_resp_send(sm, p_madw, 7, payload);
223 		if (status != IB_SUCCESS)
224 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F05: "
225 				"Error sending response (%s)\n",
226 				ib_get_err_str(status));
227 		CL_PLOCK_RELEASE(sm->p_lock);
228 		goto Exit;
229 	}
230 
231 	/* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */
232 	switch (p_smp->attr_mod) {
233 	case IB_SMINFO_ATTR_MOD_HANDOVER:
234 		sm_signal = OSM_SM_SIGNAL_HANDOVER;
235 		break;
236 	case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE:
237 		sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE;
238 		break;
239 	case IB_SMINFO_ATTR_MOD_DISABLE:
240 		sm_signal = OSM_SM_SIGNAL_DISABLE;
241 		break;
242 	case IB_SMINFO_ATTR_MOD_STANDBY:
243 		sm_signal = OSM_SM_SIGNAL_STANDBY;
244 		break;
245 	case IB_SMINFO_ATTR_MOD_DISCOVER:
246 		sm_signal = OSM_SM_SIGNAL_DISCOVER;
247 		break;
248 	default:
249 		/*
250 		   This code shouldn't be reached - checked in the
251 		   check legality
252 		 */
253 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F06: "
254 			"THIS CODE SHOULD NOT BE REACHED!!\n");
255 		CL_PLOCK_RELEASE(sm->p_lock);
256 		goto Exit;
257 	}
258 
259 	/* check legality of the needed transition in the SM state machine */
260 	status = osm_sm_state_mgr_check_legality(sm, sm_signal);
261 	if (status != IB_SUCCESS) {
262 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F07: "
263 			"Failed check of legality of needed SM transition. AttributeModifier:0x%X RemoteState:%s\n",
264 			p_smp->attr_mod,
265 			osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi)));
266 		status = osm_resp_send(sm, p_madw, 7, payload);
267 		if (status != IB_SUCCESS)
268 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F08: "
269 				"Error sending response (%s)\n",
270 				ib_get_err_str(status));
271 		CL_PLOCK_RELEASE(sm->p_lock);
272 		goto Exit;
273 	}
274 
275 	/* the SubnSet(SMInfo) command is ok. Send a response. */
276 	status = osm_resp_send(sm, p_madw, 0, payload);
277 	if (status != IB_SUCCESS)
278 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F09: "
279 			"Error sending response (%s)\n",
280 			ib_get_err_str(status));
281 
282 	/* it is a legal packet - act according to it */
283 
284 	/* if the AttributeModifier is STANDBY - need to save on the sm in */
285 	/* the master_sm_guid variable - the guid of the current master. */
286 	if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY) {
287 		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
288 			"Received a STANDBY signal. Updating "
289 			"sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
290 			cl_ntoh64(sm_smi->guid));
291 		sm->master_sm_guid = sm_smi->guid;
292 	}
293 
294 	CL_PLOCK_RELEASE(sm->p_lock);
295 	status = osm_sm_state_mgr_process(sm, sm_signal);
296 
297 	if (status != IB_SUCCESS)
298 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F10: "
299 			"Error in SM state transition (%s)\n",
300 			ib_get_err_str(status));
301 
302 Exit:
303 	OSM_LOG_EXIT(sm->p_log);
304 }
305 
306 /**********************************************************************
307  **********************************************************************/
308 static osm_signal_t
__osm_sminfo_rcv_process_get_sm(IN osm_sm_t * sm,IN const osm_remote_sm_t * const p_sm,boolean_t light_sweep)309 __osm_sminfo_rcv_process_get_sm(IN osm_sm_t * sm,
310 				IN const osm_remote_sm_t * const p_sm,
311 				boolean_t light_sweep)
312 {
313 	const ib_sm_info_t *p_smi;
314 
315 	OSM_LOG_ENTER(sm->p_log);
316 
317 	p_smi = &p_sm->smi;
318 
319 	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
320 		"Detected SM 0x%016" PRIx64 " in state %u\n",
321 		cl_ntoh64(p_smi->guid), ib_sminfo_get_state(p_smi));
322 
323 	/* Check the state of this SM vs. our own. */
324 	switch (sm->p_subn->sm_state) {
325 	case IB_SMINFO_STATE_NOTACTIVE:
326 		break;
327 
328 	case IB_SMINFO_STATE_DISCOVERING:
329 		switch (ib_sminfo_get_state(p_smi)) {
330 		case IB_SMINFO_STATE_NOTACTIVE:
331 			break;
332 		case IB_SMINFO_STATE_MASTER:
333 			sm->master_sm_found = 1;
334 			/* save on the sm the guid of the current master. */
335 			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
336 				"Found master SM. Updating sm_state_mgr master_guid: 0x%016"
337 				PRIx64 "\n", cl_ntoh64(p_sm->p_port->guid));
338 			sm->master_sm_guid = p_sm->p_port->guid;
339 			break;
340 		case IB_SMINFO_STATE_DISCOVERING:
341 		case IB_SMINFO_STATE_STANDBY:
342 			if (__osm_sminfo_rcv_remote_sm_is_higher(sm, p_smi)
343 			    == TRUE) {
344 				/* the remote is a higher sm - need to stop sweeping */
345 				sm->master_sm_found = 1;
346 				/* save on the sm the guid of the higher SM we found - */
347 				/* we will poll it - as long as it lives - we should be in Standby. */
348 				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
349 					"Found higher SM. Updating sm_state_mgr master_guid:"
350 					" 0x%016" PRIx64 "\n",
351 					cl_ntoh64(p_sm->p_port->guid));
352 				sm->master_sm_guid = p_sm->p_port->guid;
353 			}
354 			break;
355 		default:
356 			break;
357 		}
358 		break;
359 
360 	case IB_SMINFO_STATE_STANDBY:
361 		/* if the guid of the SM that sent us this response is equal to the */
362 		/* p_sm_mgr->master_guid - then this is a signal that the polling */
363 		switch (ib_sminfo_get_state(p_smi)) {
364 		case IB_SMINFO_STATE_MASTER:
365 			/* This means the master is alive */
366 			/* Signal that to the SM state mgr */
367 			osm_sm_state_mgr_signal_master_is_alive(sm);
368 			break;
369 		case IB_SMINFO_STATE_STANDBY:
370 			/* This should be the response from the sm we are polling. */
371 			/* If it is - then signal master is alive */
372 			if (sm->master_sm_guid == p_sm->p_port->guid) {
373 				/* Make sure that it is an SM with higher priority than us.
374 				   If we started polling it when it was master, and it moved
375 				   to standby - then it might be with a lower priority than
376 				   us - and then we don't want to continue polling it. */
377 				if (__osm_sminfo_rcv_remote_sm_is_higher
378 				    (sm, p_smi) == TRUE)
379 					osm_sm_state_mgr_signal_master_is_alive(sm);
380 			}
381 			break;
382 		default:
383 			/* any other state - do nothing */
384 			break;
385 		}
386 		break;
387 
388 	case IB_SMINFO_STATE_MASTER:
389 		switch (ib_sminfo_get_state(p_smi)) {
390 		case IB_SMINFO_STATE_MASTER:
391 			/* If this is a response due to our polling, this means that we are
392 			   waiting for a handover from this SM, and it is still alive -
393 			   signal that. */
394 			if (sm->p_polling_sm)
395 				osm_sm_state_mgr_signal_master_is_alive(sm);
396 			else {
397 				/* This is a response we got while sweeping the subnet.
398 				   We will handle a case of handover needed later on, when the sweep
399 				   is done and all SMs are recongnized. */
400 			}
401 			break;
402 		case IB_SMINFO_STATE_STANDBY:
403 			if (light_sweep &&
404 			    __osm_sminfo_rcv_remote_sm_is_higher(sm, p_smi))
405 				sm->p_subn->force_heavy_sweep = TRUE;
406 			break;
407 		default:
408 			/* any other state - do nothing */
409 			break;
410 		}
411 		break;
412 
413 	default:
414 		break;
415 	}
416 
417 	OSM_LOG_EXIT(sm->p_log);
418 	return 0;
419 }
420 
421 /**********************************************************************
422  **********************************************************************/
423 static void
__osm_sminfo_rcv_process_get_response(IN osm_sm_t * sm,IN const osm_madw_t * const p_madw)424 __osm_sminfo_rcv_process_get_response(IN osm_sm_t * sm,
425 				      IN const osm_madw_t * const p_madw)
426 {
427 	const ib_smp_t *p_smp;
428 	const ib_sm_info_t *p_smi;
429 	cl_qmap_t *p_sm_tbl;
430 	osm_port_t *p_port;
431 	ib_net64_t port_guid;
432 	osm_remote_sm_t *p_sm;
433 
434 	OSM_LOG_ENTER(sm->p_log);
435 
436 	CL_ASSERT(p_madw);
437 
438 	p_smp = osm_madw_get_smp_ptr(p_madw);
439 
440 	if (p_smp->method != IB_MAD_METHOD_GET_RESP) {
441 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F11: "
442 			"Unsupported method 0x%X\n", p_smp->method);
443 		goto Exit;
444 	}
445 
446 	p_smi = ib_smp_get_payload_ptr(p_smp);
447 	p_sm_tbl = &sm->p_subn->sm_guid_tbl;
448 	port_guid = p_smi->guid;
449 
450 	osm_dump_sm_info(sm->p_log, p_smi, OSM_LOG_DEBUG);
451 
452 	/* Check that the sm_key of the found SM is the same as ours,
453 	   or is zero. If not - OpenSM cannot continue with configuration!. */
454 	if (p_smi->sm_key != 0 && p_smi->sm_key != sm->p_subn->opt.sm_key) {
455 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F18: "
456 			"Got SM with sm_key that doesn't match our "
457 			"local key. Exiting\n");
458 		osm_log(sm->p_log, OSM_LOG_SYS,
459 			"Found remote SM with non-matching sm_key. Exiting\n");
460 		osm_exit_flag = TRUE;
461 		goto Exit;
462 	}
463 
464 	/* Determine if we already have another SM object for this SM. */
465 	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
466 
467 	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
468 	if (!p_port) {
469 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F12: "
470 			"No port object for this SM\n");
471 		goto _unlock_and_exit;
472 	}
473 
474 	if (osm_port_get_guid(p_port) != p_smi->guid) {
475 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F13: "
476 			"Bogus SM port GUID\n\t\t\t\tExpected 0x%016" PRIx64
477 			", Received 0x%016" PRIx64 "\n",
478 			cl_ntoh64(osm_port_get_guid(p_port)),
479 			cl_ntoh64(p_smi->guid));
480 		goto _unlock_and_exit;
481 	}
482 
483 	if (port_guid == sm->p_subn->sm_port_guid) {
484 		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
485 			"Self query response received - SM port 0x%016" PRIx64
486 			"\n", cl_ntoh64(port_guid));
487 		goto _unlock_and_exit;
488 	}
489 
490 	p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid);
491 	if (p_sm == (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) {
492 		p_sm = malloc(sizeof(*p_sm));
493 		if (p_sm == NULL) {
494 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F14: "
495 				"Unable to allocate SM object\n");
496 			goto _unlock_and_exit;
497 		}
498 
499 		osm_remote_sm_init(p_sm, p_port, p_smi);
500 
501 		cl_qmap_insert(p_sm_tbl, port_guid, &p_sm->map_item);
502 	} else
503 		/* We already know this SM. Update the SMInfo attribute. */
504 		p_sm->smi = *p_smi;
505 
506 	__osm_sminfo_rcv_process_get_sm(sm, p_sm,
507 					osm_madw_get_smi_context_ptr(p_madw)->light_sweep);
508 
509 _unlock_and_exit:
510 	CL_PLOCK_RELEASE(sm->p_lock);
511 
512 Exit:
513 	OSM_LOG_EXIT(sm->p_log);
514 }
515 
516 /**********************************************************************
517  **********************************************************************/
518 static void
__osm_sminfo_rcv_process_set_response(IN osm_sm_t * sm,IN const osm_madw_t * const p_madw)519 __osm_sminfo_rcv_process_set_response(IN osm_sm_t * sm,
520 				      IN const osm_madw_t * const p_madw)
521 {
522 	const ib_smp_t *p_smp;
523 	const ib_sm_info_t *p_smi;
524 
525 	OSM_LOG_ENTER(sm->p_log);
526 
527 	CL_ASSERT(p_madw);
528 
529 	p_smp = osm_madw_get_smp_ptr(p_madw);
530 
531 	if (p_smp->method != IB_MAD_METHOD_GET_RESP) {
532 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F16: "
533 			"Unsupported method 0x%X\n", p_smp->method);
534 		goto Exit;
535 	}
536 
537 	p_smi = ib_smp_get_payload_ptr(p_smp);
538 	osm_dump_sm_info(sm->p_log, p_smi, OSM_LOG_DEBUG);
539 
540 	/* Check the AttributeModifier */
541 	if (p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER) {
542 		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F17: "
543 			"Unsupported attribute modifier 0x%X\n",
544 			p_smp->attr_mod);
545 		goto Exit;
546 	}
547 
548 	/* This is a response on a HANDOVER request - Nothing to do. */
549 
550 Exit:
551 	OSM_LOG_EXIT(sm->p_log);
552 }
553 
554 /**********************************************************************
555  **********************************************************************/
osm_sminfo_rcv_process(IN void * context,IN void * data)556 void osm_sminfo_rcv_process(IN void *context, IN void *data)
557 {
558 	osm_sm_t *sm = context;
559 	osm_madw_t *p_madw = data;
560 	ib_smp_t *p_smp;
561 	osm_smi_context_t *p_smi_context;
562 
563 	OSM_LOG_ENTER(sm->p_log);
564 
565 	CL_ASSERT(p_madw);
566 
567 	p_smp = osm_madw_get_smp_ptr(p_madw);
568 
569 	/* Determine if this is a request for our own SMInfo or if
570 	   this is a response to our request for another SM's SMInfo. */
571 	if (ib_smp_is_response(p_smp)) {
572 		const ib_sm_info_t *p_smi = ib_smp_get_payload_ptr(p_smp);
573 
574 		/* Get the context - to see if this is a response to a Get or Set method */
575 		p_smi_context = osm_madw_get_smi_context_ptr(p_madw);
576 
577 		/* Verify that response is from expected port and there is
578 		   no port moving issue. */
579 		if (p_smi_context->port_guid != p_smi->guid) {
580 			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F19: "
581 				"Unexpected SM port GUID in response"
582 				"\n\t\t\t\tExpected 0x%016" PRIx64
583 				", Received 0x%016" PRIx64 "\n",
584 				cl_ntoh64(p_smi_context->port_guid),
585 				cl_ntoh64(p_smi->guid));
586 			goto Exit;
587 		}
588 
589 		if (p_smi_context->set_method == FALSE)
590 			/* this is a response to a Get method */
591 			__osm_sminfo_rcv_process_get_response(sm, p_madw);
592 		else
593 			/* this is a response to a Set method */
594 			__osm_sminfo_rcv_process_set_response(sm, p_madw);
595 	} else if (p_smp->method == IB_MAD_METHOD_GET)
596 		/* This is a SubnGet request */
597 		__osm_sminfo_rcv_process_get_request(sm, p_madw);
598 	else
599 		/* This should be a SubnSet request */
600 		__osm_sminfo_rcv_process_set_request(sm, p_madw);
601 
602 Exit:
603 	OSM_LOG_EXIT(sm->p_log);
604 }
605