2 * Copyright (c) 2005-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2009,2010 HNR Consulting. All rights reserved.
4 * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
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:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
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.
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
38 #endif /* HAVE_CONFIG_H */
40 #define _WITH_GETLINE /* for getline */
44 #include <sys/types.h>
45 #include <sys/socket.h>
48 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
49 #include <arpa/inet.h>
50 #include <netinet/in.h>
51 #include <sys/socket.h>
57 #include <opensm/osm_file_ids.h>
58 #define FILE_ID OSM_FILE_CONSOLE_C
59 #include <opensm/osm_console.h>
60 #include <complib/cl_passivelock.h>
61 #include <opensm/osm_perfmgr.h>
62 #include <opensm/osm_subnet.h>
64 extern void osm_update_node_desc(IN osm_opensm_t *osm);
68 void (*help_function) (FILE * out, int detail);
69 void (*parse_function) (char **p_last, osm_opensm_t * p_osm,
77 void (*loop_function) (osm_opensm_t * p_osm, FILE * out);
79 .on = 0, .delay_s = 2, .loop_function = NULL};
81 static const struct command console_cmds[];
83 static char *next_token(char **p_last)
85 return strtok_r(NULL, " \t\n\r", p_last);
88 #ifdef ENABLE_OSM_PERF_MGR
89 static char *name_token(char **p_last)
91 return strtok_r(NULL, "\t\n\r", p_last);
95 static void help_command(FILE * out, int detail)
99 fprintf(out, "Supported commands and syntax:\n");
100 fprintf(out, "help [<command>]\n");
101 /* skip help command */
102 for (i = 1; console_cmds[i].name; i++)
103 console_cmds[i].help_function(out, 0);
106 static void help_quit(FILE * out, int detail)
108 fprintf(out, "quit (not valid in local mode; use ctl-c)\n");
111 static void help_loglevel(FILE * out, int detail)
113 fprintf(out, "loglevel [<log-level>]\n");
115 fprintf(out, " log-level is OR'ed from the following\n");
116 fprintf(out, " OSM_LOG_NONE 0x%02X\n",
118 fprintf(out, " OSM_LOG_ERROR 0x%02X\n",
120 fprintf(out, " OSM_LOG_INFO 0x%02X\n",
122 fprintf(out, " OSM_LOG_VERBOSE 0x%02X\n",
124 fprintf(out, " OSM_LOG_DEBUG 0x%02X\n",
126 fprintf(out, " OSM_LOG_FUNCS 0x%02X\n",
128 fprintf(out, " OSM_LOG_FRAMES 0x%02X\n",
130 fprintf(out, " OSM_LOG_ROUTING 0x%02X\n",
132 fprintf(out, " OSM_LOG_SYS 0x%02X\n",
135 fprintf(out, " OSM_LOG_DEFAULT_LEVEL 0x%02X\n",
136 OSM_LOG_DEFAULT_LEVEL);
140 static void help_permodlog(FILE * out, int detail)
142 fprintf(out, "permodlog\n");
145 static void help_priority(FILE * out, int detail)
147 fprintf(out, "priority [<sm-priority>]\n");
150 static void help_resweep(FILE * out, int detail)
152 fprintf(out, "resweep [heavy|light]\n");
155 static void help_reroute(FILE * out, int detail)
157 fprintf(out, "reroute\n");
159 fprintf(out, "reroute the fabric\n");
163 static void help_sweep(FILE * out, int detail)
165 fprintf(out, "sweep [on|off]\n");
167 fprintf(out, "enable or disable sweeping\n");
168 fprintf(out, " [on] sweep normally\n");
169 fprintf(out, " [off] inhibit all sweeping\n");
173 static void help_status(FILE * out, int detail)
175 fprintf(out, "status [loop]\n");
177 fprintf(out, " loop -- type \"q<ret>\" to quit\n");
181 static void help_logflush(FILE * out, int detail)
183 fprintf(out, "logflush [on|off] -- toggle opensm.log file flushing\n");
186 static void help_querylid(FILE * out, int detail)
189 "querylid lid -- print internal information about the lid specified\n");
192 static void help_portstatus(FILE * out, int detail)
194 fprintf(out, "portstatus [ca|switch|router]\n");
196 fprintf(out, "summarize port status\n");
198 " [ca|switch|router] -- limit the results to the node type specified\n");
203 static void help_switchbalance(FILE * out, int detail)
205 fprintf(out, "switchbalance [verbose] [guid]\n");
207 fprintf(out, "output switch balancing information\n");
209 " [verbose] -- verbose output\n"
210 " [guid] -- limit results to specified guid\n");
214 static void help_lidbalance(FILE * out, int detail)
216 fprintf(out, "lidbalance [switchguid]\n");
218 fprintf(out, "output lid balanced forwarding information\n");
220 " [switchguid] -- limit results to specified switch guid\n");
224 static void help_dump_conf(FILE *out, int detail)
226 fprintf(out, "dump_conf\n");
228 fprintf(out, "dump current opensm configuration\n");
232 static void help_update_desc(FILE *out, int detail)
234 fprintf(out, "update_desc\n");
236 fprintf(out, "update node description for all nodes\n");
240 #ifdef ENABLE_OSM_PERF_MGR
241 static void help_perfmgr(FILE * out, int detail)
244 "perfmgr(pm) [enable|disable\n"
245 " |clear_counters|dump_counters|print_counters(pc)|print_errors(pe)\n"
246 " |set_rm_nodes|clear_rm_nodes|clear_inactive\n"
247 " |set_query_cpi|clear_query_cpi\n"
248 " |dump_redir|clear_redir\n"
249 " |sweep|sweep_time[seconds]]\n");
252 "perfmgr -- print the performance manager state\n");
254 " [enable|disable] -- change the perfmgr state\n");
256 " [sweep] -- Initiate a sweep of the fabric\n");
258 " [sweep_time] -- change the perfmgr sweep time (requires [seconds] option)\n");
260 " [clear_counters] -- clear the counters stored\n");
262 " [dump_counters [mach]] -- dump the counters (optionally in [mach]ine readable format)\n");
264 " [print_counters [<nodename|nodeguid>][:<port>]] -- print the internal counters\n"
265 " Optionally limit output by name, guid, or port\n");
267 " [pc [<nodename|nodeguid>][:<port>]] -- same as print_counters\n");
269 " [print_errors [<nodename|nodeguid>]] -- print only ports with errors\n"
270 " Optionally limit output by name or guid\n");
272 " [pe [<nodename|nodeguid>]] -- same as print_errors\n");
274 " [dump_redir [<nodename|nodeguid>]] -- dump the redirection table\n");
276 " [clear_redir [<nodename|nodeguid>]] -- clear the redirection table\n");
278 " [[set|clear]_rm_nodes] -- enable/disable the removal of \"inactive\" nodes from the DB\n"
279 " Inactive nodes are those which no longer appear on the fabric\n");
281 " [[set|clear]_query_cpi] -- enable/disable PerfMgrGet(ClassPortInfo)\n"
282 " ClassPortInfo indicates hardware support for extended attributes such as PortCountersExtended\n");
284 " [clear_inactive] -- Delete inactive nodes from the DB\n");
287 static void help_pm(FILE *out, int detail)
290 help_perfmgr(out, detail);
292 #endif /* ENABLE_OSM_PERF_MGR */
294 /* more help routines go here */
296 static void help_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
301 p_cmd = next_token(p_last);
303 help_command(out, 0);
305 for (i = 1; console_cmds[i].name; i++) {
306 if (!strcmp(p_cmd, console_cmds[i].name)) {
308 console_cmds[i].help_function(out, 1);
313 fprintf(out, "%s : Command not found\n\n", p_cmd);
314 help_command(out, 0);
319 static void loglevel_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
324 p_cmd = next_token(p_last);
326 fprintf(out, "Current log level is 0x%x\n",
327 osm_log_get_level(&p_osm->log));
329 /* Handle x, 0x, and decimal specification of log level */
330 if (!strncmp(p_cmd, "x", 1)) {
332 level = strtoul(p_cmd, NULL, 16);
334 if (!strncmp(p_cmd, "0x", 2)) {
336 level = strtoul(p_cmd, NULL, 16);
338 level = strtol(p_cmd, NULL, 10);
340 if ((level >= 0) && (level < 256)) {
341 fprintf(out, "Setting log level to 0x%x\n", level);
342 osm_log_set_level(&p_osm->log, level);
344 fprintf(out, "Invalid log level 0x%x\n", level);
348 static void permodlog_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
353 if (p_osm->subn.opt.per_module_logging_file != NULL) {
354 fp = fopen(p_osm->subn.opt.per_module_logging_file, "r");
358 fprintf(out, "fopen(%s) failed: %s\n",
359 p_osm->subn.opt.per_module_logging_file,
364 fprintf(out, "Per module logging file: %s\n",
365 p_osm->subn.opt.per_module_logging_file);
366 while (fgets(buf, sizeof buf, fp) != NULL)
367 fprintf(out, "%s", buf);
373 static void priority_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
378 p_cmd = next_token(p_last);
380 fprintf(out, "Current sm-priority is %d\n",
381 p_osm->subn.opt.sm_priority);
383 priority = strtol(p_cmd, NULL, 0);
384 if (0 > priority || 15 < priority)
386 "Invalid sm-priority %d; must be between 0 and 15\n",
389 fprintf(out, "Setting sm-priority to %d\n", priority);
390 osm_set_sm_priority(&p_osm->sm, (uint8_t)priority);
395 static const char *sm_state_str(int state)
398 case IB_SMINFO_STATE_DISCOVERING:
399 return "Discovering";
400 case IB_SMINFO_STATE_STANDBY:
402 case IB_SMINFO_STATE_NOTACTIVE:
403 return "Not Active ";
404 case IB_SMINFO_STATE_MASTER:
410 static const char *sa_state_str(osm_sa_state_t state)
413 case OSM_SA_STATE_INIT:
415 case OSM_SA_STATE_READY:
421 static void dump_sms(osm_opensm_t * p_osm, FILE * out)
423 osm_subn_t *p_subn = &p_osm->subn;
424 osm_remote_sm_t *p_rsm;
426 fprintf(out, "\n Known SMs\n"
428 fprintf(out, " Port GUID SM State Priority\n");
429 fprintf(out, " --------- -------- --------\n");
430 fprintf(out, " 0x%" PRIx64 " %s %d SELF\n",
431 cl_ntoh64(p_subn->sm_port_guid),
432 sm_state_str(p_subn->sm_state),
433 p_subn->opt.sm_priority);
435 CL_PLOCK_ACQUIRE(p_osm->sm.p_lock);
436 p_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl);
437 while (p_rsm != (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) {
438 fprintf(out, " 0x%" PRIx64 " %s %d\n",
439 cl_ntoh64(p_rsm->smi.guid),
440 sm_state_str(ib_sminfo_get_state(&p_rsm->smi)),
441 ib_sminfo_get_priority(&p_rsm->smi));
442 p_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item);
444 CL_PLOCK_RELEASE(p_osm->sm.p_lock);
447 static void print_status(osm_opensm_t * p_osm, FILE * out)
449 cl_list_item_t *item;
454 cl_plock_acquire(&p_osm->lock);
455 fprintf(out, " OpenSM Version : %s\n", p_osm->osm_version);
456 fprintf(out, " SM State : %s\n",
457 sm_state_str(p_osm->subn.sm_state));
458 fprintf(out, " SM Priority : %d\n",
459 p_osm->subn.opt.sm_priority);
460 fprintf(out, " SA State : %s\n",
461 sa_state_str(p_osm->sa.state));
463 re_str = p_osm->routing_engine_used ?
464 osm_routing_engine_type_str(p_osm->routing_engine_used->type) :
465 osm_routing_engine_type_str(OSM_ROUTING_ENGINE_TYPE_NONE);
466 fprintf(out, " Routing Engine : %s\n", re_str);
468 fprintf(out, " Loaded event plugins :");
469 if (cl_qlist_head(&p_osm->plugin_list) ==
470 cl_qlist_end(&p_osm->plugin_list)) {
471 fprintf(out, " <none>");
473 for (item = cl_qlist_head(&p_osm->plugin_list);
474 item != cl_qlist_end(&p_osm->plugin_list);
475 item = cl_qlist_next(item))
477 ((osm_epi_plugin_t *)item)->plugin_name);
480 #ifdef ENABLE_OSM_PERF_MGR
481 fprintf(out, "\n PerfMgr state/sweep state : %s/%s\n",
482 osm_perfmgr_get_state_str(&p_osm->perfmgr),
483 osm_perfmgr_get_sweep_state_str(&p_osm->perfmgr));
485 fprintf(out, "\n MAD stats\n"
487 " QP0 MADs outstanding : %u\n"
488 " QP0 MADs outstanding (on wire) : %u\n"
489 " QP0 MADs rcvd : %u\n"
490 " QP0 MADs sent : %u\n"
491 " QP0 unicasts sent : %u\n"
492 " QP0 unknown MADs rcvd : %u\n"
493 " SA MADs outstanding : %u\n"
494 " SA MADs rcvd : %u\n"
495 " SA MADs sent : %u\n"
496 " SA unknown MADs rcvd : %u\n"
497 " SA MADs ignored : %u\n",
498 (uint32_t)p_osm->stats.qp0_mads_outstanding,
499 (uint32_t)p_osm->stats.qp0_mads_outstanding_on_wire,
500 (uint32_t)p_osm->stats.qp0_mads_rcvd,
501 (uint32_t)p_osm->stats.qp0_mads_sent,
502 (uint32_t)p_osm->stats.qp0_unicasts_sent,
503 (uint32_t)p_osm->stats.qp0_mads_rcvd_unknown,
504 (uint32_t)p_osm->stats.sa_mads_outstanding,
505 (uint32_t)p_osm->stats.sa_mads_rcvd,
506 (uint32_t)p_osm->stats.sa_mads_sent,
507 (uint32_t)p_osm->stats.sa_mads_rcvd_unknown,
508 (uint32_t)p_osm->stats.sa_mads_ignored);
509 fprintf(out, "\n Subnet flags\n"
511 " Sweeping enabled : %d\n"
512 " Sweep interval (seconds) : %u\n"
513 " Ignore existing lfts : %d\n"
514 " Subnet Init errors : %d\n"
515 " In sweep hop 0 : %d\n"
516 " First time master sweep : %d\n"
517 " Coming out of standby : %d\n",
518 p_osm->subn.sweeping_enabled,
519 p_osm->subn.opt.sweep_interval,
520 p_osm->subn.ignore_existing_lfts,
521 p_osm->subn.subnet_initialization_error,
522 p_osm->subn.in_sweep_hop_0,
523 p_osm->subn.first_time_master_sweep,
524 p_osm->subn.coming_out_of_standby);
525 dump_sms(p_osm, out);
527 cl_plock_release(&p_osm->lock);
531 static int loop_command_check_time(void)
533 time_t cur = time(NULL);
534 if ((loop_command.previous + loop_command.delay_s) < cur) {
535 loop_command.previous = cur;
541 static void status_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
545 p_cmd = next_token(p_last);
547 if (strcmp(p_cmd, "loop") == 0) {
548 fprintf(out, "Looping on status command...\n");
551 loop_command.previous = time(NULL);
552 loop_command.loop_function = print_status;
558 print_status(p_osm, out);
561 static void resweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
565 p_cmd = next_token(p_last);
567 (strcmp(p_cmd, "heavy") != 0 && strcmp(p_cmd, "light") != 0)) {
568 fprintf(out, "Invalid resweep command\n");
569 help_resweep(out, 1);
571 if (strcmp(p_cmd, "heavy") == 0)
572 p_osm->subn.force_heavy_sweep = TRUE;
573 osm_opensm_sweep(p_osm);
577 static void reroute_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
579 p_osm->subn.force_reroute = TRUE;
580 osm_opensm_sweep(p_osm);
583 static void sweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
587 p_cmd = next_token(p_last);
589 (strcmp(p_cmd, "on") != 0 && strcmp(p_cmd, "off") != 0)) {
590 fprintf(out, "Invalid sweep command\n");
593 if (strcmp(p_cmd, "on") == 0)
594 p_osm->subn.sweeping_enabled = TRUE;
596 p_osm->subn.sweeping_enabled = FALSE;
600 static void logflush_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
604 p_cmd = next_token(p_last);
606 (strcmp(p_cmd, "on") != 0 && strcmp(p_cmd, "off") != 0)) {
607 fprintf(out, "Invalid logflush command\n");
610 if (strcmp(p_cmd, "on") == 0) {
611 p_osm->log.flush = TRUE;
612 fflush(p_osm->log.out_port);
614 p_osm->log.flush = FALSE;
618 static void querylid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
622 osm_port_t *p_port = NULL;
623 char *p_cmd = next_token(p_last);
626 fprintf(out, "no LID specified\n");
627 help_querylid(out, 1);
631 lid = (uint16_t) strtoul(p_cmd, NULL, 0);
632 cl_plock_acquire(&p_osm->lock);
633 p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid);
637 fprintf(out, "Query results for LID %u\n", lid);
639 " GUID : 0x%016" PRIx64 "\n"
643 cl_ntoh64(p_port->guid),
644 p_port->p_node->print_desc,
645 ib_get_node_type_str(osm_node_get_type(p_port->p_node)),
646 p_port->p_node->node_info.num_ports);
648 if (p_port->p_node->sw)
652 for ( /* see above */ ; p < p_port->p_node->physp_tbl_size; p++) {
654 " Port %u health : %s\n",
656 p_port->p_node->physp_table[p].
657 healthy ? "OK" : "ERROR");
660 cl_plock_release(&p_osm->lock);
664 cl_plock_release(&p_osm->lock);
665 fprintf(out, "Invalid lid %d\n", lid);
670 * Data structures for the portstatus command
672 typedef struct _port_report {
673 struct _port_report *next;
676 char print_desc[IB_NODE_DESCRIPTION_SIZE + 1];
680 __tag_port_report(port_report_t ** head, uint64_t node_guid,
681 uint8_t port_num, char *print_desc)
683 port_report_t *rep = malloc(sizeof(*rep));
687 rep->node_guid = node_guid;
688 rep->port_num = port_num;
689 memcpy(rep->print_desc, print_desc, IB_NODE_DESCRIPTION_SIZE + 1);
698 static void __print_port_report(FILE * out, port_report_t * head)
700 port_report_t *item = head;
701 while (item != NULL) {
702 fprintf(out, " 0x%016" PRIx64 " %d (%s)\n",
703 item->node_guid, item->port_num, item->print_desc);
704 port_report_t *next = item->next;
711 uint8_t node_type_lim; /* limit the results; 0 == ALL */
712 uint64_t total_nodes;
713 uint64_t total_ports;
715 uint64_t ports_active;
716 uint64_t ports_disabled;
717 port_report_t *disabled_ports;
723 uint64_t ports_unknown_width;
724 port_report_t *unknown_width_ports;
725 uint64_t ports_unenabled_width;
726 port_report_t *unenabled_width_ports;
727 uint64_t ports_reduced_width;
728 port_report_t *reduced_width_ports;
732 uint64_t ports_fdr10;
735 uint64_t ports_unknown_speed;
736 port_report_t *unknown_speed_ports;
737 uint64_t ports_unenabled_speed;
738 port_report_t *unenabled_speed_ports;
739 uint64_t ports_reduced_speed;
740 port_report_t *reduced_speed_ports;
744 * iterator function to get portstatus on each node
746 static void __get_stats(cl_map_item_t * const p_map_item, void *context)
748 fabric_stats_t *fs = (fabric_stats_t *) context;
749 osm_node_t *node = (osm_node_t *) p_map_item;
752 uint8_t num_ports = osm_node_get_num_physp(node);
755 /* Skip nodes we are not interested in */
756 if (fs->node_type_lim != 0
757 && fs->node_type_lim != node->node_info.node_type)
762 if (osm_node_get_type(node) == IB_NODE_TYPE_SWITCH) {
763 physp0 = osm_node_get_physp_ptr(node, 0);
764 pi0 = &physp0->port_info;
768 for (port = 1; port < num_ports; port++) {
769 osm_physp_t *phys = osm_node_get_physp_ptr(node, port);
770 ib_port_info_t *pi = NULL;
771 ib_mlnx_ext_port_info_t *epi = NULL;
772 uint8_t active_speed = 0;
773 uint8_t enabled_speed = 0;
774 uint8_t active_width = 0;
775 uint8_t enabled_width = 0;
776 uint8_t port_state = 0;
777 uint8_t port_phys_state = 0;
782 pi = &phys->port_info;
783 epi = &phys->ext_port_info;
786 active_speed = ib_port_info_get_link_speed_active(pi);
787 enabled_speed = ib_port_info_get_link_speed_enabled(pi);
788 active_width = pi->link_width_active;
789 enabled_width = pi->link_width_enabled;
790 port_state = ib_port_info_get_port_state(pi);
791 port_phys_state = ib_port_info_get_port_phys_state(pi);
793 if (port_state == IB_LINK_DOWN)
795 else if (port_state == IB_LINK_ACTIVE)
797 if (port_phys_state == IB_PORT_PHYS_STATE_DISABLED) {
798 __tag_port_report(&(fs->disabled_ports),
799 cl_ntoh64(node->node_info.node_guid),
800 port, node->print_desc);
801 fs->ports_disabled++;
806 if (port_state == IB_LINK_DOWN)
809 if (!(active_width & enabled_width)) {
810 __tag_port_report(&(fs->unenabled_width_ports),
811 cl_ntoh64(node->node_info.node_guid),
812 port, node->print_desc);
813 fs->ports_unenabled_width++;
815 else if ((enabled_width ^ active_width) > active_width) {
816 __tag_port_report(&(fs->reduced_width_ports),
817 cl_ntoh64(node->node_info.node_guid),
818 port, node->print_desc);
819 fs->ports_reduced_width++;
822 /* unenabled speed usually due to problems with force_link_speed */
823 if (!(active_speed & enabled_speed)) {
824 __tag_port_report(&(fs->unenabled_speed_ports),
825 cl_ntoh64(node->node_info.node_guid),
826 port, node->print_desc);
827 fs->ports_unenabled_speed++;
829 else if ((enabled_speed ^ active_speed) > active_speed) {
830 __tag_port_report(&(fs->reduced_speed_ports),
831 cl_ntoh64(node->node_info.node_guid),
832 port, node->print_desc);
833 fs->ports_reduced_speed++;
836 switch (active_speed) {
837 case IB_LINK_SPEED_ACTIVE_2_5:
840 case IB_LINK_SPEED_ACTIVE_5:
843 case IB_LINK_SPEED_ACTIVE_10:
844 if (!(pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) ||
845 !ib_port_info_get_link_speed_ext_active(pi)) {
846 if (epi->link_speed_active & FDR10)
850 /* check for speed reduced from FDR10 */
851 if (epi->link_speed_enabled & FDR10) {
852 __tag_port_report(&(fs->reduced_speed_ports),
853 cl_ntoh64(node->node_info.node_guid),
854 port, node->print_desc);
855 fs->ports_reduced_speed++;
860 case IB_LINK_SPEED_ACTIVE_EXTENDED:
863 __tag_port_report(&(fs->unknown_speed_ports),
864 cl_ntoh64(node->node_info.node_guid),
865 port, node->print_desc);
866 fs->ports_unknown_speed++;
869 if (pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS &&
870 ib_port_info_get_link_speed_ext_sup(pi) &&
871 (enabled_speed = ib_port_info_get_link_speed_ext_enabled(pi)) != IB_LINK_SPEED_EXT_DISABLE &&
872 active_speed == IB_LINK_SPEED_ACTIVE_10) {
873 active_speed = ib_port_info_get_link_speed_ext_active(pi);
874 if (!(active_speed & enabled_speed)) {
875 __tag_port_report(&(fs->unenabled_speed_ports),
876 cl_ntoh64(node->node_info.node_guid),
877 port, node->print_desc);
878 fs->ports_unenabled_speed++;
880 else if ((enabled_speed ^ active_speed) > active_speed) {
881 __tag_port_report(&(fs->reduced_speed_ports),
882 cl_ntoh64(node->node_info.node_guid),
883 port, node->print_desc);
884 fs->ports_reduced_speed++;
886 switch (active_speed) {
887 case IB_LINK_SPEED_EXT_ACTIVE_14:
890 case IB_LINK_SPEED_EXT_ACTIVE_25:
893 case IB_LINK_SPEED_EXT_ACTIVE_NONE:
896 __tag_port_report(&(fs->unknown_speed_ports),
897 cl_ntoh64(node->node_info.node_guid),
898 port, node->print_desc);
899 fs->ports_unknown_speed++;
903 switch (active_width) {
904 case IB_LINK_WIDTH_ACTIVE_1X:
907 case IB_LINK_WIDTH_ACTIVE_4X:
910 case IB_LINK_WIDTH_ACTIVE_8X:
913 case IB_LINK_WIDTH_ACTIVE_12X:
916 case IB_LINK_WIDTH_ACTIVE_2X:
920 __tag_port_report(&(fs->unknown_width_ports),
921 cl_ntoh64(node->node_info.node_guid),
922 port, node->print_desc);
923 fs->ports_unknown_width++;
929 static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
932 struct timeval before, after;
935 memset(&fs, 0, sizeof(fs));
937 p_cmd = next_token(p_last);
939 if (strcmp(p_cmd, "ca") == 0) {
940 fs.node_type_lim = IB_NODE_TYPE_CA;
941 } else if (strcmp(p_cmd, "switch") == 0) {
942 fs.node_type_lim = IB_NODE_TYPE_SWITCH;
943 } else if (strcmp(p_cmd, "router") == 0) {
944 fs.node_type_lim = IB_NODE_TYPE_ROUTER;
946 fprintf(out, "Node type not understood\n");
947 help_portstatus(out, 1);
952 gettimeofday(&before, NULL);
954 /* for each node in the system gather the stats */
955 cl_plock_acquire(&p_osm->lock);
956 cl_qmap_apply_func(&(p_osm->subn.node_guid_tbl), __get_stats,
958 cl_plock_release(&p_osm->lock);
960 gettimeofday(&after, NULL);
962 /* report the stats */
963 fprintf(out, "\"%s\" port status:\n",
964 fs.node_type_lim ? ib_get_node_type_str(fs.
965 node_type_lim) : "ALL");
967 " %" PRIu64 " port(s) scanned on %" PRIu64
968 " nodes in %lu us\n", fs.total_ports, fs.total_nodes,
969 after.tv_usec - before.tv_usec);
972 fprintf(out, " %" PRIu64 " down\n", fs.ports_down);
974 fprintf(out, " %" PRIu64 " active\n", fs.ports_active);
976 fprintf(out, " %" PRIu64 " at 1X\n", fs.ports_1X);
978 fprintf(out, " %" PRIu64 " at 4X\n", fs.ports_4X);
980 fprintf(out, " %" PRIu64 " at 8X\n", fs.ports_8X);
982 fprintf(out, " %" PRIu64 " at 12X\n", fs.ports_12X);
985 fprintf(out, " %" PRIu64 " at 2.5 Gbps\n", fs.ports_sdr);
987 fprintf(out, " %" PRIu64 " at 5.0 Gbps\n", fs.ports_ddr);
989 fprintf(out, " %" PRIu64 " at 10.0 Gbps\n", fs.ports_qdr);
991 fprintf(out, " %" PRIu64 " at 10.0 Gbps (FDR10)\n", fs.ports_fdr10);
993 fprintf(out, " %" PRIu64 " at 14.0625 Gbps\n", fs.ports_fdr);
995 fprintf(out, " %" PRIu64 " at 25.78125 Gbps\n", fs.ports_edr);
997 if (fs.ports_disabled + fs.ports_reduced_speed + fs.ports_reduced_width
998 + fs.ports_unenabled_width + fs.ports_unenabled_speed
999 + fs.ports_unknown_width + fs.ports_unknown_speed > 0) {
1000 fprintf(out, "\nPossible issues:\n");
1002 if (fs.ports_disabled) {
1003 fprintf(out, " %" PRIu64 " disabled\n", fs.ports_disabled);
1004 __print_port_report(out, fs.disabled_ports);
1006 if (fs.ports_unenabled_speed) {
1007 fprintf(out, " %" PRIu64 " with unenabled speed\n",
1008 fs.ports_unenabled_speed);
1009 __print_port_report(out, fs.unenabled_speed_ports);
1011 if (fs.ports_reduced_speed) {
1012 fprintf(out, " %" PRIu64 " with reduced speed\n",
1013 fs.ports_reduced_speed);
1014 __print_port_report(out, fs.reduced_speed_ports);
1016 if (fs.ports_unknown_speed) {
1017 fprintf(out, " %" PRIu64 " with unknown speed\n",
1018 fs.ports_unknown_speed);
1019 __print_port_report(out, fs.unknown_speed_ports);
1021 if (fs.ports_unenabled_width) {
1022 fprintf(out, " %" PRIu64 " with unenabled width\n",
1023 fs.ports_unenabled_width);
1024 __print_port_report(out, fs.unenabled_width_ports);
1026 if (fs.ports_reduced_width) {
1027 fprintf(out, " %" PRIu64 " with reduced width\n",
1028 fs.ports_reduced_width);
1029 __print_port_report(out, fs.reduced_width_ports);
1031 if (fs.ports_unknown_width) {
1032 fprintf(out, " %" PRIu64 " with unknown width\n",
1033 fs.ports_unknown_width);
1034 __print_port_report(out, fs.unknown_width_ports);
1039 static void switchbalance_check(osm_opensm_t * p_osm,
1040 osm_switch_t * p_sw, FILE * out, int verbose)
1044 const cl_qmap_t *p_port_tbl;
1046 osm_physp_t *p_physp;
1047 osm_physp_t *p_rem_physp;
1048 osm_node_t *p_rem_node;
1049 uint32_t count[255]; /* max ports is a uint8_t */
1050 uint8_t output_ports[255];
1051 uint8_t output_ports_count = 0;
1052 uint32_t min_count = 0xFFFFFFFF;
1053 uint32_t max_count = 0;
1056 memset(count, '\0', sizeof(uint32_t) * 255);
1058 /* Count port usage */
1059 p_port_tbl = &p_osm->subn.port_guid_tbl;
1060 for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
1061 p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
1062 p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
1063 uint16_t min_lid_ho;
1064 uint16_t max_lid_ho;
1067 /* Don't count switches in port usage */
1068 if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
1071 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
1073 if (min_lid_ho == 0 || max_lid_ho == 0)
1076 for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
1077 port_num = osm_switch_get_port_by_lid(p_sw, lid_ho,
1079 if (port_num == OSM_NO_PATH)
1086 num_ports = p_sw->num_ports;
1087 for (port_num = 1; port_num < num_ports; port_num++) {
1088 p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
1090 /* if port is down/unhealthy, don't consider it in
1091 * min/max calculations
1093 if (!p_physp || !osm_physp_is_healthy(p_physp)
1094 || !osm_physp_get_remote(p_physp))
1097 p_rem_physp = osm_physp_get_remote(p_physp);
1098 p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
1100 /* If we are directly connected to a CA/router, its not really
1101 * up for balancing consideration.
1103 if (osm_node_get_type(p_rem_node) != IB_NODE_TYPE_SWITCH)
1106 output_ports[output_ports_count] = port_num;
1107 output_ports_count++;
1109 if (count[port_num] < min_count)
1110 min_count = count[port_num];
1111 if (count[port_num] > max_count)
1112 max_count = count[port_num];
1115 if (verbose || ((max_count - min_count) > 1)) {
1116 if ((max_count - min_count) > 1)
1118 "Unbalanced Switch: 0x%016" PRIx64 " (%s)\n",
1119 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1120 p_sw->p_node->print_desc);
1123 "Switch: 0x%016" PRIx64 " (%s)\n",
1124 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1125 p_sw->p_node->print_desc);
1127 for (i = 0; i < output_ports_count; i++) {
1130 output_ports[i], count[output_ports[i]]);
1135 static void switchbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1142 p_cmd = next_token(p_last);
1146 if (strcmp(p_cmd, "verbose") == 0) {
1148 p_cmd = next_token(p_last);
1152 guid = strtoull(p_cmd, &p_end, 0);
1153 if (!guid || *p_end != '\0') {
1154 fprintf(out, "Invalid guid specified\n");
1155 help_switchbalance(out, 1);
1161 cl_plock_acquire(&p_osm->lock);
1163 p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
1165 fprintf(out, "guid not found\n");
1169 switchbalance_check(p_osm, p_sw, out, verbose);
1171 cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
1172 for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
1173 p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
1174 p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
1175 switchbalance_check(p_osm, p_sw, out, verbose);
1178 cl_plock_release(&p_osm->lock);
1182 static void lidbalance_check(osm_opensm_t * p_osm,
1183 osm_switch_t * p_sw, FILE * out)
1186 const cl_qmap_t *p_port_tbl;
1189 p_port_tbl = &p_osm->subn.port_guid_tbl;
1190 for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
1191 p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
1192 p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
1193 uint32_t port_count[255]; /* max ports is a uint8_t */
1194 osm_node_t *rem_node[255];
1195 uint32_t rem_node_count;
1196 uint32_t rem_count[255];
1197 osm_physp_t *p_physp;
1198 osm_physp_t *p_rem_physp;
1199 osm_node_t *p_rem_node;
1200 uint32_t port_min_count = 0xFFFFFFFF;
1201 uint32_t port_max_count = 0;
1202 uint32_t rem_min_count = 0xFFFFFFFF;
1203 uint32_t rem_max_count = 0;
1204 uint16_t min_lid_ho;
1205 uint16_t max_lid_ho;
1210 /* we only care about non-switches */
1211 if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
1214 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
1216 if (min_lid_ho == 0 || max_lid_ho == 0)
1219 memset(port_count, '\0', sizeof(uint32_t) * 255);
1220 memset(rem_node, '\0', sizeof(osm_node_t *) * 255);
1222 memset(rem_count, '\0', sizeof(uint32_t) * 255);
1224 for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
1225 boolean_t rem_node_found = FALSE;
1226 unsigned int indx = 0;
1228 port_num = osm_switch_get_port_by_lid(p_sw, lid_ho,
1230 if (port_num == OSM_NO_PATH)
1234 osm_node_get_physp_ptr(p_sw->p_node, port_num);
1236 /* if port is down/unhealthy, can't calculate */
1237 if (!p_physp || !osm_physp_is_healthy(p_physp)
1238 || !osm_physp_get_remote(p_physp))
1241 p_rem_physp = osm_physp_get_remote(p_physp);
1242 p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
1244 /* determine if we've seen this remote node before.
1245 * If not, store it. If yes, update the counter
1247 for (i = 0; i < rem_node_count; i++) {
1248 if (rem_node[i] == p_rem_node) {
1249 rem_node_found = TRUE;
1255 if (!rem_node_found) {
1256 rem_node[rem_node_count] = p_rem_node;
1257 rem_count[rem_node_count]++;
1258 indx = rem_node_count;
1263 port_count[port_num]++;
1266 if (!rem_node_count)
1269 for (i = 0; i < rem_node_count; i++) {
1270 if (rem_count[i] < rem_min_count)
1271 rem_min_count = rem_count[i];
1272 if (rem_count[i] > rem_max_count)
1273 rem_max_count = rem_count[i];
1276 num_ports = p_sw->num_ports;
1277 for (i = 0; i < num_ports; i++) {
1280 if (port_count[i] < port_min_count)
1281 port_min_count = port_count[i];
1282 if (port_count[i] > port_max_count)
1283 port_max_count = port_count[i];
1286 /* Output if this CA/router is being forwarded an unbalanced number of
1287 * times to a destination.
1289 if ((rem_max_count - rem_min_count) > 1) {
1291 "Unbalanced Remote Forwarding: Switch 0x%016"
1293 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1294 p_sw->p_node->print_desc);
1295 if (osm_node_get_type(p_port->p_node) ==
1298 else if (osm_node_get_type(p_port->p_node) ==
1299 IB_NODE_TYPE_ROUTER)
1300 fprintf(out, "Router");
1301 fprintf(out, " 0x%016" PRIx64 " (%s): ",
1302 cl_ntoh64(p_port->p_node->node_info.node_guid),
1303 p_port->p_node->print_desc);
1304 for (i = 0; i < rem_node_count; i++) {
1306 "Dest 0x%016" PRIx64 "(%s) - %u ",
1307 cl_ntoh64(rem_node[i]->node_info.
1309 rem_node[i]->print_desc, rem_count[i]);
1314 /* Output if this CA/router is being forwarded through a port
1315 * an unbalanced number of times.
1317 if ((port_max_count - port_min_count) > 1) {
1319 "Unbalanced Port Forwarding: Switch 0x%016"
1321 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1322 p_sw->p_node->print_desc);
1323 if (osm_node_get_type(p_port->p_node) ==
1326 else if (osm_node_get_type(p_port->p_node) ==
1327 IB_NODE_TYPE_ROUTER)
1328 fprintf(out, "Router");
1329 fprintf(out, " 0x%016" PRIx64 " (%s): ",
1330 cl_ntoh64(p_port->p_node->node_info.node_guid),
1331 p_port->p_node->print_desc);
1332 for (i = 0; i < num_ports; i++) {
1335 fprintf(out, "Port %u - %u: ", i,
1343 static void lidbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1349 p_cmd = next_token(p_last);
1353 guid = strtoull(p_cmd, &p_end, 0);
1354 if (!guid || *p_end != '\0') {
1355 fprintf(out, "Invalid switchguid specified\n");
1356 help_lidbalance(out, 1);
1361 cl_plock_acquire(&p_osm->lock);
1363 p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
1365 fprintf(out, "switchguid not found\n");
1368 lidbalance_check(p_osm, p_sw, out);
1370 cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
1371 for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
1372 p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
1373 p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
1374 lidbalance_check(p_osm, p_sw, out);
1378 cl_plock_release(&p_osm->lock);
1382 static void dump_conf_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1384 osm_subn_output_conf(out, &p_osm->subn.opt);
1387 static void update_desc_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1389 osm_update_node_desc(p_osm);
1392 #ifdef ENABLE_OSM_PERF_MGR
1393 static monitored_node_t *find_node_by_name(osm_opensm_t * p_osm,
1396 cl_map_item_t *item;
1397 monitored_node_t *node;
1399 item = cl_qmap_head(&p_osm->perfmgr.monitored_map);
1400 while (item != cl_qmap_end(&p_osm->perfmgr.monitored_map)) {
1401 node = (monitored_node_t *)item;
1402 if (strcmp(node->name, nodename) == 0)
1404 item = cl_qmap_next(item);
1410 static monitored_node_t *find_node_by_guid(osm_opensm_t * p_osm,
1413 cl_map_item_t *node;
1415 node = cl_qmap_get(&p_osm->perfmgr.monitored_map, guid);
1416 if (node != cl_qmap_end(&p_osm->perfmgr.monitored_map))
1417 return (monitored_node_t *)node;
1422 static void dump_redir_entry(monitored_node_t *p_mon_node, FILE * out)
1426 /* only display monitored nodes with redirection info */
1428 for (port = (p_mon_node->esp0) ? 0 : 1;
1429 port < p_mon_node->num_ports; port++) {
1430 if (p_mon_node->port[port].redirection) {
1432 fprintf(out, " Node GUID ESP0 Name\n");
1433 fprintf(out, " --------- ---- ----\n");
1434 fprintf(out, " 0x%" PRIx64 " %d %s\n",
1435 p_mon_node->guid, p_mon_node->esp0,
1437 fprintf(out, "\n Port Valid LIDs PKey QP PKey Index\n");
1438 fprintf(out, " ---- ----- ---- ---- -- ----------\n");
1441 fprintf(out, " %d %d %u->%u 0x%x 0x%x %d\n",
1442 port, p_mon_node->port[port].valid,
1443 cl_ntoh16(p_mon_node->port[port].orig_lid),
1444 cl_ntoh16(p_mon_node->port[port].lid),
1445 cl_ntoh16(p_mon_node->port[port].pkey),
1446 cl_ntoh32(p_mon_node->port[port].qp),
1447 p_mon_node->port[port].pkey_ix);
1454 static void dump_redir(osm_opensm_t * p_osm, char *nodename, FILE * out)
1456 monitored_node_t *p_mon_node;
1459 if (!p_osm->subn.opt.perfmgr_redir)
1460 fprintf(out, "Perfmgr redirection not enabled\n");
1462 fprintf(out, "\nRedirection Table\n");
1463 fprintf(out, "-----------------\n");
1464 cl_plock_acquire(&p_osm->lock);
1466 guid = strtoull(nodename, NULL, 0);
1467 if (guid == 0 && errno)
1468 p_mon_node = find_node_by_name(p_osm, nodename);
1470 p_mon_node = find_node_by_guid(p_osm, guid);
1472 dump_redir_entry(p_mon_node, out);
1474 if (guid == 0 && errno)
1475 fprintf(out, "Node %s not found...\n", nodename);
1477 fprintf(out, "Node 0x%" PRIx64 " not found...\n", guid);
1480 p_mon_node = (monitored_node_t *) cl_qmap_head(&p_osm->perfmgr.monitored_map);
1481 while (p_mon_node != (monitored_node_t *) cl_qmap_end(&p_osm->perfmgr.monitored_map)) {
1482 dump_redir_entry(p_mon_node, out);
1483 p_mon_node = (monitored_node_t *) cl_qmap_next((const cl_map_item_t *)p_mon_node);
1486 cl_plock_release(&p_osm->lock);
1489 static void clear_redir_entry(monitored_node_t *p_mon_node)
1492 ib_net16_t orig_lid;
1494 for (port = (p_mon_node->esp0) ? 0 : 1;
1495 port < p_mon_node->num_ports; port++) {
1496 if (p_mon_node->port[port].redirection) {
1497 orig_lid = p_mon_node->port[port].orig_lid;
1498 memset(&p_mon_node->port[port], 0,
1499 sizeof(monitored_port_t));
1500 p_mon_node->port[port].valid = TRUE;
1501 p_mon_node->port[port].orig_lid = orig_lid;
1506 static void clear_redir(osm_opensm_t * p_osm, char *nodename, FILE * out)
1508 monitored_node_t *p_mon_node;
1511 if (!p_osm->subn.opt.perfmgr_redir)
1512 fprintf(out, "Perfmgr redirection not enabled\n");
1514 cl_plock_acquire(&p_osm->lock);
1516 guid = strtoull(nodename, NULL, 0);
1517 if (guid == 0 && errno)
1518 p_mon_node = find_node_by_name(p_osm, nodename);
1520 p_mon_node = find_node_by_guid(p_osm, guid);
1522 clear_redir_entry(p_mon_node);
1524 if (guid == 0 && errno)
1525 fprintf(out, "Node %s not found...\n", nodename);
1527 fprintf(out, "Node 0x%" PRIx64 " not found...\n", guid);
1530 p_mon_node = (monitored_node_t *) cl_qmap_head(&p_osm->perfmgr.monitored_map);
1531 while (p_mon_node != (monitored_node_t *) cl_qmap_end(&p_osm->perfmgr.monitored_map)) {
1532 clear_redir_entry(p_mon_node);
1533 p_mon_node = (monitored_node_t *) cl_qmap_next((const cl_map_item_t *)p_mon_node);
1536 cl_plock_release(&p_osm->lock);
1539 static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1543 p_cmd = next_token(p_last);
1545 if (strcmp(p_cmd, "enable") == 0) {
1546 osm_perfmgr_set_state(&p_osm->perfmgr,
1547 PERFMGR_STATE_ENABLED);
1548 } else if (strcmp(p_cmd, "disable") == 0) {
1549 osm_perfmgr_set_state(&p_osm->perfmgr,
1550 PERFMGR_STATE_DISABLE);
1551 } else if (strcmp(p_cmd, "clear_counters") == 0) {
1552 osm_perfmgr_clear_counters(&p_osm->perfmgr);
1553 } else if (strcmp(p_cmd, "set_rm_nodes") == 0) {
1554 osm_perfmgr_set_rm_nodes(&p_osm->perfmgr, 1);
1555 } else if (strcmp(p_cmd, "clear_rm_nodes") == 0) {
1556 osm_perfmgr_set_rm_nodes(&p_osm->perfmgr, 0);
1557 } else if (strcmp(p_cmd, "set_query_cpi") == 0) {
1558 osm_perfmgr_set_query_cpi(&p_osm->perfmgr, 1);
1559 } else if (strcmp(p_cmd, "clear_query_cpi") == 0) {
1560 osm_perfmgr_set_query_cpi(&p_osm->perfmgr, 0);
1561 } else if (strcmp(p_cmd, "dump_counters") == 0) {
1562 p_cmd = next_token(p_last);
1563 if (p_cmd && (strcmp(p_cmd, "mach") == 0)) {
1564 osm_perfmgr_dump_counters(&p_osm->perfmgr,
1565 PERFMGR_EVENT_DB_DUMP_MR);
1567 osm_perfmgr_dump_counters(&p_osm->perfmgr,
1568 PERFMGR_EVENT_DB_DUMP_HR);
1570 } else if (strcmp(p_cmd, "clear_inactive") == 0) {
1571 unsigned cnt = osm_perfmgr_delete_inactive(&p_osm->perfmgr);
1572 fprintf(out, "Removed %u nodes from Database\n", cnt);
1573 } else if (strcmp(p_cmd, "print_counters") == 0 ||
1574 strcmp(p_cmd, "pc") == 0) {
1576 p_cmd = name_token(p_last);
1578 port = strchr(p_cmd, ':');
1584 osm_perfmgr_print_counters(&p_osm->perfmgr, p_cmd,
1586 } else if (strcmp(p_cmd, "print_errors") == 0 ||
1587 strcmp(p_cmd, "pe") == 0) {
1588 p_cmd = name_token(p_last);
1589 osm_perfmgr_print_counters(&p_osm->perfmgr, p_cmd,
1591 } else if (strcmp(p_cmd, "dump_redir") == 0) {
1592 p_cmd = name_token(p_last);
1593 dump_redir(p_osm, p_cmd, out);
1594 } else if (strcmp(p_cmd, "clear_redir") == 0) {
1595 p_cmd = name_token(p_last);
1596 clear_redir(p_osm, p_cmd, out);
1597 } else if (strcmp(p_cmd, "sweep_time") == 0) {
1598 p_cmd = next_token(p_last);
1600 uint16_t time_s = atoi(p_cmd);
1603 "sweep_time requires a "
1604 "positive time period "
1605 "(in seconds) to be "
1608 osm_perfmgr_set_sweep_time_s(
1613 "sweep_time requires a time period "
1614 "(in seconds) to be specified\n");
1616 } else if (strcmp(p_cmd, "sweep") == 0) {
1617 osm_sm_signal(&p_osm->sm, OSM_SIGNAL_PERFMGR_SWEEP);
1618 fprintf(out, "sweep initiated...\n");
1620 fprintf(out, "\"%s\" option not found\n", p_cmd);
1623 fprintf(out, "Performance Manager status:\n"
1625 "sweep state : %s\n"
1626 "sweep time : %us\n"
1627 "outstanding queries/max : %d/%u\n"
1628 "remove missing nodes from DB : %s\n"
1629 "query ClassPortInfo : %s\n",
1630 osm_perfmgr_get_state_str(&p_osm->perfmgr),
1631 osm_perfmgr_get_sweep_state_str(&p_osm->perfmgr),
1632 osm_perfmgr_get_sweep_time_s(&p_osm->perfmgr),
1633 p_osm->perfmgr.outstanding_queries,
1634 p_osm->perfmgr.max_outstanding_queries,
1635 osm_perfmgr_get_rm_nodes(&p_osm->perfmgr)
1637 osm_perfmgr_get_query_cpi(&p_osm->perfmgr)
1638 ? "TRUE" : "FALSE");
1641 #endif /* ENABLE_OSM_PERF_MGR */
1643 static void quit_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1645 cio_close(&p_osm->console, &p_osm->log);
1648 static void help_version(FILE * out, int detail)
1650 fprintf(out, "version -- print the OSM version\n");
1653 static void version_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1655 fprintf(out, "%s build %s %s\n", p_osm->osm_version, __DATE__, __TIME__);
1658 /* more parse routines go here */
1659 typedef struct _regexp_list {
1661 struct _regexp_list *next;
1664 static void dump_portguid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1666 cl_qmap_t *p_alias_port_guid_tbl;
1667 osm_alias_guid_t *p_alias_guid, *p_next_alias_guid;
1668 regexp_list_t *p_regexp, *p_head_regexp = NULL;
1672 char *p_cmd = next_token(p_last);
1676 if (strcmp(p_cmd, "file") == 0) {
1677 p_cmd = next_token(p_last);
1679 output = fopen(p_cmd, "w+");
1680 if (output == NULL) {
1682 "Could not open file %s: %s\n",
1683 p_cmd, strerror(errno));
1687 fprintf(out, "No file name passed\n");
1688 } else if (!(p_regexp = malloc(sizeof(*p_regexp)))) {
1689 fprintf(out, "No memory\n");
1691 } else if (regcomp(&p_regexp->exp, p_cmd,
1692 REG_NOSUB | REG_EXTENDED) != 0) {
1693 fprintf(out, "Cannot parse regular expression \'%s\'."
1694 " Skipping\n", p_cmd);
1698 p_regexp->next = p_head_regexp;
1699 p_head_regexp = p_regexp;
1703 /* Check we have at least one expression to match */
1704 if (p_head_regexp == NULL) {
1705 fprintf(out, "No valid expression provided. Aborting\n");
1709 if (p_osm->sm.p_subn->need_update != 0) {
1710 fprintf(out, "Subnet is not ready yet. Try again later\n");
1714 /* Subnet doesn't need to be updated so we can carry on */
1716 p_alias_port_guid_tbl = &(p_osm->sm.p_subn->alias_port_guid_tbl);
1717 CL_PLOCK_ACQUIRE(p_osm->sm.p_lock);
1719 p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_alias_port_guid_tbl);
1720 while (p_next_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_alias_port_guid_tbl)) {
1722 p_alias_guid = p_next_alias_guid;
1724 (osm_alias_guid_t *) cl_qmap_next(&p_next_alias_guid->map_item);
1726 for (p_regexp = p_head_regexp; p_regexp != NULL;
1727 p_regexp = p_regexp->next)
1728 if (regexec(&p_regexp->exp,
1729 p_alias_guid->p_base_port->p_node->print_desc,
1731 fprintf(output, "0x%" PRIxLEAST64 "\n",
1732 cl_ntoh64(p_alias_guid->alias_guid));
1737 CL_PLOCK_RELEASE(p_osm->sm.p_lock);
1740 for (; p_head_regexp; p_head_regexp = p_regexp) {
1741 p_regexp = p_head_regexp->next;
1742 regfree(&p_head_regexp->exp);
1743 free(p_head_regexp);
1750 static void help_dump_portguid(FILE * out, int detail)
1753 "dump_portguid [file filename] regexp1 [regexp2 [regexp3 ...]] -- Dump port GUID matching a regexp \n");
1756 "getguidgetguid -- Dump all the port GUID whom node_desc matches one of the provided regexp\n");
1758 " [file filename] -- Send the port GUID list to the specified file instead of regular output\n");
1763 static const struct command console_cmds[] = {
1764 {"help", &help_command, &help_parse},
1765 {"quit", &help_quit, &quit_parse},
1766 {"loglevel", &help_loglevel, &loglevel_parse},
1767 {"permodlog", &help_permodlog, &permodlog_parse},
1768 {"priority", &help_priority, &priority_parse},
1769 {"resweep", &help_resweep, &resweep_parse},
1770 {"reroute", &help_reroute, &reroute_parse},
1771 {"sweep", &help_sweep, &sweep_parse},
1772 {"status", &help_status, &status_parse},
1773 {"logflush", &help_logflush, &logflush_parse},
1774 {"querylid", &help_querylid, &querylid_parse},
1775 {"portstatus", &help_portstatus, &portstatus_parse},
1776 {"switchbalance", &help_switchbalance, &switchbalance_parse},
1777 {"lidbalance", &help_lidbalance, &lidbalance_parse},
1778 {"dump_conf", &help_dump_conf, &dump_conf_parse},
1779 {"update_desc", &help_update_desc, &update_desc_parse},
1780 {"version", &help_version, &version_parse},
1781 #ifdef ENABLE_OSM_PERF_MGR
1782 {"perfmgr", &help_perfmgr, &perfmgr_parse},
1783 {"pm", &help_pm, &perfmgr_parse},
1784 #endif /* ENABLE_OSM_PERF_MGR */
1785 {"dump_portguid", &help_dump_portguid, &dump_portguid_parse},
1786 {NULL, NULL, NULL} /* end of array */
1789 static void parse_cmd_line(char *line, osm_opensm_t * p_osm)
1791 char *p_cmd, *p_last;
1793 FILE *out = p_osm->console.out;
1795 while (isspace(*line))
1800 /* find first token which is the command */
1801 p_cmd = strtok_r(line, " \t\n\r", &p_last);
1803 for (i = 0; console_cmds[i].name; i++) {
1804 if (loop_command.on) {
1805 if (!strcmp(p_cmd, "q")) {
1806 loop_command.on = 0;
1811 if (!strcmp(p_cmd, console_cmds[i].name)) {
1813 console_cmds[i].parse_function(&p_last, p_osm,
1819 fprintf(out, "%s : Command not found\n\n", p_cmd);
1820 help_command(out, 0);
1823 fprintf(out, "Error parsing command line: `%s'\n", line);
1825 if (loop_command.on) {
1826 fprintf(out, "use \"q<ret>\" to quit loop\n");
1831 int osm_console(osm_opensm_t * p_osm)
1833 struct pollfd pollfd[2];
1839 osm_console_t *p_oct = &p_osm->console;
1841 pollfd[0].fd = p_oct->socket;
1842 pollfd[0].events = POLLIN;
1843 pollfd[0].revents = 0;
1845 pollfd[1].fd = p_oct->in_fd;
1846 pollfd[1].events = POLLIN;
1847 pollfd[1].revents = 0;
1849 fds = p_oct->socket < 0 ? &pollfd[1] : pollfd;
1850 nfds = p_oct->socket < 0 || pollfd[1].fd < 0 ? 1 : 2;
1852 if (loop_command.on && loop_command_check_time() &&
1853 loop_command.loop_function) {
1855 loop_command.loop_function(p_osm, p_oct->out);
1858 loop_command.on = 0;
1862 if (poll(fds, nfds, 1000) <= 0)
1865 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
1866 if (pollfd[0].revents & POLLIN) {
1868 struct sockaddr_in sin;
1869 socklen_t len = sizeof(sin);
1870 struct hostent *hent;
1871 if ((new_fd = accept(p_oct->socket, (struct sockaddr *)&sin, &len)) < 0) {
1872 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
1873 "ERR 4B04: Failed to accept console socket: %s\n",
1879 (AF_INET, &sin.sin_addr, p_oct->client_ip,
1880 sizeof(p_oct->client_ip)) == NULL) {
1881 snprintf(p_oct->client_ip, sizeof(p_oct->client_ip),
1884 if ((hent = gethostbyaddr((const char *)&sin.sin_addr,
1885 sizeof(struct in_addr),
1886 AF_INET)) == NULL) {
1887 snprintf(p_oct->client_hn, sizeof(p_oct->client_hn),
1890 snprintf(p_oct->client_hn, sizeof(p_oct->client_hn),
1891 "%s", hent->h_name);
1893 if (is_authorized(p_oct)) {
1894 cio_open(p_oct, new_fd, &p_osm->log);
1896 OSM_LOG(&p_osm->log, OSM_LOG_ERROR,
1897 "ERR 4B05: Console connection denied: %s (%s)\n",
1898 p_oct->client_hn, p_oct->client_ip);
1905 if (pollfd[1].revents & POLLIN) {
1907 /* Get input line */
1908 n = getline(&p_line, &len, p_oct->in);
1910 /* Parse and act on input */
1911 parse_cmd_line(p_line, p_osm);
1912 if (!loop_command.on) {
1913 osm_console_prompt(p_oct->out);
1916 cio_close(p_oct, &p_osm->log);
1921 /* input fd is closed (hanged up) */
1922 if (pollfd[1].revents & POLLHUP) {
1923 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
1924 /* If we are using a socket, we close the current connection */
1925 if (p_oct->socket >= 0) {
1926 cio_close(p_oct, &p_osm->log);
1930 /* If we use a local console, stdin is closed (most probable is pipe ended)
1931 * so we close the local console */