blob: 5214c1ef70cdcb880f357e377a4069103532d9db [file] [log] [blame]
Harald Welte379d45a2017-08-03 09:55:15 +02001module GGSN_Tests {
2
Harald Welte94ade362017-08-04 00:36:55 +02003 import from General_Types all;
Harald Welte811651e2017-08-05 15:25:06 +02004 import from Osmocom_Types all;
Harald Welte94ade362017-08-04 00:36:55 +02005 import from IPL4asp_PortType all;
6 import from IPL4asp_Types all;
7 import from GTP_CodecPort all;
8 import from GTP_CodecPort_CtrlFunct all;
9 import from GTPC_Types all;
10 import from GTPU_Types all;
Harald Welte231b9412017-08-09 17:16:31 +020011 import from IP_Types all;
12 import from ICMPv6_Types all;
Harald Welte94ade362017-08-04 00:36:55 +020013
14 const integer GTP0_PORT := 3386;
15 const integer GTP1C_PORT := 2123;
16 const integer GTP1U_PORT := 2152;
Harald Welte876345e2017-08-04 16:19:59 +020017 const charstring g_bind_ip_c := "127.23.42.1";
18 const charstring g_bind_ip_u := g_bind_ip_c;
Harald Welte94ade362017-08-04 00:36:55 +020019
Harald Welte811651e2017-08-05 15:25:06 +020020 type set PdpContext {
21 hexstring imsi,
22 octetstring msisdn optional,
23 octetstring apn,
Harald Welteed7a1772017-08-09 20:26:20 +020024 ProtConfigOptions pco_req optional,
25 ProtConfigOptions pco_neg optional,
Harald Welte811651e2017-08-05 15:25:06 +020026 EndUserAddress eua,
Harald Welte231b9412017-08-09 17:16:31 +020027 OCT16 ip6_prefix optional,
Harald Welte811651e2017-08-05 15:25:06 +020028 BIT4 nsapi,
29 /* TEI (Data) local side */
30 OCT4 teid,
31 /* TEI (Control) local side */
32 OCT4 teic,
33 /* TEI (Data) remote side */
34 OCT4 teid_remote,
35 /* TEI (Control) remote side */
Harald Welte5438b9d2017-08-13 13:27:48 +020036 OCT4 teic_remote
Harald Welte811651e2017-08-05 15:25:06 +020037 }
38
Harald Welte94ade362017-08-04 00:36:55 +020039 type component GT_CT {
40 port GTPC_PT GTPC;
41 port GTPU_PT GTPU;
42
Harald Welte0be142b2017-08-13 13:28:10 +020043 var boolean g_initialized := false;
44
Harald Welte94ade362017-08-04 00:36:55 +020045 var OCT1 g_restart_ctr := '01'O;
46 /* FIXME: unify with g_bind_ip + parse from config file */
Harald Welte876345e2017-08-04 16:19:59 +020047 var OCT4 g_sgsn_ip_c := '7f172a01'O;
48 var OCT4 g_sgsn_ip_u := '7f172a01'O;
Harald Welte94ade362017-08-04 00:36:55 +020049 /* FIXME: parse remName from config file */
Harald Welte811651e2017-08-05 15:25:06 +020050 var GtpPeer g_peer_c := { connId := 0, remName := "127.0.0.6", remPort := GTP1C_PORT };
51 var GtpPeer g_peer_u := { connId := 0, remName := "127.0.0.6", remPort := GTP1U_PORT };
Harald Welte94ade362017-08-04 00:36:55 +020052 timer T_default := 3.0;
Harald Welte5438b9d2017-08-13 13:27:48 +020053
54 /* next to-be-sent GTP-C sequence number */
55 var uint16_t g_c_seq_nr;
56 /* next to-be-sent GTP-U sequence number */
57 var uint16_t g_d_seq_nr;
Harald Welte94ade362017-08-04 00:36:55 +020058 }
59
60 function f_init() runs on GT_CT {
Harald Welte0be142b2017-08-13 13:28:10 +020061 if (g_initialized == true) {
62 return;
63 }
64 g_initialized := true;
65
Harald Welte94ade362017-08-04 00:36:55 +020066 var Result res;
67 map(self:GTPC, system:GTPC);
Harald Welte876345e2017-08-04 16:19:59 +020068 res := GTP_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, g_bind_ip_c, GTP1C_PORT, {udp:={}});
Harald Welte94ade362017-08-04 00:36:55 +020069 log("GTP1C ConnectionID: ", res.connId);
Harald Welte811651e2017-08-05 15:25:06 +020070 g_peer_c.connId := res.connId;
Harald Welte94ade362017-08-04 00:36:55 +020071
72 map(self:GTPU, system:GTPU);
Harald Welte811651e2017-08-05 15:25:06 +020073 res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, g_bind_ip_u, GTP1U_PORT, {udp:={}});
74 g_peer_u.connId:= res.connId;
Harald Welte5438b9d2017-08-13 13:27:48 +020075
76 g_restart_ctr := f_rnd_octstring(1);
77 g_c_seq_nr := (oct2int(g_restart_ctr) * 1024) mod 65536;
78 g_d_seq_nr := (oct2int(g_restart_ctr) * 2000) mod 65536;
Harald Welte94ade362017-08-04 00:36:55 +020079 }
80
81 /* generalized GTP-C receive template */
82 template PDU_GTPC tr_GTP1C_PDU(template OCT1 msg_type, template OCT4 teid) := {
83 /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
84 * error if this flag is set to '1'. */
85 pn_bit := '0'B,
86 /* Sequence number flag (S) shall be set to '1'. */
87 s_bit := '1'B,
88 e_bit := ?,
89 spare := ?,
90 /* Protocol Type flag (PT) shall be set to '1'.*/
91 pt := '1'B,
92 /* Version shall be set to decimal 1 ('001'). */
93 version := '001'B,
94 messageType := msg_type,
95 lengthf := ?,
96 teid := teid,
97 opt_part := *,
98 gtpc_pdu := ?
99 }
100
101 /* generalized GTP-C send template */
Harald Welte811651e2017-08-05 15:25:06 +0200102 template PDU_GTPC ts_GTP1C_PDU(OCT1 msg_type, OCT4 teid, GTPC_PDUs pdu, uint16_t seq_nr) := {
Harald Welte94ade362017-08-04 00:36:55 +0200103 /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
104 * error if this flag is set to '1'. */
105 pn_bit := '0'B,
106 /* Sequence number flag (S) shall be set to '1'. */
107 s_bit := '1'B,
108 e_bit := '0'B,
109 spare := '0'B,
110 /* Protocol Type flag (PT) shall be set to '1'.*/
111 pt := '1'B,
112 /* Version shall be set to decimal 1 ('001'). */
113 version := '001'B,
114 messageType := msg_type,
115 lengthf := 0, /* we assume encoder overwrites this */
116 teid := teid,
117 opt_part := {
Harald Welte811651e2017-08-05 15:25:06 +0200118 sequenceNumber := int2oct(seq_nr, 2),
Harald Welte94ade362017-08-04 00:36:55 +0200119 npduNumber := '00'O,
120 nextExtHeader := '00'O,
121 gTPC_extensionHeader_List := omit
122 },
123 gtpc_pdu := pdu
124 }
125
126 /* recovery IE */
127 template Recovery_gtpc ts_Recovery(OCT1 restart_counter) := {
128 type_gtpc := '00'O, /* we assume encoder fixes this */
129 restartCounter := restart_counter
130 }
131
132 /* template matching reception of GTP-C echo-request */
133 template Gtp1cUnitdata tr_GTPC_MsgType(template GtpPeer peer, template OCT1 msg_type, template OCT4 teid) := {
134 peer := peer,
135 gtpc := tr_GTP1C_PDU(msg_type, teid)
136 }
137
138 /* template matching reception of GTP-C echo-request */
139 template Gtp1cUnitdata tr_GTPC_PING(template GtpPeer peer) := tr_GTPC_MsgType(peer, echoRequest, '00000000'O);
140
141 template GTPC_PDUs ts_EchoRespPDU(OCT1 restart_counter) := {
142 echoResponse := {
143 recovery := {
144 type_gtpc := '00'O, /* we assume encoder fixes? */
145 restartCounter := restart_counter
146 },
147 private_extension_gtpc := omit
148 }
149 }
150
151 /* master template for senidng a GTP-C echo response */
Harald Welte811651e2017-08-05 15:25:06 +0200152 template Gtp1cUnitdata ts_GTPC_PONG(GtpPeer peer, uint16_t seq, OCT1 rest_ctr) := {
Harald Welte94ade362017-08-04 00:36:55 +0200153 peer := peer,
Harald Welte811651e2017-08-05 15:25:06 +0200154 gtpc := ts_GTP1C_PDU(echoResponse, '00000000'O, valueof(ts_EchoRespPDU(rest_ctr)), seq)
Harald Welte94ade362017-08-04 00:36:55 +0200155 }
156
157 template EndUserAddress t_EuaIPv4(template OCT4 ip_addr) := {
158 type_gtpc := '80'O,
159 endUserAddress := {
160 endUserAddressIPv4 := {
161 lengthf := 2,
162 pdp_typeorg := '0001'B,
163 spare := '1111'B,
164 pdp_typenum := '21'O,
165 ipv4_address := ip_addr
166 }
167 }
168 }
169 template EndUserAddress t_EuaIPv4Dyn := t_EuaIPv4(omit);
170 template EndUserAddress t_EuaIPv6(template OCT16 ip_addr) := {
171 type_gtpc := '80'O,
172 endUserAddress := {
173 endUserAddressIPv6 := {
174 lengthf := 2,
175 pdp_typeorg := '0001'B,
176 spare := '1111'B,
177 pdp_typenum := '57'O,
178 ipv6_address := ip_addr
179 }
180 }
181 }
182 template EndUserAddress t_EuaIPv6Dyn := t_EuaIPv6(omit);
183
184 template AccessPointName ts_APN(octetstring apn) := {
185 type_gtpc := '83'O,
186 lengthf := lengthof(apn),
187 apn_value := apn
188 }
189
190 template GSN_Address_GTPC ts_GsnAddr(octetstring ip_addr) := {
191 type_gtpc := '85'O,
192 lengthf := lengthof(ip_addr),
193 addressf := ip_addr
194 }
195
196 template MSISDN ts_Msisdn(octetstring msisdn) := {
197 type_gtpc := '86'O,
198 lengthf := lengthof(msisdn),
199 msisdn := msisdn
200 }
201
202 template QualityOfServiceProfile ts_QosDefault := {
203 type_gtpc := '87'O,
204 lengthf := 4,
205 allocRetensionPrio := '00'O,
206 qos_ProfileValue := {
207 reliabilityClass := '011'B,
208 delayClass := '001'B,
209 spare1 := '00'B,
210 precedenceClass := '010'B,
211 spare2 := '0'B,
212 peakThroughput := '1001'B,
213 meanThroughput := '11111'B,
214 spare3 := '000'B,
215 deliverErroneusSDU := omit,
216 deliveryOrder := omit,
217 trafficClass := omit,
218 maxSDUSize := omit,
219 maxBitrateUplink := omit,
220 maxBitrateDownlink := omit,
221 sduErrorRatio := omit,
222 residualBER := omit,
223 trafficHandlingPriority := omit,
224 transferDelay := omit,
225 guaranteedBitRateUplink := omit,
226 guaranteedBitRateDownlink := omit,
227 sourceStatisticsDescriptor := omit,
228 signallingIndication := omit,
229 spare4 := omit,
230 maxBitrateDownlinkExt := omit,
231 guaranteedBitRateDownlinkExt := omit,
232 maxBitrateUplinkExt := omit,
233 guaranteedBitRateUplinkExt := omit
234 }
235 }
236
237 template IMSI_gtpc ts_Imsi(hexstring digits) := {
238 type_gtpc := '02'O,
239 digits := digits,
240 padding := 'F'H
241 }
242
243 template GTPC_PDUs ts_CreatePdpPDU(hexstring imsi, OCT1 restart_ctr, OCT4 teid_data, OCT4 teid_ctrl,
244 BIT4 nsapi, EndUserAddress eua, octetstring apn,
245 octetstring sgsn_ip_sign, octetstring sgsn_ip_data,
Harald Welteed7a1772017-08-09 20:26:20 +0200246 octetstring msisdn, template ProtConfigOptions pco := omit) := {
Harald Welte94ade362017-08-04 00:36:55 +0200247 createPDPContextRequest := {
248 imsi := ts_Imsi(imsi),
249 rai := omit,
250 recovery := ts_Recovery(restart_ctr),
251 selectionMode := {
252 type_gtpc := '0F'O,
253 selectModeValue := '00'B,
254 spare := '111111'B
255 },
256 teidDataI := {
257 type_gtpc := '00'O,
258 teidDataI := teid_data
259 },
260 teidControlPlane := {
261 type_gtpc := '00'O,
262 teidControlPlane := teid_ctrl
263 },
264 nsapi := {
265 type_gtpc := '00'O,
266 nsapi := nsapi,
267 unused := '0000'B
268 },
269 linked_nsapi := omit,
270 charging_char := omit,
271 trace_ref := omit,
272 trace_type := omit,
273 endUserAddress := eua,
274 accessPointName := ts_APN(apn),
Harald Welteed7a1772017-08-09 20:26:20 +0200275 protConfigOptions := pco,
Harald Welte94ade362017-08-04 00:36:55 +0200276 sgsn_addr_signalling := ts_GsnAddr(sgsn_ip_sign),
277 sgsn_addr_traffic := ts_GsnAddr(sgsn_ip_data),
278 msisdn := ts_Msisdn(msisdn),
279 qualityOfServiceProfile := ts_QosDefault,
280 tft := omit,
281 triggerId := omit,
282 omcId := omit,
283 commonFlags := omit,
284 aPN_Restriction := omit,
285 ratType := omit,
286 userLocationInformation := omit,
287 mS_TimeZone := omit,
288 imeisv := omit,
289 camelChargingInformationContainer := omit,
290 additionalTraceInfo := omit,
291 correlationID := omit,
292 evolvedAllocationRetentionPriorityI := omit,
293 extendedCommonFlags := omit,
294 userCSGInformation := omit,
295 aPN_AMBR := omit,
296 signallingPriorityIndication := omit,
297 cN_OperatorSelectionEntity := omit,
298 private_extension_gtpc := omit
299 }
300 }
301
Harald Welte811651e2017-08-05 15:25:06 +0200302 template Gtp1cUnitdata ts_GTPC_CreatePDP(GtpPeer peer, uint16_t seq, hexstring imsi,
303 OCT1 restart_ctr, OCT4 teid_data,
Harald Welte94ade362017-08-04 00:36:55 +0200304 OCT4 teid_ctrl, BIT4 nsapi, EndUserAddress eua,
305 octetstring apn, octetstring sgsn_ip_sign,
Harald Welteed7a1772017-08-09 20:26:20 +0200306 octetstring sgsn_ip_data, octetstring msisdn,
307 template ProtConfigOptions pco := omit) := {
Harald Welte94ade362017-08-04 00:36:55 +0200308 peer := peer,
309 gtpc := ts_GTP1C_PDU(createPDPContextRequest, '00000000'O,
310 valueof(ts_CreatePdpPDU(imsi, restart_ctr, teid_data, teid_ctrl,
311 nsapi, eua, apn, sgsn_ip_sign,
Harald Welteed7a1772017-08-09 20:26:20 +0200312 sgsn_ip_data, msisdn, pco)), seq)
313 }
314
315 template ProtConfigOptions ts_PCO := {
316 type_gtpc := '84'O,
317 lengthf := 0,
318 configProtocol := '000'B,
319 spare := '0000'B,
320 extension0 := '1'B,
321 protocols := {}
322 }
323
324
325 template ProtConfigOptions ts_PCO_IPv6_DNS modifies ts_PCO := {
326 protocols := {
327 { protocolID := '0003'O, lengthProtoID := 0, protoIDContents := ''O }
328 }
329 }
330
331 template ProtConfigOptions ts_PCO_IPv4_DNS_IPCP modifies ts_PCO := {
332 protocols := {
333 { protocolID := '8021'O, lengthProtoID := 16, protoIDContents := '01000010810600000000830600000000'O }
334 }
335 }
336
337 template ProtConfigOptions ts_PCO_IPv4_DNS_CONT modifies ts_PCO := {
338 protocols := {
339 { protocolID := '000d'O, lengthProtoID := 0, protoIDContents := ''O }
340 }
Harald Welte94ade362017-08-04 00:36:55 +0200341 }
342
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200343 function f_teardown_ind_IE(in template BIT1 ind) return template TearDownInd {
Harald Welte811651e2017-08-05 15:25:06 +0200344/*
345 if (not isvalue(ind)) {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200346 return omit;
347 }
Harald Welte811651e2017-08-05 15:25:06 +0200348*/
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200349 var TearDownInd ret := {
350 type_gtpc := '13'O,
351 tdInd := valueof(ind),
352 spare:= '0000000'B
353 }
354 return ret;
355 }
356
357 template GTPC_PDUs ts_DeletePdpPDU(BIT4 nsapi, template BIT1 teardown_ind) := {
358 deletePDPContextRequest := {
359 cause := omit,
360 tearDownIndicator := f_teardown_ind_IE(teardown_ind),
361 nsapi := {
362 type_gtpc := '14'O,
363 nsapi := nsapi,
364 unused := '0000'B
365 },
366 protConfigOptions := omit,
367 userLocationInformation := omit,
368 mS_TimeZone := omit,
369 extendedCommonFlags := omit,
370 uLI_Timestamp := omit,
371 private_extension_gtpc := omit
372 }
373 }
374
Harald Welte811651e2017-08-05 15:25:06 +0200375 template Gtp1cUnitdata ts_GTPC_DeletePDP(GtpPeer peer, uint16_t seq, OCT4 teid,
376 BIT4 nsapi, template BIT1 teardown_ind) := {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200377 peer := peer,
378 gtpc := ts_GTP1C_PDU(deletePDPContextRequest, teid,
Harald Welte811651e2017-08-05 15:25:06 +0200379 valueof(ts_DeletePdpPDU(nsapi, teardown_ind)), seq)
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200380 }
381
382
Harald Welte3af89482017-08-04 16:20:23 +0200383 /* GTP-U */
384
Harald Welte231b9412017-08-09 17:16:31 +0200385 template PDU_GTPU tr_GTP1U_PDU(template OCT1 msg_type, template OCT4 teid, template GTPU_IEs ies := ?) := {
Harald Welte3af89482017-08-04 16:20:23 +0200386 pn_bit := ?,
387 s_bit := ?,
388 e_bit := ?,
389 spare := ?,
390 /* Protocol Type flag (PT) shall be set to '1' in GTP */
391 pt := '1'B,
392 /* Version shall be set to decimal 1 ('001'). */
393 version := '001'B,
394 messageType := msg_type,
395 lengthf := ?,
396 teid := teid,
397 opt_part := *,
Harald Welte231b9412017-08-09 17:16:31 +0200398 gtpu_IEs := ies
Harald Welte3af89482017-08-04 16:20:23 +0200399 }
400
401 /* generalized GTP-U send template */
Harald Welte811651e2017-08-05 15:25:06 +0200402 template PDU_GTPU ts_GTP1U_PDU(OCT1 msg_type, uint16_t seq, OCT4 teid, GTPU_IEs ies) := {
Harald Welte3af89482017-08-04 16:20:23 +0200403 /* N-PDU Number flag (PN): the GTP-U header contains a meaningful N-PDU Number field if the PN
404 * flag is set to 1. */
405 pn_bit := '0'B, /* we assume the encoder overwrites this if an optional part is given */
406 /* If the Sequence Number flag (S) is set to '1' the sequence number field is present and
407 * meaningful otherwise it is set to '0'. For GTP-U messages Echo Request, Echo Response,
408 * Error Indication and Supported Extension Headers Notification, the S flag shall be set to '1'. */
Harald Welte811651e2017-08-05 15:25:06 +0200409 s_bit := '1'B, /* we assume the encoder overwrites this if an optional part is given */
Harald Welte3af89482017-08-04 16:20:23 +0200410 /* Extension header presence */
411 e_bit := '0'B,
412 spare := '0'B,
413 /* Protocol Type flag (PT) shall be set to '1' in GTP */
414 pt := '1'B,
415 /* Version shall be set to decimal 1 ('001'). */
416 version := '001'B,
417 messageType := msg_type,
418 lengthf := 0, /* we assume encoder overwrites this */
419 teid := teid,
Harald Welte811651e2017-08-05 15:25:06 +0200420 opt_part := {
421 sequenceNumber := int2oct(seq, 2),
422 npduNumber := '00'O,
423 nextExtHeader := '00'O,
424 gTPU_extensionHeader_List := omit
425 },
Harald Welte3af89482017-08-04 16:20:23 +0200426 gtpu_IEs := ies
427 }
428
429 template Gtp1uUnitdata tr_GTPU_MsgType(template GtpPeer peer, template OCT1 msg_type, template OCT4 teid) := {
430 peer := peer,
431 gtpu := tr_GTP1U_PDU(msg_type, teid)
432 }
433
434
Harald Welte231b9412017-08-09 17:16:31 +0200435 /* template matching reception of GTP-U echo-request */
Harald Welte3af89482017-08-04 16:20:23 +0200436 template Gtp1uUnitdata tr_GTPU_PING(template GtpPeer peer) := tr_GTPU_MsgType(peer, echoRequest, '00000000'O);
437
Harald Welte231b9412017-08-09 17:16:31 +0200438 /* template matching reception of GTP-U GPDU */
439 template GTPU_IEs t_GPDU(template octetstring data) := {
440 g_PDU_IEs := {
441 data := data
442 }
443 }
444 template Gtp1uUnitdata tr_GTPU_GPDU(template GtpPeer peer, template OCT4 teid, template octetstring data := ?) := {
445 peer := peer,
446 gtpu := tr_GTP1U_PDU('FF'O, teid, t_GPDU(data))
447 }
448
Harald Welte3af89482017-08-04 16:20:23 +0200449 template GTPU_IEs ts_UEchoRespPDU(OCT1 restart_counter) := {
450 echoResponse_IEs := {
451 recovery_gtpu := {
452 type_gtpu := '00'O, /* we assume encoder fixes? */
453 restartCounter := restart_counter
454 },
455 private_extension_gtpu := omit
456 }
457 }
458
459 /* master template for sending a GTP-U echo response */
Harald Welte811651e2017-08-05 15:25:06 +0200460 template Gtp1uUnitdata ts_GTPU_PONG(GtpPeer peer, uint16_t seq, OCT1 rest_ctr) := {
Harald Welte3af89482017-08-04 16:20:23 +0200461 peer := peer,
Harald Welte811651e2017-08-05 15:25:06 +0200462 gtpu := ts_GTP1U_PDU(echoResponse, seq, '00000000'O, valueof(ts_UEchoRespPDU(rest_ctr)))
Harald Welte3af89482017-08-04 16:20:23 +0200463 }
464
Harald Welte811651e2017-08-05 15:25:06 +0200465 /* master template for sending a GTP-U user plane data */
466 template Gtp1uUnitdata ts_GTP1U_GPDU(GtpPeer peer, uint16_t seq, OCT4 teid, octetstring data) := {
467 peer := peer,
468 gtpu := ts_GTP1U_PDU('FF'O, seq, teid, { g_PDU_IEs := { data := data }})
469 }
Harald Welte3af89482017-08-04 16:20:23 +0200470
Harald Welte94ade362017-08-04 00:36:55 +0200471 /* Altstep implementing responses to any incoming echo requests */
472 altstep pingpong() runs on GT_CT {
473 var Gtp1cUnitdata ud;
Harald Welte3af89482017-08-04 16:20:23 +0200474 var Gtp1uUnitdata udu;
Harald Welte94ade362017-08-04 00:36:55 +0200475 [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
Harald Welte811651e2017-08-05 15:25:06 +0200476 var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
477 GTPC.send(ts_GTPC_PONG(ud.peer, seq, '00'O));
Harald Welte94ade362017-08-04 00:36:55 +0200478 repeat;
479 };
Harald Welte3af89482017-08-04 16:20:23 +0200480 [] GTPU.receive(tr_GTPU_PING(?)) -> value udu {
Harald Welte811651e2017-08-05 15:25:06 +0200481 var uint16_t seq := oct2int(udu.gtpu.opt_part.sequenceNumber);
482 GTPU.send(ts_GTPU_PONG(udu.peer, seq, '00'O));
Harald Welte3af89482017-08-04 16:20:23 +0200483 };
Harald Welte94ade362017-08-04 00:36:55 +0200484 [] T_default.timeout { setverdict(fail); };
485 }
486
Harald Welte811651e2017-08-05 15:25:06 +0200487 /* 'internet' in DNS encoding */
Harald Welteed097432017-08-13 13:28:49 +0200488 const octetstring c_ApnInternet := '08696E7465726E6574'O;
489 const octetstring c_ApnInet6 := '05696E657436'O;
490 const octetstring c_ApnInet46 := '06696E65743436'O;
Harald Welte94ade362017-08-04 00:36:55 +0200491
Harald Welte811651e2017-08-05 15:25:06 +0200492 /* return random integer between 0 and max */
493 function f_rnd_int(integer max) return integer {
494 return float2int(rnd()*int2float(max));
495 }
496
497 /* return random NSAPI */
498 function f_rnd_nsapi() return BIT4 {
499 return int2bit(f_rnd_int(16), 4);
500 }
501
502 /* return random TEI[DC] */
503 function f_rnd_tei() return OCT4 {
504 return int2oct(f_rnd_int(4294967296), 4);
505 }
506
Harald Welteed097432017-08-13 13:28:49 +0200507 /* return hexstring composed of random digits */
508 function f_rnd_hexstring(in integer len, in integer max := 15) return hexstring {
509 var integer i;
510 var hexstring ret := ''H;
511 for (i := 0; i < len; i := i + 1) {
512 ret := ret & int2hex(f_rnd_int(max), 1);
513 }
514 return ret;
515 }
516
517 /* return octetstring composed of random bytes */
518 function f_rnd_octstring(in integer len) return octetstring {
519 var integer i;
520 var octetstring ret := ''O;
521 for (i := 0; i < len; i := i + 1) {
522 ret := ret & int2oct(f_rnd_int(255), 1);
523 }
524 return ret;
525 }
526
527 function f_rnd_imsi(in hexstring prefix) return hexstring {
528 return prefix & f_rnd_hexstring(15 - lengthof(prefix), 9);
529 }
530
531 function f_rnd_msisdn(in octetstring prefix, integer len := 6) return octetstring {
532 return prefix & f_rnd_octstring(len - lengthof(prefix));
533 }
534
535
Harald Welte811651e2017-08-05 15:25:06 +0200536 /* define an (internal) representation of a PDP context */
537 template PdpContext t_DefinePDP(hexstring imsi, octetstring msisdn, octetstring apn,
538 EndUserAddress eua) := {
539 imsi := imsi,
540 msisdn := msisdn,
541 nsapi := f_rnd_nsapi(),
542 apn := apn,
Harald Welteed7a1772017-08-09 20:26:20 +0200543 pco_req := omit,
Harald Welte811651e2017-08-05 15:25:06 +0200544 eua := eua,
545 teid := f_rnd_tei(),
Harald Welte5438b9d2017-08-13 13:27:48 +0200546 teic := f_rnd_tei()
Harald Welte811651e2017-08-05 15:25:06 +0200547 }
548
549 /* send GTP-C for a given context and increment sequence number */
Harald Welte41575e92017-08-13 13:49:57 +0200550 function f_send_gtpc(in template Gtp1cUnitdata data) runs on GT_CT {
Harald Welte811651e2017-08-05 15:25:06 +0200551 GTPC.send(data);
Harald Welte5438b9d2017-08-13 13:27:48 +0200552 g_c_seq_nr := g_c_seq_nr + 1;
Harald Welte811651e2017-08-05 15:25:06 +0200553 }
554
555 /* send GTP-U for a given context and increment sequence number */
Harald Welte231b9412017-08-09 17:16:31 +0200556 function f_send_gtpu(inout PdpContext ctx, in octetstring data) runs on GT_CT {
Harald Welte5438b9d2017-08-13 13:27:48 +0200557 GTPU.send(ts_GTP1U_GPDU(g_peer_u, g_d_seq_nr, ctx.teid_remote, data));
558 g_d_seq_nr := g_d_seq_nr + 1;
Harald Welte811651e2017-08-05 15:25:06 +0200559 }
560
561 /* send a PDP context activation */
562 function f_pdp_ctx_act(inout PdpContext ctx) runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200563 var Gtp1cUnitdata ud;
Harald Welte94ade362017-08-04 00:36:55 +0200564 var default d;
565
566 log("sending CreatePDP");
Harald Welte41575e92017-08-13 13:49:57 +0200567 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 +0200568 ctx.teid, ctx.teic, ctx.nsapi, ctx.eua, ctx.apn,
Harald Welteed7a1772017-08-09 20:26:20 +0200569 g_sgsn_ip_c, g_sgsn_ip_u, ctx.msisdn, ctx.pco_req));
Harald Welte94ade362017-08-04 00:36:55 +0200570 T_default.start;
Harald Welte94ade362017-08-04 00:36:55 +0200571 d := activate(pingpong());
572 alt {
Harald Welte811651e2017-08-05 15:25:06 +0200573 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ctx.teic)) -> value ud {
574 var CreatePDPContextResponse cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
575 if (cpr.cause.causevalue == '80'O) {
576 ctx.teid_remote := cpr.teidDataI.teidDataI;
577 ctx.teic_remote := cpr.teidControlPlane.teidControlPlane;
Harald Welte231b9412017-08-09 17:16:31 +0200578 ctx.eua := cpr.endUserAddress;
Harald Welteed7a1772017-08-09 20:26:20 +0200579 ctx.pco_neg := cpr.protConfigOptions;
Harald Welte94ade362017-08-04 00:36:55 +0200580 setverdict(pass);
581 } else {
582 setverdict(fail);
583 }
584 }
585 }
586 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200587 T_default.stop;
Harald Welte94ade362017-08-04 00:36:55 +0200588 }
589
Harald Welte811651e2017-08-05 15:25:06 +0200590 function f_pdp_ctx_del(PdpContext ctx, template BIT1 teardown_ind) runs on GT_CT {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200591 var Gtp1cUnitdata ud;
592 var default d;
593
Harald Welte41575e92017-08-13 13:49:57 +0200594 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 +0200595 T_default.start;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200596 d := activate(pingpong());
597 alt {
Harald Welte811651e2017-08-05 15:25:06 +0200598 [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ctx.teic)) -> value ud {
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200599 if (ud.gtpc.gtpc_pdu.deletePDPContextResponse.cause.causevalue == '80'O) {
600 setverdict(pass);
601 } else {
602 setverdict(fail);
603 }
604 }
605 }
606 deactivate(d);
Harald Welte811651e2017-08-05 15:25:06 +0200607 T_default.stop;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200608 }
Harald Welte811651e2017-08-05 15:25:06 +0200609 /* IPv6 router solicitation fe80::2 -> ff02::2 from 02:88:b5:1f:25:59 */
610 const octetstring c_router_solicit := '6000000000103afffe800000000000000000000000000002ff02000000000000000000000000000285009f2b0000000001010288b51f2559'O;
611 /* IPv6 neighbor solicitation fe80::2 -> ff02::1:ff00:2 from 02:88:b5:1f:25:59 */
612 const octetstring c_neigh_solicit:= '6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff00000287009f9600000000fe80000000000000000000000000000201010288b51f2559'O;
Harald Weltef1e0d5a2017-08-05 08:51:22 +0200613
Harald Welte231b9412017-08-09 17:16:31 +0200614 /* template to generate a 'Prefix Information' ICMPv6 option */
615 template OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
616 prefixInformation := {
617 typeField := 3,
618 lengthIndicator := 8,
619 prefixLength := prefix_len,
620 reserved1 := '000000'B,
621 a_Bit := '0'B,
622 l_Bit := '0'B,
623 validLifetime := oct2int('FFFFFFFF'O),
624 preferredLifetime := oct2int('FFFFFFFF'O),
625 reserved2 := '00000000'O,
626 prefix := prefix
627 }
628 }
629
630 /* template for an ICMPv6 router solicitation */
631 template PDU_ICMPv6 ts_ICMPv6_RS := {
632 routerSolicitation := {
633 typeField := 133,
634 code := 0,
635 checksum := '0000'O,
636 reserved := '00000000'O,
637 /* TODO: do we need 'Source link-layer address' ? */
638 options := omit
639 }
640 }
641
642 /* template for an ICMPv6 router advertisement */
643 template PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
644 routerAdvertisement := {
645 typeField := 134,
646 code := 0,
647 checksum := '0000'O,
648 curHopLimit := ?,
649 reserved := '000000'B,
650 o_Bit := '0'B,
651 m_Bit := '0'B,
652 routerLifetime := oct2int('FFFF'O),
653 reachableTime := oct2int('FFFFFFFF'O),
654 retransTimer := oct2int('FFFFFFFF'O),
655 options := {
656 ts_ICMP6_OptPrefix(prefix, prefix_len)
657 }
658 }
659 }
660
661 template PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
662 neighborSolicitation := {
663 typeField := 135,
664 code := 0,
665 checksum := '0000'O,
666 reserved := '00000000'O,
667 targetAddress := target_addr,
668 /* TODO: do we need 'Source link-layer address' ? */
669 options := omit
670 }
671 }
672
673 /* derive ICMPv6 link-local address from lower 64bit of link_id */
674 /* template for receiving/matching an ICMPv6 'Prefix Information' option */
675 template OptionField tr_ICMP6_OptPrefix(template OCT16 prefix, template INT1 prefix_len) := {
676 prefixInformation := {
677 typeField := 3,
678 lengthIndicator := 4,
679 prefixLength := prefix_len,
680 reserved1 := ?,
681 a_Bit := ?,
682 l_Bit := ?,
683 validLifetime := ?,
684 preferredLifetime := ?,
685 reserved2 := ?,
686 prefix := prefix
687 }
688 }
689
690 /* template for receiving/matching an ICMPv6 router advertisement */
691 template PDU_ICMPv6 tr_ICMPv6_RA(template OCT16 prefix, template INT1 prefix_len) := {
692 routerAdvertisement := {
693 typeField := 134,
694 code := 0,
695 checksum := ?,
696 curHopLimit := ?,
697 reserved := ?,
698 o_Bit := '0'B,
699 m_Bit := '0'B,
700 routerLifetime := ?,
701 reachableTime := ?,
702 retransTimer := ?,
703 options := {
704 tr_ICMP6_OptPrefix(prefix, prefix_len)
705 }
706 }
707 }
708
709 /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
710 template IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
711 header := {
712 ver := 6,
713 trclass := 0,
714 flabel := 0,
715 plen := 0,
716 nexthead := nexthead,
717 hlim := hlim,
718 srcaddr := srcaddr,
719 dstaddr := dstaddr
720 },
721 ext_headers := omit,
722 payload := payload
723 }
724
725 function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
726 return 'FE80000000000000'O & substr(link_id, 8, 8);
727 }
728
729 /* Compute solicited-node multicast address as per RFC4291 2.7.1 */
730 function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
731 return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
732 }
733
734 /* generate and encode ICMPv6 router solicitation */
735 function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
736 const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
737 var OCT16 saddr := f_ipv6_link_local(link_id);
738
739 var octetstring tmp;
740 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
741 var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));
742
743 return f_IPv6_enc(ip6);
744 }
745
746 /* create ICMPv6 router solicitation deriving link-id from PDP Context EUA */
747 function f_icmpv6_rs_for_pdp(in PdpContext ctx) return octetstring {
748 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
749 return f_gen_icmpv6_router_solicitation(interface_id);
750 }
751
752 /* generate and encode ICMPv6 neighbor solicitation */
753 function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
754 var octetstring tmp;
755 tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
756 var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
757 return f_IPv6_enc(ip6);
758 }
759
760 /* generate and encode ICMPv6 neighbor solicitation for PDP Context */
761 function f_gen_icmpv6_neigh_solicit_for_pdp(in PdpContext ctx) return octetstring {
762 var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
763 var OCT16 link_local := f_ipv6_link_local(interface_id);
764 var OCT16 daddr := f_ipv6_sol_node_mcast(link_local);
765
766 return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local);
767 }
768
769 /* wait for GGSN to send us an ICMPv6 router advertisement */
770 function f_wait_rtr_adv(PdpContext ctx) runs on GT_CT {
771 var Gtp1uUnitdata ud;
772 T_default.start;
773 alt {
774 //'6???????????3aff'O
775 [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
776 var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
777 var IPv6_packet ip6 := f_IPv6_dec(gpdu);
778 if (ip6.header.ver != 6 or ip6.header.nexthead != 58 or ip6.header.hlim != 255) {
779 repeat;
780 }
781 var PDU_ICMPv6 icmp6 := f_dec_PDU_ICMPv6(ip6.payload);
782 if (not match(icmp6, tr_ICMPv6_RA(?, 64))) {
783 repeat;
784 }
785 ctx.ip6_prefix := icmp6.routerAdvertisement.options[0].prefixInformation.prefix;
786 log("RA with /64 prefix ", ctx.ip6_prefix);
787 }
788 [] GTPU.receive(tr_GTPU_GPDU(?, ?)) { repeat; }
789 [] GTPU.receive { setverdict(fail); }
790 [] T_default.timeout { setverdict(fail); }
791 }
792 T_default.stop;
793 }
794
Harald Welteed7a1772017-08-09 20:26:20 +0200795 testcase TC_pdp6_act_deact() runs on GT_CT {
Harald Welte94ade362017-08-04 00:36:55 +0200796 f_init();
Harald Welte231b9412017-08-09 17:16:31 +0200797
Harald Welteed097432017-08-13 13:28:49 +0200798 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welte811651e2017-08-05 15:25:06 +0200799 f_pdp_ctx_act(ctx);
Harald Welteed7a1772017-08-09 20:26:20 +0200800 f_pdp_ctx_del(ctx, '1'B);
801 }
802
803 testcase TC_pdp6_act_deact_pcodns() runs on GT_CT {
804 f_init();
805
Harald Welteed097432017-08-13 13:28:49 +0200806 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200807 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
808 f_pdp_ctx_act(ctx);
809 f_pdp_ctx_del(ctx, '1'B);
810 }
811
812 testcase TC_pdp6_act_deact_icmp6() runs on GT_CT {
813 f_init();
814
Harald Welteed097432017-08-13 13:28:49 +0200815 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200816 ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
817 f_pdp_ctx_act(ctx);
Harald Welte231b9412017-08-09 17:16:31 +0200818
819 //f_send_gtpu(ctx, c_router_solicit);
820 //f_send_gtpu(ctx, c_neigh_solicit);
821
822 f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
823 f_wait_rtr_adv(ctx);
824 f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
825
Harald Welte811651e2017-08-05 15:25:06 +0200826 f_pdp_ctx_del(ctx, '1'B);
Harald Welte94ade362017-08-04 00:36:55 +0200827 }
828
Harald Welteed7a1772017-08-09 20:26:20 +0200829 testcase TC_pdp4_act_deact() runs on GT_CT {
830 f_init();
Harald Welteed097432017-08-13 13:28:49 +0200831 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200832 f_pdp_ctx_act(ctx);
833 f_pdp_ctx_del(ctx, '1'B);
834 }
835
836 testcase TC_pdp4_act_deact_ipcp() runs on GT_CT {
837 f_init();
Harald Welteed097432017-08-13 13:28:49 +0200838 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200839 f_pdp_ctx_act(ctx);
840 f_pdp_ctx_del(ctx, '1'B);
841 }
842
843 testcase TC_pdp4_act_deact_pcodns() runs on GT_CT {
844 f_init();
Harald Welteed097432017-08-13 13:28:49 +0200845 var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
Harald Welteed7a1772017-08-09 20:26:20 +0200846 f_pdp_ctx_act(ctx);
847 f_pdp_ctx_del(ctx, '1'B);
848 }
849
Harald Welte94ade362017-08-04 00:36:55 +0200850 control {
Harald Welteed7a1772017-08-09 20:26:20 +0200851 execute(TC_pdp4_act_deact());
852 execute(TC_pdp4_act_deact_ipcp());
853 execute(TC_pdp4_act_deact_pcodns());
854
855 execute(TC_pdp6_act_deact());
856 execute(TC_pdp6_act_deact_pcodns());
857 execute(TC_pdp6_act_deact_icmp6());
Harald Welte94ade362017-08-04 00:36:55 +0200858 }
Harald Welte379d45a2017-08-03 09:55:15 +0200859}