xref: /trueos/contrib/ofed/management/opensm/opensm/osm_perfmgr_db.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
2  * Copyright (c) 2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2007 The Regents of the University of California.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34 
35 #if HAVE_CONFIG_H
36 #  include <config.h>
37 #endif				/* HAVE_CONFIG_H */
38 
39 #ifdef ENABLE_OSM_PERF_MGR
40 
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <limits.h>
44 #include <dlfcn.h>
45 #include <sys/stat.h>
46 
47 #include <opensm/osm_perfmgr_db.h>
48 #include <opensm/osm_perfmgr.h>
49 #include <opensm/osm_opensm.h>
50 
51 /** =========================================================================
52  */
perfmgr_db_construct(osm_perfmgr_t * perfmgr)53 perfmgr_db_t *perfmgr_db_construct(osm_perfmgr_t *perfmgr)
54 {
55 	perfmgr_db_t *db = malloc(sizeof(*db));
56 	if (!db)
57 		return (NULL);
58 
59 	cl_qmap_init(&(db->pc_data));
60 	cl_plock_construct(&(db->lock));
61 	cl_plock_init(&(db->lock));
62 	db->perfmgr = perfmgr;
63 	return ((void *)db);
64 }
65 
66 /** =========================================================================
67  */
perfmgr_db_destroy(perfmgr_db_t * db)68 void perfmgr_db_destroy(perfmgr_db_t * db)
69 {
70 	if (db) {
71 		cl_plock_destroy(&(db->lock));
72 		free(db);
73 	}
74 }
75 
76 /**********************************************************************
77  * Internal call db->lock should be held when calling
78  **********************************************************************/
_get(perfmgr_db_t * db,uint64_t guid)79 static inline _db_node_t *_get(perfmgr_db_t * db, uint64_t guid)
80 {
81 	cl_map_item_t *rc = cl_qmap_get(&(db->pc_data), guid);
82 	const cl_map_item_t *end = cl_qmap_end(&(db->pc_data));
83 
84 	if (rc == end)
85 		return (NULL);
86 	return ((_db_node_t *) rc);
87 }
88 
bad_node_port(_db_node_t * node,uint8_t port)89 static inline perfmgr_db_err_t bad_node_port(_db_node_t * node, uint8_t port)
90 {
91 	if (!node)
92 		return (PERFMGR_EVENT_DB_GUIDNOTFOUND);
93 	if (port == 0 || port >= node->num_ports)
94 		return (PERFMGR_EVENT_DB_PORTNOTFOUND);
95 	return (PERFMGR_EVENT_DB_SUCCESS);
96 }
97 
98 /** =========================================================================
99  */
__malloc_node(uint64_t guid,uint8_t num_ports,char * name)100 static _db_node_t *__malloc_node(uint64_t guid, uint8_t num_ports, char *name)
101 {
102 	int i = 0;
103 	time_t cur_time = 0;
104 	_db_node_t *rc = malloc(sizeof(*rc));
105 	if (!rc)
106 		return (NULL);
107 
108 	rc->ports = calloc(num_ports, sizeof(_db_port_t));
109 	if (!rc->ports)
110 		goto free_rc;
111 	rc->num_ports = num_ports;
112 	rc->node_guid = guid;
113 
114 	cur_time = time(NULL);
115 	for (i = 0; i < num_ports; i++) {
116 		rc->ports[i].last_reset = cur_time;
117 		rc->ports[i].err_previous.time = cur_time;
118 		rc->ports[i].dc_previous.time = cur_time;
119 	}
120 	snprintf(rc->node_name, NODE_NAME_SIZE, "%s", name);
121 
122 	return (rc);
123 
124 free_rc:
125 	free(rc);
126 	return (NULL);
127 }
128 
129 /** =========================================================================
130  */
__free_node(_db_node_t * node)131 static void __free_node(_db_node_t * node)
132 {
133 	if (!node)
134 		return;
135 	if (node->ports)
136 		free(node->ports);
137 	free(node);
138 }
139 
140 /* insert nodes to the database */
__insert(perfmgr_db_t * db,_db_node_t * node)141 static perfmgr_db_err_t __insert(perfmgr_db_t * db, _db_node_t * node)
142 {
143 	cl_map_item_t *rc = cl_qmap_insert(&(db->pc_data), node->node_guid,
144 					   (cl_map_item_t *) node);
145 
146 	if ((void *)rc != (void *)node)
147 		return (PERFMGR_EVENT_DB_FAIL);
148 	return (PERFMGR_EVENT_DB_SUCCESS);
149 }
150 
151 /**********************************************************************
152  **********************************************************************/
153 perfmgr_db_err_t
perfmgr_db_create_entry(perfmgr_db_t * db,uint64_t guid,uint8_t num_ports,char * name)154 perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid,
155 			uint8_t num_ports, char *name)
156 {
157 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
158 
159 	cl_plock_excl_acquire(&(db->lock));
160 	if (!_get(db, guid)) {
161 		_db_node_t *pc_node = __malloc_node(guid, num_ports, name);
162 		if (!pc_node) {
163 			rc = PERFMGR_EVENT_DB_NOMEM;
164 			goto Exit;
165 		}
166 		if (__insert(db, pc_node)) {
167 			__free_node(pc_node);
168 			rc = PERFMGR_EVENT_DB_FAIL;
169 			goto Exit;
170 		}
171 	}
172 Exit:
173 	cl_plock_release(&(db->lock));
174 	return (rc);
175 }
176 
177 /**********************************************************************
178  * Dump a reading vs the previous reading to stdout
179  **********************************************************************/
180 static inline void
debug_dump_err_reading(perfmgr_db_t * db,uint64_t guid,uint8_t port_num,_db_port_t * port,perfmgr_db_err_reading_t * cur)181 debug_dump_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num,
182 		       _db_port_t * port, perfmgr_db_err_reading_t * cur)
183 {
184 	osm_log_t *log = db->perfmgr->log;
185 
186 	if (!osm_log_is_active(log, OSM_LOG_DEBUG))
187 		return;		/* optimize this a bit */
188 
189 	osm_log(log, OSM_LOG_DEBUG,
190 		"GUID 0x%" PRIx64 " Port %u:\n", guid, port_num);
191 	osm_log(log, OSM_LOG_DEBUG,
192 		"sym %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
193 		cur->symbol_err_cnt, port->err_previous.symbol_err_cnt,
194 		port->err_total.symbol_err_cnt);
195 	osm_log(log, OSM_LOG_DEBUG,
196 		"ler %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
197 		cur->link_err_recover, port->err_previous.link_err_recover,
198 		port->err_total.link_err_recover);
199 	osm_log(log, OSM_LOG_DEBUG,
200 		"ld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
201 		cur->link_downed, port->err_previous.link_downed,
202 		port->err_total.link_downed);
203 	osm_log(log, OSM_LOG_DEBUG,
204 		"re %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_err,
205 		port->err_previous.rcv_err, port->err_total.rcv_err);
206 	osm_log(log, OSM_LOG_DEBUG,
207 		"rrp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
208 		cur->rcv_rem_phys_err, port->err_previous.rcv_rem_phys_err,
209 		port->err_total.rcv_rem_phys_err);
210 	osm_log(log, OSM_LOG_DEBUG,
211 		"rsr %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
212 		cur->rcv_switch_relay_err,
213 		port->err_previous.rcv_switch_relay_err,
214 		port->err_total.rcv_switch_relay_err);
215 	osm_log(log, OSM_LOG_DEBUG,
216 		"xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
217 		cur->xmit_discards, port->err_previous.xmit_discards,
218 		port->err_total.xmit_discards);
219 	osm_log(log, OSM_LOG_DEBUG,
220 		"xce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
221 		cur->xmit_constraint_err,
222 		port->err_previous.xmit_constraint_err,
223 		port->err_total.xmit_constraint_err);
224 	osm_log(log, OSM_LOG_DEBUG,
225 		"rce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
226 		cur->rcv_constraint_err, port->err_previous.rcv_constraint_err,
227 		port->err_total.rcv_constraint_err);
228 	osm_log(log, OSM_LOG_DEBUG,
229 		"li %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
230 		cur->link_integrity, port->err_previous.link_integrity,
231 		port->err_total.link_integrity);
232 	osm_log(log, OSM_LOG_DEBUG,
233 		"bo %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
234 		cur->buffer_overrun, port->err_previous.buffer_overrun,
235 		port->err_total.buffer_overrun);
236 	osm_log(log, OSM_LOG_DEBUG,
237 		"vld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
238 		cur->vl15_dropped, port->err_previous.vl15_dropped,
239 		port->err_total.vl15_dropped);
240 }
241 
242 /**********************************************************************
243  * perfmgr_db_err_reading_t functions
244  **********************************************************************/
245 perfmgr_db_err_t
perfmgr_db_add_err_reading(perfmgr_db_t * db,uint64_t guid,uint8_t port,perfmgr_db_err_reading_t * reading)246 perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid,
247 			   uint8_t port, perfmgr_db_err_reading_t * reading)
248 {
249 	_db_port_t *p_port = NULL;
250 	_db_node_t *node = NULL;
251 	perfmgr_db_err_reading_t *previous = NULL;
252 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
253 	osm_epi_pe_event_t epi_pe_data;
254 
255 	cl_plock_excl_acquire(&(db->lock));
256 	node = _get(db, guid);
257 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
258 		goto Exit;
259 
260 	p_port = &(node->ports[port]);
261 	previous = &(node->ports[port].err_previous);
262 
263 	debug_dump_err_reading(db, guid, port, p_port, reading);
264 
265 	epi_pe_data.time_diff_s = (reading->time - previous->time);
266 	osm_epi_create_port_id(&(epi_pe_data.port_id), guid, port,
267 			       node->node_name);
268 
269 	/* calculate changes from previous reading */
270 	epi_pe_data.symbol_err_cnt =
271 	    (reading->symbol_err_cnt - previous->symbol_err_cnt);
272 	p_port->err_total.symbol_err_cnt += epi_pe_data.symbol_err_cnt;
273 	epi_pe_data.link_err_recover =
274 	    (reading->link_err_recover - previous->link_err_recover);
275 	p_port->err_total.link_err_recover += epi_pe_data.link_err_recover;
276 	epi_pe_data.link_downed =
277 	    (reading->link_downed - previous->link_downed);
278 	p_port->err_total.link_downed += epi_pe_data.link_downed;
279 	epi_pe_data.rcv_err = (reading->rcv_err - previous->rcv_err);
280 	p_port->err_total.rcv_err += epi_pe_data.rcv_err;
281 	epi_pe_data.rcv_rem_phys_err =
282 	    (reading->rcv_rem_phys_err - previous->rcv_rem_phys_err);
283 	p_port->err_total.rcv_rem_phys_err += epi_pe_data.rcv_rem_phys_err;
284 	epi_pe_data.rcv_switch_relay_err =
285 	    (reading->rcv_switch_relay_err - previous->rcv_switch_relay_err);
286 	p_port->err_total.rcv_switch_relay_err +=
287 	    epi_pe_data.rcv_switch_relay_err;
288 	epi_pe_data.xmit_discards =
289 	    (reading->xmit_discards - previous->xmit_discards);
290 	p_port->err_total.xmit_discards += epi_pe_data.xmit_discards;
291 	epi_pe_data.xmit_constraint_err =
292 	    (reading->xmit_constraint_err - previous->xmit_constraint_err);
293 	p_port->err_total.xmit_constraint_err +=
294 	    epi_pe_data.xmit_constraint_err;
295 	epi_pe_data.rcv_constraint_err =
296 	    (reading->rcv_constraint_err - previous->rcv_constraint_err);
297 	p_port->err_total.rcv_constraint_err += epi_pe_data.rcv_constraint_err;
298 	epi_pe_data.link_integrity =
299 	    (reading->link_integrity - previous->link_integrity);
300 	p_port->err_total.link_integrity += epi_pe_data.link_integrity;
301 	epi_pe_data.buffer_overrun =
302 	    (reading->buffer_overrun - previous->buffer_overrun);
303 	p_port->err_total.buffer_overrun += epi_pe_data.buffer_overrun;
304 	epi_pe_data.vl15_dropped =
305 	    (reading->vl15_dropped - previous->vl15_dropped);
306 	p_port->err_total.vl15_dropped += epi_pe_data.vl15_dropped;
307 
308 	p_port->err_previous = *reading;
309 
310 	osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_ERRORS,
311 				&epi_pe_data);
312 
313 Exit:
314 	cl_plock_release(&(db->lock));
315 	return (rc);
316 }
317 
perfmgr_db_get_prev_err(perfmgr_db_t * db,uint64_t guid,uint8_t port,perfmgr_db_err_reading_t * reading)318 perfmgr_db_err_t perfmgr_db_get_prev_err(perfmgr_db_t * db, uint64_t guid,
319 					 uint8_t port,
320 					 perfmgr_db_err_reading_t * reading)
321 {
322 	_db_node_t *node = NULL;
323 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
324 
325 	cl_plock_acquire(&(db->lock));
326 
327 	node = _get(db, guid);
328 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
329 		goto Exit;
330 
331 	*reading = node->ports[port].err_previous;
332 
333 Exit:
334 	cl_plock_release(&(db->lock));
335 	return (rc);
336 }
337 
338 perfmgr_db_err_t
perfmgr_db_clear_prev_err(perfmgr_db_t * db,uint64_t guid,uint8_t port)339 perfmgr_db_clear_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port)
340 {
341 	_db_node_t *node = NULL;
342 	perfmgr_db_err_reading_t *previous = NULL;
343 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
344 
345 	cl_plock_excl_acquire(&(db->lock));
346 	node = _get(db, guid);
347 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
348 		goto Exit;
349 
350 	previous = &(node->ports[port].err_previous);
351 
352 	memset(previous, 0, sizeof(*previous));
353 	node->ports[port].err_previous.time = time(NULL);
354 
355 Exit:
356 	cl_plock_release(&(db->lock));
357 	return (rc);
358 }
359 
360 static inline void
debug_dump_dc_reading(perfmgr_db_t * db,uint64_t guid,uint8_t port_num,_db_port_t * port,perfmgr_db_data_cnt_reading_t * cur)361 debug_dump_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num,
362 		      _db_port_t * port, perfmgr_db_data_cnt_reading_t * cur)
363 {
364 	osm_log_t *log = db->perfmgr->log;
365 	if (!osm_log_is_active(log, OSM_LOG_DEBUG))
366 		return;		/* optimize this a big */
367 
368 	osm_log(log, OSM_LOG_DEBUG,
369 		"xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
370 		cur->xmit_data, port->dc_previous.xmit_data,
371 		port->dc_total.xmit_data);
372 	osm_log(log, OSM_LOG_DEBUG,
373 		"rd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_data,
374 		port->dc_previous.rcv_data, port->dc_total.rcv_data);
375 	osm_log(log, OSM_LOG_DEBUG,
376 		"xp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n",
377 		cur->xmit_pkts, port->dc_previous.xmit_pkts,
378 		port->dc_total.xmit_pkts);
379 	osm_log(log, OSM_LOG_DEBUG,
380 		"rp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_pkts,
381 		port->dc_previous.rcv_pkts, port->dc_total.rcv_pkts);
382 }
383 
384 /**********************************************************************
385  * perfmgr_db_data_cnt_reading_t functions
386  **********************************************************************/
387 perfmgr_db_err_t
perfmgr_db_add_dc_reading(perfmgr_db_t * db,uint64_t guid,uint8_t port,perfmgr_db_data_cnt_reading_t * reading)388 perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid,
389 			  uint8_t port, perfmgr_db_data_cnt_reading_t * reading)
390 {
391 	_db_port_t *p_port = NULL;
392 	_db_node_t *node = NULL;
393 	perfmgr_db_data_cnt_reading_t *previous = NULL;
394 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
395 	osm_epi_dc_event_t epi_dc_data;
396 
397 	cl_plock_excl_acquire(&(db->lock));
398 	node = _get(db, guid);
399 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
400 		goto Exit;
401 
402 	p_port = &(node->ports[port]);
403 	previous = &(node->ports[port].dc_previous);
404 
405 	debug_dump_dc_reading(db, guid, port, p_port, reading);
406 
407 	epi_dc_data.time_diff_s = (reading->time - previous->time);
408 	osm_epi_create_port_id(&(epi_dc_data.port_id), guid, port,
409 			       node->node_name);
410 
411 	/* calculate changes from previous reading */
412 	epi_dc_data.xmit_data = (reading->xmit_data - previous->xmit_data);
413 	p_port->dc_total.xmit_data += epi_dc_data.xmit_data;
414 	epi_dc_data.rcv_data = (reading->rcv_data - previous->rcv_data);
415 	p_port->dc_total.rcv_data += epi_dc_data.rcv_data;
416 	epi_dc_data.xmit_pkts = (reading->xmit_pkts - previous->xmit_pkts);
417 	p_port->dc_total.xmit_pkts += epi_dc_data.xmit_pkts;
418 	epi_dc_data.rcv_pkts = (reading->rcv_pkts - previous->rcv_pkts);
419 	p_port->dc_total.rcv_pkts += epi_dc_data.rcv_pkts;
420 	epi_dc_data.unicast_xmit_pkts =
421 	    (reading->unicast_xmit_pkts - previous->unicast_xmit_pkts);
422 	p_port->dc_total.unicast_xmit_pkts += epi_dc_data.unicast_xmit_pkts;
423 	epi_dc_data.unicast_rcv_pkts =
424 	    (reading->unicast_rcv_pkts - previous->unicast_rcv_pkts);
425 	p_port->dc_total.unicast_rcv_pkts += epi_dc_data.unicast_rcv_pkts;
426 	epi_dc_data.multicast_xmit_pkts =
427 	    (reading->multicast_xmit_pkts - previous->multicast_xmit_pkts);
428 	p_port->dc_total.multicast_xmit_pkts += epi_dc_data.multicast_xmit_pkts;
429 	epi_dc_data.multicast_rcv_pkts =
430 	    (reading->multicast_rcv_pkts - previous->multicast_rcv_pkts);
431 	p_port->dc_total.multicast_rcv_pkts += epi_dc_data.multicast_rcv_pkts;
432 
433 	p_port->dc_previous = *reading;
434 
435 	osm_opensm_report_event(db->perfmgr->osm,
436 				OSM_EVENT_ID_PORT_DATA_COUNTERS, &epi_dc_data);
437 
438 Exit:
439 	cl_plock_release(&(db->lock));
440 	return (rc);
441 }
442 
perfmgr_db_get_prev_dc(perfmgr_db_t * db,uint64_t guid,uint8_t port,perfmgr_db_data_cnt_reading_t * reading)443 perfmgr_db_err_t perfmgr_db_get_prev_dc(perfmgr_db_t * db, uint64_t guid,
444 					uint8_t port,
445 					perfmgr_db_data_cnt_reading_t * reading)
446 {
447 	_db_node_t *node = NULL;
448 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
449 
450 	cl_plock_acquire(&(db->lock));
451 
452 	node = _get(db, guid);
453 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
454 		goto Exit;
455 
456 	*reading = node->ports[port].dc_previous;
457 
458 Exit:
459 	cl_plock_release(&(db->lock));
460 	return (rc);
461 }
462 
463 perfmgr_db_err_t
perfmgr_db_clear_prev_dc(perfmgr_db_t * db,uint64_t guid,uint8_t port)464 perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port)
465 {
466 	_db_node_t *node = NULL;
467 	perfmgr_db_data_cnt_reading_t *previous = NULL;
468 	perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS;
469 
470 	cl_plock_excl_acquire(&(db->lock));
471 	node = _get(db, guid);
472 	if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS)
473 		goto Exit;
474 
475 	previous = &(node->ports[port].dc_previous);
476 
477 	memset(previous, 0, sizeof(*previous));
478 	node->ports[port].dc_previous.time = time(NULL);
479 
480 Exit:
481 	cl_plock_release(&(db->lock));
482 	return (rc);
483 }
484 
__clear_counters(cl_map_item_t * const p_map_item,void * context)485 static void __clear_counters(cl_map_item_t * const p_map_item, void *context)
486 {
487 	_db_node_t *node = (_db_node_t *) p_map_item;
488 	int i = 0;
489 	time_t ts = time(NULL);
490 
491 	for (i = 0; i < node->num_ports; i++) {
492 		node->ports[i].err_total.symbol_err_cnt = 0;
493 		node->ports[i].err_total.link_err_recover = 0;
494 		node->ports[i].err_total.link_downed = 0;
495 		node->ports[i].err_total.rcv_err = 0;
496 		node->ports[i].err_total.rcv_rem_phys_err = 0;
497 		node->ports[i].err_total.rcv_switch_relay_err = 0;
498 		node->ports[i].err_total.xmit_discards = 0;
499 		node->ports[i].err_total.xmit_constraint_err = 0;
500 		node->ports[i].err_total.rcv_constraint_err = 0;
501 		node->ports[i].err_total.link_integrity = 0;
502 		node->ports[i].err_total.buffer_overrun = 0;
503 		node->ports[i].err_total.vl15_dropped = 0;
504 		node->ports[i].err_total.time = ts;
505 
506 		node->ports[i].dc_total.xmit_data = 0;
507 		node->ports[i].dc_total.rcv_data = 0;
508 		node->ports[i].dc_total.xmit_pkts = 0;
509 		node->ports[i].dc_total.rcv_pkts = 0;
510 		node->ports[i].dc_total.unicast_xmit_pkts = 0;
511 		node->ports[i].dc_total.unicast_rcv_pkts = 0;
512 		node->ports[i].dc_total.multicast_xmit_pkts = 0;
513 		node->ports[i].dc_total.multicast_rcv_pkts = 0;
514 		node->ports[i].dc_total.time = ts;
515 
516 		node->ports[i].last_reset = ts;
517 	}
518 }
519 
520 /**********************************************************************
521  * Clear all the counters from the db
522  **********************************************************************/
perfmgr_db_clear_counters(perfmgr_db_t * db)523 void perfmgr_db_clear_counters(perfmgr_db_t * db)
524 {
525 	cl_plock_excl_acquire(&(db->lock));
526 	cl_qmap_apply_func(&(db->pc_data), __clear_counters, (void *)db);
527 	cl_plock_release(&(db->lock));
528 #if 0
529 	if (db->db_impl->clear_counters)
530 		db->db_impl->clear_counters(db->db_data);
531 #endif
532 }
533 
534 /**********************************************************************
535  * Output a tab delimited output of the port counters
536  **********************************************************************/
__dump_node_mr(_db_node_t * node,FILE * fp)537 static void __dump_node_mr(_db_node_t * node, FILE * fp)
538 {
539 	int i = 0;
540 
541 	fprintf(fp, "\nName\tGUID\tPort\tLast Reset\t"
542 		"%s\t%s\t"
543 		"%s\t%s\t%s\t%s\t%s\t%s\t%s\t"
544 		"%s\t%s\t%s\t%s\t%s\t%s\t%s\t"
545 		"%s\t%s\t%s\t%s\n",
546 		"symbol_err_cnt",
547 		"link_err_recover",
548 		"link_downed",
549 		"rcv_err",
550 		"rcv_rem_phys_err",
551 		"rcv_switch_relay_err",
552 		"xmit_discards",
553 		"xmit_constraint_err",
554 		"rcv_constraint_err",
555 		"link_int_err",
556 		"buf_overrun_err",
557 		"vl15_dropped",
558 		"xmit_data",
559 		"rcv_data",
560 		"xmit_pkts",
561 		"rcv_pkts",
562 		"unicast_xmit_pkts",
563 		"unicast_rcv_pkts",
564 		"multicast_xmit_pkts", "multicast_rcv_pkts");
565 	for (i = 1; i < node->num_ports; i++) {
566 		char *since = ctime(&(node->ports[i].last_reset));
567 		since[strlen(since) - 1] = '\0';	/* remove \n */
568 
569 		fprintf(fp,
570 			"%s\t0x%" PRIx64 "\t%d\t%s\t%" PRIu64 "\t%" PRIu64 "\t"
571 			"%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t"
572 			"%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64
573 			"\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64
574 			"\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64
575 			"\t%" PRIu64 "\t%" PRIu64 "\n", node->node_name,
576 			node->node_guid, i, since,
577 			node->ports[i].err_total.symbol_err_cnt,
578 			node->ports[i].err_total.link_err_recover,
579 			node->ports[i].err_total.link_downed,
580 			node->ports[i].err_total.rcv_err,
581 			node->ports[i].err_total.rcv_rem_phys_err,
582 			node->ports[i].err_total.rcv_switch_relay_err,
583 			node->ports[i].err_total.xmit_discards,
584 			node->ports[i].err_total.xmit_constraint_err,
585 			node->ports[i].err_total.rcv_constraint_err,
586 			node->ports[i].err_total.link_integrity,
587 			node->ports[i].err_total.buffer_overrun,
588 			node->ports[i].err_total.vl15_dropped,
589 			node->ports[i].dc_total.xmit_data,
590 			node->ports[i].dc_total.rcv_data,
591 			node->ports[i].dc_total.xmit_pkts,
592 			node->ports[i].dc_total.rcv_pkts,
593 			node->ports[i].dc_total.unicast_xmit_pkts,
594 			node->ports[i].dc_total.unicast_rcv_pkts,
595 			node->ports[i].dc_total.multicast_xmit_pkts,
596 			node->ports[i].dc_total.multicast_rcv_pkts);
597 	}
598 }
599 
600 /**********************************************************************
601  * Output a human readable output of the port counters
602  **********************************************************************/
__dump_node_hr(_db_node_t * node,FILE * fp)603 static void __dump_node_hr(_db_node_t * node, FILE * fp)
604 {
605 	int i = 0;
606 
607 	fprintf(fp, "\n");
608 	for (i = 1; i < node->num_ports; i++) {
609 		char *since = ctime(&(node->ports[i].last_reset));
610 		since[strlen(since) - 1] = '\0';	/* remove \n */
611 
612 		fprintf(fp, "\"%s\" 0x%" PRIx64 " port %d (Since %s)\n"
613 			"     symbol_err_cnt       : %" PRIu64 "\n"
614 			"     link_err_recover     : %" PRIu64 "\n"
615 			"     link_downed          : %" PRIu64 "\n"
616 			"     rcv_err              : %" PRIu64 "\n"
617 			"     rcv_rem_phys_err     : %" PRIu64 "\n"
618 			"     rcv_switch_relay_err : %" PRIu64 "\n"
619 			"     xmit_discards        : %" PRIu64 "\n"
620 			"     xmit_constraint_err  : %" PRIu64 "\n"
621 			"     rcv_constraint_err   : %" PRIu64 "\n"
622 			"     link_integrity_err   : %" PRIu64 "\n"
623 			"     buf_overrun_err      : %" PRIu64 "\n"
624 			"     vl15_dropped         : %" PRIu64 "\n"
625 			"     xmit_data            : %" PRIu64 "\n"
626 			"     rcv_data             : %" PRIu64 "\n"
627 			"     xmit_pkts            : %" PRIu64 "\n"
628 			"     rcv_pkts             : %" PRIu64 "\n"
629 			"     unicast_xmit_pkts    : %" PRIu64 "\n"
630 			"     unicast_rcv_pkts     : %" PRIu64 "\n"
631 			"     multicast_xmit_pkts  : %" PRIu64 "\n"
632 			"     multicast_rcv_pkts   : %" PRIu64 "\n",
633 			node->node_name,
634 			node->node_guid,
635 			i,
636 			since,
637 			node->ports[i].err_total.symbol_err_cnt,
638 			node->ports[i].err_total.link_err_recover,
639 			node->ports[i].err_total.link_downed,
640 			node->ports[i].err_total.rcv_err,
641 			node->ports[i].err_total.rcv_rem_phys_err,
642 			node->ports[i].err_total.rcv_switch_relay_err,
643 			node->ports[i].err_total.xmit_discards,
644 			node->ports[i].err_total.xmit_constraint_err,
645 			node->ports[i].err_total.rcv_constraint_err,
646 			node->ports[i].err_total.link_integrity,
647 			node->ports[i].err_total.buffer_overrun,
648 			node->ports[i].err_total.vl15_dropped,
649 			node->ports[i].dc_total.xmit_data,
650 			node->ports[i].dc_total.rcv_data,
651 			node->ports[i].dc_total.xmit_pkts,
652 			node->ports[i].dc_total.rcv_pkts,
653 			node->ports[i].dc_total.unicast_xmit_pkts,
654 			node->ports[i].dc_total.unicast_rcv_pkts,
655 			node->ports[i].dc_total.multicast_xmit_pkts,
656 			node->ports[i].dc_total.multicast_rcv_pkts);
657 	}
658 }
659 
660 /* Define a context for the __db_dump callback */
661 typedef struct {
662 	FILE *fp;
663 	perfmgr_db_dump_t dump_type;
664 } dump_context_t;
665 
666 /**********************************************************************
667  **********************************************************************/
__db_dump(cl_map_item_t * const p_map_item,void * context)668 static void __db_dump(cl_map_item_t * const p_map_item, void *context)
669 {
670 	_db_node_t *node = (_db_node_t *) p_map_item;
671 	dump_context_t *c = (dump_context_t *) context;
672 	FILE *fp = c->fp;
673 
674 	switch (c->dump_type) {
675 	case PERFMGR_EVENT_DB_DUMP_MR:
676 		__dump_node_mr(node, fp);
677 		break;
678 	case PERFMGR_EVENT_DB_DUMP_HR:
679 	default:
680 		__dump_node_hr(node, fp);
681 		break;
682 	}
683 }
684 
685 /**********************************************************************
686  * print node data to fp
687  **********************************************************************/
688 void
perfmgr_db_print_by_name(perfmgr_db_t * db,char * nodename,FILE * fp)689 perfmgr_db_print_by_name(perfmgr_db_t * db, char *nodename, FILE *fp)
690 {
691 	cl_map_item_t *item = NULL;
692 	_db_node_t *node = NULL;
693 
694 	cl_plock_acquire(&(db->lock));
695 
696 	/* find the node */
697 	item = cl_qmap_head(&(db->pc_data));
698 	while (item != cl_qmap_end(&(db->pc_data))) {
699 		node = (_db_node_t *)item;
700 		if (strcmp(node->node_name, nodename) == 0) {
701 			__dump_node_hr(node, fp);
702 			goto done;
703 		}
704 		item = cl_qmap_next(item);
705 	}
706 
707 	fprintf(fp, "Node %s not found...\n", nodename);
708 done:
709 	cl_plock_release(&(db->lock));
710 }
711 
712 /**********************************************************************
713  * print node data to fp
714  **********************************************************************/
715 void
perfmgr_db_print_by_guid(perfmgr_db_t * db,uint64_t nodeguid,FILE * fp)716 perfmgr_db_print_by_guid(perfmgr_db_t * db, uint64_t nodeguid, FILE *fp)
717 {
718 	cl_map_item_t *node = NULL;
719 
720 	cl_plock_acquire(&(db->lock));
721 
722 	node = cl_qmap_get(&(db->pc_data), nodeguid);
723 	if (node != cl_qmap_end(&(db->pc_data)))
724 		__dump_node_hr((_db_node_t *)node, fp);
725 	else
726 		fprintf(fp, "Node %"PRIx64" not found...\n", nodeguid);
727 
728 	cl_plock_release(&(db->lock));
729 }
730 
731 /**********************************************************************
732  * dump the data to the file "file"
733  **********************************************************************/
734 perfmgr_db_err_t
perfmgr_db_dump(perfmgr_db_t * db,char * file,perfmgr_db_dump_t dump_type)735 perfmgr_db_dump(perfmgr_db_t * db, char *file, perfmgr_db_dump_t dump_type)
736 {
737 	dump_context_t context;
738 
739 	context.fp = fopen(file, "w+");
740 	if (!context.fp)
741 		return (PERFMGR_EVENT_DB_FAIL);
742 	context.dump_type = dump_type;
743 
744 	cl_plock_acquire(&(db->lock));
745 	cl_qmap_apply_func(&(db->pc_data), __db_dump, (void *)&context);
746 	cl_plock_release(&(db->lock));
747 	fclose(context.fp);
748 	return (PERFMGR_EVENT_DB_SUCCESS);
749 }
750 
751 /**********************************************************************
752  * Fill in the various DB objects from their wire counter parts
753  **********************************************************************/
754 void
perfmgr_db_fill_err_read(ib_port_counters_t * wire_read,perfmgr_db_err_reading_t * reading)755 perfmgr_db_fill_err_read(ib_port_counters_t * wire_read,
756 			 perfmgr_db_err_reading_t * reading)
757 {
758 	reading->symbol_err_cnt = cl_ntoh16(wire_read->symbol_err_cnt);
759 	reading->link_err_recover = cl_ntoh16(wire_read->link_err_recover);
760 	reading->link_downed = wire_read->link_downed;
761 	reading->rcv_err = wire_read->rcv_err;
762 	reading->rcv_rem_phys_err = cl_ntoh16(wire_read->rcv_rem_phys_err);
763 	reading->rcv_switch_relay_err =
764 	    cl_ntoh16(wire_read->rcv_switch_relay_err);
765 	reading->xmit_discards = cl_ntoh16(wire_read->xmit_discards);
766 	reading->xmit_constraint_err =
767 	    cl_ntoh16(wire_read->xmit_constraint_err);
768 	reading->rcv_constraint_err = wire_read->rcv_constraint_err;
769 	reading->link_integrity =
770 	    PC_LINK_INT(wire_read->link_int_buffer_overrun);
771 	reading->buffer_overrun =
772 	    PC_BUF_OVERRUN(wire_read->link_int_buffer_overrun);
773 	reading->vl15_dropped = cl_ntoh16(wire_read->vl15_dropped);
774 	reading->time = time(NULL);
775 }
776 
777 void
perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read,perfmgr_db_data_cnt_reading_t * reading)778 perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read,
779 				 perfmgr_db_data_cnt_reading_t * reading)
780 {
781 	reading->xmit_data = cl_ntoh32(wire_read->xmit_data);
782 	reading->rcv_data = cl_ntoh32(wire_read->rcv_data);
783 	reading->xmit_pkts = cl_ntoh32(wire_read->xmit_pkts);
784 	reading->rcv_pkts = cl_ntoh32(wire_read->rcv_pkts);
785 	reading->unicast_xmit_pkts = 0;
786 	reading->unicast_rcv_pkts = 0;
787 	reading->multicast_xmit_pkts = 0;
788 	reading->multicast_rcv_pkts = 0;
789 	reading->time = time(NULL);
790 }
791 
792 void
perfmgr_db_fill_data_cnt_read_epc(ib_port_counters_ext_t * wire_read,perfmgr_db_data_cnt_reading_t * reading)793 perfmgr_db_fill_data_cnt_read_epc(ib_port_counters_ext_t * wire_read,
794 				  perfmgr_db_data_cnt_reading_t * reading)
795 {
796 	reading->xmit_data = cl_ntoh64(wire_read->xmit_data);
797 	reading->rcv_data = cl_ntoh64(wire_read->rcv_data);
798 	reading->xmit_pkts = cl_ntoh64(wire_read->xmit_pkts);
799 	reading->rcv_pkts = cl_ntoh64(wire_read->rcv_pkts);
800 	reading->unicast_xmit_pkts = cl_ntoh64(wire_read->unicast_xmit_pkts);
801 	reading->unicast_rcv_pkts = cl_ntoh64(wire_read->unicast_rcv_pkts);
802 	reading->multicast_xmit_pkts =
803 	    cl_ntoh64(wire_read->multicast_xmit_pkts);
804 	reading->multicast_rcv_pkts = cl_ntoh64(wire_read->multicast_rcv_pkts);
805 	reading->time = time(NULL);
806 }
807 #endif				/* ENABLE_OSM_PERF_MGR */
808