blob: 042f244bf78497106fed7038eb74755f0c8e5df9 [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 {
13 import from TELNETasp_PortType all;
Stefan Sperlingcff13562018-11-13 15:24:06 +010014 import from Osmocom_Types all;
Harald Welte8542cef2017-07-19 20:06:26 +020015
Harald Welte553f6552018-01-24 18:50:53 +010016 modulepar {
17 charstring mp_prompt_prefix := "OpenBSC";
18 }
Harald Welte8542cef2017-07-19 20:06:26 +020019
Harald Welte553f6552018-01-24 18:50:53 +010020 const charstring VTY_VIEW_SUFFIX := "> ";
21 const charstring VTY_ENABLE_SUFFIX := "# ";
22 const charstring VTY_CFG_SUFFIX := "(*)";
23
24 template charstring t_vty_unknown := pattern "*% Unknown command.";
Harald Welte8542cef2017-07-19 20:06:26 +020025
26 /* configure prompts in TELNETasp module */
Harald Weltea2663252018-09-10 10:21:44 +020027 function f_vty_set_prompts(TELNETasp_PT pt, charstring prompt_prefix := mp_prompt_prefix) {
Harald Welte553f6552018-01-24 18:50:53 +010028 var ASP_TelnetDynamicConfig vty_prompt[3] := {
29 {
30 prompt := {
31 id := 1,
Harald Weltea2663252018-09-10 10:21:44 +020032 prompt := prompt_prefix & VTY_VIEW_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010033 has_wildcards := false
34 }
35 }, {
36 prompt := {
37 id := 2,
Harald Weltea2663252018-09-10 10:21:44 +020038 prompt := prompt_prefix & VTY_ENABLE_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010039 has_wildcards := false
40 }
41 }, {
42 prompt := {
43 id := 3,
Harald Weltea2663252018-09-10 10:21:44 +020044 prompt := prompt_prefix & VTY_CFG_SUFFIX,
Harald Welte553f6552018-01-24 18:50:53 +010045 has_wildcards := true
46 }
47 }
48 };
49
Harald Welte8542cef2017-07-19 20:06:26 +020050 /* set some configuration that isn't possible to express
51 * in the config file due to syntactic restrictions (Who invents config
52 * files that don't permit regular expressions? */
53 for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
Harald Welte553f6552018-01-24 18:50:53 +010054 pt.send(vty_prompt[i]);
Harald Welte8542cef2017-07-19 20:06:26 +020055 }
56 }
57
58 /* wait for any of the permitted prompts; buffer + return all intermediate output */
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +000059 function f_vty_wait_for_prompt(TELNETasp_PT pt, boolean strict := true, charstring log_label := "(?)") return charstring {
Harald Welte8542cef2017-07-19 20:06:26 +020060 var charstring rx, buf := "";
Stefan Sperling23b45972018-07-27 17:20:38 +020061 var integer fd;
Harald Welte8542cef2017-07-19 20:06:26 +020062 timer T := 2.0;
63
64 T.start;
65 alt {
Pau Espin Pedrol1a4d4e92019-12-04 16:59:29 +010066 [] pt.receive(pattern "[\w-]+" & VTY_VIEW_SUFFIX) { };
67 [] pt.receive(pattern "[\w-]+\# ") { };
68 [] pt.receive(pattern "[\w-]+\(*\)\# ") { };
Neels Hofmeyr5c59a8f2020-08-12 00:55:50 +000069 [] pt.receive(t_vty_unknown) -> value rx {
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +000070 if (strict) {
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +000071 setverdict(fail, "VTY: Unknown Command: " & log_label);
Neels Hofmeyr345a15f2020-08-12 00:56:56 +000072 mtc.stop;
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +000073 } else {
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +000074 log("VTY: Unknown Command (ignored): " & log_label);
Neels Hofmeyre4b0a662020-08-12 00:55:50 +000075 buf := buf & rx;
76 repeat;
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +000077 }
Harald Welte553f6552018-01-24 18:50:53 +010078 };
Harald Welte8542cef2017-07-19 20:06:26 +020079 [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
Stefan Sperling23b45972018-07-27 17:20:38 +020080 [] pt.receive(integer:?) -> value fd {
81 if (fd == -1) {
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +000082 setverdict(fail, "VTY Telnet Connection Failure: " & log_label);
Stefan Sperling23b45972018-07-27 17:20:38 +020083 mtc.stop;
84 } else {
85 repeat; /* telnet connection succeeded */
86 }
87 }
Harald Welte553f6552018-01-24 18:50:53 +010088 [] T.timeout {
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +000089 setverdict(fail, "VTY Timeout for prompt: " & log_label);
Daniel Willmanne4ff5372018-07-05 17:35:03 +020090 mtc.stop;
Harald Welte553f6552018-01-24 18:50:53 +010091 };
Harald Welte8542cef2017-07-19 20:06:26 +020092 }
93 T.stop;
94 return buf;
95 }
96
97 /* send a VTY command and obtain response until prompt is received */
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +000098 function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx, boolean strict := true) return charstring {
Harald Welte8542cef2017-07-19 20:06:26 +020099 pt.send(tx);
Neels Hofmeyr9ebabc82020-11-25 22:56:13 +0000100 return f_vty_wait_for_prompt(pt, strict, tx);
Harald Welte8542cef2017-07-19 20:06:26 +0200101 }
102
103 /* send a VTY command and obtain response until prompt is received */
Neels Hofmeyr2fe5ad12020-08-09 21:50:25 +0000104 function f_vty_transceive(TELNETasp_PT pt, charstring tx, boolean strict := true) {
105 var charstring unused := f_vty_transceive_ret(pt, tx, strict);
Harald Welte8542cef2017-07-19 20:06:26 +0200106 }
107
108 type integer BtsNr (0..255);
109 type integer BtsTrxNr (0..255);
110 type integer BtsTimeslotNr (0..7);
Philipp Maierd0e64b02019-03-13 14:15:23 +0100111 type integer MscNr (0..255);
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100112 type integer Cs7Nr (0..255);
Harald Welte8542cef2017-07-19 20:06:26 +0200113
114 type charstring BtsGprsMode ("none", "gprs", "egrps");
115
116 /* enter the'confiugration' mode of the VTY */
117 function f_vty_enter_config(TELNETasp_PT pt) {
118 f_vty_transceive(pt, "configure terminal")
119 }
120
121 function f_vty_enter_cfg_network(TELNETasp_PT pt) {
122 f_vty_enter_config(pt);
123 f_vty_transceive(pt, "network")
124 }
125
126 function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
127 f_vty_enter_cfg_network(pt);
128 f_vty_transceive(pt, "bts " & int2str(bts));
129 }
130
131 function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
132 f_vty_enter_cfg_bts(pt, bts);
133 f_vty_transceive(pt, "trx " & int2str(trx));
134 }
135
136 function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
137 f_vty_enter_cfg_trx(pt, bts, trx);
138 f_vty_transceive(pt, "timeslot " & int2str(ts));
139 }
140
Philipp Maierd0e64b02019-03-13 14:15:23 +0100141 function f_vty_enter_cfg_msc(TELNETasp_PT pt, MscNr msc := 0) {
142 f_vty_enter_config(pt);
143 f_vty_transceive(pt, "msc " & int2str(msc));
144 }
145
Pau Espin Pedrolc675b612020-01-09 19:55:40 +0100146 function f_vty_enter_cfg_cs7_inst(TELNETasp_PT pt, Cs7Nr cs7_inst := 0) {
147 f_vty_enter_config(pt);
148 f_vty_transceive(pt, "cs7 instance " & int2str(cs7_inst));
149 }
150
Harald Weltef640a012018-04-14 17:49:21 +0200151type record of charstring rof_charstring;
152function f_vty_config2(TELNETasp_PT pt, rof_charstring config_nodes, charstring cmd)
Harald Welte872ce172018-02-16 22:10:33 +0100153{
154 /* enter config mode; enter node */
155 f_vty_enter_config(pt);
Harald Weltef640a012018-04-14 17:49:21 +0200156 for (var integer i := 0; i < sizeof(config_nodes); i := i+1) {
157 f_vty_transceive(pt, config_nodes[i]);
158 }
Harald Welte872ce172018-02-16 22:10:33 +0100159 /* execute command */
160 f_vty_transceive(pt, cmd);
161 /* leave config mode */
162 f_vty_transceive(pt, "end");
163}
164
165
Harald Weltef640a012018-04-14 17:49:21 +0200166function f_vty_config(TELNETasp_PT pt, charstring config_node, charstring cmd)
167{
168 f_vty_config2(pt, {config_node}, cmd);
169}
170
Alexander Couzens98aa59e2018-06-12 13:45:59 +0200171function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
172 var charstring ret := f_vty_transceive_ret(pt, cmd);
173 if (not match(ret, exp_ret)) {
174 setverdict(fail, "Non-matching VTY response: ", ret);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200175 mtc.stop;
Alexander Couzens98aa59e2018-06-12 13:45:59 +0200176 }
177}
178
Alexander Couzens1e6d9902018-06-12 13:48:26 +0200179function f_vty_transceive_not_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
180 var charstring ret := f_vty_transceive_ret(pt, cmd);
181 if (match(ret, exp_ret)) {
182 setverdict(fail, "Unexpected matching VTY response: ", ret);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200183 mtc.stop;
Alexander Couzens1e6d9902018-06-12 13:48:26 +0200184 }
185}
186
Stefan Sperlingcff13562018-11-13 15:24:06 +0100187function f_vty_transceive_match_regex(TELNETasp_PT pt, charstring cmd, charstring regex, integer groupno) return charstring
188{
189 var charstring resp := f_vty_transceive_ret(pt, cmd);
190 return regexp(resp, regex, groupno);
191}
192
193function f_vty_transceive_match_regexp_retry(TELNETasp_PT pt, charstring cmd, charstring regex,
194 integer groupno, integer num_attempts, float retry_delay) return charstring
195{
196 while (num_attempts > 0) {
197 var charstring ret := f_vty_transceive_match_regex(pt, cmd, regex, groupno);
198 if (ret != "") {
199 return ret;
200 }
201 f_sleep(retry_delay);
202 num_attempts := num_attempts - 1;
203 }
204
205 setverdict(fail, "No matching VTY response for regular expression '", regex,
206 "' after ", num_attempts, " attempts." );
207 mtc.stop;
208}
Harald Weltef640a012018-04-14 17:49:21 +0200209
Harald Welte8542cef2017-07-19 20:06:26 +0200210}