1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2006 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#if HAVE_CONFIG_H
37219820Sjeff#  include <config.h>
38219820Sjeff#endif				/* HAVE_CONFIG_H */
39219820Sjeff
40219820Sjeff#if defined(OSM_VENDOR_INTF_SIM)
41219820Sjeff#undef IN
42219820Sjeff#undef OUT
43219820Sjeff
44219820Sjeff#include <unistd.h>
45219820Sjeff#include <vendor/osm_vendor_api.h>
46219820Sjeff#include <opensm/osm_log.h>
47219820Sjeff#include <stdlib.h>
48219820Sjeff#include <stdio.h>
49219820Sjeff#include <sys/types.h>
50219820Sjeff#include <dirent.h>
51219820Sjeff#include <stdlib.h>
52219820Sjeff#include <sys/stat.h>
53219820Sjeff#include <stdint.h>
54219820Sjeff#include <fcntl.h>
55219820Sjeff
56219820Sjeff/******************************************************************************
57219820Sjeff*
58219820Sjeff* Provides the functionality for selecting an HCA Port and Obtaining it's guid.
59219820Sjeff* This version is based on $IBMGTSIM_DIR/$IBMGTSIM_NODE file system.
60219820Sjeff* This is a mimic of the OpenIB gen1 file system
61219820Sjeff*
62219820Sjeff******************************************************************************/
63219820Sjeff
64219820Sjeffchar *__get_simulator_dir(void)
65219820Sjeff{
66219820Sjeff	static char *ibmgtSimDir = NULL;
67219820Sjeff	static char *defaultIbmgtSimDir = "/tmp/ibmgtsim";
68219820Sjeff	static char *ibmgtSimNode = NULL;
69219820Sjeff	static char dirName[1024];
70219820Sjeff
71219820Sjeff	/* we use the first pointer to know if we were here */
72219820Sjeff	if (ibmgtSimDir == NULL) {
73219820Sjeff		/* obtain the simulator directory */
74219820Sjeff		ibmgtSimDir = getenv("IBMGTSIM_DIR");
75219820Sjeff		if (ibmgtSimDir == NULL) {
76219820Sjeff			printf
77219820Sjeff			    ("-W- Environment variable: IBMGTSIM_DIR does not exist.\n");
78219820Sjeff			printf
79219820Sjeff			    ("    Please create one used by the simulator.\n");
80219820Sjeff			printf("    Using /tmp/ibmgtsim as default.\n");
81219820Sjeff			ibmgtSimDir = defaultIbmgtSimDir;
82219820Sjeff		}
83219820Sjeff
84219820Sjeff		/* obtain the node name we simulate */
85219820Sjeff		ibmgtSimNode = getenv("IBMGTSIM_NODE");
86219820Sjeff		if (ibmgtSimNode == NULL) {
87219820Sjeff			printf
88219820Sjeff			    ("-W- Environment variable: IBMGTSIM_NODE does not exist.\n");
89219820Sjeff			printf
90219820Sjeff			    ("    This variable should be the name of the node you wish to simulate.\n");
91219820Sjeff			printf("    Using H-1 as default.\n");
92219820Sjeff			ibmgtSimNode = "H-1";
93219820Sjeff		}
94219820Sjeff		sprintf(dirName, "%s/%s", ibmgtSimDir, ibmgtSimNode);
95219820Sjeff	}
96219820Sjeff
97219820Sjeff	return dirName;
98219820Sjeff}
99219820Sjeff
100219820Sjefftypedef struct _osm_ca_info {
101219820Sjeff	ib_net64_t guid;
102219820Sjeff	size_t attr_size;
103219820Sjeff	ib_ca_attr_t *p_attr;
104219820Sjeff
105219820Sjeff} osm_ca_info_t;
106219820Sjeff
107219820Sjeff/**********************************************************************
108219820Sjeff * Returns a pointer to the port attribute of the specified port
109219820Sjeff * owned by this CA.
110219820Sjeff ************************************************************************/
111219820Sjeffstatic ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t *
112219820Sjeff						       const p_ca_info,
113219820Sjeff						       IN const uint8_t index)
114219820Sjeff{
115219820Sjeff	return (&p_ca_info->p_attr->p_port_attr[index]);
116219820Sjeff}
117219820Sjeff
118219820Sjeff/**********************************************************************
119219820Sjeff * Obtain the number of local CAs by scanning /proc/infiniband/core
120219820Sjeff **********************************************************************/
121219820Sjeffint __hca_sim_get_num_cas(void)
122219820Sjeff{
123219820Sjeff	int num_cas = 0;
124219820Sjeff	DIR *dp;
125219820Sjeff	struct dirent *ep;
126219820Sjeff
127219820Sjeff	dp = opendir(__get_simulator_dir());
128219820Sjeff
129219820Sjeff	if (dp != NULL) {
130219820Sjeff		while ((ep = readdir(dp))) {
131219820Sjeff			/* CAs are directories with the format ca[1-9][0-9]* */
132219820Sjeff			/*  if ((ep->d_type == DT_DIR) && !strncmp(ep->d_name, "ca", 2)) */
133219820Sjeff			if (!strncmp(ep->d_name, "ca", 2)) {
134219820Sjeff				num_cas++;
135219820Sjeff			}
136219820Sjeff		}
137219820Sjeff		closedir(dp);
138219820Sjeff	} else {
139219820Sjeff		printf("__hca_sim_get_num_cas: ERROR : ail to open dir %s\n",
140219820Sjeff		       __get_simulator_dir());
141219820Sjeff		exit(1);
142219820Sjeff	}
143219820Sjeff
144219820Sjeff	if (!num_cas)
145219820Sjeff		exit(1);
146219820Sjeff	return num_cas;
147219820Sjeff}
148219820Sjeff
149219820Sjeff/*
150219820Sjeff  name:          InfiniHost0
151219820Sjeff  provider:      tavor
152219820Sjeff  node GUID:     0002:c900:0120:3470
153219820Sjeff  ports:         2
154219820Sjeff  vendor ID:     0x2c9
155219820Sjeff  device ID:     0x5a44
156219820Sjeff  HW revision:   0xa1
157219820Sjeff  FW revision:   0x300020080
158219820Sjeff*/
159219820Sjefftypedef struct _sim_ca_info {
160219820Sjeff	char name[32];
161219820Sjeff	char provider[32];
162219820Sjeff	uint64_t guid;
163219820Sjeff	uint8_t num_ports;
164219820Sjeff	uint32_t vend_id;
165219820Sjeff	uint16_t dev_id;
166219820Sjeff	uint16_t rev_id;
167219820Sjeff	uint64_t fw_rev;
168219820Sjeff} sim_ca_info_t;
169219820Sjeff
170219820Sjeff/**********************************************************************
171219820Sjeff * Parse the CA Info file available in ibmgtSimDir/caN/info
172219820Sjeff **********************************************************************/
173219820Sjeffstatic ib_api_status_t
174219820Sjeff__parse_ca_info_file(IN osm_vendor_t * const p_vend,
175219820Sjeff		     IN uint32_t idx, OUT sim_ca_info_t * sim_ca_info)
176219820Sjeff{
177219820Sjeff	ib_api_status_t status = IB_ERROR;
178219820Sjeff	int info_file;
179219820Sjeff	char file_name[256];
180219820Sjeff	char file_buffer[3200];
181219820Sjeff	char *p_ch;
182219820Sjeff	int g1, g2, g3, g4;
183219820Sjeff	int num_ports;
184219820Sjeff	uint32_t len;
185219820Sjeff
186219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
187219820Sjeff
188219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
189219820Sjeff		"__parse_ca_info_file: " "Querying CA %d.\n", idx);
190219820Sjeff
191219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
192219820Sjeff	sprintf(file_name, "%s/ca%d/info", __get_simulator_dir(), idx);
193219820Sjeff	info_file = open(file_name, O_RDONLY);
194219820Sjeff	if (!info_file) {
195219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
196219820Sjeff			"__parse_ca_info_file: ERR 5105: "
197219820Sjeff			"Fail to open HCA:%d info file:(%s).\n", idx,
198219820Sjeff			file_name);
199219820Sjeff		goto Exit;
200219820Sjeff	}
201219820Sjeff
202219820Sjeff	/* read in the file */
203219820Sjeff	len = read(info_file, file_buffer, 3200);
204219820Sjeff	close(info_file);
205219820Sjeff	file_buffer[len] = '\0';
206219820Sjeff
207219820Sjeff	/*
208219820Sjeff	   parse the file ...
209219820Sjeff	   name:          InfiniHost0
210219820Sjeff	   provider:      tavor
211219820Sjeff	   node GUID:     0002:c900:0120:3470
212219820Sjeff	   ports:         2
213219820Sjeff	   vendor ID:     0x2c9
214219820Sjeff	   device ID:     0x5a44
215219820Sjeff	   HW revision:   0xa1
216219820Sjeff	   FW revision:   0x300020080
217219820Sjeff	 */
218219820Sjeff	if (!(p_ch = strstr(file_buffer, "name:"))) {
219219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
220219820Sjeff			"__parse_ca_info_file: ERR 5106: "
221219820Sjeff			"Fail to obtain HCA name. In info file:(%s).\n",
222219820Sjeff			file_buffer);
223219820Sjeff		goto Exit;
224219820Sjeff	}
225219820Sjeff	if (sscanf(p_ch, "name: %s", sim_ca_info->name) != 1) {
226219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
227219820Sjeff			"__parse_ca_info_file: ERR 5107: "
228219820Sjeff			"Fail to parse name in info file:(%s).\n", p_ch);
229219820Sjeff		goto Exit;
230219820Sjeff	}
231219820Sjeff
232219820Sjeff	/* get the guid of the HCA */
233219820Sjeff	if (!(p_ch = strstr(file_buffer, "node GUID:"))) {
234219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
235219820Sjeff			"__parse_ca_info_file: ERR 5108: "
236219820Sjeff			"Fail to obtain GUID in info file:(%s).\n",
237219820Sjeff			file_buffer);
238219820Sjeff		goto Exit;
239219820Sjeff	}
240219820Sjeff	if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) {
241219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
242219820Sjeff			"__parse_ca_info_file: ERR 5109: "
243219820Sjeff			"Fail to parse GUID in info file:(%s).\n", p_ch);
244219820Sjeff		goto Exit;
245219820Sjeff	}
246219820Sjeff	sim_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32
247219820Sjeff	    | (uint64_t) g1 << 16 | (uint64_t) g3;
248219820Sjeff
249219820Sjeff	/* obtain number of ports */
250219820Sjeff	if (!(p_ch = strstr(file_buffer, "ports:"))) {
251219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
252219820Sjeff			"__parse_ca_info_file: ERR 5110: "
253219820Sjeff			"Fail to obtain number of ports in info file:(%s).\n",
254219820Sjeff			file_buffer);
255219820Sjeff		goto Exit;
256219820Sjeff	}
257219820Sjeff	if (sscanf(p_ch, "ports: %d", &num_ports) != 1) {
258219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
259219820Sjeff			"__parse_ca_info_file: ERR 5111: "
260219820Sjeff			"Fail to parse num ports in info file:(%s).\n", p_ch);
261219820Sjeff		goto Exit;
262219820Sjeff	}
263219820Sjeff	sim_ca_info->num_ports = num_ports;
264219820Sjeff
265219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
266219820Sjeff		"__parse_ca_info_file: "
267219820Sjeff		"CA1 = name:%s guid:0x%016llx ports:%d\n",
268219820Sjeff		sim_ca_info->name, sim_ca_info->guid, sim_ca_info->num_ports);
269219820Sjeff
270219820Sjeff	status = IB_SUCCESS;
271219820SjeffExit:
272219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
273219820Sjeff	return status;
274219820Sjeff}
275219820Sjeff
276219820Sjeff/*
277219820Sjeff  state:         ACTIVE
278219820Sjeff  LID:           0x0001
279219820Sjeff  LMC:           0x0000
280219820Sjeff  SM LID:        0x0001
281219820Sjeff  SM SL:         0x0000
282219820Sjeff  Capabilities:  IsSM
283219820Sjeff  IsTrapSupported
284219820Sjeff  IsAutomaticMigrationSupported
285219820Sjeff  IsSLMappingSupported
286219820Sjeff  IsLEDInfoSupported
287219820Sjeff  IsSystemImageGUIDSupported
288219820Sjeff  IsVendorClassSupported
289219820Sjeff  IsCapabilityMaskNoticeSupported
290219820Sjeff*/
291219820Sjefftypedef struct _sim_port_info {
292219820Sjeff	uint8_t state;
293219820Sjeff	uint16_t lid;
294219820Sjeff	uint8_t lmc;
295219820Sjeff	uint16_t sm_lid;
296219820Sjeff	uint8_t sm_sl;
297219820Sjeff} sim_port_info_t;
298219820Sjeff
299219820Sjeff/**********************************************************************
300219820Sjeff * Parse the Port Info file available in ibmgtSimDir/caN/portM/info
301219820Sjeff * Port num is 1..N
302219820Sjeff **********************************************************************/
303219820Sjeffstatic ib_api_status_t
304219820Sjeff__parse_port_info_file(IN osm_vendor_t * const p_vend,
305219820Sjeff		       IN uint32_t hca_idx,
306219820Sjeff		       IN uint8_t port_num, OUT sim_port_info_t * sim_port_info)
307219820Sjeff{
308219820Sjeff	ib_api_status_t status = IB_ERROR;
309219820Sjeff	int info_file;
310219820Sjeff	char file_name[256];
311219820Sjeff	char file_buffer[3200];
312219820Sjeff	char state[12];
313219820Sjeff	char *p_ch;
314219820Sjeff	int lid, sm_lid, lmc, sm_sl;
315219820Sjeff	uint32_t len;
316219820Sjeff
317219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
318219820Sjeff
319219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
320219820Sjeff		"__parse_port_info_file: "
321219820Sjeff		"Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx,
322219820Sjeff		port_num);
323219820Sjeff
324219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
325219820Sjeff	sprintf(file_name, "%s/ca%d/port%d/info", __get_simulator_dir(),
326219820Sjeff		hca_idx, port_num);
327219820Sjeff	info_file = open(file_name, O_RDONLY);
328219820Sjeff	if (!info_file) {
329219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
330219820Sjeff			"__parse_port_info_file: ERR 5112: "
331219820Sjeff			"Fail to open HCA:%d Port:%d info file:(%s).\n",
332219820Sjeff			hca_idx, port_num, file_name);
333219820Sjeff		goto Exit;
334219820Sjeff	}
335219820Sjeff
336219820Sjeff	/* read in the file */
337219820Sjeff	len = read(info_file, file_buffer, 3200);
338219820Sjeff	close(info_file);
339219820Sjeff	file_buffer[len] = '\0';
340219820Sjeff
341219820Sjeff	/*
342219820Sjeff	   parse the file ...
343219820Sjeff	   state:         ACTIVE
344219820Sjeff	   LID:           0x0001
345219820Sjeff	   LMC:           0x0000
346219820Sjeff	   SM LID:        0x0001
347219820Sjeff	   SM SL:         0x0000
348219820Sjeff	   ...
349219820Sjeff	 */
350219820Sjeff	if (!(p_ch = strstr(file_buffer, "state:"))) {
351219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
352219820Sjeff			"__parse_port_info_file: ERR 5113: "
353219820Sjeff			"Fail to obtain port state. In info file:(%s).\n",
354219820Sjeff			file_buffer);
355219820Sjeff		goto Exit;
356219820Sjeff	}
357219820Sjeff	if (sscanf(p_ch, "state: %s", state) != 1) {
358219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
359219820Sjeff			"__parse_port_info_file: ERR 5114: "
360219820Sjeff			"Fail to parse state from info file:(%s).\n", p_ch);
361219820Sjeff		goto Exit;
362219820Sjeff	}
363219820Sjeff
364219820Sjeff	if (!strcmp(state, "ACTIVE"))
365219820Sjeff		sim_port_info->state = IB_LINK_ACTIVE;
366219820Sjeff	else if (!strcmp(state, "DOWN"))
367219820Sjeff		sim_port_info->state = IB_LINK_DOWN;
368219820Sjeff	else if (!strcmp(state, "INIT"))
369219820Sjeff		sim_port_info->state = IB_LINK_INIT;
370219820Sjeff	else if (!strcmp(state, "ARMED"))
371219820Sjeff		sim_port_info->state = IB_LINK_ARMED;
372219820Sjeff	else
373219820Sjeff		sim_port_info->state = 0;
374219820Sjeff
375219820Sjeff	/* get lid */
376219820Sjeff	if (!(p_ch = strstr(file_buffer, "LID:"))) {
377219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
378219820Sjeff			"__parse_port_info_file: ERR 5115: "
379219820Sjeff			"Fail to obtain port lid. In info file:(%s).\n",
380219820Sjeff			file_buffer);
381219820Sjeff		goto Exit;
382219820Sjeff	}
383219820Sjeff	if (sscanf(p_ch, "LID: %x", &lid) != 1) {
384219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
385219820Sjeff			"__parse_port_info_file: ERR 5116: "
386219820Sjeff			"Fail to parse lid from info file:(%s).\n", p_ch);
387219820Sjeff		goto Exit;
388219820Sjeff	}
389219820Sjeff	sim_port_info->lid = lid;
390219820Sjeff	/* get LMC */
391219820Sjeff	if (!(p_ch = strstr(file_buffer, "LMC:"))) {
392219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
393219820Sjeff			"__parse_port_info_file: ERR 5117: "
394219820Sjeff			"Fail to obtain port LMC. In info file:(%s).\n",
395219820Sjeff			file_buffer);
396219820Sjeff		goto Exit;
397219820Sjeff	}
398219820Sjeff	if (sscanf(p_ch, "LMC: %x", &lmc) != 1) {
399219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
400219820Sjeff			"__parse_port_info_file: ERR 5118: "
401219820Sjeff			"Fail to parse LMC from info file:(%s).\n", p_ch);
402219820Sjeff		goto Exit;
403219820Sjeff	}
404219820Sjeff	sim_port_info->lmc = lmc;
405219820Sjeff
406219820Sjeff	/* get SM LID */
407219820Sjeff	if (!(p_ch = strstr(file_buffer, "SM LID:"))) {
408219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
409219820Sjeff			"__parse_port_info_file: ERR 5119: "
410219820Sjeff			"Fail to obtain port SM LID. In info file:(%s).\n",
411219820Sjeff			file_buffer);
412219820Sjeff		goto Exit;
413219820Sjeff	}
414219820Sjeff	if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) {
415219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
416219820Sjeff			"__parse_port_info_file: ERR 5120: "
417219820Sjeff			"Fail to parse SM LID from info file:(%s).\n", p_ch);
418219820Sjeff		goto Exit;
419219820Sjeff	}
420219820Sjeff	sim_port_info->sm_lid = sm_lid;
421219820Sjeff
422219820Sjeff	/* get SM LID */
423219820Sjeff	if (!(p_ch = strstr(file_buffer, "SM SL:"))) {
424219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
425219820Sjeff			"__parse_port_info_file: ERR 5121: "
426219820Sjeff			"Fail to obtain port SM SL. In info file:(%s).\n",
427219820Sjeff			file_buffer);
428219820Sjeff		goto Exit;
429219820Sjeff	}
430219820Sjeff	if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) {
431219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
432219820Sjeff			"__parse_port_info_file: ERR 5122: "
433219820Sjeff			"Fail to parse SM SL from info file:(%s).\n", p_ch);
434219820Sjeff		goto Exit;
435219820Sjeff	}
436219820Sjeff	sim_port_info->sm_sl = sm_sl;
437219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
438219820Sjeff		"__parse_port_info_file:  "
439219820Sjeff		"Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n",
440219820Sjeff		port_num, sim_port_info->state, sim_port_info->lid,
441219820Sjeff		sim_port_info->lmc, sim_port_info->sm_lid,
442219820Sjeff		sim_port_info->sm_sl);
443219820Sjeff
444219820Sjeff	status = IB_SUCCESS;
445219820SjeffExit:
446219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
447219820Sjeff	return status;
448219820Sjeff}
449219820Sjeff
450219820Sjeff/**********************************************************************
451219820Sjeff * Parse the port guid_tbl file to obtain the port guid.
452219820Sjeff * File format is:
453219820Sjeff * [  0] fe80:0000:0000:0000:0002:c900:0120:3472
454219820Sjeff **********************************************************************/
455219820Sjeffstatic ib_api_status_t
456219820Sjeff__get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend,
457219820Sjeff				  IN uint32_t hca_idx,
458219820Sjeff				  IN uint8_t port_num, OUT uint64_t * port_guid)
459219820Sjeff{
460219820Sjeff	ib_api_status_t status = IB_ERROR;
461219820Sjeff	int info_file;
462219820Sjeff	char file_name[256];
463219820Sjeff	char file_buffer[3200];
464219820Sjeff	char *p_ch;
465219820Sjeff	int g[8];
466219820Sjeff	uint32_t len;
467219820Sjeff
468219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
469219820Sjeff
470219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
471219820Sjeff		"__get_port_guid_from_port_gid_tbl: "
472219820Sjeff		"Parsing Proc File System Port Guid Table CA %d Port %d.\n",
473219820Sjeff		hca_idx, port_num);
474219820Sjeff
475219820Sjeff	/* we use the proc file system so we must be able to open the info file .. */
476219820Sjeff	sprintf(file_name, "%s/ca%d/port%d/gid_table",
477219820Sjeff		__get_simulator_dir(), hca_idx, port_num);
478219820Sjeff	info_file = open(file_name, O_RDONLY);
479219820Sjeff	if (!info_file) {
480219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
481219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5123: "
482219820Sjeff			"Fail to open HCA:%d Port:%d gid_table file:(%s).\n",
483219820Sjeff			hca_idx, port_num, file_name);
484219820Sjeff		goto Exit;
485219820Sjeff	}
486219820Sjeff
487219820Sjeff	/* read in the file */
488219820Sjeff	len = read(info_file, file_buffer, 3200);
489219820Sjeff	close(info_file);
490219820Sjeff	file_buffer[len] = '\0';
491219820Sjeff
492219820Sjeff	/*
493219820Sjeff	   parse the file ...
494219820Sjeff	   [  0] fe80:0000:0000:0000:0002:c900:0120:3472
495219820Sjeff	   ...
496219820Sjeff	 */
497219820Sjeff	if (!(p_ch = strstr(file_buffer, "[  0]"))) {
498219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
499219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5124: "
500219820Sjeff			"Fail to obtain first gid index. In gid_table file:(%s).\n",
501219820Sjeff			file_buffer);
502219820Sjeff		goto Exit;
503219820Sjeff	}
504219820Sjeff	if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x",
505219820Sjeff		   &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8)
506219820Sjeff	{
507219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
508219820Sjeff			"__get_port_guid_from_port_gid_tbl: ERR 5125: "
509219820Sjeff			"Fail to parse gid from gid_table file:(%s).\n", p_ch);
510219820Sjeff		goto Exit;
511219820Sjeff	}
512219820Sjeff
513219820Sjeff	*port_guid =
514219820Sjeff	    (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] <<
515219820Sjeff	    16 | g[0];
516219820Sjeff	status = IB_SUCCESS;
517219820SjeffExit:
518219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
519219820Sjeff	return status;
520219820Sjeff}
521219820Sjeff
522219820Sjeff/**********************************************************************
523219820Sjeff * Initialize an Info Struct for the Given HCA by its index 1..N
524219820Sjeff **********************************************************************/
525219820Sjeffstatic ib_api_status_t
526219820Sjeff__osm_ca_info_init(IN osm_vendor_t * const p_vend,
527219820Sjeff		   IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info)
528219820Sjeff{
529219820Sjeff	ib_api_status_t status = IB_ERROR;
530219820Sjeff	uint8_t port_num;
531219820Sjeff	uint64_t port_guid;
532219820Sjeff
533219820Sjeff	sim_ca_info_t sim_ca_info;
534219820Sjeff
535219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
536219820Sjeff
537219820Sjeff	/* parse the CA info file */
538219820Sjeff	if (__parse_ca_info_file(p_vend, idx, &sim_ca_info) != IB_SUCCESS)
539219820Sjeff		goto Exit;
540219820Sjeff
541219820Sjeff	p_ca_info->guid = cl_hton64(sim_ca_info.guid);
542219820Sjeff
543219820Sjeff	/* set size of attributes and allocate them */
544219820Sjeff	p_ca_info->attr_size = 1;
545219820Sjeff	p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t));
546219820Sjeff
547219820Sjeff	p_ca_info->p_attr->ca_guid = p_ca_info->guid;
548219820Sjeff	p_ca_info->p_attr->num_ports = sim_ca_info.num_ports;
549219820Sjeff
550219820Sjeff	/* now obtain the attributes of the ports */
551219820Sjeff	p_ca_info->p_attr->p_port_attr =
552219820Sjeff	    (ib_port_attr_t *) malloc(sim_ca_info.num_ports *
553219820Sjeff				      sizeof(ib_port_attr_t));
554219820Sjeff
555219820Sjeff	/* get all the ports info */
556219820Sjeff	for (port_num = 1; port_num <= sim_ca_info.num_ports; port_num++) {
557219820Sjeff		sim_port_info_t sim_port_info;
558219820Sjeff		/* query the port attributes */
559219820Sjeff		if (__parse_port_info_file
560219820Sjeff		    (p_vend, idx, port_num, &sim_port_info)) {
561219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
562219820Sjeff				"__osm_ca_info_init: ERR 5126: "
563219820Sjeff				"Fail to get HCA:%d Port:%d Attributes.\n", idx,
564219820Sjeff				port_num);
565219820Sjeff			goto Exit;
566219820Sjeff		}
567219820Sjeff
568219820Sjeff		/* HACK: the lids should have been converted to network but the rest of the code
569219820Sjeff		   is wrong and provdes them as is (host order) - so we stick with it. */
570219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].lid =
571219820Sjeff		    sim_port_info.lid;
572219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].link_state =
573219820Sjeff		    sim_port_info.state;
574219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid =
575219820Sjeff		    sim_port_info.sm_lid;
576219820Sjeff
577219820Sjeff		/* get the port guid */
578219820Sjeff		if (__get_port_guid_from_port_gid_tbl
579219820Sjeff		    (p_vend, idx, port_num, &port_guid)) {
580219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
581219820Sjeff				"__osm_ca_info_init: ERR 5127: "
582219820Sjeff				"Fail to get HCA:%d Port:%d Guid.\n", idx,
583219820Sjeff				port_num);
584219820Sjeff			goto Exit;
585219820Sjeff		}
586219820Sjeff		p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid =
587219820Sjeff		    cl_hton64(port_guid);
588219820Sjeff	}
589219820Sjeff
590219820Sjeff	status = IB_SUCCESS;
591219820SjeffExit:
592219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
593219820Sjeff	return (status);
594219820Sjeff}
595219820Sjeff
596219820Sjeff/**********************************************************************
597219820Sjeff **********************************************************************/
598219820Sjeffvoid
599219820Sjeffosm_ca_info_destroy(IN osm_vendor_t * const p_vend,
600219820Sjeff		    IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca)
601219820Sjeff{
602219820Sjeff	osm_ca_info_t *p_ca;
603219820Sjeff	uint8_t i;
604219820Sjeff
605219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
606219820Sjeff
607219820Sjeff	for (i = 0; i < num_ca; i++) {
608219820Sjeff		p_ca = &p_ca_info[i];
609219820Sjeff
610219820Sjeff		if (NULL != p_ca->p_attr) {
611219820Sjeff			if (0 != p_ca->p_attr->num_ports) {
612219820Sjeff				free(p_ca->p_attr->p_port_attr);
613219820Sjeff			}
614219820Sjeff
615219820Sjeff			free(p_ca->p_attr);
616219820Sjeff		}
617219820Sjeff	}
618219820Sjeff
619219820Sjeff	free(p_ca_info);
620219820Sjeff
621219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
622219820Sjeff}
623219820Sjeff
624219820Sjeff/**********************************************************************
625219820Sjeff * Fill in the array of port_attr with all available ports on ALL the
626219820Sjeff * avilable CAs on this machine.
627219820Sjeff **********************************************************************/
628219820Sjeffib_api_status_t
629219820Sjeffosm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
630219820Sjeff			     IN ib_port_attr_t * const p_attr_array,
631219820Sjeff			     IN uint32_t * const p_num_ports)
632219820Sjeff{
633219820Sjeff	ib_api_status_t status = IB_SUCCESS;
634219820Sjeff
635219820Sjeff	uint32_t caIdx;
636219820Sjeff	uint32_t ca_count = 0;
637219820Sjeff	uint32_t port_count = 0;
638219820Sjeff	uint8_t port_num;
639219820Sjeff	uint32_t total_ports = 0;
640219820Sjeff	osm_ca_info_t *p_ca_infos = NULL;
641219820Sjeff	uint32_t attr_array_sz = *p_num_ports;
642219820Sjeff
643219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
644219820Sjeff
645219820Sjeff	CL_ASSERT(p_vend);
646219820Sjeff
647219820Sjeff	/* determine the number of CA's */
648219820Sjeff	ca_count = __hca_sim_get_num_cas();
649219820Sjeff	if (!ca_count) {
650219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
651219820Sjeff			"osm_vendor_get_all_port_attr: ERR 5128: "
652219820Sjeff			"Fail to get Any CA Ids.\n");
653219820Sjeff		goto Exit;
654219820Sjeff	}
655219820Sjeff
656219820Sjeff	/* Allocate an array big enough to hold the ca info objects */
657219820Sjeff	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
658219820Sjeff	if (p_ca_infos == NULL) {
659219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
660219820Sjeff			"osm_vendor_get_all_port_attr: ERR 5129: "
661219820Sjeff			"Unable to allocate CA information array.\n");
662219820Sjeff		goto Exit;
663219820Sjeff	}
664219820Sjeff
665219820Sjeff	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));
666219820Sjeff
667219820Sjeff	/*
668219820Sjeff	 * For each CA, retrieve the CA info attributes
669219820Sjeff	 */
670219820Sjeff	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
671219820Sjeff		status =
672219820Sjeff		    __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]);
673219820Sjeff		if (status != IB_SUCCESS) {
674219820Sjeff			osm_log(p_vend->p_log, OSM_LOG_ERROR,
675219820Sjeff				"osm_vendor_get_all_port_attr: ERR 5130: "
676219820Sjeff				"Unable to initialize CA Info object (%s).\n",
677219820Sjeff				ib_get_err_str(status));
678219820Sjeff			goto Exit;
679219820Sjeff		}
680219820Sjeff		total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports;
681219820Sjeff	}
682219820Sjeff
683219820Sjeff	*p_num_ports = total_ports;
684219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
685219820Sjeff		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);
686219820Sjeff
687219820Sjeff	/*
688219820Sjeff	 * If the user supplied enough storage, return the port guids,
689219820Sjeff	 * otherwise, return the appropriate error.
690219820Sjeff	 */
691219820Sjeff	if (attr_array_sz >= total_ports) {
692219820Sjeff		for (caIdx = 1; caIdx <= ca_count; caIdx++) {
693219820Sjeff			uint32_t num_ports;
694219820Sjeff
695219820Sjeff			num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports;
696219820Sjeff
697219820Sjeff			for (port_num = 0; port_num < num_ports; port_num++) {
698219820Sjeff				p_attr_array[port_count] =
699219820Sjeff				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
700219820Sjeff								     [caIdx -
701219820Sjeff								      1],
702219820Sjeff								     port_num);
703219820Sjeff				port_count++;
704219820Sjeff			}
705219820Sjeff		}
706219820Sjeff	} else {
707219820Sjeff		status = IB_INSUFFICIENT_MEMORY;
708219820Sjeff		goto Exit;
709219820Sjeff	}
710219820Sjeff
711219820Sjeff	status = IB_SUCCESS;
712219820Sjeff
713219820SjeffExit:
714219820Sjeff	if (p_ca_infos) {
715219820Sjeff		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
716219820Sjeff	}
717219820Sjeff
718219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
719219820Sjeff	return (status);
720219820Sjeff}
721219820Sjeff
722219820Sjeff/**********************************************************************
723219820Sjeff * Given the vendor obj and a port guid
724219820Sjeff * return the ca id and port number that have that guid
725219820Sjeff **********************************************************************/
726219820Sjeff
727219820Sjeffib_api_status_t
728219820Sjeffosm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend,
729219820Sjeff				IN ib_net64_t const guid,
730219820Sjeff				OUT uint32_t * p_hca_hndl,
731219820Sjeff				OUT char *p_hca_id,
732219820Sjeff				OUT uint8_t * p_hca_idx,
733219820Sjeff				OUT uint32_t * p_port_num)
734219820Sjeff{
735219820Sjeff	uint32_t caIdx;
736219820Sjeff	uint32_t ca_count = 0;
737219820Sjeff	uint8_t port_num;
738219820Sjeff	ib_api_status_t status = IB_ERROR;
739219820Sjeff
740219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
741219820Sjeff
742219820Sjeff	CL_ASSERT(p_vend);
743219820Sjeff
744219820Sjeff	/* determine the number of CA's */
745219820Sjeff	ca_count = __hca_sim_get_num_cas();
746219820Sjeff	if (!ca_count) {
747219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
748219820Sjeff			"osm_vendor_get_guid_ca_and_port: ERR 5131: "
749219820Sjeff			"Fail to get Any CA Ids.\n");
750219820Sjeff		goto Exit;
751219820Sjeff	}
752219820Sjeff
753219820Sjeff	/*
754219820Sjeff	 * For each CA, retrieve the CA info attributes
755219820Sjeff	 */
756219820Sjeff	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
757219820Sjeff		sim_ca_info_t sim_ca_info;
758219820Sjeff		if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
759219820Sjeff		    IB_SUCCESS) {
760219820Sjeff			/* get all the ports info */
761219820Sjeff			for (port_num = 1; port_num <= sim_ca_info.num_ports;
762219820Sjeff			     port_num++) {
763219820Sjeff				uint64_t port_guid;
764219820Sjeff				if (!__get_port_guid_from_port_gid_tbl
765219820Sjeff				    (p_vend, caIdx, port_num, &port_guid)) {
766219820Sjeff					if (cl_hton64(port_guid) == guid) {
767219820Sjeff						osm_log(p_vend->p_log,
768219820Sjeff							OSM_LOG_DEBUG,
769219820Sjeff							"osm_vendor_get_guid_ca_and_port: "
770219820Sjeff							"Found Matching guid on HCA:%d Port:%d.\n",
771219820Sjeff							caIdx, port_num);
772219820Sjeff						strcpy(p_hca_id,
773219820Sjeff						       sim_ca_info.name);
774219820Sjeff						*p_port_num = port_num;
775219820Sjeff						*p_hca_idx = caIdx - 1;
776219820Sjeff						*p_hca_hndl = 0;
777219820Sjeff						status = IB_SUCCESS;
778219820Sjeff						goto Exit;
779219820Sjeff					}
780219820Sjeff				}
781219820Sjeff			}
782219820Sjeff		}
783219820Sjeff	}
784219820Sjeff
785219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_ERROR,
786219820Sjeff		"osm_vendor_get_guid_ca_and_port: ERR 5132: "
787219820Sjeff		"Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n",
788219820Sjeff		cl_ntoh64(guid));
789219820Sjeff	status = IB_INVALID_GUID;
790219820Sjeff
791219820SjeffExit:
792219820Sjeff
793219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
794219820Sjeff	return (status);
795219820Sjeff}
796219820Sjeff
797219820Sjeff/**********************************************************************
798219820Sjeff * Given the vendor obj HCA ID and Port Num
799219820Sjeff * update the given port guid if found. Return 0 on success.
800219820Sjeff **********************************************************************/
801219820Sjeff
802219820Sjeffib_api_status_t
803219820Sjeffosm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend,
804219820Sjeff				   IN char *hca_id,
805219820Sjeff				   IN uint32_t port_num,
806219820Sjeff				   OUT uint64_t * p_port_guid)
807219820Sjeff{
808219820Sjeff	uint32_t caIdx;
809219820Sjeff	uint32_t ca_count = 0;
810219820Sjeff	ib_api_status_t status = IB_ERROR;
811219820Sjeff
812219820Sjeff	OSM_LOG_ENTER(p_vend->p_log);
813219820Sjeff
814219820Sjeff	CL_ASSERT(p_vend);
815219820Sjeff
816219820Sjeff	/* determine the number of CA's */
817219820Sjeff	ca_count = __hca_sim_get_num_cas();
818219820Sjeff	if (!ca_count) {
819219820Sjeff		osm_log(p_vend->p_log, OSM_LOG_ERROR,
820219820Sjeff			"osm_vendor_get_guid_by_ca_and_port: ERR 5133: "
821219820Sjeff			"Fail to get Any CA Ids.\n");
822219820Sjeff		goto Exit;
823219820Sjeff	}
824219820Sjeff
825219820Sjeff	/*
826219820Sjeff	 * For each CA, retrieve the CA info attributes
827219820Sjeff	 */
828219820Sjeff	for (caIdx = 1; caIdx <= ca_count; caIdx++) {
829219820Sjeff		sim_ca_info_t sim_ca_info;
830219820Sjeff		if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) ==
831219820Sjeff		    IB_SUCCESS) {
832219820Sjeff			/* if not identical by id - go to next one */
833219820Sjeff			if (strcmp(sim_ca_info.name, hca_id))
834219820Sjeff				continue;
835219820Sjeff
836219820Sjeff			if ((port_num < 1)
837219820Sjeff			    || (port_num > sim_ca_info.num_ports)) {
838219820Sjeff				return 1;
839219820Sjeff			}
840219820Sjeff
841219820Sjeff			if (!__get_port_guid_from_port_gid_tbl
842219820Sjeff			    (p_vend, caIdx, port_num, p_port_guid)) {
843219820Sjeff				osm_log(p_vend->p_log, OSM_LOG_DEBUG,
844219820Sjeff					"osm_vendor_get_guid_by_ca_and_port: "
845219820Sjeff					"Found Matching guid on HCA:%d Port:%d.\n",
846219820Sjeff					caIdx, port_num);
847219820Sjeff				status = IB_SUCCESS;
848219820Sjeff				goto Exit;
849219820Sjeff			}
850219820Sjeff		}
851219820Sjeff	}
852219820Sjeff
853219820Sjeff	osm_log(p_vend->p_log, OSM_LOG_ERROR,
854219820Sjeff		"osm_vendor_get_guid_by_ca_and_port: ERR 5134: "
855219820Sjeff		"Fail to find HCA:%s\n", hca_id);
856219820Sjeff	status = IB_INVALID_GUID;
857219820Sjeff
858219820SjeffExit:
859219820Sjeff
860219820Sjeff	OSM_LOG_EXIT(p_vend->p_log);
861219820Sjeff	return (status);
862219820Sjeff}
863219820Sjeff
864219820Sjeff#endif
865