blob: 4368a8a759de725f1055685c31d76bc24e181653 [file] [log] [blame]
Harald Weltec69cf4e2018-02-17 20:57:02 +01001module GTP_Emulation {
2
3import from IPL4asp_Types all;
4import from General_Types all;
5import from Osmocom_Types all;
6import from GTPC_Types all;
7import from GTPU_Types all;
8import from GTP_CodecPort all;
9import from GTP_CodecPort_CtrlFunct all;
10
11/***********************************************************************
12 * Main Emulation Component
13 ***********************************************************************/
14
15const integer GTP0_PORT := 3386;
16const integer GTP1C_PORT := 2123;
17const integer GTP1U_PORT := 2152;
18
19type record GtpEmulationCfg {
20 HostName gtpc_bind_ip,
21 PortNumber gtpc_bind_port,
22 HostName gtpu_bind_ip,
23 PortNumber gtpu_bind_port,
24 boolean sgsn_role
25};
26
27type component GTP_Emulation_CT {
28 /* Communication with underlying GTP CodecPort */
29 port GTPC_PT GTPC;
30 port GTPU_PT GTPU;
31
32 /* Communication with Clients */
33 port GTPEM_PT CLIENT;
34 port GTPEM_PROC_PT CLIENT_PROC;
35
36 /* Configuration by the user */
37 var GtpEmulationCfg g_gtp_cfg;
38
39 /* State */
40 var integer g_gtpc_id, g_gtpu_id;
41 var OCT1 g_restart_ctr;
42 var uint16_t g_c_seq_nr, g_u_seq_nr;
43 var TidTableRec TidTable[16];
44 var ImsiTableRec ImsiTable[16];
45};
46
47type record TidTableRec {
48 OCT4 teid,
49 GTP_ConnHdlr vc_conn
50};
51
52type record ImsiTableRec {
53 hexstring imsi,
54 GTP_ConnHdlr vc_conn
55};
56
57private function f_comp_by_teid(OCT4 teid) runs on GTP_Emulation_CT return GTP_ConnHdlr {
58 var integer i;
59 for (i := 0; i < sizeof(TidTable); i := i+1) {
60 if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
61 return TidTable[i].vc_conn;
62 }
63 }
64 setverdict(fail, "No Component for TEID ", teid);
Daniel Willmanne4ff5372018-07-05 17:35:03 +020065 mtc.stop;
Harald Weltec69cf4e2018-02-17 20:57:02 +010066}
67
68private function f_comp_by_imsi(hexstring imsi) runs on GTP_Emulation_CT return GTP_ConnHdlr {
69 var integer i;
70 for (i := 0; i < sizeof(ImsiTable); i := i+1) {
71 if (isbound(ImsiTable[i].imsi) and ImsiTable[i].imsi == imsi) {
72 return ImsiTable[i].vc_conn;
73 }
74 }
75 setverdict(fail, "No Component for IMSI ", imsi);
Daniel Willmanne4ff5372018-07-05 17:35:03 +020076 mtc.stop;
Harald Weltec69cf4e2018-02-17 20:57:02 +010077}
78
79private function f_tid_tbl_add(OCT4 teid, GTP_ConnHdlr vc_conn) runs on GTP_Emulation_CT {
80 var integer i;
81 for (i := 0; i < sizeof(TidTable); i := i+1) {
82 if (not isbound(TidTable[i].teid)) {
83 TidTable[i].teid := teid;
84 TidTable[i].vc_conn := vc_conn;
85 return;
86 }
87 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +020088 testcase.stop("No Space in TidTable for ", teid);
Harald Weltec69cf4e2018-02-17 20:57:02 +010089}
90
91private function f_imsi_tbl_add(hexstring imsi, GTP_ConnHdlr vc_conn) runs on GTP_Emulation_CT {
92 var integer i;
93 for (i := 0; i < sizeof(ImsiTable); i := i+1) {
94 if (not isbound(ImsiTable[i].imsi)) {
95 ImsiTable[i].imsi := imsi;
96 ImsiTable[i].vc_conn := vc_conn;
97 return;
98 }
99 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200100 testcase.stop("No Space in IMSI Table for ", imsi);
Harald Weltec69cf4e2018-02-17 20:57:02 +0100101}
102
103function f_gtpc_extract_imsi(PDU_GTPC gtp) return template (omit) hexstring {
104 if (ischosen(gtp.gtpc_pdu.createPDPContextRequest)) {
105 return gtp.gtpc_pdu.createPDPContextRequest.imsi.digits;
106 } else if (ischosen(gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestSGSN)) {
107 return gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestSGSN.imsi.digits;
108 } else if (ischosen(gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestGGSN)) {
109 return gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestGGSN.imsi.digits;
110 } else if (ischosen(gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestCGW)) {
111 return gtp.gtpc_pdu.updatePDPContextRequest.updatePDPContextRequestCGW.imsi.digits;
112 } else if (ischosen(gtp.gtpc_pdu.pdu_NotificationRequest)) {
113 return gtp.gtpc_pdu.pdu_NotificationRequest.imsi.digits;
114 } else if (ischosen(gtp.gtpc_pdu.sendRouteingInformationForGPRSRequest)) {
115 return gtp.gtpc_pdu.sendRouteingInformationForGPRSRequest.imsi.digits;
116 } else if (ischosen(gtp.gtpc_pdu.sendRouteingInformationForGPRSResponse)) {
117 return gtp.gtpc_pdu.sendRouteingInformationForGPRSResponse.imsi.digits;
118 } else if (ischosen(gtp.gtpc_pdu.failureReportRequest)) {
119 return gtp.gtpc_pdu.failureReportRequest.imsi.digits;
120 } else if (ischosen(gtp.gtpc_pdu.noteMS_GPRSPresentRequest)) {
121 return gtp.gtpc_pdu.noteMS_GPRSPresentRequest.imsi.digits;
122 } else if (ischosen(gtp.gtpc_pdu.identificationResponse) ){
123 return gtp.gtpc_pdu.identificationResponse.imsi.digits;
124 } else if (ischosen(gtp.gtpc_pdu.sgsn_ContextRequest)) {
125 return gtp.gtpc_pdu.sgsn_ContextRequest.imsi.digits;
126 } else if (ischosen(gtp.gtpc_pdu.sgsn_ContextResponse)) {
127 return gtp.gtpc_pdu.sgsn_ContextResponse.imsi.digits;
128 } else if (ischosen(gtp.gtpc_pdu.forwardRelocationRequest)) {
129 return gtp.gtpc_pdu.forwardRelocationRequest.imsi.digits;
130 } else if (ischosen(gtp.gtpc_pdu.relocationCancelRequest)) {
131 return gtp.gtpc_pdu.relocationCancelRequest.imsi.digits;
132 } else if (ischosen(gtp.gtpc_pdu.uERegistrationQueryRequest)) {
133 return gtp.gtpc_pdu.uERegistrationQueryRequest.imsi.digits;
134 } else if (ischosen(gtp.gtpc_pdu.uERegistrationQueryResponse)) {
135 return gtp.gtpc_pdu.uERegistrationQueryResponse.imsi.digits;
136 } else if (ischosen(gtp.gtpc_pdu.mBMSNotificationRequest)) {
137 return gtp.gtpc_pdu.mBMSNotificationRequest.imsi.digits;
138 } else if (ischosen(gtp.gtpc_pdu.createMBMSContextRequest)) {
139 return gtp.gtpc_pdu.createMBMSContextRequest.imsi.digits;
140 } else if (ischosen(gtp.gtpc_pdu.deleteMBMSContextRequest)) {
141 return gtp.gtpc_pdu.deleteMBMSContextRequest.imsi.digits;
142 } else if (ischosen(gtp.gtpc_pdu.mS_InfoChangeNotificationRequest)) {
143 return gtp.gtpc_pdu.mS_InfoChangeNotificationRequest.imsi.digits;
144 } else if (ischosen(gtp.gtpc_pdu.mS_InfoChangeNotificationResponse)) {
145 return gtp.gtpc_pdu.mS_InfoChangeNotificationResponse.imsi.digits;
146 } else {
147 return omit;
148 }
149}
150
151private function f_init(GtpEmulationCfg cfg) runs on GTP_Emulation_CT {
152 var Result res;
153
154 map(self:GTPC, system:GTPC);
155 res := GTP_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, cfg.gtpc_bind_ip,
156 cfg.gtpc_bind_port, {udp:={}});
157 g_gtpc_id := res.connId;
158
159 map(self:GTPU, system:GTPU);
160 res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, cfg.gtpu_bind_ip,
161 cfg.gtpu_bind_port, {udp:={}});
162 g_gtpu_id := res.connId;
163
164 g_restart_ctr := f_rnd_octstring(1);
165 g_c_seq_nr := f_rnd_int(65535);
166 g_u_seq_nr := f_rnd_int(65535);
167 g_gtp_cfg := cfg;
168}
169
170function main(GtpEmulationCfg cfg) runs on GTP_Emulation_CT {
171 var Gtp1cUnitdata g1c_ud;
172 var Gtp1uUnitdata g1u_ud;
173 var GTP_ConnHdlr vc_conn;
174 var hexstring imsi;
175 var OCT4 teid;
176
177 f_init(cfg);
178
179 while (true) {
180 alt {
181 /* route inbound GTP-C based on IMSI or TEID */
182 [] GTPC.receive(Gtp1cUnitdata:?) -> value g1c_ud {
183 var template hexstring imsi_t := f_gtpc_extract_imsi(g1c_ud.gtpc);
184 if (isvalue(imsi_t)) {
185 vc_conn := f_comp_by_imsi(valueof(imsi_t));
Pau Espin Pedrol20e16c12018-07-10 18:38:17 +0200186 CLIENT.send(g1c_ud) to vc_conn;
187 } else if(g1c_ud.gtpc.teid != int2oct(0, 4)) {
Harald Weltec69cf4e2018-02-17 20:57:02 +0100188 vc_conn := f_comp_by_teid(g1c_ud.gtpc.teid);
Pau Espin Pedrol20e16c12018-07-10 18:38:17 +0200189 CLIENT.send(g1c_ud) to vc_conn;
190 } else {
191 /* Send to all clients */
192 var integer i;
193 for (i := 0; i < sizeof(TidTable); i := i+1) {
194 if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
195 CLIENT.send(g1c_ud) to TidTable[i].vc_conn;
196 }
197 }
Harald Weltec69cf4e2018-02-17 20:57:02 +0100198 }
Harald Weltec69cf4e2018-02-17 20:57:02 +0100199 }
200 [] GTPU.receive(Gtp1uUnitdata:?) -> value g1u_ud {
201 vc_conn := f_comp_by_teid(g1u_ud.gtpu.teid);
202 CLIENT.send(g1u_ud) to vc_conn;
203 }
204
205 /* transparently forward any GTP-C / GTP-U from clients to peer[s] */
206 [] CLIENT.receive(Gtp1cUnitdata:?) -> value g1c_ud sender vc_conn {
207 GTPC.send(g1c_ud);
208 }
209 [] CLIENT.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn {
210 GTPU.send(g1u_ud);
211 }
212
213
214 [] CLIENT_PROC.getcall(GTPEM_register_imsi:{?}) -> param(imsi) sender vc_conn {
215 f_imsi_tbl_add(imsi, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200216 CLIENT_PROC.reply(GTPEM_register_imsi:{imsi}) to vc_conn;
Harald Weltec69cf4e2018-02-17 20:57:02 +0100217 }
218
219 [] CLIENT_PROC.getcall(GTPEM_register_teid:{?}) -> param(teid) sender vc_conn {
220 f_tid_tbl_add(teid, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200221 CLIENT_PROC.reply(GTPEM_register_teid:{teid}) to vc_conn;
Harald Weltec69cf4e2018-02-17 20:57:02 +0100222 }
223
224 }
225 }
226}
227
228
229/***********************************************************************
230 * Interaction between Main and Client Components
231 ***********************************************************************/
232type port GTPEM_PT message {
233 inout Gtp1cUnitdata, Gtp1uUnitdata;
234} with { extension "internal" };
235
236signature GTPEM_register_imsi(hexstring imsi);
237signature GTPEM_register_teid(OCT4 teid);
238
239type port GTPEM_PROC_PT procedure {
240 inout GTPEM_register_imsi, GTPEM_register_teid;
241} with { extension "internal" };
242
243/***********************************************************************
244 * Client Compoennt
245 ***********************************************************************/
246
247type component GTP_ConnHdlr {
248 port GTPEM_PT GTP;
249 port GTPEM_PROC_PT GTP_PROC;
250};
251
252function f_gtp_register_imsi(hexstring imsi) runs on GTP_ConnHdlr {
253 GTP_PROC.call(GTPEM_register_imsi:{imsi}) {
254 [] GTP_PROC.getreply(GTPEM_register_imsi:{imsi});
255 }
256}
257
258function f_gtp_register_teid(OCT4 teid) runs on GTP_ConnHdlr {
259 GTP_PROC.call(GTPEM_register_teid:{teid}) {
260 [] GTP_PROC.getreply(GTPEM_register_teid:{teid});
261 }
262}
263
264}