pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43378?usp=email )
Change subject: WIP: pfcp working ......................................................................
WIP: pfcp working
Change-Id: I661a1893a3f7c3659753c82b009398763a06a92d --- M deps/Makefile M smf/SMF_Session_CT.ttcn M smf/SMF_Tests.ttcn M smf/gen_links.sh 4 files changed, 163 insertions(+), 7 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/78/43378/1
diff --git a/deps/Makefile b/deps/Makefile index 7d3198e..8abd962 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -38,7 +38,6 @@ titan.ProtocolModules.NS_v7.3.0 \ titan.ProtocolModules.SGsAP_13.2.0 \ titan.ProtocolModules.SNDCP_v7.0.0 \ - titan.ProtocolModules.PFCP_v15.1.0 \ titan.TestPorts.Common_Components.Socket-API \ titan.TestPorts.Common_Components.Abstract_Socket \ titan.TestPorts.HTTPmsg \ @@ -61,6 +60,7 @@ OSMOGITEA_REPOS= nas \ titan.ProtocolModules.BSSMAP \ titan.ProtocolModules.MAP \ + titan.ProtocolModules.PFCP_v15.1.0 \ titan.TestPorts.AF_PACKET \ titan.TestPorts.USB
@@ -107,7 +107,7 @@ titan.ProtocolModules.SUA_commit= R.5.A-5-gcf1137a titan.ProtocolModules.TCP_commit= R.3.A-5-g39e5f45 titan.ProtocolModules.UDP_commit= R.4.A-5-geea8aa3 -titan.ProtocolModules.PFCP_v15.1.0_commit= d550ad9ddb6f9c823c9a555254cd76cf0e738d18 +titan.ProtocolModules.PFCP_v15.1.0_commit= f2e70e48265386264b3fad1b92de484c344e0656 titan.TestPorts.AF_PACKET_commit= 0.1-5-g89ebea6 titan.TestPorts.Common_Components.Socket-API_commit= R.6.A-6-gf4380d0 titan.TestPorts.Common_Components.Abstract_Socket_commit= R.9.B-4-gbd41994 diff --git a/smf/SMF_Session_CT.ttcn b/smf/SMF_Session_CT.ttcn index 9c5024b..e322435 100644 --- a/smf/SMF_Session_CT.ttcn +++ b/smf/SMF_Session_CT.ttcn @@ -15,7 +15,6 @@
import from DNS_Helpers all;
- import from DIAMETER_Types all; import from DIAMETER_Templates all; import from DIAMETER_ts29_212_Templates all; @@ -24,14 +23,23 @@ import from DIAMETER_ts32_299_Templates all; import from DIAMETER_Emulation all;
+import from PFCP_Types all; +import from PFCP_Emulation all; +import from PFCP_Templates all; +import from PFCP_CodecPort all; + +import from Mutex all; + import from SMF_Tests all;
const integer DIA_Gx := 0; const integer DIA_Gy := 1; const integer DIA_S6b := 2;
+const OCT8 c_SEID0 := '0000000000000000'O; + /* per-session component; we typically have 1..N per testcase */ -type component SMF_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr, DIAMETER_ConnHdlr { +type component SMF_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr, DIAMETER_ConnHdlr, PFCP_ConnHdlr, MutexCT { var SessionPars g_pars;
/* GTP-U IPv4 address remote sie */ @@ -64,6 +72,63 @@ DIAMETER_Resultcode cca_res_code };
+type record FTeids { + F_TEID local, + F_TEID remote optional +} +template (value) FTeids t_FTeids(template (value) F_TEID local, + template (omit) F_TEID remote) := { + local := local, + remote := remote +} + +/* 'local' and 'remote' refer to the GTP information from the UPF's point of view: + * HNB UPF CN + * access.remote <---> access.local | core.local <---> core.remote + */ +type record Gtp1uParameters { + FTeids core, + FTeids access +} +template (value) Gtp1uParameters +t_Gtp1uParameters_default(uint32_t idx := 1, + charstring mp_pfcp_ip_local) := { + core := { + local := ts_PFCP_F_TEID_ipv4(int2oct(idx + 8192, 4), + f_inet_addr(mp_pfcp_ip_local)), + remote := omit + }, + access := { + local := ts_PFCP_F_TEID_ipv4(int2oct(idx, 4), + f_inet_addr(mp_pfcp_ip_local)), + remote := omit + } +} + +type record PfcpParameters { + charstring pfcp_local_addr, + Node_ID local_node_id, + F_SEID local_f_seid, + F_SEID remote_cp_f_seid optional, + Gtp1uParameters gtp1u_pars +} + + +function f_t_PfcpParams(uint32_t idx := 1, + charstring pfcp_local_addr := mp_pfcp_ip_local, + template (value) Node_ID local_node_id := ts_PFCP_Node_ID_ipv4(f_inet_addr(mp_pfcp_ip_local))) +return PfcpParameters { + var uint64_t local_f_seid := idx; + var template (value) PfcpParameters pfcp_pars := { + pfcp_local_addr := pfcp_local_addr, + local_node_id := local_node_id, + local_f_seid := ts_PFCP_F_SEID_ipv4(f_inet_addr(pfcp_local_addr), int2oct(local_f_seid, 8)), + remote_cp_f_seid := omit, + gtp1u_pars := t_Gtp1uParameters_default(idx, pfcp_local_addr) + } + return valueof(pfcp_pars); +} + /* configuration data for a given Session */ type record SessionPars { hexstring imsi, @@ -88,7 +153,9 @@ /* Bearer Contexts to be created */ BearerConfig bearer optional,
- SessionParsGy gy + SessionParsGy gy, + + PfcpParameters pfcp_pars }
template (value) SessionPars @@ -97,7 +164,8 @@ GTP2C_RAT_Type rat_type := GTP2C_RAT_EUTRAN, charstring apn := "internet", boolean selection_mode := false, - GTP2C_PDN_Type pdn_type := GTP2C_PDN_IPv4) := { + GTP2C_PDN_Type pdn_type := GTP2C_PDN_IPv4, + template (value) PfcpParameters pfcp_pars := f_t_PfcpParams(1)) := { imsi := imsi, msisdn := msisdn, rat_type := rat_type, @@ -116,7 +184,8 @@ gy := { validity_time := 0, cca_res_code := DIAMETER_SUCCESS - } + }, + pfcp_pars := pfcp_pars }
@@ -305,6 +374,22 @@ apco := apco); g2c.gtpcv2_pdu.createSessionRequest.servingNetwork := ts_GTP2C_ServingNetwork('001'H, '01F'H);
+ +/////////////////////// + /* This code block cannot be executed by more than one component at a time because + * the RANAP RAB Ass Request triggers the IUT to send PFCP Session Establishment + * Request PDU(s), which needs to be routed to the respective ConnHdlr component (us). + * As per 3GPP TS 29.244, section 7.2.2.4.2, these PFCP PDUs shall all have SEID=0, + * so that the PFCPEM component cannot route them unambiguously. This is why we + * need to ensure that only one ConnHdlr is triggering PFCP session establishment + * at the given moment of time. */ + f_Mutex_lock(__BFILE__, __LINE__); + + /* Subscribe for PFCP Session Establishment Request PDU(s), which are + * expected to have SEID set to 0, as per 3GPP TS 29.244, section 7.2.2.4.2. */ + f_PFCPEM_subscribe_seid(c_SEID0); +/////////////////////// + GTP2.send(g2c); if (do_s6b and DIAMETER[DIA_S6b].checkstate("Connected")) { as_DIA_S6b_AAR(); @@ -316,6 +401,25 @@ if (DIAMETER[DIA_Gy].checkstate("Connected")) { as_DIA_Gy_CCR(INITIAL_REQUEST); } + +/////////////////////// + var PDU_PFCP m; + /* Expect PFCP Session Establishment Request. */ + m := f_pfcp_expect(tr_PFCP_Session_Est_Req()); + log("PFCP Session Establishment Request received!", m) + /* Ask PFCPEM to route PDUs with to be indicated F-SEID to us. */ + f_PFCPEM_subscribe_seid(g_pars.pfcp_pars.local_f_seid.seid); + /* We're done establishing PFCP sessions, so at this point we no longer expect to + * receive Session Establishment Request PDUs with SEID=0. Unregister and unlock + * the mutex, enabling other components to establish PFCP sessions after us. */ + f_PFCPEM_unsubscribe_seid(c_SEID0); + f_Mutex_unlock(__BFILE__, __LINE__); + + log("DONE PROCESSING PFCP Session Establishment Request") + f_pfcp_sess_est_resp(m); +/////////////////////// + + alt { [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid := g_pars.teic_local, cause := Request_accepted, @@ -453,4 +557,47 @@ } }
+function f_pfcp_expect(template (present) PDU_PFCP exp_rx, float wait_time := 5.0) runs on SMF_Session_CT return PDU_PFCP +{ + var PDU_PFCP rx; + timer T := wait_time; + T.start; + alt { + [] PFCP.receive(exp_rx) -> value rx { + setverdict(pass); + } + [] PFCP.receive(PDU_PFCP:?) { + setverdict(fail, "Got an unexpected PFCP message, was waiting for ", exp_rx); + mtc.stop; + } + [] T.timeout { + setverdict(fail, "Timeout waiting for PFCP ", exp_rx); + mtc.stop; + } + } + T.stop; + return rx; +} + +function f_pfcp_sess_est_resp(PDU_PFCP req) runs on SMF_Session_CT { + //TODO: send SessEstResp back!!!! See hnbgw/ConnHdlr.ttcn: + var PFCP_Session_Establishment_Request serq := req.message_body.pfcp_session_establishment_request; + /* Store peer's F-SEID for later: */ + g_pars.pfcp_pars.remote_cp_f_seid := serq.CP_F_SEID; + + /* Acting as UPF, invent a new PFCP SEID to send to the peer. Respond to the Session Establishment. + * The PFCP response must have the same sequence_number as the request. */ + var Gtp1uParameters gtp1_pars := g_pars.pfcp_pars.gtp1u_pars; + var template Created_PDR pdr1 := ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id, + local_F_TEID := gtp1_pars.core.local); + var template Created_PDR pdr2 := ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id, + local_F_TEID := gtp1_pars.access.local); + var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(seq_nr := req.sequence_number, + node_id := g_pars.pfcp_pars.local_node_id, + seid := g_pars.pfcp_pars.remote_cp_f_seid.seid, + f_seid := g_pars.pfcp_pars.local_f_seid, + created_pdr := {pdr1, pdr2}); + PFCP.send(r); +} + } diff --git a/smf/SMF_Tests.ttcn b/smf/SMF_Tests.ttcn index 15b0390..a2cd432 100644 --- a/smf/SMF_Tests.ttcn +++ b/smf/SMF_Tests.ttcn @@ -28,6 +28,7 @@ import from PFCP_Templates all; import from PFCP_CodecPort all;
+import from Mutex all; import from SMF_Session_CT all;
modulepar { @@ -73,6 +74,7 @@
/* emulated UPF */ var PFCP_Emulation_CT vc_PFCP; + var MutexDispCT vc_mutex_disp; var boolean g_pfcp_answer_heartbeat_req := true;
/* global test case guard timer (actual timeout value is set in f_init()) */ @@ -195,6 +197,8 @@ function f_init_pfcp(charstring id) runs on SMF_Test_CT { id := id & "-PFCP";
+ vc_mutex_disp := f_MutexDisp_start(); + var PFCP_Emulation_Cfg pfcp_cfg := { pfcp_bind_ip := mp_pfcp_ip_local, pfcp_bind_port := PFCP_PORT, @@ -260,6 +264,10 @@ connect(vc_conn:GTP1U[0], vc_GTP1U:CLIENT); connect(vc_conn:GTP1U_PROC[0], vc_GTP1U:CLIENT_PROC);
+ connect(vc_conn:PFCP, vc_PFCP:CLIENT); + connect(vc_conn:PFCP_PROC, vc_PFCP:CLIENT_PROC); + f_MutexDisp_connect(vc_mutex_disp, vc_conn); + if (isbound(vc_Gx)) { connect(vc_conn:DIAMETER_PROC[DIA_Gx], vc_Gx:DIAMETER_PROC); connect(vc_conn:DIAMETER[DIA_Gx], vc_Gx:DIAMETER_CLIENT); diff --git a/smf/gen_links.sh b/smf/gen_links.sh index bd3ecd8..a733486 100755 --- a/smf/gen_links.sh +++ b/smf/gen_links.sh @@ -68,6 +68,7 @@ FILES+="DIAMETER_Templates.ttcn DIAMETER_rfc4004_Templates.ttcn DIAMETER_rfc5447_Templates.ttcn DIAMETER_ts29_212_Templates.ttcn DIAMETER_ts29_212_Templates.ttcn DIAMETER_ts29_229_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn DIAMETER_ts29_273_Templates.ttcn DIAMETER_ts32_299_Templates.ttcn " FILES+="SCTP_Templates.ttcn " FILES+="PFCP_CodecPort.ttcn PFCP_CodecPort_CtrlFunct.ttcn PFCP_CodecPort_CtrlFunctDef.cc PFCP_Emulation.ttcn PFCP_Templates.ttcn " +FILES+="Mutex.ttcn " gen_links $DIR $FILES
gen_links_finish