summaryrefslogtreecommitdiffstats
path: root/src/vty/fsm_vty.c
blob: 422de9d9115981eba6bdaa06f796b75a16e425e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* Osmocom FSM introspection via VTY */
/* (C) 2016 by Harald Welte <laforge@gnumonks.org>
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include <stdlib.h>
#include <string.h>

#include "../../config.h"

#include <osmocom/vty/command.h>
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/misc.h>

#include <osmocom/core/fsm.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/linuxlist.h>

/* we don't want to add this to a public header file; this is simply
 * exported by libosmocore and used by libmsomvty but not for public
 * consumption. */
extern struct llist_head osmo_g_fsms;

/*! \brief Print information about a FSM [class] to the given VTY
 *  \param vty The VTY to which to print
 *  \param[in] fsm The FSM class to print
 */
void vty_out_fsm(struct vty *vty, struct osmo_fsm *fsm)
{
	unsigned int i;
	const struct value_string *evt_name;

	vty_out(vty, "FSM Name: '%s', Log Subsys: '%s'%s", fsm->name,
		log_category_name(fsm->log_subsys), VTY_NEWLINE);
	/* list the events */
	for (evt_name = fsm->event_names; evt_name->str != NULL; evt_name++) {
		vty_out(vty, " Event %02u (0x%08x): '%s'%s", evt_name->value,
			(1 << evt_name->value), evt_name->str, VTY_NEWLINE);
	}
	/* list the states */
	vty_out(vty, " Number of States: %u%s", fsm->num_states, VTY_NEWLINE);
	for (i = 0; i < fsm->num_states; i++) {
		const struct osmo_fsm_state *state = &fsm->states[i];
		vty_out(vty, "  State %-20s InEvtMask: 0x%08x, OutStateMask: 0x%08x%s",
			state->name, state->in_event_mask, state->out_state_mask,
			VTY_NEWLINE);
	}
}

/*! \brief Print a FSM instance to the given VTY
 *  \param vty The VTY to which to print
 *  \param[in] fsmi The FSM instance to print
 */
void vty_out_fsm_inst(struct vty *vty, struct osmo_fsm_inst *fsmi)
{
	struct osmo_fsm_inst *child;

	vty_out(vty, "FSM Instance Name: '%s', ID: '%s'%s",
		fsmi->name, fsmi->id, VTY_NEWLINE);
	vty_out(vty, " Log-Level: '%s', State: '%s'%s",
		log_level_str(fsmi->log_level),
		osmo_fsm_state_name(fsmi->fsm, fsmi->state),
		VTY_NEWLINE);
	if (fsmi->T)
		vty_out(vty, " Timer: %u%s", fsmi->T, VTY_NEWLINE);
	if (fsmi->proc.parent) {
		vty_out(vty, " Parent: '%s', Term-Event: '%s'%s",
			fsmi->proc.parent->name,
			osmo_fsm_event_name(fsmi->proc.parent->fsm,
					    fsmi->proc.parent_term_event),
			VTY_NEWLINE);
	}
	llist_for_each_entry(child, &fsmi->proc.children, list) {
		vty_out(vty, " Child: '%s'%s", child->name, VTY_NEWLINE);
	}
}

#define SH_FSM_STR	SHOW_STR "Show information about finite state machines\n"
#define SH_FSMI_STR	SHOW_STR "Show information about finite state machine instances\n"

DEFUN(show_fsms, show_fsms_cmd,
	"show fsm all",
	SH_FSM_STR
	"Display a list of all registered finite state machines\n")
{
	struct osmo_fsm *fsm;

	llist_for_each_entry(fsm, &osmo_g_fsms, list)
		vty_out_fsm(vty, fsm);

	return CMD_SUCCESS;
}

DEFUN(show_fsm, show_fsm_cmd,
	"show fsm NAME",
	SH_FSM_STR
	"Display information about a single named finite state machine\n")
{
	struct osmo_fsm *fsm;

	fsm = osmo_fsm_find_by_name(argv[0]);
	if (!fsm) {
		vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
			argv[0], VTY_NEWLINE);
		return CMD_WARNING;
	}

	vty_out_fsm(vty, fsm);

	return CMD_SUCCESS;
}

DEFUN(show_fsm_insts, show_fsm_insts_cmd,
	"show fsm-instances all",
	SH_FSMI_STR
	"Display a list of all FSM instances of all finite state machine")
{
	struct osmo_fsm *fsm;

	llist_for_each_entry(fsm, &osmo_g_fsms, list) {
		struct osmo_fsm_inst *fsmi;
		llist_for_each_entry(fsmi, &fsm->instances, list)
			vty_out_fsm_inst(vty, fsmi);
	}

	return CMD_SUCCESS;
}

DEFUN(show_fsm_inst, show_fsm_inst_cmd,
	"show fsm-instances NAME",
	SH_FSMI_STR
	"Display a list of all FSM instances of the named finite state machine")
{
	struct osmo_fsm *fsm;
	struct osmo_fsm_inst *fsmi;

	fsm = osmo_fsm_find_by_name(argv[0]);
	if (!fsm) {
		vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s",
			argv[0], VTY_NEWLINE);
		return CMD_WARNING;
	}

	llist_for_each_entry(fsmi, &fsm->instances, list)
		vty_out_fsm_inst(vty, fsmi);

	return CMD_SUCCESS;
}

/*! \brief Install VTY commands for FSM introspection
 *  This installs a couple of VTY commands for introspection of FSM
 *  classes as well as FSM instances. Call this once from your
 *  application if you want to support those commands. */
void osmo_fsm_vty_add_cmds(void)
{
	install_element_ve(&show_fsm_cmd);
	install_element_ve(&show_fsms_cmd);
	install_element_ve(&show_fsm_inst_cmd);
	install_element_ve(&show_fsm_insts_cmd);
}