blob: 74c2e8c00e450811bd14cfcb08ed360a5e153498 [file] [log] [blame]
Harald Welte379d45a2017-08-03 09:55:15 +02001module GGSN_Tests {
2
Harald Welte34b5a952019-05-27 11:54:11 +02003/* GGSN test suite in TTCN-3
4 * (C) 2017-2019 Harald Welte <laforge@gnumonks.org>
5 * (C) 2018-2019 sysmocom - s.f.m.c. GmbH
6 * All rights reserved.
7 *
8 * Released under the terms of GNU General Public License, Version 2 or
9 * (at your option) any later version.
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
Pau Espin Pedrold25095f2022-05-18 16:29:05 +020014 import from TCCEncoding_Functions all;
Harald Welte34b5a952019-05-27 11:54:11 +020015
Harald Welte94ade362017-08-04 00:36:55 +020016 import from General_Types all;
Harald Welte811651e2017-08-05 15:25:06 +020017 import from Osmocom_Types all;
Pau Espin Pedrolc04c69e2020-03-03 16:46:29 +010018 import from Misc_Helpers all;
Harald Welte94ade362017-08-04 00:36:55 +020019 import from IPL4asp_PortType all;
20 import from IPL4asp_Types all;
Pau Espin Pedrol4b090c92024-02-29 19:47:07 +010021 import from GTPv1C_CodecPort all;
22 import from GTPv1U_CodecPort all;
23 import from GTPv1C_CodecPort_CtrlFunct all;
24 import from GTPv1U_CodecPort_CtrlFunct all;
Harald Welte94ade362017-08-04 00:36:55 +020025 import from GTPC_Types all;
26 import from GTPU_Types all;
Pau Espin Pedrol4b090c92024-02-29 19:47:07 +010027 import from GTPv1C_Templates all;
28 import from GTPv1U_Templates all;
Harald Welte71a36022017-12-04 18:55:58 +010029 import from IPCP_Types all;
Harald Weltef8298542019-04-10 10:15:28 +020030 import from PAP_Types all;
Harald Welte231b9412017-08-09 17:16:31 +020031 import from IP_Types all;
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +010032 import from ICMP_Types all;
Harald Welte231b9412017-08-09 17:16:31 +020033 import from ICMPv6_Types all;
Pau Espin Pedrole16e9282024-03-01 14:45:22 +010034 import from ICMP_Templates all;
35 import from ICMPv6_Templates all;
Harald Welteddeecbb2017-08-18 22:53:30 +020036 import from Native_Functions all;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +020037 import from Osmocom_VTY_Functions all;
38 import from TELNETasp_PortType all;
Harald Welte94ade362017-08-04 00:36:55 +020039
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +010040 import from DIAMETER_Types all;
41 import from DIAMETER_Templates all;
Pau Espin Pedrol867b1302024-01-24 16:14:28 +010042 import from DIAMETER_ts29_212_Templates all;
Pau Espin Pedrol117a94f2023-12-21 16:10:12 +010043 import from DIAMETER_ts29_272_Templates all;
Pau Espin Pedrol867b1302024-01-24 16:14:28 +010044 import from DIAMETER_ts32_299_Templates all;
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +010045 import from DIAMETER_Emulation all;
46
Harald Welte94ade362017-08-04 00:36:55 +020047 const integer GTP0_PORT := 3386;
48 const integer GTP1C_PORT := 2123;
49 const integer GTP1U_PORT := 2152;
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +010050 const integer PCRF_PORT := 3868;
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +010051 const integer OCS_PORT := 3869;
Harald Welteddeecbb2017-08-18 22:53:30 +020052
Pau Espin Pedrolc1b1ddf2022-01-19 18:10:30 +010053 type enumerated GGSN_Impl {
54 GGSN_IMPL_OSMOCOM,
55 GGSN_IMPL_OPEN5GS
56 };
57
Harald Welteddeecbb2017-08-18 22:53:30 +020058 modulepar {
Stefan Sperlingcb782b92018-04-03 16:03:15 +020059 /* Default IP addresses. May be overridden by GGSN_Tests configuration files. */
60
61 /* The SGSN simulated by TTCN3 will bind to these addresses for GTP control and GTP user planes. */
Harald Welteddeecbb2017-08-18 22:53:30 +020062 charstring m_bind_ip_gtpc := "127.23.42.1";
63 charstring m_bind_ip_gtpu := "127.23.42.1";
64
Stefan Sperlingcb782b92018-04-03 16:03:15 +020065 /* Addresses the GGSN which is being tested is listening on for SGSN connections. */
Harald Welteddeecbb2017-08-18 22:53:30 +020066 charstring m_ggsn_ip_gtpc := "127.0.0.6";
67 charstring m_ggsn_ip_gtpu := "127.0.0.6";
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +010068
Stefan Sperlingcb782b92018-04-03 16:03:15 +020069 /*
70 * Our tests expect to see these DNS servers in 'Create PDP context responses' sent by the GGSN.
71 * These addresses must therefore match 'ip[v6] dns' options configured in osmo-ggsn.conf.
72 *
73 * These addresses are not expected to serve actual DNS requests. However, tests may expect to be
74 * able to ping these addresses (currently, IPv4 addresses must respond with an ICMP 'echo reply',
75 * and IPv6 addresses may respond with either ICMPv6 'echo reply' or 'destination unreachable').
76 */
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +010077 charstring m_ggsn_ip4_dns1 := "192.168.100.1"
78 charstring m_ggsn_ip4_dns2 := "8.8.8.8"
Pau Espin Pedrol363ba482018-01-29 18:42:00 +010079 charstring m_ggsn_ip6_dns1 := "2001:4860:4860::8888"
80 charstring m_ggsn_ip6_dns2 := "2001:4860:4860::8844"
Stefan Sperlingcb782b92018-04-03 16:03:15 +020081
82 /*
83 * Additional address ranges are defined in osmo-ggsn.conf from which addresses are assigned
84 * to MS "behind" the simulated SGSN. These addresses appear on tun devices used by osmo-ggsn.
85 * The tests expect to be able to send ping packets between any two simulated MS within the same
86 * address range. This requires IP forwarding to be enabled on the corresponding tun interfaces.
87 */
Pau Espin Pedrolbfad97f2022-11-04 12:03:17 +010088 integer mp_t3_response := 5; /* local T3-RESPONSE timeout, seconds */
89 integer mp_n3_requests := 3; /* local N3-REQUESTS counter */
Pau Espin Pedrolc1b1ddf2022-01-19 18:10:30 +010090
91 GGSN_Impl m_ggsn_impl := GGSN_IMPL_OSMOCOM;
Harald Welteddeecbb2017-08-18 22:53:30 +020092 }
Harald Welte94ade362017-08-04 00:36:55 +020093
Harald Welte811651e2017-08-05 15:25:06 +020094 type set PdpContext {
95 hexstring imsi,
96 octetstring msisdn optional,
97 octetstring apn,
Harald Welteed7a1772017-08-09 20:26:20 +020098 ProtConfigOptions pco_req optional,
99 ProtConfigOptions pco_neg optional,
Harald Welte811651e2017-08-05 15:25:06 +0200100 EndUserAddress eua,
Harald Welte231b9412017-08-09 17:16:31 +0200101 OCT16 ip6_prefix optional,
Harald Welte811651e2017-08-05 15:25:06 +0200102 BIT4 nsapi,
103 /* TEI (Data) local side */
104 OCT4 teid,
105 /* TEI (Control) local side */
106 OCT4 teic,
107 /* TEI (Data) remote side */
108 OCT4 teid_remote,
109 /* TEI (Control) remote side */
Pau Espin Pedrol38aeffb2022-02-01 20:46:29 +0100110 OCT4 teic_remote,
Pau Espin Pedrolca587f12022-02-02 10:42:01 +0100111 OCT1 ratType optional,
Pau Espin Pedrol0e127872022-05-12 17:58:50 +0200112 UserLocationInformation uli optional,
Pau Espin Pedrol38968e92022-05-13 16:17:48 +0200113 OCT2 charging_char optional,
Pau Espin Pedrol535ca262022-05-16 14:07:17 +0200114 OCT8 imeisv optional,
115 MS_TimeZone ms_tz optional
Harald Welte811651e2017-08-05 15:25:06 +0200116 }
117
Harald Welte94ade362017-08-04 00:36:55 +0200118 type component GT_CT {
119 port GTPC_PT GTPC;
120 port GTPU_PT GTPU;
121
Harald Welte0be142b2017-08-13 13:28:10 +0200122 var boolean g_initialized := false;
123
Harald Welte94ade362017-08-04 00:36:55 +0200124 var OCT1 g_restart_ctr := '01'O;
125 /* FIXME: unify with g_bind_ip + parse from config file */
Harald Welteddeecbb2017-08-18 22:53:30 +0200126 var OCT4 g_sgsn_ip_c;
127 var OCT4 g_sgsn_ip_u;
Harald Welte94ade362017-08-04 00:36:55 +0200128 /* FIXME: parse remName from config file */
Pau Espin Pedrol4b090c92024-02-29 19:47:07 +0100129 var Gtp1cPeer g_peer_c := { connId := 0, remName := m_ggsn_ip_gtpc, remPort := GTP1C_PORT };
130 var Gtp1uPeer g_peer_u := { connId := 0, remName := m_ggsn_ip_gtpu, remPort := GTP1U_PORT };
Harald Welte94ade362017-08-04 00:36:55 +0200131 timer T_default := 3.0;
Harald Welte5438b9d2017-08-13 13:27:48 +0200132
133 /* next to-be-sent GTP-C sequence number */
134 var uint16_t g_c_seq_nr;
135 /* next to-be-sent GTP-U sequence number */
136 var uint16_t g_d_seq_nr;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200137
138 port TELNETasp_PT GGSNVTY;
Harald Welted2394e92018-04-26 10:21:49 +0200139 var boolean use_gtpu_txseq := false;
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100140 var integer g_use_echo_intval := 0; /* 0 = disabled */
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100141
Pau Espin Pedrol733369a2022-05-20 18:39:55 +0200142 /* Emulated PCRF, used with m_ggsn_impl = GGSN_IMPL_OPEN5GS */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200143 var DIAMETER_conn_parameters g_gx_pars;
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100144 var DIAMETER_Emulation_CT vc_Gx;
145 port DIAMETER_PT Gx_UNIT;
146 port DIAMETEREM_PROC_PT Gx_PROC;
Pau Espin Pedrol733369a2022-05-20 18:39:55 +0200147
148 /* Emulated OCS, used with m_ggsn_impl = GGSN_IMPL_OPEN5GS */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200149 var DIAMETER_conn_parameters g_gy_pars;
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100150 var DIAMETER_Emulation_CT vc_Gy;
151 port DIAMETER_PT Gy_UNIT;
152 port DIAMETEREM_PROC_PT Gy_PROC;
153 var integer g_gy_validity_time := 0; /* In seconds. 0 => disabled, !0 => grant over CC-Time period */
Pau Espin Pedrol52562c92022-05-23 15:45:46 +0200154 var integer g_gy_volume_threshold := 0; /* In octets. 0 => disabled, !0 => request IUT to revalidate after N octets */
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200155 var PDU_DIAMETER g_rx_gy; /* Store last received Gy message */
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200156 }
157
158 private function f_init_vty() runs on GT_CT {
159 map(self:GGSNVTY, system:GGSNVTY);
160 f_vty_set_prompts(GGSNVTY);
161 f_vty_transceive(GGSNVTY, "enable");
162 }
163
164 private function f_vty_set_gpdu_txseq(boolean enable) runs on GT_CT {
165 f_vty_enter_config(GGSNVTY);
166 f_vty_transceive(GGSNVTY, "ggsn ggsn0");
Pau Espin Pedrol205a3842018-07-06 13:24:14 +0200167
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200168 f_vty_transceive(GGSNVTY, "apn internet");
169 if (enable) {
170 f_vty_transceive(GGSNVTY, "g-pdu tx-sequence-numbers");
171 } else {
172 f_vty_transceive(GGSNVTY, "no g-pdu tx-sequence-numbers");
173 }
Pau Espin Pedrol205a3842018-07-06 13:24:14 +0200174 f_vty_transceive(GGSNVTY, "exit");
175
176 f_vty_transceive(GGSNVTY, "apn inet6");
177 if (enable) {
178 f_vty_transceive(GGSNVTY, "g-pdu tx-sequence-numbers");
179 } else {
180 f_vty_transceive(GGSNVTY, "no g-pdu tx-sequence-numbers");
181 }
182 f_vty_transceive(GGSNVTY, "exit");
183
184 f_vty_transceive(GGSNVTY, "apn inet46");
185 if (enable) {
186 f_vty_transceive(GGSNVTY, "g-pdu tx-sequence-numbers");
187 } else {
188 f_vty_transceive(GGSNVTY, "no g-pdu tx-sequence-numbers");
189 }
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200190 f_vty_transceive(GGSNVTY, "end");
191 }
192
193 private function f_verify_gtpu_txseq(in PDU_GTPU gtpu, in boolean expect_gptu_txseq) return boolean {
194 if (expect_gptu_txseq) {
195 if (gtpu.s_bit != '1'B) {
196 log("GTPU sequence number expected but not present")
197 return false;
198 }
199 } else {
200 if (gtpu.s_bit != '0'B) {
201 log("GTPU sequence number not expected but present")
202 return false;
203 }
204 }
205 return true;
Harald Welte94ade362017-08-04 00:36:55 +0200206 }
207
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100208 private function f_vty_enable_echo_interval(integer intval_sec) runs on GT_CT {
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200209 f_vty_enter_config(GGSNVTY);
210 f_vty_transceive(GGSNVTY, "ggsn ggsn0");
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100211 if (intval_sec > 0) {
212 f_vty_transceive(GGSNVTY, "echo-interval " & int2str(intval_sec));
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200213 } else {
214 f_vty_transceive(GGSNVTY, "no echo-interval");
215 }
216 f_vty_transceive(GGSNVTY, "end");
217 }
218
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100219 private function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
220 runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
221 DIAMETER_UNIT.send(msg);
222 return omit;
223 }
224
225 private function f_init_diameter(charstring id) runs on GT_CT {
226 var DIAMETEROps ops := {
227 create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
228 unitdata_cb := refers(DiameterForwardUnitdataCallback),
229 raw := true /* handler mode (single component for all IMSI)) */
230 };
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100231
232 /* Gx setup: */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200233 g_gx_pars := {
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100234 remote_ip := m_ggsn_ip_gtpc,
235 remote_sctp_port := -1,
236 local_ip := m_bind_ip_gtpc,
237 local_sctp_port := PCRF_PORT,
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100238 origin_host := "pcrf.localdomain",
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100239 origin_realm := "localdomain",
Pau Espin Pedrol33b47492022-03-08 17:43:01 +0100240 auth_app_id := omit,
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100241 vendor_app_id := c_DIAMETER_3GPP_Gx_AID
242 };
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100243 vc_Gx := DIAMETER_Emulation_CT.create(id);
244 map(vc_Gx:DIAMETER, system:DIAMETER_CODEC_PT);
245 connect(vc_Gx:DIAMETER_UNIT, self:Gx_UNIT);
246 connect(vc_Gx:DIAMETER_PROC, self:Gx_PROC);
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200247 vc_Gx.start(DIAMETER_Emulation.main(ops, g_gx_pars, id));
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100248
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100249 /* Gy setup: */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200250 g_gy_pars := {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100251 remote_ip := m_ggsn_ip_gtpc,
252 remote_sctp_port := -1,
253 local_ip := m_bind_ip_gtpc,
254 local_sctp_port := OCS_PORT,
255 origin_host := "ocs.localdomain",
256 origin_realm := "localdomain",
257 auth_app_id := c_DIAMETER_CREDIT_CONTROL_AID,
258 vendor_app_id := omit
259 };
260 vc_Gy := DIAMETER_Emulation_CT.create(id);
261 map(vc_Gy:DIAMETER, system:DIAMETER_CODEC_PT);
262 connect(vc_Gy:DIAMETER_UNIT, self:Gy_UNIT);
263 connect(vc_Gy:DIAMETER_PROC, self:Gy_PROC);
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200264 vc_Gy.start(DIAMETER_Emulation.main(ops, g_gy_pars, id));
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100265
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100266 f_diameter_wait_capability(Gx_UNIT);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100267 f_diameter_wait_capability(Gy_UNIT);
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100268 /* Give some time for our emulation to get out of SUSPECT list of SUT (3 watchdong ping-pongs):
269 * RFC6733 sec 5.1
270 * RFC3539 sec 3.4.1 [5]
271 * https://github.com/freeDiameter/freeDiameter/blob/master/libfdcore/p_psm.c#L49
272 */
273 f_sleep(1.0);
274 }
275
Harald Welte94ade362017-08-04 00:36:55 +0200276 function f_init() runs on GT_CT {
Harald Welte0be142b2017-08-13 13:28:10 +0200277 if (g_initialized == true) {
278 return;
279 }
280 g_initialized := true;
281
Harald Welteddeecbb2017-08-18 22:53:30 +0200282 g_sgsn_ip_c := f_inet_addr(m_bind_ip_gtpc);
283 g_sgsn_ip_u := f_inet_addr(m_bind_ip_gtpu);
284
Harald Welte94ade362017-08-04 00:36:55 +0200285 var Result res;
286 map(self:GTPC, system:GTPC);
Pau Espin Pedrol4b090c92024-02-29 19:47:07 +0100287 res := GTPv1C_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, m_bind_ip_gtpc, GTP1C_PORT, {udp:={}});
Harald Welte94ade362017-08-04 00:36:55 +0200288 log("GTP1C ConnectionID: ", res.connId);
Harald Welte811651e2017-08-05 15:25:06 +0200289 g_peer_c.connId := res.connId;
Harald Welte94ade362017-08-04 00:36:55 +0200290
291 map(self:GTPU, system:GTPU);
Pau Espin Pedrol4b090c92024-02-29 19:47:07 +0100292 res := GTPv1U_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, m_bind_ip_gtpu, GTP1U_PORT, {udp:={}});
Harald Welte811651e2017-08-05 15:25:06 +0200293 g_peer_u.connId:= res.connId;
Harald Welte5438b9d2017-08-13 13:27:48 +0200294
295 g_restart_ctr := f_rnd_octstring(1);
Harald Welte11dbc7b2017-08-13 18:57:56 +0200296 g_c_seq_nr := f_rnd_int(65535);
297 g_d_seq_nr := f_rnd_int(65535);
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200298
Pau Espin Pedrolc1b1ddf2022-01-19 18:10:30 +0100299 if (m_ggsn_impl == GGSN_IMPL_OSMOCOM) {
300 f_init_vty();
301 f_vty_set_gpdu_txseq(use_gtpu_txseq);
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100302 f_vty_enable_echo_interval(g_use_echo_intval);
Oliver Smith95722c62023-10-20 13:59:10 +0200303 /* Emit a marker to appear in the SUT's own logging output */
304 f_logp(GGSNVTY, testcasename() & "() start");
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100305 } else if (m_ggsn_impl == GGSN_IMPL_OPEN5GS) {
306 f_init_diameter(testcasename());
Pau Espin Pedrolc1b1ddf2022-01-19 18:10:30 +0100307 }
Harald Welte94ade362017-08-04 00:36:55 +0200308 }
309
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +0100310 function f_shutdown_helper() runs on GT_CT {
Pau Espin Pedrolbfad97f2022-11-04 12:03:17 +0100311 /* Sleep (T3-RESPONSE * N3-REQUESTS) seconds.
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +0100312 * This ensures all retransmit queues are cleared before jumping
313 * into next tests, hence avoding situation where a test resuses
314 * a seqnum still in the GGSN's resp queue (dup req detector).
315 * See OS#5485 avout decreasing time. We could also add a new
316 * VTY command that calls gtp_clear_queues() */
Pau Espin Pedrolbfad97f2022-11-04 12:03:17 +0100317 f_sleep(int2float(mp_t3_response * mp_n3_requests));
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +0100318 setverdict(pass);
319 }
320
Harald Welte94ade362017-08-04 00:36:55 +0200321 /* Altstep implementing responses to any incoming echo requests */
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100322 private altstep pingpong() runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200323 var Gtp1cUnitdata ud;
Harald Welte3af89482017-08-04 16:20:23 +0200324 var Gtp1uUnitdata udu;
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100325 [g_use_echo_intval > 0] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
Harald Welte811651e2017-08-05 15:25:06 +0200326 var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200327 GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
Harald Welte94ade362017-08-04 00:36:55 +0200328 repeat;
329 };
Pau Espin Pedrol05118022022-02-17 19:49:13 +0100330 [g_use_echo_intval == 0] GTPC.receive(tr_GTPC_PING(?)) {
Pau Espin Pedrolc04c69e2020-03-03 16:46:29 +0100331 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
332 "GTP Echo Req rceived but not enabled in VTY");
Harald Welte3af89482017-08-04 16:20:23 +0200333 };
Pau Espin Pedrolc04c69e2020-03-03 16:46:29 +0100334 [] T_default.timeout {
335 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
Oliver Smithbbbe05d2024-02-28 11:14:32 +0100336 "pingpong T_default timeout");
Pau Espin Pedrolc04c69e2020-03-03 16:46:29 +0100337 };
Harald Welte94ade362017-08-04 00:36:55 +0200338 }
339
Harald Welte811651e2017-08-05 15:25:06 +0200340 /* 'internet' in DNS encoding */
Harald Welteed097432017-08-13 13:28:49 +0200341 const octetstring c_ApnInternet := '08696E7465726E6574'O;
342 const octetstring c_ApnInet6 := '05696E657436'O;
343 const octetstring c_ApnInet46 := '06696E65743436'O;
Harald Welte94ade362017-08-04 00:36:55 +0200344
Harald Welte811651e2017-08-05 15:25:06 +0200345 /* return random NSAPI */
346 function f_rnd_nsapi() return BIT4 {
347 return int2bit(f_rnd_int(16), 4);
348 }
349
350 /* return random TEI[DC] */
351 function f_rnd_tei() return OCT4 {
352 return int2oct(f_rnd_int(4294967296), 4);
353 }
354
Pau Espin Pedrol38968e92022-05-13 16:17:48 +0200355 /* return random IMEI(SV) */
356 function f_rnd_imeisv() return OCT8 {
357 return hex2oct(f_rnd_hexstring(16, 10));
358 }
359
Harald Welte811651e2017-08-05 15:25:06 +0200360 /* define an (internal) representation of a PDP context */
Pau Espin Pedrold25095f2022-05-18 16:29:05 +0200361 template PdpContext t_DefinePDP(hexstring imsi, charstring msisdn, octetstring apn,
Pau Espin Pedrol38aeffb2022-02-01 20:46:29 +0100362 EndUserAddress eua, OCT1 ratType := '02'O /* GERAN */) := {
Harald Welte811651e2017-08-05 15:25:06 +0200363 imsi := imsi,
Pau Espin Pedrold25095f2022-05-18 16:29:05 +0200364 msisdn := '11'O & f_enc_TBCD(msisdn), /* encoded as TS 29.060 7.7.33, TS 29.002 */
Harald Welte811651e2017-08-05 15:25:06 +0200365 nsapi := f_rnd_nsapi(),
366 apn := apn,
Harald Welteed7a1772017-08-09 20:26:20 +0200367 pco_req := omit,
Harald Welte811651e2017-08-05 15:25:06 +0200368 eua := eua,
369 teid := f_rnd_tei(),
Pau Espin Pedrol38aeffb2022-02-01 20:46:29 +0100370 teic := f_rnd_tei(),
Pau Espin Pedrolca587f12022-02-02 10:42:01 +0100371 ratType := ratType,
372 uli := {
373 type_gtpc := '98'O,
374 lengthf := 0 /* filled in by encoder */,
375 geographicLocationType := '00'O /* CGI */,
376 geographicLocation := {
377 geographicLocationCGI := ts_GeographicLocationCGI('262'H, '42F'H, '0001'O, '0002'O)
378 }
Pau Espin Pedrol0e127872022-05-12 17:58:50 +0200379 },
Pau Espin Pedrol38968e92022-05-13 16:17:48 +0200380 charging_char := '0000'O,
Pau Espin Pedrol535ca262022-05-16 14:07:17 +0200381 imeisv := f_rnd_imeisv(),
382 ms_tz := f_ts_MS_TimeZone('03'O, '01'B)
Harald Welte811651e2017-08-05 15:25:06 +0200383 }
384
385 /* send GTP-C for a given context and increment sequence number */
Harald Welte41575e92017-08-13 13:49:57 +0200386 function f_send_gtpc(in template Gtp1cUnitdata data) runs on GT_CT {
Harald Welte811651e2017-08-05 15:25:06 +0200387 GTPC.send(data);
Pau Espin Pedrol82a7f702022-05-19 17:41:29 +0200388 g_c_seq_nr := (g_c_seq_nr + 1) mod 65536;
Harald Welte811651e2017-08-05 15:25:06 +0200389 }
390
391 /* send GTP-U for a given context and increment sequence number */
Harald Welte231b9412017-08-09 17:16:31 +0200392 function f_send_gtpu(inout PdpContext ctx, in octetstring data) runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +0200393 if (use_gtpu_txseq) {
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200394 GTPU.send(ts_GTP1U_GPDU(g_peer_u, g_d_seq_nr, ctx.teid_remote, data));
Pau Espin Pedrol82a7f702022-05-19 17:41:29 +0200395 g_d_seq_nr := (g_d_seq_nr + 1) mod 65536;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200396 } else {
397 GTPU.send(ts_GTP1U_GPDU(g_peer_u, omit, ctx.teid_remote, data));
398 }
Harald Welte811651e2017-08-05 15:25:06 +0200399 }
400
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100401 function f_handle_create_req(inout PdpContext ctx, in Gtp1cUnitdata ud, in template OCT1 exp_cause := '80'O) runs on GT_CT {
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200402 var CreatePDPContextResponse cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100403
404 if (not match(cpr.cause.causevalue, exp_cause)) {
405 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
406 "CreatePDPContextResp: cause expectancies didn't match");
407 }
408
409 if (cpr.cause.causevalue == '80'O) { /* Accepted */
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200410 /* Check if EUA type corresponds to requested type */
411 if (match(ctx.eua, t_EuaIPv4(?)) and
412 not match(cpr.endUserAddress, tr_EuaIPv4(?))){
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100413 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
414 "EUAv4 expectancies didn't match");
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200415 }
416 if (match(ctx.eua, t_EuaIPv6(?)) and
417 not match(cpr.endUserAddress, tr_EuaIPv6(?))) {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100418 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
419 "EUAv6 expectancies didn't match");
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200420 }
421 if (match(ctx.eua, t_EuaIPv4v6(?, ?)) and
422 not match(cpr.endUserAddress, tr_EuaIPv4v6(?, ?))) {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100423 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
424 "EUAv4v6 expectancies didn't match");
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200425 }
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100426 } else if (cpr.cause.causevalue == '81'O) { /* Cause: New PDP type due to network preference */
427 /* ETSI TS 129 060 7.3.2 Create PDP Context Response. OS#5449 */
428 /* This should only happen if EUA requested type is v4v6: */
429 if (not ischosen(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6)) {
430 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
431 "Cause not expected when requesting a non v4v6 EUA");
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200432 }
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100433 if (not match(cpr.endUserAddress, (tr_EuaIPv4(?), tr_EuaIPv6(?)))) {
434 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
435 "Cause not expected when requesting+receiving EUAv4v6");
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200436 }
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200437 } else {
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100438 if (ispresent(cpr.endUserAddress)) {
439 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
440 "EUA received on createPDPContextResponse cause=" & oct2str(cpr.cause.causevalue));
441 }
442 setverdict(pass);
443 return;
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200444 }
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100445
446 /* Check if PCO response corresponds to request */
447 if (ispresent(ctx.pco_req)) {
448 if (match(ctx.pco_req, ts_PCO_IPv4_DNS_CONT) and
449 not match(cpr.protConfigOptions, tr_PCO_IPv4_DNS_CONT_resp(?))) {
450 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
451 "IPv4 DNS Container requested, but missing");
452 }
453 if (match(ctx.pco_req, ts_PCO_IPv6_DNS) and
454 not match(cpr.protConfigOptions, tr_PCO_IPv6_DNS_resp(?))) {
455 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
456 "IPv6 DNS Container requested, but missing");
457 }
458 }
459 ctx.teid_remote := cpr.teidDataI.teidDataI;
460 ctx.teic_remote := cpr.teidControlPlane.teidControlPlane;
461 ctx.eua := cpr.endUserAddress;
462 ctx.pco_neg := cpr.protConfigOptions;
463 setverdict(pass);
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200464 }
465
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100466 function f_handle_update_req(inout PdpContext ctx, in Gtp1cUnitdata ud, in OCT1 exp_cause := '80'O) runs on GT_CT {
467 var UpdatePDPContextResponseGGSN upr := ud.gtpc.gtpc_pdu.updatePDPContextResponse.updatePDPContextResponseGGSN;
468 if (exp_cause == '80'O and exp_cause == upr.cause.causevalue) {
469 ctx.teid_remote := upr.teidDataI.teidDataI;
470 ctx.teic_remote := upr.teidControlPlane.teidControlPlane;
471 if (ispresent(upr.protConfigOptions)) {
472 ctx.pco_neg := upr.protConfigOptions;
473 }
474 setverdict(pass);
475 } else if (exp_cause != '80'O and exp_cause == upr.cause.causevalue) {
476 setverdict(pass);
477 } else {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100478 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
479 "UpdatePDPContextResp: cause expectancies didn't match");
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100480 }
481 }
482
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100483 private altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on GT_CT {
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100484 var PDU_DIAMETER rx_dia;
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100485 [] Gx_UNIT.receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia {
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100486 var template (omit) AVP avp;
487 var octetstring sess_id;
488 var AVP_Unsigned32 req_num;
489
490 avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
491 sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
492
493 avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_DCC_NONE_CC_Request_Number);
494 req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
495
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100496 Gx_UNIT.send(ts_DIA_Gx_CCA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100497 req_type, req_num));
498 }
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100499 [] Gx_UNIT.receive(PDU_DIAMETER:?) -> value rx_dia {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100500 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
501 log2str("Received unexpected DIAMETER ", rx_dia));
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100502 }
503 }
504
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200505 private function f_tr_DIA_Gy_CCR(template (omit) PdpContext ctx, DCC_NONE_CC_Request_Type req_type)
506 runs on GT_CT return template (present) PDU_DIAMETER
507 {
508 var template (present) PDU_DIAMETER tpl;
509 var charstring smf_origin_host := "smf.localdomain";
510 var template (present) octetstring imsi := ?;
511 var template (present) octetstring msisdn := ?;
512 var template (present) octetstring imeisv := ?;
513 var template (present) octetstring rat_type := ?;
514 var template (present) OCT4 charging_char := ?;
515 var template (present) OCT1 nsapi := ?;
516 if (not istemplatekind(ctx, "omit")) {
517 var PdpContext ctx_val := valueof(ctx);
518 imsi := char2oct(f_dec_TBCD(imsi_hex2oct(ctx_val.imsi)));
519 msisdn := char2oct(f_dec_TBCD(substr(ctx_val.msisdn, 1, lengthof(ctx_val.msisdn) -1)));
520 imeisv := char2oct(f_dec_TBCD(ctx_val.imeisv));
521 rat_type := ctx_val.ratType;
522 charging_char := char2oct(oct2str(ctx_val.charging_char));
523 nsapi := char2oct(hex2str(bit2hex(ctx_val.nsapi)));
524 }
525 select (req_type) {
526 case (INITIAL_REQUEST) {
527 tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
528 avps := superset(
529 tr_AVP_SessionId,
530 tr_AVP_OriginHost(smf_origin_host),
531 tr_AVP_OriginRealm(g_gy_pars.origin_realm),
532 tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
533 tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
534 tr_AVP_ServiceContextId,
535 tr_AVP_CcReqType(req_type),
536 tr_AVP_CcReqNum(?),
537 tr_AVP_EventTimestamp(?),
538 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
539 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
540 tr_AVP_RequestedAction(DIRECT_DEBITING),
541 tr_AVP_3GPP_AoCRequestType,
542 tr_AVP_MultipleServicesIndicator,
543 tr_AVP_Multiple_Services_Credit_Control(content := superset(
544 tr_AVP_Requested_Service_Unit,
Pau Espin Pedrol6477d732022-06-03 12:04:40 +0200545 tr_AVP_PCC_3GPP_QoS_Information,
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200546 tr_AVP_GI_3GPP_RatType(rat_type)
547 )),
548 tr_AVP_3GPP_ServiceInformation(content := superset(
549 tr_AVP_3GPP_PSInformation(content := superset(
550 tr_AVP_3GPP_ChargingId,
551 tr_AVP_3GPP_PDPType((IPv4,IPv6,IPv4v6)),
552 tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
553 tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
554 tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
555 tr_AVP_3GPP_CalledStationId,
556 tr_AVP_3GPP_SelectionMode,
557 tr_AVP_3GPP_ChargingCharacteristics(charging_char),
558 tr_AVP_3GPP_SGSNMCCMNC,
559 tr_AVP_3GPP_NSAPI(nsapi),
560 tr_AVP_3GPP_MS_TimeZone,
561 tr_AVP_3GPP_ULI,
562 tr_AVP_UserEquipmentInfo({
563 tr_AVP_UserEquipmentInfoType(IMEISV),
564 tr_AVP_UserEquipmentInfoValue(imeisv)
565 })
566 ))
567 ))
568 ));
569 }
570 case (UPDATE_REQUEST) {
571 tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
572 avps := superset(
573 tr_AVP_SessionId,
574 tr_AVP_OriginHost(smf_origin_host),
575 tr_AVP_OriginRealm(g_gy_pars.origin_realm),
576 tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
577 tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
578 tr_AVP_ServiceContextId,
579 tr_AVP_CcReqType(req_type),
580 tr_AVP_CcReqNum(?),
581 tr_AVP_DestinationHost(?),
582 tr_AVP_EventTimestamp(?),
583 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
584 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
585 tr_AVP_RequestedAction(DIRECT_DEBITING),
586 tr_AVP_3GPP_AoCRequestType,
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200587 tr_AVP_Multiple_Services_Credit_Control(content := superset(
588 tr_AVP_Requested_Service_Unit,
589 tr_AVP_Used_Service_Unit,
Pau Espin Pedrolcba0f6d2022-05-24 13:49:46 +0200590 /* tr_AVP_3GPP_Reporting_Reason, can be sometimes inside UsedServiceUnit */
Pau Espin Pedrol6477d732022-06-03 12:04:40 +0200591 tr_AVP_PCC_3GPP_QoS_Information,
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200592 tr_AVP_GI_3GPP_RatType(rat_type)
593 )),
594 tr_AVP_3GPP_ServiceInformation(content := superset(
595 tr_AVP_3GPP_PSInformation(content := superset(
596 tr_AVP_3GPP_ChargingId,
597 /* tr_AVP_3GPP_PDPType, Only in INIT */
598 tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
599 tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
600 tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
601 tr_AVP_3GPP_CalledStationId,
602 tr_AVP_3GPP_SelectionMode,
603 tr_AVP_3GPP_ChargingCharacteristics(charging_char),
604 tr_AVP_3GPP_SGSNMCCMNC,
605 tr_AVP_3GPP_NSAPI(nsapi),
606 tr_AVP_3GPP_MS_TimeZone,
607 tr_AVP_3GPP_ULI,
608 tr_AVP_UserEquipmentInfo({
609 tr_AVP_UserEquipmentInfoType(IMEISV),
610 tr_AVP_UserEquipmentInfoValue(imeisv)
611 })
612 ))
613 ))
614 ));
615 }
616 case (TERMINATION_REQUEST) {
617 tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
618 avps := superset(
619 tr_AVP_SessionId,
620 tr_AVP_OriginHost(smf_origin_host),
621 tr_AVP_OriginRealm(g_gy_pars.origin_realm),
622 tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
623 tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
624 tr_AVP_ServiceContextId,
625 tr_AVP_CcReqType(req_type),
626 tr_AVP_CcReqNum(?),
627 tr_AVP_DestinationHost(?),
628 tr_AVP_EventTimestamp(?),
629 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
630 tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
631 tr_AVP_TerminationCause(?),
632 tr_AVP_RequestedAction(DIRECT_DEBITING),
633 tr_AVP_3GPP_AoCRequestType,
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200634 tr_AVP_Multiple_Services_Credit_Control(content := superset(
635 /* tr_AVP_Requested_Service_Unit, Only in INIT and UPDATE */
636 tr_AVP_Used_Service_Unit,
Pau Espin Pedrolcba0f6d2022-05-24 13:49:46 +0200637 tr_AVP_3GPP_Reporting_Reason(FINAL),
Pau Espin Pedrol6477d732022-06-03 12:04:40 +0200638 tr_AVP_PCC_3GPP_QoS_Information,
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200639 tr_AVP_GI_3GPP_RatType(rat_type)
640 )),
641 tr_AVP_3GPP_ServiceInformation(content := superset(
642 tr_AVP_3GPP_PSInformation(content := superset(
643 tr_AVP_3GPP_ChargingId,
644 /* tr_AVP_3GPP_PDPType, Only in INIT */
645 tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
646 tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
647 tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
648 tr_AVP_3GPP_CalledStationId,
649 tr_AVP_3GPP_SelectionMode,
650 tr_AVP_3GPP_ChargingCharacteristics(charging_char),
651 tr_AVP_3GPP_SGSNMCCMNC,
652 tr_AVP_3GPP_NSAPI(nsapi),
653 tr_AVP_3GPP_MS_TimeZone,
654 tr_AVP_3GPP_ULI,
655 tr_AVP_UserEquipmentInfo({
656 tr_AVP_UserEquipmentInfoType(IMEISV),
657 tr_AVP_UserEquipmentInfoValue(imeisv)
658 })
659 ))
660 ))
661 ));
662 }
663 }
664 return tpl;
665 }
666
667 private altstep as_DIA_Gy_CCR(template (omit) PdpContext ctx, DCC_NONE_CC_Request_Type req_type) runs on GT_CT {
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200668 [] Gy_UNIT.receive(f_tr_DIA_Gy_CCR(ctx, req_type := req_type)) -> value g_rx_gy {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100669 var template (value) PDU_DIAMETER tx_dia;
670 var template (omit) AVP avp;
671 var octetstring sess_id;
672 var AVP_Unsigned32 req_num;
673
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200674 avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_BASE_NONE_Session_Id);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100675 sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
676
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200677 avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_DCC_NONE_CC_Request_Number);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100678 req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
679 if (g_gy_validity_time > 0) {
Pau Espin Pedrol52562c92022-05-23 15:45:46 +0200680 if (g_gy_volume_threshold > 0) {
681 tx_dia := ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id,
682 req_type, req_num, g_gy_validity_time, g_gy_volume_threshold);
683 } else {
684 tx_dia := ts_DIA_Gy_CCA_ValidityTime(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id,
685 req_type, req_num, g_gy_validity_time);
686 }
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100687 } else {
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200688 tx_dia := ts_DIA_Gy_CCA(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id,
Pau Espin Pedrol06fba9c2024-03-18 20:12:12 +0100689 DIAMETER_SUCCESS, req_type, req_num);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100690 }
691 Gy_UNIT.send(tx_dia);
692 }
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200693 [] Gy_UNIT.receive(PDU_DIAMETER:?) -> value g_rx_gy {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100694 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +0200695 log2str("Received unexpected DIAMETER Gy", g_rx_gy));
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100696 }
697 }
698
Harald Welte811651e2017-08-05 15:25:06 +0200699 /* send a PDP context activation */
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100700 function f_pdp_ctx_act(inout PdpContext ctx, template OCT1 exp_cause := '80'O) runs on GT_CT return CreatePDPContextResponse {
Harald Welte94ade362017-08-04 00:36:55 +0200701 var Gtp1cUnitdata ud;
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100702 var CreatePDPContextResponse cpr;
Harald Welte94ade362017-08-04 00:36:55 +0200703 var default d;
704
705 log("sending CreatePDP");
Harald Welte41575e92017-08-13 13:49:57 +0200706 f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx.imsi, g_restart_ctr,
Harald Welte811651e2017-08-05 15:25:06 +0200707 ctx.teid, ctx.teic, ctx.nsapi, ctx.eua, ctx.apn,
Pau Espin Pedrol0e127872022-05-12 17:58:50 +0200708 g_sgsn_ip_c, g_sgsn_ip_u, ctx.msisdn, ctx.pco_req, ctx.ratType,
Pau Espin Pedrol535ca262022-05-16 14:07:17 +0200709 ctx.uli, ctx.charging_char, ctx.imeisv, ctx.ms_tz));
Harald Welte94ade362017-08-04 00:36:55 +0200710 T_default.start;
Harald Welte94ade362017-08-04 00:36:55 +0200711 d := activate(pingpong());
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100712 if (Gx_PROC.checkstate("Connected")) {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100713 as_DIA_Gx_CCR(INITIAL_REQUEST);
714 }
715 if (Gy_PROC.checkstate("Connected")) {
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200716 as_DIA_Gy_CCR(ctx, INITIAL_REQUEST);
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100717 }
Harald Welte94ade362017-08-04 00:36:55 +0200718 alt {
Harald Welte811651e2017-08-05 15:25:06 +0200719 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ctx.teic)) -> value ud {
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +0200720 f_handle_create_req(ctx, ud, exp_cause);
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100721 cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
Harald Welte94ade362017-08-04 00:36:55 +0200722 }
723 }
724 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200725 T_default.stop;
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +0100726 return cpr;
Harald Welte94ade362017-08-04 00:36:55 +0200727 }
728
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200729 function f_pdp_ctx_exp_del_req(PdpContext ctx, template (omit) OCT1 expect_cause := omit, boolean expect_teardown := false) runs on GT_CT {
730 var Gtp1cUnitdata ud;
731 var default d;
732
733 T_default.start;
734 d := activate(pingpong());
735 alt {
736 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextRequest, ctx.teic)) -> value ud {
737 if (istemplatekind(expect_cause, "omit") and not ispresent(ud.gtpc.gtpc_pdu.deletePDPContextRequest.cause.causevalue)) {
738 setverdict(pass);
739 } else if (not istemplatekind(expect_cause, "omit") and
740 ispresent(ud.gtpc.gtpc_pdu.deletePDPContextRequest.cause.causevalue) and
741 ud.gtpc.gtpc_pdu.deletePDPContextRequest.cause.causevalue == valueof(expect_cause)) {
742 setverdict(pass);
743 } else {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100744 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
745 "DeletePDPContextReq: cause expectancies didn't match");
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200746 }
747
748 if (expect_teardown == ispresent(ud.gtpc.gtpc_pdu.deletePDPContextRequest.tearDownIndicator)) {
749 setverdict(pass);
750 } else {
751 setverdict(fail);
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100752 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
753 "DeletePDPContextReq: tearDownIndicator expectancies didn't match");
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +0200754 }
755 }
756 }
757 deactivate(d);
758 T_default.stop;
759 }
760
Pau Espin Pedrol10ec96e2022-02-09 17:03:15 +0100761 function f_pdp_ctx_del(PdpContext ctx, template BIT1 teardown_ind, OCT1 expect_causevalue := '80'O, boolean expect_diameter := true) runs on GT_CT {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200762 var Gtp1cUnitdata ud;
763 var default d;
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +0200764 var OCT4 expect_teid;
765
766 /* 3GPP TS 29.060 sec 7.3.6 specifies TEID used in response
767 message with cause value "Non existent" shall be zero. */
768 if (expect_causevalue == 'C0'O) {
769 expect_teid := '00000000'O;
770 } else {
771 expect_teid := ctx.teic;
772 }
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200773
Harald Welte41575e92017-08-13 13:49:57 +0200774 f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, ctx.teic_remote, ctx.nsapi, teardown_ind));
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200775 T_default.start;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200776 d := activate(pingpong());
Pau Espin Pedrol45d57022022-03-08 13:49:02 +0100777 if (Gx_PROC.checkstate("Connected") and expect_diameter) {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +0100778 as_DIA_Gx_CCR(TERMINATION_REQUEST);
779 }
780 if (Gy_PROC.checkstate("Connected") and expect_diameter) {
Pau Espin Pedrola2af5782022-05-18 16:34:29 +0200781 as_DIA_Gy_CCR(ctx, TERMINATION_REQUEST);
Pau Espin Pedrol0bcfd9d2022-02-02 11:01:35 +0100782 }
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200783 alt {
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +0200784 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, expect_teid)) -> value ud {
785 if (ud.gtpc.gtpc_pdu.deletePDPContextResponse.cause.causevalue == expect_causevalue) {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200786 setverdict(pass);
787 } else {
Pau Espin Pedrol8ad031a2022-02-16 17:33:43 +0100788 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
789 "DeletePDPContextResp: cause expectancies didn't match");
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200790 }
791 }
792 }
793 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200794 T_default.stop;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200795 }
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100796
797 /* send a Update PdP Context Request, expect Response */
798 function f_pdp_ctx_update(inout PdpContext ctx, OCT1 exp_cause := '80'O, template (omit) OCT4 new_teid := omit, template (omit) OCT4 new_teic := omit) runs on GT_CT {
799 var Gtp1cUnitdata ud;
800 var default d;
801
802 if (not istemplatekind(new_teid, "omit")) {
803 ctx.teid := valueof(new_teid);
804 }
805 if (not istemplatekind(new_teic, "omit")) {
806 ctx.teic := valueof(new_teic);
807 }
808
809 log("sending UpdatePDP");
810 f_send_gtpc(ts_GTPC_UpdatePDP(g_peer_c, ctx.teic_remote, g_c_seq_nr, ctx.imsi, g_restart_ctr,
811 ctx.teid, ctx.teic, ctx.nsapi, g_sgsn_ip_c, g_sgsn_ip_u,
812 ctx.pco_req, ctx.ratType, ctx.uli));
813 T_default.start;
814 d := activate(pingpong());
815 alt {
816 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, updatePDPContextResponse, ctx.teic)) -> value ud {
817 f_handle_update_req(ctx, ud, exp_cause);
818 }
819 }
820 deactivate(d);
821 T_default.stop;
822 }
823
Pau Espin Pedrol57604212022-02-14 16:54:18 +0100824 /* Get link-id from PDP Context EUA */
825 function f_ctx_get_ipv6_interface_id(in PdpContext ctx) return OCT16 {
826 var OCT16 interface_id;
827 if (ischosen(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6)) {
828 interface_id := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address;
829 } else if (ischosen(ctx.eua.endUserAddress.endUserAddressIPv6)) {
830 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
831 } else {
832 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected request to submit icmpv6 rs in IPv4 PDP context");
833 }
834 return interface_id;
835 }
836
Harald Welte231b9412017-08-09 17:16:31 +0200837 /* create ICMPv6 router solicitation deriving link-id from PDP Context EUA */
838 function f_icmpv6_rs_for_pdp(in PdpContext ctx) return octetstring {
Pau Espin Pedrol57604212022-02-14 16:54:18 +0100839 var OCT16 interface_id := f_ctx_get_ipv6_interface_id(ctx);
Harald Welte231b9412017-08-09 17:16:31 +0200840 return f_gen_icmpv6_router_solicitation(interface_id);
841 }
842
Harald Welte231b9412017-08-09 17:16:31 +0200843 /* generate and encode ICMPv6 neighbor solicitation for PDP Context */
844 function f_gen_icmpv6_neigh_solicit_for_pdp(in PdpContext ctx) return octetstring {
Pau Espin Pedrol57604212022-02-14 16:54:18 +0100845 var OCT16 interface_id := f_ctx_get_ipv6_interface_id(ctx);
Harald Welte231b9412017-08-09 17:16:31 +0200846 var OCT16 link_local := f_ipv6_link_local(interface_id);
847 var OCT16 daddr := f_ipv6_sol_node_mcast(link_local);
848
849 return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local);
850 }
851
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100852 /* Wait for ICMPv4 from GTP */
853 function f_wait_icmp4(PdpContext ctx, template PDU_ICMP expected) runs on GT_CT {
Harald Welte231b9412017-08-09 17:16:31 +0200854 var Gtp1uUnitdata ud;
855 T_default.start;
856 alt {
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100857 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ctx.teid)) -> value ud {
Harald Welte3e0b0392018-04-26 09:46:21 +0200858 if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200859 setverdict(fail);
860 stop;
861 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100862 var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
863 var IPv4_packet ip4 := f_IPv4_dec(gpdu);
864 if (ip4.header.ver != 4) {
865 repeat;
866 }
867 var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload);
868 if (not match(icmp4, expected)) {
869 repeat;
870 }
871 }
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100872 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
Oliver Smith9daae3e2024-02-28 11:54:22 +0100873 setverdict(fail, "Received wrong local TEID");
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +0100874 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100875 [] GTPU.receive { setverdict(fail); }
876 [] T_default.timeout { setverdict(fail); }
877 }
878 T_default.stop;
879 }
880
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100881 /* Wait for ICMPv4 echo request from GTP */
882 function f_wait_icmp4_echo_request(PdpContext ctx) runs on GT_CT {
883 f_wait_icmp4(ctx, tr_ICMPv4_ERQ);
884 }
885
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100886 /* Wait for ICMPv4 echo reply (or unreachable) from GTP */
887 function f_wait_icmp4_echo_reply(PdpContext ctx) runs on GT_CT {
888 f_wait_icmp4(ctx, (tr_ICMPv4_ERP, tr_ICMPv4_DU));
889 }
890
891 /* Wait for ICMPv6 from GTP */
892 function f_wait_icmp6(PdpContext ctx, template PDU_ICMPv6 expected) runs on GT_CT {
893 var Gtp1uUnitdata ud;
894 T_default.start;
895 alt {
Harald Welte231b9412017-08-09 17:16:31 +0200896 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
Harald Welte3e0b0392018-04-26 09:46:21 +0200897 if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
Pau Espin Pedrol9c1c2ae2023-12-05 14:24:49 +0100898 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
899 log2str("Received GTPU with wrong txseq while waiting for ICMPv6: ", expected));
Stefan Sperlingc479e4f2018-04-03 19:34:16 +0200900 }
Harald Welte231b9412017-08-09 17:16:31 +0200901 var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
902 var IPv6_packet ip6 := f_IPv6_dec(gpdu);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100903 if (ip6.header.ver != 6 or ip6.header.nexthead != 58) {
Harald Welte231b9412017-08-09 17:16:31 +0200904 repeat;
905 }
906 var PDU_ICMPv6 icmp6 := f_dec_PDU_ICMPv6(ip6.payload);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100907 if (not match(icmp6, expected)) {
Harald Welte231b9412017-08-09 17:16:31 +0200908 repeat;
909 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100910 /* We are waiting for RA, update ctx */
911 if (match(icmp6, tr_ICMPv6_RA(?, 64))) {
912 ctx.ip6_prefix := icmp6.routerAdvertisement.options[0].prefixInformation.prefix;
913 log("RA with /64 prefix ", ctx.ip6_prefix);
914 }
Harald Welte231b9412017-08-09 17:16:31 +0200915 }
916 [] GTPU.receive(tr_GTPU_GPDU(?, ?)) { repeat; }
Pau Espin Pedrol9c1c2ae2023-12-05 14:24:49 +0100917 [] GTPU.receive {
918 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
919 log2str("Received unexpected GTPU while waiting for ICMPv6: ", expected));
920 }
921 [] T_default.timeout {
922 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
923 log2str("Timeout waiting for ICMPv6: ", expected));
924 }
Harald Welte231b9412017-08-09 17:16:31 +0200925 }
926 T_default.stop;
927 }
928
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100929 /* wait for GGSN to send us an ICMPv6 router advertisement */
930 function f_wait_rtr_adv(PdpContext ctx) runs on GT_CT {
931 f_wait_icmp6(ctx, tr_ICMPv6_RA(?, 64));
932 }
933
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +0100934 /* Wait for ICMPv6 echo request from GTP */
935 function f_wait_icmp6_echo_request(PdpContext ctx) runs on GT_CT {
936 f_wait_icmp6(ctx, tr_ICMPv6_ERQ);
937 }
938
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100939 /* Wait for ICMPv6 echo reply (or unreachable) from GTP */
940 function f_wait_icmp6_echo_reply(PdpContext ctx) runs on GT_CT {
941 f_wait_icmp6(ctx, (tr_ICMPv6_ERP,tr_ICMPv6_DU));
942 }
943
Oliver Smithee6a0882019-03-08 11:05:46 +0100944 /* create ICMPv6 router solicitation deriving link-id from PDP Context EUA */
945 function f_icmpv6_rs_for_pdp46(in PdpContext ctx) return octetstring {
946 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address;
947 return f_gen_icmpv6_router_solicitation(interface_id);
948 }
949
950 /* generate and encode ICMPv6 neighbor solicitation for PDP Context */
951 function f_gen_icmpv6_neigh_solicit_for_pdp46(in PdpContext ctx) return octetstring {
952 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address;
953 var OCT16 link_local := f_ipv6_link_local(interface_id);
954 var OCT16 daddr := f_ipv6_sol_node_mcast(link_local);
955
956 return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local);
957 }
958
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +0100959 /* Assert we don't receive a ICMPv4/6 echo reply (or unreachable) from GTP */
960 function f_wait_gtpu_fail(PdpContext ctx) runs on GT_CT {
961 T_default.start;
962 alt {
963 [] GTPU.receive { setverdict(fail); }
964 [] T_default.timeout { }
965 }
966 T_default.stop;
967 }
968
Harald Welte79737b42019-04-10 10:39:30 +0200969 /* list of protocols where we don't accept duplicates */
970 const OCT2List protocol_ids_nodupes := { 'C021'O, 'C023'O, 'C223'O, '8021'O };
971 private function f_PCO_permits_duplicates(OCT2 id) return boolean {
972 var integer i;
973 for (i := 0; i < lengthof(protocol_ids_nodupes); i := i+1) {
974 if (id == protocol_ids_nodupes[i]) {
975 return false;
976 }
977 }
978 return true;
979 }
980
981 /* ensure that every given protocol Identifier exist only exactly once in the PCO */
982 function f_PCO_ensure_no_duplicates(ProtConfigOptions pco) {
983 var OCT2List protocol_ids := {};
984 var integer i, j;
985 for (i := 0; i < lengthof(pco.protocols); i := i+1) {
986 var OCT2 id := pco.protocols[i].protocolID;
987 for (j := 0; j < lengthof(protocol_ids); j := j+1) {
988 if (not f_PCO_permits_duplicates(id) and id == protocol_ids[j]) {
989 setverdict(fail, "Duplicate ProtocolID ", id, " already present in ", pco.protocols);
990 }
991 }
992 protocol_ids := protocol_ids & { id };
993 }
994 }
995
Harald Welte0ef285b2017-08-13 20:06:01 +0200996 /* Test IPv6 context activation for dynamic IPv6 EUA without request of IPv6 DNS */
Harald Welteed7a1772017-08-09 20:26:20 +0200997 testcase TC_pdp6_act_deact() runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200998 f_init();
Harald Welte231b9412017-08-09 17:16:31 +0200999
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001000 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welte811651e2017-08-05 15:25:06 +02001001 f_pdp_ctx_act(ctx);
Harald Welteed7a1772017-08-09 20:26:20 +02001002 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001003 f_shutdown_helper();
Harald Welteed7a1772017-08-09 20:26:20 +02001004 }
1005
Harald Welte0ef285b2017-08-13 20:06:01 +02001006 /* Test IPv6 context activation for dynamic IPv6 EUA wirh request of IPv6 DNS in PCO */
Harald Welteed7a1772017-08-09 20:26:20 +02001007 testcase TC_pdp6_act_deact_pcodns() runs on GT_CT {
1008 f_init();
1009
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001010 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +02001011 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1012 f_pdp_ctx_act(ctx);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +01001013
Harald Welte79737b42019-04-10 10:39:30 +02001014 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +01001015 /* verify PCO contains both primary and secondary DNS */
1016 var OCT4 ggsn_ip6_dns1 := f_inet6_addr(m_ggsn_ip6_dns1);
1017 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 1), ggsn_ip6_dns1)) {
1018 setverdict(fail, "Primary DNS IPv6 PCO option not found");
1019 }
1020
1021 var OCT4 ggsn_ip6_dns2 := f_inet6_addr(m_ggsn_ip6_dns2);
1022 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 2), ggsn_ip6_dns2)) {
1023 setverdict(fail, "Secondary DNS IPv6 PCO option not found");
1024 }
1025
Harald Welteed7a1772017-08-09 20:26:20 +02001026 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001027 f_shutdown_helper();
Harald Welteed7a1772017-08-09 20:26:20 +02001028 }
1029
Harald Welte0ef285b2017-08-13 20:06:01 +02001030 /* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement */
Harald Welteed7a1772017-08-09 20:26:20 +02001031 testcase TC_pdp6_act_deact_icmp6() runs on GT_CT {
1032 f_init();
1033
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001034 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +02001035 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1036 f_pdp_ctx_act(ctx);
Harald Welte231b9412017-08-09 17:16:31 +02001037
Harald Welte79737b42019-04-10 10:39:30 +02001038 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Harald Welte231b9412017-08-09 17:16:31 +02001039
1040 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1041 f_wait_rtr_adv(ctx);
1042 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1043
Harald Welte811651e2017-08-05 15:25:06 +02001044 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001045 f_shutdown_helper();
Harald Welte94ade362017-08-04 00:36:55 +02001046 }
1047
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001048 /* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement.
1049 Test we can send ICMPv6 ping over GTPU to DNS server. */
1050 testcase TC_pdp6_act_deact_gtpu_access() runs on GT_CT {
1051 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001052 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001053 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1054 f_pdp_ctx_act(ctx);
1055
1056 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1057 f_wait_rtr_adv(ctx);
1058 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1059
1060 var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
1061
1062 /* Check if we can use valid link-local src addr. */
1063 var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1064 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_ll, dns1_addr));
Pau Espin Pedrolb63d85f2022-02-07 16:11:47 +01001065 if (m_ggsn_impl == GGSN_IMPL_OSMOCOM) {
1066 f_wait_icmp6_echo_reply(ctx);
1067 } else {
1068 f_wait_gtpu_fail(ctx);
1069 }
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001070
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001071 /* Check if we can use valid global src addr, should work */
1072 var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1073 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_glob, dns1_addr));
1074 f_wait_icmp6_echo_reply(ctx);
1075
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001076 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001077 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001078 }
1079
1080 /* Check that attempting RA with another ll src addr won't work, packet dropped: */
1081 testcase TC_pdp6_act_deact_gtpu_access_wrong_ll_saddr() runs on GT_CT {
1082 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001083 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001084 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1085 f_pdp_ctx_act(ctx);
1086
1087 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1088 f_wait_rtr_adv(ctx);
1089 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1090
1091 var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1092 var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8);
1093 f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong));
1094 f_wait_gtpu_fail(ctx);
1095
1096 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001097 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001098 }
1099
1100 /* Assert that packets with wrong global src addr are dropped by GGSN */
1101 testcase TC_pdp6_act_deact_gtpu_access_wrong_global_saddr() runs on GT_CT {
1102 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001103 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001104 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1105 f_pdp_ctx_act(ctx);
1106
1107 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1108 f_wait_rtr_adv(ctx);
1109 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1110
1111 var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
1112 var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001113 var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob);
1114 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr));
1115 f_wait_gtpu_fail(ctx);
1116
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001117 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001118 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001119 }
1120
1121 /* Send an IPv4 ICMP ECHO REQUEST to APN6, should fail (packet dropped */
1122 testcase TC_pdp6_act_deact_gtpu_access_ipv4_apn6() runs on GT_CT {
1123 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001124 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001125 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1126 f_pdp_ctx_act(ctx);
1127
1128 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1129 f_wait_rtr_adv(ctx);
1130 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1131
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001132 var OCT4 saddr_v4 := f_inet_addr("192.168.10.2");
1133 var OCT4 daddr_v4 := f_inet_addr("8.8.8.8");
1134 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_v4, daddr_v4));
1135 f_wait_gtpu_fail(ctx);
1136
1137 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001138 f_shutdown_helper();
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001139 }
1140
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001141 /* Validate if different clients (pdp ctx) can reach one another through GGSN. */
1142 testcase TC_pdp6_clients_interact() runs on GT_CT {
1143 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001144 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
1145 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001146 f_pdp_ctx_act(ctxA);
1147 f_send_gtpu(ctxA, f_icmpv6_rs_for_pdp(ctxA));
1148 f_wait_rtr_adv(ctxA);
1149 f_send_gtpu(ctxA, f_gen_icmpv6_neigh_solicit_for_pdp(ctxA));
1150
1151 f_pdp_ctx_act(ctxB);
1152 f_send_gtpu(ctxB, f_icmpv6_rs_for_pdp(ctxB));
1153 f_wait_rtr_adv(ctxB);
1154 f_send_gtpu(ctxB, f_gen_icmpv6_neigh_solicit_for_pdp(ctxB));
1155
1156 var OCT16 addrA_ll := f_ipv6_link_local(ctxA.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1157 var OCT16 addrB_ll := f_ipv6_link_local(ctxB.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1158 var OCT16 addrA_glob := f_ipv6_global(ctxA.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1159 var OCT16 addrB_glob := f_ipv6_global(ctxB.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
1160
1161 /* Validate if clients can interact using ll addr. */
1162 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_ll, addrB_ll));
1163 f_wait_gtpu_fail(ctxB);
1164
1165 /* Validate if clients can interact using global addr. */
1166 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_glob, addrB_glob));
1167 f_wait_gtpu_fail(ctxB);
1168
1169 f_pdp_ctx_del(ctxA, '1'B);
Pau Espin Pedrolbb2bb062019-09-03 12:28:12 +02001170 f_pdp_ctx_del(ctxB, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001171 f_shutdown_helper();
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001172 }
1173
Harald Welte0ef285b2017-08-13 20:06:01 +02001174 /* Test PDP context activation for dynamic IPv4 EUA without DNS request */
Harald Welteed7a1772017-08-09 20:26:20 +02001175 testcase TC_pdp4_act_deact() runs on GT_CT {
1176 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001177 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +02001178 f_pdp_ctx_act(ctx);
1179 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001180 f_shutdown_helper();
Harald Welteed7a1772017-08-09 20:26:20 +02001181 }
1182
Harald Welte0ef285b2017-08-13 20:06:01 +02001183 /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP */
Harald Welteed7a1772017-08-09 20:26:20 +02001184 testcase TC_pdp4_act_deact_ipcp() runs on GT_CT {
1185 f_init();
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +01001186 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1187 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
Pau Espin Pedrolcff72f82024-01-26 16:58:48 +01001188 var uint8_t ipcp_req_id := oct2int(f_rnd_octstring(1));
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001189 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolcff72f82024-01-26 16:58:48 +01001190 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP(ipcp_req_id));
Harald Welteed7a1772017-08-09 20:26:20 +02001191 f_pdp_ctx_act(ctx);
Harald Welte79737b42019-04-10 10:39:30 +02001192 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Harald Welte71a36022017-12-04 18:55:58 +01001193 /* verify IPCP is at all contained */
1194 if (not match(ctx.pco_neg, tr_PCO_Contains('8021'O))) {
1195 setverdict(fail, "IPCP not found in PCO");
1196 }
1197 /* verify IPCP contains both primary and secondary DNS */
1198 var IpcpPacket ipcp := dec_IpcpPacket(f_PCO_extract_proto(ctx.pco_neg, '8021'O));
Pau Espin Pedrolcff72f82024-01-26 16:58:48 +01001199 if (not match(ipcp, tr_IPCP_Ack_DNS(ipcp_req_id, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
1200 if (not match(ipcp, tr_IPCP_Ack_DNS(ipcp_req_id))) {
1201 if (not match(ipcp, tr_IPCP_Ack_DNS(?))) {
1202 setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
1203 } else {
1204 setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected identifier");
1205 }
Pau Espin Pedrolf69a4382018-01-29 13:09:00 +01001206 } else {
1207 setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected values");
1208 }
Harald Welte71a36022017-12-04 18:55:58 +01001209 }
Harald Welteed7a1772017-08-09 20:26:20 +02001210 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001211 f_shutdown_helper();
Harald Welteed7a1772017-08-09 20:26:20 +02001212 }
1213
Harald Weltef8298542019-04-10 10:15:28 +02001214 /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP + PAP authentication (broken) */
1215 testcase TC_pdp4_act_deact_ipcp_pap_broken() runs on GT_CT {
1216 f_init();
1217 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1218 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001219 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Weltef8298542019-04-10 10:15:28 +02001220 ctx.pco_req := valueof(ts_PCO_PAP_IPv4_DNS);
1221 f_pdp_ctx_act(ctx);
1222 f_PCO_ensure_no_duplicates(ctx.pco_neg);
1223 /* verify IPCP is at all contained */
1224 if (not match(ctx.pco_neg, tr_PCO_Contains('8021'O))) {
1225 setverdict(fail, "IPCP not found in PCO");
1226 }
1227 /* verify IPCP contains both primary and secondary DNS */
1228 var IpcpPacket ipcp := dec_IpcpPacket(f_PCO_extract_proto(ctx.pco_neg, '8021'O));
1229 if (not match(ipcp, tr_IPCP_Ack_DNS(0, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
1230 if (not match(ipcp, tr_IPCP_Ack_DNS(0))) {
1231 setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
1232 } else {
1233 setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected values");
1234 }
1235 }
1236 /* verify that PAP is contained */
1237 if (not match(ctx.pco_neg, tr_PCO_Contains('C023'O))) {
1238 setverdict(fail, "PAP not found in PCO");
1239 }
1240 var PapPacket pap := dec_PapPacket(f_PCO_extract_proto(ctx.pco_neg, 'C023'O));
1241 if (not match(pap, tr_PAP_AuthAck)) {
1242 setverdict(fail, "PAP isn't an AuthenticateAck: ", pap);
1243 }
1244 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001245 f_shutdown_helper();
Harald Weltef8298542019-04-10 10:15:28 +02001246 }
1247
Harald Welte0ef285b2017-08-13 20:06:01 +02001248 /* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in PCO */
Harald Welteed7a1772017-08-09 20:26:20 +02001249 testcase TC_pdp4_act_deact_pcodns() runs on GT_CT {
1250 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001251 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Weltedca80052017-08-13 20:01:38 +02001252 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
Harald Welteed7a1772017-08-09 20:26:20 +02001253 f_pdp_ctx_act(ctx);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +01001254
Harald Welte79737b42019-04-10 10:39:30 +02001255 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Pau Espin Pedrol363ba482018-01-29 18:42:00 +01001256 /* verify PCO contains both primary and secondary DNS */
1257 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1258 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 1), ggsn_ip4_dns1)) {
1259 setverdict(fail, "Primary DNS IPv4 PCO option not found");
1260 }
1261
1262 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
1263 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 2), ggsn_ip4_dns2)) {
1264 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
1265 }
1266
Harald Welteed7a1772017-08-09 20:26:20 +02001267 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001268 f_shutdown_helper();
Harald Welteed7a1772017-08-09 20:26:20 +02001269 }
1270
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001271 /* Test PDP context activation for dynamic IPv4 EUA.
1272 Test we can send ICMPv6 ping over GTPU to DNS server. */
1273 testcase TC_pdp4_act_deact_gtpu_access() runs on GT_CT {
1274 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001275 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001276 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1277 f_pdp_ctx_act(ctx);
1278
Harald Welte79737b42019-04-10 10:39:30 +02001279 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001280 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
1281
1282 /* Check if we can use valid global src addr, should work */
1283 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
1284 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
1285 f_wait_icmp4_echo_reply(ctx);
1286
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001287 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001288 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001289 }
1290
1291 /* Assert that packets with wrong global src addr are dropped by GGSN */
1292 testcase TC_pdp4_act_deact_gtpu_access_wrong_saddr() runs on GT_CT {
1293 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001294 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001295 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1296 f_pdp_ctx_act(ctx);
1297
1298 f_PCO_ensure_no_duplicates(ctx.pco_neg);
1299 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
1300 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001301 var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O);
1302 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr));
1303 f_wait_gtpu_fail(ctx);
1304
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001305 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001306 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001307 }
1308
1309 /* Send an IPv6 RA to APN4, should fail (packet dropped) */
1310 testcase TC_pdp4_act_deact_gtpu_access_ipv6_apn4() runs on GT_CT {
1311 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001312 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001313 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1314 f_pdp_ctx_act(ctx);
1315
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001316 /* Send an IPv6 RA to APN4, should fail (packet dropped) */
1317 var OCT16 saddr_v6 := f_inet6_addr("fde4:8dba:82e1:2000:1:2:3:4");
1318 f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_v6));
1319 f_wait_gtpu_fail(ctx);
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001320
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001321 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001322 f_shutdown_helper();
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01001323 }
1324
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001325 /* Helper function for tests below. */
1326 function f_pdp4_clients_interact() runs on GT_CT {
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001327 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001328 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
1329 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001330 f_pdp_ctx_act(ctxA);
1331 f_pdp_ctx_act(ctxB);
1332 var OCT4 addrA := ctxA.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
1333 var OCT4 addrB := ctxB.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
1334 f_send_gtpu(ctxA, f_gen_icmpv4_echo(addrA, addrB));
1335 f_wait_icmp4_echo_request(ctxB);
1336
1337 f_pdp_ctx_del(ctxA, '1'B);
Pau Espin Pedrolbb2bb062019-09-03 12:28:12 +02001338 f_pdp_ctx_del(ctxB, '1'B);
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01001339 }
1340
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001341 /* Validate if different clients (pdp ctx) can reach one another through GGSN. */
1342 testcase TC_pdp4_clients_interact_with_txseq() runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +02001343 use_gtpu_txseq := true;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001344 f_pdp4_clients_interact();
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001345 f_shutdown_helper();
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001346 }
1347
1348 /* Validate if different clients (pdp ctx) can reach one another through GGSN (without Tx sequence number). */
1349 testcase TC_pdp4_clients_interact_without_txseq() runs on GT_CT {
Harald Welte3e0b0392018-04-26 09:46:21 +02001350 use_gtpu_txseq := false;
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001351 f_pdp4_clients_interact();
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001352 f_shutdown_helper();
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02001353 }
1354
Harald Weltedca80052017-08-13 20:01:38 +02001355 testcase TC_echo_req_resp() runs on GT_CT {
1356 f_init();
1357 f_send_gtpc(ts_GTPC_PING(g_peer_c, g_c_seq_nr));
1358 T_default.start;
1359 alt {
1360 [] GTPC.receive(tr_GTPC_PONG(g_peer_c)) { setverdict(pass); };
1361 [] GTPC.receive { repeat; };
1362 [] T_default.timeout { setverdict(fail); }
1363 }
1364 T_default.stop;
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001365 f_shutdown_helper();
Harald Weltedca80052017-08-13 20:01:38 +02001366 }
1367
Pau Espin Pedrol480e67f2022-02-09 16:37:47 +01001368 testcase TC_echo_req_resp_gtpu() runs on GT_CT {
1369 f_init();
1370 GTPU.send(ts_GTPU_PING(g_peer_u, g_d_seq_nr));
1371 T_default.start;
1372 alt {
1373 [] GTPU.receive(tr_GTPU_PONG(g_peer_u)) { setverdict(pass); };
1374 [] GTPU.receive { repeat; };
1375 [] T_default.timeout { setverdict(fail); }
1376 }
1377 T_default.stop;
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001378 f_shutdown_helper();
Pau Espin Pedrol480e67f2022-02-09 16:37:47 +01001379 }
1380
Philipp Maier33e52612018-05-30 17:22:02 +02001381 /* Test if the parser can cope with PCO that only contain either a
1382 * single primary DNS or a secondary DNS. */
1383 testcase TC_pdp4_act_deact_with_single_dns() runs on GT_CT {
1384
1385 /* Note: an unpatched osmo-ggsn version will enter an endless-loop when
1386 * the test is executed.
1387 * see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
1388
1389 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001390 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Philipp Maier33e52612018-05-30 17:22:02 +02001391 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1392 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
1393 var octetstring pco_neg_dns;
1394 var octetstring pco_neg_dns_expected;
1395
1396 /* PCO with primary DNS only */
1397 ctx.pco_req := valueof(ts_PCO_IPv4_PRI_DNS_IPCP);
1398 f_pdp_ctx_act(ctx);
Harald Welte79737b42019-04-10 10:39:30 +02001399 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Philipp Maier33e52612018-05-30 17:22:02 +02001400 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
1401 pco_neg_dns_expected := '0200000A8106'O & ggsn_ip4_dns1
1402 /* Note: The prepended hex bytes encode the following information:
1403 * 0x02 = Configuration ACK
1404 * 0x00 = Identifier
1405 * 0x000a = Length
1406 * 0x81 = Type (Primary DNS Server Address)
1407 * 0x06 = Length
1408 * (4 byte IP-Address appended) */
1409 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1410 setverdict(fail, "Primary DNS IPv4 PCO option not found");
1411 }
1412 f_pdp_ctx_del(ctx, '1'B);
1413
1414 /* PCO with secondary DNS only */
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001415 ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Philipp Maier33e52612018-05-30 17:22:02 +02001416 ctx.pco_req := valueof(ts_PCO_IPv4_SEC_DNS_IPCP);
1417 f_pdp_ctx_act(ctx);
1418 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
1419 pco_neg_dns_expected := '0200000A8306'O & ggsn_ip4_dns2
1420 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1421 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
1422 }
1423 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001424 f_shutdown_helper();
Philipp Maier33e52612018-05-30 17:22:02 +02001425 }
1426
1427 /* Test if the parser can cope with PCO that contains primary and secondary DNS in a separate IPCP container.
1428 * Note: an unpatched osmo-ggsn version will enter an endless-loop when the test is run
1429 * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288. */
1430 testcase TC_pdp4_act_deact_with_separate_dns() runs on GT_CT {
1431
1432 /* Note: an unpatched osmo-ggsn version will enter an endless-loop when
1433 * the test is executed.
1434 * see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
1435
1436 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001437 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Philipp Maier33e52612018-05-30 17:22:02 +02001438 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1439 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
1440 var octetstring pco_neg_dns;
1441 var octetstring pco_neg_dns_expected;
1442
1443 ctx.pco_req := valueof(ts_PCO_IPv4_SEPARATE_DNS_IPCP);
1444 f_pdp_ctx_act(ctx);
1445
1446 /* Check if primary DNS is contained */
1447 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
1448 pco_neg_dns_expected := '0200000A8106'O & ggsn_ip4_dns1
1449 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1450 setverdict(fail, "Primary DNS IPv4 PCO option not found");
1451 }
Philipp Maier33e52612018-05-30 17:22:02 +02001452
1453 /* Check if secondary DNS is contained */
Stefan Sperling8e7a3962018-07-19 19:24:38 +02001454 /* This used to fail due to a bug in osmo-ggsn, see OS#3381 */
1455 pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 2);
Philipp Maier33e52612018-05-30 17:22:02 +02001456 pco_neg_dns_expected := '0200000A8306'O & ggsn_ip4_dns2
1457 if (not match(pco_neg_dns, pco_neg_dns_expected)) {
1458 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
1459 }
1460 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001461 f_shutdown_helper();
Philipp Maier33e52612018-05-30 17:22:02 +02001462 }
1463
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01001464 /* Validate that SUT updates remote TEIC when requested through UpdatePDPContextRequest */
1465 testcase TC_pdp4_act_update_teic() runs on GT_CT {
1466 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001467 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01001468 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1469 f_pdp_ctx_act(ctx);
1470
1471 /* UpdatePDPContestRequest changing the local TEIC */
1472 var OCT4 new_teic := ctx.teic;
1473 new_teic[3] := new_teic[3] xor4b '11'O;
1474 f_pdp_ctx_update(ctx, new_teic := new_teic);
1475
1476 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001477 f_shutdown_helper();
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01001478 }
1479
1480 /* Validate that SUT updates remote TEID when requested through UpdatePDPContextRequest */
1481 testcase TC_pdp4_act_update_teid() runs on GT_CT {
1482 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001483 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01001484 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1485 f_pdp_ctx_act(ctx);
1486
1487 f_PCO_ensure_no_duplicates(ctx.pco_neg);
1488 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
1489 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
1490
1491 /* Data is sent (back) to the local TEID established during CreatePDPContext */
1492 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
1493 f_wait_icmp4_echo_reply(ctx);
1494
1495 /* UpdatePDPContestRequest changing the local TEID */
1496 var OCT4 new_teid := ctx.teid;
1497 new_teid[3] := new_teid[3] xor4b '11'O;
1498 f_pdp_ctx_update(ctx, new_teid := new_teid);
1499
1500 /* Check if we can send data after updating the PDP context. Answer should be sent to the new TEID */
1501 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
1502 f_wait_icmp4_echo_reply(ctx);
1503
1504 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001505 f_shutdown_helper();
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01001506 }
1507
Oliver Smithee6a0882019-03-08 11:05:46 +01001508 /* Test IPv4v6 context activation for dynamic IPv4v6 EUA without DNS request */
1509 testcase TC_pdp46_act_deact() runs on GT_CT {
1510 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001511 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001512 f_pdp_ctx_act(ctx);
1513 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001514 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001515 }
1516
1517 /* Test PDP context activation for dynamic IPv4v6 EUA with IPv4 DNS in IPCP */
1518 testcase TC_pdp46_act_deact_ipcp() runs on GT_CT {
1519 f_init();
1520 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1521 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001522 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001523 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP);
1524 f_pdp_ctx_act(ctx);
Harald Welte79737b42019-04-10 10:39:30 +02001525 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Oliver Smithee6a0882019-03-08 11:05:46 +01001526 /* verify IPCP is at all contained */
1527 if (not match(ctx.pco_neg, tr_PCO_Contains('8021'O))) {
1528 setverdict(fail, "IPCP not found in PCO");
1529 }
Harald Welte79737b42019-04-10 10:39:30 +02001530 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Oliver Smithee6a0882019-03-08 11:05:46 +01001531 /* verify IPCP contains both primary and secondary IPv4 DNS */
1532 var IpcpPacket ipcp := dec_IpcpPacket(f_PCO_extract_proto(ctx.pco_neg, '8021'O));
1533 if (not match(ipcp, tr_IPCP_Ack_DNS(0, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
1534 if (not match(ipcp, tr_IPCP_Ack_DNS(0))) {
1535 setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
1536 } else {
1537 setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected values");
1538 }
1539 }
1540 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001541 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001542 }
1543
1544 /* Test PDP context activation for dynamic IPv4v6 EUA with IPv6 DNS in PCO and router solicitation/advertisement */
1545 testcase TC_pdp46_act_deact_icmp6() runs on GT_CT {
1546 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001547 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001548 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1549 f_pdp_ctx_act(ctx);
1550
1551 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp46(ctx));
1552 f_wait_rtr_adv(ctx);
1553 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp46(ctx));
1554
1555 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001556 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001557 }
1558
1559 /* Test IPv4v6 context activation for dynamic IPv4v6 EUA with request of IPv4 DNS in PCO */
1560 testcase TC_pdp46_act_deact_pcodns4() runs on GT_CT {
1561 f_init();
1562
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001563 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001564 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1565 f_pdp_ctx_act(ctx);
1566
Harald Welte79737b42019-04-10 10:39:30 +02001567 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Oliver Smithee6a0882019-03-08 11:05:46 +01001568 /* verify PCO contains both primary and secondary IPv4 DNS */
1569 var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
1570 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 1), ggsn_ip4_dns1)) {
1571 setverdict(fail, "Primary DNS IPv4 PCO option not found");
1572 }
1573
1574 var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
1575 if (not match(f_PCO_extract_proto(ctx.pco_neg, '000d'O, 2), ggsn_ip4_dns2)) {
1576 setverdict(fail, "Secondary DNS IPv4 PCO option not found");
1577 }
1578
1579 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001580 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001581 }
1582
1583 /* Test IPv4v6 context activation for dynamic IPv4v6 EUA with request of IPv6 DNS in PCO */
1584 testcase TC_pdp46_act_deact_pcodns6() runs on GT_CT {
1585 f_init();
1586
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001587 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001588 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1589 f_pdp_ctx_act(ctx);
1590
Harald Welte79737b42019-04-10 10:39:30 +02001591 f_PCO_ensure_no_duplicates(ctx.pco_neg);
Oliver Smithee6a0882019-03-08 11:05:46 +01001592 /* verify PCO contains both primary and secondary IPv6 DNS */
1593 var OCT4 ggsn_ip6_dns1 := f_inet6_addr(m_ggsn_ip6_dns1);
1594 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 1), ggsn_ip6_dns1)) {
1595 setverdict(fail, "Primary DNS IPv6 PCO option not found");
1596 }
1597
1598 var OCT4 ggsn_ip6_dns2 := f_inet6_addr(m_ggsn_ip6_dns2);
1599 if (not match(f_PCO_extract_proto(ctx.pco_neg, '0003'O, 2), ggsn_ip6_dns2)) {
1600 setverdict(fail, "Secondary DNS IPv6 PCO option not found");
1601 }
1602
1603 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001604 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001605 }
1606
1607 /* Test PDP context activation for dynamic IPv4v6 EUA.
1608 Test we can send ICMPv6 ping over GTPU to DNS server. */
1609 testcase TC_pdp46_act_deact_gtpu_access() runs on GT_CT {
1610 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001611 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001612 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1613 f_pdp_ctx_act(ctx);
1614
1615 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
1616
1617 /* Check if we can use valid global src addr, should work */
1618 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv4_address;
1619 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
1620 f_wait_icmp4_echo_reply(ctx);
1621
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001622 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001623 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001624 }
1625
1626 /* Assert that packets with wrong ipv4 src addr are dropped by GGSN on APN IPv4v6 */
1627 testcase TC_pdp46_act_deact_gtpu_access_wrong_saddr_ipv4() runs on GT_CT {
1628 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001629 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001630 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1631 f_pdp_ctx_act(ctx);
1632
1633 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
1634 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv4_address;
Oliver Smithee6a0882019-03-08 11:05:46 +01001635 var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O);
1636 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr));
1637 f_wait_gtpu_fail(ctx);
1638
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001639 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001640 f_shutdown_helper();
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001641 }
1642
Pau Espin Pedrolc6ac6952022-02-14 11:19:23 +01001643 /* Check that attempting RA with another ll src addr won't work, packet dropped: */
1644 testcase TC_pdp46_act_deact_gtpu_access_wrong_ll_saddr_ipv6() runs on GT_CT {
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001645 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001646 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001647 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1648 f_pdp_ctx_act(ctx);
1649
Pau Espin Pedrolc6ac6952022-02-14 11:19:23 +01001650 var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1651 var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8);
1652 f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong));
1653 f_wait_gtpu_fail(ctx);
1654
1655 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001656 f_shutdown_helper();
Pau Espin Pedrolc6ac6952022-02-14 11:19:23 +01001657 }
1658
1659 /* Assert that packets with wrong ipv6 global src addr are dropped by GGSN on APN IPv4v6 */
1660 testcase TC_pdp46_act_deact_gtpu_access_wrong_global_saddr_ipv6() runs on GT_CT {
1661 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001662 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Pau Espin Pedrolc6ac6952022-02-14 11:19:23 +01001663 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
1664 f_pdp_ctx_act(ctx);
1665
1666 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
1667 f_wait_rtr_adv(ctx);
1668 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
1669
1670 var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
1671 var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1672 var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob);
1673 f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr));
Oliver Smithee6a0882019-03-08 11:05:46 +01001674 f_wait_gtpu_fail(ctx);
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01001675
Oliver Smithee6a0882019-03-08 11:05:46 +01001676 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001677 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001678 }
1679
1680 /* Validate if different clients (pdp ctx) can reach one another through GGSN. */
1681 testcase TC_pdp46_clients_interact() runs on GT_CT {
1682 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001683 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
1684 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
Oliver Smithee6a0882019-03-08 11:05:46 +01001685 f_pdp_ctx_act(ctxA);
1686 f_send_gtpu(ctxA, f_icmpv6_rs_for_pdp46(ctxA));
1687 f_wait_rtr_adv(ctxA);
1688 f_send_gtpu(ctxA, f_gen_icmpv6_neigh_solicit_for_pdp46(ctxA));
1689
1690 f_pdp_ctx_act(ctxB);
1691 f_send_gtpu(ctxB, f_icmpv6_rs_for_pdp46(ctxB));
1692 f_wait_rtr_adv(ctxB);
1693 f_send_gtpu(ctxB, f_gen_icmpv6_neigh_solicit_for_pdp46(ctxB));
1694
1695 var OCT16 addrA_ll := f_ipv6_link_local(ctxA.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1696 var OCT16 addrB_ll := f_ipv6_link_local(ctxB.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1697 var OCT16 addrA_glob := f_ipv6_global(ctxA.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1698 var OCT16 addrB_glob := f_ipv6_global(ctxB.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
1699
1700 /* Validate if clients can interact using ll addr. */
1701 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_ll, addrB_ll));
1702 f_wait_gtpu_fail(ctxB);
1703
1704 /* Validate if clients can interact using global addr. */
1705 f_send_gtpu(ctxA, f_gen_icmpv6_echo(addrA_glob, addrB_glob));
1706 f_wait_gtpu_fail(ctxB);
1707
1708 f_pdp_ctx_del(ctxA, '1'B);
Pau Espin Pedrolbb2bb062019-09-03 12:28:12 +02001709 f_pdp_ctx_del(ctxB, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001710 f_shutdown_helper();
Oliver Smithee6a0882019-03-08 11:05:46 +01001711 }
1712
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001713 /* Test IPv4v6 context activation for dynamic IPv4v6 EUA on a v4-only APN */
1714 testcase TC_pdp46_act_deact_apn4() runs on GT_CT {
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001715 const OCT1 cause_accept := '80'O; /* Normal accept cause */
1716 const OCT1 cause_new_pdp_type := '81'O; /* Cause: New PDP type due to network preference */
1717 const OCT1 cause_unknown_pdp := 'DC'O; /* Cause: Unknown PDP address or PDP type */
1718 var CreatePDPContextResponse cpr;
1719
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001720 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001721 var PdpContext ctx46 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dynv6Dyn)));
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001722 cpr := f_pdp_ctx_act(ctx46, (cause_unknown_pdp, cause_new_pdp_type));
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001723
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001724 if (cpr.cause.causevalue == cause_new_pdp_type) {
1725 /* 3GPP TS 23.060 sec 9.2.1: "If the MS requests PDP type IPv4v6,
1726 * but the operator preferences dictate the use of a single IP
1727 * version only, the PDP type shall be changed to a single address
1728 * PDP type (IPv4 or IPv6) and a reason cause shall be returned to
1729 * the MS indicating that only the assigned PDP type is allowed. In
1730 * this case, the MS shall not request another PDP context for the
1731 * other PDP type during the existence of the PDP context." */
1732 f_pdp_ctx_del(ctx46, '1'B);
1733 } else {
1734 /* 3GPP TS 23.060 sec 9.2.1 NOTE 5: If the MS requests PDP type
1735 * IPv4v6, and the PDP context is rejected due to "unknown PDP
1736 * type", the MS can attempt to establish dual-stack connectivity
1737 * by performing two PDP context request procedures to activate an
1738 * IPv4 PDP context and an IPv6 PDP context, both to the same APN. A
1739 * typical MS first attempts v4v6, and if rejected, then tries v4
1740 * and v6 separetly */
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001741 var PdpContext ctx4 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001742 f_pdp_ctx_act(ctx4, cause_accept); /* Normal accept cause */
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001743
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001744 var PdpContext ctx6 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv6Dyn)));
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001745 f_pdp_ctx_act(ctx6, cause_unknown_pdp); /* Cause: Unknown PDP address or PDP type */
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001746
Pau Espin Pedrol0f464d62022-02-23 14:04:29 +01001747 f_pdp_ctx_del(ctx4, '1'B);
1748 }
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001749 f_shutdown_helper();
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02001750 }
1751
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +02001752 /* Validate if 2nd CtxCreateReq with increased Recovery IE causes ggsn to drop 1st one (while keeping 2nd one). */
1753 testcase TC_pdp_act2_recovery() runs on GT_CT {
1754 var Gtp1cUnitdata ud;
1755 var default d;
1756 var boolean ctxA_deleted := false;
1757 var boolean ctxB_created := false;
1758
1759 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001760 var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
1761 var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +02001762 f_pdp_ctx_act(ctxA);
1763
Vadim Yanitskiyd344b4a2022-02-09 18:28:18 +06001764 g_restart_ctr := int2oct((oct2int(g_restart_ctr) + 1) mod 256, 1);
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +02001765
1766 log("sending 2nd CreatePDP (recovery increased)");
1767 f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctxB.imsi, g_restart_ctr,
1768 ctxB.teid, ctxB.teic, ctxB.nsapi, ctxB.eua, ctxB.apn,
1769 g_sgsn_ip_c, g_sgsn_ip_u, ctxB.msisdn, ctxB.pco_req));
1770 T_default.start;
1771 d := activate(pingpong());
1772 alt {
1773 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ctxB.teic)) -> value ud {
1774 f_handle_create_req(ctxB, ud);
1775 if (not ctxB_created) {
1776 ctxB_created := true;
1777 setverdict(pass);
1778 } else {
1779 setverdict(fail, "Repeated createPDPContextResponse(ctxB)");
1780 }
1781
1782 if (not ctxA_deleted) {
1783 repeat;
1784 }
1785 }
1786 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextRequest, ctxA.teic)) -> value ud {
1787 if (ispresent(ud.gtpc.gtpc_pdu.deletePDPContextRequest.tearDownIndicator)) {
1788 setverdict(pass);
1789 } else {
1790 setverdict(fail);
1791 }
1792
1793 if (not ctxA_deleted) {
1794 ctxA_deleted := true;
1795 setverdict(pass);
1796 } else {
1797 setverdict(fail, "Repeated deletePDPContextRequest(ctxA)");
1798 }
1799
1800 if (not ctxB_created) {
1801 repeat;
1802 }
1803 }
1804 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextRequest, ctxB.teic)) -> value ud {
1805 setverdict(fail, "GGSN dropping still valid pdp ctx");
1806 }
1807 }
1808 deactivate(d);
1809 T_default.stop;
1810
1811 f_pdp_ctx_del(ctxB, '1'B);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001812 f_shutdown_helper();
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +02001813 }
1814
1815
Pau Espin Pedrolbfad97f2022-11-04 12:03:17 +01001816 /* Send a duplicate echo req. osmo-ggsn maintains a queue for sent responses (T3-RESPONSE * N3-REQUESTS):
1817 * If same delete req is sent and duplicate is detected, saved duplicate response should be sent back. */
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02001818 testcase TC_act_deact_retrans_duplicate() runs on GT_CT {
1819 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001820 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02001821 f_pdp_ctx_act(ctx);
1822 f_pdp_ctx_del(ctx, '1'B);
1823 /* leave some time in between to make sure retransmit response queue keeps packets for a while */
Pau Espin Pedrolbfad97f2022-11-04 12:03:17 +01001824 f_sleep(int2float(mp_t3_response));
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02001825 /* g_c_seq_nr was increased during f_pdp_ctx_del(), we want a
1826 duplicate. If it was not a duplicate, osmo-ggsn would answer
1827 with a failure since that PDP ctx was already deleted. */
Pau Espin Pedrold6b51332022-05-19 17:47:11 +02001828 if (g_c_seq_nr == 0) {
1829 g_c_seq_nr := 65535;
1830 } else {
1831 g_c_seq_nr := g_c_seq_nr - 1;
1832 }
Pau Espin Pedrol10ec96e2022-02-09 17:03:15 +01001833 f_pdp_ctx_del(ctx, '1'B, expect_diameter := false);
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02001834
1835 /* Now send a new pdp ctx del (increased seqnum). It should fail with cause "non-existent": */
1836 var OCT1 cause_nonexistent := 'C0'O;
Pau Espin Pedrol10ec96e2022-02-09 17:03:15 +01001837 f_pdp_ctx_del(ctx, '1'B, cause_nonexistent, expect_diameter := false);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001838 f_shutdown_helper();
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02001839 }
1840
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001841 /* Activate PDP context + trigger Recovery procedure through EchoResp */
1842 testcase TC_pdp_act_restart_ctr_echo() runs on GT_CT {
1843 var Gtp1cUnitdata ud;
Pau Espin Pedrol05118022022-02-17 19:49:13 +01001844 g_use_echo_intval := 5;
1845 timer T_echo;
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001846 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02001847 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001848 f_pdp_ctx_act(ctx);
1849
1850 /* Wait to receive echo request and send initial Restart counter */
Pau Espin Pedrol05118022022-02-17 19:49:13 +01001851 T_echo.start(int2float(g_use_echo_intval) + 1.0);
1852 alt {
1853 [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001854 var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
1855 GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
Pau Espin Pedrol05118022022-02-17 19:49:13 +01001856 }
1857 [] T_echo.timeout {
1858 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1859 "Timeout waiting for ping");
1860 }
1861 }
1862 T_echo.stop;
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001863
1864 /* Wait to receive second echo request and send incremented Restart
1865 counter. This will fake a restarted SGSN, and pdp ctx allocated
1866 should be released by GGSN */
Vadim Yanitskiyd344b4a2022-02-09 18:28:18 +06001867 g_restart_ctr := int2oct((oct2int(g_restart_ctr) + 1) mod 256, 1);
Pau Espin Pedrol05118022022-02-17 19:49:13 +01001868 T_echo.start(int2float(g_use_echo_intval) + 1.0);
1869 alt {
1870 [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001871 var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
1872 GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
Pau Espin Pedrol05118022022-02-17 19:49:13 +01001873 }
1874 [] T_echo.timeout {
1875 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1876 "Timeout waiting for ping");
1877 }
1878 }
1879 T_echo.stop;
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001880 f_pdp_ctx_exp_del_req(ctx, omit, true);
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001881 f_shutdown_helper();
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02001882 }
1883
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001884 /* Test creation, user plane and deletion of big amount (1000) of concurrent PDP context */
1885 testcase TC_lots_of_concurrent_pdp_ctx() runs on GT_CT {
1886 var Gtp1cUnitdata udc;
1887 var Gtp1uUnitdata udu;
1888 const integer num_ctx := 1000;
1889 var PdpContext ctx[num_ctx];
1890 timer T_next := 0.01;
1891 var integer next_req_ctx := 0;
1892 var integer rx_resp_ctx := 0;
1893 var integer rx_pong := 0;
1894 var OCT4 dns1_addr;
1895 var OCT4 saddr;
1896 var integer teic;
1897 var integer idx;
1898
1899 f_init();
1900
1901 for (var integer i := 0; i < num_ctx; i := i + 1) {
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02001902 ctx[i] := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234" & int2str(f_rnd_int(4294967296)), c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001903 ctx[i].teic := int2oct(i+1, 4); /* +1: skip TEIC=0 */
1904 ctx[i].teid := int2oct(i+1, 4); /* +1: skip TEID=0 */
1905 ctx[i].pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
1906 }
1907
1908 T_default.start(60.0);
1909
1910 T_next.start;
1911 alt {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01001912 [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(INITIAL_REQUEST) { repeat; }
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02001913 [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, INITIAL_REQUEST) { repeat; }
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001914 [] pingpong();
1915 [] T_next.timeout {
1916 f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx[next_req_ctx].imsi, g_restart_ctr,
1917 ctx[next_req_ctx].teid, ctx[next_req_ctx].teic, ctx[next_req_ctx].nsapi,
1918 ctx[next_req_ctx].eua, ctx[next_req_ctx].apn, g_sgsn_ip_c, g_sgsn_ip_u,
1919 ctx[next_req_ctx].msisdn, ctx[next_req_ctx].pco_req, ctx[next_req_ctx].ratType,
Pau Espin Pedrol535ca262022-05-16 14:07:17 +02001920 ctx[next_req_ctx].uli, ctx[next_req_ctx].charging_char, ctx[next_req_ctx].imeisv,
1921 ctx[next_req_ctx].ms_tz));
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001922 next_req_ctx := next_req_ctx + 1;
1923 if (next_req_ctx < num_ctx) {
1924 T_next.start;
1925 }
1926 repeat;
1927 }
1928 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ?)) -> value udc {
1929 teic := oct2int(udc.gtpc.teid);
1930 if (not match(teic, (1 .. num_ctx))) {
1931 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1932 "Rx Unexpected TEIC");
1933 }
1934 idx := teic - 1;
1935 f_handle_create_req(ctx[idx], udc);
1936 rx_resp_ctx := rx_resp_ctx + 1;
1937
1938 dns1_addr := f_PCO_extract_proto(ctx[idx].pco_neg, '000d'O);
1939 saddr := ctx[idx].eua.endUserAddress.endUserAddressIPv4.ipv4_address;
1940 f_send_gtpu(ctx[idx], f_gen_icmpv4_echo(saddr, dns1_addr));
1941 repeat;
1942 }
1943 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value udu {
1944 var octetstring gpdu := udu.gtpu.gtpu_IEs.g_PDU_IEs.data;
1945 var IPv4_packet ip4 := f_IPv4_dec(gpdu);
1946 if (ip4.header.ver != 4) {
1947 repeat;
1948 }
1949 var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload);
1950 if (not match(icmp4, (tr_ICMPv4_ERP, tr_ICMPv4_DU))) {
1951 repeat;
1952 }
1953 rx_pong := rx_pong + 1;
1954 if (rx_pong < num_ctx) {
1955 repeat;
1956 }
1957 setverdict(pass);
1958 }
1959 [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
1960 [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
1961 }
1962
1963 /* Let's close them now: */
1964 next_req_ctx := 0;
1965 rx_resp_ctx := 0;
1966 T_next.start;
1967 alt {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01001968 [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(TERMINATION_REQUEST) { repeat; }
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02001969 [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, TERMINATION_REQUEST) { repeat; }
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001970 [] pingpong();
1971 [] T_next.timeout {
1972 f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, ctx[next_req_ctx].teic_remote, ctx[next_req_ctx].nsapi, '1'B));
1973 next_req_ctx := next_req_ctx + 1;
1974 if (next_req_ctx < num_ctx) {
1975 T_next.start;
1976 }
1977 repeat;
1978 }
1979 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ?)) -> value udc {
1980 teic := oct2int(udc.gtpc.teid);
1981 if (not match(teic, (1 .. num_ctx))) {
1982 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
1983 "Rx Unexpected TEIC");
1984 }
1985 rx_resp_ctx := rx_resp_ctx + 1;
1986 if (rx_resp_ctx < num_ctx) {
1987 repeat;
1988 }
1989 setverdict(pass);
1990 }
1991 [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
1992 [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
1993 }
1994 T_next.stop;
1995
1996 T_default.stop;
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01001997 f_shutdown_helper();
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01001998 }
1999
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002000 /* Test callocation of PDP contexts until reaching addr pool exhaustion */
2001 type record of OCT4 TEIClist;
2002 testcase TC_addr_pool_exhaustion() runs on GT_CT {
2003 var Gtp1cUnitdata udc;
2004 var Gtp1uUnitdata udu;
2005 var PdpContext ctx;
2006 timer T_next := 0.005;
2007 var integer next_req_ctx := 0;
2008 var integer rx_resp_ctx := 0;
2009 var integer num_ctx;
2010 var boolean cont_req := true;
2011 var CreatePDPContextResponse cpr;
2012 var TEIClist teic_list := {};
2013 var integer teic;
2014
2015 f_init();
2016
2017 T_default.start(120.0);
2018
2019 T_next.start;
2020 alt {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002021 [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(INITIAL_REQUEST) { repeat; }
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002022 [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, INITIAL_REQUEST) { repeat; }
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002023 [] pingpong();
2024 [] T_next.timeout {
2025 if (cont_req) {
2026 if (next_req_ctx - rx_resp_ctx < 100) { /* if we have too many in progress, wait a bit to continue */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002027 ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234" & int2str(f_rnd_int(4294967296)), c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002028 ctx.nsapi := '0001'B;
2029 ctx.teic := int2oct(next_req_ctx+1, 4); /* +1: skip TEIC=0 */
2030 ctx.teid := int2oct(next_req_ctx+1, 4); /* +1: skip TEID=0 */
2031 f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx.imsi, g_restart_ctr,
2032 ctx.teid, ctx.teic, ctx.nsapi,
2033 ctx.eua, ctx.apn, g_sgsn_ip_c, g_sgsn_ip_u,
2034 ctx.msisdn, ctx.pco_req, ctx.ratType,
Pau Espin Pedrol535ca262022-05-16 14:07:17 +02002035 ctx.uli, ctx.charging_char, ctx.imeisv,
2036 ctx.ms_tz));
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002037 next_req_ctx := next_req_ctx + 1;
2038 }
2039 T_next.start;
2040 }
2041 repeat;
2042 }
2043 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ?)) -> value udc {
2044 cpr := udc.gtpc.gtpc_pdu.createPDPContextResponse;
2045
2046 if (cpr.cause.causevalue == '80'O) {
2047 teic_list := teic_list & {cpr.teidControlPlane.teidControlPlane};
2048 } else {
2049 if (cont_req == true) {
2050 num_ctx := rx_resp_ctx;
2051 log("Successfully created ", num_ctx, " PDP contexts before exhausting the pool");
2052 setverdict(pass);
2053 }
2054 cont_req := false;
2055 }
2056 rx_resp_ctx := rx_resp_ctx + 1;
2057 if (not cont_req and next_req_ctx == rx_resp_ctx) {
2058 break;
2059 } else {
2060 repeat;
2061 }
2062 }
2063 [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
2064 [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
2065 }
2066
2067 /* Let's close them now: */
2068 next_req_ctx := 0;
2069 rx_resp_ctx := 0;
2070 T_next.start;
2071 alt {
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002072 [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(TERMINATION_REQUEST) { repeat; }
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002073 [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, TERMINATION_REQUEST) { repeat; }
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002074 [] pingpong();
2075 [] T_next.timeout {
2076 f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, teic_list[next_req_ctx], '0001'B, '1'B));
2077 next_req_ctx := next_req_ctx + 1;
2078 if (next_req_ctx < num_ctx) {
2079 T_next.start;
2080 }
2081 repeat;
2082 }
2083 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ?)) -> value udc {
2084 teic := oct2int(udc.gtpc.teid);
2085 if (not match(teic, (1 .. num_ctx))) {
2086 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2087 "Rx Unexpected TEIC");
2088 }
2089 rx_resp_ctx := rx_resp_ctx + 1;
2090 if (rx_resp_ctx < num_ctx) {
2091 repeat;
2092 }
2093 setverdict(pass);
2094 }
2095 [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
2096 [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
2097 }
2098 T_next.stop;
2099
2100 T_default.stop;
Pau Espin Pedrolc441ce02022-03-07 14:35:45 +01002101 f_shutdown_helper();
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002102 }
2103
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002104 /* Test charging over Gy interface. */
2105 testcase TC_gy_charging_cc_time() runs on GT_CT {
2106 var default d;
2107
2108 g_gy_validity_time := 3; /* Grant access for 3 seconds, needs to be re-validated afterwards */
2109 f_init();
Pau Espin Pedrold25095f2022-05-18 16:29:05 +02002110 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002111 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
2112 f_pdp_ctx_act(ctx);
2113
2114 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
2115
2116 /* Send some UL traffic: */
2117 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
2118 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
2119 f_wait_icmp4_echo_reply(ctx);
2120
2121 T_default.start(10.0);
2122 d := activate(pingpong());
2123
2124 g_gy_validity_time := 2;
2125 /* First update reports octests/pkt on both UL/DL (see icmp ping-pong above) */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002126 as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +02002127 f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), 28, 28);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002128
2129 /* Second update: 0 ul/dl pkt/octet should be reported, since nothing was sent */
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002130 as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +02002131 f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (2..3), 0, 0);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002132
2133 /* Third update: make sure report contains again octets/pkts for both UL/DL: */
2134 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
2135 f_wait_icmp4_echo_reply(ctx);
2136 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
2137 f_wait_icmp4_echo_reply(ctx);
Pau Espin Pedrola2af5782022-05-18 16:34:29 +02002138 as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +02002139 f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (2..3), 56, 56);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002140
2141 /* Let the CCA reach the GGSN */
2142 f_sleep(0.5);
2143 deactivate(d);
2144 T_default.stop;
2145
2146 /* Send some data and validate it is reported in the TERMINATION_REQUEST
2147 * (triggered by PFCP Session Deletion Response): */
2148 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
2149 f_wait_icmp4_echo_reply(ctx);
2150
2151 f_pdp_ctx_del(ctx, '1'B);
Pau Espin Pedrol8fa22842022-05-20 14:47:55 +02002152 f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 28, 28);
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002153
2154
2155 f_shutdown_helper();
2156 }
2157
Pau Espin Pedrol52562c92022-05-23 15:45:46 +02002158 /* Test Volume-Quota-Thresold AVP triggers request before Validity-Time */
2159 testcase TC_gy_charging_volume_quota_threshold() runs on GT_CT {
2160 var default d;
2161 timer Tout;
2162 g_gy_volume_threshold := 1000; /* Will make a trigger when we send bigger payload below */
2163 g_gy_validity_time := 8; /* Grant access for 8 seconds, needs to be re-validated afterwards */
2164 f_init();
2165 var float tout_sec := int2float(g_gy_validity_time) / 2.0;
2166 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
2167 ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
2168 f_pdp_ctx_act(ctx);
2169
2170 var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
2171
2172 T_default.start(40.0);
2173 d := activate(pingpong());
2174
2175 /* Send some UL traffic: */
2176 var octetstring payload := f_rnd_octstring(1200);
2177 var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
2178 f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr, payload));
2179 f_wait_icmp4_echo_reply(ctx);
2180
2181 /* ICMP Req generates one report: */
2182 Tout.start(tout_sec);
2183 alt {
2184 [] as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
2185 [] Tout.timeout {
2186 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
2187 "TImeout waiting for Gy UPDATE triggered by Volume-Quota-Threshold");
2188 }
2189 }
Pau Espin Pedrol5fa8f782022-10-03 13:57:54 +02002190 f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..6), (1200..1400), 0);
Pau Espin Pedrol52562c92022-05-23 15:45:46 +02002191
2192 /* ICMP Resp (echo back) generates one report: */
2193 as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
Pau Espin Pedrol5fa8f782022-10-03 13:57:54 +02002194 f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..1), 0, (1200..1400));
Pau Espin Pedrol52562c92022-05-23 15:45:46 +02002195
2196 /* Second update: 0 ul/dl pkt/octet should be reported, since nothing was sent */
2197 as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
2198 f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (8..9), 0, 0);
2199
2200 /* Let the CCA reach the GGSN */
2201 f_sleep(0.5);
2202 deactivate(d);
2203 T_default.stop;
2204
2205 f_pdp_ctx_del(ctx, '1'B);
2206 f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 0, 0);
2207
2208
2209 f_shutdown_helper();
2210 }
2211
Harald Welte94ade362017-08-04 00:36:55 +02002212 control {
Harald Welteed7a1772017-08-09 20:26:20 +02002213 execute(TC_pdp4_act_deact());
2214 execute(TC_pdp4_act_deact_ipcp());
Harald Weltef8298542019-04-10 10:15:28 +02002215 execute(TC_pdp4_act_deact_ipcp_pap_broken());
Harald Welteed7a1772017-08-09 20:26:20 +02002216 execute(TC_pdp4_act_deact_pcodns());
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01002217 execute(TC_pdp4_act_deact_gtpu_access());
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01002218 execute(TC_pdp4_act_deact_gtpu_access_wrong_saddr());
2219 execute(TC_pdp4_act_deact_gtpu_access_ipv6_apn4());
Stefan Sperlingc479e4f2018-04-03 19:34:16 +02002220 execute(TC_pdp4_clients_interact_with_txseq());
2221 execute(TC_pdp4_clients_interact_without_txseq());
Philipp Maier33e52612018-05-30 17:22:02 +02002222 execute(TC_pdp4_act_deact_with_single_dns());
2223 execute(TC_pdp4_act_deact_with_separate_dns());
Pau Espin Pedrolcd326c52022-02-14 18:57:43 +01002224 execute(TC_pdp4_act_update_teic());
2225 execute(TC_pdp4_act_update_teid());
Harald Welteed7a1772017-08-09 20:26:20 +02002226
2227 execute(TC_pdp6_act_deact());
2228 execute(TC_pdp6_act_deact_pcodns());
2229 execute(TC_pdp6_act_deact_icmp6());
Pau Espin Pedrol3d9338f2018-01-29 20:42:54 +01002230 execute(TC_pdp6_act_deact_gtpu_access());
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01002231 execute(TC_pdp6_act_deact_gtpu_access_wrong_ll_saddr());
2232 execute(TC_pdp6_act_deact_gtpu_access_wrong_global_saddr());
2233 execute(TC_pdp6_act_deact_gtpu_access_ipv4_apn6());
Pau Espin Pedrol6c7285d2018-01-30 17:20:22 +01002234 execute(TC_pdp6_clients_interact());
Harald Weltedca80052017-08-13 20:01:38 +02002235
Oliver Smithee6a0882019-03-08 11:05:46 +01002236 execute(TC_pdp46_act_deact());
2237 execute(TC_pdp46_act_deact_ipcp());
2238 execute(TC_pdp46_act_deact_icmp6());
2239 execute(TC_pdp46_act_deact_pcodns4());
2240 execute(TC_pdp46_act_deact_pcodns6());
2241 execute(TC_pdp46_act_deact_gtpu_access());
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01002242 execute(TC_pdp46_act_deact_gtpu_access_wrong_saddr_ipv4());
Pau Espin Pedrolc6ac6952022-02-14 11:19:23 +01002243 execute(TC_pdp46_act_deact_gtpu_access_wrong_ll_saddr_ipv6());
Pau Espin Pedrolc8c03412022-02-11 13:39:26 +01002244 execute(TC_pdp46_act_deact_gtpu_access_wrong_global_saddr_ipv6());
Oliver Smithee6a0882019-03-08 11:05:46 +01002245 execute(TC_pdp46_clients_interact());
Pau Espin Pedrol22d597f2019-08-21 16:16:58 +02002246 execute(TC_pdp46_act_deact_apn4());
Oliver Smithee6a0882019-03-08 11:05:46 +01002247
Harald Weltedca80052017-08-13 20:01:38 +02002248 execute(TC_echo_req_resp());
Pau Espin Pedrol480e67f2022-02-09 16:37:47 +01002249 execute(TC_echo_req_resp_gtpu());
Pau Espin Pedrolfa1ca022019-08-23 18:58:53 +02002250 execute(TC_pdp_act2_recovery());
Pau Espin Pedrol9a5f42f2019-05-27 20:04:35 +02002251 execute(TC_act_deact_retrans_duplicate());
Pau Espin Pedrol6916ec42019-08-23 16:15:07 +02002252
Pau Espin Pedrol6f319f92020-01-03 20:18:57 +01002253 execute(TC_pdp_act_restart_ctr_echo());
Pau Espin Pedrol68c2af52022-02-25 11:56:17 +01002254
2255 execute(TC_lots_of_concurrent_pdp_ctx());
Pau Espin Pedrolbfea8352022-02-28 12:11:26 +01002256 /* Keep at the end, crashes older osmo-ggsn versions (OS#5469): */
2257 execute(TC_addr_pool_exhaustion());
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002258
2259 /* open5gs specific tests: */
2260 if (m_ggsn_impl == GGSN_IMPL_OPEN5GS) {
2261 execute(TC_gy_charging_cc_time());
Pau Espin Pedrol52562c92022-05-23 15:45:46 +02002262 execute(TC_gy_charging_volume_quota_threshold());
Pau Espin Pedrol77fdd0b2022-03-08 14:03:33 +01002263 }
Harald Welte94ade362017-08-04 00:36:55 +02002264 }
Harald Welte379d45a2017-08-03 09:55:15 +02002265}