aboutsummaryrefslogtreecommitdiffstats
path: root/stp/STP_Tests_IPA.ttcn
blob: f7273dc9767fc5f5b53b6883b712e8e868470962 (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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
module STP_Tests_IPA {

/* Osmocom STP test suite in in TTCN-3
 * (C) 2019 Harald Welte <laforge@gnumonks.org>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

friend module STP_Tests;

import from General_Types all;
import from Osmocom_Types all;
import from IPL4asp_Types all;

import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;

import from SCCP_Types all;
import from SCCP_Templates all;
import from SCCPasp_Types all;
import from SCCP_Emulation all;

import from IPA_Emulation all;

import from M3UA_Emulation all;
import from M3UA_CodecPort all;
import from MTP3asp_Types all;
import from MTP3asp_PortType all;

import from STP_Tests_Common all;

private const integer NR_IPA := 4;

type record of charstring AspNameArray;

modulepar {
	integer mp_stp_ipa_port := 5000;
	integer mp_local_ipa_port := 20000;
	AspNameArray mp_ipa_as_names := {"ipa-as-loadshare-sender",
					 "ipa-as-loadshare-receiver",
					 "ipa-as-loadshare-receiver",
					 "ipa-as-dynamic-asp"
					 };
}

type component IPA_CT extends Test_CT {
	/* for IPA we use the IPA_Emulation and not directly IPA_CodecPort to avoid
	 * having to re-invent IPA CCM handling here */
	port MTP3asp_PT IPA[NR_IPA];
	var IPA_Emulation_CT vc_IPA[NR_IPA];
	var IPA_CCM_Parameters g_ccm_pars[NR_IPA];
}

friend function f_IPA_send(integer idx, octetstring data) runs on IPA_CT {
	var MTP3_Field_sio sio := { ni := '00'B, prio := '00'B, si := '0011'B };
	IPA[idx].send(t_ASP_MTP3_TRANSFERreq(sio, 0, 0, 0, data));
}

friend function f_IPA_exp(integer idx, template (present) octetstring data) runs on IPA_CT {
	alt {
	[] IPA[idx].receive(t_ASP_MTP3_TRANSFERind(?, ?, ?, ?, data)) {
		setverdict(pass);
		}
	[] IPA[idx].receive {
		setverdict(fail, "Received unexpected data on IPA port while waiting for ", data);
		mtc.stop;
		}
	}
}

private function f_rnd_ipa_len() runs on IPA_CT return integer {
	var integer rnd_len := f_rnd_int(100);
	/* We need at least 1 byte of data, othewise osmocom IPA stack will discard and close the socket */
	if (rnd_len == 0) {
		rnd_len := 1;
	}
	return rnd_len;
}

/* Test if traffic is routed from idx_tx to idx_rx */
private function f_test_traffic(integer idx_tx, integer idx_rx)
runs on IPA_CT {
	var octetstring data := f_rnd_octstring(f_rnd_ipa_len());
	f_IPA_send(idx_tx, data);
	f_IPA_exp(idx_rx, data);
}

friend function f_init_ipa() runs on IPA_CT {
	var integer i;

	f_init_common();

	for (i := 0; i < NR_IPA; i:=i+1) {
		vc_IPA[i] := IPA_Emulation_CT.create("IPA" & int2str(i));
		map(vc_IPA[i]:IPA_PORT, system:IPA_CODEC_PT);
		connect(self:IPA[i], vc_IPA[i]:MTP3_SP_PORT);
		g_ccm_pars[i] := c_IPA_default_ccm_pars;
		g_ccm_pars[i].name := mp_ipa_as_names[i];
	}
}

friend function f_connect_ipa(integer idx) runs on IPA_CT {
	vc_IPA[idx].start(IPA_Emulation.main_client(mp_stp_ip, mp_stp_ipa_port, mp_local_ip,
			mp_local_ipa_port+idx, g_ccm_pars[idx]));
}


/* "accept-asp-connections pre-configured" and client from unknown source */
testcase TC_unknown_client_nodynamic() runs on IPA_CT {
	f_init_common();
	f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
		      "accept-asp-connections pre-configured");
	f_init_ipa();
	/* Add 100 to the port since we know that port is not configured in any
	  ASP only up to NR_IPA are configured. */
	vc_IPA[0].start(IPA_Emulation.main_client(mp_stp_ip, mp_stp_ipa_port, mp_local_ip,
			mp_local_ipa_port+100, g_ccm_pars[0]));
	f_sleep(1.0);
	if (IPA[0].checkstate("Connected")) {
		setverdict(fail, "Expected IPA port to be disconnected");
	} else {
		setverdict(pass);
	}
	/* switch back to default */
	f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
		      "accept-asp-connections dynamic-permitted");
}

