blob: 49f587d567a11766f3e9ec7863da747345020573 [file] [log] [blame]
Harald Welte34b5a952019-05-27 11:54:11 +02001/* Osmocom VTY interface functions in TTCN-3
2 * (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
3 * contributions by sysmocom - s.f.m.c. GmbH
4 * All rights reserved.
5 *
6 * Released under the terms of GNU General Public License, Version 2 or
7 * (at your option) any later version.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
Harald Welte8542cef2017-07-19 20:06:26 +020012module Osmocom_VTY_Functions {
Pau Espin Pedrol3bc82b42021-02-05 16:01:36 +010013
14 import from Misc_Helpers all;
Harald Welte8542cef2017-07-19 20:06:26 +020015 import from TELNETasp_PortType all;
Stefan Sperlingcff13562018-11-13 15:24:06 +010016 import from Osmocom_Types all;
Harald Welte8542cef2017-07-19 20:06:26 +020017
Harald Welte553f6552018-01-24 18:50:53 +010018 modulepar {
19 charstring mp_prompt_prefix := "OpenBSC";
Vadim Yanitskiybc1e66a2021-01-30 14:14:15 +010020 float mp_prompt_timeout := 2.0;
Harald Welte553f6552018-01-24 18:50:53 +010021 }
Harald Welte8542cef2017-07-19 20:06:26 +020022
Harald Welte553f6552018-01-24 18:50:53 +010023 const charstring VTY_VIEW_SUFFIX := "> ";
24 const charstring VTY_ENABLE_SUFFIX := "# ";
25 const charstring VTY_CFG_SUFFIX := "(*)";
26
27 template charstring t_vty_unknown := pattern "*% Unknown command.";
Harald Welte8542cef2017-07-19 20:06:26 +020028
29 /* configure prompts in TELNETasp module */
Harald Weltea2663252018-09-10 10:21:44 +020030 function f_vty_set_prompts(TELNETasp_PT pt, charstring prompt_prefix := mp_prompt_prefix) {
Harald Welte553f6552018-01-24 18:50:53 +010031 var ASP_TelnetDynamicConfig vty_prompt[3] := {
32 {
33 prompt := {
34 id := 1,
Harald Weltea2663252018-09-10 10:21:44 +020035 prompt := prompt_prefix & VTY_VIEW_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010036 has_wildcards := false
37 }
38 }, {
39 prompt := {
40 id := 2,
Harald Weltea2663252018-09-10 10:21:44 +020041 prompt := prompt_prefix & VTY_ENABLE_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010042 has_wildcards := false
43 }
44 }, {
45 prompt := {
46 id := 3,
Harald Weltea2663252018-09-10 10:21:44 +020047 prompt := prompt_prefix & VTY_CFG_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010048 has_wildcards := true
49 }
50 }
51 };
52
Harald Welte8542cef2017-07-19 20:06:26 +020053 /* set some configuration that isn't possible to express
54 * in the config file due to syntactic restrictions (Who invents config
55 * files that don't permit regular expressions? */
56 for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
Harald Welte553f6552018-01-24 18:50:53 +010057 pt.send(vty_prompt[i]);
Harald Welte8542cef2017-07-19 20:06:26 +020058 }
59 }
60
61 /* wait for any of the permitted prompts; buffer + return all intermediate output */
Vadim Yanitskiy26e30aa2021-01-30 14:06:37 +010062 function f_vty_wait_for_prompt(TELNETasp_PT pt, boolean strict := true, charstring log_label := "(?)")
63 return charstring {
Harald Welte8542cef2017-07-19 20:06:26 +020064 var charstring rx, buf := "";
Stefan Sperling23b45972018-07-27 17:20:38 +020065 var integer fd;
Vadim Yanitskiybc1e66a2021-01-30 14:14:15 +010066 timer T;
Harald Welte8542cef2017-07-19 20:06:26 +020067
Vadim Yanitskiybc1e66a2021-01-30 14:14:15 +010068 T.start(mp_prompt_timeout);
Harald Welte8542cef2017-07-19 20:06:26 +020069 alt {
Vadim Yanitskiy26e30aa2021-01-30 14:06:37 +010070 [] pt.receive(pattern "[\w-]+" & VTY_VIEW_SUFFIX) { };
71 [] pt.receive(pattern "[\w-]+\# ") { };
72 [] pt.receive(pattern "[\w-]+\(*\)\# ") { };
73 [] pt.receive(t_vty_unknown) -> value rx {
74 if (strict) {
75 setverdict(fail, "VTY: Unknown Command: " & log_label);
Daniel Willmanne4ff5372018-07-05 17:35:03 +020076 mtc.stop;
Vadim Yanitskiy26e30aa2021-01-30 14:06:37 +010077 } else {
78 log("VTY: Unknown Command (ignored): " & log_label);
79 buf := buf & rx;
80 repeat;
81 }
82 };
83 [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
84 [] pt.receive(integer:?) -> value fd {
85 if (fd == -1) {
86 setverdict(fail, "VTY Telnet Connection Failure: " & log_label);
87 mtc.stop;
88 } else {
89 repeat; /* telnet connection succeeded */
90 }
91 }
92 [] T.timeout {
93 setverdict(fail, "VTY Timeout for prompt: " & log_label);
94 mtc.stop;
95 };
Harald Welte8542cef2017-07-19 20:06:26 +020096 }
97 T.stop;
98 return buf;
99 }
100
101 /* send a VTY command and obtain response until prompt is received */
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +0000102 function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx, boolean strict := true) return charstring {
Harald Welte8542cef2017-07-19 20:06:26 +0200103 pt.send(tx);
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +0000104 return f_vty_wait_for_prompt(pt, strict, tx);
Harald Welte8542cef2017-07-19 20:06:26 +0200105 }
106
107 /* send a VTY command and obtain response until prompt is received */
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +0000108 function f_vty_transceive(TELNETasp_PT pt, charstring tx, boolean strict := true) {
109 var charstring unused := f_vty_transceive_ret(pt, tx, strict);
Harald Welte8542cef2017-07-19 20:06:26 +0200110 }
111
112 type integer BtsNr (0..255);
113 type integer BtsTrxNr (0..255);
114 type integer BtsTimeslotNr (0..7);
Philipp Maierd0e64b02019-03-13 14:15:23 +0100115 type integer MscNr (0..255);
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100116 type integer Cs7Nr (0..255);
Harald Welte8542cef2017-07-19 20:06:26 +0200117
118 type charstring BtsGprsMode ("none", "gprs", "egrps");
119
120 /* enter the'confiugration' mode of the VTY */
121 function f_vty_enter_config(TELNETasp_PT pt) {
122 f_vty_transceive(pt, "configure terminal")
123 }
124
125 function f_vty_enter_cfg_network(TELNETasp_PT pt) {
126 f_vty_enter_config(pt);
127 f_vty_transceive(pt, "network")
128 }
129
130 function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
131 f_vty_enter_cfg_network(pt);
132 f_vty_transceive(pt, "bts " & int2str(bts));
133 }
134
135 function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
136 f_vty_enter_cfg_bts(pt, bts);
137 f_vty_transceive(pt, "trx " & int2str(trx));
138 }
139
140 function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
141 f_vty_enter_cfg_trx(pt, bts, trx);
142 f_vty_transceive(pt, "timeslot " & int2str(ts));
143 }
144
Philipp Maierd0e64b02019-03-13 14:15:23 +0100145 function f_vty_enter_cfg_msc(TELNETasp_PT pt, MscNr msc := 0) {
146 f_vty_enter_config(pt);
147 f_vty_transceive(pt, "msc " & int2str(msc));
148 }
149
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100150 function f_vty_enter_cfg_cs7_inst(TELNETasp_PT pt, Cs7Nr cs7_inst := 0) {
151 f_vty_enter_config(pt);
152 f_vty_transceive(pt, "cs7 instance " & int2str(cs7_inst));
153 }
154
Harald Weltef640a012018-04-14 17:49:21 +0200155type record of charstring rof_charstring;
Neels Hofmeyr1a1f8542020-11-25 23:39:46 +0000156function f_vty_config3(TELNETasp_PT pt, rof_charstring config_nodes, rof_charstring cmds)
Harald Welte872ce172018-02-16 22:10:33 +0100157{
158 /* enter config mode; enter node */
159 f_vty_enter_config(pt);
Harald Weltef640a012018-04-14 17:49:21 +0200160 for (var integer i := 0; i < sizeof(config_nodes); i := i+1) {
161 f_vty_transceive(pt, config_nodes[i]);
162 }
Neels Hofmeyr1a1f8542020-11-25 23:39:46 +0000163 /* execute commands */
164 for (var integer i := 0; i < sizeof(cmds); i := i+1) {
165 f_vty_transceive(pt, cmds[i]);
166 }
Harald Welte872ce172018-02-16 22:10:33 +0100167 /* leave config mode */
168 f_vty_transceive(pt, "end");
169}
170
Neels Hofmeyr1a1f8542020-11-25 23:39:46 +0000171function f_vty_config2(TELNETasp_PT pt, rof_charstring config_nodes, charstring cmd)
172{
173 f_vty_config3(pt, config_nodes, { cmd });
174}
Harald Welte872ce172018-02-16 22:10:33 +0100175
Harald Weltef640a012018-04-14 17:49:21 +0200176function f_vty_config(TELNETasp_PT pt, charstring config_node, charstring cmd)
177{
178 f_vty_config2(pt, {config_node}, cmd);
179}
180
Neels Hofmeyr2a5670b2020-11-25 23:39:57 +0000181function f_vty_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0, rof_charstring cmds) {
182 f_vty_config3(pt, {"network", "bts " & int2str(bts)}, cmds);
183}
184
185function f_vty_cfg_msc(TELNETasp_PT pt, MscNr msc := 0, rof_charstring cmds) {
186 f_vty_config3(pt, {"msc " & int2str(msc)}, cmds);
187}
188
Alexander Couzens98aa59e2018-06-12 13:45:59 +0200189function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
190 var charstring ret := f_vty_transceive_ret(pt, cmd);
191 if (not match(ret, exp_ret)) {
192 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200193 mtc.stop;
Alexander Couzens98aa59e2018-06-12 13:45:59 +0200194 }
195}
196
Alexander Couzens1e6d9902018-06-12 13:48:26 +0200197function f_vty_transceive_not_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
198 var charstring ret := f_vty_transceive_ret(pt, cmd);
199 if (match(ret, exp_ret)) {
200 setverdict(fail, "Unexpected matching VTY response: ", ret);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200201 mtc.stop;
Alexander Couzens1e6d9902018-06-12 13:48:26 +0200202 }
203}
204
Stefan Sperlingcff13562018-11-13 15:24:06 +0100205function f_vty_transceive_match_regex(TELNETasp_PT pt, charstring cmd, charstring regex, integer groupno) return charstring
206{
207 var charstring resp := f_vty_transceive_ret(pt, cmd);
208 return regexp(resp, regex, groupno);
209}
210
211function f_vty_transceive_match_regexp_retry(TELNETasp_PT pt, charstring cmd, charstring regex,
212 integer groupno, integer num_attempts, float retry_delay) return charstring
213{
214 while (num_attempts > 0) {
215 var charstring ret := f_vty_transceive_match_regex(pt, cmd, regex, groupno);
216 if (ret != "") {
217 return ret;
218 }
219 f_sleep(retry_delay);
220 num_attempts := num_attempts - 1;
221 }
222
Pau Espin Pedrol3bc82b42021-02-05 16:01:36 +0100223 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
224 log2str("No matching VTY response for regular expression '",
225 regex, "' after ", num_attempts, " attempts." ));
226 return "";
Stefan Sperlingcff13562018-11-13 15:24:06 +0100227}
Harald Weltef640a012018-04-14 17:49:21 +0200228
Harald Welte8542cef2017-07-19 20:06:26 +0200229}