pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40744?usp=email )
Change subject: Split GTPv1U out of GTPv2_Emulation ......................................................................
Split GTPv1U out of GTPv2_Emulation
GTPv1U and GTPv2C are 2 different protocols, working on 2 different ports, on 2 different sockets. Hence, it makes no sense to put them together, since some tests may want to use only the control-plane, others may want to use the user-plane, etc. Morevoer, GTPv1U can be used together with both GTPv2C anf GTPv1C.
This commit also fixes the confusion where TEIC and TEID were not properly separated in GTPv2_Emulation.
Change-Id: Ia45307107753294c6761cb588f0ab769821eb213 --- M epdg/EPDG_Tests.ttcn M epdg/gen_links.sh A library/GTPv1U_Emulation.ttcn M library/GTPv2_Emulation.ttcn M mme/MME_Tests.ttcn M mme/gen_links.sh M mme/regen_makefile.sh M pgw/PGW_Tests.cfg M pgw/PGW_Tests.ttcn M pgw/gen_links.sh 10 files changed, 500 insertions(+), 262 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve
diff --git a/epdg/EPDG_Tests.ttcn b/epdg/EPDG_Tests.ttcn index 61476e2..f67fc2c 100644 --- a/epdg/EPDG_Tests.ttcn +++ b/epdg/EPDG_Tests.ttcn @@ -24,9 +24,10 @@ import from DIAMETER_ts29_273_Templates all; import from DIAMETER_Emulation all;
-import from GTPv1U_CodecPort all; import from GTPU_Types all; +import from GTPv1U_CodecPort all; import from GTPv1U_Templates all; +import from GTPv1U_Emulation all;
import from GTPv2_Types all; import from GTPv2_Templates all; @@ -90,7 +91,10 @@ port IPA_CTRL_PT GSUP_IPA_EVENT;
var GTPv2_Emulation_CT vc_GTP2; - port GTP2EM_PT TEID0; + port GTP2EM_PT TEIC0; + + var GTPv1U_Emulation_CT vc_GTP1U; + port GTP1UEM_PT TEID0;
port Coord_PT COORD;
@@ -133,7 +137,7 @@ } }
-type component EPDG_ConnHdlr extends DIAMETER_ConnHdlr, GSUP_ConnHdlr, GTP2_ConnHdlr { +type component EPDG_ConnHdlr extends DIAMETER_ConnHdlr, GSUP_ConnHdlr, GTP2_ConnHdlr, GTP1U_ConnHdlr { var EPDG_ConnHdlrPars g_pars;
port DIAMETER_Conn_PT SWx; @@ -298,22 +302,32 @@ f_sleep(int2float(mp_diam_watchdog_initial_wait_sec)); }
-private function f_init_gtp(charstring id) runs on MTC_CT { +private function f_init_gtp2c(charstring id) runs on MTC_CT { var Gtp2EmulationCfg cfg := { gtpc_bind_ip := mp_s2b_local_ip, gtpc_bind_port := mp_s2b_local_port, gtpc_remote_ip := mp_s2b_remote_ip, gtpc_remote_port := mp_s2b_remote_port, + sgw_role := false + }; + + vc_GTP2 := GTPv2_Emulation_CT.create(id & "-GTPv2C"); + map(vc_GTP2:GTP2C, system:GTP2C); + connect(vc_GTP2:TEIC0, self:TEIC0); + vc_GTP2.start(GTPv2_Emulation.main(cfg)); +} + +private function f_init_gtp1u(charstring id) runs on MTC_CT { + var Gtp1uEmulationCfg cfg := { gtpu_bind_ip := mp_upf_gtpu_local_ip, gtpu_bind_port := GTP1U_PORT, - sgw_role := false, use_gtpu_daemon := false /* TODO: maybe use, set to true */ };
- vc_GTP2 := GTPv2_Emulation_CT.create(id & "-GTPV2"); - map(vc_GTP2:GTP2C, system:GTP2C); - connect(vc_GTP2:TEID0, self:TEID0); - vc_GTP2.start(GTPv2_Emulation.main(cfg)); + vc_GTP1U := GTPv1U_Emulation_CT.create(id & "-GTPv1U"); + map(vc_GTP1U:GTP1U, system:GTP1U); + connect(vc_GTP1U:TEID0, self:TEID0); + vc_GTP1U.start(GTPv1U_Emulation.main(cfg)); }
private function f_init(float t_guard := 40.0) runs on MTC_CT { @@ -323,7 +337,8 @@
f_init_gsup(testcasename()); f_init_diameter(testcasename()); - f_init_gtp(testcasename()); + f_init_gtp2c(testcasename()); + f_init_gtp1u(testcasename()); }
private type function void_fn(charstring id) runs on EPDG_ConnHdlr; @@ -352,9 +367,12 @@ connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT); connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
- /* GTP2 */ + /* GTP2C */ connect(vc_conn:GTP2, vc_GTP2:CLIENT); connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC); + /* GTP1U */ + connect(vc_conn:GTP1U, vc_GTP1U:CLIENT); + connect(vc_conn:GTP1U_PROC, vc_GTP1U:CLIENT_PROC);
/* SWx */ vc_conn_swx := DIAMETER_ConnHdlr_CT.create(id); @@ -704,8 +722,8 @@ }*/
/* allocate + register TEID-C on local side */ - g_pars.teic_local := f_gtp2_allocate_teid(); - g_pars.bearer.teid_local := g_pars.teic_local; + g_pars.teic_local := f_gtp2_allocate_teic(); + g_pars.bearer.teid_local := f_gtp1u_allocate_teid(); }
/* ePDG Creates session at the PGW. PGW sends Diameter s6b AAR + AAA. */ @@ -862,18 +880,18 @@ } private function f_GTP1U_send(octetstring payload) runs on EPDG_ConnHdlr { var Gtp1uPeer peer := valueof(ts_GtpPeerU(f_inet_addr(g_pars.bearer.gtpu_addr_remote))); - GTP2.send(ts_GTP1U_GPDU(peer, omit /*opt_part*/, g_pars.bearer.teid_remote, payload)); + GTP1U.send(ts_GTP1U_GPDU(peer, omit /*opt_part*/, g_pars.bearer.teid_remote, payload)); } private function f_GTP1U_echo_ping_pong(uint16_t seq_nr := 0) runs on EPDG_ConnHdlr { var Gtp1uPeer peer := valueof(ts_GtpPeerU(f_inet_addr(g_pars.bearer.gtpu_addr_remote))); - GTP2.send(ts_GTPU_PING(peer, seq := seq_nr)); - GTP2.receive(tr_GTPU_PONG(peer)); + GTP1U.send(ts_GTPU_PING(peer, seq := seq_nr)); + GTP1U.receive(tr_GTPU_PONG(peer)); } private altstep as_GTPU_rx_icmp4(template (present) PDU_ICMP expected := ?) runs on EPDG_ConnHdlr { var Gtp1uUnitdata rx_msg; var template (value) Gtp1uPeer peer := ts_GtpPeerU(f_inet_addr(g_pars.bearer.gtpu_addr_remote));
- [] GTP2.receive(tr_GTPU_GPDU(peer, g_pars.bearer.teid_local)) -> value rx_msg { + [] GTP1U.receive(tr_GTPU_GPDU(peer, g_pars.bearer.teid_local)) -> value rx_msg { /*TODO: verify gtpu txseq: if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) { setverdict(fail); @@ -890,7 +908,7 @@ repeat; } } - [] GTP2.receive(Gtp1uUnitdata:?) -> value rx_msg { + [] GTP1U.receive(Gtp1uUnitdata:?) -> value rx_msg { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP msg rx: ", rx_msg)); } } @@ -1298,7 +1316,7 @@ private function f_TC_upf_echo_req(charstring id) runs on EPDG_ConnHdlr { f_initial_attach(); /* Dispatch Echo Resp to this component: */ - f_gtp2_register_teid('00000000'O); + f_gtp1u_register_teid('00000000'O); f_GTP1U_echo_ping_pong(seq_nr := 0); /* Send one again, to validate it works several times: */ f_GTP1U_echo_ping_pong(seq_nr := 1); @@ -1316,7 +1334,7 @@ private function f_TC_mt_ipv4_echo_req(charstring id) runs on EPDG_ConnHdlr { f_initial_attach(); /* Dispatch Echo Resp to this component: */ - f_gtp2_register_teid('00000000'O); + f_gtp1u_register_teid('00000000'O); var octetstring echo_req := f_gen_icmpv4_echo(f_inet_addr(mp_upf_gtpu_local_ip), f_inet_addr(g_pars.ue_ip)); f_GTP1U_send(echo_req); as_GTPU_rx_icmp4((tr_ICMPv4_ERP, tr_ICMPv4_DU)); diff --git a/epdg/gen_links.sh b/epdg/gen_links.sh index 889cb9a..d41e2e1 100755 --- a/epdg/gen_links.sh +++ b/epdg/gen_links.sh @@ -59,7 +59,7 @@ FILES+="IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp " FILES+="PCO_Types.ttcn GSUP_Types.ttcn GSUP_Templates.ttcn GSUP_Emulation.ttcn " -FILES+="GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1U_Templates.ttcn " +FILES+="GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1U_Templates.ttcn GTPv1U_Emulation.ttcn " FILES+="GTPv2_PrivateExtensions.ttcn GTPv2_Templates.ttcn " FILES+="GTPv2_CodecPort.ttcn GTPv2_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunct.ttcn GTPv2_Emulation.ttcn " FILES+="ICMP_Templates.ttcn " diff --git a/library/GTPv1U_Emulation.ttcn b/library/GTPv1U_Emulation.ttcn new file mode 100644 index 0000000..7c031b7 --- /dev/null +++ b/library/GTPv1U_Emulation.ttcn @@ -0,0 +1,361 @@ +/* GTPv1U Emulation in TTCN-3 + * + * (C) 2018-2020 Harald Welte laforge@gnumonks.org + * (C) 2025 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * All rights reserved. + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +module GTPv1U_Emulation { + +import from IPL4asp_Types all; +import from General_Types all; +import from Osmocom_Types all; +import from GTPU_Types all; +import from GTPv1U_CodecPort all; +import from GTPv1U_CodecPort_CtrlFunct all; + +import from SCTP_Templates all; +import from UECUPS_Types all; +import from UECUPS_CodecPort all; +import from UECUPS_CodecPort_CtrlFunct all; + +/*********************************************************************** + * Main Emulation Component + ***********************************************************************/ + +modulepar { + charstring mp_uecups_host := "127.0.0.1"; + integer mp_uecups_port := UECUPS_SCTP_PORT; +}; + +const integer GTP1U_PORT := 2152; + +type record Gtp1uEmulationCfg { + HostName gtpu_bind_ip optional, + IPL4asp_Types.PortNumber gtpu_bind_port optional, + boolean use_gtpu_daemon +}; + +type component GTPv1U_Emulation_CT { + /* Communication with underlying GTP CodecPort */ + port GTPU_PT GTP1U; + + /* Control port to GTP-U Daemon */ + port UECUPS_CODEC_PT UECUPS; + + /* Communication with Clients */ + port GTP1UEM_PT TEID0; + port GTP1UEM_PT CLIENT; + port GTP1UEM_PROC_PT CLIENT_PROC; + + /* Configuration by the user */ + var Gtp1uEmulationCfg g_gtp1u_cfg; + + /* State */ + var integer g_gtp1u_id := -1; + var OCT1 g_restart_ctr; + var uint16_t g_c_seq_nr; + var TidTableRec TidTable[256]; + var PidTableRec PidTable[256]; + + var integer g_uecups_conn_id := -1; +}; + +/* local TEID <-> ConnHdlr mapping */ +type record TidTableRec { + OCT4 teid, + GTP1U_ConnHdlr vc_conn +}; + +/* pid <-> ConnHdlr mapping (for UECUPS process termination indication) */ +type record PidTableRec { + /* process ID of the running process */ + integer pid, + /* component that started it */ + GTP1U_ConnHdlr vc_conn +}; + +private function f_teid_known(OCT4 teid) runs on GTPv1U_Emulation_CT return boolean { + var integer i; + for (i := 0; i < sizeof(TidTable); i := i+1) { + if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) { + return true; + } + } + return false; +} + +private function f_comp_by_teid(OCT4 teid) runs on GTPv1U_Emulation_CT return GTP1U_ConnHdlr { + var integer i; + for (i := 0; i < sizeof(TidTable); i := i+1) { + if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) { + return TidTable[i].vc_conn; + } + } + setverdict(fail, "No Component for TEID ", teid); + mtc.stop; +} + +private function f_comp_by_pid(integer pid) runs on GTPv1U_Emulation_CT return GTP1U_ConnHdlr { + var integer i; + for (i := 0; i < sizeof(PidTable); i := i+1) { + if (isbound(PidTable[i].pid) and PidTable[i].pid == pid) { + /* fixme: remove */ + return PidTable[i].vc_conn; + } + } + setverdict(fail, "No Component for PID ", pid); + mtc.stop; +} + +private function f_tid_tbl_add(OCT4 teid, GTP1U_ConnHdlr vc_conn) runs on GTPv1U_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(TidTable); i := i+1) { + if (not isbound(TidTable[i].teid)) { + TidTable[i].teid := teid; + TidTable[i].vc_conn := vc_conn; + return; + } + } + testcase.stop("No Space in TidTable for ", teid); +} + +private function f_pid_tbl_add(integer pid, GTP1U_ConnHdlr vc_conn) runs on GTPv1U_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(PidTable); i := i+1) { + if (not isbound(PidTable[i].pid)) { + PidTable[i].pid := pid; + PidTable[i].vc_conn := vc_conn; + return; + } + } + testcase.stop("No Space in PID Table for ", pid); +} + + +/* allocate an unused local teid */ +private function f_alloc_teid() runs on GTPv1U_Emulation_CT return OCT4 { + var OCT4 teid; + var integer i, j; + for (i := 0; i < 100; i := i+1) { + teid := f_rnd_octstring(4); + for (j := 0; j < sizeof(TidTable); j := j+1) { + if (isbound(TidTable) and TidTable[i].teid == teid) { + continue; + } + } + /* we iterated over all entries and found no match: great! */ + return teid; + } + testcase.stop("Cannot find unused TEID after ", i, " attempts"); +} + +function tr_UECUPS_RecvFrom_R(template PDU_UECUPS msg) +runs on GTPv1U_Emulation_CT return template UECUPS_RecvFrom { + var template UECUPS_RecvFrom mrf := { + connId := g_uecups_conn_id, + remName := ?, + remPort := ?, + locName := ?, + locPort := ?, + msg := msg + } + return mrf; +} + + +private function f_uecups_xceive(template (value) PDU_UECUPS tx, + template PDU_UECUPS rx_t := ?, float time_out := 10.0) +runs on GTPv1U_Emulation_CT return PDU_UECUPS { + timer T := time_out; + var UECUPS_RecvFrom mrf; + + UECUPS.send(t_UECUPS_Send(g_uecups_conn_id, tx)); + T.start; + alt { + [] UECUPS.receive(tr_UECUPS_RecvFrom_R(rx_t)) -> value mrf { } + [] UECUPS.receive(tr_SctpAssocChange) { repeat; } + [] UECUPS.receive(tr_SctpPeerAddrChange) { repeat; } + [] T.timeout { + setverdict(fail, "Timeout waiting for ", rx_t); + mtc.stop; + } + } + return mrf.msg; +} + +private function f_init(Gtp1uEmulationCfg cfg) runs on GTPv1U_Emulation_CT { + var Result res; + + g_restart_ctr := f_rnd_octstring(1); + g_c_seq_nr := f_rnd_int(65535); + g_gtp1u_cfg := cfg; + + if (g_gtp1u_cfg.use_gtpu_daemon) { + map(self:UECUPS, system:UECUPS); + res := UECUPS_CodecPort_CtrlFunct.f_IPL4_connect(UECUPS, mp_uecups_host, mp_uecups_port, "", -1, -1, + { sctp := valueof(ts_SctpTuple) }); + if (not ispresent(res.connId)) { + setverdict(fail, "Could not connect UECUPS socket, check your configuration"); + testcase.stop; + } + g_uecups_conn_id := res.connId; + /* clear all tunnel state in the daemon at start */ + f_uecups_xceive({reset_all_state := {}}, {reset_all_state_res:=?}, 30.0); + /* make sure we always pass incoming UECUPS indications whenever receiving fom the UECUPS port */ + activate(as_uecups_ind()); + } else if (isvalue(cfg.gtpu_bind_ip) and isvalue(cfg.gtpu_bind_port)) { + map(self:GTP1U, system:GTP1U); + res := GTPv1U_CodecPort_CtrlFunct.f_GTPU_listen(GTP1U, cfg.gtpu_bind_ip, + cfg.gtpu_bind_port, {udp:={}}); + g_gtp1u_id := res.connId; + } +} + +private altstep as_uecups_ind() runs on GTPv1U_Emulation_CT { +var UECUPS_RecvFrom rx; +var GTP1U_ConnHdlr vc_conn; +/* handle incoming program_term_ind; dispatch to whatever component started the process */ +[] UECUPS.receive(tr_UECUPS_RecvFrom_R({program_term_ind:=?})) -> value rx { + vc_conn := f_comp_by_pid(rx.msg.program_term_ind.pid); + CLIENT.send(rx.msg.program_term_ind) to vc_conn; + /* FIXME: remove from table */ + repeat; + } +} + +function main(Gtp1uEmulationCfg cfg) runs on GTPv1U_Emulation_CT { + var Gtp1uUnitdata g1u_ud; + var GTP1U_ConnHdlr vc_conn; + var OCT4 teid; + var PDU_UECUPS rx_uecups; + var UECUPS_CreateTun gtc; + var UECUPS_DestroyTun gtd; + var UECUPS_StartProgram sprog; + + f_init(cfg); + + while (true) { + alt { + [] GTP1U.receive(Gtp1uUnitdata:?) -> value g1u_ud { + if (f_teid_known(g1u_ud.gtpu.teid)) { + vc_conn := f_comp_by_teid(g1u_ud.gtpu.teid); + CLIENT.send(g1u_ud) to vc_conn; + } else if (g1u_ud.gtpu.teid == '00000000'O) { + TEID0.send(g1u_ud); + } else { + log("No client registered for TEID=", g1u_ud.gtpu.teid, "!"); + } + } + [] TEID0.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn { + GTP1U.send(g1u_ud); + } + [] CLIENT.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn { + GTP1U.send(g1u_ud); + } + + [] CLIENT_PROC.getcall(GTP1UEM_register_teid:{?}) -> param(teid) sender vc_conn { + f_tid_tbl_add(teid, vc_conn); + CLIENT_PROC.reply(GTP1UEM_register_teid:{teid}) to vc_conn; + } + [] CLIENT_PROC.getcall(GTP1UEM_allocate_teid:{}) -> sender vc_conn { + var OCT4 t := f_alloc_teid(); + f_tid_tbl_add(t, vc_conn); + CLIENT_PROC.reply(GTP1UEM_allocate_teid:{} value t) to vc_conn; + } + [] CLIENT_PROC.getcall(GTP1UEM_create_tunnel:{?}) -> param(gtc) sender vc_conn { + rx_uecups := f_uecups_xceive({create_tun := gtc}, {create_tun_res:={result:=OK}}); + CLIENT_PROC.reply(GTP1UEM_create_tunnel:{gtc}) to vc_conn; + } + [] CLIENT_PROC.getcall(GTP1UEM_destroy_tunnel:{?}) -> param(gtd) sender vc_conn { + rx_uecups := f_uecups_xceive({destroy_tun := gtd}, {destroy_tun_res:={result:=OK}}); + CLIENT_PROC.reply(GTP1UEM_destroy_tunnel:{gtd}) to vc_conn; + } + [] CLIENT_PROC.getcall(GTP1UEM_start_program:{?}) -> param(sprog) sender vc_conn { + rx_uecups := f_uecups_xceive({start_program := sprog}, {start_program_res:=?}); + /* if successful: store (pid, vc_conn) tuple so we can route program_term_ind */ + if (rx_uecups.start_program_res.result == OK) { + f_pid_tbl_add(rx_uecups.start_program_res.pid, vc_conn); + } + CLIENT_PROC.reply(GTP1UEM_start_program:{sprog} value rx_uecups.start_program_res) to vc_conn; + } + + } + } +} + + +/*********************************************************************** + * Interaction between Main and Client Components + ***********************************************************************/ +type port GTP1UEM_PT message { + inout Gtp1uUnitdata, UECUPS_ProgramTermInd; +} with { extension "internal" }; + +signature GTP1UEM_register_teid(OCT4 teid); +signature GTP1UEM_allocate_teid() return OCT4; +signature GTP1UEM_create_tunnel(UECUPS_CreateTun gtc); +signature GTP1UEM_destroy_tunnel(UECUPS_DestroyTun gtd); +signature GTP1UEM_start_program(UECUPS_StartProgram sprog) return UECUPS_StartProgramRes; + +type port GTP1UEM_PROC_PT procedure { + inout GTP1UEM_register_teid, GTP1UEM_allocate_teid, + GTP1UEM_create_tunnel, GTP1UEM_destroy_tunnel, GTP1UEM_start_program; +} with { extension "internal" }; + +/*********************************************************************** + * Client Component + ***********************************************************************/ + +type component GTP1U_ConnHdlr { + port GTP1UEM_PT GTP1U; + port GTP1UEM_PROC_PT GTP1U_PROC; +}; + + +function f_gtp1u_register_teid(OCT4 teid) runs on GTP1U_ConnHdlr { + GTP1U_PROC.call(GTP1UEM_register_teid:{teid}) { + [] GTP1U_PROC.getreply(GTP1UEM_register_teid:{teid}); + } +} + +function f_gtp1u_allocate_teid() runs on GTP1U_ConnHdlr return OCT4 { + var OCT4 t; + GTP1U_PROC.call(GTP1UEM_allocate_teid:{}) { + [] GTP1U_PROC.getreply(GTP1UEM_allocate_teid:{}) -> value t { + return t; + } + } +} + +function f_gtp1u_create_tunnel(template (value) UECUPS_CreateTun gtc) +runs on GTP1U_ConnHdlr { + GTP1U_PROC.call(GTP1UEM_create_tunnel:{valueof(gtc)}) { + [] GTP1U_PROC.getreply(GTP1UEM_create_tunnel:{gtc}); + } +} + +function f_gtp1u_destroy_tunnel(template (value) UECUPS_DestroyTun gtd) +runs on GTP1U_ConnHdlr { + GTP1U_PROC.call(GTP1UEM_destroy_tunnel:{valueof(gtd)}) { + [] GTP1U_PROC.getreply(GTP1UEM_destroy_tunnel:{gtd}); + } +} + +function f_gtp1u_start_program(template (value) UECUPS_StartProgram sprog) +runs on GTP1U_ConnHdlr return UECUPS_StartProgramRes { + var UECUPS_StartProgramRes res; + GTP1U_PROC.call(GTP1UEM_start_program:{valueof(sprog)}) { + [] GTP1U_PROC.getreply(GTP1UEM_start_program:{sprog}) -> value res; + } + return res; +} + + + +} diff --git a/library/GTPv2_Emulation.ttcn b/library/GTPv2_Emulation.ttcn index 15720f9..7ef5283 100644 --- a/library/GTPv2_Emulation.ttcn +++ b/library/GTPv2_Emulation.ttcn @@ -14,52 +14,33 @@ import from IPL4asp_Types all; import from General_Types all; import from Osmocom_Types all; -import from GTPU_Types all; -import from GTPv1U_CodecPort all; -import from GTPv1U_CodecPort_CtrlFunct all; import from GTPv2_Types all; import from GTPv2_Templates all; import from GTPv2_CodecPort all; import from GTPv2_CodecPort_CtrlFunct all; -import from SCTP_Templates all; - -import from UECUPS_Types all; -import from UECUPS_CodecPort all; -import from UECUPS_CodecPort_CtrlFunct all;
/*********************************************************************** * Main Emulation Component ***********************************************************************/
-modulepar { - charstring mp_uecups_host := "127.0.0.1"; - integer mp_uecups_port := UECUPS_SCTP_PORT; -}; +//modulepar {};
const integer GTP2C_PORT := 2123; -const integer GTP1U_PORT := 2152;
type record Gtp2EmulationCfg { HostName gtpc_bind_ip, IPL4asp_Types.PortNumber gtpc_bind_port, HostName gtpc_remote_ip, IPL4asp_Types.PortNumber gtpc_remote_port, - HostName gtpu_bind_ip optional, - IPL4asp_Types.PortNumber gtpu_bind_port optional, - boolean sgw_role, - boolean use_gtpu_daemon + boolean sgw_role };
type component GTPv2_Emulation_CT { /* Communication with underlying GTP CodecPort */ port GTPv2C_PT GTP2C; - port GTPU_PT GTPU; - - /* Control port to GTP-U Daemon */ - port UECUPS_CODEC_PT UECUPS;
/* Communication with Clients */ - port GTP2EM_PT TEID0; + port GTP2EM_PT TEIC0; port GTP2EM_PT CLIENT; port GTP2EM_PROC_PT CLIENT_PROC;
@@ -68,7 +49,7 @@
/* State */ var Gtp2cPeer g_peer; - var integer g_gtp2c_id, g_gtp1u_id; + var integer g_gtp2c_id; var OCT1 g_restart_ctr; var uint16_t g_c_seq_nr; var TidTableRec TidTable[256]; @@ -76,13 +57,11 @@ var ImsiTableRec ImsiTable[256]; var UdMsgTableRec UdMsgTable[256]; var PidTableRec PidTable[256]; - - var integer g_uecups_conn_id; };
-/* local TEID <-> ConnHdlr mapping */ +/* local TEIC <-> ConnHdlr mapping */ type record TidTableRec { - OCT4 teid, + OCT4 teic, GTP2_ConnHdlr vc_conn };
@@ -112,24 +91,24 @@ GTP2_ConnHdlr vc_conn };
-private function f_teid_known(OCT4 teid) runs on GTPv2_Emulation_CT return boolean { +private function f_teic_known(OCT4 teic) runs on GTPv2_Emulation_CT return boolean { var integer i; for (i := 0; i < sizeof(TidTable); i := i+1) { - if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) { + if (isbound(TidTable[i].teic) and TidTable[i].teic == teic) { return true; } } return false; }
-private function f_comp_by_teid(OCT4 teid) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr { +private function f_comp_by_teic(OCT4 teic) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr { var integer i; for (i := 0; i < sizeof(TidTable); i := i+1) { - if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) { + if (isbound(TidTable[i].teic) and TidTable[i].teic == teic) { return TidTable[i].vc_conn; } } - setverdict(fail, "No Component for TEID ", teid); + setverdict(fail, "No Component for TEIC ", teic); mtc.stop; }
@@ -187,16 +166,16 @@ mtc.stop; }
-private function f_tid_tbl_add(OCT4 teid, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT { +private function f_tid_tbl_add(OCT4 teic, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT { var integer i; for (i := 0; i < sizeof(TidTable); i := i+1) { - if (not isbound(TidTable[i].teid)) { - TidTable[i].teid := teid; + if (not isbound(TidTable[i].teic)) { + TidTable[i].teic := teic; TidTable[i].vc_conn := vc_conn; return; } } - testcase.stop("No Space in TidTable for ", teid); + testcase.stop("No Space in TidTable for ", teic); }
private function f_seq_tbl_add(OCT3 seq, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT { @@ -260,21 +239,21 @@ }
-/* allocate an unused local teid */ -private function f_alloc_teid() runs on GTPv2_Emulation_CT return OCT4 { - var OCT4 teid; +/* allocate an unused local teic */ +private function f_alloc_teic() runs on GTPv2_Emulation_CT return OCT4 { + var OCT4 teic; var integer i, j; for (i := 0; i < 100; i := i+1) { - teid := f_rnd_octstring(4); + teic := f_rnd_octstring(4); for (j := 0; j < sizeof(TidTable); j := j+1) { - if (isbound(TidTable) and TidTable[i].teid == teid) { + if (isbound(TidTable) and TidTable[i].teic == teic) { continue; } } /* we iterated over all entries and found no match: great! */ - return teid; + return teic; } - testcase.stop("Cannot find unused TEID after ", i, " attempts"); + testcase.stop("Cannot find unused TEIC after ", i, " attempts"); }
/* obtain the IMSI from a GTPv2C PDU, if there is any IMSI contained. The way how the TITAN @@ -432,40 +411,6 @@ return false; }
-function tr_UECUPS_RecvFrom_R(template PDU_UECUPS msg) -runs on GTPv2_Emulation_CT return template UECUPS_RecvFrom { - var template UECUPS_RecvFrom mrf := { - connId := g_uecups_conn_id, - remName := ?, - remPort := ?, - locName := ?, - locPort := ?, - msg := msg - } - return mrf; -} - - -private function f_uecups_xceive(template (value) PDU_UECUPS tx, - template PDU_UECUPS rx_t := ?, float time_out := 10.0) -runs on GTPv2_Emulation_CT return PDU_UECUPS { - timer T := time_out; - var UECUPS_RecvFrom mrf; - - UECUPS.send(t_UECUPS_Send(g_uecups_conn_id, tx)); - T.start; - alt { - [] UECUPS.receive(tr_UECUPS_RecvFrom_R(rx_t)) -> value mrf { } - [] UECUPS.receive(tr_SctpAssocChange) { repeat; } - [] UECUPS.receive(tr_SctpPeerAddrChange) { repeat; } - [] T.timeout { - setverdict(fail, "Timeout waiting for ", rx_t); - mtc.stop; - } - } - return mrf.msg; -} - private function f_init(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT { var Result res;
@@ -482,41 +427,6 @@ remName := g_gtp2_cfg.gtpc_remote_ip, remPort := g_gtp2_cfg.gtpc_remote_port } - - g_uecups_conn_id := res.connId; - - if (g_gtp2_cfg.use_gtpu_daemon) { - map(self:UECUPS, system:UECUPS); - res := UECUPS_CodecPort_CtrlFunct.f_IPL4_connect(UECUPS, mp_uecups_host, mp_uecups_port, "", -1, -1, - { sctp := valueof(ts_SctpTuple) }); - if (not ispresent(res.connId)) { - setverdict(fail, "Could not connect UECUPS socket, check your configuration"); - testcase.stop; - } - - /* clear all tunnel state in the daemon at start */ - f_uecups_xceive({reset_all_state := {}}, {reset_all_state_res:=?}, 30.0); - } else if (isvalue(cfg.gtpu_bind_ip) and isvalue(cfg.gtpu_bind_port)) { - map(self:GTPU, system:GTPU); - res := GTPv1U_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, cfg.gtpu_bind_ip, - cfg.gtpu_bind_port, {udp:={}}); - g_gtp1u_id := res.connId; - } - - /* make sure we always pass incoming UECUPS indications whenever receiving fom the UECUPS port */ - activate(as_uecups_ind()); -} - -private altstep as_uecups_ind() runs on GTPv2_Emulation_CT { -var UECUPS_RecvFrom rx; -var GTP2_ConnHdlr vc_conn; -/* handle incoming program_term_ind; dispatch to whatever component started the process */ -[] UECUPS.receive(tr_UECUPS_RecvFrom_R({program_term_ind:=?})) -> value rx { - vc_conn := f_comp_by_pid(rx.msg.program_term_ind.pid); - CLIENT.send(rx.msg.program_term_ind) to vc_conn; - /* FIXME: remove from table */ - repeat; - } }
private function SendToUdMsgTable(Gtp2cUnitdata g2c_ud) runs on GTPv2_Emulation_CT { @@ -536,22 +446,17 @@
function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT { var Gtp2cUnitdata g2c_ud; - var Gtp1uUnitdata g1u_ud; var PDU_GTPCv2 g2c; var GTP2_ConnHdlr vc_conn; var hexstring imsi; var OCT1 messageType; - var OCT4 teid; - var PDU_UECUPS rx_uecups; - var UECUPS_CreateTun gtc; - var UECUPS_DestroyTun gtd; - var UECUPS_StartProgram sprog; + var OCT4 teic;
f_init(cfg);
while (true) { alt { - /* route inbound GTP2-C based on TEID, SEQ or IMSI */ + /* route inbound GTP2-C based on TEIC, SEQ or IMSI */ [] GTP2C.receive(Gtp2cUnitdata:?) -> value g2c_ud { var template hexstring imsi_t := f_gtp2c_extract_imsi(g2c_ud.gtpc); /* if this is a response, route by SEQ: */ @@ -563,17 +468,17 @@ vc_conn := f_comp_by_imsi(valueof(imsi_t)); CLIENT.send(g2c_ud.gtpc) to vc_conn; } else if ((ispresent(g2c_ud.gtpc.tEID) and g2c_ud.gtpc.tEID != '00000000'O) - and f_teid_known(g2c_ud.gtpc.tEID)) { - vc_conn := f_comp_by_teid(g2c_ud.gtpc.tEID); + and f_teic_known(g2c_ud.gtpc.tEID)) { + vc_conn := f_comp_by_teic(g2c_ud.gtpc.tEID); CLIENT.send(g2c_ud.gtpc) to vc_conn; } else if ((not ispresent(g2c_ud.gtpc.tEID) or g2c_ud.gtpc.tEID == '00000000'O) - and f_teid_known('00000000'O)) { - vc_conn := f_comp_by_teid(g2c_ud.gtpc.tEID); + and f_teic_known('00000000'O)) { + vc_conn := f_comp_by_teic(g2c_ud.gtpc.tEID); CLIENT.send(g2c_ud.gtpc) to vc_conn; } else { SendToUdMsgTable(g2c_ud); if (not ispresent(g2c_ud.gtpc.tEID) or g2c_ud.gtpc.tEID == '00000000'O) { - TEID0.send(g2c_ud.gtpc); + TEIC0.send(g2c_ud.gtpc); } }
@@ -583,18 +488,8 @@ }
} - [] GTPU.receive(Gtp1uUnitdata:?) -> value g1u_ud { - if (f_teid_known(g1u_ud.gtpu.teid)) { - vc_conn := f_comp_by_teid(g1u_ud.gtpu.teid); - CLIENT.send(g1u_ud) to vc_conn; - } else if (g1u_ud.gtpu.teid == '00000000'O) { - TEID0.send(g1u_ud); - } else { - log("No client registered for TEID=", g1u_ud.gtpu.teid, "!"); - } - }
- [] TEID0.receive(PDU_GTPCv2:?) -> value g2c sender vc_conn { + [] TEIC0.receive(PDU_GTPCv2:?) -> value g2c sender vc_conn { /* patch in the next sequence number on outbound Initial message */ if (f_gtp2c_is_initial_msg(g2c)) { g2c.sequenceNumber := int2oct(g_c_seq_nr, 3); @@ -607,9 +502,6 @@ f_seq_tbl_add(g2c.sequenceNumber, vc_conn); } } - [] TEID0.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn { - GTPU.send(g1u_ud); - }
[] CLIENT.receive(PDU_GTPCv2:?) -> value g2c sender vc_conn { /* patch in the next sequence number on outbound Initial message */ @@ -624,9 +516,6 @@ f_seq_tbl_add(g2c.sequenceNumber, vc_conn); } } - [] CLIENT.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn { - GTPU.send(g1u_ud); - }
[] CLIENT_PROC.getcall(GTP2EM_register_imsi:{?}) -> param(imsi) sender vc_conn { f_imsi_tbl_add(imsi, vc_conn); @@ -637,32 +526,15 @@ CLIENT_PROC.reply(GTP2EM_register_udmsg:{messageType}) to vc_conn; }
- [] CLIENT_PROC.getcall(GTP2EM_register_teid:{?}) -> param(teid) sender vc_conn { - f_tid_tbl_add(teid, vc_conn); - CLIENT_PROC.reply(GTP2EM_register_teid:{teid}) to vc_conn; + [] CLIENT_PROC.getcall(GTP2EM_register_teic:{?}) -> param(teic) sender vc_conn { + f_tid_tbl_add(teic, vc_conn); + CLIENT_PROC.reply(GTP2EM_register_teic:{teic}) to vc_conn; } - [] CLIENT_PROC.getcall(GTP2EM_allocate_teid:{}) -> sender vc_conn { - var OCT4 t := f_alloc_teid(); + [] CLIENT_PROC.getcall(GTP2EM_allocate_teic:{}) -> sender vc_conn { + var OCT4 t := f_alloc_teic(); f_tid_tbl_add(t, vc_conn); - CLIENT_PROC.reply(GTP2EM_allocate_teid:{} value t) to vc_conn; + CLIENT_PROC.reply(GTP2EM_allocate_teic:{} value t) to vc_conn; } - [] CLIENT_PROC.getcall(GTP2EM_create_tunnel:{?}) -> param(gtc) sender vc_conn { - rx_uecups := f_uecups_xceive({create_tun := gtc}, {create_tun_res:={result:=OK}}); - CLIENT_PROC.reply(GTP2EM_create_tunnel:{gtc}) to vc_conn; - } - [] CLIENT_PROC.getcall(GTP2EM_destroy_tunnel:{?}) -> param(gtd) sender vc_conn { - rx_uecups := f_uecups_xceive({destroy_tun := gtd}, {destroy_tun_res:={result:=OK}}); - CLIENT_PROC.reply(GTP2EM_destroy_tunnel:{gtd}) to vc_conn; - } - [] CLIENT_PROC.getcall(GTP2EM_start_program:{?}) -> param(sprog) sender vc_conn { - rx_uecups := f_uecups_xceive({start_program := sprog}, {start_program_res:=?}); - /* if successful: store (pid, vc_conn) tuple so we can route program_term_ind */ - if (rx_uecups.start_program_res.result == OK) { - f_pid_tbl_add(rx_uecups.start_program_res.pid, vc_conn); - } - CLIENT_PROC.reply(GTP2EM_start_program:{sprog} value rx_uecups.start_program_res) to vc_conn; - } - } } } @@ -672,20 +544,17 @@ * Interaction between Main and Client Components ***********************************************************************/ type port GTP2EM_PT message { - inout PDU_GTPCv2, Gtp1uUnitdata, UECUPS_ProgramTermInd; + inout PDU_GTPCv2; } with { extension "internal" };
signature GTP2EM_register_imsi(hexstring imsi); signature GTP2EM_register_udmsg(OCT1 messageType); -signature GTP2EM_register_teid(OCT4 teid); -signature GTP2EM_allocate_teid() return OCT4; -signature GTP2EM_create_tunnel(UECUPS_CreateTun gtc); -signature GTP2EM_destroy_tunnel(UECUPS_DestroyTun gtd); -signature GTP2EM_start_program(UECUPS_StartProgram sprog) return UECUPS_StartProgramRes; +signature GTP2EM_register_teic(OCT4 teic); +signature GTP2EM_allocate_teic() return OCT4;
type port GTP2EM_PROC_PT procedure { - inout GTP2EM_register_imsi, GTP2EM_register_udmsg, GTP2EM_register_teid, GTP2EM_allocate_teid, - GTP2EM_create_tunnel, GTP2EM_destroy_tunnel, GTP2EM_start_program; + inout GTP2EM_register_imsi, GTP2EM_register_udmsg, + GTP2EM_register_teic, GTP2EM_allocate_teic; } with { extension "internal" };
/*********************************************************************** @@ -713,44 +582,18 @@ } }
-function f_gtp2_register_teid(OCT4 teid) runs on GTP2_ConnHdlr { - GTP2_PROC.call(GTP2EM_register_teid:{teid}) { - [] GTP2_PROC.getreply(GTP2EM_register_teid:{teid}); +function f_gtp2_register_teic(OCT4 teic) runs on GTP2_ConnHdlr { + GTP2_PROC.call(GTP2EM_register_teic:{teic}) { + [] GTP2_PROC.getreply(GTP2EM_register_teic:{teic}); } }
-function f_gtp2_allocate_teid() runs on GTP2_ConnHdlr return OCT4 { +function f_gtp2_allocate_teic() runs on GTP2_ConnHdlr return OCT4 { var OCT4 t; - GTP2_PROC.call(GTP2EM_allocate_teid:{}) { - [] GTP2_PROC.getreply(GTP2EM_allocate_teid:{}) -> value t { + GTP2_PROC.call(GTP2EM_allocate_teic:{}) { + [] GTP2_PROC.getreply(GTP2EM_allocate_teic:{}) -> value t { return t; } } } - -function f_gtp2_create_tunnel(template (value) UECUPS_CreateTun gtc) -runs on GTP2_ConnHdlr { - GTP2_PROC.call(GTP2EM_create_tunnel:{valueof(gtc)}) { - [] GTP2_PROC.getreply(GTP2EM_create_tunnel:{gtc}); - } -} - -function f_gtp2_destroy_tunnel(template (value) UECUPS_DestroyTun gtd) -runs on GTP2_ConnHdlr { - GTP2_PROC.call(GTP2EM_destroy_tunnel:{valueof(gtd)}) { - [] GTP2_PROC.getreply(GTP2EM_destroy_tunnel:{gtd}); - } -} - -function f_gtp2_start_program(template (value) UECUPS_StartProgram sprog) -runs on GTP2_ConnHdlr return UECUPS_StartProgramRes { - var UECUPS_StartProgramRes res; - GTP2_PROC.call(GTP2EM_start_program:{valueof(sprog)}) { - [] GTP2_PROC.getreply(GTP2EM_start_program:{sprog}) -> value res; - } - return res; -} - - - } diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn index c006aa4..4885b1e 100644 --- a/mme/MME_Tests.ttcn +++ b/mme/MME_Tests.ttcn @@ -120,7 +120,7 @@
/* S11 interface (GTPv2C) of emulated SGW-C */ var GTPv2_Emulation_CT vc_GTP2; - port GTP2EM_PT TEID0; + port GTP2EM_PT TEIC0;
var UeParams g_ue_pars[NUM_UE]; } @@ -371,15 +371,12 @@ gtpc_bind_port := mp_s11_local_port, gtpc_remote_ip := mp_s11_remote_ip, gtpc_remote_port := mp_s11_remote_port, - gtpu_bind_ip := omit, /* using gtpu daemon */ - gtpu_bind_port := omit, /* using gtpu daemon */ - sgw_role := true, - use_gtpu_daemon := false + sgw_role := true };
vc_GTP2 := GTPv2_Emulation_CT.create(id); map(vc_GTP2:GTP2C, system:GTP2C); - connect(vc_GTP2:TEID0, self:TEID0); + connect(vc_GTP2:TEIC0, self:TEIC0); vc_GTP2.start(GTPv2_Emulation.main(cfg)); }
@@ -840,9 +837,9 @@ g_pars.ue_pars.bearer.ebi := rx_bctx_ies.ePS_Bearer_ID.ePS_Bearer_ID_Value;
/* allocate + register TEID-C on local side */ - g_pars.ue_pars.s11_teic_local := f_gtp2_allocate_teid(); + g_pars.ue_pars.s11_teic_local := f_gtp2_allocate_teic(); g_pars.ue_pars.bearer.s11_teid_local := g_pars.ue_pars.s11_teic_local; - g_pars.ue_pars.s5c_teic_local := f_gtp2_allocate_teid(); + g_pars.ue_pars.s5c_teic_local := f_gtp2_allocate_teic(); g_pars.ue_pars.bearer.s5c_teid_local := g_pars.ue_pars.s5c_teic_local;
s11_fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S11_MME_GTPC, g_pars.ue_pars.s11_teic_local, 0, diff --git a/mme/gen_links.sh b/mme/gen_links.sh index af0355f..ea9179f 100755 --- a/mme/gen_links.sh +++ b/mme/gen_links.sh @@ -55,10 +55,6 @@ FILES="GTPv2_Types.ttcn" gen_links $DIR $FILES
-DIR=$BASEDIR/osmo-uecups/ttcn3 -FILES="UECUPS_CodecPort.ttcn UECUPS_CodecPort_CtrlFunct.ttcn UECUPS_CodecPort_CtrlFunctDef.cc UECUPS_Types.ttcn " -gen_links $DIR $FILES - DIR=$BASEDIR/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src FILES="DIAMETER_EncDec.cc" gen_links $DIR $FILES diff --git a/mme/regen_makefile.sh b/mme/regen_makefile.sh index 4eb0f1a..c1859da 100755 --- a/mme/regen_makefile.sh +++ b/mme/regen_makefile.sh @@ -26,7 +26,6 @@ TCCEncoding.cc TCCInterface.cc TELNETasp_PT.cc - UECUPS_CodecPort_CtrlFunctDef.cc "
. ../_buildsystem/regen_makefile.inc.sh diff --git a/pgw/PGW_Tests.cfg b/pgw/PGW_Tests.cfg index ce3076b..68688c1 100644 --- a/pgw/PGW_Tests.cfg +++ b/pgw/PGW_Tests.cfg @@ -20,7 +20,7 @@ PGW_Tests.mp_pcrf_local_ip:= "127.0.0.202" PGW_Tests.mp_ocs_local_ip:= "127.0.0.202" PGW_Tests.mp_aaa_local_ip:= "127.0.0.202" -GTPv2_Emulation.mp_uecups_host := "127.0.0.20" +GTPv1U_Emulation.mp_uecups_host := "127.0.0.20"
[MAIN_CONTROLLER]
diff --git a/pgw/PGW_Tests.ttcn b/pgw/PGW_Tests.ttcn index 4a4f77f..4d225fa 100644 --- a/pgw/PGW_Tests.ttcn +++ b/pgw/PGW_Tests.ttcn @@ -7,6 +7,8 @@ import from Native_Functions all; import from Misc_Helpers all;
+import from GTPv1U_Emulation all; + import from GTPv2_Types all; import from GTPv2_Templates all; import from GTPv2_Emulation all; @@ -47,9 +49,11 @@ }
/* main component, we typically have one per testcase */ -type component PGW_Test_CT extends GTP2_ConnHdlr { +type component PGW_Test_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr { var GTPv2_Emulation_CT vc_GTP2; - port GTP2EM_PT TEID0; + port GTP2EM_PT TEIC0; + var GTPv1U_Emulation_CT vc_GTP1U; + port GTP1UEM_PT TEID0;
/* emulated PCRF */ var DIAMETER_Emulation_CT vc_Gx; @@ -100,7 +104,7 @@
/* per-session component; we typically have 1..N per testcase */ -type component PGW_Session_CT extends GTP2_ConnHdlr { +type component PGW_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr { var SessionPars g_pars;
port DIAMETER_Conn_PT Gx; @@ -280,27 +284,44 @@ f_sleep(1.0); }
-private function f_init(float guard_timeout := 60.0) runs on PGW_Test_CT { - T_guard.start(guard_timeout); - activate(as_Tguard()); - +private function f_init_gtp2c() runs on PGW_Test_CT { var Gtp2EmulationCfg cfg := { gtpc_bind_ip := mp_local_hostname_c, gtpc_bind_port := GTP2C_PORT, gtpc_remote_ip := mp_pgw_hostname, gtpc_remote_port := GTP2C_PORT, - gtpu_bind_ip := omit, /* using gtpu daemon */ - gtpu_bind_port := omit, /* using gtpu daemon */ - sgw_role := true, - use_gtpu_daemon := true + sgw_role := true };
- vc_GTP2 := GTPv2_Emulation_CT.create("GTP2_EM"); + vc_GTP2 := GTPv2_Emulation_CT.create("GTP2C_EM"); map(vc_GTP2:GTP2C, system:GTP2C); - connect(vc_GTP2:TEID0, self:TEID0); + connect(vc_GTP2:TEIC0, self:TEIC0); connect(vc_GTP2:CLIENT, self:GTP2); connect(vc_GTP2:CLIENT_PROC, self:GTP2_PROC); vc_GTP2.start(GTPv2_Emulation.main(cfg)); +} + +private function f_init_gtp1u() runs on PGW_Test_CT { + var Gtp1uEmulationCfg cfg := { + gtpu_bind_ip := omit, /* using gtpu daemon */ + gtpu_bind_port := omit, /* using gtpu daemon */ + use_gtpu_daemon := true + }; + + vc_GTP1U := GTPv1U_Emulation_CT.create("GTP1U_EM"); + map(vc_GTP1U:GTP1U, system:GTP1U); + connect(vc_GTP1U:TEID0, self:TEID0); + connect(vc_GTP1U:CLIENT, self:GTP1U); + connect(vc_GTP1U:CLIENT_PROC, self:GTP1U_PROC); + vc_GTP1U.start(GTPv1U_Emulation.main(cfg)); +} + +private function f_init(float guard_timeout := 60.0) runs on PGW_Test_CT { + T_guard.start(guard_timeout); + activate(as_Tguard()); + + f_init_gtp2c(); + f_init_gtp1u();
if (mp_pcrf_local_ip != "") { f_init_diameter(testcasename()); @@ -323,6 +344,8 @@ vc_conn := PGW_Session_CT.create(id); connect(vc_conn:GTP2, vc_GTP2:CLIENT); connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC); + connect(vc_conn:GTP1U, vc_GTP1U:CLIENT); + connect(vc_conn:GTP1U_PROC, vc_GTP1U:CLIENT_PROC);
if (isbound(vc_Gx)) { vc_conn_gx := DIAMETER_ConnHdlr_CT.create(id); @@ -355,9 +378,9 @@ private function f_handler_init(void_fn fn, SessionPars pars) runs on PGW_Session_CT { g_pars := valueof(pars); - /* allocate + register TEID-C on local side */ - g_pars.teic_local := f_gtp2_allocate_teid(); - g_pars.bearer.teid_local := g_pars.teic_local; + /* allocate + register TEI{C,D} on local side */ + g_pars.teic_local := f_gtp2_allocate_teic(); + g_pars.bearer.teid_local := f_gtp1u_allocate_teid(); fn.apply(); }
@@ -693,12 +716,12 @@ /* create tunnel in daemon */ if (isbound(g_ip4_addr)) { uecups_create.user_addr := g_ip4_addr; - f_gtp2_create_tunnel(uecups_create); + f_gtp1u_create_tunnel(uecups_create); } if (isbound(g_ip6_addr)) { uecups_create.user_addr_type := IPV6; uecups_create.user_addr := g_ip6_addr; - f_gtp2_create_tunnel(uecups_create); + f_gtp1u_create_tunnel(uecups_create); } }
@@ -871,7 +894,7 @@ rx_teid := oct2int(g_pars.bearer.teid_local) }; /* FIXME: what about IPv4/IPv6 differentiation? */ - f_gtp2_destroy_tunnel(uecups_destroy); + f_gtp1u_destroy_tunnel(uecups_destroy); } }
@@ -896,7 +919,7 @@ }
log("Starting a program: ", command); - var UECUPS_StartProgramRes res := f_gtp2_start_program(sprog); + var UECUPS_StartProgramRes res := f_gtp1u_start_program(sprog); if (res.result != OK) { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unable to start program '", command, "'")); @@ -914,10 +937,10 @@
T.start; alt { - [] GTP2.receive(UECUPS_ProgramTermInd:{pid := pid, exit_code := exit_code}) { + [] GTP1U.receive(UECUPS_ProgramTermInd:{pid := pid, exit_code := exit_code}) { setverdict(pass); } - [] GTP2.receive(UECUPS_ProgramTermInd:?) -> value pti { + [] GTP1U.receive(UECUPS_ProgramTermInd:?) -> value pti { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected ProgramTermInd := ", pti)); } diff --git a/pgw/gen_links.sh b/pgw/gen_links.sh index 314050e..fa69ee4 100755 --- a/pgw/gen_links.sh +++ b/pgw/gen_links.sh @@ -59,7 +59,8 @@
DIR=../library FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPCP_Types.ttcn IPCP_Templates.ttcn PAP_Types.ttcn " -FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1C_Templates.ttcn Osmocom_Gb_Types.ttcn " +FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1C_Templates.ttcn Osmocom_Gb_Types.ttcn " +FILES+="GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1U_Emulation.ttcn " FILES+="GTPv2_PrivateExtensions.ttcn GTPv2_Templates.ttcn " FILES+="GTPv2_CodecPort.ttcn GTPv2_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunct.ttcn GTPv2_Emulation.ttcn " FILES+="DNS_Helpers.ttcn "