]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/opensm/opensm/osm_console.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / opensm / opensm / osm_console.c
1 /*
2  * Copyright (c) 2005-2008 Voltaire, Inc. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  *
32  */
33
34 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #endif                          /* HAVE_CONFIG_H */
37
38 #define _GNU_SOURCE             /* for getline */
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <sys/poll.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netdb.h>
45 #ifdef ENABLE_OSM_CONSOLE_SOCKET
46 #include <arpa/inet.h>
47 #endif
48 #include <unistd.h>
49 #include <errno.h>
50 #include <ctype.h>
51 #include <sys/time.h>
52 #include <opensm/osm_console.h>
53 #include <complib/cl_passivelock.h>
54 #include <opensm/osm_perfmgr.h>
55 #include <opensm/osm_subnet.h>
56
57 struct command {
58         char *name;
59         void (*help_function) (FILE * out, int detail);
60         void (*parse_function) (char **p_last, osm_opensm_t * p_osm,
61                                 FILE * out);
62 };
63
64 static struct {
65         int on;
66         int delay_s;
67         time_t previous;
68         void (*loop_function) (osm_opensm_t * p_osm, FILE * out);
69 } loop_command = {
70         .on = 0,
71         .delay_s = 2,
72         .loop_function = NULL,
73 };
74
75 static const struct command console_cmds[];
76
77 static inline char *next_token(char **p_last)
78 {
79         return strtok_r(NULL, " \t\n\r", p_last);
80 }
81
82 static void help_command(FILE * out, int detail)
83 {
84         int i;
85
86         fprintf(out, "Supported commands and syntax:\n");
87         fprintf(out, "help [<command>]\n");
88         /* skip help command */
89         for (i = 1; console_cmds[i].name; i++)
90                 console_cmds[i].help_function(out, 0);
91 }
92
93 static void help_quit(FILE * out, int detail)
94 {
95         fprintf(out, "quit (not valid in local mode; use ctl-c)\n");
96 }
97
98 static void help_loglevel(FILE * out, int detail)
99 {
100         fprintf(out, "loglevel [<log-level>]\n");
101         if (detail) {
102                 fprintf(out, "   log-level is OR'ed from the following\n");
103                 fprintf(out, "   OSM_LOG_NONE             0x%02X\n",
104                         OSM_LOG_NONE);
105                 fprintf(out, "   OSM_LOG_ERROR            0x%02X\n",
106                         OSM_LOG_ERROR);
107                 fprintf(out, "   OSM_LOG_INFO             0x%02X\n",
108                         OSM_LOG_INFO);
109                 fprintf(out, "   OSM_LOG_VERBOSE          0x%02X\n",
110                         OSM_LOG_VERBOSE);
111                 fprintf(out, "   OSM_LOG_DEBUG            0x%02X\n",
112                         OSM_LOG_DEBUG);
113                 fprintf(out, "   OSM_LOG_FUNCS            0x%02X\n",
114                         OSM_LOG_FUNCS);
115                 fprintf(out, "   OSM_LOG_FRAMES           0x%02X\n",
116                         OSM_LOG_FRAMES);
117                 fprintf(out, "   OSM_LOG_ROUTING          0x%02X\n",
118                         OSM_LOG_ROUTING);
119                 fprintf(out, "   OSM_LOG_SYS              0x%02X\n",
120                         OSM_LOG_SYS);
121                 fprintf(out, "\n");
122                 fprintf(out, "   OSM_LOG_DEFAULT_LEVEL    0x%02X\n",
123                         OSM_LOG_DEFAULT_LEVEL);
124         }
125 }
126
127 static void help_priority(FILE * out, int detail)
128 {
129         fprintf(out, "priority [<sm-priority>]\n");
130 }
131
132 static void help_resweep(FILE * out, int detail)
133 {
134         fprintf(out, "resweep [heavy|light]\n");
135 }
136
137 static void help_reroute(FILE * out, int detail)
138 {
139         fprintf(out, "reroute\n");
140         if (detail) {
141                 fprintf(out, "reroute the fabric\n");
142         }
143 }
144
145 static void help_status(FILE * out, int detail)
146 {
147         fprintf(out, "status [loop]\n");
148         if (detail) {
149                 fprintf(out, "   loop -- type \"q<ret>\" to quit\n");
150         }
151 }
152
153 static void help_logflush(FILE * out, int detail)
154 {
155         fprintf(out, "logflush -- flush the opensm.log file\n");
156 }
157
158 static void help_querylid(FILE * out, int detail)
159 {
160         fprintf(out,
161                 "querylid lid -- print internal information about the lid specified\n");
162 }
163
164 static void help_portstatus(FILE * out, int detail)
165 {
166         fprintf(out, "portstatus [ca|switch|router]\n");
167         if (detail) {
168                 fprintf(out, "summarize port status\n");
169                 fprintf(out,
170                         "   [ca|switch|router] -- limit the results to the node type specified\n");
171         }
172
173 }
174
175 static void help_switchbalance(FILE * out, int detail)
176 {
177         fprintf(out, "switchbalance [verbose] [guid]\n");
178         if (detail) {
179                 fprintf(out, "output switch balancing information\n");
180                 fprintf(out,
181                         "  [verbose] -- verbose output\n"
182                         "  [guid] -- limit results to specified guid\n");
183         }
184 }
185
186 static void help_lidbalance(FILE * out, int detail)
187 {
188         fprintf(out, "lidbalance [switchguid]\n");
189         if (detail) {
190                 fprintf(out, "output lid balanced forwarding information\n");
191                 fprintf(out,
192                         "  [switchguid] -- limit results to specified switch guid\n");
193         }
194 }
195
196 static void help_dump_conf(FILE *out, int detail)
197 {
198         fprintf(out, "dump_conf\n");
199         if (detail) {
200                 fprintf(out, "dump current opensm configuration\n");
201         }
202 }
203
204 #ifdef ENABLE_OSM_PERF_MGR
205 static void help_perfmgr(FILE * out, int detail)
206 {
207         fprintf(out,
208                 "perfmgr [enable|disable|clear_counters|dump_counters|sweep_time[seconds]]\n");
209         if (detail) {
210                 fprintf(out,
211                         "perfmgr -- print the performance manager state\n");
212                 fprintf(out,
213                         "   [enable|disable] -- change the perfmgr state\n");
214                 fprintf(out,
215                         "   [sweep_time] -- change the perfmgr sweep time (requires [seconds] option)\n");
216                 fprintf(out,
217                         "   [clear_counters] -- clear the counters stored\n");
218                 fprintf(out,
219                         "   [dump_counters [mach]] -- dump the counters (optionally in [mach]ine readable format)\n");
220                 fprintf(out,
221                         "   [print_counters <nodename|nodeguid>] -- print the counters for the specified node\n");
222         }
223 }
224 #endif                          /* ENABLE_OSM_PERF_MGR */
225
226 /* more help routines go here */
227
228 static void help_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
229 {
230         char *p_cmd;
231         int i, found = 0;
232
233         p_cmd = next_token(p_last);
234         if (!p_cmd)
235                 help_command(out, 0);
236         else {
237                 for (i = 1; console_cmds[i].name; i++) {
238                         if (!strcmp(p_cmd, console_cmds[i].name)) {
239                                 found = 1;
240                                 console_cmds[i].help_function(out, 1);
241                                 break;
242                         }
243                 }
244                 if (!found) {
245                         fprintf(out, "%s : Command not found\n\n", p_cmd);
246                         help_command(out, 0);
247                 }
248         }
249 }
250
251 static void loglevel_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
252 {
253         char *p_cmd;
254         int level;
255
256         p_cmd = next_token(p_last);
257         if (!p_cmd)
258                 fprintf(out, "Current log level is 0x%x\n",
259                         osm_log_get_level(&p_osm->log));
260         else {
261                 /* Handle x, 0x, and decimal specification of log level */
262                 if (!strncmp(p_cmd, "x", 1)) {
263                         p_cmd++;
264                         level = strtoul(p_cmd, NULL, 16);
265                 } else {
266                         if (!strncmp(p_cmd, "0x", 2)) {
267                                 p_cmd += 2;
268                                 level = strtoul(p_cmd, NULL, 16);
269                         } else
270                                 level = strtol(p_cmd, NULL, 10);
271                 }
272                 if ((level >= 0) && (level < 256)) {
273                         fprintf(out, "Setting log level to 0x%x\n", level);
274                         osm_log_set_level(&p_osm->log, level);
275                 } else
276                         fprintf(out, "Invalid log level 0x%x\n", level);
277         }
278 }
279
280 static void priority_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
281 {
282         char *p_cmd;
283         int priority;
284
285         p_cmd = next_token(p_last);
286         if (!p_cmd)
287                 fprintf(out, "Current sm-priority is %d\n",
288                         p_osm->subn.opt.sm_priority);
289         else {
290                 priority = strtol(p_cmd, NULL, 0);
291                 if (0 > priority || 15 < priority)
292                         fprintf(out,
293                                 "Invalid sm-priority %d; must be between 0 and 15\n",
294                                 priority);
295                 else {
296                         fprintf(out, "Setting sm-priority to %d\n", priority);
297                         osm_set_sm_priority(&p_osm->sm, (uint8_t)priority);
298                 }
299         }
300 }
301
302 static char *sm_state_str(int state)
303 {
304         switch (state) {
305         case IB_SMINFO_STATE_DISCOVERING:
306                 return ("Discovering");
307         case IB_SMINFO_STATE_STANDBY:
308                 return ("Standby");
309         case IB_SMINFO_STATE_NOTACTIVE:
310                 return ("Not Active");
311         case IB_SMINFO_STATE_MASTER:
312                 return ("Master");
313         }
314         return ("UNKNOWN");
315 }
316
317 static char *sa_state_str(osm_sa_state_t state)
318 {
319         switch (state) {
320         case OSM_SA_STATE_INIT:
321                 return ("Init");
322         case OSM_SA_STATE_READY:
323                 return ("Ready");
324         }
325         return ("UNKNOWN");
326 }
327
328 static void print_status(osm_opensm_t * p_osm, FILE * out)
329 {
330         cl_list_item_t *item;
331
332         if (out) {
333                 cl_plock_acquire(&p_osm->lock);
334                 fprintf(out, "   OpenSM Version       : %s\n", p_osm->osm_version);
335                 fprintf(out, "   SM State             : %s\n",
336                         sm_state_str(p_osm->subn.sm_state));
337                 fprintf(out, "   SA State             : %s\n",
338                         sa_state_str(p_osm->sa.state));
339                 fprintf(out, "   Routing Engine       : %s\n",
340                         osm_routing_engine_type_str(p_osm->
341                                                     routing_engine_used));
342
343                 fprintf(out, "   Loaded event plugins :");
344                 if (cl_qlist_head(&p_osm->plugin_list) ==
345                         cl_qlist_end(&p_osm->plugin_list)) {
346                         fprintf(out, " <none>");
347                 }
348                 for (item = cl_qlist_head(&p_osm->plugin_list);
349                      item != cl_qlist_end(&p_osm->plugin_list);
350                      item = cl_qlist_next(item))
351                         fprintf(out, " %s",
352                                 ((osm_epi_plugin_t *)item)->plugin_name);
353                 fprintf(out, "\n");
354
355 #ifdef ENABLE_OSM_PERF_MGR
356                 fprintf(out, "\n   PerfMgr state/sweep state : %s/%s\n",
357                         osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
358                         osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)));
359 #endif
360                 fprintf(out, "\n   MAD stats\n"
361                         "   ---------\n"
362                         "   QP0 MADs outstanding           : %d\n"
363                         "   QP0 MADs outstanding (on wire) : %d\n"
364                         "   QP0 MADs rcvd                  : %d\n"
365                         "   QP0 MADs sent                  : %d\n"
366                         "   QP0 unicasts sent              : %d\n"
367                         "   QP0 unknown MADs rcvd          : %d\n"
368                         "   SA MADs outstanding            : %d\n"
369                         "   SA MADs rcvd                   : %d\n"
370                         "   SA MADs sent                   : %d\n"
371                         "   SA unknown MADs rcvd           : %d\n"
372                         "   SA MADs ignored                : %d\n",
373                         p_osm->stats.qp0_mads_outstanding,
374                         p_osm->stats.qp0_mads_outstanding_on_wire,
375                         p_osm->stats.qp0_mads_rcvd,
376                         p_osm->stats.qp0_mads_sent,
377                         p_osm->stats.qp0_unicasts_sent,
378                         p_osm->stats.qp0_mads_rcvd_unknown,
379                         p_osm->stats.sa_mads_outstanding,
380                         p_osm->stats.sa_mads_rcvd,
381                         p_osm->stats.sa_mads_sent,
382                         p_osm->stats.sa_mads_rcvd_unknown,
383                         p_osm->stats.sa_mads_ignored);
384                 fprintf(out, "\n   Subnet flags\n"
385                         "   ------------\n"
386                         "   Ignore existing lfts           : %d\n"
387                         "   Subnet Init errors             : %d\n"
388                         "   In sweep hop 0                 : %d\n"
389                         "   First time master sweep        : %d\n"
390                         "   Coming out of standby          : %d\n",
391                         p_osm->subn.ignore_existing_lfts,
392                         p_osm->subn.subnet_initialization_error,
393                         p_osm->subn.in_sweep_hop_0,
394                         p_osm->subn.first_time_master_sweep,
395                         p_osm->subn.coming_out_of_standby);
396                 fprintf(out, "\n");
397                 cl_plock_release(&p_osm->lock);
398         }
399 }
400
401 static int loop_command_check_time(void)
402 {
403         time_t cur = time(NULL);
404         if ((loop_command.previous + loop_command.delay_s) < cur) {
405                 loop_command.previous = cur;
406                 return (1);
407         }
408         return (0);
409 }
410
411 static void status_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
412 {
413         char *p_cmd;
414
415         p_cmd = next_token(p_last);
416         if (p_cmd) {
417                 if (strcmp(p_cmd, "loop") == 0) {
418                         fprintf(out, "Looping on status command...\n");
419                         fflush(out);
420                         loop_command.on = 1;
421                         loop_command.previous = time(NULL);
422                         loop_command.loop_function = print_status;
423                 } else {
424                         help_status(out, 1);
425                         return;
426                 }
427         }
428         print_status(p_osm, out);
429 }
430
431 static void resweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
432 {
433         char *p_cmd;
434
435         p_cmd = next_token(p_last);
436         if (!p_cmd ||
437             (strcmp(p_cmd, "heavy") != 0 && strcmp(p_cmd, "light") != 0)) {
438                 fprintf(out, "Invalid resweep command\n");
439                 help_resweep(out, 1);
440         } else {
441                 if (strcmp(p_cmd, "heavy") == 0)
442                         p_osm->subn.force_heavy_sweep = TRUE;
443                 osm_opensm_sweep(p_osm);
444         }
445 }
446
447 static void reroute_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
448 {
449         p_osm->subn.force_reroute = TRUE;
450         osm_opensm_sweep(p_osm);
451 }
452
453 static void logflush_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
454 {
455         fflush(p_osm->log.out_port);
456 }
457
458 static void querylid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
459 {
460         int p = 0;
461         uint16_t lid = 0;
462         osm_port_t *p_port = NULL;
463         char *p_cmd = next_token(p_last);
464
465         if (!p_cmd) {
466                 fprintf(out, "no LID specified\n");
467                 help_querylid(out, 1);
468                 return;
469         }
470
471         lid = (uint16_t) strtoul(p_cmd, NULL, 0);
472         cl_plock_acquire(&p_osm->lock);
473         if (lid > cl_ptr_vector_get_capacity(&(p_osm->subn.port_lid_tbl)))
474                 goto invalid_lid;
475         p_port = cl_ptr_vector_get(&(p_osm->subn.port_lid_tbl), lid);
476         if (!p_port)
477                 goto invalid_lid;
478
479         fprintf(out, "Query results for LID %u\n", lid);
480         fprintf(out,
481                 "   GUID                : 0x%016" PRIx64 "\n"
482                 "   Node Desc           : %s\n"
483                 "   Node Type           : %s\n"
484                 "   Num Ports           : %d\n",
485                 cl_ntoh64(p_port->guid),
486                 p_port->p_node->print_desc,
487                 ib_get_node_type_str(osm_node_get_type(p_port->p_node)),
488                 p_port->p_node->node_info.num_ports);
489
490         if (p_port->p_node->sw)
491                 p = 0;
492         else
493                 p = 1;
494         for ( /* see above */ ; p < p_port->p_node->physp_tbl_size; p++) {
495                 fprintf(out,
496                         "   Port %d health       : %s\n",
497                         p,
498                         p_port->p_node->physp_table[p].
499                         healthy ? "OK" : "ERROR");
500         }
501
502         cl_plock_release(&p_osm->lock);
503         return;
504
505 invalid_lid:
506         cl_plock_release(&p_osm->lock);
507         fprintf(out, "Invalid lid %d\n", lid);
508         return;
509 }
510
511 /**
512  * Data structures for the portstatus command
513  */
514 typedef struct _port_report {
515         struct _port_report *next;
516         uint64_t node_guid;
517         uint8_t port_num;
518         char print_desc[IB_NODE_DESCRIPTION_SIZE + 1];
519 } port_report_t;
520
521 static void
522 __tag_port_report(port_report_t ** head, uint64_t node_guid,
523                   uint8_t port_num, char *print_desc)
524 {
525         port_report_t *rep = malloc(sizeof(*rep));
526         if (!rep)
527                 return;
528
529         rep->node_guid = node_guid;
530         rep->port_num = port_num;
531         memcpy(rep->print_desc, print_desc, IB_NODE_DESCRIPTION_SIZE + 1);
532         rep->next = NULL;
533         if (*head) {
534                 rep->next = *head;
535                 *head = rep;
536         } else
537                 *head = rep;
538 }
539
540 static void __print_port_report(FILE * out, port_report_t * head)
541 {
542         port_report_t *item = head;
543         while (item != NULL) {
544                 fprintf(out, "      0x%016" PRIx64 " %d (%s)\n",
545                         item->node_guid, item->port_num, item->print_desc);
546                 port_report_t *next = item->next;
547                 free(item);
548                 item = next;
549         }
550 }
551
552 typedef struct {
553         uint8_t node_type_lim;  /* limit the results; 0 == ALL */
554         uint64_t total_nodes;
555         uint64_t total_ports;
556         uint64_t ports_down;
557         uint64_t ports_active;
558         uint64_t ports_disabled;
559         port_report_t *disabled_ports;
560         uint64_t ports_1X;
561         uint64_t ports_4X;
562         uint64_t ports_8X;
563         uint64_t ports_12X;
564         uint64_t ports_unknown_width;
565         uint64_t ports_reduced_width;
566         port_report_t *reduced_width_ports;
567         uint64_t ports_sdr;
568         uint64_t ports_ddr;
569         uint64_t ports_qdr;
570         uint64_t ports_unknown_speed;
571         uint64_t ports_reduced_speed;
572         port_report_t *reduced_speed_ports;
573 } fabric_stats_t;
574
575 /**
576  * iterator function to get portstatus on each node
577  */
578 static void __get_stats(cl_map_item_t * const p_map_item, void *context)
579 {
580         fabric_stats_t *fs = (fabric_stats_t *) context;
581         osm_node_t *node = (osm_node_t *) p_map_item;
582         uint8_t num_ports = osm_node_get_num_physp(node);
583         uint8_t port = 0;
584
585         /* Skip nodes we are not interested in */
586         if (fs->node_type_lim != 0
587             && fs->node_type_lim != node->node_info.node_type)
588                 return;
589
590         fs->total_nodes++;
591
592         for (port = 1; port < num_ports; port++) {
593                 osm_physp_t *phys = osm_node_get_physp_ptr(node, port);
594                 ib_port_info_t *pi = NULL;
595                 uint8_t active_speed = 0;
596                 uint8_t enabled_speed = 0;
597                 uint8_t active_width = 0;
598                 uint8_t enabled_width = 0;
599                 uint8_t port_state = 0;
600                 uint8_t port_phys_state = 0;
601
602                 if (!phys)
603                         continue;
604
605                 pi = &(phys->port_info);
606                 active_speed = ib_port_info_get_link_speed_active(pi);
607                 enabled_speed = ib_port_info_get_link_speed_enabled(pi);
608                 active_width = pi->link_width_active;
609                 enabled_width = pi->link_width_enabled;
610                 port_state = ib_port_info_get_port_state(pi);
611                 port_phys_state = ib_port_info_get_port_phys_state(pi);
612
613                 if ((enabled_width ^ active_width) > active_width) {
614                         __tag_port_report(&(fs->reduced_width_ports),
615                                           cl_ntoh64(node->node_info.node_guid),
616                                           port, node->print_desc);
617                         fs->ports_reduced_width++;
618                 }
619
620                 if ((enabled_speed ^ active_speed) > active_speed) {
621                         __tag_port_report(&(fs->reduced_speed_ports),
622                                           cl_ntoh64(node->node_info.node_guid),
623                                           port, node->print_desc);
624                         fs->ports_reduced_speed++;
625                 }
626
627                 switch (active_speed) {
628                 case IB_LINK_SPEED_ACTIVE_2_5:
629                         fs->ports_sdr++;
630                         break;
631                 case IB_LINK_SPEED_ACTIVE_5:
632                         fs->ports_ddr++;
633                         break;
634                 case IB_LINK_SPEED_ACTIVE_10:
635                         fs->ports_qdr++;
636                         break;
637                 default:
638                         fs->ports_unknown_speed++;
639                         break;
640                 }
641                 switch (active_width) {
642                 case IB_LINK_WIDTH_ACTIVE_1X:
643                         fs->ports_1X++;
644                         break;
645                 case IB_LINK_WIDTH_ACTIVE_4X:
646                         fs->ports_4X++;
647                         break;
648                 case IB_LINK_WIDTH_ACTIVE_8X:
649                         fs->ports_8X++;
650                         break;
651                 case IB_LINK_WIDTH_ACTIVE_12X:
652                         fs->ports_12X++;
653                         break;
654                 default:
655                         fs->ports_unknown_width++;
656                         break;
657                 }
658                 if (port_state == IB_LINK_DOWN)
659                         fs->ports_down++;
660                 else if (port_state == IB_LINK_ACTIVE)
661                         fs->ports_active++;
662                 if (port_phys_state == IB_PORT_PHYS_STATE_DISABLED) {
663                         __tag_port_report(&(fs->disabled_ports),
664                                           cl_ntoh64(node->node_info.node_guid),
665                                           port, node->print_desc);
666                         fs->ports_disabled++;
667                 }
668
669                 fs->total_ports++;
670         }
671 }
672
673 static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
674 {
675         fabric_stats_t fs;
676         struct timeval before, after;
677         char *p_cmd;
678
679         memset(&fs, 0, sizeof(fs));
680
681         p_cmd = next_token(p_last);
682         if (p_cmd) {
683                 if (strcmp(p_cmd, "ca") == 0) {
684                         fs.node_type_lim = IB_NODE_TYPE_CA;
685                 } else if (strcmp(p_cmd, "switch") == 0) {
686                         fs.node_type_lim = IB_NODE_TYPE_SWITCH;
687                 } else if (strcmp(p_cmd, "router") == 0) {
688                         fs.node_type_lim = IB_NODE_TYPE_ROUTER;
689                 } else {
690                         fprintf(out, "Node type not understood\n");
691                         help_portstatus(out, 1);
692                         return;
693                 }
694         }
695
696         gettimeofday(&before, NULL);
697
698         /* for each node in the system gather the stats */
699         cl_plock_acquire(&p_osm->lock);
700         cl_qmap_apply_func(&(p_osm->subn.node_guid_tbl), __get_stats,
701                            (void *)&fs);
702         cl_plock_release(&p_osm->lock);
703
704         gettimeofday(&after, NULL);
705
706         /* report the stats */
707         fprintf(out, "\"%s\" port status:\n",
708                 fs.node_type_lim ? ib_get_node_type_str(fs.
709                                                         node_type_lim) : "ALL");
710         fprintf(out,
711                 "   %" PRIu64 " port(s) scanned on %" PRIu64
712                 " nodes in %lu us\n", fs.total_ports, fs.total_nodes,
713                 after.tv_usec - before.tv_usec);
714
715         if (fs.ports_down)
716                 fprintf(out, "   %" PRIu64 " down\n", fs.ports_down);
717         if (fs.ports_active)
718                 fprintf(out, "   %" PRIu64 " active\n", fs.ports_active);
719         if (fs.ports_1X)
720                 fprintf(out, "   %" PRIu64 " at 1X\n", fs.ports_1X);
721         if (fs.ports_4X)
722                 fprintf(out, "   %" PRIu64 " at 4X\n", fs.ports_4X);
723         if (fs.ports_8X)
724                 fprintf(out, "   %" PRIu64 " at 8X\n", fs.ports_8X);
725         if (fs.ports_12X)
726                 fprintf(out, "   %" PRIu64 " at 12X\n", fs.ports_12X);
727
728         if (fs.ports_sdr)
729                 fprintf(out, "   %" PRIu64 " at 2.5 Gbps\n", fs.ports_sdr);
730         if (fs.ports_ddr)
731                 fprintf(out, "   %" PRIu64 " at 5.0 Gbps\n", fs.ports_ddr);
732         if (fs.ports_qdr)
733                 fprintf(out, "   %" PRIu64 " at 10.0 Gbps\n", fs.ports_qdr);
734
735         if (fs.ports_disabled + fs.ports_reduced_speed + fs.ports_reduced_width
736             > 0) {
737                 fprintf(out, "\nPossible issues:\n");
738         }
739         if (fs.ports_disabled) {
740                 fprintf(out, "   %" PRIu64 " disabled\n", fs.ports_disabled);
741                 __print_port_report(out, fs.disabled_ports);
742         }
743         if (fs.ports_reduced_speed) {
744                 fprintf(out, "   %" PRIu64 " with reduced speed\n",
745                         fs.ports_reduced_speed);
746                 __print_port_report(out, fs.reduced_speed_ports);
747         }
748         if (fs.ports_reduced_width) {
749                 fprintf(out, "   %" PRIu64 " with reduced width\n",
750                         fs.ports_reduced_width);
751                 __print_port_report(out, fs.reduced_width_ports);
752         }
753         fprintf(out, "\n");
754 }
755
756 static void switchbalance_check(osm_opensm_t * p_osm,
757                                 osm_switch_t * p_sw, FILE * out, int verbose)
758 {
759         uint8_t port_num;
760         uint8_t num_ports;
761         const cl_qmap_t *p_port_tbl;
762         osm_port_t *p_port;
763         osm_physp_t *p_physp;
764         osm_physp_t *p_rem_physp;
765         osm_node_t *p_rem_node;
766         uint32_t count[255];    /* max ports is a uint8_t */
767         uint8_t output_ports[255];
768         uint8_t output_ports_count = 0;
769         uint32_t min_count = 0xFFFFFFFF;
770         uint32_t max_count = 0;
771         unsigned int i;
772
773         memset(count, '\0', sizeof(uint32_t) * 255);
774
775         /* Count port usage */
776         p_port_tbl = &p_osm->subn.port_guid_tbl;
777         for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
778              p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
779              p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
780                 uint16_t min_lid_ho;
781                 uint16_t max_lid_ho;
782                 uint16_t lid_ho;
783
784                 /* Don't count switches in port usage */
785                 if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
786                         continue;
787
788                 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
789
790                 if (min_lid_ho == 0 || max_lid_ho == 0)
791                         continue;
792
793                 for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
794                         port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
795                         if (port_num == OSM_NO_PATH)
796                                 continue;
797
798                         count[port_num]++;
799                 }
800         }
801
802         num_ports = p_sw->num_ports;
803         for (port_num = 1; port_num < num_ports; port_num++) {
804                 p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
805
806                 /* if port is down/unhealthy, don't consider it in
807                  * min/max calculations
808                  */
809                 if (!p_physp || !osm_physp_is_healthy(p_physp)
810                     || !osm_physp_get_remote(p_physp))
811                         continue;
812
813                 p_rem_physp = osm_physp_get_remote(p_physp);
814                 p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
815
816                 /* If we are directly connected to a CA/router, its not really
817                  * up for balancing consideration.
818                  */
819                 if (osm_node_get_type(p_rem_node) != IB_NODE_TYPE_SWITCH)
820                         continue;
821
822                 output_ports[output_ports_count] = port_num;
823                 output_ports_count++;
824
825                 if (count[port_num] < min_count)
826                         min_count = count[port_num];
827                 if (count[port_num] > max_count)
828                         max_count = count[port_num];
829         }
830
831         if (verbose || ((max_count - min_count) > 1)) {
832                 if ((max_count - min_count) > 1)
833                         fprintf(out,
834                                 "Unbalanced Switch: 0x%016" PRIx64 " (%s)\n",
835                                 cl_ntoh64(p_sw->p_node->node_info.node_guid),
836                                 p_sw->p_node->print_desc);
837                 else
838                         fprintf(out,
839                                 "Switch: 0x%016" PRIx64 " (%s)\n",
840                                 cl_ntoh64(p_sw->p_node->node_info.node_guid),
841                                 p_sw->p_node->print_desc);
842
843                 for (i = 0; i < output_ports_count; i++) {
844                         fprintf(out,
845                                 "Port %d: %d\n",
846                                 output_ports[i], count[output_ports[i]]);
847                 }
848         }
849 }
850
851 static void switchbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
852 {
853         char *p_cmd;
854         uint64_t guid = 0;
855         osm_switch_t *p_sw;
856         int verbose = 0;
857
858         p_cmd = next_token(p_last);
859         if (p_cmd) {
860                 char *p_end;
861
862                 if (strcmp(p_cmd, "verbose") == 0) {
863                         verbose++;
864                         p_cmd = next_token(p_last);
865                 }
866
867                 if (p_cmd) {
868                         guid = strtoull(p_cmd, &p_end, 0);
869                         if (!guid || *p_end != '\0') {
870                                 fprintf(out, "Invalid guid specified\n");
871                                 help_switchbalance(out, 1);
872                                 return;
873                         }
874                 }
875         }
876
877         cl_plock_acquire(&p_osm->lock);
878         if (guid) {
879                 p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
880                 if (!p_sw) {
881                         fprintf(out, "guid not found\n");
882                         goto lock_exit;
883                 }
884
885                 switchbalance_check(p_osm, p_sw, out, verbose);
886         } else {
887                 cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
888                 for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
889                      p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
890                      p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
891                         switchbalance_check(p_osm, p_sw, out, verbose);
892         }
893 lock_exit:
894         cl_plock_release(&p_osm->lock);
895         return;
896 }
897
898 static void lidbalance_check(osm_opensm_t * p_osm,
899                              osm_switch_t * p_sw, FILE * out)
900 {
901         uint8_t port_num;
902         const cl_qmap_t *p_port_tbl;
903         osm_port_t *p_port;
904
905         p_port_tbl = &p_osm->subn.port_guid_tbl;
906         for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl);
907              p_port != (osm_port_t *) cl_qmap_end(p_port_tbl);
908              p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) {
909                 uint32_t port_count[255];       /* max ports is a uint8_t */
910                 osm_node_t *rem_node[255];
911                 uint32_t rem_node_count;
912                 uint32_t rem_count[255];
913                 osm_physp_t *p_physp;
914                 osm_physp_t *p_rem_physp;
915                 osm_node_t *p_rem_node;
916                 uint32_t port_min_count = 0xFFFFFFFF;
917                 uint32_t port_max_count = 0;
918                 uint32_t rem_min_count = 0xFFFFFFFF;
919                 uint32_t rem_max_count = 0;
920                 uint16_t min_lid_ho;
921                 uint16_t max_lid_ho;
922                 uint16_t lid_ho;
923                 uint8_t num_ports;
924                 unsigned int i;
925
926                 /* we only care about non-switches */
927                 if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH)
928                         continue;
929
930                 osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
931
932                 if (min_lid_ho == 0 || max_lid_ho == 0)
933                         continue;
934
935                 memset(port_count, '\0', sizeof(uint32_t) * 255);
936                 memset(rem_node, '\0', sizeof(osm_node_t *) * 255);
937                 rem_node_count = 0;
938                 memset(rem_count, '\0', sizeof(uint32_t) * 255);
939
940                 for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) {
941                         boolean_t rem_node_found = FALSE;
942                         unsigned int indx = 0;
943
944                         port_num = osm_switch_get_port_by_lid(p_sw, lid_ho);
945                         if (port_num == OSM_NO_PATH)
946                                 continue;
947
948                         p_physp =
949                             osm_node_get_physp_ptr(p_sw->p_node, port_num);
950
951                         /* if port is down/unhealthy, can't calculate */
952                         if (!p_physp || !osm_physp_is_healthy(p_physp)
953                             || !osm_physp_get_remote(p_physp))
954                                 continue;
955
956                         p_rem_physp = osm_physp_get_remote(p_physp);
957                         p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
958
959                         /* determine if we've seen this remote node before.
960                          * If not, store it.  If yes, update the counter
961                          */
962                         for (i = 0; i < rem_node_count; i++) {
963                                 if (rem_node[i] == p_rem_node) {
964                                         rem_node_found = TRUE;
965                                         indx = i;
966                                         break;
967                                 }
968                         }
969
970                         if (!rem_node_found) {
971                                 rem_node[rem_node_count] = p_rem_node;
972                                 rem_count[rem_node_count]++;
973                                 indx = rem_node_count;
974                                 rem_node_count++;
975                         } else
976                                 rem_count[indx]++;
977
978                         port_count[port_num]++;
979                 }
980
981                 if (!rem_node_count)
982                         continue;
983
984                 for (i = 0; i < rem_node_count; i++) {
985                         if (rem_count[i] < rem_min_count)
986                                 rem_min_count = rem_count[i];
987                         if (rem_count[i] > rem_max_count)
988                                 rem_max_count = rem_count[i];
989                 }
990
991                 num_ports = p_sw->num_ports;
992                 for (i = 0; i < num_ports; i++) {
993                         if (!port_count[i])
994                                 continue;
995                         if (port_count[i] < port_min_count)
996                                 port_min_count = port_count[i];
997                         if (port_count[i] > port_max_count)
998                                 port_max_count = port_count[i];
999                 }
1000
1001                 /* Output if this CA/router is being forwarded an unbalanced number of
1002                  * times to a destination.
1003                  */
1004                 if ((rem_max_count - rem_min_count) > 1) {
1005                         fprintf(out,
1006                                 "Unbalanced Remote Forwarding: Switch 0x%016"
1007                                 PRIx64 " (%s): ",
1008                                 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1009                                 p_sw->p_node->print_desc);
1010                         if (osm_node_get_type(p_port->p_node) ==
1011                             IB_NODE_TYPE_CA)
1012                                 fprintf(out, "CA");
1013                         else if (osm_node_get_type(p_port->p_node) ==
1014                                  IB_NODE_TYPE_ROUTER)
1015                                 fprintf(out, "Router");
1016                         fprintf(out, " 0x%016" PRIx64 " (%s): ",
1017                                 cl_ntoh64(p_port->p_node->node_info.node_guid),
1018                                 p_port->p_node->print_desc);
1019                         for (i = 0; i < rem_node_count; i++) {
1020                                 fprintf(out,
1021                                         "Dest 0x%016" PRIx64 "(%s) - %u ",
1022                                         cl_ntoh64(rem_node[i]->node_info.
1023                                                   node_guid),
1024                                         rem_node[i]->print_desc, rem_count[i]);
1025                         }
1026                         fprintf(out, "\n");
1027                 }
1028
1029                 /* Output if this CA/router is being forwarded through a port
1030                  * an unbalanced number of times.
1031                  */
1032                 if ((port_max_count - port_min_count) > 1) {
1033                         fprintf(out,
1034                                 "Unbalanced Port Forwarding: Switch 0x%016"
1035                                 PRIx64 " (%s): ",
1036                                 cl_ntoh64(p_sw->p_node->node_info.node_guid),
1037                                 p_sw->p_node->print_desc);
1038                         if (osm_node_get_type(p_port->p_node) ==
1039                             IB_NODE_TYPE_CA)
1040                                 fprintf(out, "CA");
1041                         else if (osm_node_get_type(p_port->p_node) ==
1042                                  IB_NODE_TYPE_ROUTER)
1043                                 fprintf(out, "Router");
1044                         fprintf(out, " 0x%016" PRIx64 " (%s): ",
1045                                 cl_ntoh64(p_port->p_node->node_info.node_guid),
1046                                 p_port->p_node->print_desc);
1047                         for (i = 0; i < num_ports; i++) {
1048                                 if (!port_count[i])
1049                                         continue;
1050                                 fprintf(out, "Port %u - %u: ", i,
1051                                         port_count[i]);
1052                         }
1053                         fprintf(out, "\n");
1054                 }
1055         }
1056 }
1057
1058 static void lidbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1059 {
1060         char *p_cmd;
1061         uint64_t guid = 0;
1062         osm_switch_t *p_sw;
1063
1064         p_cmd = next_token(p_last);
1065         if (p_cmd) {
1066                 char *p_end;
1067
1068                 guid = strtoull(p_cmd, &p_end, 0);
1069                 if (!guid || *p_end != '\0') {
1070                         fprintf(out, "Invalid switchguid specified\n");
1071                         help_lidbalance(out, 1);
1072                         return;
1073                 }
1074         }
1075
1076         cl_plock_acquire(&p_osm->lock);
1077         if (guid) {
1078                 p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid));
1079                 if (!p_sw) {
1080                         fprintf(out, "switchguid not found\n");
1081                         goto lock_exit;
1082                 }
1083                 lidbalance_check(p_osm, p_sw, out);
1084         } else {
1085                 cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl;
1086                 for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl);
1087                      p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl);
1088                      p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item))
1089                         lidbalance_check(p_osm, p_sw, out);
1090         }
1091
1092 lock_exit:
1093         cl_plock_release(&p_osm->lock);
1094         return;
1095 }
1096
1097 static void dump_conf_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1098 {
1099         osm_subn_output_conf(out, &p_osm->subn.opt);
1100 }
1101
1102 #ifdef ENABLE_OSM_PERF_MGR
1103 static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1104 {
1105         char *p_cmd;
1106
1107         p_cmd = next_token(p_last);
1108         if (p_cmd) {
1109                 if (strcmp(p_cmd, "enable") == 0) {
1110                         osm_perfmgr_set_state(&(p_osm->perfmgr),
1111                                               PERFMGR_STATE_ENABLED);
1112                 } else if (strcmp(p_cmd, "disable") == 0) {
1113                         osm_perfmgr_set_state(&(p_osm->perfmgr),
1114                                               PERFMGR_STATE_DISABLE);
1115                 } else if (strcmp(p_cmd, "clear_counters") == 0) {
1116                         osm_perfmgr_clear_counters(&(p_osm->perfmgr));
1117                 } else if (strcmp(p_cmd, "dump_counters") == 0) {
1118                         p_cmd = next_token(p_last);
1119                         if (p_cmd && (strcmp(p_cmd, "mach") == 0)) {
1120                                 osm_perfmgr_dump_counters(&(p_osm->perfmgr),
1121                                                           PERFMGR_EVENT_DB_DUMP_MR);
1122                         } else {
1123                                 osm_perfmgr_dump_counters(&(p_osm->perfmgr),
1124                                                           PERFMGR_EVENT_DB_DUMP_HR);
1125                         }
1126                 } else if (strcmp(p_cmd, "print_counters") == 0) {
1127                         p_cmd = next_token(p_last);
1128                         if (p_cmd) {
1129                                 osm_perfmgr_print_counters(&(p_osm->perfmgr),
1130                                                            p_cmd, out);
1131                         } else {
1132                                 fprintf(out,
1133                                         "print_counters requires a node name to be specified\n");
1134                         }
1135                 } else if (strcmp(p_cmd, "sweep_time") == 0) {
1136                         p_cmd = next_token(p_last);
1137                         if (p_cmd) {
1138                                 uint16_t time_s = atoi(p_cmd);
1139                                 osm_perfmgr_set_sweep_time_s(&(p_osm->perfmgr),
1140                                                              time_s);
1141                         } else {
1142                                 fprintf(out,
1143                                         "sweep_time requires a time period (in seconds) to be specified\n");
1144                         }
1145                 } else {
1146                         fprintf(out, "\"%s\" option not found\n", p_cmd);
1147                 }
1148         } else {
1149                 fprintf(out, "Performance Manager status:\n"
1150                         "state                   : %s\n"
1151                         "sweep state             : %s\n"
1152                         "sweep time              : %us\n"
1153                         "outstanding queries/max : %d/%u\n",
1154                         osm_perfmgr_get_state_str(&(p_osm->perfmgr)),
1155                         osm_perfmgr_get_sweep_state_str(&(p_osm->perfmgr)),
1156                         osm_perfmgr_get_sweep_time_s(&(p_osm->perfmgr)),
1157                         p_osm->perfmgr.outstanding_queries,
1158                         p_osm->perfmgr.max_outstanding_queries);
1159         }
1160 }
1161 #endif                          /* ENABLE_OSM_PERF_MGR */
1162
1163 static void quit_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1164 {
1165         osm_console_exit(&p_osm->console, &p_osm->log);
1166 }
1167
1168 static void help_version(FILE * out, int detail)
1169 {
1170         fprintf(out, "version -- print the OSM version\n");
1171 }
1172
1173 static void version_parse(char **p_last, osm_opensm_t * p_osm, FILE * out)
1174 {
1175         fprintf(out, "%s build %s %s\n", p_osm->osm_version, __DATE__, __TIME__);
1176 }
1177
1178 /* more parse routines go here */
1179
1180 static const struct command console_cmds[] = {
1181         {"help", &help_command, &help_parse},
1182         {"quit", &help_quit, &quit_parse},
1183         {"loglevel", &help_loglevel, &loglevel_parse},
1184         {"priority", &help_priority, &priority_parse},
1185         {"resweep", &help_resweep, &resweep_parse},
1186         {"reroute", &help_reroute, &reroute_parse},
1187         {"status", &help_status, &status_parse},
1188         {"logflush", &help_logflush, &logflush_parse},
1189         {"querylid", &help_querylid, &querylid_parse},
1190         {"portstatus", &help_portstatus, &portstatus_parse},
1191         {"switchbalance", &help_switchbalance, &switchbalance_parse},
1192         {"lidbalance", &help_lidbalance, &lidbalance_parse},
1193         {"dump_conf", &help_dump_conf, &dump_conf_parse},
1194         {"version", &help_version, &version_parse},
1195 #ifdef ENABLE_OSM_PERF_MGR
1196         {"perfmgr", &help_perfmgr, &perfmgr_parse},
1197 #endif                          /* ENABLE_OSM_PERF_MGR */
1198         {NULL, NULL, NULL}      /* end of array */
1199 };
1200
1201 static void parse_cmd_line(char *line, osm_opensm_t * p_osm)
1202 {
1203         char *p_cmd, *p_last;
1204         int i, found = 0;
1205         FILE *out = p_osm->console.out;
1206
1207         while (isspace(*line))
1208                 line++;
1209         if (!*line)
1210                 return;
1211
1212         /* find first token which is the command */
1213         p_cmd = strtok_r(line, " \t\n\r", &p_last);
1214         if (p_cmd) {
1215                 for (i = 0; console_cmds[i].name; i++) {
1216                         if (loop_command.on) {
1217                                 if (!strcmp(p_cmd, "q")) {
1218                                         loop_command.on = 0;
1219                                 }
1220                                 found = 1;
1221                                 break;
1222                         }
1223                         if (!strcmp(p_cmd, console_cmds[i].name)) {
1224                                 found = 1;
1225                                 console_cmds[i].parse_function(&p_last, p_osm,
1226                                                                out);
1227                                 break;
1228                         }
1229                 }
1230                 if (!found) {
1231                         fprintf(out, "%s : Command not found\n\n", p_cmd);
1232                         help_command(out, 0);
1233                 }
1234         } else {
1235                 fprintf(out, "Error parsing command line: `%s'\n", line);
1236         }
1237         if (loop_command.on) {
1238                 fprintf(out, "use \"q<ret>\" to quit loop\n");
1239                 fflush(out);
1240         }
1241 }
1242
1243 void osm_console(osm_opensm_t * p_osm)
1244 {
1245         struct pollfd pollfd[2];
1246         char *p_line;
1247         size_t len;
1248         ssize_t n;
1249         struct pollfd *fds;
1250         nfds_t nfds;
1251         osm_console_t *p_oct = &p_osm->console;
1252         osm_log_t *p_log = &p_osm->log;
1253
1254         pollfd[0].fd = p_oct->socket;
1255         pollfd[0].events = POLLIN;
1256         pollfd[0].revents = 0;
1257
1258         pollfd[1].fd = p_oct->in_fd;
1259         pollfd[1].events = POLLIN;
1260         pollfd[1].revents = 0;
1261
1262         fds = p_oct->socket < 0 ? &pollfd[1] : pollfd;
1263         nfds = p_oct->socket < 0 || pollfd[1].fd < 0 ? 1 : 2;
1264
1265         if (loop_command.on && loop_command_check_time() &&
1266             loop_command.loop_function) {
1267                 if (p_oct->out) {
1268                         loop_command.loop_function(p_osm, p_oct->out);
1269                         fflush(p_oct->out);
1270                 } else {
1271                         loop_command.on = 0;
1272                 }
1273         }
1274
1275         if (poll(fds, nfds, 1000) <= 0)
1276                 return;
1277
1278 #ifdef ENABLE_OSM_CONSOLE_SOCKET
1279         if (pollfd[0].revents & POLLIN) {
1280                 int new_fd = 0;
1281                 struct sockaddr_in sin;
1282                 socklen_t len = sizeof(sin);
1283                 struct hostent *hent;
1284                 if ((new_fd = accept(p_oct->socket, &sin, &len)) < 0) {
1285                         OSM_LOG(p_log, OSM_LOG_ERROR,
1286                                 "ERR 4B04: Failed to accept console socket: %s\n",
1287                                 strerror(errno));
1288                         p_oct->in_fd = -1;
1289                         return;
1290                 }
1291                 if (inet_ntop
1292                     (AF_INET, &sin.sin_addr, p_oct->client_ip,
1293                      sizeof(p_oct->client_ip)) == NULL) {
1294                         snprintf(p_oct->client_ip, 64, "STRING_UNKNOWN");
1295                 }
1296                 if ((hent = gethostbyaddr((const char *)&sin.sin_addr,
1297                                           sizeof(struct in_addr),
1298                                           AF_INET)) == NULL) {
1299                         snprintf(p_oct->client_hn, 128, "STRING_UNKNOWN");
1300                 } else {
1301                         snprintf(p_oct->client_hn, 128, "%s", hent->h_name);
1302                 }
1303                 if (is_authorized(p_oct)) {
1304                         cio_open(p_oct, new_fd, p_log);
1305                 } else {
1306                         OSM_LOG(p_log, OSM_LOG_ERROR,
1307                                 "ERR 4B05: Console connection denied: %s (%s)\n",
1308                                 p_oct->client_hn, p_oct->client_ip);
1309                         close(new_fd);
1310                 }
1311                 return;
1312         }
1313 #endif
1314
1315         if (pollfd[1].revents & POLLIN) {
1316                 p_line = NULL;
1317                 /* Get input line */
1318                 n = getline(&p_line, &len, p_oct->in);
1319                 if (n > 0) {
1320                         /* Parse and act on input */
1321                         parse_cmd_line(p_line, p_osm);
1322                         if (!loop_command.on) {
1323                                 osm_console_prompt(p_oct->out);
1324                         }
1325                 } else
1326                         osm_console_exit(p_oct, p_log);
1327                 if (p_line)
1328                         free(p_line);
1329         }
1330 }