blob: da6038fab3bed41bdf1e705071a16b350e359f88 [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 *
Harald Welte34193912017-01-07 11:49:55 +010017 */
18
19#include <stdlib.h>
20#include <string.h>
21
Pau Espin Pedrol88955fb2023-01-18 18:54:00 +010022#include "config.h"
Harald Welte34193912017-01-07 11:49:55 +010023
24#include <osmocom/vty/command.h>
25#include <osmocom/vty/buffer.h>
26#include <osmocom/vty/vty.h>
27#include <osmocom/vty/telnet_interface.h>
28#include <osmocom/vty/misc.h>
29
30#include <osmocom/core/fsm.h>
31#include <osmocom/core/logging.h>
32#include <osmocom/core/linuxlist.h>
33
Harald Welte8c648252017-10-16 15:17:03 +020034/*! \file fsm_vty.c
35 * Osmocom FSM introspection via VTY.
Harald Welte96e2a002017-06-12 21:44:18 +020036 *
37 * This is code implementing generic VTY access to Osmocom FSMs from
38 * libosmocore. This means that any application can expose all state
39 * of all instances of all registered FSM classes by calling a single
40 * command during startup: \ref osmo_fsm_vty_add_cmds
41 */
42
Harald Welte34193912017-01-07 11:49:55 +010043/* we don't want to add this to a public header file; this is simply
44 * exported by libosmocore and used by libmsomvty but not for public
45 * consumption. */
46extern struct llist_head osmo_g_fsms;
47
Neels Hofmeyr87e45502017-06-20 00:17:59 +020048/*! Print information about a FSM [class] to the given VTY
Harald Welte34193912017-01-07 11:49:55 +010049 * \param vty The VTY to which to print
Harald Weltecec4bbe2021-01-19 20:55:00 +010050 * \param[in] prefix prefix to print at start of each line (typically indenting)
Harald Welte34193912017-01-07 11:49:55 +010051 * \param[in] fsm The FSM class to print
52 */
Harald Weltecec4bbe2021-01-19 20:55:00 +010053void vty_out_fsm2(struct vty *vty, const char *prefix, struct osmo_fsm *fsm)
Harald Welte34193912017-01-07 11:49:55 +010054{
55 unsigned int i;
56 const struct value_string *evt_name;
57
Harald Weltecec4bbe2021-01-19 20:55:00 +010058 vty_out(vty, "%sFSM Name: '%s', Log Subsys: '%s'%s", prefix, fsm->name,
Harald Welte34193912017-01-07 11:49:55 +010059 log_category_name(fsm->log_subsys), VTY_NEWLINE);
60 /* list the events */
Stefan Sperlingcc817222018-02-26 19:02:30 +010061 if (fsm->event_names) {
62 for (evt_name = fsm->event_names; evt_name->str != NULL; evt_name++) {
Harald Weltecec4bbe2021-01-19 20:55:00 +010063 vty_out(vty, "%s Event %02u (0x%08x): '%s'%s", prefix, evt_name->value,
Harald Welteb17cc802022-05-16 22:14:48 +020064 (1U << evt_name->value), evt_name->str, VTY_NEWLINE);
Stefan Sperlingcc817222018-02-26 19:02:30 +010065 }
66 } else
Harald Weltecec4bbe2021-01-19 20:55:00 +010067 vty_out(vty, "%s No event names are defined for this FSM! Please fix!%s", prefix, VTY_NEWLINE);
Stefan Sperlingcc817222018-02-26 19:02:30 +010068
Harald Welte34193912017-01-07 11:49:55 +010069 /* list the states */
Harald Weltecec4bbe2021-01-19 20:55:00 +010070 vty_out(vty, "%s Number of States: %u%s", prefix, fsm->num_states, VTY_NEWLINE);
Harald Welte34193912017-01-07 11:49:55 +010071 for (i = 0; i < fsm->num_states; i++) {
72 const struct osmo_fsm_state *state = &fsm->states[i];
Harald Weltecec4bbe2021-01-19 20:55:00 +010073 vty_out(vty, "%s State %-20s InEvtMask: 0x%08x, OutStateMask: 0x%08x%s", prefix,
Harald Welte34193912017-01-07 11:49:55 +010074 state->name, state->in_event_mask, state->out_state_mask,
75 VTY_NEWLINE);
76 }
77}
78
Harald Weltecec4bbe2021-01-19 20:55:00 +010079/*! Print information about a FSM [class] to the given VTY
80 * \param vty The VTY to which to print
81 * \param[in] fsm The FSM class to print
82 */
83void vty_out_fsm(struct vty *vty, struct osmo_fsm *fsm)
84{
85 vty_out_fsm2(vty, "", fsm);
86}
87
88/*! Print a FSM instance to the given VTY
89 * \param vty The VTY to which to print
90 * \param[in] prefix prefix to print at start of each line (typically indenting)
91 * \param[in] fsmi The FSM instance to print
92 */
93void vty_out_fsm_inst2(struct vty *vty, const char *prefix, struct osmo_fsm_inst *fsmi)
94{
95 struct osmo_fsm_inst *child;
96
97 vty_out(vty, "%sFSM Instance Name: '%s', ID: '%s'%s", prefix,
98 fsmi->name, fsmi->id, VTY_NEWLINE);
99 vty_out(vty, "%s Log-Level: '%s', State: '%s'%s", prefix,
100 log_level_str(fsmi->log_level),
101 osmo_fsm_state_name(fsmi->fsm, fsmi->state),
102 VTY_NEWLINE);
103 if (fsmi->T)
104 vty_out(vty, "%s Timer: %u%s", prefix, fsmi->T, VTY_NEWLINE);
105 if (fsmi->proc.parent) {
106 vty_out(vty, "%s Parent: '%s', Term-Event: '%s'%s", prefix,
107 fsmi->proc.parent->name,
108 osmo_fsm_event_name(fsmi->proc.parent->fsm,
109 fsmi->proc.parent_term_event),
110 VTY_NEWLINE);
111 }
112 llist_for_each_entry(child, &fsmi->proc.children, proc.child) {
113 vty_out(vty, "%s Child: '%s'%s", prefix, child->name, VTY_NEWLINE);
114 }
115}
116
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200117/*! Print a FSM instance to the given VTY
Harald Welte34193912017-01-07 11:49:55 +0100118 * \param vty The VTY to which to print
119 * \param[in] fsmi The FSM instance to print
120 */
121void vty_out_fsm_inst(struct vty *vty, struct osmo_fsm_inst *fsmi)
122{
Harald Weltecec4bbe2021-01-19 20:55:00 +0100123 vty_out_fsm_inst2(vty, "", fsmi);
Harald Welte34193912017-01-07 11:49:55 +0100124}
125
126#define SH_FSM_STR SHOW_STR "Show information about finite state machines\n"
127#define SH_FSMI_STR SHOW_STR "Show information about finite state machine instances\n"
128
129DEFUN(show_fsms, show_fsms_cmd,
130 "show fsm all",
131 SH_FSM_STR
132 "Display a list of all registered finite state machines\n")
133{
134 struct osmo_fsm *fsm;
135
136 llist_for_each_entry(fsm, &osmo_g_fsms, list)
137 vty_out_fsm(vty, fsm);
138
139 return CMD_SUCCESS;
140}
141
142DEFUN(show_fsm, show_fsm_cmd,
143 "show fsm NAME",
144 SH_FSM_STR
145 "Display information about a single named finite state machine\n")
146{
147 struct osmo_fsm *fsm;
148
149 fsm = osmo_fsm_find_by_name(argv[0]);
150 if (!fsm) {
151 vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
152 argv[0], VTY_NEWLINE);
153 return CMD_WARNING;
154 }
155
156 vty_out_fsm(vty, fsm);
157
158 return CMD_SUCCESS;
159}
160
161DEFUN(show_fsm_insts, show_fsm_insts_cmd,
162 "show fsm-instances all",
163 SH_FSMI_STR
164 "Display a list of all FSM instances of all finite state machine")
165{
166 struct osmo_fsm *fsm;
167
168 llist_for_each_entry(fsm, &osmo_g_fsms, list) {
169 struct osmo_fsm_inst *fsmi;
170 llist_for_each_entry(fsmi, &fsm->instances, list)
171 vty_out_fsm_inst(vty, fsmi);
172 }
173
174 return CMD_SUCCESS;
175}
176
177DEFUN(show_fsm_inst, show_fsm_inst_cmd,
178 "show fsm-instances NAME",
179 SH_FSMI_STR
180 "Display a list of all FSM instances of the named finite state machine")
181{
182 struct osmo_fsm *fsm;
183 struct osmo_fsm_inst *fsmi;
184
185 fsm = osmo_fsm_find_by_name(argv[0]);
186 if (!fsm) {
187 vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
188 argv[0], VTY_NEWLINE);
189 return CMD_WARNING;
190 }
191
192 llist_for_each_entry(fsmi, &fsm->instances, list)
193 vty_out_fsm_inst(vty, fsmi);
194
195 return CMD_SUCCESS;
196}
197
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200198/*! Install VTY commands for FSM introspection
Harald Welte34193912017-01-07 11:49:55 +0100199 * This installs a couple of VTY commands for introspection of FSM
200 * classes as well as FSM instances. Call this once from your
201 * application if you want to support those commands. */
202void osmo_fsm_vty_add_cmds(void)
203{
Stefan Sperling218c4de2018-02-22 18:16:29 +0100204 static bool osmo_fsm_vty_cmds_installed;
205
206 /* Make sure FSM commands get installed only once.
207 * We might be called from libraries or from an application.
208 * An application might be oblivious to the fact that one or
209 * more of its libaries are using osmo_fsm. And likewise,
210 * any given library will not know if another library has
211 * already installled these commands. */
212 if (osmo_fsm_vty_cmds_installed)
213 return;
214
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700215 install_lib_element_ve(&show_fsm_cmd);
216 install_lib_element_ve(&show_fsms_cmd);
217 install_lib_element_ve(&show_fsm_inst_cmd);
218 install_lib_element_ve(&show_fsm_insts_cmd);
Stefan Sperling218c4de2018-02-22 18:16:29 +0100219 osmo_fsm_vty_cmds_installed = true;
Harald Welte34193912017-01-07 11:49:55 +0100220}