blob: 9bde241cebe7e69314a2749eb17843c90a6fe360 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*
2 * (C) 2016 by Harald Welte <laforge@gnumonks.org>
Harald Welte34193912017-01-07 11:49:55 +01003 * All Rights Reserved
4 *
Harald Weltee08da972017-11-13 01:00:26 +09005 * SPDX-License-Identifier: GPL-2.0+
6 *
Harald Welte34193912017-01-07 11:49:55 +01007 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdlib.h>
24#include <string.h>
25
26#include "../../config.h"
27
28#include <osmocom/vty/command.h>
29#include <osmocom/vty/buffer.h>
30#include <osmocom/vty/vty.h>
31#include <osmocom/vty/telnet_interface.h>
32#include <osmocom/vty/misc.h>
33
34#include <osmocom/core/fsm.h>
35#include <osmocom/core/logging.h>
36#include <osmocom/core/linuxlist.h>
37
Harald Welte8c648252017-10-16 15:17:03 +020038/*! \file fsm_vty.c
39 * Osmocom FSM introspection via VTY.
Harald Welte96e2a002017-06-12 21:44:18 +020040 *
41 * This is code implementing generic VTY access to Osmocom FSMs from
42 * libosmocore. This means that any application can expose all state
43 * of all instances of all registered FSM classes by calling a single
44 * command during startup: \ref osmo_fsm_vty_add_cmds
45 */
46
Harald Welte34193912017-01-07 11:49:55 +010047/* we don't want to add this to a public header file; this is simply
48 * exported by libosmocore and used by libmsomvty but not for public
49 * consumption. */
50extern struct llist_head osmo_g_fsms;
51
Neels Hofmeyr87e45502017-06-20 00:17:59 +020052/*! Print information about a FSM [class] to the given VTY
Harald Welte34193912017-01-07 11:49:55 +010053 * \param vty The VTY to which to print
54 * \param[in] fsm The FSM class to print
55 */
56void vty_out_fsm(struct vty *vty, struct osmo_fsm *fsm)
57{
58 unsigned int i;
59 const struct value_string *evt_name;
60
61 vty_out(vty, "FSM Name: '%s', Log Subsys: '%s'%s", fsm->name,
62 log_category_name(fsm->log_subsys), VTY_NEWLINE);
63 /* list the events */
Stefan Sperlingcc817222018-02-26 19:02:30 +010064 if (fsm->event_names) {
65 for (evt_name = fsm->event_names; evt_name->str != NULL; evt_name++) {
66 vty_out(vty, " Event %02u (0x%08x): '%s'%s", evt_name->value,
67 (1 << evt_name->value), evt_name->str, VTY_NEWLINE);
68 }
69 } else
70 vty_out(vty, " No event names are defined for this FSM! Please fix!%s", VTY_NEWLINE);
71
Harald Welte34193912017-01-07 11:49:55 +010072 /* list the states */
73 vty_out(vty, " Number of States: %u%s", fsm->num_states, VTY_NEWLINE);
74 for (i = 0; i < fsm->num_states; i++) {
75 const struct osmo_fsm_state *state = &fsm->states[i];
76 vty_out(vty, " State %-20s InEvtMask: 0x%08x, OutStateMask: 0x%08x%s",
77 state->name, state->in_event_mask, state->out_state_mask,
78 VTY_NEWLINE);
79 }
80}
81
Neels Hofmeyr87e45502017-06-20 00:17:59 +020082/*! Print a FSM instance to the given VTY
Harald Welte34193912017-01-07 11:49:55 +010083 * \param vty The VTY to which to print
84 * \param[in] fsmi The FSM instance to print
85 */
86void vty_out_fsm_inst(struct vty *vty, struct osmo_fsm_inst *fsmi)
87{
88 struct osmo_fsm_inst *child;
89
90 vty_out(vty, "FSM Instance Name: '%s', ID: '%s'%s",
91 fsmi->name, fsmi->id, VTY_NEWLINE);
92 vty_out(vty, " Log-Level: '%s', State: '%s'%s",
93 log_level_str(fsmi->log_level),
94 osmo_fsm_state_name(fsmi->fsm, fsmi->state),
95 VTY_NEWLINE);
96 if (fsmi->T)
97 vty_out(vty, " Timer: %u%s", fsmi->T, VTY_NEWLINE);
98 if (fsmi->proc.parent) {
99 vty_out(vty, " Parent: '%s', Term-Event: '%s'%s",
100 fsmi->proc.parent->name,
101 osmo_fsm_event_name(fsmi->proc.parent->fsm,
102 fsmi->proc.parent_term_event),
103 VTY_NEWLINE);
104 }
Alexander Couzens49865052018-07-17 18:35:05 +0200105 llist_for_each_entry(child, &fsmi->proc.children, proc.child) {
Harald Welte34193912017-01-07 11:49:55 +0100106 vty_out(vty, " Child: '%s'%s", child->name, VTY_NEWLINE);
107 }
108}
109
110#define SH_FSM_STR SHOW_STR "Show information about finite state machines\n"
111#define SH_FSMI_STR SHOW_STR "Show information about finite state machine instances\n"
112
113DEFUN(show_fsms, show_fsms_cmd,
114 "show fsm all",
115 SH_FSM_STR
116 "Display a list of all registered finite state machines\n")
117{
118 struct osmo_fsm *fsm;
119
120 llist_for_each_entry(fsm, &osmo_g_fsms, list)
121 vty_out_fsm(vty, fsm);
122
123 return CMD_SUCCESS;
124}
125
126DEFUN(show_fsm, show_fsm_cmd,
127 "show fsm NAME",
128 SH_FSM_STR
129 "Display information about a single named finite state machine\n")
130{
131 struct osmo_fsm *fsm;
132
133 fsm = osmo_fsm_find_by_name(argv[0]);
134 if (!fsm) {
135 vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
136 argv[0], VTY_NEWLINE);
137 return CMD_WARNING;
138 }
139
140 vty_out_fsm(vty, fsm);
141
142 return CMD_SUCCESS;
143}
144
145DEFUN(show_fsm_insts, show_fsm_insts_cmd,
146 "show fsm-instances all",
147 SH_FSMI_STR
148 "Display a list of all FSM instances of all finite state machine")
149{
150 struct osmo_fsm *fsm;
151
152 llist_for_each_entry(fsm, &osmo_g_fsms, list) {
153 struct osmo_fsm_inst *fsmi;
154 llist_for_each_entry(fsmi, &fsm->instances, list)
155 vty_out_fsm_inst(vty, fsmi);
156 }
157
158 return CMD_SUCCESS;
159}
160
161DEFUN(show_fsm_inst, show_fsm_inst_cmd,
162 "show fsm-instances NAME",
163 SH_FSMI_STR
164 "Display a list of all FSM instances of the named finite state machine")
165{
166 struct osmo_fsm *fsm;
167 struct osmo_fsm_inst *fsmi;
168
169 fsm = osmo_fsm_find_by_name(argv[0]);
170 if (!fsm) {
171 vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
172 argv[0], VTY_NEWLINE);
173 return CMD_WARNING;
174 }
175
176 llist_for_each_entry(fsmi, &fsm->instances, list)
177 vty_out_fsm_inst(vty, fsmi);
178
179 return CMD_SUCCESS;
180}
181
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200182/*! Install VTY commands for FSM introspection
Harald Welte34193912017-01-07 11:49:55 +0100183 * This installs a couple of VTY commands for introspection of FSM
184 * classes as well as FSM instances. Call this once from your
185 * application if you want to support those commands. */
186void osmo_fsm_vty_add_cmds(void)
187{
Stefan Sperling218c4de2018-02-22 18:16:29 +0100188 static bool osmo_fsm_vty_cmds_installed;
189
190 /* Make sure FSM commands get installed only once.
191 * We might be called from libraries or from an application.
192 * An application might be oblivious to the fact that one or
193 * more of its libaries are using osmo_fsm. And likewise,
194 * any given library will not know if another library has
195 * already installled these commands. */
196 if (osmo_fsm_vty_cmds_installed)
197 return;
198
Harald Welte34193912017-01-07 11:49:55 +0100199 install_element_ve(&show_fsm_cmd);
200 install_element_ve(&show_fsms_cmd);
201 install_element_ve(&show_fsm_inst_cmd);
202 install_element_ve(&show_fsm_insts_cmd);
Stefan Sperling218c4de2018-02-22 18:16:29 +0100203 osmo_fsm_vty_cmds_installed = true;
Harald Welte34193912017-01-07 11:49:55 +0100204}