/* "accept-asp-connections pre-configured" and client from known source */
testcase TC_known_client_nodynamic() runs on IPA_CT {
	f_init_common();
	f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
		      "accept-asp-connections pre-configured");
	f_init_ipa();
	f_connect_ipa(0);
	f_sleep(1.0);
	if (not IPA[0].checkstate("Connected")) {
		setverdict(fail, "Expected IPA port to be connected");
	} else {
		setverdict(pass);
	}
	/* switch back to default */
	f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
		      "accept-asp-connections dynamic-permitted");
}


/* "accept-asp-connections dynamic-permitted" and client from unknown source */
testcase TC_unknown_client_dynamic() runs on IPA_CT {
	f_init_common();
	f_init_ipa();
	/* Add 100 to the port since we know that port is not configured in any
	  ASP only up to NR_IPA are configured. */
	vc_IPA[0].start(IPA_Emulation.main_client(mp_stp_ip, mp_stp_ipa_port, mp_local_ip,
			mp_local_ipa_port+100, g_ccm_pars[0]));
	f_sleep(1.0);
	if (not IPA[0].checkstate("Connected")) {
		setverdict(fail, "Expected IPA port to be connected");
	} else {
		setverdict(pass);
	}
}

private altstep as_count_rx(integer idx, template (present) octetstring exp, inout integer counter)
runs on IPA_CT {
	[] IPA[idx].receive(t_ASP_MTP3_TRANSFERind(?, ?, ?, ?, exp)) {
		counter := counter + 1;
		}
}

/* test "traffic-mode load-share" behavior */
testcase TC_tmt_loadshare() runs on IPA_CT {
	var integer i;

	f_init_ipa();

	/* bring up the 'sender' side (single ASP in AS) */
	f_connect_ipa(0);
	/* activate the first 'receiver' side ASP */
	f_connect_ipa(1);
	f_sleep(1.0);

	/* verify traffic is routed from sender to [sole] receiver */
	for (i := 0; i < 10; i := i+1) {
		f_test_traffic(0, 1);
	}

	/* activate the second 'receiver' side ASP */
	f_connect_ipa(2);
	f_sleep(1.0);

	/* verify traffic is routed from sender to new receiver */
	const integer iter_per_asp := 5;
	var integer num_rx[3] := { 0, 0, 0 };
	for (i := 0; i < 2*iter_per_asp; i := i+1) {
		var octetstring data := f_rnd_octstring(f_rnd_ipa_len());
		f_IPA_send(0, data);
		alt {
		[] as_count_rx(1, data, num_rx[1])
		[] as_count_rx(2, data, num_rx[2])
		}
	}
	/* FIXME: check for extraneous messages? */
	for (i := 1; i <= 2; i := i+1) {
		if (num_rx[i] != iter_per_asp) {
			setverdict(fail, "Received ", num_rx[i], " out of expected ", iter_per_asp,
				   "DATA messages at IPA port ", i);
		}
	}
	setverdict(pass);
}


control {
	execute( TC_unknown_client_nodynamic() );
	execute( TC_known_client_nodynamic() );
	execute( TC_unknown_client_dynamic() );
	execute( TC_tmt_loadshare() );
}


}