Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 1 | module STP_Tests_IPA { |
| 2 | |
| 3 | /* Osmocom STP test suite in in TTCN-3 |
| 4 | * (C) 2019 Harald Welte <laforge@gnumonks.org> |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Released under the terms of GNU General Public License, Version 2 or |
| 8 | * (at your option) any later version. |
| 9 | * |
| 10 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 11 | */ |
| 12 | |
| 13 | friend module STP_Tests; |
| 14 | |
| 15 | import from General_Types all; |
| 16 | import from Osmocom_Types all; |
| 17 | import from IPL4asp_Types all; |
| 18 | |
| 19 | import from TELNETasp_PortType all; |
| 20 | import from Osmocom_VTY_Functions all; |
| 21 | |
| 22 | import from SCCP_Types all; |
| 23 | import from SCCP_Templates all; |
| 24 | import from SCCPasp_Types all; |
| 25 | import from SCCP_Emulation all; |
| 26 | |
| 27 | import from IPA_Emulation all; |
| 28 | |
| 29 | import from M3UA_Emulation all; |
| 30 | import from M3UA_CodecPort all; |
| 31 | import from MTP3asp_Types all; |
| 32 | import from MTP3asp_PortType all; |
| 33 | |
| 34 | import from STP_Tests_Common all; |
| 35 | |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 36 | private const integer NR_IPA := 7; |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 37 | |
| 38 | type record of charstring AspNameArray; |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 39 | |
| 40 | modulepar { |
| 41 | integer mp_stp_ipa_port := 5000; |
| 42 | integer mp_local_ipa_port := 20000; |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 43 | AspNameArray mp_ipa_as_names := {"ipa-as-loadshare-sender", |
| 44 | "ipa-as-loadshare-receiver", |
| 45 | "ipa-as-loadshare-receiver", |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 46 | "ipa-as-dynamic-asp", |
| 47 | "ipa-as-override-sender", |
| 48 | "ipa-as-override-receiver", |
| 49 | "ipa-as-override-receiver" |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 50 | }; |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | type component IPA_CT extends Test_CT { |
| 54 | /* for IPA we use the IPA_Emulation and not directly IPA_CodecPort to avoid |
| 55 | * having to re-invent IPA CCM handling here */ |
| 56 | port MTP3asp_PT IPA[NR_IPA]; |
| 57 | var IPA_Emulation_CT vc_IPA[NR_IPA]; |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 58 | var IPA_CCM_Parameters g_ccm_pars[NR_IPA]; |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | friend function f_IPA_send(integer idx, octetstring data) runs on IPA_CT { |
| 62 | var MTP3_Field_sio sio := { ni := '00'B, prio := '00'B, si := '0011'B }; |
| 63 | IPA[idx].send(t_ASP_MTP3_TRANSFERreq(sio, 0, 0, 0, data)); |
| 64 | } |
| 65 | |
| 66 | friend function f_IPA_exp(integer idx, template (present) octetstring data) runs on IPA_CT { |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 67 | alt { |
| 68 | [] IPA[idx].receive(t_ASP_MTP3_TRANSFERind(?, ?, ?, ?, data)) { |
| 69 | setverdict(pass); |
| 70 | } |
| 71 | [] IPA[idx].receive { |
| 72 | setverdict(fail, "Received unexpected data on IPA port while waiting for ", data); |
| 73 | mtc.stop; |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 78 | private function f_rnd_ipa_len() runs on IPA_CT return integer { |
| 79 | var integer rnd_len := f_rnd_int(100); |
| 80 | /* We need at least 1 byte of data, othewise osmocom IPA stack will discard and close the socket */ |
| 81 | if (rnd_len == 0) { |
| 82 | rnd_len := 1; |
| 83 | } |
| 84 | return rnd_len; |
| 85 | } |
| 86 | |
| 87 | /* Test if traffic is routed from idx_tx to idx_rx */ |
| 88 | private function f_test_traffic(integer idx_tx, integer idx_rx) |
| 89 | runs on IPA_CT { |
| 90 | var octetstring data := f_rnd_octstring(f_rnd_ipa_len()); |
| 91 | f_IPA_send(idx_tx, data); |
| 92 | f_IPA_exp(idx_rx, data); |
| 93 | } |
| 94 | |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 95 | friend function f_init_ipa() runs on IPA_CT { |
| 96 | var integer i; |
| 97 | |
| 98 | f_init_common(); |
| 99 | |
| 100 | for (i := 0; i < NR_IPA; i:=i+1) { |
| 101 | vc_IPA[i] := IPA_Emulation_CT.create("IPA" & int2str(i)); |
| 102 | map(vc_IPA[i]:IPA_PORT, system:IPA_CODEC_PT); |
| 103 | connect(self:IPA[i], vc_IPA[i]:MTP3_SP_PORT); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 104 | g_ccm_pars[i] := c_IPA_default_ccm_pars; |
| 105 | g_ccm_pars[i].name := mp_ipa_as_names[i]; |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 106 | } |
| 107 | } |
| 108 | |
Pau Espin Pedrol | 9f51483 | 2019-11-08 15:24:13 +0100 | [diff] [blame] | 109 | friend function f_connect_ipa(integer idx, boolean use_unknown_asp_port := false) runs on IPA_CT { |
| 110 | var integer port_offset := 0; |
| 111 | if (use_unknown_asp_port) { |
| 112 | /* Add 100 to the port since we know that port is not configured in any |
| 113 | ASP only up to NR_IPA are configured. */ |
| 114 | port_offset := 100; |
| 115 | } |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 116 | vc_IPA[idx].start(IPA_Emulation.main_client(mp_stp_ip, mp_stp_ipa_port, mp_local_ip, |
Pau Espin Pedrol | 9f51483 | 2019-11-08 15:24:13 +0100 | [diff] [blame] | 117 | mp_local_ipa_port + idx + port_offset, g_ccm_pars[idx])); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 118 | } |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 119 | |
| 120 | |
| 121 | /* "accept-asp-connections pre-configured" and client from unknown source */ |
| 122 | testcase TC_unknown_client_nodynamic() runs on IPA_CT { |
| 123 | f_init_common(); |
| 124 | f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"}, |
| 125 | "accept-asp-connections pre-configured"); |
| 126 | f_init_ipa(); |
Pau Espin Pedrol | 9f51483 | 2019-11-08 15:24:13 +0100 | [diff] [blame] | 127 | f_connect_ipa(0, true); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 128 | f_sleep(1.0); |
| 129 | if (IPA[0].checkstate("Connected")) { |
| 130 | setverdict(fail, "Expected IPA port to be disconnected"); |
| 131 | } else { |
| 132 | setverdict(pass); |
| 133 | } |
| 134 | /* switch back to default */ |
| 135 | f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"}, |
| 136 | "accept-asp-connections dynamic-permitted"); |
| 137 | } |
| 138 | |
| 139 | /* "accept-asp-connections pre-configured" and client from known source */ |
| 140 | testcase TC_known_client_nodynamic() runs on IPA_CT { |
| 141 | f_init_common(); |
| 142 | f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"}, |
| 143 | "accept-asp-connections pre-configured"); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 144 | f_init_ipa(); |
Pau Espin Pedrol | 9f51483 | 2019-11-08 15:24:13 +0100 | [diff] [blame] | 145 | f_connect_ipa(0, false); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 146 | f_sleep(1.0); |
| 147 | if (not IPA[0].checkstate("Connected")) { |
| 148 | setverdict(fail, "Expected IPA port to be connected"); |
| 149 | } else { |
| 150 | setverdict(pass); |
| 151 | } |
| 152 | /* switch back to default */ |
| 153 | f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"}, |
| 154 | "accept-asp-connections dynamic-permitted"); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | |
| 158 | /* "accept-asp-connections dynamic-permitted" and client from unknown source */ |
| 159 | testcase TC_unknown_client_dynamic() runs on IPA_CT { |
| 160 | f_init_common(); |
| 161 | f_init_ipa(); |
Pau Espin Pedrol | 9f51483 | 2019-11-08 15:24:13 +0100 | [diff] [blame] | 162 | f_connect_ipa(0, true); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 163 | f_sleep(1.0); |
| 164 | if (not IPA[0].checkstate("Connected")) { |
| 165 | setverdict(fail, "Expected IPA port to be connected"); |
| 166 | } else { |
| 167 | setverdict(pass); |
| 168 | } |
| 169 | } |
| 170 | |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 171 | private function f_tc_tmt_override(boolean unknwon_dynamic_asp) |
| 172 | runs on IPA_CT { |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 173 | f_init_ipa(); |
| 174 | |
| 175 | /* bring up the 'sender' side (single ASP in AS) */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 176 | f_connect_ipa(4, unknwon_dynamic_asp); |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 177 | /* activate the first 'receiver' side ASP */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 178 | f_connect_ipa(5, unknwon_dynamic_asp); |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 179 | f_sleep(1.0); |
| 180 | |
| 181 | /* verify traffic is routed from sender to [sole] receiver */ |
| 182 | f_test_traffic(4, 5); |
| 183 | |
| 184 | /* activate the second 'receiver' side ASP */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 185 | f_connect_ipa(6, unknwon_dynamic_asp); |
Pau Espin Pedrol | b72928d | 2019-11-07 17:38:32 +0100 | [diff] [blame] | 186 | f_sleep(1.0); |
| 187 | |
| 188 | /* verify traffic is routed from sender to new receiver */ |
| 189 | f_test_traffic(4, 6); |
| 190 | } |
| 191 | |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 192 | /* test "traffic-mode override" behavior */ |
| 193 | testcase TC_tmt_override() runs on IPA_CT { |
| 194 | f_tc_tmt_override(false); |
| 195 | } |
| 196 | |
| 197 | /* test "traffic-mode override" behavior, with "accept-asp-connections dynamic-permitted" and clients from unknown ASPs */ |
| 198 | testcase TC_unknown_client_dynamic_tmt_override() runs on IPA_CT { |
| 199 | f_tc_tmt_override(true); |
| 200 | } |
| 201 | |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 202 | private altstep as_count_rx(integer idx, template (present) octetstring exp, inout integer counter) |
| 203 | runs on IPA_CT { |
| 204 | [] IPA[idx].receive(t_ASP_MTP3_TRANSFERind(?, ?, ?, ?, exp)) { |
| 205 | counter := counter + 1; |
| 206 | } |
| 207 | } |
| 208 | |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 209 | private function f_tc_tmt_loadshare(boolean unknwon_dynamic_asp) |
| 210 | runs on IPA_CT { |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 211 | var integer i; |
| 212 | |
| 213 | f_init_ipa(); |
| 214 | |
| 215 | /* bring up the 'sender' side (single ASP in AS) */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 216 | f_connect_ipa(0, unknwon_dynamic_asp); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 217 | /* activate the first 'receiver' side ASP */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 218 | f_connect_ipa(1, unknwon_dynamic_asp); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 219 | f_sleep(1.0); |
| 220 | |
| 221 | /* verify traffic is routed from sender to [sole] receiver */ |
| 222 | for (i := 0; i < 10; i := i+1) { |
| 223 | f_test_traffic(0, 1); |
| 224 | } |
| 225 | |
| 226 | /* activate the second 'receiver' side ASP */ |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 227 | f_connect_ipa(2, unknwon_dynamic_asp); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 228 | f_sleep(1.0); |
| 229 | |
| 230 | /* verify traffic is routed from sender to new receiver */ |
| 231 | const integer iter_per_asp := 5; |
| 232 | var integer num_rx[3] := { 0, 0, 0 }; |
| 233 | for (i := 0; i < 2*iter_per_asp; i := i+1) { |
| 234 | var octetstring data := f_rnd_octstring(f_rnd_ipa_len()); |
| 235 | f_IPA_send(0, data); |
| 236 | alt { |
| 237 | [] as_count_rx(1, data, num_rx[1]) |
| 238 | [] as_count_rx(2, data, num_rx[2]) |
| 239 | } |
| 240 | } |
| 241 | /* FIXME: check for extraneous messages? */ |
| 242 | for (i := 1; i <= 2; i := i+1) { |
| 243 | if (num_rx[i] != iter_per_asp) { |
| 244 | setverdict(fail, "Received ", num_rx[i], " out of expected ", iter_per_asp, |
| 245 | "DATA messages at IPA port ", i); |
| 246 | } |
| 247 | } |
| 248 | setverdict(pass); |
| 249 | } |
| 250 | |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 251 | /* test "traffic-mode load-share" behavior */ |
| 252 | testcase TC_tmt_loadshare() runs on IPA_CT { |
| 253 | f_tc_tmt_loadshare(false); |
| 254 | } |
| 255 | |
| 256 | /* test "traffic-mode override" behavior, with "accept-asp-connections dynamic-permitted" and clients from unknown ASPs */ |
| 257 | testcase TC_unknown_client_dynamic_tmt_loadshare() runs on IPA_CT { |
| 258 | f_tc_tmt_override(true); |
| 259 | } |
| 260 | |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 261 | control { |
| 262 | execute( TC_unknown_client_nodynamic() ); |
| 263 | execute( TC_known_client_nodynamic() ); |
| 264 | execute( TC_unknown_client_dynamic() ); |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 265 | execute( TC_tmt_override() ); |
| 266 | execute( TC_unknown_client_dynamic_tmt_override() ); |
Pau Espin Pedrol | 01ec0bf | 2019-11-07 14:50:07 +0100 | [diff] [blame] | 267 | execute( TC_tmt_loadshare() ); |
Pau Espin Pedrol | 7021cfd | 2019-11-08 15:25:44 +0100 | [diff] [blame] | 268 | execute( TC_unknown_client_dynamic_tmt_loadshare() ); |
Harald Welte | 0db4413 | 2019-10-17 11:09:05 +0200 | [diff] [blame] | 269 | } |
| 270 | |
| 271 | |
| 272 | } |