pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/43307?usp=email )
Change subject: smf: Introduce testsuite ......................................................................
smf: Introduce testsuite
This commit introduces a ttcn3-test-smf-testsuite reusing (copying over) most of existing ttcn3 code in pgw testsuite. Contrary to the PGW one, this testsuite allows to test specifically the SMF, hence also validating PFCP interface.
Moreover, this testsuite will be extended to also test 5G SMF functionality by using the N11 interface (SBI based) instead of LTE GTPv2C based interace.
With the current commit the testsuite is not expected to pass tests yet, only TC_tx_echo() is probably passing, because others still lack the PFCP support, which will be added in a follow up commit. This way it's easier to track what was copied from pgw/ (basically a trimmed down version removing UECUPs functionalities).
Change-Id: Ide6275323085f3d1f5d1ab01f3425fd6baa0f8b3 --- M Makefile A smf/README.md A smf/SMF_Session_CT.ttcn A smf/SMF_Tests.cfg A smf/SMF_Tests.default A smf/SMF_Tests.ttcn A smf/expected-results.xml A smf/freediameter.conf A smf/gen_links.sh A smf/open5gs-nrf.yaml A smf/open5gs-smf.yaml A smf/regen_makefile.sh A smf/testenv.cfg 13 files changed, 1,127 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/07/43307/1
diff --git a/Makefile b/Makefile index b58fcf3..b15ec40 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,7 @@ sgsn \ simtrace \ sip \ + smf \ smlc \ smdpp \ stp \ diff --git a/smf/README.md b/smf/README.md new file mode 100644 index 0000000..f25ffc5 --- /dev/null +++ b/smf/README.md @@ -0,0 +1,25 @@ +# SMF_Tests.ttcn + +* external interfaces + * N11: HTTP2/SBI (emulates AMF side) + * N4: UDP/PFCP (emulates UPF) + * Gx: Diameter (emulates PCRF) + * Gy: Diameter (emulates OCS) + * S6b: Diameter (emulates AAA) + * Internet: emulates the Internet side from/to UPF + +{% dot smf_tests.svg +digraph G { + rankdir=LR; + ATS [label="ATS\nC5G_Tests.ttcn"]; + SMF [label="AMF\open5gs-smfd",shape="box"]; + NRF [label="SMF\nopen5gs-nrfd"]; + + ATS -> SMF [label="N11"]; + ATS -> SMF [label="N4"]; + ATS -> SMF [label="Gx"]; + ATS -> SMF [label="Gy"]; + ATS -> SMF [label="S6b"]; + SMF -> NRF [label="SBI"]; +} +%} diff --git a/smf/SMF_Session_CT.ttcn b/smf/SMF_Session_CT.ttcn new file mode 100644 index 0000000..9c5024b --- /dev/null +++ b/smf/SMF_Session_CT.ttcn @@ -0,0 +1,456 @@ +module SMF_Session_CT { + +import from TCCEncoding_Functions all; + +import from General_Types all; +import from Osmocom_Types all; +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; + +import from DNS_Helpers all; + + +import from DIAMETER_Types all; +import from DIAMETER_Templates all; +import from DIAMETER_ts29_212_Templates all; +import from DIAMETER_ts29_272_Templates all; +import from DIAMETER_ts29_273_Templates all; +import from DIAMETER_ts32_299_Templates all; +import from DIAMETER_Emulation all; + +import from SMF_Tests all; + +const integer DIA_Gx := 0; +const integer DIA_Gy := 1; +const integer DIA_S6b := 2; + +/* per-session component; we typically have 1..N per testcase */ +type component SMF_Session_CT extends GTP2_ConnHdlr, GTP1U_ConnHdlr, DIAMETER_ConnHdlr { + var SessionPars g_pars; + + /* GTP-U IPv4 address remote sie */ + var OCT4 g_gtpu4_remote; + var OCT16 g_gtpu6_remote; + + /* Address allocation */ + var OCT4 g_ip4_addr; + var OCT8 g_ip6_interface_id; + var OCT16 g_ip6_addr; + + /* Store last received Gy message */ + var PDU_DIAMETER g_rx_gy; +} + +type record BearerConfig { + /* EPS Bearer ID */ + uint4_t ebi optional, + /* TEI (Data) local side */ + OCT4 teid_local optional, + /* TEI (Data) remote side */ + OCT4 teid_remote optional +}; + +type record SessionParsGy { + /* In seconds. 0 => disabled, !0 => grant over CC-Time period */ + integer validity_time, + + /* Result-Code to use when sending Gy CCA, usually DIAMETER_SUCCESS */ + DIAMETER_Resultcode cca_res_code +}; + +/* configuration data for a given Session */ +type record SessionPars { + hexstring imsi, + hexstring msisdn optional, + // serving network + GTP2C_RAT_Type rat_type, + // flags? + charstring apn, + /* Apn subscribed or non-subscribed */ + boolean selection_mode, + GTP2C_PDN_Type pdn_type, + /* PAA */ + /* Max APN Restriction */ + /* APN-AMBR */ + octetstring pco optional, + octetstring epco optional, + + /* TEI (Control) local side */ + OCT4 teic_local, + /* TEI (Control) remote side */ + OCT4 teic_remote optional, + /* Bearer Contexts to be created */ + BearerConfig bearer optional, + + SessionParsGy gy +} + +template (value) SessionPars +t_SessionPars(hexstring imsi, + template (omit) hexstring msisdn := '1234'H, + GTP2C_RAT_Type rat_type := GTP2C_RAT_EUTRAN, + charstring apn := "internet", + boolean selection_mode := false, + GTP2C_PDN_Type pdn_type := GTP2C_PDN_IPv4) := { + imsi := imsi, + msisdn := msisdn, + rat_type := rat_type, + apn := apn, + selection_mode := selection_mode, + pdn_type := pdn_type, + pco := omit, + epco := omit, + teic_local := '00000000'O, + teic_remote := omit, + bearer := { + ebi := 5, + teid_local := omit, + teid_remote := omit + }, + gy := { + validity_time := 0, + cca_res_code := DIAMETER_SUCCESS + } +} + + +type function void_fn() runs on SMF_Session_CT; + +function f_handler_init(void_fn fn, SessionPars pars) +runs on SMF_Session_CT { + g_pars := valueof(pars); + + if (DIAMETER_PROC[DIA_Gx].checkstate("Connected")) { + f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gx); + } + + if (DIAMETER_PROC[DIA_Gy].checkstate("Connected")) { + f_diameter_expect_imsi(g_pars.imsi, idx := DIA_Gy); + } + + if (DIAMETER_PROC[DIA_S6b].checkstate("Connected")) { + f_diameter_expect_imsi(g_pars.imsi, idx := DIA_S6b); + } + + /* 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(); +} + +/* S6b emulation (AAA-Server) */ +private altstep as_DIA_S6b_AAR() runs on SMF_Session_CT { + var PDU_DIAMETER rx_dia; + [] DIAMETER[DIA_S6b].receive(tr_DIA_S6b_AAR()) -> value rx_dia { + var template (value) PDU_DIAMETER tx_dia; + tx_dia := f_ts_DIA_S6b_AAA(rx_dia, + "aaa." & mp_diam_realm, + mp_diam_realm, + mp_diam_realm); + DIAMETER[DIA_S6b].send(tx_dia); + setverdict(pass); + } + [] DIAMETER[DIA_S6b].receive(PDU_DIAMETER:?) -> value rx_dia { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Received unexpected DIAMETER ", rx_dia)); + } +} + +/* Gx emulation (PCRF)*/ +altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on SMF_Session_CT { + var PDU_DIAMETER rx_dia; + [] DIAMETER[DIA_Gx].receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia { + var template (value) PDU_DIAMETER tx_dia := f_ts_DIA_Gx_CCA(rx_dia); + DIAMETER[DIA_Gx].send(tx_dia); + } + [] DIAMETER[DIA_Gx].receive(PDU_DIAMETER:?) -> value rx_dia { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Received unexpected DIAMETER ", rx_dia)); + } +} + +/* Gy emulation (OCS) */ +private function f_tr_DIA_Gy_CCR_sess(DCC_NONE_CC_Request_Type req_type) +runs on SMF_Session_CT return template (present) PDU_DIAMETER +{ + var octetstring imsi := char2oct(f_dec_TBCD(imsi_hex2oct(g_pars.imsi))); + var octetstring rat_type := int2oct(enum2int(g_pars.rat_type), 1); + var OCT1 nsapi := int2oct(g_pars.bearer.ebi, 1); + var OCT4 charging_char := char2oct(oct2str('0000'O)); // f_s5s8_create_session() uses hardcoded chg_car := '0000'O + var template (present) octetstring msisdn := ?; + var charstring smf_origin_host := "smf." & mp_diam_realm; + var octetstring sgsn_addr := f_inet_addr(mp_pcrf_local_ip); + var octetstring ggsn_addr := f_inet_addr(mp_smf_hostname); + + return DIAMETER_ts32_299_Templates.f_tr_DIA_Gy_CCR(req_type, + imsi, + msisdn, + rat_type, + nsapi, + charging_char, + smf_origin_host, + mp_diam_realm, + sgsn_addr, + ggsn_addr); + +} + +altstep as_DIA_Gy_CCR(DCC_NONE_CC_Request_Type req_type) +runs on SMF_Session_CT { + [] DIAMETER[DIA_Gy].receive(f_tr_DIA_Gy_CCR_sess(req_type := req_type)) -> value g_rx_gy { + var template (value) PDU_DIAMETER tx_dia; + var template (omit) integer validity_time := omit; + if (g_pars.gy.validity_time > 0) { + validity_time := g_pars.gy.validity_time; + } + tx_dia := DIAMETER_ts32_299_Templates.f_ts_DIA_Gy_CCA(g_rx_gy, g_pars.gy.cca_res_code, validity_time); + DIAMETER[DIA_Gy].send(tx_dia); + } + [] DIAMETER[DIA_Gy].receive(PDU_DIAMETER:?) -> value g_rx_gy { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Received unexpected DIAMETER Gy", g_rx_gy)); + } +} + +/* GTPv2C */ +private function is_s2b_iface() runs on SMF_Session_CT return boolean { + return (g_pars.rat_type == GTP2C_RAT_WLAN or g_pars.rat_type == GTP2C_RAT_Virtual); +} + +private function f_perform_ipv6_slaac() runs on SMF_Session_CT +{ + //var UECUPS_IPv6SLAACInd ipv6slaac_ind; + //var template (value) UECUPS_IPv6SLAAC ipv6slaac; + //ipv6slaac := ts_UECUPS_IPv6SLAAC( + // local_gtp_ep := ts_UECUPS_SockAddr(f_inet_addr(mp_local_hostname_u)), + // rx_teid := oct2int(g_pars.bearer.teid_local) + //); + //f_gtp1u_ipv6_slaac(ipv6slaac); + //GTP1U[0].receive(UECUPS_IPv6SLAACInd:?) -> value ipv6slaac_ind; + //log("5GC assigned IPv6 global prefix: ", ipv6slaac_ind.ipv6_prefix, " -> ", f_inet6_ntoa(ipv6slaac_ind.ipv6_prefix & '0000000000000000'O)); + + ///* Use the first global IPv6 address in the IPv6 prefix picked by osmo-uecups: */ + //g_ip6_addr := ipv6slaac_ind.ipv6_user_addr; + //log("Using IPv6 global address: ", g_ip6_addr); +} + +/* process one to-be-created bearer context */ +private function process_bctx_create(BearerContextGrouped bctx) runs on SMF_Session_CT +{ + g_pars.bearer.ebi := bctx.bearerContextIEs.ePS_Bearer_ID.ePS_Bearer_ID_Value; + /* FIXME: Cause */ + + var integer exp_fteid_if_type; + var BIT4 exp_fteid_instance; + if (is_s2b_iface()) { + exp_fteid_if_type := 33; + exp_fteid_instance := '0100'B; + } else { + exp_fteid_if_type := 5; + exp_fteid_instance := '0010'B; + } + + /* find F-TEID of the P-GW U side */ + var FullyQualifiedTEID rx_fteid; + rx_fteid := valueof(f_GTP2C_find_teid(bctx.bearerContextIEs.fullyQualifiedTEID, + exp_fteid_if_type, exp_fteid_instance)); + g_pars.bearer.teid_remote := rx_fteid.tEID_GRE_Key; + if (rx_fteid.v4_Flag == '1'B) { + g_gtpu4_remote := rx_fteid.iPv4_Address; + } + if (rx_fteid.v6_Flag == '1'B) { + g_gtpu6_remote := rx_fteid.iPv6_Address; + } + + if (g_pars.pdn_type == GTP2C_PDN_IPv6 or + g_pars.pdn_type == GTP2C_PDN_IPv4v6) { + f_perform_ipv6_slaac(); + } +} + +/* create a session on the SMF */ +private function f_create_session(template (value) FullyQualifiedTEID fteid_c_ie, + template (value) FullyQualifiedTEID fteid_u_ie, + template (omit) UserLocationInfo uli_ie := omit, + template (omit) APCO apco := omit, + template APCO exp_apco := *) runs on SMF_Session_CT { + var PDU_GTPCv2 rx; + + /* Defaults used for s5/s8: */ + var boolean do_s6b := false; + var template APN_Restriction apn_restriction := ?; + /* Change behavior when on S2b: */ + if (is_s2b_iface()) { + do_s6b := true; + apn_restriction := omit; + } + + var template (value) PDU_GTPCv2 g2c := + ts_GTP2C_CreateSessionReq(imsi := g_pars.imsi, + msisdn := g_pars.msisdn, + rat_type := enum2int(g_pars.rat_type), + sender_fteid := fteid_c_ie, + apn := f_enc_dns_hostname(g_pars.apn), + pdn_type := int2bit(enum2int(g_pars.pdn_type), 3), + teid_list := { fteid_u_ie }, + chg_car := '0000'O, + bearer_id := g_pars.bearer.ebi, + uli := uli_ie, + apco := apco); + g2c.gtpcv2_pdu.createSessionRequest.servingNetwork := ts_GTP2C_ServingNetwork('001'H, '01F'H); + + GTP2.send(g2c); + if (do_s6b and DIAMETER[DIA_S6b].checkstate("Connected")) { + as_DIA_S6b_AAR(); + } + if (DIAMETER[DIA_Gx].checkstate("Connected")) { + as_DIA_Gx_CCR(INITIAL_REQUEST); + } + /* FIXME: When on S2b interface, SMF is not using the Gy interface, unknown reason. */ + if (DIAMETER[DIA_Gy].checkstate("Connected")) { + as_DIA_Gy_CCR(INITIAL_REQUEST); + } + alt { + [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid := g_pars.teic_local, + cause := Request_accepted, + apn_restriction := apn_restriction, + exp_apco := exp_apco)) -> value rx { + /* extract TEIDs */ + var CreateSessionResponse resp := rx.gtpcv2_pdu.createSessionResponse; + g_pars.teic_remote := resp.fullyQualifiedTEID[0].tEID_GRE_Key; + + /* extract allocated address[es] */ + var PDN_Address_and_Prefix paa := resp.pDN_AddressAllocation.pDN_Address_and_Prefix; + if (ischosen(paa.iPv4_Address)) { + g_ip4_addr := paa.iPv4_Address; + log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr)); + } else if (ischosen(paa.iPv6_Address)) { + if (paa.iPv6_Address.prefixLength != 64) { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Got IPv6 Prefix Length ", + paa.iPv6_Address.prefixLength, " vs exp 64")); + } + g_ip6_interface_id := substr(paa.iPv6_Address.iPv6_Address, 8, 8); + log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id); + g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id; + log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr)); + } else if (ischosen(paa.iPv4_IPv6)) { + if (paa.iPv4_IPv6.prefixLength != 64) { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Got IPv6 Prefix Length ", + paa.iPv4_IPv6.prefixLength, " vs exp 64")); + } + g_ip4_addr := paa.iPv4_IPv6.iPv4_Address; + log("SMF assigned UE IPv4 address: ", f_inet_ntoa(g_ip4_addr)); + g_ip6_interface_id := substr(paa.iPv4_IPv6.iPv6_Address, 8, 8); + log("SMF assigned IPv6 Interface Id: ", g_ip6_interface_id); + g_ip6_addr := 'FE80000000000000'O & g_ip6_interface_id; + log("SMF assigned IPv6 link-local Address: ", f_inet6_ntoa(g_ip6_addr)); + } + var integer i; + for (i := 0; i < lengthof(resp.bearerContextGrouped); i := i+1) { + var BearerContextGrouped bctx := resp.bearerContextGrouped[i]; + select (bctx.instance) { + case ('0000'B) { // created + process_bctx_create(bctx); + } + case ('0001'B) { // removed + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + "We don't expect removed bearer contexts yet"); + } + } + } + } + [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_pars.teic_local, cause:=?)) -> value rx { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + log2str("Unexpected CreateSessionResp(cause=", + rx.gtpcv2_pdu.createSessionResponse.cause.causeValue, ")")); + } + [] GTP2.receive { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + "Unexpected GTPv2 while waiting for CreateSessionResp"); + } + } + +} + +/* create a session on the SMF on a S5/S8 interface (from SGW )*/ +function f_s5s8_create_session() runs on SMF_Session_CT { + var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie; + var template (value) UserLocationInfo uli_ie; + + fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0, + f_inet_addr(mp_local_hostname_c), omit); + fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPU, g_pars.bearer.teid_local, 2, + f_inet_addr(mp_local_hostname_u), omit); + + + /* open5gs up to 1.2.3 won't accept it without ULI, despite not mandatory */ + var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O }; + var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 }; + uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi); + + f_create_session(fteid_c_ie, fteid_u_ie, uli_ie); + +} + +/* create a session on the SMF on a S2b interface (from ePDG)*/ +function f_s2b_create_session(template (omit) APCO apco := omit, + template APCO exp_apco := *) runs on SMF_Session_CT { + var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie; + var template (value) UserLocationInfo uli_ie; + + fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S2b_ePDG_GTPC, g_pars.teic_local, 0, + f_inet_addr(mp_local_hostname_c), omit); + fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_ePDG_GTPU, g_pars.bearer.teid_local, 5, + f_inet_addr(mp_local_hostname_u), omit); + + var template (value) TAI tai := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0001'O }; + var template (value) ECGI ecgi := { '0'H, '0'H, '1'H, 'F'H, '0'H, '1'H, '0'H, 23 }; + uli_ie := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi); + + f_create_session(fteid_c_ie, fteid_u_ie, uli_ie := uli_ie, apco := apco, exp_apco := exp_apco); + +} + +/* delete the session from the SMF */ +function f_delete_session(template (omit) GTP2C_Cause tx_cause := omit, + template (present) GTP2C_Cause exp_cause, + boolean expect_diameter := true) runs on SMF_Session_CT { + var template (value) FullyQualifiedTEID fteid_c_ie + fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_pars.teic_local, 0, + f_inet_addr(mp_local_hostname_c), omit); + var template PDU_GTPCv2 g2c := + ts_GTP2C_DeleteSessionReq(d_teid := g_pars.teic_remote, cause := tx_cause, + sender_fteid := fteid_c_ie, + teid_list := {}, bearer_id := g_pars.bearer.ebi); + + GTP2.send(g2c); + if (DIAMETER[DIA_Gx].checkstate("Connected") and expect_diameter) { + as_DIA_Gx_CCR(TERMINATION_REQUEST); + } + if (DIAMETER[DIA_Gy].checkstate("Connected") and expect_diameter) { + as_DIA_Gy_CCR(TERMINATION_REQUEST); + } + alt { + [] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := g_pars.teic_local, cause := exp_cause)) { + setverdict(pass); + } + [] GTP2.receive(tr_GTP2C_DeleteSessionResp(?, ?)) { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + "Unexpected DeleteSessionResp"); + } + [] GTP2.receive { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, + "Unexpected GTPv2 while waiting for DeleteSessionResp"); + } + } +} + +} diff --git a/smf/SMF_Tests.cfg b/smf/SMF_Tests.cfg new file mode 100644 index 0000000..9568e2e --- /dev/null +++ b/smf/SMF_Tests.cfg @@ -0,0 +1,24 @@ +[ORDERED_INCLUDE] +# Common configuration, shared between test suites +"../Common.cfg" +# testsuite specific configuration, not expected to change +"./SMF_Tests.default" + +# Local configuration below + +[LOGGING] + +[TESTPORT_PARAMETERS] + +[MODULE_PARAMETERS] +SMF_Tests.mp_smf_hostname := "127.0.0.4" +SMF_Tests.mp_local_hostname_c := "127.0.0.202" +SMF_Tests.mp_local_hostname_u := "127.0.0.20" +SMF_Tests.mp_pcrf_local_ip:= "127.0.0.202" +SMF_Tests.mp_ocs_local_ip:= "127.0.0.202" +SMF_Tests.mp_aaa_local_ip:= "127.0.0.202" + +[MAIN_CONTROLLER] + +[EXECUTE] +SMF_Tests.control diff --git a/smf/SMF_Tests.default b/smf/SMF_Tests.default new file mode 100644 index 0000000..4c0b502 --- /dev/null +++ b/smf/SMF_Tests.default @@ -0,0 +1,7 @@ +[LOGGING] + +[TESTPORT_PARAMETERS] + +[MODULE_PARAMETERS] + +[EXECUTE] diff --git a/smf/SMF_Tests.ttcn b/smf/SMF_Tests.ttcn new file mode 100644 index 0000000..1e11337 --- /dev/null +++ b/smf/SMF_Tests.ttcn @@ -0,0 +1,365 @@ +module SMF_Tests { + +import from TCCEncoding_Functions all; + +import from General_Types all; +import from Osmocom_Types all; +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; + +import from DNS_Helpers all; + +import from DIAMETER_Types all; +import from DIAMETER_Templates all; +import from DIAMETER_ts29_212_Templates all; +import from DIAMETER_ts29_272_Templates all; +import from DIAMETER_ts29_273_Templates all; +import from DIAMETER_ts32_299_Templates all; +import from DIAMETER_Emulation all; + +import from SMF_Session_CT all; + +modulepar { + charstring mp_smf_hostname := "127.0.0.4"; + charstring mp_local_hostname_c := "127.0.0.1"; + charstring mp_local_hostname_u := "127.0.0.1"; + + charstring mp_pcrf_local_ip := "127.0.0.9"; + integer mp_pcrf_local_port := 3868; + + charstring mp_ocs_local_ip := "127.0.0.9"; + integer mp_ocs_local_port := 3869; + + charstring mp_aaa_local_ip := "127.0.0.9"; + integer mp_aaa_local_port := 3870; + + charstring mp_diam_realm := "localdomain"; +} + +/* main component, we typically have one per testcase */ +type component SMF_Test_CT extends GTP2_ConnHdlr { + var GTPv2_Emulation_CT vc_GTP2; + port GTP2EM_PT TEIC0; + var GTPv1U_Emulation_CT vc_GTP1U; + port GTP1UEM_PT TEID0; + + /* emulated PCRF */ + var DIAMETER_Emulation_CT vc_Gx; + port DIAMETER_PT Gx_UNIT; + port DIAMETEREM_PROC_PT Gx_PROC; + /* emulated OCS */ + var DIAMETER_Emulation_CT vc_Gy; + port DIAMETER_PT Gy_UNIT; + port DIAMETEREM_PROC_PT Gy_PROC; + /* emulated AAA-Server */ + var DIAMETER_Emulation_CT vc_S6b; + port DIAMETER_PT S6b_UNIT; + port DIAMETEREM_PROC_PT S6b_PROC; + /* global test case guard timer (actual timeout value is set in f_init()) */ + timer T_guard; +} + +/* global altstep for global guard timer; */ +altstep as_Tguard() runs on SMF_Test_CT { + [] T_guard.timeout { + setverdict(fail, "Timeout of T_guard"); + mtc.stop; + } +} + +friend function DiameterForwardUnitdataCallback(PDU_DIAMETER msg) +runs on DIAMETER_Emulation_CT return template PDU_DIAMETER { + DIAMETER_UNIT.send(msg); + return omit; +} + +friend function f_init_diameter(charstring id) runs on SMF_Test_CT { + var DIAMETEROps ops := { + create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback), + unitdata_cb := refers(DiameterForwardUnitdataCallback), + raw := false /* handler mode (IMSI based routing) */ + }; + var DIAMETER_conn_parameters pars; + + /* Gx setup: */ + pars := { + remote_ip := mp_smf_hostname, + remote_sctp_port := -1, + local_ip := mp_pcrf_local_ip, + local_sctp_port := mp_pcrf_local_port, + origin_host := "pcrf." & mp_diam_realm, + origin_realm := mp_diam_realm, + auth_app_id := omit, + vendor_app_id := c_DIAMETER_3GPP_Gx_AID + }; + vc_Gx := DIAMETER_Emulation_CT.create(id); + map(vc_Gx:DIAMETER, system:DIAMETER_CODEC_PT); + connect(vc_Gx:DIAMETER_UNIT, self:Gx_UNIT); + connect(vc_Gx:DIAMETER_PROC, self:Gx_PROC); + vc_Gx.start(DIAMETER_Emulation.main(ops, pars, id)); + + /* Gy setup: */ + pars := { + remote_ip := mp_smf_hostname, + remote_sctp_port := -1, + local_ip := mp_ocs_local_ip, + local_sctp_port := mp_ocs_local_port, + origin_host := "ocs." & mp_diam_realm, + origin_realm := mp_diam_realm, + auth_app_id := c_DIAMETER_CREDIT_CONTROL_AID, + vendor_app_id := omit + }; + vc_Gy := DIAMETER_Emulation_CT.create(id); + map(vc_Gy:DIAMETER, system:DIAMETER_CODEC_PT); + connect(vc_Gy:DIAMETER_UNIT, self:Gy_UNIT); + connect(vc_Gy:DIAMETER_PROC, self:Gy_PROC); + vc_Gy.start(DIAMETER_Emulation.main(ops, pars, id)); + + /* S6b setup: */ + pars := { + remote_ip := mp_smf_hostname, + remote_sctp_port := -1, + local_ip := mp_aaa_local_ip, + local_sctp_port := mp_aaa_local_port, + origin_host := "aaa." & mp_diam_realm, + origin_realm := mp_diam_realm, + auth_app_id := c_DIAMETER_3GPP_S6b_AID, + vendor_app_id := c_DIAMETER_3GPP_S6b_AID + }; + vc_S6b := DIAMETER_Emulation_CT.create(id); + map(vc_S6b:DIAMETER, system:DIAMETER_CODEC_PT); + connect(vc_S6b:DIAMETER_UNIT, self:S6b_UNIT); + connect(vc_S6b:DIAMETER_PROC, self:S6b_PROC); + vc_S6b.start(DIAMETER_Emulation.main(ops, pars, id)); + + f_diameter_wait_capability(Gx_UNIT); + f_diameter_wait_capability(Gy_UNIT); + f_diameter_wait_capability(S6b_UNIT); + /* Give some time for our emulation to get out of SUSPECT list of SUT (3 watchdog ping-pongs): + * RFC6733 sec 5.1 + * RFC3539 sec 3.4.1 [5] + * https://github.com/freeDiameter/freeDiameter/blob/master/libfdcore/p_psm.c#L... + */ + f_sleep(1.0); +} + +private function f_init_gtp2c() runs on SMF_Test_CT { + var Gtp2EmulationCfg cfg := { + gtpc_bind_ip := mp_local_hostname_c, + gtpc_bind_port := GTP2C_PORT, + gtpc_remote_ip := mp_smf_hostname, + gtpc_remote_port := GTP2C_PORT, + sgw_role := true + }; + + vc_GTP2 := GTPv2_Emulation_CT.create("GTP2C_EM"); + map(vc_GTP2:GTP2C, system:GTP2C); + 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 SMF_Test_CT { + var Gtp1uEmulationCfg cfg := { + gtpu_bind_ip := omit, /* using gtpu daemon */ + gtpu_bind_port := omit, /* using gtpu daemon */ + use_gtpu_daemon := false + }; + + vc_GTP1U := GTPv1U_Emulation_CT.create("GTP1U_EM"); + map(vc_GTP1U:GTP1U, system:GTP1U); + vc_GTP1U.start(GTPv1U_Emulation.main(cfg)); +} + +private function f_init(float guard_timeout := 60.0) runs on SMF_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()); + } +} + +function f_start_handler(void_fn fn, template (omit) SessionPars pars_tmpl := omit) +runs on SMF_Test_CT return SMF_Session_CT { + var charstring id := testcasename(); + var SMF_Session_CT vc_conn; + var SessionPars pars; + + if (isvalue(pars_tmpl)) { + pars := valueof(pars_tmpl); + } else { + /*TODO: set default values */ + } + + vc_conn := SMF_Session_CT.create(id); + connect(vc_conn:GTP2, vc_GTP2:CLIENT); + connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC); + connect(vc_conn:GTP1U[0], vc_GTP1U:CLIENT); + connect(vc_conn:GTP1U_PROC[0], vc_GTP1U:CLIENT_PROC); + + 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); + } + + if (isbound(vc_Gy)) { + connect(vc_conn:DIAMETER_PROC[DIA_Gy], vc_Gy:DIAMETER_PROC); + connect(vc_conn:DIAMETER[DIA_Gy], vc_Gy:DIAMETER_CLIENT); + } + + if (isbound(vc_S6b)) { + connect(vc_conn:DIAMETER_PROC[DIA_S6b], vc_S6b:DIAMETER_PROC); + connect(vc_conn:DIAMETER[DIA_S6b], vc_S6b:DIAMETER_CLIENT); + } + + vc_conn.start(f_handler_init(fn, pars)); + return vc_conn; +} + +/* send echo request; expect response */ +testcase TC_tx_echo() runs on SMF_Test_CT { + timer T := 5.0; + + f_init(); + + GTP2.send(ts_GTP2C_EchoReq(0)); + T.start; + alt { + [] GTP2.receive(tr_GTP2C_EchoResp) { + setverdict(pass); + } + [] T.timeout { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "timeout waiting for Echo Response"); + } + } +} + +/* create a session, expect it to succeed */ +private function f_TC_createSession() runs on SMF_Session_CT { + f_s5s8_create_session(); + setverdict(pass); +} +testcase TC_createSession() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H, + pdn_type := GTP2C_PDN_IPv4)); + f_init(); + vc_conn := f_start_handler(refers(f_TC_createSession), pars); + vc_conn.done; +} + +/* create a session, then delete it again */ +private function f_TC_createSession_deleteSession() runs on SMF_Session_CT { + f_s5s8_create_session(); + f_delete_session(omit, Request_accepted); + setverdict(pass); +} +testcase TC_createSession_deleteSession() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H)); + f_init(); + vc_conn := f_start_handler(refers(f_TC_createSession_deleteSession), pars); + vc_conn.done; +} + +/* send a DeleteSessionReq for an unknown/invalid TEID */ +private function f_TC_deleteSession_unknown() runs on SMF_Session_CT { + g_pars.teic_remote := f_rnd_octstring(4); + f_delete_session(omit, Context_Not_Found, false); + setverdict(pass); +} +testcase TC_deleteSession_unknown() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H)); + f_init(); + vc_conn := f_start_handler(refers(f_TC_deleteSession_unknown), pars); + vc_conn.done; +} + +/* Test Gy CCR rejected with CCA Result-Code DIAMETER_AUTHORIZATION_REJECTED (5003) */ +private function f_TC_gy_ccr_update_rejected() runs on SMF_Session_CT { + var default d; + + f_s5s8_create_session(); + + /* We should receive an update even if no traffic is sent: */ + as_DIA_Gy_CCR(UPDATE_REQUEST); + + /* Answer next CCR[Update] with CCA Reject: */ + g_pars.gy.cca_res_code := DIAMETER_AUTHORIZATION_REJECTED; + as_DIA_Gy_CCR(UPDATE_REQUEST); + + /* Expect SMF to tear down the connection as a result: */ + as_DIA_Gx_CCR(TERMINATION_REQUEST); + as_DIA_Gy_CCR(TERMINATION_REQUEST); + + setverdict(pass); +} +testcase TC_gy_ccr_update_rejected() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H)); + pars.gy.validity_time := 3; /* Grant access for 3 seconds, needs to be re-validated afterwards */ + f_init(); + vc_conn := f_start_handler(refers(f_TC_gy_ccr_update_rejected), pars); + vc_conn.done; +} + +/* create a session, expect it to succeed */ +private function f_TC_s2b_createSession_v4_noapco() runs on SMF_Session_CT { + var template (omit) APCO apco := omit; + var template APCO exp_apco := omit; + f_s2b_create_session(apco, exp_apco); + setverdict(pass); +} +testcase TC_s2b_createSession_v4_noapco() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H, + rat_type := GTP2C_RAT_WLAN)); + f_init(); + vc_conn := f_start_handler(refers(f_TC_s2b_createSession_v4_noapco), pars); + vc_conn.done; +} + +private function f_TC_s2b_createSession_v4_apco() runs on SMF_Session_CT { + var template (omit) APCO apco := ts_GTP2C_APCO('0000'B, + {ts_GTP2C_PCO_P_DNS_IPv4(''O), + ts_GTP2C_PCO_P_PCSCF_IPv4(''O)}); + var template APCO exp_apco := tr_GTP2C_APCO('0000'B, + {tr_GTP2C_PCO_P_DNS_IPv4(?), + *, /* open5gs-smfd can contain several DNS servers */ + tr_GTP2C_PCO_P_PCSCF_IPv4(?)}); + f_s2b_create_session(apco, exp_apco); + setverdict(pass); +} +testcase TC_s2b_createSession_v4_apco() runs on SMF_Test_CT { + var SMF_Session_CT vc_conn; + var SessionPars pars := valueof(t_SessionPars('001010123456789'H, + rat_type := GTP2C_RAT_WLAN)); + f_init(); + vc_conn := f_start_handler(refers(f_TC_s2b_createSession_v4_apco), pars); + vc_conn.done; +} + +control { + execute( TC_tx_echo() ); + execute( TC_createSession() ); + execute( TC_createSession_deleteSession() ); + execute( TC_deleteSession_unknown() ); + execute( TC_gy_ccr_update_rejected() ); + execute( TC_s2b_createSession_v4_noapco() ); + execute( TC_s2b_createSession_v4_apco() ); +} + + +} diff --git a/smf/expected-results.xml b/smf/expected-results.xml new file mode 100644 index 0000000..fc32e75 --- /dev/null +++ b/smf/expected-results.xml @@ -0,0 +1,4 @@ +<?xml version="1.0"?> +<testsuite name='Titan' tests='1' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'> + <testcase classname='SMF_Tests' name='TC_tx_echo' time='MASKED'/> +</testsuite> diff --git a/smf/freediameter.conf b/smf/freediameter.conf new file mode 100644 index 0000000..266f894 --- /dev/null +++ b/smf/freediameter.conf @@ -0,0 +1,20 @@ +# See https://github.com/open5gs/freeDiameter/blob/main/doc/freediameter.conf.samp... + +Identity = "smf.localdomain"; +Realm = "localdomain"; +Port = 3868; +SecPort = 0; +ListenOn = "127.0.0.4"; +NoRelay; + +LoadExtension = "dbg_msg_dumps.fdx" : "0x8888"; +LoadExtension = "dict_rfc5777.fdx"; +LoadExtension = "dict_mip6i.fdx"; +LoadExtension = "dict_nasreq.fdx"; +LoadExtension = "dict_nas_mipv6.fdx"; +LoadExtension = "dict_dcca.fdx"; +LoadExtension = "dict_dcca_3gpp.fdx"; + +ConnectPeer = "pcrf.localdomain" { ConnectTo = "127.0.0.202"; No_TLS; TcTimer = 2; }; +ConnectPeer = "ocs.localdomain" { ConnectTo = "127.0.0.202"; Port = 3869; No_TLS; TcTimer = 2; }; +ConnectPeer = "aaa.localdomain" { ConnectTo = "127.0.0.202"; Port = 3870; No_TLS; TcTimer = 2; }; diff --git a/smf/gen_links.sh b/smf/gen_links.sh new file mode 100755 index 0000000..1f56b9c --- /dev/null +++ b/smf/gen_links.sh @@ -0,0 +1,68 @@ +#!/bin/bash -e + +BASEDIR=../deps + +. ../_buildsystem/gen_links.inc.sh + +DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src +FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h" +FILES+=" TCCEncoding_Functions.ttcn TCCEncoding.cc " # BCD coding +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src +FILES="Socket_API_Definitions.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.TestPorts.IPL4asp/src +FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.ICMP/src +FILES="ICMP_EncDec.cc ICMP_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.ICMPv6/src +FILES="ICMPv6_EncDec.cc ICMPv6_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.IP/src +FILES="IP_EncDec.cc IP_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.UDP/src +FILES="UDP_EncDec.cc UDP_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.NS_v7.3.0/src +FILES="NS_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.BSSGP_v13.0.0/src +FILES="BSSGP_EncDec.cc BSSGP_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.GTP_v13.5.0/src +FILES="GTPC_EncDec.cc GTPC_Types.ttcn GTPU_EncDec.cc GTPU_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.GTPv2_v13.7.0/src +FILES="GTPv2_Types.ttcn" +gen_links $DIR $FILES + +DIR=$BASEDIR/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src +FILES="DIAMETER_EncDec.cc" +gen_links $DIR $FILES + +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 GTPv1C_Templates.ttcn Osmocom_Gb_Types.ttcn " +FILES+="GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1U_Emulation.ttcnpp " +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 " +FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn " +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 " +gen_links $DIR $FILES + +gen_links_finish diff --git a/smf/open5gs-nrf.yaml b/smf/open5gs-nrf.yaml new file mode 100644 index 0000000..0979be0 --- /dev/null +++ b/smf/open5gs-nrf.yaml @@ -0,0 +1,40 @@ +# See https://github.com/open5gs/open5gs/blob/main/configs/open5gs/nrf.yaml.in + +db_uri: mongodb://localhost/open5gs + +logger: + level: info + +global: + max: + ue: 1024 + +sbi: + server: + no_tls: true + cacert: /etc/open5gs/tls/ca.crt + key: /etc/open5gs/tls/nrf.key + cert: /etc/open5gs/tls/nrf.crt + client: + no_tls: true + cacert: /etc/open5gs/tls/ca.crt + key: /etc/open5gs/tls/nrf.key + cert: /etc/open5gs/tls/nrf.crt + +nrf: + sbi: + server: + - address: 127.0.0.10 + port: 7777 + +scp: + sbi: + - addr: 127.0.1.10 + port: 7777 + + +parameter: + +max: + +time: diff --git a/smf/open5gs-smf.yaml b/smf/open5gs-smf.yaml new file mode 100644 index 0000000..34aabc3 --- /dev/null +++ b/smf/open5gs-smf.yaml @@ -0,0 +1,72 @@ +# See https://github.com/open5gs/open5gs/blob/main/configs/open5gs/smf.yaml.in + +logger: + level: info + +global: + max: + ue: 1024 + +sbi: + server: + no_tls: true + cacert: /etc/open5gs/tls/ca.crt + key: /etc/open5gs/tls/smf.key + cert: /etc/open5gs/tls/smf.crt + client: + no_tls: true + cacert: /etc/open5gs/tls/ca.crt + key: /etc/open5gs/tls/smf.key + cert: /etc/open5gs/tls/smf.crt + +smf: + sbi: + server: + - address: 127.0.0.4 + port: 7777 + client: + nrf: + - uri: http://127.0.0.10:7777 + scp: + - uri: http://127.0.1.10:7777 + pfcp: + server: + - address: 127.0.0.4 + client: + upf: + - address: 127.0.0.7 + gtpc: + server: + - address: 127.0.0.4 + gtpu: + server: + - address: 127.0.0.4 + metrics: + server: + - address: 127.0.0.4 + port: 9090 + session: + - subnet: 10.45.0.0/16 + gateway: 10.45.0.1 + dnn: internet + - subnet: 2001:db8:cafe::/48 + gateway: 2001:db8:cafe::1 + dnn: internet + dns: + - 8.8.8.8 + - 8.8.4.4 + - 2001:4860:4860::8888 + - 2001:4860:4860::8844 + mtu: 1400 + p-cscf: + - 127.0.0.7 + - fd02:db8:18::7 + ctf: + enabled: auto + freeDiameter: freediameter.conf + +parameter: + +max: + +time: diff --git a/smf/regen_makefile.sh b/smf/regen_makefile.sh new file mode 100755 index 0000000..51a50d4 --- /dev/null +++ b/smf/regen_makefile.sh @@ -0,0 +1,30 @@ +#!/bin/sh -e + +NAME=SMF_Tests + +FILES=" + *.ttcn + *.ttcnpp + BSSGP_EncDec.cc + DIAMETER_CodecPort_CtrlFunctDef.cc + DIAMETER_EncDec.cc + GTPC_EncDec.cc + GTPU_EncDec.cc + GTPv1C_CodecPort_CtrlFunctDef.cc + GTPv1U_CodecPort_CtrlFunctDef.cc + GTPv2_CodecPort_CtrlFunctDef.cc + ICMP_EncDec.cc + ICMPv6_EncDec.cc + IPL4asp_PT.cc + IPL4asp_discovery.cc + IP_EncDec.cc + Native_FunctionDefs.cc + TCCConversion.cc + TCCInterface.cc + TCCEncoding.cc + UDP_EncDec.cc +" + +CPPFLAGS_TTCN3="" + +. ../_buildsystem/regen_makefile.inc.sh diff --git a/smf/testenv.cfg b/smf/testenv.cfg new file mode 100644 index 0000000..b6cbb10 --- /dev/null +++ b/smf/testenv.cfg @@ -0,0 +1,15 @@ +[testsuite] +program=SMF_Tests +config=SMF_Tests.cfg + +[nrf] +program=open5gs-nrfd -c open5gs-nrf.yaml +make=open5gs +package=open5gs-nrf +copy=open5gs-nrf.yaml + +[smf] +program=open5gs-smfd -c open5gs-smf.yaml +make=open5gs +package=open5gs-smf +copy=open5gs-smf.yaml freediameter.conf