aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.checkpatch.conf2
-rw-r--r--.github/FUNDING.yml1
-rw-r--r--.gitignore4
-rw-r--r--Common.cfg2
-rw-r--r--Makefile51
-rw-r--r--README.md30
-rwxr-xr-xSCCP_Test/regen_makefile.sh12
-rw-r--r--asterisk/AMI_Functions.ttcn212
-rw-r--r--asterisk/Asterisk_Tests.cfg18
-rw-r--r--asterisk/Asterisk_Tests.default29
-rw-r--r--asterisk/Asterisk_Tests.ttcn276
-rw-r--r--asterisk/README.md16
-rw-r--r--asterisk/SIP_ConnectionHandler.ttcn707
-rw-r--r--asterisk/expected-results.xml8
-rwxr-xr-xasterisk/gen_links.sh46
-rwxr-xr-xasterisk/regen_makefile.sh22
-rw-r--r--bsc-nat/BSCNAT_Tests.ttcn2
-rw-r--r--bsc-nat/BSC_MS_ConnectionHandler.ttcn2
-rw-r--r--bsc-nat/MSC_ConnectionHandler.ttcn1
-rwxr-xr-xbsc-nat/gen_links.sh2
-rwxr-xr-xbsc-nat/regen_makefile.sh31
-rw-r--r--bsc/BSC_Tests.cfg2
-rw-r--r--bsc/BSC_Tests.default9
-rw-r--r--bsc/BSC_Tests.ttcn8173
-rw-r--r--bsc/BSC_Tests_ASCI.ttcn808
-rw-r--r--bsc/BSC_Tests_CBSP.ttcn885
-rw-r--r--bsc/BSC_Tests_LCLS.ttcn46
-rw-r--r--bsc/BSC_Tests_OML.ttcn374
-rw-r--r--bsc/BSC_Tests_SCCPlite.cfg35
-rw-r--r--bsc/BSC_Tests_VAMOS.cfg18
-rw-r--r--bsc/BSC_Tests_VAMOS.ttcn796
-rw-r--r--bsc/MSC_ConnectionHandler.ttcn843
-rw-r--r--bsc/README.md3
-rw-r--r--bsc/README.txt2
-rw-r--r--bsc/expected-results.xml239
-rwxr-xr-xbsc/gen_links.sh6
-rw-r--r--bsc/osmo-bsc-sccplite.cfg366
-rw-r--r--bsc/osmo-bsc-vamos.cfg418
-rw-r--r--bsc/osmo-bsc.cfg179
-rw-r--r--bsc/osmo-stp.cfg37
-rwxr-xr-xbsc/regen_makefile.sh37
-rw-r--r--bts/BTS_Tests.cfg15
-rw-r--r--bts/BTS_Tests.default57
-rw-r--r--bts/BTS_Tests.ttcn3945
-rw-r--r--bts/BTS_Tests_ASCI.ttcn423
-rw-r--r--bts/BTS_Tests_LAPDm.ttcn186
-rw-r--r--bts/BTS_Tests_OML.ttcn254
-rw-r--r--bts/BTS_Tests_SMSCB.ttcn51
-rw-r--r--bts/BTS_Tests_VAMOS.ttcn334
-rw-r--r--bts/expected-results.xml162
-rwxr-xr-xbts/gen_links.sh9
-rw-r--r--bts/osmo-bsc.cfg132
-rw-r--r--bts/osmo-bts.cfg70
-rwxr-xr-xbts/regen_makefile.sh31
-rwxr-xr-xbts/run_fake_trx.sh11
-rw-r--r--cbc/BSC_ConnectionHandler.ttcn206
-rw-r--r--cbc/CBC_Tests.cfg18
-rw-r--r--cbc/CBC_Tests.default12
-rw-r--r--cbc/CBC_Tests.ttcn937
-rw-r--r--cbc/CBS_Message.ttcn50
-rw-r--r--cbc/ECBE_Components.ttcn139
-rw-r--r--cbc/ECBE_Types.ttcn147
-rw-r--r--cbc/MME_ConnectionHandler.ttcn146
-rw-r--r--cbc/expected-results.xml32
-rwxr-xr-xcbc/gen_links.sh62
-rwxr-xr-xcbc/regen_makefile.sh32
-rw-r--r--ccid/CCID_Tests.ttcn139
-rwxr-xr-xccid/gen_links.sh6
-rwxr-xr-xccid/regen_makefile.sh14
-rw-r--r--deps/Makefile126
-rw-r--r--dia2gsup/DIA2GSUP_Tests.cfg19
-rw-r--r--dia2gsup/DIA2GSUP_Tests.default8
-rw-r--r--dia2gsup/DIA2GSUP_Tests.ttcn362
-rwxr-xr-xdia2gsup/gen_links.sh46
-rwxr-xr-xdia2gsup/regen_makefile.sh25
-rw-r--r--doc/bsc_tests_aoip.dot81
-rw-r--r--doc/bts_tests.dot49
-rw-r--r--doc/gb_stack_fr.dot48
-rw-r--r--doc/gb_stack_ip.dot43
-rw-r--r--doc/msc_tests_aoip.dot89
-rw-r--r--doc/ran_emulation_aoip.dot39
-rw-r--r--doc/ran_emulation_sccplite.dot39
-rw-r--r--epdg/EPDG_Tests.cfg19
-rw-r--r--epdg/EPDG_Tests.default8
-rw-r--r--epdg/EPDG_Tests.ttcn1349
-rw-r--r--epdg/expected-results.xml18
-rwxr-xr-xepdg/gen_links.sh68
-rwxr-xr-xepdg/regen_makefile.sh31
-rw-r--r--fr-net/FRNET_Tests.cfg18
-rw-r--r--fr-net/FRNET_Tests.default22
-rw-r--r--fr-net/FRNET_Tests.ttcn142
-rwxr-xr-xfr-net/gen_links.sh55
-rwxr-xr-xfr-net/regen_makefile.sh23
-rw-r--r--fr/FR_Tests.cfg16
-rw-r--r--fr/FR_Tests.default16
-rw-r--r--fr/FR_Tests.ttcn320
-rwxr-xr-xfr/gen_links.sh55
-rwxr-xr-xfr/regen_makefile.sh24
-rw-r--r--gbproxy/GBProxy_Tests.cfg27
-rw-r--r--gbproxy/GBProxy_Tests.default32
-rw-r--r--gbproxy/GBProxy_Tests.fr.cfg119
-rw-r--r--gbproxy/GBProxy_Tests.ttcn3805
-rw-r--r--gbproxy/README.md18
-rw-r--r--gbproxy/expected-results.xml79
-rwxr-xr-xgbproxy/gen_links.sh98
-rw-r--r--gbproxy/osmo-gbproxy.cfg47
-rw-r--r--gbproxy/osmo-gbproxy.fr.cfg60
-rwxr-xr-xgbproxy/regen_makefile.sh36
-rw-r--r--gen_links.sh.inc2
-rw-r--r--ggsn_tests/GGSN_Tests.cfg4
-rw-r--r--ggsn_tests/GGSN_Tests.default1
-rw-r--r--ggsn_tests/GGSN_Tests.ttcn1679
-rwxr-xr-xggsn_tests/gen_links.sh19
-rw-r--r--ggsn_tests/osmo-ggsn.cfg83
-rwxr-xr-xggsn_tests/regen_makefile.sh29
-rw-r--r--hlr/HLR_EUSE.ttcn1
-rw-r--r--hlr/HLR_Tests.cfg1
-rw-r--r--hlr/HLR_Tests.ttcn223
-rw-r--r--hlr/expected-results.xml34
-rwxr-xr-xhlr/gen_links.sh3
-rwxr-xr-xhlr/regen_makefile.sh27
-rw-r--r--hnbgw/HNBGW_Tests.cfg18
-rw-r--r--hnbgw/HNBGW_Tests.default28
-rw-r--r--hnbgw/HNBGW_Tests.ttcn2933
-rw-r--r--hnbgw/expected-results.xml50
-rwxr-xr-xhnbgw/gen_links.sh110
-rw-r--r--hnbgw/osmo-hnbgw-with-pfcp.cfg133
-rw-r--r--hnbgw/osmo-hnbgw.cfg147
-rw-r--r--hnbgw/osmo-stp.cfg96
-rwxr-xr-xhnbgw/regen_makefile.sh41
-rw-r--r--hnodeb/HNBGW_ConnectionHandler.ttcn295
-rw-r--r--hnodeb/HNB_Tests.cfg18
-rw-r--r--hnodeb/HNB_Tests.default28
-rw-r--r--hnodeb/HNB_Tests.ttcn470
-rw-r--r--hnodeb/README.md30
-rw-r--r--hnodeb/README.txt32
-rw-r--r--hnodeb/expected-results.xml10
-rwxr-xr-xhnodeb/gen_links.sh71
-rw-r--r--hnodeb/osmo-hnodeb.cfg19
-rwxr-xr-xhnodeb/regen_makefile.sh40
-rw-r--r--hss/HSS_Tests.cfg18
-rw-r--r--hss/HSS_Tests.default7
-rw-r--r--hss/HSS_Tests.ttcn275
-rw-r--r--hss/expected-results.xml5
-rwxr-xr-xhss/gen_links.sh30
-rwxr-xr-xhss/regen_makefile.sh20
-rwxr-xr-xlapdm/regen_makefile.sh15
-rw-r--r--library/AMR_Types.ttcn91
-rw-r--r--library/AbisOML_Types.ttcn62
-rw-r--r--library/BSSAP_CodecPort.ttcn2
-rw-r--r--library/BSSAP_LE_Adapter.ttcn137
-rw-r--r--library/BSSAP_LE_CodecPort.ttcn380
-rw-r--r--library/BSSAP_LE_Emulation.ttcn731
-rw-r--r--library/BSSAP_LE_Types.ttcn594
-rw-r--r--library/BSSGP_Emulation.ttcn769
-rw-r--r--library/BSSGP_Emulation.ttcnpp1459
-rw-r--r--library/BSSLAP_Types.ttcn606
-rw-r--r--library/BSSMAP_LE_Templates.ttcn455
-rw-r--r--library/BSSMAP_Templates.ttcn1323
-rw-r--r--library/CBSP_Adapter.ttcn23
-rw-r--r--library/CBSP_Templates.ttcn336
-rw-r--r--library/CBSP_Types.ttcn29
-rw-r--r--library/DIAMETER_Emulation.ttcn241
-rw-r--r--library/DIAMETER_Templates.ttcn1112
-rw-r--r--library/DIAMETER_Types.ttcn8636
-rw-r--r--library/DIAMETER_rfc4004_Templates.ttcn34
-rw-r--r--library/DIAMETER_rfc5447_Templates.ttcn54
-rw-r--r--library/DIAMETER_ts29_212_Templates.ttcn69
-rw-r--r--library/DIAMETER_ts29_229_Templates.ttcn78
-rw-r--r--library/DIAMETER_ts29_272_Templates.ttcn710
-rw-r--r--library/DIAMETER_ts29_273_Templates.ttcn677
-rw-r--r--library/DIAMETER_ts32_299_Templates.ttcn184
-rw-r--r--library/DNS_Helpers.ttcn2
-rw-r--r--library/GSMTAP_Types.ttcn3
-rw-r--r--library/GSM_RR_Types.ttcn794
-rw-r--r--library/GSM_RestOctets.ttcn613
-rw-r--r--library/GSM_SystemInformation.ttcn20
-rw-r--r--library/GSM_Types.ttcn583
-rw-r--r--library/GSUP_Emulation.ttcn75
-rw-r--r--library/GSUP_Templates.ttcn1845
-rw-r--r--library/GSUP_Types.ttcn1469
-rw-r--r--library/GTP_Emulation.ttcn56
-rw-r--r--library/GTP_Templates.ttcn747
-rw-r--r--library/GTPv1C_CodecPort.ttcn65
-rw-r--r--library/GTPv1C_CodecPort_CtrlFunct.ttcn (renamed from library/GTP_CodecPort_CtrlFunct.ttcn)12
-rw-r--r--library/GTPv1C_CodecPort_CtrlFunctDef.cc (renamed from library/NS_CodecPort_CtrlFunctDef.cc)23
-rw-r--r--library/GTPv1C_Templates.ttcn1845
-rw-r--r--library/GTPv1U_CodecPort.ttcn (renamed from library/GTP_CodecPort.ttcn)44
-rw-r--r--library/GTPv1U_CodecPort_CtrlFunct.ttcn13
-rw-r--r--library/GTPv1U_CodecPort_CtrlFunctDef.cc17
-rw-r--r--library/GTPv1U_Templates.ttcn167
-rw-r--r--library/GTPv2_CodecPort.ttcn4
-rw-r--r--library/GTPv2_Emulation.ttcn238
-rw-r--r--library/GTPv2_Templates.ttcn481
-rw-r--r--library/General_Types.ttcn10
-rw-r--r--library/HNBLLIF_CodecPort.ttcn95
-rw-r--r--library/HNBLLIF_Templates.ttcn561
-rw-r--r--library/HNBLLIF_Types.ttcn532
-rw-r--r--library/HTTP_Adapter.ttcn113
-rw-r--r--library/HTTP_Server_Emulation.ttcn147
-rw-r--r--library/ICMP_Templates.ttcn96
-rw-r--r--library/ICMPv6_Templates.ttcn238
-rw-r--r--library/IPA_Emulation.ttcnpp98
-rw-r--r--library/IPA_Types.ttcn3
-rw-r--r--library/IuUP_Emulation.ttcn104
-rw-r--r--library/IuUP_Types.ttcn185
-rw-r--r--library/Iuh_CodecPort.ttcn137
-rw-r--r--library/Iuh_CodecPort_CtrlFunct.ttcn (renamed from library/NS_CodecPort_CtrlFunct.ttcn)15
-rw-r--r--library/Iuh_CodecPort_CtrlFunctDef.cc55
-rw-r--r--library/Iuh_Emulation.ttcn225
-rw-r--r--library/Iuh_Types.ttcn36
-rw-r--r--library/L1CTL_PortType.ttcn185
-rw-r--r--library/L1CTL_Types.ttcn864
-rw-r--r--library/L3_Common.ttcn64
-rw-r--r--library/L3_Templates.ttcn504
-rw-r--r--library/LAPDm_RAW_PT.ttcn35
-rw-r--r--library/LAPDm_Types.ttcn76
-rw-r--r--library/M3UA_CodecPort.ttcn30
-rw-r--r--library/M3UA_CodecPort_CtrlFunct.ttcn7
-rw-r--r--library/M3UA_CodecPort_CtrlFunctDef.cc9
-rw-r--r--library/M3UA_Templates.ttcn215
-rw-r--r--library/MGCP_CodecPort.ttcn4
-rw-r--r--library/MGCP_Emulation.ttcn37
-rw-r--r--library/MGCP_Templates.ttcn771
-rw-r--r--library/MGCP_Types.ttcn7
-rw-r--r--library/MNCC_Emulation.ttcn23
-rw-r--r--library/MNCC_EncDec.cc74
-rw-r--r--library/MNCC_Types.ttcn141
-rw-r--r--library/Misc_Helpers.ttcn74
-rw-r--r--library/NAS_Templates.ttcn294
-rw-r--r--library/NS_CodecPort.ttcn61
-rw-r--r--library/NS_Emulation.ttcn339
-rw-r--r--library/NS_Emulation.ttcnpp1044
-rw-r--r--library/NS_Provider_FR.ttcn105
-rw-r--r--library/NS_Provider_IPL4.ttcn229
-rw-r--r--library/NS_Types.ttcn2
-rw-r--r--library/Native_FunctionDefs.cc13
-rw-r--r--library/Native_Functions.ttcn2
-rw-r--r--library/OPCAP_Adapter.ttcn105
-rw-r--r--library/OPCAP_CodecPort.ttcn64
-rw-r--r--library/OPCAP_CodecPort_CtrlFunct.ttcn52
-rw-r--r--library/OPCAP_CodecPort_CtrlFunctdef.cc (renamed from library/GTP_CodecPort_CtrlFunctDef.cc)30
-rw-r--r--library/OPCAP_Templates.ttcn54
-rw-r--r--library/OPCAP_Types.ttcn78
-rw-r--r--library/OSMUX_Emulation.ttcn80
-rw-r--r--library/OSMUX_Types.ttcn61
-rw-r--r--library/Osmocom_CTRL_Adapter.ttcn81
-rw-r--r--library/Osmocom_CTRL_Functions.ttcn120
-rw-r--r--library/Osmocom_CTRL_Types.ttcn2
-rw-r--r--library/Osmocom_Gb_Types.ttcn2533
-rw-r--r--library/Osmocom_Types.ttcn373
-rw-r--r--library/Osmocom_VTY_Functions.ttcn195
-rw-r--r--library/PCO_Types.ttcn151
-rw-r--r--library/PCUIF_CodecPort.ttcn66
-rw-r--r--library/PCUIF_Types.ttcn612
-rw-r--r--library/PFCP_CodecPort.ttcn56
-rw-r--r--library/PFCP_CodecPort_CtrlFunct.ttcn43
-rw-r--r--library/PFCP_CodecPort_CtrlFunctDef.cc55
-rw-r--r--library/PFCP_Emulation.ttcn202
-rw-r--r--library/PFCP_Templates.ttcn664
-rw-r--r--library/RAN_Adapter.ttcnpp8
-rw-r--r--library/RAN_Emulation.ttcnpp241
-rw-r--r--library/RAW_NS.ttcnpp583
-rw-r--r--library/RLCMAC_CSN1_Templates.ttcn362
-rw-r--r--library/RLCMAC_CSN1_Types.ttcn505
-rw-r--r--library/RLCMAC_EncDec.cc196
-rw-r--r--library/RLCMAC_Templates.ttcn269
-rw-r--r--library/RLCMAC_Types.ttcn74
-rw-r--r--library/RSL_Emulation.ttcn103
-rw-r--r--library/RSL_Types.ttcn891
-rw-r--r--library/RTP_Emulation.ttcn216
-rw-r--r--library/S1AP_Emulation.ttcn284
-rw-r--r--library/SCCP_Templates.ttcn258
-rw-r--r--library/SDP_Templates.ttcn159
-rw-r--r--library/SGsAP_Emulation.ttcn2
-rw-r--r--library/SGsAP_Templates.ttcn29
-rw-r--r--library/SIMTRACE_Emulation.ttcn (renamed from simtrace/SIMTRACE_Emulation.ttcn)0
-rw-r--r--library/SIMTRACE_Templates.ttcn (renamed from simtrace/SIMTRACE_Templates.ttcn)6
-rw-r--r--library/SIMTRACE_Types.ttcn (renamed from simtrace/SIMTRACE_Types.ttcn)3
-rw-r--r--library/SIP_Emulation.ttcn30
-rw-r--r--library/SIP_Templates.ttcn1190
-rw-r--r--library/SMPP_Emulation.ttcn11
-rw-r--r--library/StatsD_Checker.ttcn280
-rw-r--r--library/StatsD_CodecPort.ttcn57
-rw-r--r--library/StatsD_CodecPort_CtrlFunct.ttcn43
-rw-r--r--library/StatsD_CodecPort_CtrlFunctdef.cc55
-rw-r--r--library/StatsD_Types.ttcn65
-rw-r--r--library/TRXC_CodecPort.ttcn3
-rw-r--r--library/TRXC_Types.ttcn11
-rw-r--r--library/euicc/PEDefinitions.asn1128
-rw-r--r--library/euicc/PKIX1Explicit88.asn619
-rw-r--r--library/euicc/PKIX1Explicit88_EncDec.cc213
-rw-r--r--library/euicc/PKIX1Explicit88_Templates.ttcn1901
-rw-r--r--library/euicc/PKIX1Explicit88_Types.ttcn42
-rw-r--r--library/euicc/PKIX1Implicit88.asn387
-rw-r--r--library/euicc/PKIX1Implicit88_EncDec.cc26
-rw-r--r--library/euicc/PKIX1Implicit88_Templates.ttcn16
-rw-r--r--library/euicc/PKIX1Implicit88_Types.ttcn9
-rw-r--r--library/euicc/RSPDefinitions.asn825
-rw-r--r--library/euicc/RSPDefinitions_EncDec.cc281
-rw-r--r--library/euicc/RSPDefinitions_Templates.ttcn579
-rw-r--r--library/euicc/RSPDefinitions_Types.ttcn54
-rw-r--r--library/euicc/SGP32Definitions.asn806
-rw-r--r--library/euicc/SGP32Definitions_EncDec.cc113
-rw-r--r--library/euicc/SGP32Definitions_Templates.ttcn433
-rw-r--r--library/euicc/SGP32Definitions_Types.ttcn24
-rw-r--r--library/hnbap/HNBAP_Templates.ttcn422
-rw-r--r--library/mncc.h17
-rw-r--r--library/ranap/RANAP_Templates.ttcn584
-rwxr-xr-xlibrary/regen-DIAMETER_Types_ttcn.sh24
-rw-r--r--library/rua/RUA_Emulation.ttcn404
-rw-r--r--library/rua/RUA_Templates.ttcn306
-rw-r--r--library/s1ap/S1AP_Templates.ttcn95
-rw-r--r--library/sabp/SABP_Adapter.ttcn (renamed from library/SABP_Adapter.ttcn)4
-rw-r--r--library/sabp/SABP_CodecPort.ttcn (renamed from library/SABP_CodecPort.ttcn)0
-rw-r--r--library/sabp/SABP_CodecPort_CtrlFunct.ttcn (renamed from library/SABP_CodecPort_CtrlFunct.ttcn)0
-rw-r--r--library/sabp/SABP_CodecPort_CtrlFunctDef.cc (renamed from library/SABP_CodecPort_CtrlFunctDef.cc)0
-rw-r--r--library/sabp/SABP_Selftest.ttcn180
-rwxr-xr-xlibrary/sabp/regen_makefile.sh9
-rw-r--r--library/sbcap/SBC_AP_Adapter.ttcn108
-rw-r--r--library/sbcap/SBC_AP_CodecPort.ttcn84
-rw-r--r--library/sbcap/SBC_AP_CodecPort_CtrlFunct.ttcn44
-rw-r--r--library/sbcap/SBC_AP_CodecPort_CtrlFunctDef.cc55
-rw-r--r--library/sbcap/SBC_AP_CommonDataTypes.asn35
-rw-r--r--library/sbcap/SBC_AP_Constants.asn127
-rw-r--r--library/sbcap/SBC_AP_Containers.asn121
-rw-r--r--library/sbcap/SBC_AP_EncDec.cc64
-rw-r--r--library/sbcap/SBC_AP_IEs.asn650
-rw-r--r--library/sbcap/SBC_AP_PDU_Contents.asn374
-rw-r--r--library/sbcap/SBC_AP_PDU_Descriptions.asn179
-rw-r--r--library/sbcap/SBC_AP_Templates.ttcn435
-rw-r--r--library/sbcap/SBC_AP_Types.ttcn33
-rwxr-xr-xlibrary/sbcap/regen_makefile.sh9
-rw-r--r--mgw/MGCP_Test.default13
-rw-r--r--mgw/MGCP_Test.ttcn1603
-rw-r--r--mgw/expected-results.xml57
-rwxr-xr-xmgw/gen_links.sh7
-rw-r--r--mgw/osmo-mgw.cfg37
-rwxr-xr-xmgw/regen_makefile.sh29
-rw-r--r--mme/LTE_CryptoFunctionDefs.cc8
-rw-r--r--mme/LTE_CryptoFunctions.ttcn38
-rw-r--r--mme/MME_Tests.ttcn1070
-rw-r--r--mme/expected-results.xml7
-rwxr-xr-xmme/gen_links.sh27
-rw-r--r--mme/key_derivation.c16
-rw-r--r--mme/key_derivation.h2
-rwxr-xr-xmme/regen_makefile.sh36
-rw-r--r--msc/BSC_ConnectionHandler.ttcn659
-rw-r--r--msc/MSC_Tests.cfg50
-rw-r--r--msc/MSC_Tests.ttcn1736
-rw-r--r--msc/MSC_Tests_ASCI.ttcn710
-rw-r--r--msc/expected-results.xml59
-rwxr-xr-xmsc/gen_links.sh6
-rw-r--r--msc/osmo-msc.cfg36
-rw-r--r--msc/osmo-stp.cfg35
-rwxr-xr-xmsc/regen_makefile.sh48
-rw-r--r--ns/NS_Tests.default26
-rw-r--r--ns/NS_Tests.fr.cfg57
-rw-r--r--ns/NS_Tests.sgsn.sns.cfg47
-rw-r--r--ns/NS_Tests.sns.cfg46
-rw-r--r--ns/NS_Tests.ttcn1105
-rw-r--r--ns/NS_Tests.udp.cfg46
-rw-r--r--ns/expected-results.xml27
-rwxr-xr-xns/gen_links.sh60
-rw-r--r--ns/osmo-ns.fr.cfg65
-rw-r--r--ns/osmo-ns.sgsn.sns.cfg99
-rw-r--r--ns/osmo-ns.sns.cfg101
-rw-r--r--ns/osmo-ns.udp.cfg99
-rwxr-xr-xns/regen_makefile.sh27
-rw-r--r--pcap-client/OPCAP_CLIENT_Tests.cfg18
-rw-r--r--pcap-client/OPCAP_CLIENT_Tests.default19
-rw-r--r--pcap-client/OPCAP_CLIENT_Tests.ttcn200
-rwxr-xr-xpcap-client/gen_links.sh31
-rw-r--r--pcap-client/osmo-pcap-client.cfg15
-rwxr-xr-xpcap-client/regen_makefile.sh19
-rw-r--r--pcu/GPRS_Components.ttcn1093
-rw-r--r--pcu/GPRS_TBF.ttcn10
-rw-r--r--pcu/PCUIF_Components.ttcn240
-rw-r--r--pcu/PCU_Tests.cfg52
-rw-r--r--pcu/PCU_Tests.default41
-rw-r--r--pcu/PCU_Tests.ttcn6016
-rw-r--r--pcu/PCU_Tests_NS.ttcn268
-rw-r--r--pcu/PCU_Tests_SNS.cfg52
-rw-r--r--pcu/PCU_Tests_SNS.ttcn288
-rw-r--r--pcu/PCU_Tests_SNSv6.cfg36
-rw-r--r--pcu/PCU_selftest.ttcn2
-rw-r--r--pcu/README.md93
-rw-r--r--pcu/SGSN_Components.ttcn103
-rw-r--r--pcu/expected-results.xml102
-rwxr-xr-xpcu/gen_links.sh12
-rw-r--r--pcu/osmo-pcu-sns.cfg4
-rw-r--r--pcu/osmo-pcu.cfg17
-rwxr-xr-xpcu/regen_makefile.sh26
-rw-r--r--pgw/PGW_Tests.ttcn840
-rw-r--r--pgw/expected-results.xml13
-rwxr-xr-xpgw/gen_links.sh14
-rwxr-xr-xpgw/regen_makefile.sh32
-rwxr-xr-xregen-makefile.sh19
-rw-r--r--remsim/REMSIM_Tests.default2
-rw-r--r--remsim/RSPRO.asn5
-rw-r--r--remsim/RSPRO_Server.ttcn1
-rw-r--r--remsim/RemsimBankd_Tests.ttcn12
-rw-r--r--remsim/RemsimClient_Tests.ttcn25
-rw-r--r--remsim/RemsimServer_Tests.ttcn203
-rwxr-xr-xremsim/gen_links.sh1
-rwxr-xr-xremsim/regen_makefile.sh29
-rw-r--r--sccp/SCCP_Tests_RAW.ttcn231
-rwxr-xr-xsccp/regen_makefile.sh26
-rwxr-xr-xselftest/gen_links.sh2
-rwxr-xr-xselftest/regen_makefile.sh21
-rw-r--r--sgsn/SGSN_Tests.cfg41
-rw-r--r--sgsn/SGSN_Tests.ttcn1161
-rw-r--r--sgsn/SGSN_Tests_Iu.ttcn25
-rw-r--r--sgsn/SGSN_Tests_NS.ttcn120
-rw-r--r--sgsn/SGSN_Tests_SNS.cfg72
-rw-r--r--sgsn/expected-results.xml36
-rwxr-xr-xsgsn/gen_links.sh16
-rw-r--r--sgsn/osmo-sgsn.cfg49
-rw-r--r--sgsn/osmo-sgsn.sns.cfg107
-rw-r--r--sgsn/osmo-stp.cfg31
-rwxr-xr-xsgsn/regen_makefile.sh36
-rwxr-xr-xsimtrace/gen_links.sh7
-rwxr-xr-xsimtrace/regen_makefile.sh14
-rw-r--r--sip/SIP_Tests.default1
-rw-r--r--sip/SIP_Tests.ttcn432
-rw-r--r--sip/expected-results.xml6
-rwxr-xr-xsip/gen_links.sh5
-rwxr-xr-xsip/regen_makefile.sh31
-rw-r--r--smlc/BSC_ConnectionHandler.ttcn95
-rw-r--r--smlc/SMLC_Tests.cfg18
-rw-r--r--smlc/SMLC_Tests.default19
-rw-r--r--smlc/SMLC_Tests.ttcn491
-rw-r--r--smlc/expected-results.xml8
-rwxr-xr-xsmlc/gen_links.sh75
-rw-r--r--smlc/osmo-smlc.cfg29
-rw-r--r--smlc/osmo-stp.cfg46
-rwxr-xr-xsmlc/regen_makefile.sh35
-rwxr-xr-xstart-testsuite.sh6
-rw-r--r--stp/STP_Tests.cfg2
-rw-r--r--stp/STP_Tests.ttcn46
-rw-r--r--stp/STP_Tests_Common.ttcn13
-rw-r--r--stp/STP_Tests_IPA.ttcn48
-rw-r--r--stp/STP_Tests_M3UA.ttcn816
-rw-r--r--stp/expected-results.xml53
-rw-r--r--stp/osmo-stp-tcp.confmerge22
-rw-r--r--stp/osmo-stp.cfg41
-rwxr-xr-xstp/regen_makefile.sh26
-rwxr-xr-xsysinfo/gen_links.sh4
-rwxr-xr-xsysinfo/regen_makefile.sh18
-rwxr-xr-xttcn3-dumpcap-start.sh103
-rwxr-xr-xttcn3-dumpcap-stop.sh51
-rwxr-xr-xttcn3-tcpdump-start.sh68
-rwxr-xr-xttcn3-tcpdump-stop.sh45
-rw-r--r--upf/CPF_ConnectionHandler.ttcn118
-rw-r--r--upf/README.md21
-rw-r--r--upf/README.txt4
-rw-r--r--upf/UPF_Tests.cfg19
-rw-r--r--upf/UPF_Tests.default28
-rw-r--r--upf/UPF_Tests.ttcn1176
-rw-r--r--upf/expected-results.xml11
-rwxr-xr-xupf/gen_links.sh36
-rw-r--r--upf/osmo-upf.cfg18
-rwxr-xr-xupf/regen_makefile.sh24
463 files changed, 106813 insertions, 13428 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
new file mode 100644
index 00000000..700e952a
--- /dev/null
+++ b/.checkpatch.conf
@@ -0,0 +1,2 @@
+--exclude ^library/sbcap/.*\.asn$
+--exclude ^library/DIAMETER_Types.ttcn$
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..7592debf
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+open_collective: osmocom
diff --git a/.gitignore b/.gitignore
index 5c8caa52..e77dfa77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,7 @@ selftest/Selftest
.*.sw?
*.netcat.stderr
*.d
+*.merged
+sms.db
+sms.db-shm
+sms.db-wal
diff --git a/Common.cfg b/Common.cfg
index bf0a7527..b8c76e63 100644
--- a/Common.cfg
+++ b/Common.cfg
@@ -12,7 +12,7 @@ SourceInfoFormat := Single;
LogSourceInfo := Yes;
LoggerPlugins := { JUnitLogger := "libjunitlogger2" }
FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
-ConsoleMask := ERROR | WARNING | TESTCASE | USER;
+ConsoleMask := ERROR | WARNING | TESTCASE | USER | VERDICTOP;
[EXTERNAL_COMMANDS]
BeginTestCase := $TCPDUMP_START
diff --git a/Makefile b/Makefile
index 03e7a70b..bd88ca50 100644
--- a/Makefile
+++ b/Makefile
@@ -13,8 +13,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-SUBDIRS=bsc bsc-nat bts ccid ggsn_tests hlr mgw mme msc pcu pgw remsim sccp selftest sgsn \
- simtrace sip stp sysinfo
+SUBDIRS= \
+ asterisk \
+ bsc \
+ bsc-nat \
+ bts \
+ cbc \
+ ccid \
+ dia2gsup \
+ fr \
+ fr-net \
+ epdg \
+ gbproxy \
+ ggsn_tests \
+ hlr \
+ hnbgw \
+ hnodeb \
+ hss \
+ mgw \
+ mme \
+ msc \
+ ns \
+ pcap-client \
+ pcu \
+ pgw \
+ remsim \
+ sccp \
+ selftest \
+ sgsn \
+ simtrace \
+ sip \
+ smlc \
+ stp \
+ sysinfo \
+ upf \
+ $(NULL)
NPROC=$(shell nproc 2>/dev/null)
ifeq ($(NPROC),)
@@ -36,9 +69,11 @@ PARALLEL_MAKE ?= -j$(NPROC)
default: deps all
+# Eclipse GitLab has rate limiting and sometimes to many concurrent conns fail.
+# If -jN fails, retry with -j1.
.PHONY: deps
deps:
- $(MAKE) -C deps
+ ($(MAKE) $(PARALLEL_MAKE) -C deps || $(MAKE) -j1 -C deps)
# deps-update target for backwards compat; now does the same as 'make deps'
.PHONY: deps-update
@@ -81,3 +116,13 @@ $(foreach dir,$(SUBDIRS), \
$(eval $(call DIR_clean_template,$(dir))) \
$(eval $(call DIR_all_template,$(dir))) \
)
+
+.PHONY: tags regen-diameter-types-ttcn
+tags:
+ find $(shell pwd) \
+ -type f -name "*.ttcn" -o \
+ -type f -name "*.ttcnpp" | \
+ xargs ctags
+
+regen-diameter-types-ttcn:
+ (cd library/ && ./regen-DIAMETER_Types_ttcn.sh)
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..907ebb16
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+Osmocom TTCN-3 Test Suites
+==========================
+
+This repository contains a collection of test suites developed within
+the [Osmocom](https://osmocom.org/) (Open Source Mobile Communications)
+project. The test suites are developed in the
+[TTCN-3](https://de.wikipedia.org/wiki/TTCN-3) programming language,
+compiled/executed by the [Eclipse TITAN](https://projects.eclipse.org/projects/tools.titan)
+compiler and runtime.
+
+Those test suites mostly are performing *functional testing* of cellular
+network elements, from 2G, 3G, 4G to 5G. The individual test-suites are
+in sub-directories, while some shared library code is in *library*.
+
+
+Continuous Integration
+----------------------
+
+The individual tests suites are executed against different versions of
+the respective IUT (Implementation Under Test) by the Osmocom jenkins.
+
+See the [list of all TTCN-3 jenkins jobs](https://jenkins.osmocom.org/jenkins/view/TTCN3/)
+for more details
+
+
+Further reading
+--------------
+
+Some more information about those test suites can be found
+at <https://osmocom.org/projects/cellular-infrastructure/wiki/Titan_TTCN3_Testsuites>.
diff --git a/SCCP_Test/regen_makefile.sh b/SCCP_Test/regen_makefile.sh
index 9472e0cb..ee2cdb39 100755
--- a/SCCP_Test/regen_makefile.sh
+++ b/SCCP_Test/regen_makefile.sh
@@ -1,7 +1,13 @@
#!/bin/sh
-MAIN=SCCP_Testcases.ttcn
+NAME=SCCP_Testcases
-FILES="*.ttcn *.ttcnpp"
+FILES="
+ *.ttcn
+ *.ttcnpp
+"
-../regen-makefile.sh $MAIN $FILES
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/asterisk/AMI_Functions.ttcn b/asterisk/AMI_Functions.ttcn
new file mode 100644
index 00000000..53a79642
--- /dev/null
+++ b/asterisk/AMI_Functions.ttcn
@@ -0,0 +1,212 @@
+/* Asterisk's AMI interface functions in TTCN-3
+ * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@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
+ */
+
+/*
+ * https://docs.asterisk.org/Configuration/Interfaces/Asterisk-Manager-Interface-AMI/AMI-v2-Specification/
+ */
+module AMI_Functions {
+
+import from Misc_Helpers all;
+import from TELNETasp_PortType all;
+import from Osmocom_Types all;
+import from TCCConversion_Functions all;
+import from Socket_API_Definitions all;
+
+modulepar {
+ float mp_ami_prompt_timeout := 10.0;
+}
+
+const charstring AMI_FIELD_ACTION := "Action";
+const charstring AMI_FIELD_USERNAME := "Username";
+const charstring AMI_FIELD_SECRET := "Secret";
+const charstring AMI_FIELD_RESPONSE := "Response";
+
+type record AMI_Field {
+ charstring key,
+ charstring val
+};
+type set of AMI_Field AMI_Msg;
+
+template (value) AMI_Field
+ts_AMI_Field(template (value) charstring key,
+ template (value) charstring val) := {
+ key := key,
+ val := val
+};
+
+template (present) AMI_Field
+tr_AMI_Field(template (present) charstring key := ?,
+ template (present) charstring val := ?) := {
+ key := key,
+ val := val
+};
+
+/*
+ * Field Templates:
+ */
+
+template (value) AMI_Field
+ts_AMI_Field_Action(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_ACTION, val);
+template (value) AMI_Field
+ts_AMI_Field_Username(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_USERNAME, val);
+template (value) AMI_Field
+ts_AMI_Field_Secret(template (value) charstring val) := ts_AMI_Field(AMI_FIELD_SECRET, val);
+
+template (present) AMI_Field
+tr_AMI_Field_Action(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_ACTION, val);
+template (present) AMI_Field
+tr_AMI_Field_Username(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_USERNAME, val);
+template (present) AMI_Field
+tr_AMI_Field_Secret(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_SECRET, val);
+template (present) AMI_Field
+tr_AMI_Field_Response(template (present) charstring val := ?) := tr_AMI_Field(AMI_FIELD_RESPONSE, val);
+
+
+template (present) AMI_Field
+tr_AMI_Field_ResponseSuccess := tr_AMI_Field(AMI_FIELD_RESPONSE, "Success");
+
+
+/*
+ * Message Templates:
+ */
+
+template (value) AMI_Msg
+ts_AMI_Action_Login(charstring username, charstring secret) := {
+ ts_AMI_Field_Action("Login"),
+ ts_AMI_Field_Username(username),
+ ts_AMI_Field_Secret(secret)
+};
+
+template (present) AMI_Msg
+tr_AMI_Action_Login(template(present) charstring username := ?,
+ template(present) charstring secret := ?) := superset(
+ tr_AMI_Field_Action("Login"),
+ tr_AMI_Field_Username(username),
+ tr_AMI_Field_Secret(secret)
+);
+
+template (present) AMI_Msg
+tr_AMI_Response_Success := superset(
+ tr_AMI_Field_ResponseSuccess
+);
+
+/*
+ * Functions:
+ */
+
+function f_AMI_Field_from_str(charstring str) return AMI_Field {
+ var AMI_Field field;
+ /* "each field is a key value pair delineated by a ':'.
+ * A single space MUST follow the ':' and precede the value. "*/
+ var integer pos := f_strstr(str, ": ", 0);
+ if (pos < 0) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Failed parsing AMI_Field: ", str));
+ }
+ field.key := substr(str, 0, pos);
+ /* skip ": " */
+ pos := pos + 2;
+ field.val := substr(str, pos, lengthof(str) - pos);
+ return field;
+}
+
+function f_AMI_Msg_from_str(charstring str) return AMI_Msg {
+ var AMI_Msg msg := {};
+ var Misc_Helpers.ro_charstring lines := f_str_split(str, "\n");
+
+ for (var integer i := 0; i < lengthof(lines); i := i + 1) {
+ var charstring line := lines[i];
+ var AMI_Field field := f_AMI_Field_from_str(lines[i]);
+ msg := msg & { field };
+ }
+ return msg;
+}
+
+function f_AMI_Field_to_str(AMI_Field field) return charstring {
+ return field.key & ": " & field.val;
+}
+
+function f_AMI_Msg_to_str(AMI_Msg msg) return charstring {
+ var charstring str := "";
+
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ str := str & f_AMI_Field_to_str(msg[i]) & "\r\n";
+ }
+
+ str := str & "\r\n";
+ return str;
+}
+
+private function f_ami_wait_for_prompt_str(TELNETasp_PT pt, charstring log_label := "(?)")
+return charstring {
+ var charstring rx, buf := "";
+ var integer fd;
+ timer T;
+
+ T.start(mp_ami_prompt_timeout);
+ alt {
+ [] pt.receive(pattern "\n") { };
+ [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
+ [] pt.receive(integer:?) -> value fd {
+ if (fd == -1) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "AMI Telnet Connection Failure: " & log_label);
+ } else {
+ repeat; /* telnet connection succeeded */
+ }
+ }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "AMI Timeout for prompt: " & log_label);
+ };
+ }
+ T.stop;
+ return buf;
+}
+
+function f_ami_wait_for_prompt(TELNETasp_PT pt, charstring log_label := "(?)") return AMI_Msg {
+ var charstring buf := f_ami_wait_for_prompt_str(pt, log_label);
+ var AMI_Msg msg := f_AMI_Msg_from_str(buf);
+ return msg;
+}
+
+/* send a AMI command and obtain response until prompt is received */
+private function f_ami_transceive_ret_str(TELNETasp_PT pt, charstring tx) return charstring {
+ pt.send(tx);
+ return f_ami_wait_for_prompt_str(pt, tx);
+}
+
+function f_ami_transceive_ret(TELNETasp_PT pt, template (value) AMI_Msg tx_msg) return AMI_Msg {
+ var charstring tx_txt := f_AMI_Msg_to_str(valueof(tx_msg));
+ var charstring resp_txt := f_ami_transceive_ret_str(pt, tx_txt);
+ return f_AMI_Msg_from_str(resp_txt);
+}
+
+function f_ami_transceive_match(TELNETasp_PT pt,
+ template (value) AMI_Msg tx_msg,
+ template (present) AMI_Msg exp_ret := ?) {
+ var AMI_Msg ret := f_ami_transceive_ret(pt, tx_msg);
+ if (not match(ret, exp_ret)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Non-matching AMI response: ", ret, " vs exp: ", exp_ret));
+ }
+}
+
+function f_ami_transceive_match_response_success(TELNETasp_PT pt,
+ template (value) AMI_Msg tx_msg) {
+ f_ami_transceive_match(pt, tx_msg, tr_AMI_Response_Success);
+}
+
+function f_ami_action_login(TELNETasp_PT pt, charstring username, charstring secret) {
+ f_ami_transceive_match_response_success(pt, ts_AMI_Action_Login(username, secret));
+}
+
+}
diff --git a/asterisk/Asterisk_Tests.cfg b/asterisk/Asterisk_Tests.cfg
new file mode 100644
index 00000000..a3669f93
--- /dev/null
+++ b/asterisk/Asterisk_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./Asterisk_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+Asterisk_Tests.control
diff --git a/asterisk/Asterisk_Tests.default b/asterisk/Asterisk_Tests.default
new file mode 100644
index 00000000..09965452
--- /dev/null
+++ b/asterisk/Asterisk_Tests.default
@@ -0,0 +1,29 @@
+[LOGGING]
+FileMask := LOG_ALL | TTCN_MATCHING;
+
+mtc.FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+
+[TESTPORT_PARAMETERS]
+*.*.DEBUG := "yes"
+*.AMI.PROMPT1 := "Asterisk Call Manager/9.0.0\n"
+*.AMI.PROMPT2 := "\n"
+#*.AMI.REGEX_PROMPT1 := "^Asterisk Call Manager.*$"
+*.AMI.CTRL_MODE := "client"
+*.AMI.CTRL_HOSTNAME := "127.0.0.1"
+*.AMI.CTRL_PORTNUM := "5038"
+*.AMI.CTRL_LOGIN_SKIPPED := "yes"
+*.AMI.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.AMI.CTRL_READMODE := "buffered"
+*.AMI.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.AMI.CTRL_CRLF := "yes"
+*.SIP.local_sip_port := "5060"
+*.SIP.default_local_address := "127.0.0.2"
+*.SIP.default_sip_protocol := "UDP"
+*.SIP.default_dest_port := "5060"
+*.SIP.default_dest_address := "127.0.0.1"
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
diff --git a/asterisk/Asterisk_Tests.ttcn b/asterisk/Asterisk_Tests.ttcn
new file mode 100644
index 00000000..b164ee52
--- /dev/null
+++ b/asterisk/Asterisk_Tests.ttcn
@@ -0,0 +1,276 @@
+module Asterisk_Tests {
+
+/* Asterisk test suite in TTCN-3
+ * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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
+ */
+
+import from TCCOpenSecurity_Functions all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
+import from TELNETasp_PortType all;
+import from AMI_Functions all;
+
+import from SDP_Types all;
+import from SDP_Templates all;
+
+import from SIP_Emulation all;
+import from SIPmsg_Types all;
+import from SIP_Templates all;
+
+import from SIP_ConnectionHandler all;
+
+modulepar {
+ charstring mp_local_sip_host := "127.0.0.2";
+ integer mp_local_sip_port := 5060;
+ charstring mp_remote_sip_host := "127.0.0.1";
+ integer mp_remote_sip_port := 5060;
+
+ /* Asterisk AMI: */
+ charstring mp_ami_user := "test_user";
+ charstring mp_ami_secret := "1234";
+}
+
+type component test_CT {
+ var SIP_Emulation_CT vc_SIP;
+ port TELNETasp_PT AMI;
+ port Coord_PT COORD;
+}
+
+const charstring broadcast_sip_extension := "0500";
+
+function f_init_ConnHdlrPars(integer idx := 1) runs on test_CT return SIPConnHdlrPars {
+ var template (value) CallPars cp := t_CallPars(mp_local_sip_host, 1234 + 2*idx);
+ var template (value) SIPConnHdlrPars pars := t_Pars(mp_local_sip_host,
+ mp_local_sip_port,
+ mp_remote_sip_host,
+ mp_remote_sip_port,
+ "0" & int2str(str2int(broadcast_sip_extension) + idx),
+ cp := cp);
+ return valueof(pars);
+}
+
+/* Initialize connection towards Asterisk AMI */
+private function f_init_ami() runs on test_CT {
+ map(self:AMI, system:AMI);
+ f_ami_action_login(AMI, mp_ami_user, mp_ami_secret);
+}
+
+function f_init() runs on test_CT {
+ f_init_ami();
+ f_init_sip(vc_SIP, "Asterisk_Test");
+ log("end of f_init");
+}
+
+function f_start_handler(void_fn fn, SIPConnHdlrPars pars)
+runs on test_CT return SIPConnHdlr {
+ var SIPConnHdlr vc_conn;
+ var charstring id := testcasename() & "-ConnHdlr-" & pars.user;
+
+ vc_conn := SIPConnHdlr.create(id) alive;
+
+ connect(vc_conn:SIP, vc_SIP:CLIENT);
+ connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
+
+ connect(vc_conn:COORD, self:COORD);
+
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+/* Test SIP registration of local clients */
+private function f_TC_internal_registration(charstring id) runs on SIPConnHdlr {
+
+ f_SIP_register();
+ // f_SIP_deregister();
+ setverdict(pass);
+}
+testcase TC_internal_registration() runs on test_CT {
+ var SIPConnHdlrPars pars;
+ var SIPConnHdlr vc_conn;
+ f_init();
+ pars := f_init_ConnHdlrPars();
+ vc_conn := f_start_handler(refers(f_TC_internal_registration), pars);
+ vc_conn.done;
+}
+
+/* Successful SIP MO-MT Call between local clients: */
+private function f_TC_internal_call_mo(charstring id) runs on SIPConnHdlr {
+
+ f_SIP_register();
+ COORD.send(COORD_CMD_REGISTERED);
+
+ COORD.receive(COORD_CMD_START);
+ f_SIP_mo_call_setup();
+ COORD.send(COORD_CMD_CALL_ESTABLISHED);
+
+ COORD.receive(COORD_CMD_HANGUP);
+ f_SIP_do_call_hangup();
+
+ setverdict(pass);
+}
+private function f_TC_internal_call_mt(charstring id) runs on SIPConnHdlr {
+
+ f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.cp.called.addr)));
+
+ f_SIP_register();
+ COORD.send(COORD_CMD_REGISTERED);
+
+ if (g_pars.cp.mt.exp_cancel) {
+ as_SIP_mt_call_cancelled();
+ COORD.send(COORD_CMD_CALL_CANCELLED);
+ setverdict(pass);
+ return;
+ }
+
+ as_SIP_mt_call_accept();
+ COORD.send(COORD_CMD_CALL_ESTABLISHED);
+
+ /* Once MO hangs up, Asterisk updates us to point RTP to it: */
+ as_SIP_exp_call_update(g_pars.cp.sip_seq_nr + 1);
+ as_SIP_exp_call_hangup(g_pars.cp.sip_seq_nr + 1);
+
+ setverdict(pass);
+}
+testcase TC_internal_call_momt() runs on test_CT {
+ var SIPConnHdlrPars pars[2];
+ var SIPConnHdlr vc_conn[2];
+
+ f_init();
+
+ pars[0] := f_init_ConnHdlrPars(idx := 1);
+ pars[1] := f_init_ConnHdlrPars(idx := 2);
+
+ pars[0].cp.calling := pars[0].registrar_sip_record;
+ pars[0].cp.called := pars[1].registrar_sip_record;
+
+ pars[1].cp.calling := pars[0].registrar_sip_record;
+ pars[1].cp.called := pars[1].local_sip_record;
+
+ vc_conn[0] := f_start_handler(refers(f_TC_internal_call_mo), pars[0]);
+ vc_conn[1] := f_start_handler(refers(f_TC_internal_call_mt), pars[1]);
+
+ interleave {
+ [] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[0];
+ [] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[1];
+ }
+
+ COORD.send(COORD_CMD_START) to vc_conn[0];
+
+ interleave {
+ [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[0];
+ [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[1];
+ }
+
+ /* Call on-going */
+ f_sleep(1.0);
+
+ COORD.send(COORD_CMD_HANGUP) to vc_conn[0];
+
+
+ vc_conn[0].done;
+ vc_conn[1].done;
+}
+
+/* One of the users calls (INVITE) shared extension, which makes all other user
+ * equipments ring (INVITE). The first one to pick up the call (OK 200) gets the
+ * call established (ACK), others get a CANCEL event. */
+private function TC_internal_call_all_Nregistered(integer num_conns := 2) runs on test_CT {
+ var SIPConnHdlrList vc_conn_list := {};
+ const integer vc_conn_mo_idx := 0; /* Index of MO leg in vc_conn_list */
+ const integer vc_conn_mt_idx := 1; /* Index of MT leg in vc_conn_list, peer picking up first the call */
+ var SipAddr broadcast_sip_record;
+ var SIPConnHdlrPars pars_mo;
+
+ f_init();
+
+ broadcast_sip_record := valueof(ts_SipAddr(ts_HostPort(mp_local_sip_host),
+ ts_UserInfo(broadcast_sip_extension)));
+
+ for (var integer i := 0; i < num_conns; i := i + 1) {
+ var SIPConnHdlrPars pars;
+ var SIPConnHdlr vc_conn;
+ pars := f_init_ConnHdlrPars(idx := i + 1);
+ if (i == vc_conn_mo_idx) { /* MO */
+ pars.cp.calling := pars.registrar_sip_record;
+ pars.cp.called := broadcast_sip_record;
+ vc_conn := f_start_handler(refers(f_TC_internal_call_mo), pars);
+ pars_mo := pars;
+ } else { /* MT */
+ pars.cp.calling := pars_mo.registrar_sip_record;
+ pars.cp.called := pars.local_sip_record;
+ pars.cp.mt.wait_coord_cmd_pickup := true;
+ if (i != vc_conn_mt_idx) {
+ /* Only first MT picking up (OK 200 INVITE) will be ACKed, others CANCELed: */
+ pars.cp.mt.exp_cancel := true;
+ }
+ vc_conn := f_start_handler(refers(f_TC_internal_call_mt), pars);
+ }
+ vc_conn_list := vc_conn_list & { vc_conn };
+ }
+
+ /* Wait all users are registered: */
+ for (var integer i := 0; i < num_conns; i := i + 1) {
+ /* Note: "from vc_conn_list[i]" can't be used since they may arrive from components in any order: */
+ COORD.receive(COORD_CMD_REGISTERED);
+ }
+
+ /* Ask MO user to start the call: */
+ COORD.send(COORD_CMD_START) to vc_conn_list[vc_conn_mo_idx];
+
+ /* Make sure the desired MT is the one picking up first the call: */
+ COORD.send(COORD_CMD_PICKUP) to vc_conn_list[vc_conn_mt_idx];
+ interleave {
+ [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_list[vc_conn_mo_idx];
+ [] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_list[vc_conn_mt_idx];
+ }
+
+ /* Pick up from other phone calls and expect CANCEL: */
+ for (var integer i := 0; i < num_conns; i := i + 1) {
+ if (i != vc_conn_mo_idx and i != vc_conn_mt_idx) {
+ COORD.send(COORD_CMD_PICKUP) to vc_conn_list[i];
+ COORD.receive(COORD_CMD_CALL_CANCELLED) from vc_conn_list[i];
+ }
+ }
+
+ /* Call on-going */
+ f_sleep(1.0);
+
+ COORD.send(COORD_CMD_HANGUP) to vc_conn_list[vc_conn_mo_idx];
+
+ for (var integer i := 0; i < num_conns; i := i + 1) {
+ vc_conn_list[i].done;
+ }
+}
+testcase TC_internal_call_all_2registered() runs on test_CT {
+ TC_internal_call_all_Nregistered(2);
+}
+testcase TC_internal_call_all_3registered() runs on test_CT {
+ TC_internal_call_all_Nregistered(3);
+}
+testcase TC_internal_call_all_4registered() runs on test_CT {
+ TC_internal_call_all_Nregistered(4);
+}
+
+testcase TC_selftest() runs on test_CT {
+ f_sip_digest_selftest();
+ setverdict(pass);
+}
+
+control {
+ execute( TC_internal_registration() );
+ execute( TC_internal_call_momt() );
+ execute( TC_internal_call_all_2registered() );
+ execute( TC_internal_call_all_3registered() );
+ execute( TC_internal_call_all_4registered() );
+}
+
+}
diff --git a/asterisk/README.md b/asterisk/README.md
new file mode 100644
index 00000000..c034bbba
--- /dev/null
+++ b/asterisk/README.md
@@ -0,0 +1,16 @@
+* Asterisk_Tests.ttcn
+
+* external interfaces
+ * SIP (emulates SIP UAs)
+ * VoLTE (emulates IMS server)
+
+{% dot sip_tests.svg
+digraph G {
+ rankdir=LR;
+ Asterisk [label="IUT\nAsterisk",shape="box"];
+ ATS [label="ATS\nAsterisk_Tests.ttcn"];
+
+ ATS -> Asterisk [label="SIP"];
+ ATS -> Asterisk [label="VoLTE (IMS)"];
+}
+%}
diff --git a/asterisk/SIP_ConnectionHandler.ttcn b/asterisk/SIP_ConnectionHandler.ttcn
new file mode 100644
index 00000000..13b5f049
--- /dev/null
+++ b/asterisk/SIP_ConnectionHandler.ttcn
@@ -0,0 +1,707 @@
+/* Component implementing a SIP UA towards Asterisk
+ * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@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 SIP_ConnectionHandler {
+
+import from TCCOpenSecurity_Functions all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
+
+import from SDP_Types all;
+import from SDP_Templates all;
+
+import from SIP_Emulation all;
+import from SIPmsg_Types all;
+import from SIP_Templates all;
+
+type port Coord_PT message
+{
+ inout charstring;
+} with { extension "internal" };
+
+const charstring COORD_CMD_REGISTERED := "COORD_CMD_REGISTERED";
+const charstring COORD_CMD_START := "COORD_CMD_START";
+const charstring COORD_CMD_PICKUP := "COORD_CMD_PICKUP";
+const charstring COORD_CMD_CALL_ESTABLISHED := "COORD_CMD_CALL_ESTABLISHED";
+const charstring COORD_CMD_CALL_CANCELLED := "COORD_CMD_CALL_CANCELLED";
+const charstring COORD_CMD_HANGUP := "COORD_CMD_HANGUP";
+
+type component SIPConnHdlr extends SIP_ConnHdlr {
+ var charstring g_name;
+ var SIPConnHdlrPars g_pars;
+ timer g_Tguard;
+ var PDU_SIP_Request g_rx_sip_req;
+ var PDU_SIP_Response g_rx_sip_resp;
+
+ port Coord_PT COORD;
+}
+type record of SIPConnHdlr SIPConnHdlrList;
+
+type record SIPConnHdlrPars {
+ float t_guard,
+ charstring remote_sip_host,
+ uint16_t remote_sip_port,
+ charstring user,
+ charstring display_name,
+ charstring password,
+ SipUrl registrar_sip_req_uri,
+ SipAddr registrar_sip_record,
+ CallidString registrar_sip_call_id,
+ integer registrar_sip_seq_nr,
+ Via local_via,
+ SipUrl local_sip_url_ext,
+ SipAddr local_sip_record,
+ Contact local_contact,
+ CallPars cp optional
+}
+type record of SIPConnHdlrPars SIPConnHdlrParsList;
+
+type record CallParsMT {
+ /* Whether to wait for COORD.receive(COORD_CMD_PICKUP) before accepting the call. */
+ boolean wait_coord_cmd_pickup,
+ /* Whether to expect CANCEL instead of ACK as answer to our OK */
+ boolean exp_cancel
+}
+template (value) CallParsMT t_CallParsMT := {
+ wait_coord_cmd_pickup := false,
+ exp_cancel := false
+}
+
+type record CallPars {
+ SipAddr calling optional,
+ SipAddr called optional,
+
+ SipAddr from_addr optional,
+ SipAddr to_addr optional,
+
+ CallidString sip_call_id,
+ integer sip_seq_nr,
+ charstring sip_body optional,
+
+ charstring local_rtp_addr,
+ uint16_t local_rtp_port,
+
+ SDP_Message peer_sdp optional,
+ CallParsMT mt
+}
+
+template (value) CallPars t_CallPars(charstring local_rtp_addr,
+ uint16_t local_rtp_port := 0,
+ template (omit) SipAddr calling := omit,
+ template (omit) SipAddr called := omit) := {
+ calling := calling,
+ called := called,
+ from_addr := omit,
+ to_addr := omit,
+ sip_call_id := hex2str(f_rnd_hexstring(15)),
+ sip_seq_nr := f_sip_rand_seq_nr(),
+ sip_body := omit,
+ local_rtp_addr := local_rtp_addr,
+ local_rtp_port := local_rtp_port,
+ peer_sdp := omit,
+ mt := t_CallParsMT
+}
+
+template (value) SIPConnHdlrPars t_Pars(charstring local_sip_host,
+ uint16_t local_sip_port,
+ charstring remote_sip_host,
+ uint16_t remote_sip_port,
+ charstring user,
+ charstring display_name := "Anonymous",
+ charstring password := "secret",
+ template (omit) CallPars cp := omit) := {
+ t_guard := 30.0,
+ remote_sip_host := remote_sip_host,
+ remote_sip_port := remote_sip_port,
+ user := user,
+ display_name := f_sip_str_quote(display_name),
+ password := password,
+ registrar_sip_req_uri := valueof(ts_SipUrlHost(remote_sip_host)),
+ registrar_sip_record := ts_SipAddr(ts_HostPort(remote_sip_host),
+ ts_UserInfo(user),
+ f_sip_str_quote(display_name)),
+ registrar_sip_call_id := hex2str(f_rnd_hexstring(15)) & "@" & local_sip_host,
+ registrar_sip_seq_nr := f_sip_rand_seq_nr(),
+ local_via := ts_Via_from(ts_HostPort(local_sip_host, local_sip_port)),
+ local_sip_url_ext := ts_SipUrl(ts_HostPort(local_sip_host, local_sip_port),
+ ts_UserInfo(user)),
+ local_sip_record := ts_SipAddr(ts_HostPort(local_sip_host),
+ ts_UserInfo(user)),
+ local_contact := valueof(ts_Contact({
+ ts_ContactAddress(
+ ts_Addr_Union_SipUrl(ts_SipUrl(ts_HostPort(
+ local_sip_host,
+ local_sip_port),
+ ts_UserInfo(user))),
+ omit)
+ })),
+ cp := cp
+}
+
+private altstep as_Tguard() runs on SIPConnHdlr {
+ [] g_Tguard.timeout {
+ setverdict(fail, "Tguard timeout");
+ mtc.stop;
+ }
+}
+
+type function void_fn(charstring id) runs on SIPConnHdlr;
+function f_handler_init(void_fn fn, charstring id, SIPConnHdlrPars pars)
+runs on SIPConnHdlr {
+ g_name := id;
+ g_pars := pars;
+ g_Tguard.start(pars.t_guard);
+ activate(as_Tguard());
+
+ // Make sure the UA is deregistered before starting the test:
+ // sends REGISTER with Contact = "*" and Expires = 0
+ //f_SIP_deregister();
+
+ /* call the user-supied test case function */
+ fn.apply(id);
+}
+
+private function f_tr_Via_response(Via via_req) return template (present) Via {
+ template (present) SemicolonParam_List via_resp_params := ?;
+
+ /*via_resp_params := {
+ { id := "rport", paramValue := int2str(g_pars.remote_sip_port) },
+ { id := "received", paramValue := g_pars.remote_sip_host }
+ }; */
+ return tr_Via_from(via_req.viaBody[0].sentBy,
+ via_resp_params);
+}
+
+private function f_tr_To_response(template (value) SipAddr to_req) return template (present) SipAddr {
+ return tr_SipAddr_from_val(to_req);
+}
+
+private function f_tr_From(template (value) SipAddr from_req) return template (present) SipAddr {
+ return tr_SipAddr_from_val(from_req);
+}
+
+private altstep as_SIP_fail_req(charstring exp_msg_str := "") runs on SIPConnHdlr
+{
+ var PDU_SIP_Request sip_req;
+ [] SIP.receive(PDU_SIP_Request:?) -> value sip_req {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str(g_name & ": Received unexpected SIP Req message := ", sip_req, "\nvs exp := ", exp_msg_str));
+ }
+}
+
+private altstep as_SIP_fail_resp(charstring exp_msg_str := "") runs on SIPConnHdlr
+{
+ var PDU_SIP_Response sip_resp;
+ [] SIP.receive(PDU_SIP_Response:?) -> value sip_resp {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str(g_name & ": Received unexpected SIP Resp message := ", sip_resp, "\nvs exp := ", exp_msg_str));
+ }
+}
+
+altstep as_SIP_expect_req(template (present) PDU_SIP_Request sip_expect, boolean fail_others := true) runs on SIPConnHdlr
+{
+ var charstring sip_expect_str := log2str(sip_expect);
+ [] SIP.receive(sip_expect) -> value g_rx_sip_req;
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+}
+
+altstep as_SIP_expect_resp(template (present) PDU_SIP_Response sip_expect, boolean fail_others := true) runs on SIPConnHdlr
+{
+ var charstring sip_expect_str := log2str(sip_expect);
+ [] SIP.receive(sip_expect) -> value g_rx_sip_resp;
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+}
+
+altstep as_SIP_ignore_resp(template PDU_SIP_Response sip_expect := ?) runs on SIPConnHdlr
+{
+ [] SIP.receive(sip_expect) -> value g_rx_sip_resp {
+ log("Ignoring ", g_rx_sip_resp);
+ repeat;
+ }
+}
+
+private function f_gen_sdp() runs on SIPConnHdlr return charstring {
+ var charstring sdp :=
+ "v=0\r\n" &
+ "o=0502 2390 1824 IN IP4 " & g_pars.cp.local_rtp_addr & "\r\n" &
+ "s=Talk\r\n" &
+ "c=IN IP4 " & g_pars.cp.local_rtp_addr & "\r\n" &
+ "t=0 0\r\n" &
+ "a=rtcp-xr:rcvr-rtt=all:10000 stat-summary=loss,dup,jitt,TTL voip-metrics\r\n" &
+ "a=record:off\r\n" &
+ "m=audio " & int2str(g_pars.cp.local_rtp_port) & " RTP/AVP 96 97 98 0 8 18 99 100 101\r\n" &
+ "a=rtpmap:96 opus/48000/2\r\n" &
+ "a=fmtp:96 useinbandfec=1\r\n" &
+ "a=rtpmap:97 speex/16000\r\n" &
+ "a=fmtp:97 vbr=on\r\n" &
+ "a=rtpmap:98 speex/8000\r\n" &
+ "a=fmtp:98 vbr=on\r\n" &
+ "a=fmtp:18 annexb=yes\r\n" &
+ "a=rtpmap:99 telephone-event/48000\r\n" &
+ "a=rtpmap:100 telephone-event/16000\r\n" &
+ "a=rtpmap:101 telephone-event/8000\r\n" &
+ "a=rtcp:" & int2str(g_pars.cp.local_rtp_port + 1) & "\r\n" &
+ "a=rtcp-fb:* trr-int 1000\r\n" &
+ "a=rtcp-fb:* ccm tmmbr\r\n";
+ return sdp;
+}
+
+function f_SIP_register() runs on SIPConnHdlr return PDU_SIP_Response
+{
+ var template (present) PDU_SIP_Response exp;
+ var Authorization authorization;
+ var Via via := g_pars.local_via;
+ var SipAddr from_sipaddr := g_pars.registrar_sip_record;
+ var charstring branch_value;
+
+ branch_value := f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.registrar_sip_record),
+ f_sip_SipAddr_to_str(g_pars.registrar_sip_record),
+ g_pars.registrar_sip_call_id,
+ g_pars.registrar_sip_seq_nr);
+
+ via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "branch", branch_value);
+ from_sipaddr.params := f_sip_param_set(from_sipaddr.params, "tag", f_sip_rand_tag());
+ SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_req_uri,
+ g_pars.registrar_sip_call_id,
+ from_sipaddr,
+ g_pars.registrar_sip_record,
+ via,
+ g_pars.registrar_sip_seq_nr,
+ g_pars.local_contact,
+ ts_Expires("7200")));
+
+ exp := tr_SIP_Response_Unauthorized(
+ g_pars.registrar_sip_call_id,
+ from_sipaddr,
+ f_tr_To_response(g_pars.registrar_sip_record),
+ f_tr_Via_response(via),
+ *,
+ tr_WwwAuthenticate({tr_Challenge_digestCln(?)}),
+ g_pars.registrar_sip_seq_nr);
+ as_SIP_expect_resp(exp);
+
+ /* Digest Auth: RFC 2617 */
+ authorization := f_sip_digest_gen_Authorization(g_rx_sip_resp.msgHeader.wwwAuthenticate,
+ g_pars.user, g_pars.password,
+ "REGISTER",
+ f_sip_SipUrl_to_str(g_pars.registrar_sip_req_uri))
+
+ /* New transaction: */
+ g_pars.registrar_sip_seq_nr := g_pars.registrar_sip_seq_nr + 1;
+ branch_value := f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.registrar_sip_record),
+ f_sip_SipAddr_to_str(g_pars.registrar_sip_record),
+ g_pars.registrar_sip_call_id,
+ g_pars.registrar_sip_seq_nr);
+ via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "branch", branch_value);
+
+ SIP.send(ts_SIP_REGISTER(g_pars.registrar_sip_req_uri,
+ g_pars.registrar_sip_call_id,
+ from_sipaddr,
+ g_pars.registrar_sip_record,
+ via,
+ g_pars.registrar_sip_seq_nr,
+ g_pars.local_contact,
+ ts_Expires("7200"),
+ authorization := authorization));
+
+ /* Wait for OK answer */
+ exp := tr_SIP_Response(
+ g_pars.registrar_sip_call_id,
+ from_sipaddr,
+ f_tr_To_response(g_pars.registrar_sip_record),
+ f_tr_Via_response(via),
+ *,
+ "REGISTER", 200,
+ g_pars.registrar_sip_seq_nr, "OK");
+ as_SIP_expect_resp(exp);
+
+ /* Prepare for next use: */
+ g_pars.registrar_sip_seq_nr := g_pars.registrar_sip_seq_nr + 1;
+ return g_rx_sip_resp;
+}
+
+function f_SIP_mo_call_setup() runs on SIPConnHdlr
+{
+ var template (value) PDU_SIP_Request req;
+ var template (present) PDU_SIP_Response exp;
+ var Via via;
+ var charstring tx_sdp := f_gen_sdp();
+ var default d_trying, d_ringing;
+ var charstring branch_value;
+
+ /* RFC 3261 8.1.1.3 From */
+ g_pars.cp.from_addr := g_pars.cp.calling;
+ g_pars.cp.from_addr.params := f_sip_param_set(g_pars.cp.from_addr.params, "tag", f_sip_rand_tag());
+ g_pars.cp.to_addr := g_pars.cp.called;
+ branch_value := f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.cp.from_addr),
+ f_sip_SipAddr_to_str(valueof(g_pars.cp.to_addr)),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.sip_seq_nr);
+ via := g_pars.local_via;
+ via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "branch", branch_value);
+
+ req := ts_SIP_INVITE(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ via,
+ g_pars.local_contact,
+ g_pars.cp.sip_seq_nr,
+ body := tx_sdp);
+
+ SIP.send(req);
+
+ /* RFC 3261 22.2: */
+ exp := tr_SIP_Response_Unauthorized(
+ g_pars.cp.sip_call_id,
+ f_tr_From(g_pars.cp.from_addr),
+ f_tr_To_response(g_pars.cp.to_addr),
+ f_tr_Via_response(via),
+ *,
+ tr_WwwAuthenticate({tr_Challenge_digestCln(?)}),
+ g_pars.cp.sip_seq_nr, "INVITE");
+ as_SIP_expect_resp(exp);
+
+ /* Digest Auth: RFC 2617 */
+ req.msgHeader.authorization := f_sip_digest_gen_Authorization(
+ g_rx_sip_resp.msgHeader.wwwAuthenticate,
+ g_pars.user, g_pars.password,
+ "INVITE",
+ f_sip_SipUrl_to_str(g_pars.registrar_sip_req_uri))
+ g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+ f_sip_Request_inc_seq_nr(req);
+ SIP.send(req);
+
+ /* Conditionally match and accept 100 Trying. */
+ exp := tr_SIP_Response_Trying(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ f_tr_To_response(g_pars.cp.to_addr),
+ f_tr_Via_response(via),
+ g_pars.cp.sip_seq_nr, "INVITE");
+ d_trying := activate(as_SIP_ignore_resp(exp));
+
+ /* Conditionally match and accept 180 Ringing */
+ exp := tr_SIP_Response_Ringing(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ f_tr_To_response(g_pars.cp.to_addr),
+ f_tr_Via_response(via),
+ g_pars.cp.sip_seq_nr, "INVITE");
+ d_ringing := activate(as_SIP_ignore_resp(exp));
+
+ /* Wait for OK answer */
+ exp := tr_SIP_Response(
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ f_tr_To_response(g_pars.cp.to_addr),
+ f_tr_Via_response(via),
+ *,
+ "INVITE", 200,
+ g_pars.cp.sip_seq_nr, "OK",
+ body := ?);
+ as_SIP_expect_resp(exp, fail_others := false);
+
+ deactivate(d_trying);
+ deactivate(d_ringing);
+
+ /* Update To with the tags received from peer: */
+ g_pars.cp.to_addr := valueof(ts_SipAddr_from_Addr_Union(g_rx_sip_resp.msgHeader.toField.addressField,
+ g_rx_sip_resp.msgHeader.toField.toParams));
+
+ /* Transmit ACK */
+ g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+ req := ts_SIP_ACK(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ via,
+ g_pars.cp.sip_seq_nr,
+ omit);
+ SIP.send(req);
+ g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+}
+
+private function f_ConnHdlr_parse_initial_SIP_INVITE(PDU_SIP_Request rx_sip_req) runs on SIPConnHdlr
+{
+ f_SDP_decodeMessage(rx_sip_req.messageBody, g_pars.cp.peer_sdp);
+ log("Rx Initial MT INVITE decoded SDP: ", g_pars.cp.peer_sdp);
+
+ /* Obtain params: */
+ g_pars.cp.sip_call_id := rx_sip_req.msgHeader.callId.callid;
+ g_pars.cp.from_addr := valueof(ts_SipAddr_from_Addr_Union(rx_sip_req.msgHeader.fromField.addressField,
+ rx_sip_req.msgHeader.fromField.fromParams));
+ g_pars.cp.to_addr := valueof(ts_SipAddr_from_Addr_Union(rx_sip_req.msgHeader.toField.addressField,
+ rx_sip_req.msgHeader.toField.toParams));
+ g_pars.cp.to_addr.params := f_sip_param_set(g_pars.cp.to_addr.params, "tag", f_sip_rand_tag());
+ g_pars.cp.sip_seq_nr := rx_sip_req.msgHeader.cSeq.seqNumber;
+}
+
+/* Peer is calling us, accept it: */
+altstep as_SIP_mt_call_accept(boolean exp_update_to_direct_rtp := true,
+ boolean fail_others := true) runs on SIPConnHdlr
+{
+ var template (present) PDU_SIP_Request exp_req :=
+ tr_SIP_INVITE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ ?,
+ f_tr_From(g_pars.cp.calling),
+ g_pars.cp.called,
+ tr_Via_from(f_tr_HostPort(g_pars.remote_sip_host, g_pars.remote_sip_port)),
+ ?, ?);
+ var charstring sip_expect_str := log2str(exp_req);
+
+ [] SIP.receive(exp_req) -> value g_rx_sip_req {
+ var template (value) PDU_SIP_Response tx_resp;
+ var Via via;
+ var charstring tx_sdp;
+
+ /* Obtain params: */
+ f_ConnHdlr_parse_initial_SIP_INVITE(g_rx_sip_req);
+ via := g_rx_sip_req.msgHeader.via;
+
+
+ /* Tx 180 Ringing */
+ tx_resp := ts_SIP_Response_Ringing(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ via,
+ g_pars.cp.sip_seq_nr);
+ SIP.send(tx_resp);
+
+ if (g_pars.cp.mt.wait_coord_cmd_pickup) {
+ COORD.receive(COORD_CMD_PICKUP);
+ }
+
+ /* Tx 200 OK */
+ tx_sdp := f_gen_sdp();
+ tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ "INVITE", 200,
+ g_pars.cp.sip_seq_nr,
+ "OK",
+ via,
+ body := tx_sdp);
+ SIP.send(tx_resp);
+
+ /* Wait for ACK */
+ exp_req := tr_SIP_ACK(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ f_tr_Via_response(via),
+ g_pars.cp.sip_seq_nr, *);
+ as_SIP_expect_req(exp_req);
+
+ if (exp_update_to_direct_rtp) {
+ /* Asterisk will now update the session to connect us to MO directly: */
+ /* Via is not kept since anyway "branch" will change upon following INVITE. */
+ as_SIP_exp_call_update(g_pars.cp.sip_seq_nr + 1);
+ }
+ }
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+
+}
+
+/* Peer is calling us, but cancells it during ringing: */
+altstep as_SIP_mt_call_cancelled(boolean fail_others := true) runs on SIPConnHdlr
+{
+ var template (present) PDU_SIP_Request exp_req :=
+ tr_SIP_INVITE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ ?,
+ f_tr_From(g_pars.cp.calling),
+ g_pars.cp.called,
+ tr_Via_from(f_tr_HostPort(g_pars.remote_sip_host, g_pars.remote_sip_port)),
+ ?, ?);
+ var charstring sip_expect_str := log2str(exp_req);
+
+ [] SIP.receive(exp_req) -> value g_rx_sip_req {
+ var template (value) PDU_SIP_Response tx_resp;
+ var Via via;
+ var template (present) SipAddr exp_to_addr;
+ var charstring tx_sdp;
+
+ /* Obtain params: */
+ f_ConnHdlr_parse_initial_SIP_INVITE(g_rx_sip_req);
+ via := g_rx_sip_req.msgHeader.via;
+
+
+ /* Tx 180 Ringing */
+ tx_resp := ts_SIP_Response_Ringing(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ via,
+ g_pars.cp.sip_seq_nr);
+ SIP.send(tx_resp);
+
+ if (g_pars.cp.mt.wait_coord_cmd_pickup) {
+ COORD.receive(COORD_CMD_PICKUP);
+ }
+
+ /* Wait for CANCEL */
+ /* Cancel may come even before we send Ringing, hence To's "tag"
+ * may not be known by peer, so g_pars.to_addr can't be used here: */
+ exp_to_addr := ts_SipAddr_from_Addr_Union(g_rx_sip_req.msgHeader.toField.addressField,
+ g_rx_sip_req.msgHeader.toField.toParams);
+ exp_req := tr_SIP_CANCEL(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ exp_to_addr,
+ f_tr_Via_response(via),
+ g_pars.cp.sip_seq_nr, *);
+ as_SIP_expect_req(exp_req);
+
+ /* Tx 200 OK */
+ tx_sdp := f_gen_sdp();
+ tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ "CANCEL", 200,
+ g_pars.cp.sip_seq_nr,
+ "OK",
+ via,
+ body := omit);
+ SIP.send(tx_resp);
+ }
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+
+}
+
+/* New INVITE arrives after MT call is established. Accept it: */
+altstep as_SIP_exp_call_update(template (present) integer exp_seq_nr := ?, boolean fail_others := true) runs on SIPConnHdlr
+{
+ var template (present) PDU_SIP_Request exp_req :=
+ tr_SIP_INVITE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ tr_Via_from(f_tr_HostPort(g_pars.remote_sip_host, g_pars.remote_sip_port)),
+ exp_seq_nr,
+ ?);
+ var charstring sip_expect_str := log2str(exp_req);
+
+ [] SIP.receive(exp_req) -> value g_rx_sip_req {
+ var template (value) PDU_SIP_Response tx_resp;
+ var charstring tx_sdp;
+ var Via via;
+
+ f_SDP_decodeMessage(g_rx_sip_req.messageBody, g_pars.cp.peer_sdp);
+ log("Rx Update MT INVITE decoded SDP: ", g_pars.cp.peer_sdp);
+
+ /* Update parameters: */
+ g_pars.cp.sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
+ /* "branch" has changed: */
+ via := g_rx_sip_req.msgHeader.via;
+
+ /* Tx 200 OK */
+ tx_sdp := f_gen_sdp();
+ tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ "INVITE", 200,
+ g_pars.cp.sip_seq_nr,
+ "OK",
+ via,
+ body := tx_sdp);
+ SIP.send(tx_resp);
+
+ /* Wait for ACK */
+ exp_req := tr_SIP_ACK(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ f_tr_Via_response(via),
+ g_pars.cp.sip_seq_nr, *);
+ as_SIP_expect_req(exp_req);
+ }
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+}
+
+/* Tx BYE: */
+function f_SIP_do_call_hangup() runs on SIPConnHdlr
+{
+ var template (value) PDU_SIP_Request req;
+ var template (present) PDU_SIP_Response exp_resp;
+ var Via via;
+ var charstring branch_value;
+
+ branch_value := f_sip_gen_branch(f_sip_SipAddr_to_str(g_pars.cp.from_addr),
+ f_sip_SipAddr_to_str(valueof(g_pars.cp.to_addr)),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.sip_seq_nr);
+
+ via := g_pars.local_via;
+ via.viaBody[0].viaParams := f_sip_param_set(via.viaBody[0].viaParams, "branch", branch_value);
+
+ /* Transmit ACK */
+ req := ts_SIP_BYE(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ via,
+ g_pars.cp.sip_seq_nr,
+ omit);
+ SIP.send(req);
+
+ /* Wait for OK answer */
+ exp_resp := tr_SIP_Response(
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ f_tr_To_response(g_pars.cp.to_addr),
+ f_tr_Via_response(via),
+ *,
+ "BYE", 200,
+ g_pars.cp.sip_seq_nr, "OK");
+ as_SIP_expect_resp(exp_resp);
+
+ g_pars.cp.sip_seq_nr := g_pars.cp.sip_seq_nr + 1;
+}
+
+/* Call is terminated by peer: */
+altstep as_SIP_exp_call_hangup(template (present) integer exp_seq_nr := ?, boolean fail_others := true) runs on SIPConnHdlr
+{
+ var template (present) PDU_SIP_Request exp_req :=
+ tr_SIP_BYE(f_tr_SipUrl_opt_defport(g_pars.local_sip_url_ext),
+ g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ tr_Via_from(f_tr_HostPort(g_pars.remote_sip_host, g_pars.remote_sip_port)),
+ exp_seq_nr);
+ var charstring sip_expect_str := log2str(exp_req);
+
+ [] SIP.receive(exp_req) -> value g_rx_sip_req {
+ var template (value) PDU_SIP_Response tx_resp;
+ var charstring tx_sdp;
+ var Via via;
+
+ /* Update parameters: */
+ g_pars.cp.sip_seq_nr := g_rx_sip_req.msgHeader.cSeq.seqNumber;
+ /* "branch" has changed: */
+ via := g_rx_sip_req.msgHeader.via;
+
+ /* Tx 200 OK */
+ tx_sdp := f_gen_sdp();
+ tx_resp := ts_SIP_Response(g_pars.cp.sip_call_id,
+ g_pars.cp.from_addr,
+ g_pars.cp.to_addr,
+ "BYE", 200,
+ g_pars.cp.sip_seq_nr,
+ "OK",
+ via,
+ body := tx_sdp);
+ SIP.send(tx_resp);
+ }
+ [fail_others] as_SIP_fail_resp(sip_expect_str);
+ [fail_others] as_SIP_fail_req(sip_expect_str);
+}
+
+}
diff --git a/asterisk/expected-results.xml b/asterisk/expected-results.xml
new file mode 100644
index 00000000..745a4d75
--- /dev/null
+++ b/asterisk/expected-results.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='9' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='Asterisk_Tests' name='TC_internal_registration' time='MASKED'/>
+ <testcase classname='Asterisk_Tests' name='TC_internal_call_momt' time='MASKED'/>
+ <testcase classname='Asterisk_Tests' name='TC_internal_call_all_2registered' time='MASKED'/>
+ <testcase classname='Asterisk_Tests' name='TC_internal_call_all_3registered' time='MASKED'/>
+ <testcase classname='Asterisk_Tests' name='TC_internal_call_all_4registered' time='MASKED'/>
+</testsuite>
diff --git a/asterisk/gen_links.sh b/asterisk/gen_links.sh
new file mode 100755
index 00000000..c342e517
--- /dev/null
+++ b/asterisk/gen_links.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h "
+FILES+="TCCOpenSecurity_Functions.ttcn TCCOpenSecurity.cc TCCOpenSecurity_Functions.hh "
+FILES+="TCCDateTime.cc TCCDateTime_Functions.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+# Required by MGCP and IPA
+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.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SDP/src
+FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
+SDP_parser.y lex.SDP_parse_.c"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.SIPmsg/src
+FILES="SIP_parse.h SIP_parse.y SIP_parse_.tab.h SIPmsg_PT.hh SIPmsg_Types.ttcn SIP_parse.l SIP_parse_.tab.c SIPmsg_PT.cc SIPmsg_PortType.ttcn lex.SIP_parse_.c"
+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 "
+FILES+="RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunctDef.cc "
+FILES+="SDP_Templates.ttcn "
+FILES+="SIP_Emulation.ttcn SIP_Templates.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/asterisk/regen_makefile.sh b/asterisk/regen_makefile.sh
new file mode 100755
index 00000000..5d5538e6
--- /dev/null
+++ b/asterisk/regen_makefile.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+NAME=Asterisk_Tests
+
+FILES="
+ *.c
+ *.ttcn
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SDP_EncDec.cc
+ SIPmsg_PT.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TCCOpenSecurity.cc
+ TCCDateTime.cc
+ TELNETasp_PT.cc
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/bsc-nat/BSCNAT_Tests.ttcn b/bsc-nat/BSCNAT_Tests.ttcn
index 41d58d76..1b248553 100644
--- a/bsc-nat/BSCNAT_Tests.ttcn
+++ b/bsc-nat/BSCNAT_Tests.ttcn
@@ -151,7 +151,7 @@ function f_init(void_fn_bsc_ms fn_bsc_ms, void_fn_bsc fn_bsc, BssmapCreateCallba
f_init_vty("VirtBSCNAT");
f_vty_allow_osmux(use_osmux);
- f_ipa_ctrl_start(mp_nat_ip, mp_nat_ctrl_port);
+ f_ipa_ctrl_start_client(mp_nat_ip, mp_nat_ctrl_port);
for (i := 0; i < NUM_MSC; i := i+1) {
f_init_MscState(msc[i], mp_msc_pc +i, mp_bsc_pc, mp_msc_ssn, mp_bsc_ssn);
diff --git a/bsc-nat/BSC_MS_ConnectionHandler.ttcn b/bsc-nat/BSC_MS_ConnectionHandler.ttcn
index f011c39f..8aea74ab 100644
--- a/bsc-nat/BSC_MS_ConnectionHandler.ttcn
+++ b/bsc-nat/BSC_MS_ConnectionHandler.ttcn
@@ -24,6 +24,7 @@ import from L3_Templates all;
import from MGCP_Types all;
import from MGCP_Templates all;
import from SDP_Types all;
+import from SDP_Templates all;
type function void_fn_bsc_ms(charstring id) runs on BSC_MS_ConnHdlr;
@@ -74,6 +75,7 @@ const RanOps BSC_MS_RanOps := {
protocol := RAN_PROTOCOL_BSSAP,
transport := BSSAP_TRANSPORT_AoIP,
use_osmux := false,
+ bssap_reset_retries := 1,
sccp_addr_local := omit,
sccp_addr_peer := omit
}
diff --git a/bsc-nat/MSC_ConnectionHandler.ttcn b/bsc-nat/MSC_ConnectionHandler.ttcn
index e4d38166..fdf08de7 100644
--- a/bsc-nat/MSC_ConnectionHandler.ttcn
+++ b/bsc-nat/MSC_ConnectionHandler.ttcn
@@ -104,6 +104,7 @@ const RanOps MSC_RanOps := {
protocol := RAN_PROTOCOL_BSSAP,
transport := BSSAP_TRANSPORT_AoIP,
use_osmux := false,
+ bssap_reset_retries := 1,
sccp_addr_local := omit,
sccp_addr_peer := omit
}
diff --git a/bsc-nat/gen_links.sh b/bsc-nat/gen_links.sh
index 4d2303f3..395f50e2 100755
--- a/bsc-nat/gen_links.sh
+++ b/bsc-nat/gen_links.sh
@@ -52,7 +52,7 @@ FILES="RTP_EncDec.cc RTP_Types.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn BSSMAP_Templates.ttcn RAN_Emulation.ttcnpp MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc Osmocom_CTRL_Types.ttcn Osmocom_VTY_Functions.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn BSSAP_CodecPort.ttcn"
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn BSSMAP_Templates.ttcn RAN_Emulation.ttcnpp SDP_Templates.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc Osmocom_CTRL_Types.ttcn Osmocom_VTY_Functions.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn BSSAP_CodecPort.ttcn Native_Functions.ttcn Native_FunctionDefs.cc"
gen_links $DIR $FILES
ignore_pp_results
diff --git a/bsc-nat/regen_makefile.sh b/bsc-nat/regen_makefile.sh
index c9d744e2..470d1090 100755
--- a/bsc-nat/regen_makefile.sh
+++ b/bsc-nat/regen_makefile.sh
@@ -1,9 +1,32 @@
#!/bin/sh
-MAIN=BSCNAT_Tests.ttcn
+NAME=BSCNAT_Tests
-FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc SDP_EncDec.cc *.c MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc"
+FILES="
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ RTP_EncDec.cc
+ SCCP_EncDec.cc
+ SDP_EncDec.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_SCCP -DIPA_EMULATION_MGCP -DIPA_EMULATION_CTRL -DRAN_EMULATION_BSSAP -DRAN_EMULATION_MGCP -DRAN_EMULATION_CTRL -DUSE_MTP3_DISTRIBUTOR"
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_MGCP
+ -DIPA_EMULATION_SCCP
+ -DRAN_EMULATION_BSSAP
+ -DRAN_EMULATION_CTRL
+ -DRAN_EMULATION_MGCP
+ -DUSE_MTP3_DISTRIBUTOR
+"
-../regen-makefile.sh $MAIN $FILES
+../regen-makefile.sh -e $NAME $FILES
diff --git a/bsc/BSC_Tests.cfg b/bsc/BSC_Tests.cfg
index 610e0f72..5ac91b6f 100644
--- a/bsc/BSC_Tests.cfg
+++ b/bsc/BSC_Tests.cfg
@@ -16,7 +16,9 @@
[EXECUTE]
BSC_Tests.control
+BSC_Tests_LCLS.control
BSC_Tests_CBSP.control
+#BSC_Tests_OML.control
#BSC_Tests.TC_chan_act_noreply
#BSC_Tests.TC_chan_act_ack_noest
#BSC_Tests.TC_chan_act_ack_est_ind_noreply
diff --git a/bsc/BSC_Tests.default b/bsc/BSC_Tests.default
index 88183591..50c5c0a0 100644
--- a/bsc/BSC_Tests.default
+++ b/bsc/BSC_Tests.default
@@ -17,6 +17,15 @@ mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
*.BSCVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
*.BSCVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
*.BSCVTY.PROMPT1 := "OsmoBSC> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4242"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoBSC> "
[MODULE_PARAMETERS]
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoBSC";
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 5bd0e4f5..5e4ebbc9 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -20,6 +20,11 @@ module BSC_Tests {
* level testing.
*/
+friend module BSC_Tests_VAMOS;
+friend module BSC_Tests_CBSP;
+friend module BSC_Tests_LCLS;
+friend module BSC_Tests_ASCI;
+
import from Misc_Helpers all;
import from General_Types all;
import from Osmocom_Types all;
@@ -28,6 +33,10 @@ import from IPL4asp_Types all;
import from BSSAP_Types all;
import from RAN_Adapter all;
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSLAP_Types all;
import from BSSAP_CodecPort all;
import from BSSMAP_Templates all;
import from IPA_Emulation all;
@@ -45,6 +54,11 @@ import from Osmocom_CTRL_Functions all;
import from Osmocom_CTRL_Types all;
import from Osmocom_CTRL_Adapter all;
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType all;
@@ -56,6 +70,7 @@ import from GSM_RR_Types all;
import from SCCP_Templates all;
import from BSSMAP_Templates all;
+import from BSSMAP_LE_Templates all;
import from SCCPasp_Types all;
@@ -63,15 +78,44 @@ import from GSM_SystemInformation all;
import from GSM_RestOctets all;
import from TCCConversion_Functions all;
+const integer NUM_TRX := 4;
const integer NUM_BTS := 3;
+const integer NUM_BTS_CFG := 4; /* we have 4 BTS in the osmo-bsc.cfg (for inter-BSC HO tests) but use only 3 */
+const integer NUM_TRX_CFG := 1; /* we support up to 4 TRX per BTS, but have only 1 TRX per BTS in osmo-bsc.cfg */
const integer NUM_MSC := 3;
+const integer NUM_MGW := 2;
const float T3101_MAX := 12.0;
/* make sure to sync this with the osmo-bts.cfg you're using */
const integer NUM_TCHH_PER_BTS := 2;
const integer NUM_TCHF_PER_BTS := 4;
-const integer NUM_SDCCH_PER_BTS := 4;
+const integer NUM_SDCCH_PER_BTS := 3;
+friend type record BtsTrxIdx {
+ uint8_t bts,
+ uint8_t trx
+}
+
+private type record BtsParams {
+ integer trx_num,
+ integer tsc
+}
+
+/* Default Training Sequence Code expected for bts[i]:
+ * BTS 0 has BSIC 10 (and no explicit timeslot training_sequence_code config), so expecting TSC = (BSIC & 7) = 2.
+ * BTS 1 has BSIC 11, TSC = (BSIC & 7) = 3.
+ * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
+ * BTS 2 has BSIC 12, TSC = (BSIC & 7) = 4.
+ */
+friend const BtsParams c_BtsParams[NUM_BTS_CFG] := {
+ /* BTS0 */ { trx_num := 1, tsc := 2 },
+ /* BTS1 */ { trx_num := 1, tsc := 3 },
+ /* BTS2 */ { trx_num := 4, tsc := 4 },
+ /* BTS3 */ { trx_num := 1, tsc := 4 }
+}
+
+private const RSL_IE_Body c_mr_conf_5_90 :=
+ valueof(RSL_IE_Body:{multirate_cfg := ts_RSL_MultirateCfg(true, 0, '00000100'B /* 5,90k */)});
/* per-BTS state which we keep */
type record BTS_State {
@@ -88,6 +132,71 @@ const CounterNameVals counternames_msc_mscpool := {
{ "mscpool:subscr:paged", 0 }
};
+/* List of global mscpool counters, not related to a specific 'msc' entity. */
+const CounterNameVals counternames_bsc_mscpool := {
+ { "mscpool:subscr:no_msc", 0 }
+};
+
+/* Default list of counters for 'bsc' and 'bts' entities. */
+const CounterNameVals counternames_bsc_bts_handover := {
+ { "assignment:attempted", 0 },
+ { "assignment:completed", 0 },
+ { "assignment:stopped", 0 },
+ { "assignment:no_channel", 0 },
+ { "assignment:timeout", 0 },
+ { "assignment:failed", 0 },
+ { "assignment:error", 0 },
+
+ { "handover:attempted", 0 },
+ { "handover:completed", 0 },
+ { "handover:stopped", 0 },
+ { "handover:no_channel", 0 },
+ { "handover:timeout", 0 },
+ { "handover:failed", 0 },
+ { "handover:error", 0 },
+
+ { "intra_cell_ho:attempted", 0 },
+ { "intra_cell_ho:completed", 0 },
+ { "intra_cell_ho:stopped", 0 },
+ { "intra_cell_ho:no_channel", 0 },
+ { "intra_cell_ho:timeout", 0 },
+ { "intra_cell_ho:failed", 0 },
+ { "intra_cell_ho:error", 0 },
+
+ { "intra_bsc_ho:attempted", 0 },
+ { "intra_bsc_ho:completed", 0 },
+ { "intra_bsc_ho:stopped", 0 },
+ { "intra_bsc_ho:no_channel", 0 },
+ { "intra_bsc_ho:timeout", 0 },
+ { "intra_bsc_ho:failed", 0 },
+ { "intra_bsc_ho:error", 0 },
+
+ { "interbsc_ho_out:attempted", 0 },
+ { "interbsc_ho_out:completed", 0 },
+ { "interbsc_ho_out:stopped", 0 },
+ { "interbsc_ho_out:timeout", 0 },
+ { "interbsc_ho_out:failed", 0 },
+ { "interbsc_ho_out:error", 0 },
+
+ { "interbsc_ho_in:attempted", 0 },
+ { "interbsc_ho_in:completed", 0 },
+ { "interbsc_ho_in:stopped", 0 },
+ { "interbsc_ho_in:no_channel", 0 },
+ { "interbsc_ho_in:timeout", 0 },
+ { "interbsc_ho_in:failed", 0 },
+ { "interbsc_ho_in:error", 0 }
+};
+
+const CounterNameVals counternames_bts_handover := {
+ { "incoming_intra_bsc_ho:attempted", 0 },
+ { "incoming_intra_bsc_ho:completed", 0 },
+ { "incoming_intra_bsc_ho:stopped", 0 },
+ { "incoming_intra_bsc_ho:no_channel", 0 },
+ { "incoming_intra_bsc_ho:timeout", 0 },
+ { "incoming_intra_bsc_ho:failed", 0 },
+ { "incoming_intra_bsc_ho:error", 0 }
+};
+
/* Set of all System Information received during one RSL port's startup.
* Note that some System Information may be sent on RSL, but lacking actual SI data, to indicate that the BTS should not
* broadcast that SI type. That will be reflected as 'omit' here.
@@ -100,8 +209,7 @@ type record SystemInformationConfig {
SI2quaterRestOctetsList si2quater optional,
SystemInformationType3 si3 optional,
SystemInformationType4 si4 optional,
- /* TODO: replace with proper decoding of SI13, implement SI13 in GSM_SystemInformation.ttcn */
- octetstring si13 optional,
+ SystemInformationType13 si13 optional,
SystemInformationType5 si5 optional,
SystemInformationType5bis si5bis optional,
SystemInformationType5ter si5ter optional,
@@ -131,7 +239,7 @@ template EUTRAN_CellDesc tr_EUTRAN_CellDesc_default(template (present) uint16_t
meas_bw := meas_bw);
/* tr_EUTRAN_NeighbourCells with defaults used in BSC_Tests.ttcn */
-template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
+template EUTRAN_NeighbourCells tr_EUTRAN_NeighbourCells_default(template (present) EUTRAN_CellDescs cell_desc_list := { tr_EUTRAN_CellDesc_default },
template uint3_t prio := 3,
template (present) uint5_t thresh_high := 20,
template uint5_t thresh_low := 10,
@@ -267,7 +375,24 @@ template SystemInformationConfig SystemInformationConfig_default := {
re_not_allowed := true,
acc := '0000010000000000'B
},
- cbch_chan_desc := omit,
+ cbch_chan_desc := {
+ iei := '64'O,
+ v := {
+ chan_nr := {
+ u := {
+ sdcch4 := {
+ tag := '001'B,
+ sub_chan := 2
+ }
+ },
+ tn := 0
+ },
+ tsc := 2,
+ h := false,
+ arfcn := 871,
+ maio_hsn := omit
+ }
+ },
cbch_mobile_alloc := omit,
rest_octets := {
sel_params := {
@@ -289,7 +414,44 @@ template SystemInformationConfig SystemInformationConfig_default := {
s := omit
}
},
- si13 := '9000185A6FC9E08410AB2B2B2B2B2B2B2B2B2B2B'O,
+ si13 := {
+ rest_octets := {
+ presence := '1'B,
+ bcch_change_mark := ?,
+ si_change_field := '0000'B,
+ presence2 := '0'B,
+ si13_change_mark := omit,
+ gprs_ma := omit,
+ zero := '0'B, /* PBCCH not present in cell */
+ rac := 0,
+ spgc_ccch_sup := '0'B,
+ priority_access_thr := '110'B,
+ network_control_order := '00'B,
+ gprs_cell_opts := {
+ nmo := '01'B,
+ t3168 := '011'B,
+ t3192 := '010'B,
+ drx_timer_max := '011'B,
+ access_burst_type := '0'B,
+ control_ack_type := '1'B,
+ bs_cv_max := 15,
+ pan_presence := '1'B,
+ pan_dec := 1,
+ pan_inc := 1,
+ pan_max := '111'B,
+ ext_info_presence := ?,
+ ext_info_length := *,
+ ext_info := *
+ },
+ gprs_pwr_ctrl_params := {
+ alpha := 0,
+ t_avg_w := '10000'B,
+ t_avg_t := '10000'B,
+ pc_meas_chan := '0'B,
+ n_avg_i := '1000'B
+ }
+ }
+ },
si5 := {
bcch_freq_list := '10000000000000000000000000000000'O
},
@@ -310,7 +472,14 @@ template SystemInformationConfig SystemInformationConfig_default := {
radio_link_timeout := '0111'B
},
ncc_permitted := '11111111'B,
- rest_octets := ?
+ rest_octets := {
+ pch_nch_info := ?,
+ vbs_vgcs_options := ?,
+ dtm_support := '0'B,
+ rac := omit,
+ max_lapdm := omit,
+ band_ind := '0'B /* C0 ARFCN indicates 1800 band */
+ }
}
};
@@ -398,7 +567,7 @@ function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
if (not isbound(data)) {
si.si13 := omit;
} else {
- si.si13 := dec_SystemInformation(data).payload.other;
+ si.si13 := dec_SystemInformation(data).payload.si13;
}
} else {
handled := false;
@@ -440,29 +609,49 @@ function f_sysinfo_dec_raw(inout SystemInformationConfig si, RSL_Message rsl)
}
}
+friend function gen_l3_valid_payload(hexstring imsi := ''H) return octetstring {
+ var octetstring l3_payload;
+ if (lengthof(imsi) == 0) {
+ imsi := f_rnd_imsi('00101'H);
+ }
+ l3_payload := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, ts_MI_LV(ts_MI_IMSI(imsi)))));
+ return l3_payload;
+}
+
type component test_CT extends CTRL_Adapter_CT {
- /* Array of per-BTS state */
- var BTS_State bts[NUM_BTS];
+ /* Array of per-BTS/TRX state */
+ var BTS_State bts[NUM_BTS][NUM_TRX];
/* RSL common Channel Port (for RSL_Emulation) */
port RSL_CCHAN_PT RSL_CCHAN[NUM_BTS];
- /* array of per-BTS RSL test ports */
- port IPA_RSL_PT IPA_RSL[NUM_BTS];
+ /* array of per-BTS/TRX RSL test ports */
+ port IPA_RSL_PT IPA_RSL[NUM_BTS][NUM_TRX];
port IPA_CODEC_PT IPA; /* Required for compilation of TC_rsl_unknown_unit_id() */
/* CTRL muxed over IPA in SCCPlite conn BSC<->MSC (or BSC-NAT) */
port IPA_CTRL_PT SCCPLITE_IPA_CTRL;
+ /* Configure/manage IPA_Emulation per-BTS/TRX port: */
+ port IPA_CFG_PT IPA_CFG_PORT[NUM_BTS][NUM_TRX];
- var MGCP_Emulation_CT vc_MGCP;
+ var MGCP_Emulation_CT vc_MGCP[NUM_MGW];
+ var integer g_nr_mgw; /* number of vc_MGCP to initialize */
port TELNETasp_PT BSCVTY;
+ /* StatsD */
+ var StatsD_Checker_CT vc_STATSD;
+
var RAN_Adapter g_bssap[NUM_MSC];
+ var BSSAP_LE_Adapter g_bssap_le;
/* for old legacy-tests only */
port BSSAP_CODEC_PT BSSAP;
+ port BSSAP_LE_CODEC_PT BSSAP_LE;
/* are we initialized yet */
var boolean g_initialized := false;
+ var boolean g_handler_mode := false;
+
/* Osmux is enabled through VTY */
- var boolean g_osmux_enabled := false;
+ var boolean g_osmux_enabled_cn := false;
+ var boolean g_osmux_enabled_bts := false;
/*Configure T(tias) over VTY, seconds */
var integer g_bsc_sccp_timer_ias := 7 * 60;
@@ -473,11 +662,14 @@ type component test_CT extends CTRL_Adapter_CT {
timer T_guard := 30.0;
var CounterNameValsList g_ctr_msc;
+ var CounterNameValsList g_ctr_bsc;
+ var CounterNameValsList g_ctr_bts;
/* System Information bytes as received during RSL startup, for each RSL[idx]. */
var SystemInformationConfig_list g_system_information := {};
}
+type record of charstring phys_chan_configs;
modulepar {
/* IP address at which the BSC can be reached */
charstring mp_bsc_ip := "127.0.0.1";
@@ -487,6 +679,8 @@ modulepar {
integer mp_bsc_rsl_port := 3003;
/* port number to which to establish the IPA CTRL connection */
integer mp_bsc_ctrl_port := 4249;
+ /* port number to which to listen for STATSD metrics */
+ integer mp_bsc_statsd_port := 8125;
/* IP address at which the test binds */
charstring mp_test_ip := "127.0.0.1";
@@ -526,15 +720,38 @@ modulepar {
}
};
- /* Whether to enable osmux tests. Can be dropped completely and enable
- unconditionally once new version of osmo-bsc is released (current
- version: 1.4.1) */
- boolean mp_enable_osmux_test := true;
+ /* Must match per BTS config in osmo-bsc.cfg */
+ phys_chan_configs phys_chan_config := {
+ "CCCH+SDCCH4+CBCH",
+ "TCH/F",
+ "TCH/F",
+ "TCH/F",
+ "TCH/F",
+ "TCH/H",
+ "PDCH",
+ "PDCH"
+ };
+
+ BSSAP_LE_Configuration mp_bssap_le_cfg := {
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 190, /* 0.23.6 SMLC emulation */
+ own_ssn := 252, /* SMLC side SSN */
+ peer_pc := 187, /* 0.23.3 osmo-bsc */
+ peer_ssn := 250, /* BSC side SSN */
+ sio := '83'O,
+ rctx := 6
+ };
+ boolean mp_enable_lcs_tests := true;
+
/* Value set in osmo-bsc.cfg "ms max power" */
uint8_t mp_exp_ms_power_level := 7;
+
+ /* Whether to check for memory leaks */
+ boolean mp_verify_talloc_count := true;
}
-private function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
+friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrParams {
var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
@@ -544,6 +761,11 @@ private function f_gen_test_hdlr_pars(integer bssap_idx := 0) return TestHdlrPar
}
pars.exp_ms_power_level := mp_exp_ms_power_level;
pars.mscpool.bssap_idx := bssap_idx;
+ pars.expect_tsc := c_BtsParams[0].tsc;
+ pars.imsi := f_rnd_imsi('00101'H);
+ pars.imei := f_rnd_imei('00101'H);
+
+ log(testcasename(), ": using IMSI ", pars.imsi);
return pars;
}
@@ -584,8 +806,115 @@ private function f_ctrs_msc_expect(integer msc_nr, charstring countername, integ
f_ctrs_msc_verify();
}
+/* Convenience functions for rate counters using g_ctr_bts, always also including g_ctr_bsc. */
+
+private function f_ctrs_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
+ g_ctr_bts := f_counter_name_vals_get_n(IPA_CTRL, "bts", bts_count, counternames);
+ log("initial bts rate counters: ", g_ctr_bts);
+}
+
+function f_ctrs_bsc_and_bts_init(integer bts_count := NUM_BTS, CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
+ f_ctrs_bts_init(bts_count, counternames);
+ f_ctrs_bsc_init(counternames);
+}
+
+private function f_ctrs_bsc_and_bts_handover_init(integer bts_count := NUM_BTS) runs on test_CT {
+ var CounterNameVals bts_names := counternames_bsc_bts_handover & counternames_bts_handover;
+ f_ctrs_bts_init(bts_count, bts_names);
+ f_ctrs_bsc_init(counternames_bsc_bts_handover);
+}
+
+private function f_ctrs_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_counter_name_vals_list_add(g_ctr_bts, bts_nr, countername, val);
+}
+
+private function f_ctrs_bsc_and_bts_add(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_bts_add(bts_nr, countername, val);
+ f_ctrs_bsc_add(countername, val);
+}
+
+function f_ctrs_bts_verify() runs on test_CT {
+ f_counter_name_vals_expect_n(IPA_CTRL, "bts", g_ctr_bts);
+}
+
+/* f_ctrs_bsc_and_bts_init();
+ * f_do_thing(on_bts := 0);
+ * f_do_thing(on_bts := 0);
+ * f_do_other(on_bts := 1);
+ * f_ctrs_bsc_and_bts_add(0, "thing", 2);
+ * f_ctrs_bsc_and_bts_add(1, "other");
+ * f_ctrs_bsc_and_bts_verify();
+ */
+private function f_ctrs_bsc_and_bts_verify() runs on test_CT {
+ f_ctrs_bts_verify();
+ f_ctrs_bsc_verify();
+}
+
+/* convenience: f_ctrs_bsc_and_bts_add() and f_ctrs_bsc_and_bts_verify() in one call.
+ * f_ctrs_bsc_and_bts_init();
+ * f_do_thing(on_bts := 0);
+ * f_do_thing(on_bts := 0);
+ * f_do_thing(on_bts := 0);
+ * f_ctrs_bsc_and_bts_expect(0, "thing", 3);
+ */
+private function f_ctrs_bsc_and_bts_expect(integer bts_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_bsc_and_bts_add(bts_nr, countername, val);
+ f_ctrs_bsc_and_bts_verify();
+}
+
+
+/* Convenience functions for rate counters using g_ctr_bsc. */
+
+private function f_ctrs_bsc_init(CounterNameVals counternames := counternames_bsc_bts_handover) runs on test_CT {
+ g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", 1, counternames);
+ log("initial bsc rate counters: ", g_ctr_bsc);
+}
+
+private function f_ctrs_bsc_add(charstring countername, integer val := 1) runs on test_CT {
+ f_counter_name_vals_list_add(g_ctr_bsc, 0, countername, val);
+}
+
+/* f_ctrs_bsc_init();
+ * f_do_thing();
+ * f_do_thing();
+ * f_do_other();
+ * f_ctrs_bsc_add("thing", 2);
+ * f_ctrs_bsc_add("other");
+ * f_ctrs_bsc_verify();
+ */
+private function f_ctrs_bsc_verify() runs on test_CT {
+ f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
+}
+
+/* convenience: f_ctrs_bsc_add() and f_ctrs_bsc_verify() in one call.
+ * f_ctrs_bsc_init();
+ * f_do_thing();
+ * f_ctrs_bsc_expect("thing", 1);
+ */
+private function f_ctrs_bsc_expect(charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_bsc_add(countername, val);
+ f_ctrs_bsc_verify();
+}
+
+
+friend function f_shutdown_helper(boolean ho := false) runs on test_CT {
+ /* Run the subscr and conn leak test only when the VTY is initialized */
+ if (BSCVTY.checkstate("Mapped") and mp_verify_talloc_count) {
+ f_verify_talloc_count(BSCVTY, {"struct bsc_subscr", "struct gsm_subscriber_connection"});
+ }
+
+ /* Reset handover related configuration */
+ if (ho) {
+ f_bts_0_cfg(BSCVTY,
+ {"no neighbors",
+ "neighbor-list mode manual-si5",
+ "neighbor-list add arfcn 100",
+ "neighbor-list add arfcn 200",
+ "si5 neighbor-list add arfcn 10",
+ "si5 neighbor-list add arfcn 20",
+ "handover algorithm 1"});
+ }
-private function f_shutdown_helper() runs on test_CT {
all component.stop;
setverdict(pass);
mtc.stop;
@@ -593,23 +922,36 @@ private function f_shutdown_helper() runs on test_CT {
private function f_legacy_bssap_reset(integer bssap_idx := 0) runs on test_CT {
var BSSAP_N_UNITDATA_ind ud_ind;
+ var boolean reset_received := false;
timer T := 5.0;
BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
- ts_BSSMAP_Reset(0, g_osmux_enabled)));
+ ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
T.start;
alt {
[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[bssap_idx].sccp_addr_own, g_bssap[bssap_idx].sccp_addr_peer,
- tr_BSSMAP_ResetAck(g_osmux_enabled))) {
- log("Received RESET-ACK in response to RESET, we're ready to go!");
+ tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) {
+ log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
}
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
- log("Respoding to inbound RESET with RESET-ACK");
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
+ log("BSSMAP: Respoding to inbound RESET with RESET-ACK");
BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
- ts_BSSMAP_ResetAck(g_osmux_enabled)));
+ ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
+ reset_received := true;
repeat;
}
[] BSSAP.receive { repeat; }
- [] T.timeout { setverdict(fail, "Waiting for RESET-ACK after sending RESET"); }
+ [] T.timeout {
+ /* If we received a RESET after ours was sent, it
+ may be a race condition where the other peer beacame
+ available after we sent it, but we are in a desired
+ state anyway, so go forward. */
+ if (not reset_received) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
+ } else {
+ log("BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
+ }
+ }
}
}
@@ -628,31 +970,33 @@ type record IPA_Client {
* \param clnt IPA_Client for which to establish
* \param bsc_host IP address / hostname of the BSC
* \param bsc_port TCP port number of the BSC
- * \param i number identifying this BTS
+ * \param idx BTS/TRX index values
* \param handler_mode Start an RSL_Emulation_CT component (true) or not (false) */
-function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port, integer i,
- boolean handler_mode := false)
+function f_ipa_rsl_start(inout IPA_Client clnt, charstring bsc_host, PortNumber bsc_port,
+ BtsTrxIdx idx := {0, 0}, boolean handler_mode := false)
runs on test_CT {
timer T := 10.0;
- clnt.id := "IPA" & int2str(i) & "-RSL";
- clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA");
+ clnt.id := "IPA-BTS" & int2str(idx.bts) & "-TRX" & int2str(idx.trx) & "-RSL";
+ clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id & "-IPA") alive;
clnt.ccm_pars := c_IPA_default_ccm_pars;
clnt.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
- clnt.ccm_pars.unit_id := int2str(1234+i) & "/0/0";
+ clnt.ccm_pars.unit_id := int2str(1234 + idx.bts) & "/0/" & int2str(idx.trx);
if (handler_mode) {
- clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL");
- connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[i]);
+ clnt.vc_RSL := RSL_Emulation_CT.create(clnt.id & "-RSL") alive;
+ connect(clnt.vc_RSL:CCHAN_PT, self:RSL_CCHAN[idx.bts]);
}
map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
+ connect(clnt.vc_IPA:CFG_PORT, self:IPA_CFG_PORT[idx.bts][idx.trx]);
if (handler_mode) {
connect(clnt.vc_IPA:IPA_RSL_PORT, clnt.vc_RSL:IPA_PT);
} else {
- connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[i]);
+ connect(clnt.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[idx.bts][idx.trx]);
}
- clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 10000+i, clnt.ccm_pars));
+ var integer local_port := 10000 + idx.bts * 1000 + idx.trx;
+ clnt.vc_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", local_port, clnt.ccm_pars));
if (handler_mode) {
clnt.vc_RSL.start(RSL_Emulation.main());
return;
@@ -661,12 +1005,11 @@ runs on test_CT {
/* wait for IPA RSL link to connect and send ID ACK */
T.start;
alt {
- [] IPA_RSL[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
T.stop;
- IPA_RSL[i].send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
}
- [] IPA_RSL[i].receive(ASP_IPA_Event:?) { repeat }
- [] IPA_RSL[i].receive { repeat }
+ [] IPA_RSL[idx.bts][idx.trx].receive(ASP_IPA_Event:?) { repeat }
+ [] IPA_RSL[idx.bts][idx.trx].receive { repeat }
[] T.timeout {
setverdict(fail, "Timeout RSL waiting for ASP_IPA_EVENT_ID_ACK");
mtc.stop;
@@ -674,10 +1017,23 @@ runs on test_CT {
}
}
-function f_ipa_rsl_stop(inout IPA_Client clnt) runs on test_CT {
+function f_ipa_rsl_stop(inout IPA_Client clnt, BtsTrxIdx idx := {0, 0}) runs on test_CT {
+ var IPL4asp_Types.Result res := {
+ errorCode := omit,
+ connId := omit,
+ os_error_code := omit,
+ os_error_text := omit
+ };
+
if (not isbound(clnt) or not isbound(clnt.vc_IPA)) {
return;
}
+
+ /* Alive components don't finish sockets (TCP FIN) when they are
+ * stopped. Hence, we need to manually call close() on them to make sure
+ * the IUT knows about it. */
+ f_ipa_cfg_disconnect(IPA_CFG_PORT[idx.bts][idx.trx], res);
+
clnt.vc_IPA.stop;
if (isbound(clnt.vc_RSL)) {
clnt.vc_RSL.stop;
@@ -713,22 +1069,22 @@ altstep as_Tguard() runs on test_CT {
mtc.stop;
}
/* always respond with RESET ACK to RESET */
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) -> value ud_ind {
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) -> value ud_ind {
BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
- ts_BSSMAP_ResetAck(g_osmux_enabled)));
+ ts_BSSMAP_ResetAck(g_osmux_enabled_cn)));
repeat;
}
}
altstep no_bssmap_reset() runs on test_CT {
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled))) {
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(g_osmux_enabled_cn))) {
setverdict(fail, "unexpected BSSMAP Reset");
mtc.stop;
}
}
-function f_init_mgcp(charstring id) runs on test_CT {
- id := id & "-MGCP";
+function f_init_mgcp(integer mgw_nr, charstring id) runs on test_CT {
+ id := id & "-MGCP-" & int2str(mgw_nr);
var MGCPOps ops := {
create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
@@ -738,21 +1094,21 @@ function f_init_mgcp(charstring id) runs on test_CT {
callagent_ip := mp_bsc_ip,
callagent_udp_port := -1,
mgw_ip := mp_test_ip,
- mgw_udp_port := 2427,
+ mgw_udp_port := 2427 + mgw_nr,
/* Enable it for SCCPlite, since we have 2 MGCP sockets towards MGW (UDP one +
- the on with MGCP over IPA forwarded from MSC one) */
+ the one with MGCP over IPA forwarded from MSC one) */
multi_conn_mode := (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER)
};
- vc_MGCP := MGCP_Emulation_CT.create(id);
- vc_MGCP.start(MGCP_Emulation.main(ops, mgcp_pars, id));
+ vc_MGCP[mgw_nr] := MGCP_Emulation_CT.create(id) alive;
+ vc_MGCP[mgw_nr].start(MGCP_Emulation.main(ops, mgcp_pars, id));
}
/* Enable or disable (current default) Osmux. When enabling, BSSMAP Reset
* contains extra IE (OsmuxSupport) and osmo-bsc will handle AssignReq with
* OsmuxCID IE.
*/
-private function f_vty_allow_osmux(boolean allow) runs on test_CT {
+private function f_vty_allow_osmux_cn(boolean allow) runs on test_CT {
f_vty_enter_cfg_msc(BSCVTY, 0);
if (allow) {
f_vty_transceive(BSCVTY, "osmux on");
@@ -761,7 +1117,6 @@ private function f_vty_allow_osmux(boolean allow) runs on test_CT {
}
f_vty_transceive(BSCVTY, "exit");
f_vty_transceive(BSCVTY, "exit");
- g_osmux_enabled := allow;
}
function f_init_vty(charstring id := "foo") runs on test_CT {
@@ -776,14 +1131,6 @@ function f_init_vty(charstring id := "foo") runs on test_CT {
"sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
}
-private function f_logp(charstring log_msg) runs on MSC_ConnHdlr
-{
- // log on TTCN3 log output
- log(log_msg);
- // log in stderr log
- f_vty_transceive(BSCVTY, "logp lglobal notice " & log_msg);
-}
-
private function f_sysinfo_seen(integer rsl_idx, RSL_Message rsl) runs on test_CT
{
if (rsl_idx >= lengthof(g_system_information)) {
@@ -796,19 +1143,19 @@ altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
var ASP_RSL_Unitdata rx_rsl_ud;
/* For handler_mode := false, receiving the RSL bootstrap messages directly on IPA_RSL */
- [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_BCCH_INFO)) -> value rx_rsl_ud {
f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
repeat;
}
- [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO)) -> value rx_rsl_ud {
f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
repeat;
}
- [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_NO_SACCH_FILL)) -> value rx_rsl_ud {
f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
repeat;
}
- [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_SACCH_FILL)) -> value rx_rsl_ud {
f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
repeat;
}
@@ -832,13 +1179,60 @@ altstep as_catch_RSL_sysinfo(integer rsl_idx) runs on test_CT {
}
}
+/* TODO: use BooleanList from COMMON/src/General_Types.ttcn */
+private type record of boolean my_BooleanList;
+
+private function f_vty_msc_allow_attach(TELNETasp_PT pt, my_BooleanList allow_attach_list)
+{
+ var charstring config := f_vty_transceive_ret(pt, "show running-config");
+
+ for (var integer msc_nr := 0; msc_nr < sizeof(allow_attach_list); msc_nr := msc_nr+1) {
+ if (f_strstr(config, "\nmsc " & int2str(msc_nr) & "\n") < 0) {
+ /* There is no 'msc N' for this msc_nr in the running config, so don't create an empty msc by
+ * stepping into that config node. */
+ log("msc ", msc_nr, " is not configured, skipping");
+ continue;
+ }
+ f_vty_enter_cfg_msc(pt, msc_nr);
+ if (allow_attach_list[msc_nr]) {
+ /* strict := false: ignore if osmo-bsc does not support this config option (latest build) */
+ f_vty_transceive(pt, "allow-attach", strict := false);
+ } else {
+ f_vty_transceive(pt, "no allow-attach", strict := false);
+ }
+ f_vty_transceive(pt, "exit");
+ f_vty_transceive(pt, "exit");
+ }
+}
+
+private function f_bssap_idx_init(integer bssap_idx) runs on test_CT {
+ /* Call a function of our 'parent component' RAN_Adapter_CT to start the
+ * MSC-side BSSAP emulation */
+ if (g_handler_mode) {
+ var RanOps ranops := MSC_RanOps;
+ ranops.use_osmux := g_osmux_enabled_cn;
+ f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
+ connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
+ f_ran_adapter_start(g_bssap[bssap_idx]);
+ } else {
+ f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
+ connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
+ f_ran_adapter_start(g_bssap[bssap_idx]);
+ f_legacy_bssap_reset();
+ }
+}
+
+private function f_bssap_idx_disconnect(integer bssap_idx) runs on test_CT {
+ f_ran_adapter_cleanup(g_bssap[bssap_idx]);
+}
+
/* global initialization function
* \param nr_bts Number of BTSs we should start/bring up
* \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
* \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
*/
-function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolean allow_osmux := false,
- integer nr_msc := 1, float guard_timeout := 30.0) runs on test_CT {
+function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false,
+ integer nr_msc := 1, integer nr_mgw := 1, float guard_timeout := 30.0) runs on test_CT {
var integer bssap_idx;
if (g_initialized) {
@@ -850,53 +1244,84 @@ function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolea
activate(as_Tguard());
f_init_vty("VirtMSC");
- if (mp_enable_osmux_test) {
- f_vty_allow_osmux(allow_osmux);
+ f_vty_allow_osmux_cn(g_osmux_enabled_cn);
+
+ var my_BooleanList allow_attach := { false, false, false };
+ f_init_statsd("VirtMSC", vc_STATSD, mp_test_ip, mp_bsc_statsd_port);
+
+ /* Make sure each MSC's internal state is "DISCONNECTED" at first */
+ for (bssap_idx := 0; bssap_idx < NUM_MSC; bssap_idx := bssap_idx+1) {
+ f_vty_transceive(BSCVTY, "msc " & int2str(bssap_idx) & " bssmap reset", strict := false);
}
+ g_handler_mode := handler_mode;
for (bssap_idx := 0; bssap_idx < nr_msc; bssap_idx := bssap_idx+1) {
- /* Call a function of our 'parent component' RAN_Adapter_CT to start the
- * MSC-side BSSAP emulation */
+ allow_attach[bssap_idx] := true;
+ f_bssap_idx_init(bssap_idx);
+ }
+
+ if (mp_enable_lcs_tests) {
if (handler_mode) {
- var RanOps ranops := MSC_RanOps;
- ranops.use_osmux := g_osmux_enabled;
- f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", ranops);
- connect(self:SCCPLITE_IPA_CTRL, g_bssap[bssap_idx].vc_RAN:CTRL_CLIENT);
- f_ran_adapter_start(g_bssap[bssap_idx]);
+ f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
} else {
- f_ran_adapter_init(g_bssap[bssap_idx], mp_bssap_cfg[bssap_idx], "VirtMSC", omit);
- connect(self:BSSAP, g_bssap[bssap_idx].vc_SCCP:SCCP_SP_PORT);
- f_ran_adapter_start(g_bssap[bssap_idx]);
- f_legacy_bssap_reset();
+ f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
+ connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
}
+ f_bssap_le_adapter_start(g_bssap_le);
}
- f_ipa_ctrl_start(mp_bsc_ip, mp_bsc_ctrl_port);
+ /* start the test with exactly all enabled MSCs allowed to attach */
+ f_vty_msc_allow_attach(BSCVTY, allow_attach);
- f_init_mgcp("VirtMSC");
+ f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
+
+ g_nr_mgw := nr_mgw;
+ for (var integer i := 0; i < g_nr_mgw; i := i+1) {
+ f_init_mgcp(i, "VirtMGW");
+ }
for (var integer i := 0; i < nr_bts; i := i+1) {
- f_init_bts(i, handler_mode);
+ f_init_bts(i, c_BtsParams[i].trx_num, handler_mode);
}
+
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(BSCVTY, testcasename() & "() start");
}
-function f_init_bts(integer bts_idx := 0, boolean handler_mode := false)
+function f_init_bts(integer bts_idx := 0,
+ integer trx_num := NUM_TRX_CFG,
+ boolean handler_mode := false)
runs on test_CT {
/* wait until osmo-bts-omldummy has respawned */
f_wait_oml(bts_idx, "degraded", 5.0);
- /* start RSL connection */
- f_ipa_rsl_start(bts[bts_idx].rsl, mp_bsc_ip, mp_bsc_rsl_port, bts_idx, handler_mode);
+ /* start RSL connection(s) */
+ for (var integer trx_idx := 0; trx_idx < trx_num; trx_idx := trx_idx + 1) {
+ f_ipa_rsl_start(bts[bts_idx][trx_idx].rsl,
+ mp_bsc_ip, mp_bsc_rsl_port,
+ {bts_idx, trx_idx}, handler_mode);
+ }
/* wait until BSC tells us "connected" */
f_wait_oml(bts_idx, "connected", 5.0);
+
+ /* Set up BTS with VTY commands: */
+ f_vty_enter_cfg_bts(BSCVTY, bts_idx);
+ if (g_osmux_enabled_bts) {
+ f_vty_transceive(BSCVTY, "osmux on");
+ } else {
+ f_vty_transceive(BSCVTY, "osmux off");
+ }
+ f_vty_transceive(BSCVTY, "end");
}
-function f_init_bts_and_check_sysinfo(integer bts_idx := 0, boolean handler_mode := false,
+function f_init_bts_and_check_sysinfo(integer bts_idx := 0,
+ integer trx_num := NUM_TRX_CFG,
+ boolean handler_mode := false,
template SystemInformationConfig expect_si)
runs on test_CT {
var default sysinfo := activate(as_catch_RSL_sysinfo(bts_idx));
- f_init_bts(bts_idx, handler_mode);
+ f_init_bts(bts_idx, trx_num, handler_mode);
/* Give some time to (hopefully/most likely) collect all system informations from RSL startup.
* We could stop as soon as all expected SI are received, but then we might miss SI that we don't expect and
@@ -917,18 +1342,20 @@ runs on test_CT {
}
}
-/* expect to receive a RSL message matching a specified template on a given BTS / stream */
-function f_exp_ipa_rx(integer bts_nr, template RSL_Message t_rx, float t_secs := 2.0, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
+/* expect to receive a RSL message matching a specified template on a given BTS / TRX */
+function f_exp_ipa_rx(template (present) RSL_Message t_rx,
+ BtsTrxIdx idx := {0, 0},
+ float Tval := 2.0)
runs on test_CT return RSL_Message {
var ASP_RSL_Unitdata rx_rsl_ud;
- timer T := t_secs;
+ timer T := Tval;
T.start;
alt {
- [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(t_rx, sid)) -> value rx_rsl_ud {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
T.stop;
}
- [] IPA_RSL[bts_nr].receive { repeat; }
+ [] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
[] T.timeout {
setverdict(fail, "Timeout expecting ", t_rx);
mtc.stop;
@@ -938,9 +1365,11 @@ runs on test_CT return RSL_Message {
}
/* helper function to transmit RSL on a given BTS/stream */
-function f_ipa_tx(integer bts_nr, template RSL_Message t_tx, IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
+function f_ipa_tx(template (value) RSL_Message t_tx,
+ BtsTrxIdx idx := {0, 0},
+ IpaStreamId sid := IPAC_PROTO_RSL_TRX0)
runs on test_CT {
- IPA_RSL[bts_nr].send(ts_ASP_RSL_UD(t_tx, sid));
+ IPA_RSL[idx.bts][idx.trx].send(ts_ASP_RSL_UD(t_tx, sid));
}
@@ -951,12 +1380,62 @@ testcase TC_chan_act_noreply() runs on test_CT {
f_init(1);
- IPA_RSL[0].send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD('23'O, 23)));
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
- setverdict(pass);
+ f_ipa_tx(ts_RSL_CHAN_RQD('23'O, 23));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ f_shutdown_helper();
+}
+
+const CounterNameVals counternames_bts_chreq := {
+ { "chreq:total", 0 },
+ { "chreq:attempted_emerg", 0 },
+ { "chreq:attempted_call", 0 },
+ { "chreq:attempted_location_upd", 0 },
+ { "chreq:attempted_pag", 0 },
+ { "chreq:attempted_pdch", 0 },
+ { "chreq:attempted_other", 0 },
+ { "chreq:attempted_unknown", 0 },
+ { "chreq:successful", 0 },
+ { "chreq:successful_emerg", 0 },
+ { "chreq:successful_call", 0 },
+ { "chreq:successful_location_upd", 0 },
+ { "chreq:successful_pag", 0 },
+ { "chreq:successful_pdch", 0 },
+ { "chreq:successful_other", 0 },
+ { "chreq:successful_unknown", 0 },
+ { "chreq:no_channel", 0 },
+ { "chreq:max_delay_exceeded", 0 }
+};
+
+/* verify the "chreq:*" counters */
+private function f_chan_act_counter(OCT1 ra, charstring chreq_ctr_suffix) runs on test_CT
+{
+ var GsmFrameNumber fn := 23;
+
+ f_logp(BSCVTY, "f_chan_act_counter(" & chreq_ctr_suffix & ")");
+
+ var RSL_Message rx_rsl;
+ f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
+
+ f_ctrs_bts_add(0, "chreq:total");
+ f_ctrs_bts_add(0, "chreq:attempted_" & chreq_ctr_suffix);
+ f_ctrs_bts_verify();
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+
+ f_ctrs_bts_add(0, "chreq:successful");
+ f_ctrs_bts_add(0, "chreq:successful_" & chreq_ctr_suffix);
+ f_ctrs_bts_verify();
+
+ /* test is done, release RSL Conn Fail Ind to clean up */
+ f_ipa_tx(ts_RSL_CONN_FAIL_IND(chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+ f_sleep(1.0);
}
-/* verify if the "chreq:total" counter increments as expected */
testcase TC_chan_act_counter() runs on test_CT {
var BSSAP_N_UNITDATA_ind ud_ind;
var integer chreq_total;
@@ -964,27 +1443,83 @@ testcase TC_chan_act_counter() runs on test_CT {
f_init(1);
- chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
- IPA_RSL[0].send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD('23'O, 23)));
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
- f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total", chreq_total+1);
+ f_vty_allow_emerg_bts(true, 0);
- setverdict(pass);
+ f_ctrs_bts_init(1, counternames_bts_chreq);
+
+ /* emergency call: RA & 0xe0 == 0xa0 --> CHREQ_T_EMERG_CALL */
+ f_chan_act_counter('a3'O, "emerg");
+
+ /* voice TCH/H: RA & 0xf0 == 0x40 --> CHREQ_T_VOICE_CALL_TCH_H */
+ f_chan_act_counter('43'O, "call");
+
+ /* LU: RA & 0xf0 == 0x00 --> CHREQ_T_LOCATION_UPD */
+ f_chan_act_counter('03'O, "location_upd");
+
+ /* Paging: RA & 0xf0 == 0x20 --> CHREQ_T_PAG_R_TCH_F */
+ f_chan_act_counter('23'O, "pag");
+ /* Paging: RA & 0xf0 == 0x30 --> CHREQ_T_PAG_R_TCH_FH */
+ f_chan_act_counter('33'O, "pag");
+
+ /* LU: RA & 0xfc == 0x78 --> CHREQ_T_PDCH_TWO_PHASE */
+ /* no PCU, so PDCH not allowed. Skip this test for now. */
+ /* f_chan_act_counter('7b'O, "pdch"); */
+
+ /* LU: RA & 0xf0 == 0x10 --> CHREQ_T_SDCCH */
+ f_chan_act_counter('13'O, "other");
+
+ f_shutdown_helper();
}
/* CHAN RQD -> CHAN ACT -> CHAN ACT ACK -> RF CHAN REL */
-testcase TC_chan_act_ack_noest() runs on test_CT {
+private function f_TC_chan_act_ack_noest(OCT1 ra := '23'O) runs on test_CT {
var RSL_Message rx_rsl;
- f_init(1);
-
/* Send CHAN RQD and wait for allocation; acknowledge it */
- var RslChannelNr chan_nr := f_chreq_act_ack();
+ var RslChannelNr chan_nr := f_chreq_act_ack(ra);
/* expect BSC to disable the channel again if there's no RLL EST IND */
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := T3101_MAX);
- setverdict(pass);
+ f_shutdown_helper();
+}
+
+/* Normal variant */
+testcase TC_chan_act_ack_noest() runs on test_CT {
+ f_init(1);
+ f_TC_chan_act_ack_noest();
+}
+
+/* Emergency call variant */
+testcase TC_chan_act_ack_noest_emerg() runs on test_CT {
+ /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
+ f_init(1);
+ f_vty_allow_emerg_bts(true, 0);
+ f_TC_chan_act_ack_noest(ra := 'A5'O);
+}
+
+/* Emergency call variant, but emergency calls are not allowed */
+testcase TC_chan_rqd_emerg_deny() runs on test_CT {
+ /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
+
+ var RSL_Message rx_rsl;
+ var GsmRrMessage rr;
+
+ f_init(1);
+ f_vty_allow_emerg_bts(false, 0);
+
+ IPA_RSL[0][0].clear;
+ f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
+
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
+ rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
+ if (rr.header.message_type == IMMEDIATE_ASSIGNMENT_REJECT) {
+ setverdict(pass);
+ } else {
+ setverdict(fail, "immediate assignment not rejected");
+ }
+
+ f_shutdown_helper();
}
/* Test behavior if MSC never answers to CR */
@@ -993,42 +1528,42 @@ testcase TC_chan_act_ack_est_ind_noreply() runs on test_CT {
var IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
var RSL_Message rx_rsl;
var ASP_RSL_Unitdata rx_rsl_ud;
+ var octetstring l3_payload := gen_l3_valid_payload();
f_init(1);
/* Send CHAN RQD and wait for allocation; acknowledge it */
var RslChannelNr chan_nr := f_chreq_act_ack();
- var octetstring l3 := '00010203040506'O
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
- BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3)));
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload)));
/* expect BSC to disable the channel again if there's no response from MSC */
/* MS waits 20s (T3210) at LU; 10s (T3230) at CM SERV REQ and 5s (T3220) AT detach */
- f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* Test behavior if MSC answers with CREF to CR */
testcase TC_chan_act_ack_est_ind_refused() runs on test_CT {
var BSSAP_N_CONNECT_ind rx_c_ind;
var RSL_Message rx_rsl;
+ var octetstring l3_payload := gen_l3_valid_payload();
f_init(1);
/* Send CHAN RQD and wait for allocation; acknowledge it */
var RslChannelNr chan_nr := f_chreq_act_ack();
- var octetstring l3 := '00010203040506'O
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
- BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
BSSAP.send(ts_BSSAP_DISC_req(rx_c_ind.connectionId, 0));
/* expect BSC to disable the channel */
- f_expect_chan_rel(0, chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* CHAN RQD -> CHAN ACT -> CHAN ACT NACK -> RF CHAN REL */
@@ -1040,18 +1575,18 @@ testcase TC_chan_act_nack() runs on test_CT {
chact_nack := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack");
- f_ipa_tx(0, ts_RSL_CHAN_RQD('33'O, 33));
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ f_ipa_tx(ts_RSL_CHAN_RQD('33'O, 33));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
- f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
+ f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
/* wait for some time to hope the NACK arrives before the CTRL GET below */
f_sleep(0.5);
f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chan_act:nack", chact_nack+1);
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test for channel exhaustion due to RACH overload */
@@ -1065,26 +1600,26 @@ testcase TC_chan_exhaustion() runs on test_CT {
chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
- /* GSM 04.08 Table 9.9a:
+ /* GSM 44.018 Table 9.1.8.2:
* RA = '33'O -> Establishment cause = 0011xxxx (MS dual rate capable and asks for "TCH/H or TCH/F").
* With current setup, expect 4xSDCCH + 4xTCH/F + 1xTCH/H to succeed */
for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
var RslChannelNr chan_nr := f_chreq_act_ack('33'O, i);
}
- IPA_RSL[0].clear;
+ IPA_RSL[0][0].clear;
f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
/* now expect additional channel activations to fail */
- f_ipa_tx(0, ts_RSL_CHAN_RQD('42'O, 42));
+ f_ipa_tx(ts_RSL_CHAN_RQD('42'O, 42));
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV))) {
setverdict(fail, "Received CHAN ACT ACK without resources?!?");
}
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) -> value rsl_ud {
var GsmRrMessage rr;
/* match on IMM ASS REJ */
rr := dec_GsmRrMessage(rsl_ud.rsl.ies[1].body.full_imm_ass_info.payload);
@@ -1098,8 +1633,9 @@ testcase TC_chan_exhaustion() runs on test_CT {
repeat;
}
}
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[0][0].receive { repeat; }
}
+ f_shutdown_helper();
}
/* Test channel deactivation due to silence from MS */
@@ -1116,21 +1652,22 @@ testcase TC_chan_deact_silence() runs on test_CT {
/* Expect CHANnel RELease */
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
log("Received CHANnel RELease");
setverdict(pass);
}
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN(?))) {
/* See OS#3709, OsmoBSC should not send Immediate
* Assignment Reject since a dedicated channel was
* already allocated, and Immediate Assignment was
* already sent. */
setverdict(fail, "Unexpected Immediate Assignment!");
}
- [] IPA_RSL[0].receive {
+ [] IPA_RSL[0][0].receive {
setverdict(fail, "Unexpected RSL message!");
}
}
+ f_shutdown_helper();
}
/***********************************************************************
@@ -1145,7 +1682,7 @@ testcase TC_outbound_connect(integer bssap_idx := 0) runs on test_CT {
BSSAP.send(ts_BSSAP_CONNECT_req(g_bssap[bssap_idx].sccp_addr_peer, g_bssap[bssap_idx].sccp_addr_own,
2342, ts_BSSMAP_AssignmentReq));
BSSAP.receive(tr_BSSAP_DISC_ind(2342, ?, ?));
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior if MSC answers with CREF to CR */
@@ -1156,12 +1693,12 @@ testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00000000'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
/* send assignment without AoIP IEs */
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(ts_BSSMAP_IE_CIC(0, 1))));
} else {
- /* Send assignmetn without CIC in IPA case */
+ /* Send assignment without CIC in IPA case */
var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_AssignmentReq(omit, tla)));
@@ -1176,67 +1713,115 @@ testcase TC_assignment_cic_only(integer bssap_idx := 0) runs on test_CT {
}
[] BSSAP.receive { repeat; }
}
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
}
/* generate an assignment request for either AoIP or SCCPlite */
-function f_gen_ass_req(boolean osmux_enabled := false, integer bssap_idx := 0) return PDU_BSSAP {
+function f_gen_ass_req(boolean osmux_enabled := false, uint8_t ass_cid := 0, integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4") return PDU_BSSAP {
var PDU_BSSAP ass_cmd;
- var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
+ var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(ass_cid));
if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
- valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
+ valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
if (osmux_enabled) {
ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla, osmux_cid));
} else {
ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
}
} else {
- var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
+ var BIT8 ass_cid_bit := int2bit(ass_cid, 8);
+ var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(bit2int(ass_cid_bit >> 5),
+ bit2int(ass_cid_bit and4b '00011111'B)));
ass_cmd := valueof(ts_BSSMAP_AssignmentReq(cic, omit));
}
return ass_cmd;
}
-function f_gen_handover_req(integer bssap_idx := 0) return PDU_BSSAP {
+function f_gen_handover_req(integer bssap_idx := 0, charstring aoip_tla := "1.2.3.4",
+ template (value) BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
+ template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
+ template (omit) TestHdlrEncrParams enc := omit) return PDU_BSSAP {
var PDU_BSSAP ho_req;
+
+ var BSSMAP_IE_EncryptionInformation encryptionInformation :=
+ valueof(ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O));
+ var template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit;
+ var template (omit) BSSMAP_IE_KC128 kc128 := omit;
+ if (ispresent(enc)) {
+ var TestHdlrEncrParams v_enc := valueof(enc);
+ encryptionInformation := valueof(ts_BSSMAP_IE_EncrInfo(v_enc.enc_key, v_enc.enc_alg_permitted));
+ if (ispresent(v_enc.enc_alg_chosen)) {
+ chosenEncryptionAlgorithm := valueof(
+ ts_BSSMAP_IE_ChosenEncryptionAlgorithm(int2oct(enum2int(
+ f_cipher_mode_bssmap_to_rsl(v_enc.enc_alg_chosen)), 1)));
+ }
+ if (ispresent(v_enc.enc_kc128)) {
+ kc128 := ts_BSSMAP_IE_Kc128(v_enc.enc_kc128);
+ }
+ }
+
if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
- valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
- ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla));
+ valueof(f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342));
+ ho_req := valueof(ts_BSSMAP_HandoverRequest(omit, tla,
+ cell_id_source := cell_id_source,
+ oldToNewBSSIEs := oldToNewBSSIEs,
+ encryptionInformation := encryptionInformation,
+ chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
+ kC128 := kc128,
+ /* on AoIP, allow "all" codecs (until we add more concise
+ * tests) */
+ codecList := ts_BSSMAP_IE_CodecList(
+ {ts_CodecAMR_F, ts_CodecAMR_H,
+ ts_CodecEFR, ts_CodecFR, ts_CodecHR})));
} else {
var BSSMAP_IE_CircuitIdentityCode cic := valueof(ts_BSSMAP_IE_CIC(0,1));
- ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit));
+ ho_req := valueof(ts_BSSMAP_HandoverRequest(cic, omit,
+ cell_id_source := cell_id_source,
+ oldToNewBSSIEs := oldToNewBSSIEs,
+ encryptionInformation := encryptionInformation,
+ chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
+ kC128 := kc128));
}
return ho_req;
}
/* generate an assignment complete template for either AoIP or SCCPlite */
-function f_gen_exp_compl(boolean expect_osmux := false, integer bssap_idx := 0) return template PDU_BSSAP {
+function f_gen_exp_compl(integer bssap_idx := 0)
+runs on MSC_ConnHdlr return template PDU_BSSAP {
var template PDU_BSSAP exp_compl;
- var BSSMAP_IE_Osmo_OsmuxCID osmux_cid := valueof(ts_OsmuxCID(0));
if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
- if (expect_osmux) {
- exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, osmux_cid);
- } else {
- exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, omit);
+ var template BSSMAP_IE_Osmo_OsmuxCID exp_osmux_cid := omit;
+ if (g_pars.use_osmux_cn) {
+ var template (present) INT1 exp_cid := ?;
+ if (isbound(g_media.mgcp_conn[0].local_osmux_cid) and isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
+ exp_cid := (g_media.mgcp_conn[0].local_osmux_cid, g_media.mgcp_conn[1].local_osmux_cid);
+ } else if (isbound(g_media.mgcp_conn[0].local_osmux_cid)) {
+ exp_cid := g_media.mgcp_conn[0].local_osmux_cid;
+ } else if (isbound(g_media.mgcp_conn[1].local_osmux_cid)) {
+ exp_cid := g_media.mgcp_conn[1].local_osmux_cid;
+ }
+ exp_osmux_cid := tr_OsmuxCID(exp_cid);
}
+ exp_compl := tr_BSSMAP_AssignmentComplete(omit, ?, exp_osmux_cid);
} else {
/* CIC is optional "*" as the MSC allocated it */
- exp_compl := tr_BSSMAP_AssignmentComplete(*, omit);
+ exp_compl := tr_BSSMAP_AssignmentComplete(*, omit, omit);
}
return exp_compl;
}
/* Run everything required up to sending a caller-specified assignment command and expect response */
function f_assignment_exp(PDU_BSSAP ass_cmd, template PDU_BSSAP exp, charstring fail_text)
-runs on test_CT {
+runs on test_CT return DchanTuple {
var BSSAP_N_CONNECT_ind rx_c_ind;
var RSL_Message rx_rsl;
var DchanTuple dt;
f_init(1);
- dt := f_est_dchan('23'O, 23, '00000000'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* send assignment without AoIP IEs */
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
alt {
@@ -1256,13 +1841,65 @@ runs on test_CT {
}
[] BSSAP.receive { repeat; }
}
+ return dt;
}
-testcase TC_assignment_csd() runs on test_CT {
- var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
+
+private function f_tc_assignment_csd(charstring data_rate_str, OCT1 data_rate, boolean transp := true) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
var PDU_BSSAP ass_cmd := f_gen_ass_req();
+ var SDP_FIELD_PayloadType pt_csd := PT_CSD;
+
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
- //exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
- f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for CSD");
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecCSData}));
+
+ /* Non-transparent service (3GPP TS 48.008 § 3.2.2.11, oct 5, bit 7) */
+ if (not transp) {
+ data_rate := data_rate or4b '40'O;
+ }
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := data_rate;
+
+ log("-----------------------------------------------");
+ log("Assignment req with data rate: " & data_rate_str);
+ log("-----------------------------------------------");
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected RTP payload type: ", g_media.bts.rtp_pt));
+ }
+
+ f_perform_clear();
+ f_create_mgcp_delete_ep(g_media.mgcp_ep);
+}
+private function f_tc_assignment_csd_all(charstring id) runs on MSC_ConnHdlr {
+ /* Data rates that require multi-slot HSCSD assignment are not tested
+ * on purpose (not supported): T_32k0, T_28k8, NT_43k5, NT_29k0 */
+ f_tc_assignment_csd("T_14k4", GSM0808_DATA_RATE_TRANSP_14k4);
+ f_tc_assignment_csd("T_9k6", GSM0808_DATA_RATE_TRANSP_9k6);
+ f_tc_assignment_csd("T_4k8", GSM0808_DATA_RATE_TRANSP_4k8);
+ f_tc_assignment_csd("T_2k4", GSM0808_DATA_RATE_TRANSP_2k4);
+ f_tc_assignment_csd("T_1k2", GSM0808_DATA_RATE_TRANSP_1k2);
+ f_tc_assignment_csd("T_600", GSM0808_DATA_RATE_TRANSP_600);
+ f_tc_assignment_csd("T_1200_75", GSM0808_DATA_RATE_TRANSP_1200_75);
+
+ f_tc_assignment_csd("NT_12000_6000", GSM0808_DATA_RATE_NON_TRANSP_12000_6000, false);
+ f_tc_assignment_csd("NT_14k5", GSM0808_DATA_RATE_NON_TRANSP_14k5, false);
+ f_tc_assignment_csd("NT_12k0", GSM0808_DATA_RATE_NON_TRANSP_12k0, false);
+ f_tc_assignment_csd("NT_6k0", GSM0808_DATA_RATE_NON_TRANSP_6k0, false);
+}
+testcase TC_assignment_csd() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.encr := valueof(t_EncrParams('01'O, f_rnd_octstring(8)));
+
+ f_init(1, true, guard_timeout := 120.0);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_assignment_csd_all), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
}
testcase TC_assignment_ctm() runs on test_CT {
@@ -1270,51 +1907,94 @@ testcase TC_assignment_ctm() runs on test_CT {
var PDU_BSSAP ass_cmd := f_gen_ass_req();
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
//exp_fail.pdu.bssmap.assignmentFailure.cause.causeValue := int2bit(enum2int(GSM0808_CAUSE_REQ_CODEC_TYPE_OR_CONFIG_UNAVAIL), 7);
- f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
+ var DchanTuple dt := f_assignment_exp(ass_cmd, exp_fail, "BSC accepted Assignment for Speech+CTM");
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
}
type record DchanTuple {
integer sccp_conn_id,
- RslChannelNr rsl_chan_nr
+ RslChannelNr rsl_chan_nr,
+ BtsTrxIdx idx
}
+type record of DchanTuple DchanTuples;
+
/* Send CHAN RQD and wait for allocation; acknowledge it */
-private function f_chreq_act_ack(OCT1 ra := '23'O, GsmFrameNumber fn := 23)
+private function f_chreq_act_ack(OCT1 ra := '23'O,
+ GsmFrameNumber fn := 23,
+ BtsTrxIdx idx := {0, 0})
runs on test_CT return RslChannelNr {
var RSL_Message rx_rsl;
- f_ipa_tx(0, ts_RSL_CHAN_RQD(ra, fn));
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
var RslChannelNr chan_nr := rx_rsl.ies[0].body.chan_nr;
- f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_IMM_ASSIGN(0));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10), idx);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
return chan_nr;
}
/* helper function to establish a dedicated channel via BTS and MSC */
-function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3)
+function f_est_dchan(OCT1 ra, GsmFrameNumber fn, octetstring l3,
+ BtsTrxIdx idx := {0, 0})
runs on test_CT return DchanTuple {
var BSSAP_N_CONNECT_ind rx_c_ind;
var DchanTuple dt;
/* Send CHAN RQD and wait for allocation; acknowledge it */
- dt.rsl_chan_nr := f_chreq_act_ack(ra, fn);
+ dt.rsl_chan_nr := f_chreq_act_ack(ra, fn, idx);
+
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
+
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+
+ dt.idx := idx;
+ return dt;
+}
- f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
+/* Like f_est_dchan(), but for the first lchan of a dynamic timeslot: first ACK the deactivation of PDCH. */
+function f_est_dchan_dyn(OCT1 ra, GsmFrameNumber fn, octetstring l3,
+ BtsTrxIdx idx := {0, 0})
+runs on test_CT return DchanTuple {
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ var DchanTuple dt;
+
+ /* Send CHAN RQD */
+ var RSL_Message rx_rsl;
+ f_ipa_tx(ts_RSL_CHAN_RQD(ra, fn), {idx.bts, 0});
+
+ /* The dyn TS first deactivates PDCH */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), idx, Tval := T3101_MAX);
+ dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), idx);
+
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
+ dt.rsl_chan_nr := rx_rsl.ies[0].body.chan_nr;
+
+ /* Now activates the signalling channel */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, fn+10), idx);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0), {idx.bts, 0});
+
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3), idx);
BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) -> value rx_c_ind;
dt.sccp_conn_id := rx_c_ind.connectionId;
BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+ dt.idx := idx;
return dt;
}
/* expect RF CAN REL from BTS, acknowledge it and clear the MSC side */
-private function f_exp_chan_rel_and_clear(DchanTuple dt, integer bts_nr := 0) runs on test_CT {
+private function f_exp_chan_rel_and_clear(DchanTuple dt)
+runs on test_CT {
var RSL_Message rx_rsl;
/* expect BSC to disable the channel */
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), T3101_MAX);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), dt.idx, Tval := T3101_MAX);
/* respond with CHAN REL ACK */
- f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr), dt.idx);
/* expect Clear Complete from BSC */
BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
@@ -1330,10 +2010,10 @@ testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* simulate RLL REL IND */
- f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
+ f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
/* expect Clear Request on MSC side */
BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
@@ -1343,12 +2023,12 @@ testcase TC_chan_rel_rll_rel_ind() runs on test_CT {
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
/* expect BSC to disable the channel */
- f_exp_chan_rel_and_clear(dt, 0);
+ f_exp_chan_rel_and_clear(dt);
/* wait for SCCP emulation to do its job */
f_sleep(1.0);
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior of channel release after CONN FAIL IND from BTS */
@@ -1358,10 +2038,14 @@ testcase TC_chan_rel_conn_fail() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
+
+ /* Sending CONN FAIL IND immediately may trigger a race condition.
+ * Give the BSC some time to process a new SCCP connection (OS#5823). */
+ f_sleep(0.2);
/* simulate CONN FAIL IND */
- f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+ f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
/* TODO: different cause values? */
/* expect Clear Request from BSC */
@@ -1372,12 +2056,12 @@ testcase TC_chan_rel_conn_fail() runs on test_CT {
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
/* expect BSC to disable the channel */
- f_exp_chan_rel_and_clear(dt, 0);
+ f_exp_chan_rel_and_clear(dt);
/* wait for SCCP emulation to do its job */
f_sleep(1.0);
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior of early CONN FAIL IND from BTS (before EST IND!) */
@@ -1389,18 +2073,18 @@ testcase TC_early_conn_fail() runs on test_CT {
f_init(1);
/* BTS->BSC: Send CHAN RQD and wait for allocation; acknowledge it */
- dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_octstring(1), 23);
+ dt.rsl_chan_nr := f_chreq_act_ack(f_rnd_ra_cs(), 23);
/* BTS->BSC: simulate CONN FAIL IND */
- f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+ f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
/* BTS->BSC: Expect RF channel release from BSC on Abis */
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
/* BTS<-BSC: respond with CHAN REL ACK */
- f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior of late CONN FAIL IND from BTS (ater REL IND!) */
@@ -1411,21 +2095,21 @@ testcase TC_late_conn_fail() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* BSC<-MSC: Instruct BSC to clear connection */
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(0)));
/* BTS->BSC: expect BSC to deactivate SACCH */
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_DEACT_SACCH(dt.rsl_chan_nr));
/* BTS->BSC: simulate a late CONN FAIL IND from BTS */
- f_ipa_tx(0, ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+ f_ipa_tx(ts_RSL_CONN_FAIL_IND(dt.rsl_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
/* BTS<-BSC: Expect RF channel release from BSC on Abis */
- rx_rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), 10.0);
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL), Tval := 10.0);
/* BTS->BSC: respond with CHAN REL ACK */
- f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(dt.rsl_chan_nr));
/* BSC->MSC: expect Clear Complete from BSC */
BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete));
@@ -1433,50 +2117,127 @@ testcase TC_late_conn_fail() runs on test_CT {
/* BSC<-MSC: MSC disconnects as requested. */
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
- setverdict(pass);
+ f_shutdown_helper();
+}
+
+private function f_TC_stats_conn_fail(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ f_statsd_reset();
+
+ /* Establish SDCCH (invalid DataIndicator for exp_fail) */
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeCSD);
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := 'ff'O;
+ f_establish_fully(ass_cmd, exp_fail);
+
+ /* Expect stats to be 0 */
+ var StatsDExpects expect := {
+ {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 0, max := 0},
+ {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ /* Simulate CONN FAIL IND on SDCCH */
+ RSL.send(ts_ASP_RSL_UD(
+ ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL),
+ IPAC_PROTO_RSL_TRX0));
+
+ f_sleep(1.0);
+
+ /* Expect stats to be 1 */
+ expect := {
+ {name := "TTCN3.bts.0.chan.rf_fail", mtype := "c", min := 1, max := 1},
+ {name := "TTCN3.bts.0.chan.rf_fail_sdcch", mtype := "c", min := 1, max := 1}
+ };
+ f_statsd_expect(expect);
+ BSSAP.receive(tr_BSSMAP_ClearRequest);
+ f_perform_clear();
+}
+testcase TC_stats_conn_fail() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ vc_conn := f_start_handler(refers(f_TC_stats_conn_fail), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
}
-function f_expect_chan_rel(integer bts_nr, RslChannelNr rsl_chan_nr,
+function f_expect_chan_rel(RslChannelNr rsl_chan_nr,
+ BtsTrxIdx idx := {0, 0},
boolean expect_deact_sacch := true,
boolean expect_rr_chan_rel := true,
boolean expect_rll_rel_req := true,
boolean handle_rll_rel := true,
- boolean is_csfb := false
+ template CellSelIndValue expect_cells := omit,
+ template (present) RR_Cause expect_rr_cause := ?
) runs on test_CT {
var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
var boolean got_deact_sacch := false;
var boolean got_rr_chan_rel := false;
var boolean got_rll_rel_req := false;
+ var ASP_RSL_Unitdata ud;
+ var RSL_IE_Body l3_ie;
+ var PDU_ML3_NW_MS l3;
+ var RR_Cause got_cause;
log("f_expect_chan_rel() expecting: expect_deact_sacch=", expect_deact_sacch, " expect_rr_chan_rel=", expect_rr_chan_rel,
" expect_rll_rel_req=", expect_rll_rel_req);
alt {
- [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DEACT_SACCH(rsl_chan_nr))) {
got_deact_sacch := true;
repeat;
}
- [is_csfb] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE_CSFB))) {
- got_rr_chan_rel := true;
- repeat;
- }
- [not is_csfb] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(rsl_chan_nr, ?, decmatch tr_RRM_RR_RELEASE))) -> value ud {
got_rr_chan_rel := true;
+
+ if (f_rsl_find_ie(ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
+ setverdict(fail, "cannot find L3");
+ mtc.stop;
+ }
+ l3 := dec_PDU_ML3_NW_MS(l3_ie.l3_info.payload);
+
+ if (not istemplatekind(expect_cells, "omit")) {
+ var CellSelIndValue cells := dec_CellSelIndValue(
+ l3.msgs.rrm.channelRelease.cellSelectionIndicator.cellSelectionIndicatorValue);
+
+ log("GOT RR CHANNEL RELEASE WITH CELLS: ", cells);
+ if (match(cells, expect_cells)) {
+ setverdict(pass);
+ } else {
+ log("EXPECTED CELLS: ", expect_cells);
+ setverdict(fail, "Received cells list on RR Channel Release does not match expectations");
+ }
+ }
+
+ int2enum(oct2int(l3.msgs.rrm.channelRelease.rRCause.valuePart), got_cause);
+ log("GOT CAUSE CODE: ", l3.msgs.rrm.channelRelease.rRCause.valuePart, " = ", got_cause);
+ if (match(got_cause, expect_rr_cause)) {
+ setverdict(pass);
+ } else {
+ log("EXPECTED CAUSE CODE: ", expect_rr_cause);
+ setverdict(fail, "Received RR Channel Release Cause code does not match expectations");
+ }
repeat;
}
- [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_REL_REQ(rsl_chan_nr, ?))) {
got_rll_rel_req := true;
/* FIXME: Why are we getting this for LinkID SACCH? */
if (handle_rll_rel) {
- f_ipa_tx(0, ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
+ f_ipa_tx(ts_RSL_REL_CONF(rsl_chan_nr, main_dcch));
}
repeat;
}
- [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL))) {
/* respond with CHAN REL ACK */
- f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(rsl_chan_nr));
}
/* ignore any user data */
- [] IPA_RSL[bts_nr].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeR(?))) {
repeat;
}
}
@@ -1502,7 +2263,7 @@ testcase TC_chan_rel_hard_clear() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* Instruct BSC to clear channel */
var BssmapCause cause := 0;
@@ -1514,18 +2275,73 @@ testcase TC_chan_rel_hard_clear() runs on test_CT {
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
}
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
+}
+
+function f_TC_chan_rel_last_eutran_plmn_hard_clear(boolean tx_csfb_ind) runs on test_CT {
+ var BSSAP_N_DATA_ind rx_di;
+ var DchanTuple dt;
+
+ f_init(1);
+
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
+ /* Send CommonID with some random PLMN (BSC doesn't take it into account
+ /* yet when generating the EUTRAN neigh list in RR CHannel Release) */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
+
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ if (tx_csfb_ind) {
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
+ } else {
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ }
+
+ /* expect Clear Complete from BSC on A */
+ BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
+ /* release the SCCP connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ }
+
+ /* 1 neighbor is added by default in osmo-bts.cfg and
+ SystemInformationConfig_default, use that: */
+ var template CellSelIndValue exp_cells := f_tr_rr_chan_rel_earfcns(1);
+
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := exp_cells);
+ f_shutdown_helper();
}
-/* Test behavior of channel release after Clear Command with CSFB indicator from MSC */
+/* Test behavior of RR Channel rRelease after Clear Command without CSFB indicator
+ from MSC, previously receiving any CommonID containing the "Last Used E-UTRAN
+ PLMN Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
+ EUTRAN neighbor list sent later on by BSC in RR Channel, so receiving CSFB
+ Indicator or not shouldn't matter at all. */
+testcase TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() runs on test_CT {
+ f_TC_chan_rel_last_eutran_plmn_hard_clear(false);
+}
+
+/* Test behavior of RR Channel rRelease after Clear Command with CSFB indicator from
+ MSC, previously receiving any CommonID containing the "Last Used E-UTRAN PLMN
+ Id". According to spec (3GPP TS 48.008 sec 3.1.30) that's the bit requesting
+ EUTRAN neighbor list sent later on by BSC in RR Channel. */
+testcase TC_chan_rel_last_eutran_plmn_hard_clear_csfb() runs on test_CT {
+ f_TC_chan_rel_last_eutran_plmn_hard_clear(true);
+}
+
+/* Test behavior of RR Channel Release after Clear Command with CSFB indicator from
+ MSC, without receiving any CommonID containing the "Last Used E-UTRAN PLMN
+ Id". According to spec (TS 48.008 version 16.0.0 Release 16 "3.2.1.21") the
+ CSFB Indicator should not be used anymore, and hence, there should be no
+ EUTRAN neighbor list sent by BSC in RR Channel release since no CommonId with
+ Last Used E-UTRAN PLMN Id" IE was sent for this conn. */
testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
var BSSAP_N_DATA_ind rx_di;
var DchanTuple dt;
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* Instruct BSC to clear channel */
var BssmapCause cause := 0;
@@ -1537,8 +2353,8 @@ testcase TC_chan_rel_hard_clear_csfb() runs on test_CT {
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
}
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false, is_csfb := true);
- setverdict(pass);
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* Test behavior of channel release after hard RLSD from MSC */
@@ -1547,13 +2363,13 @@ testcase TC_chan_rel_hard_rlsd() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* release the SCCP connection */
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* Test behavior of channel release after hard RLSD from MSC and MS is not responding to RLL REL REQ */
@@ -1562,13 +2378,13 @@ testcase TC_chan_rel_hard_rlsd_ms_dead() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* release the SCCP connection */
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* Test behavior of channel release after BSSMAP RESET from MSC */
@@ -1577,20 +2393,20 @@ testcase TC_chan_rel_a_reset() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* Clear the queue, it might still contain stuff like IMMEDIATE ASSIGN */
- IPA_RSL[0].clear;
+ IPA_RSL[0][0].clear;
/* perform BSSAP RESET, expect RESET ACK and DISC.ind on connection */
- BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled)));
+ BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
interleave {
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled))) { }
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
[] BSSAP.receive(tr_BSSAP_DISC_ind(dt.sccp_conn_id, ?, ?)) { }
}
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
}
/* Verify T(iar) triggers and releases the channel */
@@ -1605,9 +2421,39 @@ testcase TC_chan_rel_sccp_tiar_timeout() runs on test_CT {
f_init(1);
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
- f_expect_chan_rel(0, dt.rsl_chan_nr, expect_rll_rel_req := false);
- setverdict(pass);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+ f_shutdown_helper();
+}
+
+private function f_tc_chan_rel_rr_cause(myBSSMAP_Cause clear_cmd_cause,
+ template (present) RR_Cause expect_rr_cause)
+runs on test_CT
+{
+ var DchanTuple dt;
+
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(clear_cmd_cause))));
+ BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ }
+
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_rr_cause := expect_rr_cause);
+}
+
+/* Test that Clear Command cause codes affect the RR Channel Release cause code */
+testcase TC_chan_rel_rr_cause() runs on test_CT {
+ f_init(1);
+
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_CALL_CONTROL, GSM48_RR_CAUSE_NORMAL);
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_HANDOVER_SUCCESSFUL, GSM48_RR_CAUSE_NORMAL);
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_PREEMPTION, GSM48_RR_CAUSE_PREMPTIVE_REL);
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
+ f_tc_chan_rel_rr_cause(GSM0808_CAUSE_EQUIPMENT_FAILURE, GSM48_RR_CAUSE_ABNORMAL_UNSPEC);
+
+ f_shutdown_helper();
}
/* Test behavior if RSL EST IND for non-active channel */
@@ -1616,46 +2462,47 @@ testcase TC_rll_est_ind_inact_lchan() runs on test_CT {
f_init(1);
- var octetstring l3 := '00010203040506'O;
var RslChannelNr chan_nr := valueof(t_RslChanNr_Bm(6));
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
+ var octetstring l3_payload := gen_l3_valid_payload();
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
T.start;
alt {
- [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
setverdict(fail, "MSC received COMPL L3 for non-active lchan");
}
[] BSSAP.receive {}
- [] IPA_RSL[0].receive {}
+ [] IPA_RSL[0][0].receive {}
[] T.timeout {}
}
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior if RSL EST IND for invalid SAPI */
testcase TC_rll_est_ind_inval_sapi1() runs on test_CT {
var RslChannelNr chan_nr;
+ var octetstring l3_payload;
f_init(1);
- chan_nr := f_chreq_act_ack()
+ chan_nr := f_chreq_act_ack();
+ l3_payload := gen_l3_valid_payload();
- var octetstring l3 := '00010203040506'O;
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3));
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(1)), l3_payload));
timer T := 2.0;
T.start;
alt {
- [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
setverdict(fail, "MSC received COMPL L3 for invalid SAPI 1");
}
[] BSSAP.receive { repeat; }
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[0][0].receive { repeat; }
[] T.timeout {}
}
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior if RSL EST IND for invalid SAPI */
@@ -1665,21 +2512,21 @@ testcase TC_rll_est_ind_inval_sapi3() runs on test_CT {
f_init(1);
var RslChannelNr chan_nr := f_chreq_act_ack();
+ var octetstring l3_payload := gen_l3_valid_payload();
- var octetstring l3 := '00010203040506'O;
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3));
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(3)), l3_payload));
T.start;
alt {
- [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
setverdict(fail, "MSC received COMPL L3 for invalid SAPI 3");
}
[] BSSAP.receive { repeat; }
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[0][0].receive { repeat; }
[] T.timeout {}
}
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test behavior if RSL EST IND for invalid SACCH */
@@ -1689,26 +2536,228 @@ testcase TC_rll_est_ind_inval_sacch() runs on test_CT {
f_init(1);
var RslChannelNr chan_nr := f_chreq_act_ack();
+ var octetstring l3_payload := gen_l3_valid_payload();
- var octetstring l3 := '00010203040506'O;
- f_ipa_tx(0, ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3));
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_SACCH(0)), l3_payload));
T.start;
alt {
- [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3))) {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) {
setverdict(fail, "MSC received COMPL L3 for invalid Link SACCH");
}
[] BSSAP.receive { repeat; }
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[0][0].receive { repeat; }
[] T.timeout {}
}
- setverdict(pass);
+ f_shutdown_helper();
+}
+
+/* Verify DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
+private function f_TC_tch_dlci_link_id_sapi(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ /* SAPI0 has already been established by f_establish_fully(), establish SAPI3 */
+ RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_SACCH(3), '0904'O));
+ /* Expect BSSAP/DTAP on SAPI3 (DLCI IE) */
+ BSSAP.receive(PDU_BSSAP:{
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := 'C3'O,
+ lengthIndicator := ?,
+ pdu := { dtap := '0904'O }
+ });
+
+ /* Send messages on DCCH/SAPI0 and ACCH/SAPI3 */
+ for (var integer i := 0; i < 32; i := i + 1) {
+ var octetstring l3 := '09'O & f_rnd_octstring(14);
+ var template (value) RslLinkId link_id;
+ var template (value) OCT1 dlci;
+
+ if (i mod 2 == 0) {
+ /* SAPI0 on FACCH or SDCCH */
+ link_id := ts_RslLinkID_DCCH(0);
+ dlci := '80'O;
+ } else {
+ /* SAPI3 on SACCH */
+ link_id := ts_RslLinkID_SACCH(3);
+ dlci := 'C3'O;
+ }
+
+ /* Send MO message: RSL -> BSSAP */
+ f_mo_l3_transceive(RSL, link_id, dlci, l3);
+ /* Send MT message: BSSAP -> RSL */
+ f_mt_l3_transceive(RSL, link_id, dlci, l3);
+ }
+ f_perform_clear();
+}
+testcase TC_tch_dlci_link_id_sapi() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ vc_conn := f_start_handler(refers(f_TC_tch_dlci_link_id_sapi), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+private function f_exp_sapi_n_reject(template (present) GsmSapi sapi := ?,
+ template (present) myBSSMAP_Cause cause := ?,
+ template (present) BIT2 cc := ?,
+ float T_val := 2.0)
+runs on test_CT {
+ var BSSAP_N_DATA_ind rx_di;
+ timer T;
+
+ var template (present) BSSMAP_IE_Cause tr_cause := tr_BSSMAP_IE_Cause(cause);
+ var template (present) PDU_BSSAP tr_pdu := tr_BSSMAP_SAPInReject(sapi);
+
+ T.start(T_val);
+ alt {
+ [] BSSAP.receive(tr_BSSAP_DATA_ind(?, tr_pdu)) -> value rx_di {
+ var BSSMAP_IE_Cause rx_cause := rx_di.userData.pdu.bssmap.sAPInReject.cause;
+ if (not match(rx_cause, tr_cause)) {
+ setverdict(fail, "Rx unexpected Cause IE: ",
+ rx_cause, " vs expected ", tr_cause);
+ }
+
+ /* Who ever on the earth decided to define this field as two separate bits?!? */
+ var BIT2 rx_cc := rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c2
+ & rx_di.userData.pdu.bssmap.sAPInReject.dLCI.c1;
+ if (not match(rx_cc, cc)) {
+ setverdict(fail, "Rx unexpected Control Channel type: ",
+ rx_cc, " vs expected ", cc);
+ }
+
+ setverdict(pass);
+ }
+ [] BSSAP.receive(BSSAP_N_DATA_ind:?) -> value rx_di {
+ setverdict(fail, "Rx unexpected BSSAP PDU: ", rx_di);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for BSSMAP SAPI N Reject");
+ }
+ }
+}
+
+/* Check if we get SAPI N Reject on receipt of unexpected RLL RELease INDication */
+testcase TC_rll_rel_ind_sapi_n_reject() runs on test_CT {
+ var RSL_Message rx_rsl;
+ var DchanTuple dt;
+
+ f_init(1);
+
+ /* MS establishes a SAPI=0 link on DCCH */
+ dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+
+ /* MSC sends some data on (not yet established) SAPI=3 link */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
+ /* BSC attempts to establish a SAPI=3 link on DCCH */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
+
+ /* MS sends unexpected RELease INDication on SAPI=3 */
+ f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3)));
+ /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
+ f_exp_sapi_n_reject(3, GSM0808_CAUSE_MS_NOT_EQUIPPED);
+
+ /* Clean up the connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+
+ f_shutdown_helper();
+}
+
+/* Check if we get SAPI N Reject on receipt of unexpected RLL ERROR INDication */
+testcase TC_rll_err_ind_sapi_n_reject() runs on test_CT {
+ var RSL_Message rx_rsl;
+ var DchanTuple dt;
+
+ f_init(1);
+
+ /* MS establishes a SAPI=0 link on DCCH */
+ dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+
+ /* MSC sends some data on (not yet established) SAPI=3 link */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
+ /* BSC attempts to establish a SAPI=3 link on DCCH */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
+
+ /* BTS sends unexpected ERROR INDication on SAPI=3 */
+ f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
+ /* We expect to receive BSSMAP SAPI N Reject message from the BSC */
+ f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
+
+ /* Clean up the connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+
+ f_shutdown_helper();
+}
+
+/* Check if we get SAPI N Reject due to a SAPI=3 link establishment timeout */
+testcase TC_rll_timeout_sapi_n_reject() runs on test_CT {
+ var RSL_Message rx_rsl;
+ var DchanTuple dt;
+
+ f_init(1);
+
+ /* MS establishes a SAPI=0 link on DCCH */
+ dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+
+ /* MSC sends some data on (not yet established) SAPI=3 link */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
+ /* BSC attempts to establish a SAPI=3 link on DCCH */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
+
+ /* MS does not respond, so the link establishment timeout triggers SAPI N Reject */
+ f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, T_val := 8.0);
+
+ /* Clean up the connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+
+ f_shutdown_helper();
+}
+
+/* Check DLCI CC (Control Channel type) bits in SAPI N Reject */
+testcase TC_rll_sapi_n_reject_dlci_cc() runs on test_CT {
+ var RSL_Message rx_rsl;
+ var DchanTuple dt;
+
+ f_init(1);
+
+ /* MS establishes a SAPI=0 link on DCCH */
+ dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+
+ /* MSC sends some data on (not yet established) SAPI=3 link */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSAP_DTAP(gen_l3_valid_payload(), '03'O)));
+ /* BSC attempts to establish a SAPI=3 link on DCCH */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_EST_REQ(dt.rsl_chan_nr, tr_RslLinkID_DCCH(3)));
+
+ /* MS sends unexpected ERROR INDication on DCCH/ACCH SAPI=3 */
+ f_ipa_tx(ts_RSL_ERROR_IND(dt.rsl_chan_nr, ts_RslLinkID_DCCH(3), ''O));
+ f_exp_sapi_n_reject(3, GSM0808_CAUSE_BSS_NOT_EQUIPPED, '10'B);
+
+ /* Clean up the connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false);
+
+ f_shutdown_helper();
}
testcase TC_si_default() runs on test_CT {
f_init(0);
f_init_bts_and_check_sysinfo(0, expect_si := SystemInformationConfig_default);
+ f_shutdown_helper();
}
/* We're testing SI2quater with lists of EARFCNs. Instead of just incrementing EARFCNs, also pick some from the edges of
@@ -1735,7 +2784,8 @@ private function f_test_si2quater_earfcn_by_idx(integer earfcn_index) return uin
}
}
-function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si) runs on test_CT {
+function f_test_si2quater(integer total_earfcns, template SystemInformationConfig expect_si,
+ template CellSelIndValue expect_cells := omit) runs on test_CT {
f_init(0);
@@ -1747,6 +2797,30 @@ function f_test_si2quater(integer total_earfcns, template SystemInformationConfi
f_init_bts_and_check_sysinfo(0, expect_si := expect_si);
+ if (not istemplatekind(expect_cells, "omit")) {
+ /* Also check that RR Channel Release contains these EARFCNs.
+ * (copied code from TC_chan_rel_hard_clear_csfb) */
+ var BSSAP_N_DATA_ind rx_di;
+ var DchanTuple dt;
+
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
+ /* Send CommonID with some random PLMN (BSC doesn't take it into account
+ * yet when generating the EUTRAN neigh list in RR CHannel Release) */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_CommonId('001019876543210'H, '323454'O)));
+
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommandCSFB(cause)));
+
+ /* expect Clear Complete from BSC on A */
+ BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearComplete)) {
+ /* release the SCCP connection */
+ BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
+ }
+
+ f_expect_chan_rel(dt.rsl_chan_nr, expect_rll_rel_req := false, expect_cells := expect_cells);
+ }
+
for (var integer i := 1; i < total_earfcns; i := i + 1) {
f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
}
@@ -1770,55 +2844,80 @@ private function f_tr_si2quater_earfcns(integer count) return template SI2quater
return si2quater;
}
+private function f_tr_rr_chan_rel_earfcns(integer count) return template CellSelIndValue
+{
+ var template CellSelIndValue_EUTRAN_Descrs cells := {};
+
+ /* the lte neighbors must match the config & vty to pass this test */
+ for (var integer i := 0; i < count; i := i + 1) {
+ var integer earfcn := f_test_si2quater_earfcn_by_idx(i);
+ cells[i] := tr_CellSelIndValue_EUTRAN_Descr(earfcn, '1'B, 3);
+ }
+
+ return tr_CellSelIndValue_EUTRAN(cells);
+}
+
private function f_tc_si2quater_n_earfcns(integer n) runs on test_CT
{
var template SystemInformationConfig sic := SystemInformationConfig_default;
- sic.si2quater := f_tr_si2quater_earfcns(n);
- f_test_si2quater(n, sic);
+ sic.si2quater := f_tr_si2quater_earfcns(n);
+ var template CellSelIndValue cells := f_tr_rr_chan_rel_earfcns(n);
+ f_test_si2quater(n, sic, cells);
}
testcase TC_si2quater_2_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(2);
+ f_shutdown_helper();
}
testcase TC_si2quater_3_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(3);
+ f_shutdown_helper();
}
testcase TC_si2quater_4_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(4);
+ f_shutdown_helper();
}
testcase TC_si2quater_5_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(5);
+ f_shutdown_helper();
}
testcase TC_si2quater_6_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(6);
+ f_shutdown_helper();
}
testcase TC_si2quater_12_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(12);
+ f_shutdown_helper();
}
testcase TC_si2quater_23_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(23);
+ f_shutdown_helper();
}
testcase TC_si2quater_32_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(32);
+ f_shutdown_helper();
}
testcase TC_si2quater_33_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(33);
+ f_shutdown_helper();
}
testcase TC_si2quater_42_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(42);
+ f_shutdown_helper();
}
testcase TC_si2quater_48_earfcns() runs on test_CT {
f_tc_si2quater_n_earfcns(48);
+ f_shutdown_helper();
}
/* verify the VTY error response when adding too many EARFCNs, and showing that osmo-bsc still sends 16 SI2quater with
@@ -1852,6 +2951,7 @@ testcase TC_si2quater_49_earfcns() runs on test_CT {
for (var integer i := 1; i < 48; i := i + 1) {
f_bts_0_cfg(BSCVTY, {"si2quater neighbor-list del earfcn " & int2str(f_test_si2quater_earfcn_by_idx(i))});
}
+ f_shutdown_helper();
}
private function f_acc09_count_allowed(AccessControlClass acc) return uint8_t
@@ -1873,11 +2973,10 @@ private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return Sy
timer T := 30.0;
T.start;
alt {
- [] IPA_RSL[rsl_idx].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
- tr_RSL_BCCH_INFO,
- tr_RSL_NO_SACCH_FILL,
- tr_RSL_SACCH_FILL))
- ) -> value rx_rsl_ud {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD((tr_RSL_NO_BCCH_INFO,
+ tr_RSL_BCCH_INFO,
+ tr_RSL_NO_SACCH_FILL,
+ tr_RSL_SACCH_FILL))) -> value rx_rsl_ud {
f_sysinfo_seen(rsl_idx, rx_rsl_ud.rsl);
if (g_system_information[rsl_idx].si1 == omit) {
repeat;
@@ -1886,6 +2985,7 @@ private function f_recv_next_si1(integer rsl_idx := 0) runs on test_CT return Sy
g_system_information[rsl_idx].si1 := omit;
T.stop;
}
+ [] IPA_RSL[rsl_idx][0].receive { repeat; }
[] T.timeout { setverdict(fail, "Timeout receiving next SI1"); }
}
return last_si1;
@@ -1938,6 +3038,7 @@ testcase TC_si_acc_rotate() runs on test_CT {
f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
"rach access-control-class 5 allowed"});
+ f_shutdown_helper();
}
/* verify ACC startup ramp+rotate feature */
@@ -1998,6 +3099,57 @@ testcase TC_si_acc_ramp_rotate() runs on test_CT {
f_bts_0_cfg(BSCVTY, {"access-control-class-rotate 10",
"rach access-control-class 4 allowed",
"no access-control-class-ramping"});
+ f_shutdown_helper();
+}
+
+/* Verify NCC Permitted in System Information Type 2
+ * 3GPP TS 44.018 § 10.5.2.27 */
+testcase TC_si2_ncc_permitted() runs on test_CT {
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ timer T := 5.0;
+ var BIT8 exp;
+
+ f_init_vty();
+
+ /* Set NCC Permitted to 6 7 8 */
+ f_vty_enter_cfg_bts(BSCVTY, 0);
+ f_vty_transceive(BSCVTY, "ncc-permitted 6 7 8");
+ f_vty_transceive(BSCVTY, "end");
+ exp := '11100000'B;
+
+ f_init(1);
+ T.start;
+
+ /* Check value in SI 2 */
+ alt {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_2))) -> value rx_rsl_ud {
+ var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
+ var SystemInformation si := dec_SystemInformation(ie.other.payload);
+
+ if (si.header.message_type != SYSTEM_INFORMATION_TYPE_2) {
+ setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
+ repeat;
+ }
+
+ if (si.payload.si2.ncc_permitted != exp) {
+ setverdict(fail, "NCC Permitted is ", si.payload.si2.ncc_permitted, " but expected ", exp);
+ break;
+ }
+
+ }
+ [] IPA_RSL[0][0].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI2)");
+ }
+ }
+
+ /* Reset NCC Permitted to default (all permitted). This is already
+ * getting tested in TC_si_default(). */
+ f_vty_enter_cfg_bts(BSCVTY, 0);
+ f_vty_transceive(BSCVTY, "ncc-permitted all");
+ f_vty_transceive(BSCVTY, "end");
+
+ f_shutdown_helper();
}
testcase TC_ctrl_msc_connection_status() runs on test_CT {
@@ -2007,7 +3159,7 @@ testcase TC_ctrl_msc_connection_status() runs on test_CT {
/* See https://osmocom.org/issues/2729 */
f_ctrl_get_exp(IPA_CTRL, "msc_connection_status", "connected");
- setverdict(pass);
+ f_shutdown_helper();
}
testcase TC_ctrl_msc0_connection_status() runs on test_CT {
@@ -2016,7 +3168,163 @@ testcase TC_ctrl_msc0_connection_status() runs on test_CT {
f_init(1);
f_ctrl_get_exp(IPA_CTRL, "msc.0.connection_status", "connected");
- setverdict(pass);
+ f_shutdown_helper();
+}
+
+/* Verify correct stats on the number of configured and connected MSCs */
+private function f_tc_stat_num_msc_connected_msc_connhdlr(integer expect_num_msc_connected) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ var StatsDExpects expect := {
+ { name := "TTCN3.bsc.0.num_msc.connected", mtype := "g", min := expect_num_msc_connected, max := expect_num_msc_connected },
+ { name := "TTCN3.bsc.0.num_msc.total", mtype := "g", min := NUM_MSC, max := NUM_MSC }
+ };
+ f_statsd_expect(expect);
+}
+
+private function f_tc_stat_num_msc_connected_test_ct(void_fn tc_fn, integer nr_msc) runs on test_CT
+{
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(nr_bts := 1, handler_mode := true, nr_msc := nr_msc);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(tc_fn);
+ vc_conn.done;
+
+ /* Also verify stat exposed on CTRL interface */
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:connected", int2str(nr_msc));
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_msc:total", int2str(NUM_MSC));
+
+ f_shutdown_helper();
+}
+
+/* Verify that when 1 MSC is active, that num_msc:connected reports 1. */
+private function f_tc_stat_num_msc_connected_1(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_msc_connected_msc_connhdlr(1);
+}
+testcase TC_stat_num_msc_connected_1() runs on test_CT {
+ f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_1), 1);
+}
+
+/* Verify that when 2 MSCs are active, that num_msc:connected reports 2. */
+private function f_tc_stat_num_msc_connected_2(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_msc_connected_msc_connhdlr(2);
+}
+testcase TC_stat_num_msc_connected_2() runs on test_CT {
+ f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_2), 2);
+}
+
+/* Verify that when 3 MSCs are active, that num_msc:connected reports 3. */
+private function f_tc_stat_num_msc_connected_3(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_msc_connected_msc_connhdlr(3);
+}
+testcase TC_stat_num_msc_connected_3() runs on test_CT {
+ f_tc_stat_num_msc_connected_test_ct(refers(f_tc_stat_num_msc_connected_3), 3);
+}
+
+/* Verify correct stats on the number of configured and connected MSCs */
+private function f_tc_stat_num_bts_connected_msc_connhdlr(integer expect_num_bts_connected) runs on MSC_ConnHdlr {
+ var integer num_trx_connected := 0;
+ var integer num_trx_total := 0;
+
+ for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
+ var integer trx_num := c_BtsParams[i].trx_num;
+ num_trx_total := num_trx_total + trx_num;
+ if (i < expect_num_bts_connected) {
+ num_trx_connected := num_trx_connected + trx_num;
+ }
+ }
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bsc.0.num_bts.oml_connected", mtype := "g", min := expect_num_bts_connected, max := NUM_BTS_CFG },
+ { name := "TTCN3.bsc.0.num_bts.all_trx_rsl_connected", mtype := "g", min := expect_num_bts_connected, max := expect_num_bts_connected },
+ { name := "TTCN3.bsc.0.num_bts.total", mtype := "g", min := NUM_BTS_CFG, max := NUM_BTS_CFG },
+ { name := "TTCN3.bsc.0.num_trx.rsl_connected", mtype := "g", min := num_trx_connected, max := num_trx_connected },
+ { name := "TTCN3.bsc.0.num_trx.total", mtype := "g", min := num_trx_total, max := num_trx_total }
+ };
+
+ g_pars := f_gen_test_hdlr_pars();
+ f_statsd_expect(expect);
+}
+
+private function f_tc_stat_num_bts_connected_test_ct(void_fn tc_fn, integer nr_bts) runs on test_CT {
+ var integer num_trx_connected := 0;
+ var integer num_trx_total := 0;
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(nr_bts := nr_bts, handler_mode := true, nr_msc := 1);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(tc_fn);
+ vc_conn.done;
+
+ for (var integer i := 0; i < lengthof(c_BtsParams); i := i + 1) {
+ var integer trx_num := c_BtsParams[i].trx_num;
+ num_trx_total := num_trx_total + trx_num;
+ if (i < nr_bts) {
+ num_trx_connected := num_trx_connected + trx_num;
+ }
+ }
+
+ /* Also verify stat exposed on CTRL interface */
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:all_trx_rsl_connected", int2str(nr_bts));
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_bts:total", int2str(NUM_BTS_CFG));
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:rsl_connected", int2str(num_trx_connected));
+ f_ctrl_get_exp(IPA_CTRL, "stat_item.last.bsc.0.num_trx:total", int2str(num_trx_total));
+
+ /* Verify rf_states exposed on CTRL interface */
+ var charstring expect_net_rf_states := "";
+ for (var integer i := 0; i < NUM_BTS_CFG; i := i + 1) {
+ var charstring expect_bts_rf_states := "";
+
+ for (var integer j := 0; j < c_BtsParams[i].trx_num; j := j + 1) {
+ expect_bts_rf_states := expect_bts_rf_states &
+ int2str(i) & "," & int2str(j) & ",";
+ if (i < NUM_BTS) {
+ /* In these tests, OML for the first NUM_BTS are always connected via osmo-bts-omldummy */
+ expect_bts_rf_states := expect_bts_rf_states & "operational,unlocked,";
+ } else {
+ /* For remaining i < NUM_BTS_CFG, OML is not connected, i.e. inoperational */
+ expect_bts_rf_states := expect_bts_rf_states & "inoperational,locked,";
+ }
+ /* The RF policy is still global in osmo-bsc, i.e. always "on" */
+ expect_bts_rf_states := expect_bts_rf_states & "on,";
+ if (i < nr_bts) {
+ /* For BTS where RSL is connected, the RSL state will be "up" */
+ expect_bts_rf_states := expect_bts_rf_states & "rsl-up;";
+ } else {
+ expect_bts_rf_states := expect_bts_rf_states & "rsl-down;";
+ }
+ }
+
+ f_ctrl_get_exp(IPA_CTRL, "bts." & int2str(i) & ".rf_states", expect_bts_rf_states);
+ expect_net_rf_states := expect_net_rf_states & expect_bts_rf_states;
+ }
+ f_ctrl_get_exp(IPA_CTRL, "rf_states", expect_net_rf_states);
+
+ f_shutdown_helper();
+}
+
+/* Verify that when 1 BTS is connected, that num_{bts,trx}:*_connected reports 1. */
+private function f_tc_stat_num_bts_connected_1(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_bts_connected_msc_connhdlr(1);
+}
+testcase TC_stat_num_bts_connected_1() runs on test_CT {
+ f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_1), 1);
+}
+
+/* Verify that when 2 BTS is connected, that num_{bts,trx}:*_connected reports 2. */
+private function f_tc_stat_num_bts_connected_2(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_bts_connected_msc_connhdlr(2);
+}
+testcase TC_stat_num_bts_connected_2() runs on test_CT {
+ f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_2), 2);
+}
+
+/* Verify that when 3 BTS is connected, that num_{bts,trx}:*_connected reports 3. */
+private function f_tc_stat_num_bts_connected_3(charstring id) runs on MSC_ConnHdlr {
+ f_tc_stat_num_bts_connected_msc_connhdlr(3);
+}
+testcase TC_stat_num_bts_connected_3() runs on test_CT {
+ f_tc_stat_num_bts_connected_test_ct(refers(f_tc_stat_num_bts_connected_3), 3);
}
testcase TC_ctrl() runs on test_CT {
@@ -2048,7 +3356,7 @@ testcase TC_ctrl() runs on test_CT {
f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted", 0);
- setverdict(pass);
+ f_shutdown_helper();
}
/* Verify that Upon receival of SET "location", BSC forwards a TRAP
@@ -2074,7 +3382,7 @@ testcase TC_ctrl_location() runs on test_CT {
/* should match the one from config */
f_ctrl_set(SCCPLITE_IPA_CTRL, "rf_locked", "0");
- setverdict(pass);
+ f_shutdown_helper();
}
@@ -2119,7 +3427,7 @@ private function f_pageing_helper(hexstring imsi,
/* Clear the queue, it might still contain stuff like BCCH FILLING */
for (i := 0; i < NUM_BTS; i := i + 1) {
- IPA_RSL[i].clear;
+ IPA_RSL[i][0].clear;
}
if (isvalue(rsl_chneed)) {
@@ -2139,7 +3447,7 @@ private function f_pageing_helper(hexstring imsi,
}
for (i := 0; i < sizeof(bts_ids); i := i + 1) {
- rx_rsl := f_exp_ipa_rx(bts_ids[i], tr_RSL_PAGING_CMD(mi));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_PAGING_CMD(mi), idx := {bts_ids[i], 0});
/* check channel type, paging group */
if (rx_rsl.ies[1].body.paging_group != paging_group) {
setverdict(fail, "Paging for wrong paging group");
@@ -2158,10 +3466,10 @@ private function f_pageing_helper(hexstring imsi,
}
T.start;
alt {
- [] IPA_RSL[i].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
+ [] IPA_RSL[i][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(mi))) {
setverdict(fail, "Paging on BTS ", i, " which is not part of ", bts_ids);
}
- [] IPA_RSL[i].receive { repeat; }
+ [] IPA_RSL[i][0].receive { repeat; }
[] T.timeout { }
}
}
@@ -2312,6 +3620,51 @@ testcase TC_paging_imsi_nochan_cgi_unknown_cid() runs on test_CT {
f_shutdown_helper();
}
+/* Send paging response containing invalid (wrongly formatted) MobileIdentity IE. */
+testcase TC_paging_imsi_nochan_ci_resp_invalid_mi() runs on test_CT {
+ var template BSSMAP_FIELD_CellIdentificationList cid_list;
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ var DchanTuple dt;
+ var octetstring rr_pag_resp := '06270003535992617965720000'O;
+ /* { 06 27 } is { GSM48_PDISC_RR, GSM48_MT_RR_PAG_RESP }
+ * see 3GPP TS 44.018, table 9.1.25.1
+ * { 00 } or { 01 } is CKSN + Spare Half Octet, not important
+ * { 03 53 59 92 } is Mobile Station Classmark
+ * { 61 79 65 72 00 00 } is the invalid Mobile Identity IE (3GPP TS 24.008, 10.5.1.4),
+ * Length is 0x61 (97 in decimal).
+ */
+
+ cid_list := { cIl_CI := { ts_BSSMAP_CI_CI(cid.ci) } };
+ f_pageing_helper('001010000000008'H, cid_list, { 0 });
+
+ /* Send CHAN RQD and wait for allocation; acknowledge it */
+ dt.rsl_chan_nr := f_chreq_act_ack();
+ dt.idx := {0, 0};
+
+ /* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
+
+ /* Expevct a CR with a matching Paging response on the A-Interface */
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
+ setverdict(pass);
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+ }
+ [] BSSAP.receive {
+ setverdict(fail, "Received unexpected message on A-Interface!");
+ }
+ [] T.timeout {
+ setverdict(fail, "Received nothing on A-Interface!");
+ }
+ }
+
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
/* Verify paging retransmission interval + count */
/* Verify paging stops after channel establishment */
/* Test behavior under paging overload */
@@ -2325,22 +3678,22 @@ testcase TC_paging_imsi_load() runs on test_CT {
f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
/* tell BSC there is no paging space anymore */
- f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
+ f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
f_sleep(0.2);
- IPA_RSL[0].clear;
+ IPA_RSL[0][0].clear;
/* Wait for 4 seconds if any more PAGING CMD are received on RSL. Normally,
* there would be 8 retransmissions during 4 seconds */
T.start;
T_retrans.start;
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
setverdict(fail, "Received PAGING after LOAD_IND(0)");
mtc.stop;
}
[] T_retrans.timeout {
/* re-trnsmit the zero-space LOAD IND to avoid BSC 'auto credit' */
- f_ipa_tx(0, ts_RSL_PAGING_LOAD_IND(0));
+ f_ipa_tx(ts_RSL_PAGING_LOAD_IND(0));
T_retrans.start;
repeat;
}
@@ -2359,6 +3712,7 @@ testcase TC_paging_counter() runs on test_CT {
var integer i;
var integer paging_attempted_bsc;
var integer paging_attempted_bts[NUM_BTS];
+ var integer paging_expired_bsc;
var integer paging_expired_bts[NUM_BTS];
cid_list := valueof(ts_BSSMAP_CIL_noCell);
@@ -2366,6 +3720,7 @@ testcase TC_paging_counter() runs on test_CT {
/* read counters before paging */
paging_attempted_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:attempted");
+ paging_expired_bsc := f_ctrl_get_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired");
for (i := 0; i < NUM_BTS; i := i+1) {
paging_attempted_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:attempted");
paging_expired_bts[i] := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired");
@@ -2382,6 +3737,7 @@ testcase TC_paging_counter() runs on test_CT {
/* assume that 12s later the paging on all BTSs have expired and hence incremented by 1 */
f_sleep(12.0);
+ f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bsc", 0, "paging:expired", paging_expired_bsc+1);
for (i := 0; i < NUM_BTS; i := i+1) {
f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", i, "paging:expired",
paging_expired_bts[i]+1);
@@ -2399,9 +3755,9 @@ testcase TC_paging_imsi_a_reset() runs on test_CT {
f_pageing_helper('001010123456789'H, cid_list, c_BtsId_all);
/* Perform a BSSMAP Reset and wait for ACK */
- BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled)));
+ BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own, ts_BSSMAP_Reset(0, g_osmux_enabled_cn)));
alt {
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled))) { }
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(g_bssap[0].sccp_addr_own, g_bssap[0].sccp_addr_peer, tr_BSSMAP_ResetAck(g_osmux_enabled_cn))) { }
[] BSSAP.receive { repeat; }
}
@@ -2411,21 +3767,21 @@ testcase TC_paging_imsi_a_reset() runs on test_CT {
/* Clear the queue, it might still contain stuff like BCCH FILLING */
for (var integer i := 0; i < sizeof(IPA_RSL); i := i+1) {
- IPA_RSL[i].clear;
+ IPA_RSL[i][0].clear;
}
/* Wait for 3 seconds if any more PAGING CMD are received on RSL */
T.start;
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
setverdict(fail, "Received PAGING after A-RESET");
mtc.stop;
}
- [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
+ [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
setverdict(fail, "Received PAGING after A-RESET");
mtc.stop;
}
- [] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
+ [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?))) {
setverdict(fail, "Received PAGING after A-RESET");
mtc.stop;
}
@@ -2451,21 +3807,24 @@ testcase TC_paging_resp_unsol() runs on test_CT {
var BSSAP_N_CONNECT_ind rx_c_ind;
var DchanTuple dt;
- var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010008880018'H))));
+ var PDU_ML3_MS_NW l3 := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010008880018'H)));
var octetstring rr_pag_resp := enc_PDU_ML3_MS_NW(l3);
/* Send CHAN RQD and wait for allocation; acknowledge it */
dt.rsl_chan_nr := f_chreq_act_ack();
+ dt.idx := {0, 0};
/* Send unsolicited Paging response (no matching Paging CMD stored in BSC) */
- f_ipa_tx(0, ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), enc_PDU_ML3_MS_NW(l3)));
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), rr_pag_resp));
/* Expevct a CR with a matching Paging response on the A-Interface */
T.start;
alt {
- [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) {
+ [] BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(rr_pag_resp))) -> value rx_c_ind {
setverdict(pass);
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
}
[] BSSAP.receive {
setverdict(fail, "Received unexpected message on A-Interface!");
@@ -2475,7 +3834,90 @@ testcase TC_paging_resp_unsol() runs on test_CT {
}
}
- setverdict(pass);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+/* Verify BSC can schedule N paging requests under one minute if BTS buffer is good enough */
+function f_TC_paging_Nreq(integer num_subscribers, boolean send_pag_load_ind) runs on test_CT {
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ var Hexstrings imsis := {};
+ var Booleans rx_paging_done := {};
+ var integer rx_paging_num := 0;
+ var integer i;
+ timer T_rx := 60.0;
+ timer T_load_ind := 1.0;
+
+ for (i := 0; i < num_subscribers; i := i + 1) {
+ imsis := imsis & {f_gen_imsi(i)};
+ rx_paging_done := rx_paging_done & { false };
+ }
+
+ f_init(1, guard_timeout := 100.0);
+
+ /* Clear the queue, it might still contain stuff like BCCH FILLING */
+ IPA_RSL[0][0].clear;
+ if (send_pag_load_ind) {
+ /* Tell there's plenty of space at the BTS (UINT16_MAX): */
+ f_ipa_tx(ts_RSL_PAGING_LOAD_IND(65535));
+ }
+
+ for (i := 0; i < num_subscribers; i := i + 1) {
+ /* Page on LAC-CI of BTS0: */
+ BSSAP.send(ts_BSSAP_UNITDATA_req(g_bssap[0].sccp_addr_peer, g_bssap[0].sccp_addr_own,
+ ts_BSSMAP_Paging(imsis[i], valueof(ts_BSSMAP_CIL_LAC_CI({ts_BSSMAP_CI_LAC_CI(1, 0)})),
+ omit, omit)));
+ }
+
+ T_rx.start;
+ T_load_ind.start;
+ alt {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?), IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
+ var hexstring imsi := rx_rsl_ud.rsl.ies[2].body.ms_identity.mobileIdentityV.oddEvenInd_identity.imsi.digits;
+ var hexstring imsi_suffix := substr(imsi, lengthof(imsi)-6, 6);
+ var charstring imsi_str := hex2str(imsi_suffix);
+ var integer imsi_idx := str2int(imsi_str);
+ if (rx_paging_done[imsi_idx] == false) {
+ rx_paging_done[imsi_idx] := true;
+ rx_paging_num := rx_paging_num + 1;
+ } else {
+ setverdict(fail, "Retrans of ", imsi_str, " happened before Rx initial trans for all reqs. rx_paging_num=", rx_paging_num);
+ mtc.stop;
+ }
+ if (rx_paging_num < num_subscribers) {
+ repeat;
+ }
+ }
+ [] IPA_RSL[0][0].receive { repeat; }
+ [] T_load_ind.timeout {
+ log("[CCH Load Ind timer] received paging requests so far: ", rx_paging_num);
+ if (send_pag_load_ind) {
+ f_ipa_tx(ts_RSL_PAGING_LOAD_IND(40));
+ }
+ T_load_ind.start;
+ repeat;
+ }
+ [] T_rx.timeout {
+ setverdict(fail, "Timeout expecting paging requests, so far ", rx_paging_num);
+ mtc.stop;
+ }
+ }
+
+ /* Drop OML connection to have all paging requests flushed: */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_shutdown_helper();
+}
+/* Verify BSC can schedule 500 paging requests under one minute if BTS buffer is good enough */
+testcase TC_paging_500req() runs on test_CT {
+ f_TC_paging_Nreq(500, true);
+}
+/* Same as TC_paging_500req, but without sending CCCH Load Indication, which
+ * means BTS is always under CCH Load Threshold, aka capable of sending tons of requests.
+ * Since No CCCH Load Ind, BSC uses a conservative estimation of BTS load, which
+ * for current config yields ~8req/sec, so 480req/min maximum. */
+testcase TC_paging_450req_no_paging_load_ind() runs on test_CT {
+ f_TC_paging_Nreq(450, false);
}
/* Test RSL link drop causes counter increment */
@@ -2486,42 +3928,43 @@ testcase TC_rsl_drop_counter() runs on test_CT {
rsl_fail := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail");
- bts[0].rsl.vc_IPA.stop;
+ f_ipa_rsl_stop(bts[0][0].rsl);
f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "rsl_fail", rsl_fail+1);
- setverdict(pass);
+ f_shutdown_helper();
}
/* TODO: Test OML link drop causes counter increment */
/* The body of TC_rsl_unknown_unit_id() and TC_oml_unknown_unit_id() tests. */
function f_ipa_unknown_unit_id(integer mp_bsc_ipa_port) runs on test_CT return boolean {
+ var IPA_Client client;
timer T := 10.0;
- bts[0].rsl.id := "IPA-0-RSL";
- bts[0].rsl.vc_IPA := IPA_Emulation_CT.create(bts[0].rsl.id & "-IPA");
- bts[0].rsl.ccm_pars := c_IPA_default_ccm_pars;
- bts[0].rsl.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
- bts[0].rsl.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
+ client.id := "IPA-BTS0-TRX0-RSL";
+ client.vc_IPA := IPA_Emulation_CT.create(client.id & "-IPA") alive;
+ client.ccm_pars := c_IPA_default_ccm_pars;
+ client.ccm_pars.name := "Osmocom TTCN-3 BTS Simulator";
+ client.ccm_pars.unit_id := "99/0/0"; /* value which is unknown at BTS */
- f_ipa_ctrl_start(mp_bsc_ip, mp_bsc_ctrl_port);
+ f_ipa_ctrl_start_client(mp_bsc_ip, mp_bsc_ctrl_port);
- f_init_mgcp("VirtMSC");
+ f_init_mgcp(0, "VirtMGW");
/* start RSL/OML connection (XXX re-uses RSL port/protocol definitions for OML) */
- map(bts[0].rsl.vc_IPA:IPA_PORT, system:IPA);
- connect(bts[0].rsl.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0]);
- bts[0].rsl.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, bts[0].rsl.ccm_pars));
+ map(client.vc_IPA:IPA_PORT, system:IPA);
+ connect(client.vc_IPA:IPA_RSL_PORT, self:IPA_RSL[0][0]);
+ client.vc_IPA.start(IPA_Emulation.main_client(mp_bsc_ip, mp_bsc_ipa_port, "", 10000, client.ccm_pars));
/* wait for IPA OML link to connect and then disconnect */
T.start;
alt {
- [] IPA_RSL[0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
+ [] IPA_RSL[0][0].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) {
T.stop;
return true;
}
- [] IPA_RSL[0].receive { repeat }
+ [] IPA_RSL[0][0].receive { repeat }
[] T.timeout {
return false;
}
@@ -2536,6 +3979,7 @@ testcase TC_rsl_unknown_unit_id() runs on test_CT {
} else {
setverdict(fail, "Timeout RSL waiting for connection to close");
}
+ f_shutdown_helper();
}
@@ -2546,6 +3990,7 @@ testcase TC_oml_unknown_unit_id() runs on test_CT {
} else {
setverdict(fail, "Timeout OML waiting for connection to close");
}
+ f_shutdown_helper();
}
@@ -2554,44 +3999,65 @@ testcase TC_oml_unknown_unit_id() runs on test_CT {
***********************************************************************/
import from RAN_Emulation all;
+import from BSSAP_LE_Emulation all;
import from RSL_Emulation all;
import from MSC_ConnectionHandler all;
type function void_fn(charstring id) runs on MSC_ConnHdlr;
-/* helper function to create and connect a MSC_ConnHdlr component */
-private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT {
+/* helper function to create and connect a MSC_ConnHdlr component
+ * TODO: allow connecting to TRX1..N, not only TRX0 */
+private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx := 0, integer mgwpool_idx := 0) runs on test_CT {
connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
- connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
- connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
- connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
- if (isvalue(bts[1])) {
- connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
- connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
+ connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
+ connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
+ if (isvalue(bts[1][0])) {
+ connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
+ connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
}
- if (isvalue(bts[2])) {
- connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT);
- connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
+ if (isvalue(bts[2][0])) {
+ connect(vc_conn:RSL2, bts[2][0].rsl.vc_RSL:CLIENT_PT);
+ connect(vc_conn:RSL2_PROC, bts[2][0].rsl.vc_RSL:RSL_PROC);
}
connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
- connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
- connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI);
+ if (mp_enable_lcs_tests) {
+ connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
+ connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC);
+ }
+ connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
+ connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
+ connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
+ connect(vc_conn:MGCP_MULTI, vc_MGCP[mgwpool_idx]:MGCP_CLIENT_MULTI);
}
-function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
+function f_start_handler_create(template (omit) TestHdlrParams pars := omit)
runs on test_CT return MSC_ConnHdlr {
var charstring id := testcasename();
var MSC_ConnHdlr vc_conn;
var integer bssap_idx := 0;
+ var integer mgwpool_idx := 0;
if (isvalue(pars)) {
- bssap_idx := valueof(pars).mscpool.bssap_idx;
+ var TestHdlrParams pars_val := valueof(pars);
+ bssap_idx := pars_val.mscpool.bssap_idx;
+ mgwpool_idx := pars_val.mgwpool_idx;
}
vc_conn := MSC_ConnHdlr.create(id);
- f_connect_handler(vc_conn, bssap_idx);
+ f_connect_handler(vc_conn, bssap_idx, mgwpool_idx);
+ return vc_conn;
+}
+
+function f_start_handler_run(MSC_ConnHdlr vc_conn, void_fn fn, template (omit) TestHdlrParams pars := omit)
+runs on test_CT return MSC_ConnHdlr {
+ var charstring id := testcasename();
vc_conn.start(f_handler_init(fn, id, pars));
return vc_conn;
}
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
+runs on test_CT return MSC_ConnHdlr {
+ return f_start_handler_run(f_start_handler_create(pars), fn, pars);
+}
+
/* first function inside ConnHdlr component; sets g_pars + starts function */
private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
runs on MSC_ConnHdlr {
@@ -2601,6 +4067,21 @@ runs on MSC_ConnHdlr {
fn.apply(id);
}
+private function f_vty_encryption_a5(charstring options) runs on test_CT {
+ f_vty_transceive(BSCVTY, "configure terminal");
+ f_vty_transceive(BSCVTY, "network");
+ f_vty_transceive(BSCVTY, "encryption a5 " & options);
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+}
+
+const charstring VTY_A5_DEFAULT := "0 1 3";
+
+private function f_vty_encryption_a5_reset() runs on test_CT {
+ /* keep in sync with docker-playground.git ttcn3-bsc-test/osmo-bsc.cfg */
+ f_vty_encryption_a5(VTY_A5_DEFAULT);
+}
+
/* Establish signalling channel (non-assignment case) followed by cipher mode */
private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
@@ -2612,6 +4093,7 @@ private function f_tc_ciph_mode_a5(charstring id) runs on MSC_ConnHdlr {
exp_compl.pdu.bssmap.assignmentComplete.aoIPTransportLayer := omit;
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
testcase TC_ciph_mode_a5_0() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2622,6 +4104,7 @@ testcase TC_ciph_mode_a5_0() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
}
testcase TC_ciph_mode_a5_1() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2632,6 +4115,37 @@ testcase TC_ciph_mode_a5_1() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
+}
+/* OS#4975: verify that A5/2 is preferred over A5/0 */
+testcase TC_ciph_mode_a5_2_0() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.encr := f_encr_params('05'O, '04'O); /* A5/0 and A5/2 (0x01|0x04)*/
+
+ f_init(1, true);
+ f_vty_encryption_a5("0 1 2 3");
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
+ vc_conn.done;
+ f_vty_encryption_a5_reset();
+ f_shutdown_helper();
+}
+/* OS#4975: verify that A5/1 is preferred over A5/2 */
+testcase TC_ciph_mode_a5_2_1() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.encr := f_encr_params('06'O, '02'O); /* A5/1 and A5/2 (0x02|0x04)*/
+
+ f_init(1, true);
+ f_vty_encryption_a5("1 2");
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
+ vc_conn.done;
+ f_vty_encryption_a5_reset();
+ f_shutdown_helper();
}
testcase TC_ciph_mode_a5_3() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2642,6 +4156,41 @@ testcase TC_ciph_mode_a5_3() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
+}
+/* Establish a Signalling channel with A5/4 encryption. */
+testcase TC_ciph_mode_a5_4() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
+
+ f_init(1, true);
+ f_vty_encryption_a5("0 1 3 4");
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_ciph_mode_a5), pars);
+ vc_conn.done;
+ f_vty_encryption_a5_reset();
+ f_shutdown_helper();
+}
+/* establish initial channel, enable ciphering followed by assignment to ciphered channel */
+private function f_tc_assignment_aoip_tla_v6(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(aoip_tla := "::3");
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
+}
+testcase TC_assignment_aoip_tla_v6() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_assignment_aoip_tla_v6), pars);
+ vc_conn.done;
+ f_shutdown_helper();
}
@@ -2654,6 +4203,7 @@ private function f_tc_assignment_fr_a5(charstring id) runs on MSC_ConnHdlr {
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
testcase TC_assignment_fr_a5_0() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2664,6 +4214,7 @@ testcase TC_assignment_fr_a5_0() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
}
testcase TC_assignment_fr_a5_1() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2674,6 +4225,7 @@ testcase TC_assignment_fr_a5_1() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
}
testcase TC_assignment_fr_a5_3() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2684,6 +4236,35 @@ testcase TC_assignment_fr_a5_3() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
+}
+/* Establish a Signalling channel and re-assign to TCH/F with A5/4 encryption. */
+testcase TC_assignment_fr_a5_4() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8), f_rnd_octstring(16)));
+
+ f_init(1, true);
+ f_vty_encryption_a5("0 1 3 4");
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
+ vc_conn.done;
+ f_vty_encryption_a5_reset();
+ f_shutdown_helper();
+}
+
+/* Allow only A5/4, but omit the Kc128 IE from MSC's msg. Expect Cipher Mode Reject. */
+testcase TC_assignment_fr_a5_4_fail() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.encr := valueof(t_EncrParams('10'O, f_rnd_octstring(8))); // A5/4 support, but Kc128 missing!
+ vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
+ vc_conn.done;
+ f_shutdown_helper();
}
/* Expect ASSIGNMENT FAIL if mandatory IE is missing */
@@ -2691,12 +4272,12 @@ private function f_tc_assignment_fr_a5_1_codec_missing(charstring id) runs on MS
g_pars := f_gen_test_hdlr_pars();
var template PDU_BSSAP exp_fail := tr_BSSMAP_AssignmentFail;
var PDU_BSSAP ass_cmd := f_gen_ass_req();
- const OCT8 kc := '0001020304050607'O;
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
/* Omit: ass_cmd.pdu.bssmap.assignmentRequest.codecList */
f_establish_fully(ass_cmd, exp_fail);
+ f_perform_clear();
}
testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -2706,29 +4287,41 @@ testcase TC_assignment_fr_a5_1_codec_missing() runs on test_CT {
vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_1_codec_missing));
vc_conn.done;
+ f_shutdown_helper();
}
-private function f_tc_assignment_fr_a5_4(charstring id) runs on MSC_ConnHdlr {
- g_pars := f_gen_test_hdlr_pars();
- var template PDU_BSSAP exp_compl := f_gen_exp_compl();
- var PDU_BSSAP ass_cmd := f_gen_ass_req();
- const OCT8 kc := '0001020304050607'O;
- const OCT16 kc128 := kc & kc;
+private function f_TC_assignment_a5_not_sup(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_ass_cpl := f_gen_exp_compl();
+ var PDU_BSSAP exp_ass_req := f_gen_ass_req();
- ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
- ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
- f_establish_fully(ass_cmd, exp_compl);
- f_cipher_mode('10'O, kc, kc128, true);
- /* TODO: expect GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED cause value */
+ exp_ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ exp_ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ /* this is like the beginning of f_establish_fully(), but only up to ciphering reject */
+
+ var BSSMAP_FIELD_CodecType codecType;
+
+ codecType := exp_ass_req.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType;
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
+
+ f_create_chan_and_exp();
+ /* we should now have a COMPL_L3 at the MSC */
+
+ /* Start ciphering, expect Cipher Mode Reject */
+ f_cipher_mode(g_pars.encr, exp_fail := true);
+ f_perform_clear();
}
-testcase TC_assignment_fr_a5_4() runs on test_CT {
+testcase TC_assignment_fr_a5_not_sup() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
var MSC_ConnHdlr vc_conn;
f_init(1, true);
f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5_4));
+ pars.encr := valueof(t_EncrParams('20'O, f_rnd_octstring(8), f_rnd_octstring(16)));
+ vc_conn := f_start_handler(refers(f_TC_assignment_a5_not_sup), pars);
vc_conn.done;
+ f_shutdown_helper();
}
@@ -2737,7 +4330,18 @@ private function f_tc_assignment_sign(charstring id) runs on MSC_ConnHdlr {
var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, omit);
var PDU_BSSAP ass_cmd := f_gen_ass_req();
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelTypeSIGNAL);
+
+ f_statsd_reset();
f_establish_fully(ass_cmd, exp_compl);
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.chreq.total", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.chreq.successful", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bsc.0.assignment.attempted", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bsc.0.assignment.completed", mtype := "c", min := 1, max := 1}
+ };
+ f_statsd_expect(expect);
+ f_perform_clear();
}
testcase TC_assignment_sign() runs on test_CT {
@@ -2748,6 +4352,7 @@ testcase TC_assignment_sign() runs on test_CT {
vc_conn := f_start_handler(refers(f_tc_assignment_sign));
vc_conn.done;
+ f_shutdown_helper();
}
/***********************************************************************
@@ -2843,30 +4448,30 @@ return template RSL_IE_Body {
dtx_u := ?,
spd_ind := RSL_SPDI_SPEECH,
ch_rate_type := -,
- coding_alg_rate := -
+ u := { speech := - }
}
}
select (a_elem.codecType) {
case (GSM_FR) {
mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
- mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
+ mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
}
case (GSM_HR) {
mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
- mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM1;
+ mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
}
case (GSM_EFR) {
mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
- mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM2;
+ mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM2;
}
case (FR_AMR) {
mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_F;
- mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
+ mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
}
case (HR_AMR) {
mode_ie.chan_mode.ch_rate_type := RSL_CHRT_TCH_H;
- mode_ie.chan_mode.coding_alg_rate := RSL_CMOD_SP_GSM3;
+ mode_ie.chan_mode.u.speech := RSL_CMOD_SP_GSM3;
}
}
return mode_ie;
@@ -2879,8 +4484,12 @@ type record CodecListTest {
type record of CodecListTest CodecListTests
private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
- var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
- var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
+ f_assignment_codec(id);
+}
+
+private function f_assignment_codec(charstring id, boolean do_perform_clear := true) runs on MSC_ConnHdlr {
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
/* puzzle together the ASSIGNMENT REQ for given codec[s] */
if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
@@ -2898,38 +4507,45 @@ private function f_TC_assignment_codec(charstring id) runs on MSC_ConnHdlr {
f_establish_fully(ass_cmd, exp_compl);
- /* Verify that the RSL-side activation actually matches our expectations */
- var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
-
- var RSL_IE_Body mode_ie;
- if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
- setverdict(fail, "Couldn't find CHAN_MODE IE");
- mtc.stop;
- }
- var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
- if (not match(mode_ie, t_mode_ie)) {
- setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
- }
+ if (not g_pars.expect_channel_mode_modify) {
+ /* Verify that the RSL-side activation actually matches our expectations */
+ var RSL_Message rsl := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
- var RSL_IE_Body mr_conf;
- if (g_pars.expect_mr_conf_ie != omit) {
- if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
- setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
+ var RSL_IE_Body mode_ie;
+ if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, mode_ie) == false) {
+ setverdict(fail, "Couldn't find CHAN_MODE IE");
mtc.stop;
}
- log("found RSL MR CONFIG IE: ", mr_conf);
-
- if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
- setverdict(fail, "RSL MR CONFIG IE does not match expectation. Expected: ",
- g_pars.expect_mr_conf_ie);
+ var template RSL_IE_Body t_mode_ie := f_rsl_chmod_tmpl_from_codec(g_pars.ass_codec_list.codecElements[0]);
+ if (not match(mode_ie, t_mode_ie)) {
+ log("mode_ie ", mode_ie, " != t_mode_ie ", t_mode_ie);
+ setverdict(fail, "RSL Channel Mode IE doesn't match expectation");
}
- } else {
- if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
+
+ var RSL_IE_Body mr_conf;
+ if (g_pars.expect_mr_conf_ie != omit) {
+ if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == false) {
+ setverdict(fail, "Missing MR CONFIG IE in RSL Chan Activ");
+ mtc.stop;
+ }
log("found RSL MR CONFIG IE: ", mr_conf);
- setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
- mtc.stop;
+
+ if (not match(mr_conf, g_pars.expect_mr_conf_ie)) {
+ setverdict(fail, "RSL MR CONFIG IE does not match expectation. ",
+ "Expected: ", g_pars.expect_mr_conf_ie, ", got: ", mr_conf);
+ }
+ } else {
+ if (f_rsl_find_ie(rsl, RSL_IE_MR_CONFIG, mr_conf) == true) {
+ log("found RSL MR CONFIG IE: ", mr_conf);
+ setverdict(fail, "Found MR CONFIG IE in RSL Chan Activ, expecting omit");
+ mtc.stop;
+ }
}
}
+
+ if (do_perform_clear) {
+ f_perform_clear();
+ }
}
private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr {
@@ -2946,6 +4562,40 @@ private function f_TC_assignment_codec_fail(charstring id) runs on MSC_ConnHdlr
log("expecting ASS FAIL like this: ", exp_fail);
f_establish_fully(ass_cmd, exp_fail);
+ f_perform_clear();
+}
+
+const CounterNameVals counternames_bsc_bts_assignment := {
+ { "assignment:attempted", 0 },
+ { "assignment:completed", 0 },
+ { "assignment:stopped", 0 },
+ { "assignment:no_channel", 0 },
+ { "assignment:timeout", 0 },
+ { "assignment:failed", 0 },
+ { "assignment:error", 0 }
+};
+
+const CounterNameVals counternames_bts_assignment := {
+ { "assignment:attempted_sign", 0 },
+ { "assignment:attempted_speech", 0 },
+ { "assignment:completed_sign", 0 },
+ { "assignment:completed_speech", 0 },
+ { "assignment:stopped_sign", 0 },
+ { "assignment:stopped_speech", 0 },
+ { "assignment:no_channel_sign", 0 },
+ { "assignment:no_channel_speech", 0 },
+ { "assignment:timeout_sign", 0 },
+ { "assignment:timeout_speech", 0 },
+ { "assignment:failed_sign", 0 },
+ { "assignment:failed_speech", 0 },
+ { "assignment:error_sign", 0 },
+ { "assignment:error_speech", 0 }
+};
+
+function f_ctrs_bsc_and_bts_assignment_init(integer bts_count := NUM_BTS) runs on test_CT {
+ var CounterNameVals bts_names := counternames_bsc_bts_assignment & counternames_bts_assignment;
+ f_ctrs_bts_init(bts_count, bts_names);
+ f_ctrs_bsc_init(counternames_bsc_bts_assignment);
}
testcase TC_assignment_codec_fr() runs on test_CT {
@@ -2954,10 +4604,19 @@ testcase TC_assignment_codec_fr() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_assignment_init(1);
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
+ f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
+ f_ctrs_bts_add(0, "assignment:completed_speech", 1);
+ f_ctrs_bts_verify();
+
+ f_shutdown_helper();
}
testcase TC_assignment_codec_hr() runs on test_CT {
@@ -2966,10 +4625,19 @@ testcase TC_assignment_codec_hr() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_assignment_init(1);
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
+ f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
+ f_ctrs_bts_add(0, "assignment:completed_speech", 1);
+ f_ctrs_bts_verify();
+
+ f_shutdown_helper();
}
testcase TC_assignment_codec_efr() runs on test_CT {
@@ -2982,37 +4650,51 @@ testcase TC_assignment_codec_efr() runs on test_CT {
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecEFR}));
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+ f_shutdown_helper();
}
/* Allow 5,90k only (current default config) */
private function f_allow_amr_rate_5_90k() runs on test_CT {
- f_vty_enter_cfg_msc(BSCVTY, 0);
- f_vty_transceive(BSCVTY, "amr-config 12_2k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 10_2k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 7_95k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 7_40k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 6_70k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 5_90k allowed");
- f_vty_transceive(BSCVTY, "amr-config 5_15k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 4_75k forbidden");
- f_vty_transceive(BSCVTY, "exit");
- f_vty_transceive(BSCVTY, "exit");
+ f_vty_cfg_msc(BSCVTY, 0, {
+ "amr-config 12_2k forbidden",
+ "amr-config 10_2k forbidden",
+ "amr-config 7_95k forbidden",
+ "amr-config 7_40k forbidden",
+ "amr-config 6_70k forbidden",
+ "amr-config 5_90k allowed",
+ "amr-config 5_15k forbidden",
+ "amr-config 4_75k forbidden"
+ });
}
/* Allow 4,75k, 5,90k, 4,70k and 12,2k, which are the most common rates
* ("Config-NB-Code = 1") */
private function f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k() runs on test_CT {
- f_vty_enter_cfg_msc(BSCVTY, 0);
- f_vty_transceive(BSCVTY, "amr-config 12_2k allowed");
- f_vty_transceive(BSCVTY, "amr-config 10_2k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 7_95k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 7_40k allowed");
- f_vty_transceive(BSCVTY, "amr-config 6_70k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 5_90k allowed");
- f_vty_transceive(BSCVTY, "amr-config 5_15k forbidden");
- f_vty_transceive(BSCVTY, "amr-config 4_75k allowed");
- f_vty_transceive(BSCVTY, "exit");
- f_vty_transceive(BSCVTY, "exit");
+ f_vty_cfg_msc(BSCVTY, 0, {
+ "amr-config 12_2k allowed",
+ "amr-config 10_2k forbidden",
+ "amr-config 7_95k forbidden",
+ "amr-config 7_40k allowed",
+ "amr-config 6_70k forbidden",
+ "amr-config 5_90k allowed",
+ "amr-config 5_15k forbidden",
+ "amr-config 4_75k allowed"
+ });
+}
+
+private function f_vty_amr_start_mode_set(boolean fr, charstring startmode) runs on test_CT {
+ var charstring tch;
+ if (fr) {
+ tch := "tch-f";
+ } else {
+ tch := "tch-h";
+ }
+ f_vty_cfg_bts(BSCVTY, 0, { "amr " & tch & " start-mode " & startmode });
+}
+
+/* Set the AMR start-mode for this TCH back to the default configuration. */
+private function f_vty_amr_start_mode_restore(boolean fr) runs on test_CT {
+ f_vty_amr_start_mode_set(fr, "auto");
}
testcase TC_assignment_codec_amr_f() runs on test_CT {
@@ -3022,23 +4704,27 @@ testcase TC_assignment_codec_amr_f() runs on test_CT {
/* Note: This setups the codec configuration. The parameter payload in
* mr_conf must be consistant with the parameter codecElements in pars
* and also must match the amr-config in osmo-bsc.cfg! */
- var RSL_IE_Body mr_conf := {
- other := {
- len := 2,
- payload := '2804'O
- }
- };
-
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
- pars.expect_mr_conf_ie := mr_conf;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
f_init(1, true);
f_sleep(1.0);
+ f_vty_amr_start_mode_set(true, "1");
+ f_ctrs_bsc_and_bts_assignment_init(1);
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
+ f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
+ f_ctrs_bts_add(0, "assignment:completed_speech", 1);
+ f_ctrs_bts_verify();
+
+ f_vty_amr_start_mode_restore(true);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_h() runs on test_CT {
@@ -3046,38 +4732,90 @@ testcase TC_assignment_codec_amr_h() runs on test_CT {
var MSC_ConnHdlr vc_conn;
/* See note above */
- var RSL_IE_Body mr_conf := {
- other := {
- len := 2,
- payload := '2804'O
- }
- };
-
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
- pars.expect_mr_conf_ie := mr_conf;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
f_init(1, true);
f_sleep(1.0);
+ f_vty_amr_start_mode_set(false, "1");
+ f_ctrs_bsc_and_bts_assignment_init(1);
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
+ f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
+ f_ctrs_bts_add(0, "assignment:completed_speech", 1);
+ f_ctrs_bts_verify();
+
+ f_vty_amr_start_mode_restore(false);
+ f_shutdown_helper();
}
-function f_TC_assignment_codec_amr(boolean fr, octetstring mrconf, bitstring s8_s0, bitstring exp_s8_s0)
-runs on test_CT {
+/* Establish signalling on a TCH/F lchan, and then switch to speech mode without a new Assignment. */
+testcase TC_assignment_codec_fr_by_mode_modify() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+ /* By disabling all SDCCH, the MS should be given a TCH/F for signalling. Then activating an FR codec should
+ * merely do a Channel Mode Modify, and not assign to a new lchan. f_establish_fully() already accounts for
+ * expecting a Channel Mode Modify if the channel type is compatible. */
+ f_disable_all_sdcch();
+ f_disable_all_tch_h();
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ pars.expect_channel_mode_modify := true;
+ vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
+ vc_conn.done;
+
+ f_enable_all_sdcch();
+ f_enable_all_tch();
+ f_shutdown_helper();
+}
+
+/* 'amr start-mode auto' should not keep the (unused) 'smod' bits from previous configuration */
+testcase TC_assignment_codec_amr_startmode_cruft() runs on test_CT {
var TestHdlrParams pars := f_gen_test_hdlr_pars();
var MSC_ConnHdlr vc_conn;
- /* See note above */
- var RSL_IE_Body mr_conf := {
- other := {
- len := lengthof(mrconf),
- payload := mrconf
- }
- };
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
+ pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
+ pars.ass_codec_list.codecElements[0].s8_15 := '01010111'B;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
+ pars.expect_mr_conf_ie.multirate_cfg.icmi := false; /* expect ICMI=0, smod=00: */
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ /* First set nonzero start mode bits */
+ f_vty_amr_start_mode_set(true, "4");
+ /* Now set to auto, and expect the startmode bits to be zero in the message, i.e. ensure that osmo-bsc does not
+ * let the startmode bits stick around and has deterministic MultiRate config for 'start-mode auto'; that is
+ * ensured by above '2004'O, where 'x0xx'O indicates ICMI = 0, spare = 0, smod = 00. */
+ f_vty_amr_start_mode_set(true, "auto");
+
+ vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
+ vc_conn.done;
+
+ /* Clear the startmode bits to not affect subsequent tests, in case the bits should indeed stick around. */
+ f_vty_amr_start_mode_set(true, "1");
+ f_vty_amr_start_mode_restore(true);
+ f_shutdown_helper();
+}
+
+function f_TC_assignment_codec_amr(boolean fr, RSL_IE_MultirateCfg mr_cfg,
+ bitstring s8_s0, bitstring exp_s8_s0,
+ charstring start_mode := "1")
+runs on test_CT {
+
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
if (fr) {
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_F}));
@@ -3086,16 +4824,18 @@ runs on test_CT {
}
pars.ass_codec_list.codecElements[0].s0_7 := s8_s0;
pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
- pars.expect_mr_conf_ie := mr_conf;
+ pars.expect_mr_conf_ie := { multirate_cfg := mr_cfg };
pars.expect_mr_s0_s7 := exp_s8_s0;
f_init(1, true);
f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
+ f_vty_amr_start_mode_set(fr, start_mode);
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
f_allow_amr_rate_5_90k();
+ f_vty_amr_start_mode_restore(fr);
}
function f_TC_assignment_codec_amr_fail(boolean fr, bitstring s8_s0)
@@ -3114,68 +4854,100 @@ runs on test_CT {
f_init(1, true);
f_allow_amr_rate_4_75k_5_90k_7_40k_12_20k();
+ f_vty_amr_start_mode_set(fr, "1");
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_TC_assignment_codec_fail), pars);
vc_conn.done;
f_allow_amr_rate_5_90k();
+ f_vty_amr_start_mode_restore(fr);
}
-
/* Set S1, we expect an AMR multirate configuration IE with all four rates
* set. */
testcase TC_assignment_codec_amr_f_S1() runs on test_CT {
- f_TC_assignment_codec_amr(true, '289520882208'O, '00000010'B, '00000010'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '00000011'B, '00000010'B);
+ f_shutdown_helper();
}
/* Set S1, we expect an AMR multirate configuration IE with the lower three
* rates set. */
testcase TC_assignment_codec_amr_h_S1() runs on test_CT {
- f_TC_assignment_codec_amr(false, '2815208820'O, '00000010'B, '00000010'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '00000010'B, '00000010'B);
+ f_shutdown_helper();
}
/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
* all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
testcase TC_assignment_codec_amr_f_S124() runs on test_CT {
- f_TC_assignment_codec_amr(true, '289520882208'O, '00010110'B, '00000010'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '00010110'B, '00000010'B);
+ f_shutdown_helper();
}
/* Set S1 and two other rates, we expect an AMR MULTIRATE CONFIGURATION IE with
* all four rates (and only S1 set in the ASSIGNMENT COMPLETE) */
testcase TC_assignment_codec_amr_h_S124() runs on test_CT {
- f_TC_assignment_codec_amr(false, '2815208820'O, '00010110'B, '00000010'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '00010110'B, '00000010'B);
+ f_shutdown_helper();
}
/* The following block of tests selects more and more rates until all four
* possible rates are in the active set (full rate) */
testcase TC_assignment_codec_amr_f_S0() runs on test_CT {
- f_TC_assignment_codec_amr(true, '2801'O, '00000001'B, '00000001'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
+ f_TC_assignment_codec_amr(true, mr_cfg, '00000001'B, '00000001'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_S02() runs on test_CT {
- f_TC_assignment_codec_amr(true, '28052080'O, '00000101'B, '00000101'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
+ params := '2080'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '00000101'B, '00000101'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_S024() runs on test_CT {
- f_TC_assignment_codec_amr(true, '2815208820'O, '00010101'B, '00010101'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '00010101'B, '00010101'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_S0247() runs on test_CT {
- f_TC_assignment_codec_amr(true, '289520882208'O, '10010101'B, '10010101'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '10010101'B, '10010101'B);
+ f_shutdown_helper();
}
/* The following block of tests selects more and more rates until all three
* possible rates are in the active set (half rate) */
testcase TC_assignment_codec_amr_h_S0() runs on test_CT {
- f_TC_assignment_codec_amr(false, '2801'O, '00000001'B, '00000001'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000001'B));
+ f_TC_assignment_codec_amr(false, mr_cfg, '00000001'B, '00000001'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_h_S02() runs on test_CT {
- f_TC_assignment_codec_amr(false, '28052080'O, '00000101'B, '00000101'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00000101'B,
+ params := '2080'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '00000101'B, '00000101'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
- f_TC_assignment_codec_amr(false, '2815208820'O, '00010101'B, '00010101'B);
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '00010101'B, '00010101'B);
+ f_shutdown_helper();
}
/* The following block tests what happens when the MSC does offer rate
@@ -3185,38 +4957,85 @@ testcase TC_assignment_codec_amr_h_S024() runs on test_CT {
* to offer rates that are not applicable anyway. */
testcase TC_assignment_codec_amr_h_S0247() runs on test_CT {
- /* Try to include 12,2k in into the active set even though the channel
- * is half rate only. The BSC is expected to remove the 12,0k */
- f_TC_assignment_codec_amr(false, '2815208820'O, '10010101'B, '00010101'B);
+ /* Try to include 12,2k in into the active set even though the channel
+ * is half rate only. The BSC is expected to remove the 12,0k */
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_S01234567() runs on test_CT {
- /* See what happens when all rates are selected at once. Since then
- * Also S1 is selected, this setting will be prefered and we should
- * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
- f_TC_assignment_codec_amr(true, '289520882208'O, '11111111'B, '00000010'B);
+ /* See what happens when all rates are selected at once. Since then
+ * Also S1 is selected, this setting will be prefered and we should
+ * get 12.2k, 7,40k, 5,90k, and 4,75k in the active set. */
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_S0234567() runs on test_CT {
- /* Same as above, but with S1 missing, the MSC is then expected to
- * select the currently supported rates, which are also 12.2k, 7,40k,
- * 5,90k, and 4,75k, into the active set. */
- f_TC_assignment_codec_amr(true, '289520882208'O, '11111101'B, '10010101'B);
+ /* Same as above, but with S1 missing, the MSC is then expected to
+ * select the currently supported rates, which are also 12.2k, 7,40k,
+ * 5,90k, and 4,75k, into the active set. */
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '11111101'B, '10010101'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_zero() runs on test_CT {
- /* Try to select no rates at all */
- f_TC_assignment_codec_amr_fail(true, '00000000'B);
+ /* Try to select no rates at all */
+ f_TC_assignment_codec_amr_fail(true, '00000000'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_f_unsupp() runs on test_CT {
- /* Try to select only unsupported rates */
- f_TC_assignment_codec_amr_fail(true, '01101000'B);
+ /* Try to select only unsupported rates */
+ f_TC_assignment_codec_amr_fail(true, '01101000'B);
+ f_shutdown_helper();
}
testcase TC_assignment_codec_amr_h_S7() runs on test_CT {
- /* Try to select 12,2k for half rate */
- f_TC_assignment_codec_amr_fail(false, '10000000'B);
+ /* Try to select 12,2k for half rate */
+ f_TC_assignment_codec_amr_fail(false, '10000000'B);
+ f_shutdown_helper();
+}
+
+testcase TC_assignment_codec_amr_f_start_mode_auto() runs on test_CT {
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
+ codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "auto");
+ f_shutdown_helper();
+}
+
+testcase TC_assignment_codec_amr_h_start_mode_auto() runs on test_CT {
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(icmi := false,
+ codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B,
+ start_mode := "auto");
+ f_shutdown_helper();
+}
+
+testcase TC_assignment_codec_amr_f_start_mode_4() runs on test_CT {
+ /* "amr tch-f modes 0 2 4 7" => total 4 modes and start mode 4 => '11'B on the wire */
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 3,
+ codec_modes := '10010101'B,
+ params := '20882208'O));
+ f_TC_assignment_codec_amr(true, mr_cfg, '11111111'B, '00000010'B, start_mode := "4");
+ f_shutdown_helper();
+}
+
+testcase TC_assignment_codec_amr_h_start_mode_4() runs on test_CT {
+ /* "amr tch-h modes 0 2 4" => total 3 modes and start mode 4 => '10'B on the wire */
+ var RSL_IE_MultirateCfg mr_cfg := valueof(ts_RSL_MultirateCfg(start_mode := 2,
+ codec_modes := '00010101'B,
+ params := '208820'O));
+ f_TC_assignment_codec_amr(false, mr_cfg, '10010101'B, '00010101'B, start_mode := "4");
+ f_shutdown_helper();
}
private function f_disable_all_tch_f() runs on test_CT {
@@ -3240,6 +5059,20 @@ private function f_enable_all_tch() runs on test_CT {
f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 5 sub-slot 1 unused");
}
+private function f_disable_all_sdcch() runs on test_CT {
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 borken");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 borken");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 borken");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 borken");
+}
+
+private function f_enable_all_sdcch() runs on test_CT {
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 0 unused");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 1 unused");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 2 unused");
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 0 sub-slot 3 unused");
+}
+
/* Allow HR only */
private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs on MSC_ConnHdlr {
g_pars := f_gen_test_hdlr_pars();
@@ -3250,6 +5083,7 @@ private function f_TC_assignment_codec_xr_exhausted_req_hr(charstring id) runs o
ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow FR only */
@@ -3262,6 +5096,7 @@ private function f_TC_assignment_codec_xr_exhausted_req_fr(charstring id) runs o
ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow HR only (expect assignment failure) */
@@ -3274,6 +5109,7 @@ private function f_TC_assignment_codec_xr_exhausted_req_hr_fail(charstring id) r
ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '05'O;
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
f_establish_fully(ass_cmd, exp_fail);
+ f_perform_clear();
}
/* Allow FR only (expect assignment failure) */
@@ -3286,6 +5122,7 @@ private function f_TC_assignment_codec_xr_exhausted_req_fr_fail(charstring id) r
ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechId_DataIndicator := '01'O;
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
f_establish_fully(ass_cmd, exp_fail);
+ f_perform_clear();
}
/* Allow FR and HR, but prefer FR */
@@ -3299,6 +5136,7 @@ private function f_TC_assignment_codec_fr_exhausted_req_fr_hr(charstring id) run
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow FR and HR, but prefer HR */
@@ -3312,6 +5150,7 @@ private function f_TC_assignment_codec_fr_exhausted_req_hr_fr(charstring id) run
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow FR and HR, but prefer FR */
@@ -3325,6 +5164,7 @@ private function f_TC_assignment_codec_hr_exhausted_req_fr_hr(charstring id) run
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow FR and HR, but prefer HR */
@@ -3338,6 +5178,7 @@ private function f_TC_assignment_codec_hr_exhausted_req_hr_fr(charstring id) run
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Request a HR channel while all FR channels are exhausted, this is expected
@@ -3351,7 +5192,7 @@ testcase TC_assignment_codec_fr_exhausted_req_hr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a FR channel while all FR channels are exhausted, this is expected
@@ -3365,7 +5206,7 @@ testcase TC_assignment_codec_fr_exhausted_req_fr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr_fail));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a FR (prefered) or alternatively a HR channel while all FR channels
@@ -3379,7 +5220,7 @@ testcase TC_assignment_codec_fr_exhausted_req_fr_hr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_fr_hr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a HR (prefered) or alternatively a FR channel while all FR channels
@@ -3393,7 +5234,7 @@ testcase TC_assignment_codec_fr_exhausted_req_hr_fr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_fr_exhausted_req_hr_fr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a FR channel while all HR channels are exhausted, this is expected
@@ -3407,7 +5248,7 @@ testcase TC_assignment_codec_hr_exhausted_req_fr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_fr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a HR channel while all HR channels are exhausted, this is expected
@@ -3421,7 +5262,7 @@ testcase TC_assignment_codec_hr_exhausted_req_hr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_xr_exhausted_req_hr_fail));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a HR (prefered) or alternatively a FR channel while all HR channels
@@ -3435,7 +5276,7 @@ testcase TC_assignment_codec_hr_exhausted_req_hr_fr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_hr_fr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a FR (prefered) or alternatively a HR channel while all HR channels
@@ -3449,7 +5290,7 @@ testcase TC_assignment_codec_hr_exhausted_req_fr_hr() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_assignment_codec_hr_exhausted_req_fr_hr));
vc_conn.done;
f_enable_all_tch();
- setverdict(pass);
+ f_shutdown_helper();
}
/* Allow FR and HR, but prefer HR */
@@ -3463,6 +5304,7 @@ private function f_TC_assignment_codec_req_hr_fr(charstring id) runs on MSC_Conn
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR, ts_CodecFR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000101'B; /* Expect HR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Allow FR and HR, but prefer FR */
@@ -3476,6 +5318,7 @@ private function f_TC_assignment_codec_req_fr_hr(charstring id) runs on MSC_Conn
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR, ts_CodecHR}));
exp_compl.pdu.bssmap.assignmentComplete.speechVersion.speechVersionIdentifier := '0000001'B; /* Expect FR */
f_establish_fully(ass_cmd, exp_compl);
+ f_perform_clear();
}
/* Request a HR (prefered) or alternatively a FR channel, it is expected that
@@ -3487,7 +5330,7 @@ testcase TC_assignment_codec_req_hr_fr() runs on test_CT {
f_enable_all_tch();
vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_hr_fr));
vc_conn.done;
- setverdict(pass);
+ f_shutdown_helper();
}
/* Request a FR (prefered) or alternatively a HR channel, it is expected that
@@ -3499,32 +5342,207 @@ testcase TC_assignment_codec_req_fr_hr() runs on test_CT {
f_enable_all_tch();
vc_conn := f_start_handler(refers(f_TC_assignment_codec_req_fr_hr));
vc_conn.done;
- setverdict(pass);
+ f_shutdown_helper();
}
-testcase TC_assignment_osmux() runs on test_CT {
- var TestHdlrParams pars := f_gen_test_hdlr_pars();
+/* request a signalling channel with all SDCCH exhausted, it is expected that a TCH will be selected */
+private function f_TC_assignment_sdcch_exhausted_req_signalling(charstring id) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ g_pars.ra := '02'O; /* RA containing reason=LU */
+
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
+ var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
+ var template uint3_t tsc := ?;
+
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
+ f_create_bssmap_exp(l3_enc);
+ /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
+ RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
+
+ /* we should now have a COMPL_L3 at the MSC */
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_ComplL3);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
+ }
+ }
+
+ f_perform_clear();
+}
+testcase TC_assignment_sdcch_exhausted_req_signalling() runs on test_CT {
var MSC_ConnHdlr vc_conn;
+ f_init(1, true);
+ f_sleep(1.0);
+ f_disable_all_sdcch();
+ vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_signalling));
+ vc_conn.done;
+ f_enable_all_sdcch();
+ f_shutdown_helper();
+}
- /* See note above */
- var RSL_IE_Body mr_conf := {
- other := {
- len := 2,
- payload := '2804'O
+/* Request a signalling channel with all SDCCH exhausted, it is
+ expected that no TCH will be selected for signalling and assigment will fail
+ because it's dictated by VTY config */
+testcase TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() runs on test_CT {
+ var RSL_Message rsl_unused, rsl_msg;
+ var GsmRrMessage rr;
+ f_init(1, false);
+ f_sleep(1.0);
+ f_vty_allow_tch_for_signalling(false, 0);
+ f_disable_all_sdcch();
+
+ /* RA containing reason=LU */
+ f_ipa_tx(ts_RSL_CHAN_RQD('02'O, 2342));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
+ if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
+ setverdict(fail, "Expected reject");
+ }
+
+ f_vty_allow_tch_for_signalling(true, 0);
+ f_enable_all_sdcch();
+ f_shutdown_helper();
+}
+
+/* Request a voice channel with all SDCCH exhausted, it is
+ * expected that TCH channel will be allocated since the VTY option is only
+ * aimed at signalling requests */
+private function f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden(charstring id) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ g_pars.ra := '43'O; /* RA containing reason=originating speech call*/
+
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
+ var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
+ var template uint3_t tsc := ?;
+
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
+ f_create_bssmap_exp(l3_enc);
+ /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
+ RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
+
+ /* we should now have a COMPL_L3 at the MSC */
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_ComplL3);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
}
- };
+ }
+ f_perform_clear();
+}
+testcase TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_allow_tch_for_signalling(false, 0);
+ f_disable_all_sdcch();
+
+ vc_conn := f_start_handler(refers(f_TC_assignment_sdcch_exhausted_req_voice_tch_forbidden));
+ vc_conn.done;
+
+ f_vty_allow_tch_for_signalling(true, 0);
+ f_enable_all_sdcch();
+ f_shutdown_helper();
+}
+
+/* Test Osmux setup BSC<->MSC */
+testcase TC_assignment_osmux_cn() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
+ pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
+ pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
+ pars.use_osmux_cn := true;
+
+ g_osmux_enabled_cn := true;
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_amr_start_mode_set(false, "1");
+
+ vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
+ vc_conn.done;
+
+ f_vty_amr_start_mode_restore(false);
+ f_shutdown_helper();
+}
+
+/* Test Osmux setup BTS<->BSC */
+testcase TC_assignment_osmux_bts() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
- pars.expect_mr_conf_ie := mr_conf;
- pars.use_osmux := true;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
+ pars.use_osmux_bts := true;
+
+ g_osmux_enabled_bts := true;
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_amr_start_mode_set(false, "1");
+
+ vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
+ vc_conn.done;
+
+ f_vty_amr_start_mode_restore(false);
+ f_shutdown_helper();
+}
+
+/* Test non-AMR codecs still work fine as RTP when Osmux is enabled BTS<->BSC<->MSC */
+testcase TC_assignment_codec_hr_osmux_on() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
- f_init(1, true, true);
+ g_osmux_enabled_cn := true;
+ g_osmux_enabled_bts := true;
+ f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_assignment_init(1);
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted", 1);
+ f_ctrs_bts_add(0, "assignment:attempted_speech", 1);
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed", 1);
+ f_ctrs_bts_add(0, "assignment:completed_speech", 1);
+ f_ctrs_bts_verify();
+
+ f_shutdown_helper();
+}
+
+/* Test Osmux setup BTS<->BSC<->MSC */
+testcase TC_assignment_osmux() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecAMR_H}));
+ pars.ass_codec_list.codecElements[0].s0_7 := '00000100'B; /* 5,90k */
+ pars.ass_codec_list.codecElements[0].s8_15 := '00000111'B;
+ pars.expect_mr_conf_ie := c_mr_conf_5_90;
+ pars.use_osmux_cn := true;
+ pars.use_osmux_bts := true;
+
+ g_osmux_enabled_cn := true;
+ g_osmux_enabled_bts := true;
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_amr_start_mode_set(false, "1");
+
+ vc_conn := f_start_handler(refers(f_TC_assignment_codec), pars);
+ vc_conn.done;
+
+ f_vty_amr_start_mode_restore(false);
+ f_shutdown_helper();
}
/* test the procedure of the MSC requesting a Classmark Update:
@@ -3535,7 +5553,6 @@ private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
f_create_chan_and_exp();
/* we should now have a COMPL_L3 at the MSC */
- BSSAP.receive(tr_BSSMAP_ComplL3);
BSSAP.send(ts_BSSMAP_ClassmarkRequest);
RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_CM_ENQUIRY));
@@ -3543,6 +5560,8 @@ private function f_tc_classmark(charstring id) runs on MSC_ConnHdlr {
f_rsl_send_l3(ts_RRM_CM_CHG(valueof(ts_CM2)));
BSSAP.receive(tr_BSSMAP_ClassmarkUpd(?, omit));
setverdict(pass);
+
+ f_perform_clear();
}
testcase TC_classmark() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3550,6 +5569,7 @@ testcase TC_classmark() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_classmark));
vc_conn.done;
+ f_shutdown_helper();
}
/* Send a CommonID from the simulated MSC and verify that the information is used to
@@ -3560,7 +5580,6 @@ private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
f_create_chan_and_exp();
/* we should now have a COMPL_L3 at the MSC */
- BSSAP.receive(tr_BSSMAP_ComplL3);
/* Send CommonID */
BSSAP.send(ts_BSSMAP_CommonId(g_pars.imsi));
@@ -3570,6 +5589,8 @@ private function f_tc_common_id(charstring id) runs on MSC_ConnHdlr {
f_vty_transceive_match_regexp_retry(BSCVTY, "show conns", regex, 0, 4, 1.0);
setverdict(pass);
+
+ f_perform_clear();
}
testcase TC_common_id() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3577,13 +5598,13 @@ testcase TC_common_id() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_common_id));
vc_conn.done;
+ f_shutdown_helper();
}
private function f_est_single_l3(template PDU_ML3_MS_NW l3) runs on MSC_ConnHdlr {
g_pars := f_gen_test_hdlr_pars();
f_create_chan_and_exp();
/* we should now have a COMPL_L3 at the MSC */
- BSSAP.receive(tr_BSSMAP_ComplL3);
/* send the single message we want to send */
f_rsl_send_l3(l3);
@@ -3608,6 +5629,7 @@ private function f_bssap_expect_nothing(float sec := 5.00) runs on MSC_ConnHdlr
private function f_tc_unsol_ass_fail(charstring id) runs on MSC_ConnHdlr {
f_est_single_l3(ts_RRM_AssignmentFailure('00'O));
f_bssap_expect_nothing();
+ f_perform_clear();
}
testcase TC_unsol_ass_fail() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3615,6 +5637,7 @@ testcase TC_unsol_ass_fail() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_unsol_ass_fail));
vc_conn.done;
+ f_shutdown_helper();
}
@@ -3622,6 +5645,7 @@ testcase TC_unsol_ass_fail() runs on test_CT {
private function f_tc_unsol_ass_compl(charstring id) runs on MSC_ConnHdlr {
f_est_single_l3(ts_RRM_AssignmentComplete('00'O));
f_bssap_expect_nothing();
+ f_perform_clear();
}
testcase TC_unsol_ass_compl() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3629,6 +5653,7 @@ testcase TC_unsol_ass_compl() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_unsol_ass_compl));
vc_conn.done;
+ f_shutdown_helper();
}
@@ -3636,6 +5661,7 @@ testcase TC_unsol_ass_compl() runs on test_CT {
private function f_tc_unsol_ho_fail(charstring id) runs on MSC_ConnHdlr {
f_est_single_l3(ts_RRM_HandoverFailure('00'O));
f_bssap_expect_nothing();
+ f_perform_clear();
}
testcase TC_unsol_ho_fail() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3643,6 +5669,7 @@ testcase TC_unsol_ho_fail() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_unsol_ho_fail));
vc_conn.done;
+ f_shutdown_helper();
}
@@ -3651,11 +5678,11 @@ private function f_tc_err_82_short_msg(charstring id) runs on MSC_ConnHdlr {
g_pars := f_gen_test_hdlr_pars();
f_create_chan_and_exp();
/* we should now have a COMPL_L3 at the MSC */
- BSSAP.receive(tr_BSSMAP_ComplL3);
/* send short message */
RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), ''O));
f_bssap_expect_nothing();
+ f_perform_clear();
}
testcase TC_err_82_short_msg() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3663,12 +5690,12 @@ testcase TC_err_82_short_msg() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_err_82_short_msg));
vc_conn.done;
+ f_shutdown_helper();
}
-
/* 24.008 8.4 Unknown message must trigger RR STATUS */
private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
- f_est_single_l3(ts_RRM_UL_REL('00'O));
+ f_est_single_l3(ts_RRM_DTM_ASS_FAIL('00'O));
timer T := 3.0
alt {
[] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_STATUS)) {
@@ -3677,6 +5704,7 @@ private function f_tc_err_84_unknown_msg(charstring id) runs on MSC_ConnHdlr {
[] BSSAP.receive { setverdict(fail, "unexpected BSSAP"); }
[] T.timeout { setverdict(fail, "Timeout waiting for RR STATUS"); }
}
+ f_perform_clear();
}
testcase TC_err_84_unknown_msg() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3684,6 +5712,7 @@ testcase TC_err_84_unknown_msg() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_err_84_unknown_msg));
vc_conn.done;
+ f_shutdown_helper();
}
/***********************************************************************
@@ -3699,8 +5728,10 @@ runs on test_CT {
}
/* execute a "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7>" command on given Dchan */
-private function f_vty_ss_action(charstring suffix, integer bts_nr, integer trx_nr, RslChannelNr chan_nr)
-runs on MSC_ConnHdlr {
+private function f_vty_ss_action(TELNETasp_PT pt, charstring suffix,
+ uint8_t bts_nr, uint8_t trx_nr,
+ in RslChannelNr chan_nr)
+{
/* FIXME: resolve those from component-global state */
var integer ts_nr := chan_nr.tn;
var integer ss_nr;
@@ -3719,7 +5750,7 @@ runs on MSC_ConnHdlr {
var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
" timeslot "&int2str(ts_nr)&" sub-slot "&int2str(ss_nr)&" ";
- f_vty_transceive(BSCVTY, cmd & suffix);
+ f_vty_transceive(pt, cmd & suffix);
}
/* Even though the VTY command to trigger handover takes a new BTS number as argument, behind the scenes osmo-bsc always
@@ -3727,18 +5758,16 @@ runs on MSC_ConnHdlr {
* ident key (ARFCN + BSIC) in the struct passed on to handover_request(). handover_start() then resolves that to a
* viable actual neighbor cell. So from the internal osmo-bsc perspective, we always request handover to an ARFCN + BSIC
* pair, not really to a specific BTS number. */
-private function f_vty_handover(integer bts_nr, integer trx_nr, RslChannelNr chan_nr,
- integer new_bts_nr)
-runs on MSC_ConnHdlr {
- f_vty_ss_action("handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
+private function f_vty_handover(TELNETasp_PT pt, uint8_t bts_nr, uint8_t trx_nr,
+ in RslChannelNr chan_nr, uint8_t new_bts_nr)
+{
+ f_vty_ss_action(pt, "handover " & int2str(new_bts_nr), bts_nr, trx_nr, chan_nr);
}
/* intra-BSC hand-over between BTS0 and BTS1 */
private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
- g_pars := f_gen_test_hdlr_pars();
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
var PDU_BSSAP ass_cmd := f_gen_ass_req();
- const OCT8 kc := '0001020304050607'O;
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
@@ -3749,10 +5778,11 @@ private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
var HandoverState hs := {
rr_ho_cmpl_seen := false,
handover_done := false,
- old_chan_nr := -
+ old_chan_nr := -,
+ expect_target_tsc := c_BtsParams[1].tsc
};
- /* issue hand-over command on VTY */
- f_vty_handover(0, 0, g_chan_nr, 1);
+ /* issue hand-over command on VTY, from BTS 0 to BTS 1 */
+ f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
/* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
f_rslem_suspend(RSL1_PROC);
@@ -3772,15 +5802,197 @@ private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
/* Check the amount of MGCP transactions is still consistant with the
* test expectation */
f_check_mgcp_expectations()
+
+ var RSL_Message chan_act := f_rslem_get_last_act(RSL1_PROC, 0, g_chan_nr);
+
+ /* Ensure the Channel Activation for the new channel contained the right encryption params. as_handover() set
+ * g_chan_nr to the new lchan that was handed over to. It lives in bts 1, so look it up at RSL1_PROC. */
+ f_verify_encr_info(chan_act);
+
+ f_chan_act_verify_tsc(chan_act, c_BtsParams[1].tsc);
+
+ f_perform_clear(RSL1, RSL1_PROC);
+
f_sleep(0.5);
}
testcase TC_ho_int() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+ f_init(2, true);
+ f_sleep(1.0);
+
+ pars.expect_tsc := c_BtsParams[0].tsc;
+
+ f_ctrs_bsc_and_bts_handover_init();
+
+ vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
+ vc_conn.done;
+
+ /* from f_establish_fully() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ /* from handover */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:completed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+function f_tc_ho_int_a5(OCT1 encr_alg, charstring enc_a5 := "0 1 3") runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.encr := valueof(t_EncrParams(encr_alg, f_rnd_octstring(8), f_rnd_octstring(16)));
+
+ f_init(2, true);
+ f_vty_encryption_a5(enc_a5);
+ f_sleep(1.0);
+
+ f_ctrs_bsc_and_bts_handover_init();
+
+ vc_conn := f_start_handler(refers(f_tc_ho_int), pars);
+ vc_conn.done;
+
+ /* from f_establish_fully() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ /* from handover */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:completed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:completed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_vty_encryption_a5_reset();
+ f_shutdown_helper(ho := true);
+}
+
+testcase TC_ho_int_a5_0() runs on test_CT {
+ f_tc_ho_int_a5('01'O);
+}
+
+testcase TC_ho_int_a5_1() runs on test_CT {
+ f_tc_ho_int_a5('02'O);
+}
+
+testcase TC_ho_int_a5_3() runs on test_CT {
+ f_tc_ho_int_a5('08'O);
+}
+
+testcase TC_ho_int_a5_4() runs on test_CT {
+ f_tc_ho_int_a5('10'O, "0 1 3 4");
+}
+
+/* intra-BSC hand-over with CONNection FAILure and cause Radio Link Failure: check RR release cause */
+private function f_tc_ho_int_radio_link_failure(charstring id) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+ f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
+
+ var HandoverState hs := {
+ rr_ho_cmpl_seen := false,
+ handover_done := false,
+ old_chan_nr := -,
+ expect_target_tsc := c_BtsParams[1].tsc
+ };
+ /* issue hand-over command on VTY */
+ f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
+ /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
+ f_rslem_suspend(RSL1_PROC);
+
+ /* From the MGW perspective, a handover is is characterized by
+ * performing one MDCX operation with the MGW. So we expect to see
+ * one more MDCX during handover. */
+ g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
+
+ var RSL_Message rsl;
+ var PDU_ML3_NW_MS l3;
+ var RslChannelNr new_chan_nr;
+ var GsmArfcn arfcn;
+ RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+ if (not ischosen(l3.msgs.rrm.handoverCommand)) {
+ setverdict(fail, "Expected handoverCommand");
+ mtc.stop;
+ }
+ }
+ f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
+ new_chan_nr, arfcn);
+
+ f_rslem_register(0, new_chan_nr, RSL1_PROC);
+
+ /* resume processing of RSL DChan messages, which was temporarily suspended
+ * before performing a hand-over */
+ f_rslem_resume(RSL1_PROC);
+ RSL1.receive(tr_RSL_IPA_CRCX(new_chan_nr));
+
+ f_sleep(1.0);
+
+ /* Handover fails because no HANDO DET appears on the new lchan,
+ * and the old lchan reports a Radio Link Failure. */
+ RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+
+ var PDU_BSSAP rx_clear_request;
+ BSSAP.receive(tr_BSSMAP_ClearRequest) -> value rx_clear_request;
+ var BssmapCause cause := bit2int(rx_clear_request.pdu.bssmap.clearRequest.cause.causeValue);
+ BSSAP.send(ts_BSSMAP_ClearCommand(cause));
+
+ var RR_Cause rr_cause := GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
+
+ var MgcpCommand mgcp;
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE(int2oct(enum2int(rr_cause), 1)))) {}
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr);
+ }
+ [] RSL1.receive(tr_RSL_DEACT_SACCH(new_chan_nr)) {}
+ [] RSL1.receive(tr_RSL_RF_CHAN_REL(new_chan_nr)) {
+ RSL1.send(ts_RSL_RF_CHAN_REL_ACK(new_chan_nr));
+ f_rslem_unregister(0, g_chan_nr, PT := RSL1_PROC);
+ }
+ [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ }
+ }
+
+ f_sleep(0.5);
+ setverdict(pass);
+}
+testcase TC_ho_int_radio_link_failure() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(2, true);
f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_int));
+
+ f_ctrs_bsc_and_bts_handover_init();
+
+ vc_conn := f_start_handler(refers(f_tc_ho_int_radio_link_failure));
vc_conn.done;
+
+ /* from f_establish_fully() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ /* from handover */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:stopped");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:stopped");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:stopped");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* Expecting MGCP to DLCX the endpoint's two connections: towards BTS and towards MSC */
@@ -3813,23 +6025,21 @@ private function f_expect_dlcx_conns() runs on MSC_ConnHdlr {
MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, msg_resp));
};
}
-
- BSSAP.receive(tr_BSSMAP_ClearComplete);
}
-private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
- g_pars := f_gen_test_hdlr_pars();
+private function f_ho_out_of_this_bsc(template (omit) BSSMAP_oldToNewBSSIEs exp_oldToNewBSSIEs := omit,
+ boolean skip_meas_rep := false) runs on MSC_ConnHdlr {
- var PDU_BSSAP ass_req := f_gen_ass_req();
- ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
- ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
- var template PDU_BSSAP exp_compl := f_gen_exp_compl();
- f_establish_fully(ass_req, exp_compl);
-
- f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
- f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
+ if (not skip_meas_rep) {
+ var NcellReports neighbor_rep := {
+ { rxlev := 20, bcch_freq := 0, bsic := 11 }
+ };
+ var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
+ RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
+ l3_mr, 0));
- BSSAP.receive(tr_BSSMAP_HandoverRequired);
+ BSSAP.receive(tr_BSSMAP_HandoverRequired(exp_oldToNewBSSIEs));
+ }
f_sleep(0.5);
/* The MSC negotiates Handover Request and Handover Request Ack with
@@ -3869,17 +6079,96 @@ private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
BSSAP.send(ts_BSSMAP_ClearCommand(cause));
f_expect_dlcx_conns();
+
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE));
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr));
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr));
+ [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ }
+ }
setverdict(pass);
- f_sleep(1.0);
+}
+
+private function f_tc_ho_out_of_this_bsc(charstring id) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ var PDU_BSSAP ass_req := f_gen_ass_req();
+ ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ f_establish_fully(ass_req, exp_compl);
+
+ f_ho_out_of_this_bsc();
}
testcase TC_ho_out_of_this_bsc() runs on test_CT {
var MSC_ConnHdlr vc_conn;
+ f_init_vty();
+ f_bts_0_cfg(BSCVTY,
+ {"neighbor-list mode automatic",
+ "handover 1",
+ "handover algorithm 2",
+ "handover2 window rxlev averaging 1",
+ "no neighbors",
+ "neighbor lac 99 arfcn 123 bsic any"});
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
vc_conn := f_start_handler(refers(f_tc_ho_out_of_this_bsc));
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:completed");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+private function f_mo_l3_transceive(RSL_DCHAN_PT rsl := RSL,
+ template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0),
+ template (present) OCT1 dlci := ?,
+ octetstring l3 := '0123456789'O)
+runs on MSC_ConnHdlr {
+ /* The old lchan and conn should still be active. See that arbitrary L3
+ * is still going through. */
+ rsl.send(ts_RSL_DATA_IND(g_chan_nr, link_id, l3));
+ var template PDU_BSSAP exp_data := {
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := dlci,
+ lengthIndicator := lengthof(l3),
+ pdu := {
+ dtap := l3
+ }
+ };
+ BSSAP.receive(exp_data);
+ setverdict(pass);
+}
+
+private function f_mt_l3_transceive(RSL_DCHAN_PT rsl := RSL,
+ template (present) RslLinkId link_id := tr_RslLinkID_DCCH(0),
+ template (value) OCT1 dlci := '00'O,
+ octetstring l3 := '0123456789'O)
+runs on MSC_ConnHdlr {
+ BSSAP.send(PDU_BSSAP:{
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := dlci,
+ lengthIndicator := lengthof(l3),
+ pdu := {
+ dtap := l3
+ }
+ });
+ rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, link_id, l3));
+ setverdict(pass);
}
/* BSC asks for inter-BSC HO, but the MSC decides that it won't happen and
@@ -3893,7 +6182,7 @@ private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_Con
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
f_establish_fully(ass_req, exp_compl);
- f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
+ f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
BSSAP.receive(tr_BSSMAP_HandoverRequired);
@@ -3902,22 +6191,9 @@ private function f_tc_ho_out_fail_no_msc_response(charstring id) runs on MSC_Con
* Let's give it a bit extra. */
f_sleep(15.0);
- /* The old lchan and conn should still be active. See that arbitrary L3
- * is still going through. */
- var octetstring l3 := '0123456789'O;
- RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
- var template PDU_BSSAP exp_data := {
- discriminator := '1'B,
- spare := '0000000'B,
- dlci := '00'O,
- lengthIndicator := 5,
- pdu := {
- dtap := l3
- }
- };
- BSSAP.receive(exp_data);
- setverdict(pass);
+ f_mo_l3_transceive();
f_sleep(1.0);
+ f_perform_clear();
}
testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -3925,8 +6201,19 @@ testcase TC_ho_out_fail_no_msc_response() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_msc_response));
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:timeout");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* BSC asks for inter-BSC HO, receives BSSMAP Handover Command, but MS reports
@@ -3940,7 +6227,7 @@ private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnH
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
f_establish_fully(ass_req, exp_compl);
- f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
+ f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
BSSAP.receive(tr_BSSMAP_HandoverRequired);
@@ -3983,25 +6270,12 @@ private function f_tc_ho_out_fail_rr_ho_failure(charstring id) runs on MSC_ConnH
f_sleep(1.0);
- /* The old lchan and conn should still be active. See that arbitrary L3
- * is still going through. */
- var octetstring l3 := '0123456789'O;
- RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3));
- var template PDU_BSSAP exp_data := {
- discriminator := '1'B,
- spare := '0000000'B,
- dlci := '00'O,
- lengthIndicator := 5,
- pdu := {
- dtap := l3
- }
- };
- BSSAP.receive(exp_data);
- setverdict(pass);
+ f_mo_l3_transceive();
f_sleep(1.0);
setverdict(pass);
f_sleep(1.0);
+ f_perform_clear();
}
testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
var MSC_ConnHdlr vc_conn;
@@ -4009,8 +6283,19 @@ testcase TC_ho_out_fail_rr_ho_failure() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_rr_ho_failure));
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:failed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* BSC asks for inter-BSC-out HO, receives BSSMAP Handover Command, but then no reply is received about HO outcome
@@ -4025,7 +6310,7 @@ private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
f_establish_fully(ass_req, exp_compl);
- f_bts_0_cfg(BSCVTY, {"neighbor lac 99 arfcn 123 bsic any"});
+ f_bts_0_cfg(BSCVTY, {"no neighbor lac 99", "neighbor lac 99 arfcn 123 bsic any"});
f_vty_transceive(BSCVTY, "handover any to arfcn 123 bsic any");
BSSAP.receive(tr_BSSMAP_HandoverRequired);
@@ -4079,13 +6364,16 @@ private function f_tc_ho_out_fail_no_result_after_ho_cmd(charstring id) runs on
[] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
log("Got RR Release");
}
- [] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL)) {
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
log("Got RF Chan Rel");
RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr);
}
}
f_expect_dlcx_conns();
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
setverdict(pass);
f_sleep(1.0);
@@ -4096,11 +6384,23 @@ testcase TC_ho_out_fail_no_result_after_ho_cmd() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
vc_conn := f_start_handler(refers(f_tc_ho_out_fail_no_result_after_ho_cmd));
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:timeout");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
-private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
+private function f_ho_into_this_bsc(charstring id, template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit) runs on MSC_ConnHdlr {
+ var PDU_BSSAP rx_bssap;
/* Hack: the proper way would be to wait for the BSSMAP Handover Request ACK and extract the
* actual assigned chan_nr from its L3 (RR Handover Command) message. But osmo-bsc starts acting
* on the lchan even before we get a chance to evaluate the BSSMAP Handover Request ACK. So we
@@ -4109,23 +6409,100 @@ private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
f_rslem_register(0, new_chan_nr);
g_chan_nr := new_chan_nr;
+ var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
f_sleep(1.0);
f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
- activate(as_Media());
+ var default as_media := activate(as_Media());
+
+ var PDU_BSSAP ho_req := f_gen_handover_req(aoip_tla := g_pars.host_aoip_tla,
+ cell_id_source := g_pars.cell_id_source,
+ oldToNewBSSIEs := oldToNewBSSIEs,
+ enc := g_pars.encr);
+ if (g_pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr) {
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ho_req));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+ } else {
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, omit));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+ BSSAP.send(ho_req);
+ }
- BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
- f_gen_handover_req()));
- BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap {
+ if (g_pars.expect_ho_fail) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Expected Handover Request to fail, but got Handover Request Ack")
+ }
+ }
+ [] BSSAP.receive(tr_BSSMAP_HandoverFailure) -> value rx_bssap {
+ if (not g_pars.expect_ho_fail) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Expected Handover Request to succeed, but got Handover Failure")
+ }
+ // TODO: evaluate correct cause value. But osmo-bsc doesn't seem to send meaningful causes yet!
+ // For now just accept any cause.
+ BSSAP.receive(tr_BSSMAP_ClearRequest);
+ setverdict(pass);
+ return;
+ }
+ }
+
+ if (g_pars.expect_ho_fail_lchan_est) {
+ BSSAP.receive(tr_BSSMAP_HandoverFailure);
+ setverdict(pass);
+
+ /* When we let MGCP MDCX run into a timeout, it's still in the
+ * queue and additionally after BSSAP HandoverFailure, two DLCX
+ * get sent (for AoIP, for SCCPlite one DLCX). */
+ if (g_pars.ignore_mgw_mdcx) {
+ if (g_pars.aoip) {
+ MGCP.receive(tr_MDCX);
+ MGCP.receive(tr_DLCX);
+ MGCP.receive(tr_DLCX);
+ } else {
+ MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_MDCX}));
+ MGCP_MULTI.receive(tr_MGCP_RecvFrom_any({command := tr_DLCX}));
+ }
+ }
+ return;
+ }
/* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
- var PDU_BSSAP rx_bssap;
- var octetstring ho_command_str;
+ /* we're sure that the channel activation is done now, verify the parameters in it */
+ var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
+ f_verify_encr_info(chan_act);
+ f_chan_act_verify_tsc(chan_act, expect_target_tsc);
- BSSAP.receive(tr_BSSMAP_HandoverRequestAcknowledge(?)) -> value rx_bssap;
+ if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.codecList)) {
+ if (not g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "handoverRequestAck: Expected no Speech Codec List (BSS Supported), because this is not AoIP");
+ }
+ /* TODO: check actual codecs? */
+ } else {
+ if (g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "handoverRequestAck: Expected Speech Codec List (BSS Supported), but none found");
+ }
+ }
+ if (ispresent(rx_bssap.pdu.bssmap.handoverRequestAck.speechCodec)) {
+ if (not g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "handoverRequestAck: Expected no Speech Codec (Chosen), because this is not AoIP");
+ }
+ /* TODO: check actual codec? */
+ } else {
+ if (g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "handoverRequestAck: Expected Speech Codec (Chosen), but none found");
+ }
+ }
+
+ var octetstring ho_command_str;
ho_command_str := rx_bssap.pdu.bssmap.handoverRequestAck.layer3Information.layer3info;
log("Received L3 Info in HO Request Ack: ", ho_command_str);
var PDU_ML3_NW_MS ho_command := dec_PDU_ML3_NW_MS(ho_command_str);
@@ -4144,6 +6521,35 @@ private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
}
log("Handover Command chan_nr is", actual_new_chan_nr);
+ var uint3_t got_tsc := rr_chan_desc_tsc(ho_command.msgs.rrm.handoverCommand.channelDescription2);
+ if (not match(got_tsc, expect_target_tsc)) {
+ setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
+ expect_target_tsc, " got ", got_tsc);
+ mtc.stop;
+ } else {
+ log("handoverCommand: verified TSC = ", got_tsc);
+ }
+
+ /* Check the Cipher Mode Setting IE (shall be present during inter-RAT handover) */
+ if (ispresent(ho_command.msgs.rrm.handoverCommand.cipherModeSetting)) {
+ var CipherModeSetting_TV cms := ho_command.msgs.rrm.handoverCommand.cipherModeSetting;
+ var template (present) CipherModeSetting_TV tr_cms := {
+ sC := '0'B, /* no ciphering by default */
+ algorithmIdentifier := '000'B,
+ elementIdentifier := ?
+ };
+ if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_expect != '01'O) { /* A5/N */
+ tr_cms.algorithmIdentifier := f_cipher_mode_bssmap_to_rr(g_pars.encr.enc_alg_expect);
+ tr_cms.sC := '1'B;
+ }
+ if (not match(cms, tr_cms)) {
+ setverdict(fail, "RR Handover Command: unexpected Cipher Mode Setting IE: ",
+ cms, ", expected: ", tr_cms);
+ }
+ } else {
+ setverdict(fail, "RR Handover Command: Cipher Mode Setting IE is not present");
+ }
+
/* Now the MSC forwards the RR Handover Command to the other BSC, which
* tells the MS to handover to the new lchan. Here comes the new MS on
* the new lchan with a Handover RACH: */
@@ -4161,20 +6567,249 @@ private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
enc_PDU_ML3_MS_NW(l3_tx)));
BSSAP.receive(tr_BSSMAP_HandoverComplete);
+ deactivate(as_media);
+ setverdict(pass);
+}
+
+private function f_tc_ho_into_this_bsc(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_ML3_NW_MS exp_rr_rel_tmpl;
+ var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit;
+ if (not istemplatekind(g_pars.last_used_eutran_plmn, "omit")) {
+ oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
+ }
+ if (g_pars.exp_fast_return) {
+ exp_rr_rel_tmpl := tr_RRM_RR_RELEASE_CellSelectInd;
+ } else {
+ exp_rr_rel_tmpl := tr_RRM_RR_RELEASE;
+ }
+ f_ho_into_this_bsc(id, oldToNewBSSIEs);
+ if (g_pars.expect_ho_fail) {
+ f_perform_clear_no_lchan();
+ } else if (g_pars.expect_ho_fail_lchan_est) {
+ BSSAP.receive(tr_BSSMAP_ClearRequest);
+ f_perform_clear_no_lchan();
+ } else {
+ f_perform_clear(exp_rr_rel_tmpl := exp_rr_rel_tmpl);
+ }
setverdict(pass);
}
+function f_tc_ho_into_this_bsc_main(TestHdlrParams pars, charstring vty_a5_cfg := VTY_A5_DEFAULT) runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_vty_encryption_a5(vty_a5_cfg);
+ f_ctrs_bsc_and_bts_handover_init();
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
+ vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
+ if (pars.expect_ho_fail) {
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:failed");
+ } else if (pars.expect_ho_fail_lchan_est) {
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
+ } else {
+ f_ctrs_bsc_and_bts_add(0, "handover:completed");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed");
+ }
+ f_ctrs_bsc_and_bts_verify();
+
+ f_vty_encryption_a5_reset();
+}
+
testcase TC_ho_into_this_bsc() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ f_tc_ho_into_this_bsc_main(pars);
+ f_shutdown_helper(ho := true);
+}
+
+function f_tc_ho_into_this_bsc_a5(TestHdlrEncrParams encr, charstring vty_a5_cfg := VTY_A5_DEFAULT,
+ boolean expect_fail := false) runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.encr := encr;
+ pars.expect_ho_fail := expect_fail;
+ f_tc_ho_into_this_bsc_main(pars, vty_a5_cfg);
+ f_shutdown_helper(ho := true);
+}
+
+testcase TC_ho_into_this_bsc_a5_0() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params('01'O));
+}
+
+testcase TC_ho_into_this_bsc_a5_1() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params('02'O));
+}
+
+testcase TC_ho_into_this_bsc_a5_3() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params('08'O));
+}
+
+testcase TC_ho_into_this_bsc_a5_4() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params('10'O, kc128 := true), "3 4");
+}
+
+/* Report: in inter-BSC incoming handover, when the MSC omits the Chosen Encryption Algorithm IE in the Handover Request
+ * message, then osmo-bsc starts an unencrypted lchan even if A5/0 is not permitted.
+ *
+ * This test verifies that the Encryption Information is present in the Channel Activation when the Chosen Enc Alg is
+ * omitted.
+ *
+ * Related: SYS#5839
+ */
+testcase TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O, alg_chosen := omit));
+}
+
+testcase TC_ho_into_this_bsc_a5_1_3() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '0a'O, alg_expect := '08'O));
+}
+
+/* Send a permitted algo mask that does not intersect with osmo-bsc.cfg */
+testcase TC_ho_into_this_bsc_a5_mismatch() runs on test_CT {
+ f_tc_ho_into_this_bsc_a5(f_encr_params(alg_permitted := '18'O, alg_expect := '10'O), "0 1",
+ expect_fail := true); // 0x18 = A5/3 and A5/4
+}
+
+testcase TC_ho_into_this_bsc_tla_v6() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.host_aoip_tla := "::6";
+ f_tc_ho_into_this_bsc_main(pars);
+ f_shutdown_helper(ho := true);
+}
+
+/* Similar to TC_ho_into_this_bsc, but when in SRVCC, HO Req contains "Old BSS
+ to New BSS Information" IE with "Last Used E-UTRAN PLMN Id", which, when the
+ channel is later released (RR CHannel Release), should trigger inclusion of
+ IE "Cell Selection Indicator after Release of all TCH and SDCCH" with E-UTRAN
+ neighbors. */
+testcase TC_srvcc_eutran_to_geran() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.last_used_eutran_plmn := '323454'O;
+ pars.exp_fast_return := true;
+ f_tc_ho_into_this_bsc_main(pars);
+
+ f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
+ f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+/* Same as TC_srvcc_eutran_to_geran, but enables ciphering on the target channel. */
+testcase TC_srvcc_eutran_to_geran_a5_3() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.encr := f_encr_params('08'O); /* only A5/3 */
+ pars.last_used_eutran_plmn := '323454'O;
+ pars.exp_fast_return := true;
+ f_tc_ho_into_this_bsc_main(pars);
+
+ f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
+ f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+/* Same as TC_srvcc_eutran_to_geran, but test explicitly forbiding fast return
+ on the BTS. As a result, RR Release shouldn't contain the EUTRAN neighbor
+ list when the channel is released. */
+testcase TC_srvcc_eutran_to_geran_forbid_fast_return() runs on test_CT {
+ f_init_vty();
+ f_vty_allow_srvcc_fast_return(true, 0)
+
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.last_used_eutran_plmn := '323454'O;
+ pars.exp_fast_return := false;
+ f_tc_ho_into_this_bsc_main(pars);
+ f_vty_allow_srvcc_fast_return(false, 0);
+ f_shutdown_helper();
+}
+
+/* Same as TC_srvcc_eutran_to_geran, but using SAI as serving Cell Identifier. SYS#5838 */
+testcase TC_srvcc_eutran_to_geran_src_sai() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.last_used_eutran_plmn := '323454'O;
+ pars.cell_id_source := valueof(ts_CellID_SAI('123456'O, 300, 444));
+ f_tc_ho_into_this_bsc_main(pars);
+
+ f_ctrs_bsc_and_bts_add(0, "srvcc:attempted");
+ f_ctrs_bsc_and_bts_add(0, "srvcc:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper();
+}
+
+private function f_tc_srvcc_eutran_to_geran_ho_out(charstring id) runs on MSC_ConnHdlr {
+ var template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs;
+ oldToNewBSSIEs := f_ts_BSSMAP_oldToNewBSSIEs(ts_BSSMAP_LastUsedEUTRANPLMNId(g_pars.last_used_eutran_plmn));
+ f_ho_into_this_bsc(id, oldToNewBSSIEs);
+ f_ho_out_of_this_bsc(oldToNewBSSIEs);
+ setverdict(pass);
+}
+
+private function f_tc_srvcc_eutran_to_geran_ho_out_main(boolean disable_fast_return)
+ runs on test_CT {
var MSC_ConnHdlr vc_conn;
var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ f_init_vty();
+ f_bts_0_cfg(BSCVTY,
+ {"neighbor-list mode automatic",
+ "handover 1",
+ "handover algorithm 2",
+ "handover2 window rxlev averaging 1",
+ "no neighbors",
+ "neighbor lac 99 arfcn 123 bsic any"});
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
f_init(1, true);
+ if (disable_fast_return) {
+ f_vty_allow_srvcc_fast_return(true, 0);
+ }
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
+ pars.last_used_eutran_plmn := '323454'O;
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
- vc_conn := f_start_handler(refers(f_tc_ho_into_this_bsc), pars);
+ vc_conn := f_start_handler(refers(f_tc_srvcc_eutran_to_geran_ho_out), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted", 2);
+ f_ctrs_bsc_and_bts_add(0, "handover:completed", 2);
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted", 1);
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:completed", 1);
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted", 1);
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed", 1);
+
+ f_ctrs_bsc_and_bts_add(0, "srvcc:attempted", 1);
+ f_ctrs_bsc_and_bts_add(0, "srvcc:completed", 1);
+ f_ctrs_bsc_and_bts_verify();
+
+ if (disable_fast_return) {
+ f_vty_allow_srvcc_fast_return(false, 0);
+ }
+ f_shutdown_helper();
+}
+
+/* First, HO into BSC from EUTRAN (SRVCC): HO Request contains "Old BSS to New
+ BSS Information" IE with "Last Used E-UTRAN PLMN Id".
+ Second, HO to another BSC: HO Required contains "Old BSS to New BSS Information"
+ IE with "Last Used E-UTRAN PLMN Id" from first step. */
+testcase TC_srvcc_eutran_to_geran_ho_out() runs on test_CT {
+ f_tc_srvcc_eutran_to_geran_ho_out_main(false);
+}
+/* Validate subsequent intra-GSM-HO works the same (with OldBSSToNewBSSInfo IE)
+ * independently of fast-reture allowed/forbidden in local BTS */
+testcase TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() runs on test_CT {
+ f_tc_srvcc_eutran_to_geran_ho_out_main(true);
}
private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr {
@@ -4231,6 +6866,9 @@ private function f_tc_ho_in_fail_msc_clears(charstring id) runs on MSC_ConnHdlr
BSSAP.send(ts_BSSMAP_ClearCommand(cause));
f_expect_dlcx_conns();
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
setverdict(pass);
f_sleep(1.0);
@@ -4243,11 +6881,20 @@ testcase TC_ho_in_fail_msc_clears() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:stopped");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs on MSC_ConnHdlr {
@@ -4313,7 +6960,9 @@ private function f_tc_ho_in_fail_msc_clears_after_ho_detect(charstring id) runs
BSSAP.send(ts_BSSMAP_ClearCommand(cause));
f_expect_dlcx_conns();
- setverdict(pass);
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
f_sleep(1.0);
}
testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
@@ -4323,11 +6972,20 @@ testcase TC_ho_in_fail_msc_clears_after_ho_detect() runs on test_CT {
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
vc_conn := f_start_handler(refers(f_tc_ho_in_fail_msc_clears_after_ho_detect), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:stopped");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:stopped");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* The new BSS's lchan times out before the MSC decides that handover failed. */
@@ -4392,23 +7050,34 @@ private function f_tc_ho_in_fail_no_detect(charstring id) runs on MSC_ConnHdlr {
BSSAP.send(ts_BSSMAP_ClearCommand(cause));
f_expect_dlcx_conns();
- setverdict(pass);
- f_sleep(1.0);
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
- setverdict(pass);
+ f_sleep(1.0);
}
testcase TC_ho_in_fail_no_detect() runs on test_CT {
var MSC_ConnHdlr vc_conn;
var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.fail_on_dlcx := false;
+
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* Same as f_tc_ho_in_fail_no_detect, but MSC fails to send a Clear Command */
@@ -4465,21 +7134,65 @@ private function f_tc_ho_in_fail_no_detect2(charstring id) runs on MSC_ConnHdlr
BSSAP.send(ts_BSSMAP_ClearCommand(cause));
};
f_expect_dlcx_conns();
- setverdict(pass);
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
f_sleep(1.0);
}
testcase TC_ho_in_fail_no_detect2() runs on test_CT {
var MSC_ConnHdlr vc_conn;
var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.fail_on_dlcx := false;
+
f_init(1, true);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+
pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
vc_conn := f_start_handler(refers(f_tc_ho_in_fail_no_detect2), pars);
vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_in:error");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+testcase TC_ho_in_fail_mgw_mdcx_timeout() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.ignore_mgw_mdcx := true;
+ pars.expect_ho_fail_lchan_est := true;
+
+ f_tc_ho_into_this_bsc_main(pars);
+ f_shutdown_helper(ho := true);
+}
+
+testcase TC_ho_in_fail_ipa_crcx_timeout() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.ignore_ipa_media := true;
+ pars.expect_ho_fail_lchan_est := true;
+ pars.fail_on_dlcx := false;
+
+ f_tc_ho_into_this_bsc_main(pars);
+ f_shutdown_helper(ho := true);
+}
+
+/* An incoming inter-BSC HO can either issue the Handover Request message attached to the initial SCCP N-Connect (as in
+ * the other tests we have so far), or the first CR can be "empty" with the BSSAP request following later. Test the
+ * empty N-Connect case. */
+testcase TC_ho_into_this_bsc_sccp_cr_without_bssap() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ pars.inter_bsc_ho_in__ho_req_in_initial_sccp_cr := false;
+ f_tc_ho_into_this_bsc_main(pars);
+ f_shutdown_helper(ho := true);
}
type record of charstring Commands;
@@ -4506,7 +7219,8 @@ private function f_probe_for_handover(charstring log_label,
charstring log_descr,
charstring handover_vty_cmd,
boolean expect_handover,
- boolean is_inter_bsc_handover := false)
+ boolean is_inter_bsc_handover := false,
+ template uint3_t expect_target_tsc := ?)
runs on MSC_ConnHdlr
{
/* We're going to thwart any and all handover attempts, just be ready to handle (and ignore) handover target
@@ -4538,6 +7252,17 @@ runs on MSC_ConnHdlr
log("Handover to new chan ", new_chan_nr, " on ARFCN ", arfcn);
log(l3.msgs.rrm.handoverCommand);
+ /* Verify correct TSC in handoverCommand */
+ var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
+ if (not match(got_tsc, expect_target_tsc)) {
+ setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
+ expect_target_tsc, " got ", got_tsc);
+ mtc.stop;
+ } else {
+ log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
+ expect_target_tsc, ")");
+ }
+
/* Need to register for new lchan on new BTS -- it's either bts 1 or bts 2. It doesn't really
* matter on which BTS it really is, we're not going to follow through an entire handover
* anyway. */
@@ -4619,7 +7344,6 @@ private function f_tc_ho_neighbor_config_start() runs on MSC_ConnHdlr {
g_pars := f_gen_test_hdlr_pars();
var template PDU_BSSAP exp_compl := f_gen_exp_compl();
var PDU_BSSAP ass_cmd := f_gen_ass_req();
- const OCT8 kc := '0001020304050607'O;
ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
@@ -4647,7 +7371,7 @@ private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
f_bts_0_cfg(BSCVTY, {"no neighbors"});
f_probe_for_handover("1.a", "HO to bts 1 works, implicitly listed as neighbor (legacy behavior when none are configured)",
"handover any to arfcn 871 bsic 11",
- true);
+ true, expect_target_tsc := c_BtsParams[1].tsc);
f_probe_for_handover("1.b", "HO to unknown cell does not start",
"handover any to arfcn 13 bsic 39",
@@ -4659,8 +7383,52 @@ private function f_tc_ho_neighbor_config_1(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("1.d", "HO to 871-11 still works (verify that this test properly cleans up)",
"handover any to arfcn 871 bsic 11",
- true);
+ true, expect_target_tsc := c_BtsParams[1].tsc);
+
+ f_perform_clear();
+}
+testcase TC_ho_neighbor_config_1() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true, guard_timeout := 60.0);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 1.a */
+ /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by sending a Handover Failure message. */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
+
+ /* 1.b */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ /* 1.c */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ /* 1.d */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
+
private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4677,12 +7445,43 @@ private function f_tc_ho_neighbor_config_2(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("2.a", "HO to bts 1 works, explicitly listed as neighbor",
"handover any to arfcn 871 bsic 11",
- true);
+ true, expect_target_tsc := c_BtsParams[1].tsc);
f_probe_for_handover("2.b", "HO to bts 2 doesn't work, not listed as neighbor",
"handover any to arfcn 871 bsic 12",
false);
+ f_perform_clear();
+}
+testcase TC_ho_neighbor_config_2() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true, guard_timeout := 50.0);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 2.a */
+ /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by sending a Handover Failure message. */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(1, "incoming_intra_bsc_ho:failed");
+
+ /* 2.b */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
+
private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4702,8 +7501,39 @@ private function f_tc_ho_neighbor_config_3(charstring id) runs on MSC_ConnHdlr {
false);
f_probe_for_handover("3.b", "HO to bts 2 works, explicitly listed as neighbor; no ambiguity because bts 3 is not listed as neighbor",
"handover any to arfcn 871 bsic 12",
- true);
+ true, expect_target_tsc := c_BtsParams[2].tsc);
+ f_perform_clear();
+}
+testcase TC_ho_neighbor_config_3() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true, guard_timeout := 50.0);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 3.a */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ /* 3.b */
+ /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by sending a Handover Failure message. */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
+
private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4727,7 +7557,40 @@ private function f_tc_ho_neighbor_config_4(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("4.c", "HO to 123-45 triggers inter-BSC HO",
"handover any to arfcn 123 bsic 45",
true, true);
+ f_perform_clear();
+}
+testcase TC_ho_neighbor_config_4() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true, guard_timeout := 50.0);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 4.a */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ /* 4.b */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ /* 4.c */
+ /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by timing out after the Handover Required message */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:timeout");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
+
private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4745,7 +7608,32 @@ private function f_tc_ho_neighbor_config_5(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("5.a", "HO to 871-12 triggers inter-BSC HO (ignoring local cells with same ARFCN+BSIC)",
"handover any to arfcn 871 bsic 12",
true, true);
+ f_perform_clear();
}
+testcase TC_ho_neighbor_config_5() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 5 */
+ /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by timing out after the Handover Required message */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:timeout");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4764,7 +7652,30 @@ private function f_tc_ho_neighbor_config_6(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("6.a", "HO to 871-12 is ambiguous = error",
"handover any to arfcn 871 bsic 12",
false);
+ f_perform_clear();
}
+testcase TC_ho_neighbor_config_6() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ f_init(3, true);
+ f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
+ vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
+ vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 6.a */
+ /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by timing out after the Handover Required message */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:error");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
f_tc_ho_neighbor_config_start();
@@ -4782,60 +7693,44 @@ private function f_tc_ho_neighbor_config_7(charstring id) runs on MSC_ConnHdlr {
f_probe_for_handover("7.a", "HO to 871-12 does HO to bts 2",
"handover any to arfcn 871 bsic 12",
- true);
+ true, expect_target_tsc := c_BtsParams[2].tsc);
f_probe_for_handover("7.b", "HO to 123-45 triggers inter-BSC HO",
"handover any to arfcn 123 bsic 45",
true, true);
-}
-
-testcase TC_ho_neighbor_config_1() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true, guard_timeout := 60.0);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_1));
- vc_conn.done;
-}
-testcase TC_ho_neighbor_config_2() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true, guard_timeout := 50.0);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_2));
- vc_conn.done;
-}
-testcase TC_ho_neighbor_config_3() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true, guard_timeout := 50.0);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_3));
- vc_conn.done;
-}
-testcase TC_ho_neighbor_config_4() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true, guard_timeout := 50.0);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_4));
- vc_conn.done;
-}
-testcase TC_ho_neighbor_config_5() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_5));
- vc_conn.done;
-}
-testcase TC_ho_neighbor_config_6() runs on test_CT {
- var MSC_ConnHdlr vc_conn;
- f_init(3, true);
- f_sleep(1.0);
- vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_6));
- vc_conn.done;
+ f_perform_clear();
}
testcase TC_ho_neighbor_config_7() runs on test_CT {
var MSC_ConnHdlr vc_conn;
f_init(3, true, guard_timeout := 50.0);
f_sleep(1.0);
+ f_ctrs_bsc_and_bts_handover_init();
vc_conn := f_start_handler(refers(f_tc_ho_neighbor_config_7));
vc_conn.done;
+
+ /* f_tc_ho_neighbor_config_start() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+
+ /* 7.a */
+ /* "failed" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by sending a Handover Failure message. */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:failed");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:attempted");
+ f_ctrs_bsc_and_bts_add(0, "intra_bsc_ho:failed");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:attempted");
+ f_ctrs_bts_add(2, "incoming_intra_bsc_ho:failed");
+
+ /* 7.b */
+ /* "timeout" means a handover was triggered and started (which is all this test aims for) and the test ended the
+ * handover quickly by timing out after the Handover Required message */
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:timeout");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:timeout");
+
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
}
/* OS#3041: Open and close N connections in a normal fashion, and expect no
@@ -4863,7 +7758,7 @@ testcase TC_bssap_rlsd_does_not_cause_bssmap_reset() runs on test_CT {
/* Setup a BSSAP connection and clear it right away. This is
* the MSC telling the BSC about a planned release, it's not an
* erratic loss of a connection. */
- dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
+ dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
/* MSC disconnects (RLSD). */
BSSAP.send(ts_BSSAP_DISC_req(dt.sccp_conn_id, 0));
@@ -4907,13 +7802,13 @@ testcase TC_bssmap_clear_does_not_cause_bssmap_reset() runs on test_CT {
/* Setup a BSSAP connection and clear it right away. This is
* the MSC telling the BSC about a planned release, it's not an
* erratic loss of a connection. */
- dt := f_est_dchan(int2oct(i,1), 23+i, '00010203040506'O);
+ dt := f_est_dchan(int2oct(i,1), 23+i, gen_l3_valid_payload());
/* Instruct BSC to clear channel */
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
/* expect BSC to disable the channel */
- f_exp_chan_rel_and_clear(dt, 0);
+ f_exp_chan_rel_and_clear(dt);
}
/* In the buggy behavior, a timeout of 2 seconds happens between above
@@ -4953,10 +7848,10 @@ testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
/* Setup a BSSAP connection and clear it right away. This is
* the MSC telling the BSC about a planned release, it's not an
* erratic loss of a connection. */
- dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* simulate RLL REL IND */
- f_ipa_tx(0, ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
+ f_ipa_tx(ts_RSL_REL_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
/* expect Clear Request on MSC side */
BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_di;
@@ -4966,7 +7861,7 @@ testcase TC_ms_rel_ind_does_not_cause_bssmap_reset() runs on test_CT {
BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
/* expect BSC to disable the channel */
- f_exp_chan_rel_and_clear(dt, 0);
+ f_exp_chan_rel_and_clear(dt);
}
/* In the buggy behavior, a timeout of 2 seconds happens between above
@@ -4990,12 +7885,12 @@ runs on test_CT {
/* ask BSC via VTY to activate a given IPA style chan as PDCH */
f_vty_ts_action("pdch activate", bts_nr, trx_nr, ts_nr);
/* expect the BSC to issue the related RSL command */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
if (istemplatekind(nack, "omit")) {
/* respond with a related acknowledgement */
- f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
+ f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
} else {
- f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
+ f_ipa_tx(ts_RSL_IPA_PDCH_ACT_NACK(chan_nr, valueof(nack)));
}
}
@@ -5007,12 +7902,12 @@ runs on test_CT {
/* ask BSC via VTY to activate a given IPA style chan as PDCH */
f_vty_ts_action("pdch deactivate", bts_nr, trx_nr, ts_nr);
/* expect the BSC to issue the related RSL command */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_DEACT(chan_nr));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_DEACT(chan_nr));
if (istemplatekind(nack, "omit")) {
/* respond with a related acknowledgement */
- f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
+ f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_ACK(chan_nr));
} else {
- f_ipa_tx(0, ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
+ f_ipa_tx(ts_RSL_IPA_PDCH_DEACT_NACK(chan_nr, valueof(nack)));
}
}
@@ -5040,10 +7935,19 @@ runs on test_CT {
f_vty_transceive(BSCVTY, "end");
}
+
+private function f_ts_reset_chcomb(integer bts_nr) runs on test_CT {
+ var integer i;
+ for (i := 0; i < 8; i := i + 1) {
+ f_ts_set_chcomb(bts_nr, 0, i, phys_chan_config[i]);
+ }
+}
+
private const charstring TCHF_MODE := "TCH/F mode";
private const charstring TCHH_MODE := "TCH/H mode";
private const charstring PDCH_MODE := "PDCH mode";
private const charstring NONE_MODE := "NONE mode";
+private const charstring SDCCH8_MODE := "SDCCH8 mode";
/* Test IPA PDCH activation / deactivation triggered by VTY */
testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
@@ -5062,8 +7966,8 @@ testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
log("TCH/F_PDCH pchan starts out in TCH/F mode:");
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
/* The BSC will activate the dynamic PDCH by default, so confirm that */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
- f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
+ f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
f_sleep(1.0);
log("TCH/F_PDCH pchan, PDCH ACT was ACKed, so now in PDCH mode:");
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
@@ -5089,7 +7993,7 @@ testcase TC_dyn_pdch_ipa_act_deact() runs on test_CT {
/* clean up config */
f_ts_set_chcomb(0, 0, 6, "PDCH");
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test IPA PDCH activation NACK */
@@ -5108,8 +8012,8 @@ testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, TCHF_MODE);
/* The BSC will activate the dynamic PDCH by default, so confirm that */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_IPA_PDCH_ACT(chan_nr));
- f_ipa_tx(0, ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_IPA_PDCH_ACT(chan_nr));
+ f_ipa_tx(ts_RSL_IPA_PDCH_ACT_ACK(chan_nr, ts_RSL_IE_FrameNumber(2342)));
f_sleep(1.0);
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
@@ -5126,7 +8030,7 @@ testcase TC_dyn_pdch_ipa_act_nack() runs on test_CT {
/* clean up config */
f_ts_set_chcomb(0, 0, 6, "PDCH");
- setverdict(pass);
+ f_shutdown_helper();
}
@@ -5139,15 +8043,15 @@ private function f_dyn_osmo_pdch_act(integer bts_nr, integer trx_nr, integer ts_
runs on test_CT {
var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
var RSL_Message rsl_unused;
- /* ask BSC via VTY to activate a given IPA style chan as PDCH */
+ /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
/* FIXME: no VTY command to activate Osmocom PDCH !! */
/* expect the BSC to issue the related RSL command */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT(chan_nr, ?));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT(chan_nr, ?));
if (istemplatekind(nack, "omit")) {
/* respond with a related acknowledgement */
- f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
} else {
- f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
+ f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, valueof(nack)));
}
}
@@ -5156,15 +8060,15 @@ private function f_dyn_osmo_pdch_deact(integer bts_nr, integer trx_nr, integer t
runs on test_CT {
var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(ts_nr));
var RSL_Message rsl_unused;
- /* ask BSC via VTY to activate a given IPA style chan as PDCH */
+ /* ask BSC via VTY to activate a given OSMO style chan as PDCH */
/* FIXME: no VTY command to activate Osmocom PDCH !! */
/* expect the BSC to issue the related RSL command */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_RF_CHAN_REL(chan_nr));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
if (istemplatekind(nack, "omit")) {
/* respond with a related acknowledgement */
- f_ipa_tx(0, ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
} else {
- //f_ipa_tx(0, ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
+ //f_ipa_tx(ts_RSL_RF_CHAN_REL_NACK(chan_nr, valueof(nack)));
}
}
@@ -5185,9 +8089,9 @@ testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
log("TCH/F_TCH/H_PDCH pchan starts out in disabled mode:");
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
/* The BSC will activate the dynamic PDCH by default, so confirm that */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
- f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
f_sleep(1.0);
log("TCH/F_TCH/H_PDCH requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, PDCH_MODE);
@@ -5195,7 +8099,7 @@ testcase TC_dyn_pdch_osmo_act_deact() runs on test_CT {
/* clean up config */
f_ts_set_chcomb(0, 0, 6, "PDCH");
- setverdict(pass);
+ f_shutdown_helper();
}
/* Test Osmocom dyn PDCH activation NACK behavior */
@@ -5214,17 +8118,305 @@ testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT {
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
/* The BSC will activate the dynamic PDCH by default, so confirm that */
- rsl_unused := f_exp_ipa_rx(0, tr_RSL_CHAN_ACT_PDCH(chan_nr, ?));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
/* NACK this activation and expect the "show timeslot" mode still to be NONE */
- f_ipa_tx(0, ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
+ f_ipa_tx(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL));
f_sleep(1.0);
f_ts_dyn_mode_assert(0, 0, chan_nr.tn, NONE_MODE);
/* clean up config */
f_ts_set_chcomb(0, 0, 6, "PDCH");
- setverdict(pass);
+ f_shutdown_helper();
+}
+
+/* Test Osmocom dyn TS SDCCH8 activation / deactivation */
+testcase TC_dyn_ts_sdcch8_act_deact() runs on test_CT {
+ var RSL_Message rsl_unused, rsl_msg;
+ var DchanTuple dt;
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+
+ /* change Timeslot 6 before f_init() starts RSL */
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
+
+ log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
+ /* The BSC will activate the dynamic PDCH by default, so confirm that */
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ f_sleep(1.0);
+ log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
+
+ /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
+ * on CCCH+SDCCH4+CBCH) */
+ var DchanTuples sdcch_cleanup := {};
+ var integer i;
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
+ dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
+ sdcch_cleanup := sdcch_cleanup & { dt };
+ }
+
+ /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
+
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
+ dt.idx := {0, 0};
+
+ f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
+
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt);
+
+ /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ f_sleep(1.0);
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(sdcch_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(sdcch_cleanup[i]);
+ }
+
+ /* clean up config */
+ f_ts_set_chcomb(0, 0, 6, "PDCH");
+
+ f_shutdown_helper();
+}
+
+/* Validate all 8 subslots of a dynamics TS configured as SDCCH8 are used */
+testcase TC_dyn_ts_sdcch8_all_subslots_used() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init_vty();
+ for (i := 1; i < 8; i := i + 1) {
+ if (i == 2) {
+ f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
+ } else {
+ f_ts_set_chcomb(0, 0, i, "PDCH");
+ }
+ }
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, guard_timeout := 60.0);
+
+ /* The dyn TS want to activate PDCH mode, ACK that. */
+ var RslChannelNr chan_nr;
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ f_sleep(1.0);
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ var DchanTuples chan_cleanup := {};
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* Only the dyn TS is still available. Its first lchan gets converted to SDCCH8 */
+ chan_cleanup := chan_cleanup & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ /* Also occupy the seven other SDCCH of the dyn TS */
+ for (i := 0; i < 7; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(chan_cleanup[i]);
+ }
+
+ /* clean up config */
+ f_ts_reset_chcomb(0);
+
+ f_shutdown_helper();
+}
+
+/* Test Osmocom dyn TS SDCCH8 activation / deactivation: If activating dyn TS as
+ SDCCH8 would end up in having no free TCH, then BSC should decide to activate
+ it as TCH directly instead. SYS#5309. */
+testcase TC_dyn_ts_sdcch8_tch_call_act_deact() runs on test_CT {
+ var RSL_Message rsl_unused, rsl_msg;
+ var DchanTuple dt;
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ var integer i;
+
+ /* change Timeslot 6 before f_init() starts RSL */
+ f_init_vty();
+ for (i := 1; i < 8; i := i + 1) {
+ if (i == 6) {
+ f_ts_set_chcomb(0, 0, i, "TCH/F_TCH/H_SDCCH8_PDCH");
+ } else {
+ f_ts_set_chcomb(0, 0, i, "PDCH");
+ }
+ }
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
+
+ log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
+ /* The BSC will activate the dynamic PDCH by default, so confirm that */
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ f_sleep(1.0);
+ log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
+
+ /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
+ * on CCCH+SDCCH4+CBCH) */
+ var DchanTuples chan_cleanup := {};
+ var OCT1 ra := '43'O; /* RA containing reason=originating speech call*/
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
+ dt := f_est_dchan(ra, i, gen_l3_valid_payload());
+ chan_cleanup := chan_cleanup & { dt };
+ }
+
+ /* Now the dyn ts is selected. First PDCH is released, then TCH chan is activated */
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int(ra) + i, 1), 2342));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
+
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
+ dt.idx := {0, 0};
+
+ f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(dt.rsl_chan_nr, 2342));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, TCHH_MODE);
+
+ f_ipa_tx(ts_RSL_EST_IND(dt.rsl_chan_nr, valueof(ts_RslLinkID_DCCH(0)), '1234'O));
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3('1234'O))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(dt.sccp_conn_id));
+
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt);
+
+ /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ f_sleep(1.0);
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(chan_cleanup[i]);
+ }
+
+ /* clean up config */
+ f_ts_reset_chcomb(0);
+ /* TODO: clean up other channels? */
+
+ f_shutdown_helper();
+}
+
+/* Test Osmocom dyn TS SDCCH8 activation / deactivation when SDCCH fails at BTS */
+testcase TC_dyn_ts_sdcch8_act_nack() runs on test_CT {
+ var RSL_Message rsl_unused, rsl_msg;
+ var DchanTuple dt;
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ var GsmRrMessage rr;
+
+ /* change Timeslot 6 before f_init() starts RSL */
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_SDCCH8_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ var RslChannelNr pdch_chan_nr := valueof(t_RslChanNr_PDCH(6));
+
+ log("TCH/F_TCH/H_SDCCH8_PDCH pchan starts out in disabled mode:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, NONE_MODE);
+ /* The BSC will activate the dynamic PDCH by default, so confirm that */
+ rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ f_sleep(1.0);
+ log("TCH/F_TCH/H_SDCCH8_PDC requested to PDCH ACT on startup, which was ACKed, so now in PDCH:");
+ f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE);
+
+ /* Fill TS0 SDCCH channels (NOTE: only 3 SDCCH/4 channels are available
+ * on CCCH+SDCCH4+CBCH) */
+ var DchanTuples chan_cleanup := {};
+ var integer i;
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i + 1) {
+ dt := f_est_dchan('23'O, i, gen_l3_valid_payload());
+ chan_cleanup := chan_cleanup & { dt };
+ }
+
+ /* Now the dyn ts is selected. First PDCH is released, then sdcch chan is activated */
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(oct2int('23'O) + i, 1), 2342));
+ rsl_unused := f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(pdch_chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(pdch_chan_nr));
+
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ dt.rsl_chan_nr := rsl_msg.ies[0].body.chan_nr;
+ dt.idx := {0, 0};
+
+ f_ts_dyn_mode_assert(0, 0, dt.rsl_chan_nr.tn, SDCCH8_MODE);
+ f_ipa_tx(ts_RSL_CHAN_ACT_NACK(dt.rsl_chan_nr, RSL_ERR_EQUIPMENT_FAIL));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ rr := dec_GsmRrMessage(rsl_msg.ies[1].body.full_imm_ass_info.payload);
+ if (rr.header.message_type != IMMEDIATE_ASSIGNMENT_REJECT) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Expected reject");
+ }
+
+ /* FIXME? Currently the TS stays in state BORKEN: */
+
+ /* The BSC will switch the TS back to PDCH once the only lchan using it is released: */
+ /* rsl_unused := f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(pdch_chan_nr));
+ * f_ipa_tx(ts_RSL_CHAN_ACT_ACK(pdch_chan_nr, 2342));
+ * f_sleep(1.0);
+ * f_ts_dyn_mode_assert(0, 0, pdch_chan_nr.tn, PDCH_MODE)
+ */
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(chan_cleanup[i]);
+ }
+
+ /* clean up config */
+ f_ts_set_chcomb(0, 0, 6, "PDCH");
+
+ f_shutdown_helper();
}
testcase TC_chopped_ipa_ping() runs on test_CT {
@@ -5232,6 +8424,7 @@ testcase TC_chopped_ipa_ping() runs on test_CT {
for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
}
+ f_shutdown_helper();
}
testcase TC_chopped_ipa_payload() runs on test_CT {
@@ -5240,6 +8433,7 @@ testcase TC_chopped_ipa_payload() runs on test_CT {
for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) {
IPA_Testing.f_run_TC_chopped_ipa_payload(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER);
}
+ f_shutdown_helper();
}
/* Verify the BSC sends the MS Power Parameters IE during CHAN ACT to make sure
@@ -5254,62 +8448,184 @@ testcase TC_assignment_verify_ms_power_params_ie() runs on test_CT {
f_sleep(1.0);
vc_conn := f_start_handler(refers(f_tc_assignment_fr_a5), pars);
vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify activation and deactivation of the BCCH carrier power reduction mode */
+testcase TC_c0_power_red_mode() runs on test_CT {
+ f_init(1);
+
+ for (var integer red := 6; red >= 0; red := red - 2) {
+ /* Configure BCCH carrier power reduction mode via the VTY */
+ f_vty_transceive(BSCVTY, "bts 0 c0-power-reduction " & int2str(red));
+
+ /* Expect Osmocom specific BS Power Control message on the RSL */
+ var template (present) RSL_Message tr_rsl_pdu := tr_RSL_BS_PWR_CTRL(
+ chan_nr := t_RslChanNr_BCCH(0),
+ bs_power := tr_RSL_IE_BS_Power(red / 2));
+ tr_rsl_pdu.msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false);
+ var RSL_Message unused := f_exp_ipa_rx(tr_rsl_pdu);
+
+ /* Additionally verify the applied value over the CTRL interface */
+ var CtrlValue cred := f_ctrl_get_bts(IPA_CTRL, 0, "c0-power-reduction");
+ if (cred != int2str(red)) {
+ setverdict(fail, "Unexpected BCCH carrier power reduction value ",
+ cred, " (expected ", red, ")");
+ }
+ }
+
+ f_shutdown_helper();
}
/***********************************************************************
* MSC Pooling
***********************************************************************/
-function f_tmsi_nri(integer nri_v, octetstring base_tmsi := '42000023'O, integer nri_bitlen := 10) return octetstring
-{
- return int2oct( oct2int(base_tmsi) + bit2int( (int2bit(nri_v, 32) << ( 24 - nri_bitlen)) ),
- 4);
+template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
+ ts_MI_TMSI_LV(tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v, nri_bitlen := nri_bitlen));
+
+private function f_expect_lchan_rel(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt, template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
+runs on MSC_ConnHdlr {
+ interleave {
+ [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
+ f_logp(BSCVTY, "Got RSL RR Release");
+ }
+ [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL Deact SACCH");
+ }
+ [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
+ rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
+ break;
+ }
+ }
}
-template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
- ts_MI_TMSI_LV(tmsi := f_tmsi_nri(nri_v, nri_bitlen := nri_bitlen));
+private altstep as_mgcp_ack_all_dlcx() runs on MSC_ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ var template MgcpMessage msg_dlcx := {
+ command := tr_DLCX
+ }
+ var MGCP_RecvFrom mrf;
+
+ [g_pars.aoip] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
+ MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
+ repeat;
+ }
-private function f_perform_clear(RSL_DCHAN_PT rsl) runs on MSC_ConnHdlr {
- f_logp("MSC instructs BSC to clear channel");
+ [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
+ MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
+ response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
+ }));
+ repeat;
+ }
+}
+
+private altstep as_rsl_ack_all_rel_req() runs on MSC_ConnHdlr {
+ var RslLinkId main_dcch := valueof(ts_RslLinkID_DCCH(0));
+ [] RSL.receive(tr_RSL_REL_REQ(g_chan_nr, ?)) {
+ RSL.send(ts_RSL_REL_CONF(g_chan_nr, main_dcch));
+ repeat;
+ }
+}
+
+friend function f_perform_clear(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC,
+ template PDU_ML3_NW_MS exp_rr_rel_tmpl := tr_RRM_RR_RELEASE,
+ boolean send_rel_ack := true)
+runs on MSC_ConnHdlr {
+ var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
+ var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
+ f_logp(BSCVTY, "MSC instructs BSC to clear channel");
BSSAP.send(ts_BSSMAP_ClearCommand(0));
interleave {
- [] rsl.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
- f_logp("Got RSL RR Release");
+ [] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch exp_rr_rel_tmpl)) {
+ f_logp(BSCVTY, "Got RSL RR Release");
+ }
+ [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL Deact SACCH");
}
- [] rsl.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
- f_logp("Got RSL Deact SACCH");
+ [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+ f_logp(BSCVTY, "Got BSSMAP Clear Complete");
+ /* Also drop the SCCP connection */
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ }
+ [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
+ if (send_rel_ack) {
+ rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
+ }
+ }
+ }
+ deactivate(ack_dlcx);
+ deactivate(ack_rel_req);
+}
+
+friend function f_perform_clear_no_rr_rel(RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
+runs on MSC_ConnHdlr {
+ var default ack_dlcx := activate(as_mgcp_ack_all_dlcx());
+ var default ack_rel_req := activate(as_rsl_ack_all_rel_req());
+ f_logp(BSCVTY, "MSC instructs BSC to clear channel");
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ interleave {
+ [] rsl_pt.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL Deact SACCH");
}
[] BSSAP.receive(tr_BSSMAP_ClearComplete) {
- f_logp("Got BSSMAP Clear Complete");
+ f_logp(BSCVTY, "Got BSSMAP Clear Complete");
/* Also drop the SCCP connection */
BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
}
- [] rsl.receive(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL)) {
- f_logp("Got RSL RF Chan Rel, sending Rel Ack");
- rsl.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ [] rsl_pt.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
+ rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr, PT := rsl_proc_pt);
}
}
+ deactivate(ack_dlcx);
+ deactivate(ack_rel_req);
+}
+
+friend function f_perform_clear_no_lchan()
+runs on MSC_ConnHdlr {
+ f_logp(BSCVTY, "MSC instructs BSC to clear channel");
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ f_logp(BSCVTY, "Got BSSMAP Clear Complete");
+ /* Also drop the SCCP connection */
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
}
-private function f_perform_compl_l3(RSL_DCHAN_PT rsl, template PDU_ML3_MS_NW l3_info, boolean do_clear := true)
+friend function f_perform_clear_test_ct(DchanTuple dt)
+ runs on test_CT
+{
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt);
+}
+
+private function f_perform_compl_l3(RSL_DCHAN_PT rsl_pt, RSLEM_PROC_PT rsl_proc_pt,
+ template PDU_ML3_MS_NW l3_info, boolean do_clear := true, boolean expect_bssmap_l3 := true)
runs on MSC_ConnHdlr {
timer T := 10.0;
var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(l3_info));
- f_logp("establish channel, send Complete Layer 3 Info");
+ f_logp(BSCVTY, "establish channel, send Complete Layer 3 Info");
f_create_bssmap_exp(l3_enc);
- /* RSL_Emulation.f_chan_est() on rsl:
- * This is basically code dup with s/RSL/rsl from:
+ /* RSL_Emulation.f_chan_est() on rsl_pt:
+ * This is basically code dup with s/RSL/rsl_pt from:
* RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
*/
var RSL_Message rx_rsl;
var GsmRrMessage rr;
/* request a channel to be established */
- rsl.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
+ rsl_pt.send(ts_RSLDC_ChanRqd(g_pars.ra, g_pars.fn));
/* expect immediate assignment.
- * Code dup with s/RSL/rsl from:
+ * Code dup with s/RSL/rsl_pt from:
* rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
*/
timer Tt := 10.0;
@@ -5317,10 +8633,10 @@ runs on MSC_ConnHdlr {
/* request a channel to be established */
Tt.start;
alt {
- [] rsl.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
+ [] rsl_pt.receive(tr_RSL_IMM_ASSIGN) -> value rx_rsl {
Tt.stop;
}
- [] rsl.receive {
+ [] rsl_pt.receive {
setverdict(fail, "Unexpected RSL message on DCHAN");
mtc.stop;
}
@@ -5331,41 +8647,43 @@ runs on MSC_ConnHdlr {
}
rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
- rsl.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
+ rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(g_pars.link_id), l3_enc));
- f_logp("expect BSSAP Complete Layer 3 Info at MSC");
- var template PDU_BSSAP exp_l3_compl;
- exp_l3_compl := tr_BSSMAP_ComplL3()
- if (g_pars.aoip == false) {
- exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
- } else {
- exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
- }
-
- var PDU_BSSAP bssap;
- T.start;
- alt {
- [] BSSAP.receive(exp_l3_compl) -> value bssap {
- f_logp("received expected Complete Layer 3 Info at MSC");
- log("rx exp_l3_compl = ", bssap);
- }
- [] BSSAP.receive(tr_BSSMAP_ComplL3) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
+ if (expect_bssmap_l3) {
+ f_logp(BSCVTY, "expect BSSAP Complete Layer 3 Info at MSC");
+ var template PDU_BSSAP exp_l3_compl;
+ exp_l3_compl := tr_BSSMAP_ComplL3()
+ if (g_pars.aoip == false) {
+ exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
+ } else {
+ exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
}
- [] T.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
+
+ var PDU_BSSAP bssap;
+ T.start;
+ alt {
+ [] BSSAP.receive(exp_l3_compl) -> value bssap {
+ f_logp(BSCVTY, "received expected Complete Layer 3 Info at MSC");
+ log("rx exp_l3_compl = ", bssap);
+ }
+ [] BSSAP.receive(tr_BSSMAP_ComplL3) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
+ }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
+ }
}
- }
- /* start ciphering, if requested */
- if (ispresent(g_pars.encr)) {
- f_logp("start ciphering");
- f_cipher_mode(g_pars.encr.enc_alg, g_pars.encr.enc_key);
+ /* start ciphering, if requested */
+ if (ispresent(g_pars.encr)) {
+ f_logp(BSCVTY, "start ciphering");
+ f_cipher_mode(g_pars.encr, rsl_pt := rsl_pt, rsl_proc_pt := rsl_proc_pt);
+ }
}
if (do_clear) {
- f_perform_clear(rsl);
+ f_perform_clear(rsl_pt, rsl_proc_pt);
}
setverdict(pass);
f_sleep(1.0);
@@ -5374,21 +8692,21 @@ runs on MSC_ConnHdlr {
private function f_tc_mscpool_compl_l3(charstring id) runs on MSC_ConnHdlr {
f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
if (g_pars.mscpool.rsl_idx == 0) {
- f_perform_compl_l3(RSL, g_pars.mscpool.l3_info);
+ f_perform_compl_l3(RSL, RSL_PROC, g_pars.mscpool.l3_info);
} else if (g_pars.mscpool.rsl_idx == 1) {
- f_perform_compl_l3(RSL1, g_pars.mscpool.l3_info);
+ f_perform_compl_l3(RSL1, RSL1_PROC, g_pars.mscpool.l3_info);
} else if (g_pars.mscpool.rsl_idx == 2) {
- f_perform_compl_l3(RSL2, g_pars.mscpool.l3_info);
+ f_perform_compl_l3(RSL2, RSL2_PROC, g_pars.mscpool.l3_info);
}
}
/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
private function f_tc_mscpool_L3Compl_on_1_msc(charstring id) runs on MSC_ConnHdlr {
f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
- f_perform_compl_l3(RSL, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
- f_perform_compl_l3(RSL, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
- f_perform_compl_l3(RSL, ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))) );
- f_perform_compl_l3(RSL, ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_IMSI_LV('001010000000004'H))) );
+ f_perform_compl_l3(RSL, RSL_PROC, ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O) );
+ f_perform_compl_l3(RSL, RSL_PROC, ts_CM_SERV_REQ(CM_TYPE_MO_SMS, valueof(ts_MI_IMSI_LV('001010000000002'H))) );
+ f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)) );
+ f_perform_compl_l3(RSL, RSL_PROC, ts_ML3_MO_MM_IMSI_DET_Ind(valueof(ts_MI_IMSI_LV('001010000000004'H))) );
}
testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
@@ -5403,6 +8721,7 @@ testcase TC_mscpool_L3Compl_on_1_msc() runs on test_CT {
vc_conn.done;
f_ctrs_msc_expect(0, "mscpool:subscr:new", 4);
+ f_shutdown_helper();
}
/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
@@ -5439,10 +8758,11 @@ testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
var MSC_ConnHdlr vc_conn3;
var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
pars3.mscpool.rsl_idx := 2;
- pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
+ pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(0, "mscpool:subscr:new");
+ f_shutdown_helper();
}
/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 0
@@ -5484,6 +8804,7 @@ testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
+ f_shutdown_helper();
}
/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain the NULL-NRI 1
@@ -5526,6 +8847,7 @@ testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(0, "mscpool:subscr:reattach");
+ f_shutdown_helper();
}
/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
@@ -5570,6 +8892,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(0, "mscpool:subscr:new");
+ f_shutdown_helper();
}
/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
@@ -5591,7 +8914,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin()
var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
pars1.mscpool.rsl_idx := 0;
/* An NRI that is assigned to an unconnected MSC */
- pars1.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(512))));
+ pars1.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(512)));
vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
vc_conn1.done;
f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
@@ -5620,6 +8943,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin()
f_ctrs_msc_add(2, "mscpool:subscr:attach_lost");
f_ctrs_msc_add(0, "mscpool:subscr:new");
f_ctrs_msc_verify();
+ f_shutdown_helper();
}
/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
@@ -5650,7 +8974,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
pars2.mscpool.rsl_idx := 1;
/* An NRI of the second MSC's range (256-511) */
- pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(260))));
+ pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(260)));
vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
vc_conn2.done;
f_ctrs_msc_expect(1, "mscpool:subscr:known");
@@ -5663,6 +8987,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(1, "mscpool:subscr:known");
+ f_shutdown_helper();
}
/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-bsc.cfg),
@@ -5693,7 +9018,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 2);
pars2.mscpool.rsl_idx := 1;
/* An NRI of the third MSC's range (512-767) */
- pars2.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(678))));
+ pars2.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_TMSI_NRI_LV(678)));
vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
vc_conn2.done;
f_ctrs_msc_expect(2, "mscpool:subscr:known");
@@ -5706,6 +9031,7 @@ testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(1, "mscpool:subscr:new");
+ f_shutdown_helper();
}
/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
@@ -5739,6 +9065,7 @@ testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
vc_conn2.done;
f_ctrs_msc_expect(2, "mscpool:subscr:known");
+ f_shutdown_helper();
}
/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
@@ -5767,8 +9094,7 @@ private function f_tc_mscpool_paging_imsi(charstring id) runs on MSC_ConnHdlr {
/* Despite the round robin pointing at the second MSC ('roundrobin next 1'), the earlier Paging for the same IMSI
* causes this Paging Response to go to the first MSC (bssap_idx := 0). */
- f_perform_compl_l3(RSL, ts_PAG_RESP(valueof(ts_MI_IMSI_LV(imsi))) );
- setverdict(pass);
+ f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(imsi)) );
f_sleep(1.0);
}
testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
@@ -5789,6 +9115,7 @@ testcase TC_mscpool_paging_and_response_imsi() runs on test_CT {
vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_imsi), pars1);
vc_conn1.done;
f_ctrs_msc_expect(0, "mscpool:subscr:paged");
+ f_shutdown_helper();
}
/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
@@ -5799,7 +9126,7 @@ private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
var RSL_ChanNeeded rsl_chneed := RSL_CHANNEED_SDCCH;
var template BSSMAP_IE_ChannelNeeded bssmap_chneed := ts_BSSMAP_IE_ChanNeeded(int2bit(enum2int(valueof(rsl_chneed)),2));
var integer nri_v := 300; /* <-- second MSC's NRI */
- var octetstring tmsi := f_tmsi_nri(nri_v);
+ var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
var BSSAP_N_UNITDATA_req paging;
f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
@@ -5819,8 +9146,7 @@ private function f_tc_mscpool_paging_tmsi(charstring id) runs on MSC_ConnHdlr {
/* Despite the NRI matching the second MSC (NRI from 'msc 1' in osmo-bsc.cfg) and round robin pointing at the
* third MSC ('roundrobin next 2'), the earlier Paging for the same TMSI causes this Paging Response to go to
* the first MSC (bssap_idx := 0). */
- f_perform_compl_l3(RSL, ts_PAG_RESP(valueof(ts_MI_TMSI_NRI_LV(nri_v))) );
- setverdict(pass);
+ f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_TMSI_NRI_LV(nri_v)) );
f_sleep(1.0);
}
testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
@@ -5841,6 +9167,7 @@ testcase TC_mscpool_paging_and_response_tmsi() runs on test_CT {
vc_conn1 := f_start_handler(refers(f_tc_mscpool_paging_tmsi), pars1);
vc_conn1.done;
f_ctrs_msc_expect(0, "mscpool:subscr:paged");
+ f_shutdown_helper();
}
/* For round-robin, skip an MSC that has 'no allow-attach' set. */
@@ -5850,17 +9177,13 @@ testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
f_sleep(1.0);
+ /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
+ f_vty_msc_allow_attach(BSCVTY, {true, false, true});
/* Control which MSC gets chosen next by the round-robin, otherwise
* would be randomly affected by which other tests ran before this. */
f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
- /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
- f_vty_enter_cfg_msc(BSCVTY, 1);
- f_vty_transceive(BSCVTY, "no allow-attach");
- f_vty_transceive(BSCVTY, "exit");
- f_vty_transceive(BSCVTY, "exit");
-
f_ctrs_msc_init();
var MSC_ConnHdlr vc_conn1;
@@ -5882,15 +9205,11 @@ testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
var MSC_ConnHdlr vc_conn3;
var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 0);
pars3.mscpool.rsl_idx := 2;
- pars3.mscpool.l3_info := valueof(ts_PAG_RESP(valueof(ts_MI_IMSI_LV('001010000000003'H))));
+ pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(0, "mscpool:subscr:new");
-
- f_vty_enter_cfg_msc(BSCVTY, 1);
- f_vty_transceive(BSCVTY, "allow-attach");
- f_vty_transceive(BSCVTY, "exit");
- f_vty_transceive(BSCVTY, "exit");
+ f_shutdown_helper();
}
/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
@@ -5900,16 +9219,13 @@ testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
f_init(nr_bts := 3, handler_mode := true, nr_msc := 3);
f_sleep(1.0);
+ /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
+ f_vty_msc_allow_attach(BSCVTY, {true, false, true});
+
/* Control which MSC gets chosen next by the round-robin, otherwise
* would be randomly affected by which other tests ran before this. */
f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
- /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
- f_vty_enter_cfg_msc(BSCVTY, 1);
- f_vty_transceive(BSCVTY, "no allow-attach");
- f_vty_transceive(BSCVTY, "exit");
- f_vty_transceive(BSCVTY, "exit");
-
f_ctrs_msc_init();
/* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
@@ -5937,13 +9253,1714 @@ testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
vc_conn3.done;
f_ctrs_msc_expect(2, "mscpool:subscr:new");
+ f_shutdown_helper();
+}
+
+/* When an MSC point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the MSC as unusable. */
+testcase TC_mscpool_sccp_n_pcstate_detaches_msc() runs on test_CT {
+
+ f_init(nr_bts := 3, handler_mode := true, nr_msc := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
+
+ f_ctrs_msc_init();
- f_vty_enter_cfg_msc(BSCVTY, 1);
- f_vty_transceive(BSCVTY, "allow-attach");
+ var MSC_ConnHdlr vc_conn1;
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
+ pars1.mscpool.rsl_idx := 0;
+ pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000000001'H)), '00F110'O));
+ vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
+ vc_conn1.done;
+ f_ctrs_msc_expect(0, "mscpool:subscr:new");
+
+ var MSC_ConnHdlr vc_conn2;
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 1);
+ pars2.mscpool.rsl_idx := 1;
+ pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010000000002'H))));
+ vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
+ vc_conn2.done;
+ f_ctrs_msc_expect(1, "mscpool:subscr:new");
+
+ f_logp(BSCVTY, "disconnecting msc0");
+ f_bssap_idx_disconnect(0);
+
+ /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to msc
+ * 2 again. */
+ var MSC_ConnHdlr vc_conn3;
+ var TestHdlrParams pars3 := f_gen_test_hdlr_pars(bssap_idx := 1);
+ pars3.mscpool.rsl_idx := 2;
+ pars3.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010000000003'H)));
+ vc_conn3 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars3);
+ vc_conn3.done;
+ f_ctrs_msc_expect(1, "mscpool:subscr:new");
+ f_shutdown_helper();
+}
+
+/* When an MSC point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
+ * MSC. */
+testcase TC_mscpool_sccp_n_pcstate_attaches_msc() runs on test_CT {
+
+ f_init(nr_bts := 3, handler_mode := true, nr_msc := 1);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_transceive(BSCVTY, "mscpool roundrobin next 0");
+
+ f_ctrs_msc_init();
+
+ /* There is only one MSC, round robin stays on msc0 */
+ var MSC_ConnHdlr vc_conn1;
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars(bssap_idx := 0);
+ pars1.mscpool.rsl_idx := 0;
+ pars1.mscpool.l3_info := valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('0010100230000001'H)), '00F110'O));
+ vc_conn1 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars1);
+ vc_conn1.done;
+ f_ctrs_msc_expect(0, "mscpool:subscr:new");
+
+ var MSC_ConnHdlr vc_conn2;
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars(bssap_idx := 0);
+ pars2.mscpool.rsl_idx := 1;
+ pars2.mscpool.l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV('001010023000002'H))));
+ vc_conn2 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars2);
+ vc_conn2.done;
+ f_ctrs_msc_expect(0, "mscpool:subscr:new");
+
+ f_logp(BSCVTY, "connecting msc1");
+ f_vty_msc_allow_attach(BSCVTY, { true, true });
+ f_bssap_idx_init(1);
+ f_sleep(1.0);
+
+ /* This time round-robin wraps to the second MSC, because it is now online. */
+ var MSC_ConnHdlr vc_conn4;
+ var TestHdlrParams pars4 := f_gen_test_hdlr_pars(bssap_idx := 1);
+ pars4.mscpool.rsl_idx := 2;
+ pars4.mscpool.l3_info := valueof(ts_PAG_RESP(ts_MI_IMSI_LV('001010023000003'H)));
+ vc_conn4 := f_start_handler(refers(f_tc_mscpool_compl_l3), pars4);
+ vc_conn4.done;
+ f_ctrs_msc_expect(1, "mscpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* Allow/Deny emergency calls globally via VTY */
+private function f_vty_allow_emerg_msc(boolean allow) runs on test_CT {
+ f_vty_enter_cfg_msc(BSCVTY, 0);
+ if (allow) {
+ f_vty_transceive(BSCVTY, "allow-emergency allow");
+ } else {
+ f_vty_transceive(BSCVTY, "allow-emergency deny");
+ }
f_vty_transceive(BSCVTY, "exit");
f_vty_transceive(BSCVTY, "exit");
}
+/* Allow/Deny emergency calls per BTS via VTY */
+private function f_vty_allow_emerg_bts(boolean allow, integer bts_nr) runs on test_CT {
+ f_vty_enter_cfg_bts(BSCVTY, bts_nr);
+ if (allow) {
+ f_vty_transceive(BSCVTY, "rach emergency call allowed 1");
+ } else {
+ f_vty_transceive(BSCVTY, "rach emergency call allowed 0");
+ }
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+}
+
+/* Allow/Forbid Fast Return after SRVCC on a given BTS via VTY */
+private function f_vty_allow_srvcc_fast_return(boolean allow, integer bts_nr) runs on test_CT {
+ f_vty_enter_cfg_bts(BSCVTY, bts_nr);
+ if (allow) {
+ f_vty_transceive(BSCVTY, "srvcc fast-return allow");
+ } else {
+ f_vty_transceive(BSCVTY, "srvcc fast-return forbid");
+ }
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+}
+
+/* Allow/Forbid TCH for signalling if SDCCH exhausted on a given BTS via VTY */
+private function f_vty_allow_tch_for_signalling(boolean allow, integer bts_nr) runs on test_CT {
+ f_vty_enter_cfg_bts(BSCVTY, bts_nr);
+ if (allow) {
+ f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 1");
+ } else {
+ f_vty_transceive(BSCVTY, "channel allocator allow-tch-for-signalling 0");
+ }
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+}
+
+/* Begin assignment procedure and send an EMERGENCY SETUP (RR) */
+private function f_assignment_emerg_setup() runs on MSC_ConnHdlr {
+ var PDU_ML3_MS_NW emerg_setup;
+ var octetstring emerg_setup_enc;
+ var RSL_Message emerg_setup_data_ind;
+
+ f_establish_fully(omit, omit);
+
+ emerg_setup := valueof(ts_ML3_MO_CC_EMERG_SETUP(1, valueof(ts_Bcap_voice)));
+ emerg_setup_enc := enc_PDU_ML3_MS_NW(emerg_setup);
+ emerg_setup_data_ind := valueof(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), emerg_setup_enc));
+
+ RSL.send(emerg_setup_data_ind);
+}
+
+/* expect EmergencySetup on BSSAP after calling f_assignment_emerg_setup() */
+private function f_assignment_emerg_setup_exp_bssap()
+runs on MSC_ConnHdlr {
+ var PDU_BSSAP emerg_setup_data_ind_bssap;
+ var PDU_ML3_MS_NW emerg_setup;
+ timer T := 3.0;
+
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSAP_DTAP) -> value emerg_setup_data_ind_bssap {
+ emerg_setup := dec_PDU_ML3_MS_NW(emerg_setup_data_ind_bssap.pdu.dtap);
+ if (not isbound(emerg_setup.msgs.cc.emergencySetup)) {
+ setverdict(fail, "no emergency setup");
+ }
+ }
+ [] BSSAP.receive {
+ setverdict(fail, "unexpected BSSAP message!");
+ }
+ [] T.timeout {
+ setverdict(fail, "timout waiting for EMERGENCY SETUP!");
+ }
+ }
+}
+
+private function f_assignment_emerg_setup_voice()
+runs on MSC_ConnHdlr {
+ /* Go on with voice call assignment */
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ /* Below speechOrDataIndicator and codecList are copied from an emergency call captured during tests.
+ * They seem a bit weird (AMR-WB, and the order differ between speechId_DataIndicator and the codecList), but
+ * seems a good idea to see how osmo-bsc reacts to this. */
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := {
+ elementIdentifier := '0B'O, /* overwritten */
+ lengthIndicator := 0, /* overwritten */
+ speechOrDataIndicator := '0001'B, /* speech */
+ spare1_4 := '0000'B,
+ channelRateAndType := ChRate_TCHForH_Fpref,
+ speechId_DataIndicator := 'c2918105'O
+ };
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({
+ ts_CodecHR, ts_CodecAMR_WB, ts_CodecEFR, ts_CodecFR}));
+
+ f_rslem_dchan_queue_enable();
+
+ var ExpectCriteria mgcpcrit := {
+ connid := omit,
+ endpoint := omit,
+ transid := omit
+ };
+ f_create_mgcp_expect(mgcpcrit);
+
+ BSSAP.send(ass_cmd);
+
+ var AssignmentState st := valueof(ts_AssignmentStateInit);
+ st.rtp_stream := true;
+ st.is_assignment := false;
+ alt {
+ [] as_modify(st);
+ [] as_Media();
+ [st.modify_done] BSSAP.receive(exp_compl) {
+ setverdict(pass);
+ }
+ }
+
+ /* Voice call carries on ... */
+ f_sleep(2.0);
+}
+
+/* Test if the EMERGENCY SETUP gets passed on to the MSC via A when EMERGENCY
+ * CALLS are permitted by the BSC config. */
+private function f_TC_assignment_emerg_setup_allow(charstring id) runs on MSC_ConnHdlr {
+
+ /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
+ * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
+ * another lchan. */
+ g_pars.ra := f_rnd_ra_emerg();
+ f_assignment_emerg_setup();
+ f_assignment_emerg_setup_exp_bssap();
+ f_assignment_emerg_setup_voice();
+
+ setverdict(pass);
+ f_perform_clear();
+}
+
+/* Test if the EMERGENCY SETUP gets blocked by the BSC if EMERGENCY CALLS are
+ * forbidden by the BSC config. */
+private function f_TC_assignment_emerg_setup_deny(charstring id) runs on MSC_ConnHdlr {
+ var PDU_BSSAP emerg_setup_data_ind_bssap;
+ timer T := 3.0;
+
+ f_assignment_emerg_setup();
+
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
+ setverdict(pass);
+ }
+ [] RSL.receive {
+ setverdict(fail, "unexpected RSL message!");
+ }
+ [] T.timeout {
+ setverdict(fail, "timout waiting for RR CHANNEL RELEASE!");
+ }
+ }
+ BSSAP.receive(tr_BSSMAP_ClearRequest);
+ f_perform_clear_no_rr_rel();
+}
+
+/* EMERGENCY CALL situation #1, allowed globally and by BTS */
+testcase TC_assignment_emerg_setup_allow() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+ vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Test MO emergency call using MobileIdentity=IMEI (possible for emergency
+ * calls from phones without SIM card).
+ * 3GPP TS 24.008 section 10.5.1.4, OS#5849 */
+testcase TC_assignment_emerg_setup_allow_imei() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ /* Remove IMSI set by f_gen_test_hdlr_pars(), then IMEI will be used to place the call */
+ pars.imsi := omit;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+ vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_allow), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* EMERGENCY CALL situation #2, forbidden globally but allowed by BTS */
+testcase TC_assignment_emerg_setup_deny_msc() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_vty_allow_emerg_msc(false);
+ f_vty_allow_emerg_bts(true, 0);
+ /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx): */
+ pars.ra := f_rnd_ra_emerg();
+ vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* EMERGENCY CALL situation #3, allowed globally but forbidden by BTS.
+ * The RACH req (and hence CHAN RQD) indicate other than emergency call.
+ * Hence BSC only learns about it being an emergency call later during call setup.
+ * If interested in the ra="emergency call" + deny bts policy case,
+ * see TC_chan_rqd_emerg_deny.
+ */
+testcase TC_assignment_emerg_setup_deny_bts() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ /* Note: This simulates a spec violation by the MS, correct MS
+ * implementations would not try to establish an emergency call because
+ * the system information tells in advance that emergency calls are
+ * not allowed */
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(false, 0);
+ /* Note: Here we implicitly leave default g_pars.ra which is different than "emergency call" */
+ vc_conn := f_start_handler(refers(f_TC_assignment_emerg_setup_deny), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Test what happens when an emergency call arrives while all TCH channels are
+ * busy, the BSC is expected to terminate one call in favor of the incoming
+ * emergency call */
+testcase TC_emerg_premption() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+ var RSL_Message rx_rsl;
+ var octetstring l3_payload := gen_l3_valid_payload();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+
+ /* Fill up all channels on the BTS */
+ chreq_total := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total");
+ chreq_nochan := f_ctrl_get_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:no_channel");
+ for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS; i := i+1) {
+ f_chreq_act_ack('33'O, i);
+ }
+ IPA_RSL[0][0].clear;
+ f_ctrl_get_exp_ratectr_abs(IPA_CTRL, "bts", 0, "chreq:total",
+ chreq_total + NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS + NUM_SDCCH_PER_BTS);
+
+ /* Send EST IND for the first TCH, so we get to test the RR release cause */
+ var RslChannelNr first_tch := valueof(t_RslChanNr_Bm(1));
+ f_ipa_tx(ts_RSL_EST_IND(first_tch, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ /* Accept BSSAP conn, so we get to test the Clear Request cause */
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ var integer sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ /* Send Channel request for emegergency call */
+ f_ipa_tx(ts_RSL_CHAN_RQD('A5'O, 23));
+
+ /* Expect the BSC to release one (the first) TCH/F on the BTS */
+ f_expect_chan_rel(first_tch, expect_rr_chan_rel := true, expect_rll_rel_req := false,
+ expect_rr_cause := GSM48_RR_CAUSE_PREMPTIVE_REL);
+
+ /* Also expect a BSSMAP Clear Request with PREEMPTION */
+ var BSSAP_N_DATA_ind rx_clear_req;
+ const myBSSMAP_Cause preemption := GSM0808_CAUSE_PREEMPTION;
+ BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearRequest)) -> value rx_clear_req;
+ log("XXX ", rx_clear_req);
+ if (rx_clear_req.userData.pdu.bssmap.clearRequest.cause.causeValue != int2bit(enum2int(preemption), 7)) {
+ setverdict(fail, "BSSMAP Clear Request: expected cause PREEMPTION");
+ }
+
+ /* Expect the BSC to send activate/assign the channel for the emergency call */
+ rx_rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ if (first_tch != rx_rsl.ies[0].body.chan_nr) {
+ setverdict(fail, "different TCH lchan activated than expected");
+ }
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(first_tch, 33));
+ rx_rsl := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+
+ /* complete the BSSMAP Clear to satisfy the conn leak check */
+ BSSAP.send(ts_BSSAP_DATA_req(sccp_conn_id, ts_BSSMAP_ClearCommand(enum2int(preemption))));
+ BSSAP.receive(tr_BSSAP_DATA_ind(sccp_conn_id, tr_BSSMAP_ClearComplete)) {
+ BSSAP.send(ts_BSSAP_DISC_req(sccp_conn_id, 0));
+ }
+
+ f_shutdown_helper();
+}
+
+/* Hopping parameters per a timeslot */
+private type record length(0..64) of GsmArfcn ArfcnList;
+private type record FHParamsTs {
+ boolean enabled,
+ uint6_t hsn,
+ uint6_t maio,
+ ArfcnList ma
+};
+
+/* Hopping parameters per a transceiver */
+private type record FHParamsTrx {
+ GsmBandArfcn arfcn,
+ FHParamsTs ts[8]
+};
+
+/* Randomly generate the hopping parameters for the given timeslot numbers */
+private function f_TC_fh_params_gen(template integer tr_tn := (1, 3, 5))
+runs on test_CT return FHParamsTrx {
+ var FHParamsTrx fhp;
+
+ /* Generate a random ARFCN in the range of 0 - 3. This ARFCN will
+ * fall in the GSM900 band. */
+ fhp.arfcn.arfcn := f_rnd_int(3);
+ fhp.arfcn.pcs := false;
+
+ for (var integer tn := 0; tn < 8; tn := tn + 1) {
+ if (not match(tn, tr_tn)) {
+ fhp.ts[tn].enabled := false;
+ fhp.ts[tn].ma := { };
+ continue;
+ }
+
+ /* Random HSN / MAIO values: 0..63 */
+ fhp.ts[tn].hsn := f_rnd_int(64);
+ fhp.ts[tn].maio := f_rnd_int(64);
+ fhp.ts[tn].ma := { };
+
+ /* Random Mobile Allocation (hopping channels) */
+ var integer ma_len := 2 + f_rnd_int(9); /* 2..10 channels */
+ var integer step := 3 + f_rnd_int(4); /* 3..6 stepping */
+ for (var integer i := 1; i <= ma_len; i := i + 1) {
+ fhp.ts[tn].ma := fhp.ts[tn].ma & { i * step };
+ }
+
+ fhp.ts[tn].enabled := true;
+ }
+
+ log("f_TC_fh_params_gen(): ", fhp);
+ return fhp;
+}
+
+/* Make sure that the given Channel Description IE matches the hopping configuration */
+private function f_TC_fh_params_match_chan_desc(in FHParamsTrx fhp, in ChannelDescription cd)
+{
+ var template (present) ChannelDescription tr_cd;
+ var template (present) MaioHsn tr_maio_hsn;
+ var uint3_t tn := cd.chan_nr.tn;
+
+ if (fhp.ts[tn].enabled) {
+ tr_maio_hsn := tr_HsnMaio(fhp.ts[tn].hsn, fhp.ts[tn].maio);
+ tr_cd := tr_ChanDescH1(cd.chan_nr, tr_maio_hsn);
+ } else {
+ tr_cd := tr_ChanDescH0(cd.chan_nr, fhp.arfcn.arfcn);
+ }
+
+ if (not match(cd, tr_cd)) {
+ setverdict(fail, "Channel Description IE does not match: ",
+ cd, " vs expected ", tr_cd);
+ }
+}
+
+/* Make sure that the given Mobile Allocation IE matches the hopping configuration */
+private function f_TC_fh_params_match_ma(in FHParamsTrx fhp, uint3_t tn,
+ in MobileAllocationLV ma)
+{
+ var template MobileAllocationLV tr_ma := f_TC_fh_params_gen_tr_ma(fhp, tn, ma);
+
+ if (not match(ma, tr_ma)) {
+ setverdict(fail, "Mobile Allocation IE does not match (tn := ",
+ tn, "): ", ma, " vs expected: ", tr_ma);
+ } else {
+ setverdict(pass);
+ }
+}
+
+private function f_TC_fh_params_gen_tr_ma(in FHParamsTrx fhp, uint3_t tn,
+ in MobileAllocationLV ma)
+return template MobileAllocationLV {
+ /* Mobile Allocation IE is expected to be empty if hopping is not enabled */
+ if (not fhp.ts[tn].enabled) {
+ return { len := 0, ma := ''B };
+ }
+
+ var bitstring full_mask := f_pad_bit(''B, 1024, '0'B);
+ var bitstring slot_mask := f_pad_bit(''B, 1024, '0'B);
+ var bitstring ma_mask := ''B;
+
+ /* Compose the full bit-mask (all channels, up to 1024 entries) */
+ for (var integer i := 0; i < lengthof(fhp.ts); i := i + 1) {
+ for (var integer j := 0; j < lengthof(fhp.ts[i].ma); j := j + 1) {
+ if (full_mask[fhp.ts[i].ma[j]] == '1'B)
+ { continue; }
+ full_mask[fhp.ts[i].ma[j]] := '1'B;
+ }
+ }
+
+ /* Take ARFCN of the TRX itself into account */
+ full_mask[fhp.arfcn.arfcn] := '1'B;
+
+ /* Compose a bit-mask for the given timeslot number */
+ for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
+ slot_mask[fhp.ts[tn].ma[i]] := '1'B;
+ }
+
+ /* Finally, compose the Mobile Allocation bit-mask */
+ for (var integer i := 1; i < lengthof(full_mask); i := i + 1) {
+ if (full_mask[i] != '1'B)
+ { continue; }
+
+ /* FIXME: ma_mask := ma_mask & slot_mask[i]; // triggers a bug in TITAN */
+ if (slot_mask[i] == '1'B) {
+ ma_mask := ma_mask & '1'B;
+ } else {
+ ma_mask := ma_mask & '0'B;
+ }
+ }
+
+ /* ARFCN 0 (if present) goes to the last position of the bit-mask */
+ if (full_mask[0] == '1'B) {
+ /* FIXME: ma_mask := ma_mask & slot_mask[0]; // triggers a bug in TITAN */
+ if (slot_mask[0] == '1'B) {
+ ma_mask := ma_mask & '1'B;
+ } else {
+ ma_mask := ma_mask & '0'B;
+ }
+ }
+
+ /* Ensure that ma_mask is octet-aligned */
+ var integer ma_mask_len := (lengthof(ma_mask) + 8 - 1) / 8;
+ ma_mask := f_pad_bit(ma_mask, ma_mask_len * 8, '0'B);
+
+ return { len := ma_mask_len, ma := ma_mask };
+}
+
+/* Configure the appropriate band for a given arfcn, exc */
+private function f_TC_set_band_by_arfcn(integer bts_nr, GsmBandArfcn arfcn) runs on test_CT
+{
+ var charstring band;
+ var GsmBandArfcn arfcn_ := valueof(ts_GsmBandArfcn(arfcn.arfcn, arfcn.pcs, false));
+
+ select (arfcn_) {
+ case (tr_GsmBandArfcn((259..293), false, ?)) { band := "GSM450"; }
+ case (tr_GsmBandArfcn((306..340), false, ?)) { band := "GSM480"; }
+ case (tr_GsmBandArfcn((438..511), false, ?)) { band := "GSM750"; }
+ case (tr_GsmBandArfcn((128..251), false, ?)) { band := "GSM850"; }
+ case (tr_GsmBandArfcn((0..124), false, ?)) { band := "GSM900"; }
+ case (tr_GsmBandArfcn((955..1023), false, ?)) { band := "GSM900"; }
+ case (tr_GsmBandArfcn((512..885), false, ?)) { band := "DCS1800"; }
+ case (tr_GsmBandArfcn((512..810), true, ?)) { band := "PCS1900"; }
+ case else { return; }
+ }
+
+ f_vty_enter_cfg_bts(BSCVTY, bts_nr);
+ f_vty_transceive(BSCVTY, "band " & band);
+ f_vty_transceive(BSCVTY, "end");
+}
+
+/* Configure the hopping parameters in accordance with the given record */
+private function f_TC_fh_params_set(in FHParamsTrx fhp,
+ uint8_t bts_nr := 0,
+ uint8_t trx_nr := 0)
+runs on test_CT {
+
+ f_TC_set_band_by_arfcn(bts_nr, fhp.arfcn);
+
+ /* Enter the configuration node for the given BTS/TRX numbers */
+ f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
+
+ f_vty_transceive(BSCVTY, "arfcn " & int2str(fhp.arfcn.arfcn));
+
+ for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
+ f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
+
+ if (not fhp.ts[tn].enabled) {
+ f_vty_transceive(BSCVTY, "hopping enabled 0");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+ continue;
+ }
+
+ /* Configure HSN / MAIO values */
+ f_vty_transceive(BSCVTY, "hopping sequence-number " & int2str(fhp.ts[tn].hsn));
+ f_vty_transceive(BSCVTY, "hopping maio " & int2str(fhp.ts[tn].maio));
+
+ /* Configure the Mobile Allocation (hopping channels) */
+ for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
+ f_vty_transceive(BSCVTY, "hopping arfcn add " & int2str(fhp.ts[tn].ma[i]));
+ }
+
+ f_vty_transceive(BSCVTY, "hopping enabled 1");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+ }
+
+ f_vty_transceive(BSCVTY, "end");
+}
+
+/* Disable frequency hopping on all timeslots */
+private function f_TC_fh_params_unset(in FHParamsTrx fhp,
+ uint8_t bts_nr := 0,
+ uint8_t trx_nr := 0,
+ GsmBandArfcn arfcn := {pcs := false, arfcn := 871})
+runs on test_CT {
+
+ f_TC_set_band_by_arfcn(bts_nr, arfcn);
+
+ /* Enter the configuration node for the given BTS/TRX numbers */
+ f_vty_enter_cfg_trx(BSCVTY, bts_nr, trx_nr);
+
+ f_vty_transceive(BSCVTY, "arfcn " & int2str(arfcn.arfcn));
+
+ for (var integer tn := 0; tn < lengthof(fhp.ts); tn := tn + 1) {
+ f_vty_transceive(BSCVTY, "timeslot " & int2str(tn));
+
+ /* Delete all ARFCNs from the Mobile Allocation (if any) */
+ for (var integer i := 0; i < lengthof(fhp.ts[tn].ma); i := i + 1) {
+ f_vty_transceive(BSCVTY, "hopping arfcn del " & int2str(fhp.ts[tn].ma[i]));
+ }
+
+ f_vty_transceive(BSCVTY, "hopping enabled 0");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+ }
+
+ f_vty_transceive(BSCVTY, "end");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+}
+
+/* Verify presence and correctness of the hopping parameters (HSN, MAIO)
+ * in the Channel Identification IE of the RSL CHANnel ACTIVation message. */
+testcase TC_fh_params_chan_activ() runs on test_CT {
+ var FHParamsTrx fhp := f_TC_fh_params_gen();
+ var RSL_Message rsl_msg;
+ var RSL_IE_Body ie;
+
+ f_init_vty();
+
+ f_TC_fh_params_set(fhp); /* Enable frequency hopping */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1);
+
+ /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
+ for (var integer i := 0; i < 9; i := i + 1) {
+ f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+ /* Make sure that Channel Identification IE is present */
+ if (not f_rsl_find_ie(rsl_msg, RSL_IE_CHAN_IDENT, ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ continue;
+ }
+
+ /* Make sure that hopping parameters (HSN/MAIO) match */
+ f_TC_fh_params_match_chan_desc(fhp, ie.chan_ident.ch_desc.v);
+
+ /* "Mobile Allocation shall be included but empty" - let's check this */
+ if (ie.chan_ident.ma.v.len != 0) {
+ setverdict(fail, "Mobile Allocation IE is not empty: ",
+ ie.chan_ident.ma, ", despite it shall be");
+ continue;
+ }
+ }
+
+ /* Disable frequency hopping */
+ f_TC_fh_params_unset(fhp);
+
+ f_shutdown_helper();
+}
+
+/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Immediate Assignment */
+testcase TC_fh_params_imm_ass() runs on test_CT {
+ var FHParamsTrx fhp := f_TC_fh_params_gen();
+ var RSL_Message rsl_msg;
+ var RSL_IE_Body ie;
+
+ f_init_vty();
+
+ f_TC_fh_params_set(fhp); /* Enable frequency hopping */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1);
+
+ /* CS domain: 3 (SDCCH/4+CBCH) + 4 (TCH/F) + 2 (TCH/H) channels available */
+ for (var integer i := 0; i < 9; i := i + 1) {
+ f_ipa_tx(ts_RSL_CHAN_RQD(f_rnd_ra_cs(), 23));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeC(RSL_MT_IMMEDIATE_ASSIGN_CMD));
+
+ /* Make sure that Full Immediate Assign Info IE is present */
+ if (not f_rsl_find_ie(rsl_msg, RSL_IE_FULL_IMM_ASS_INFO, ie)) {
+ setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
+ continue;
+ }
+
+ /* Decode the actual Immediate Assignment message */
+ var GsmRrMessage rr_msg := dec_GsmRrMessage(ie.full_imm_ass_info.payload);
+ if (not match(rr_msg.header, t_RrHeader(IMMEDIATE_ASSIGNMENT, ?))) {
+ setverdict(fail, "Failed to match Immediate Assignment: ", rr_msg);
+ continue;
+ }
+
+ /* Make sure that hopping parameters (HSN/MAIO) match */
+ f_TC_fh_params_match_chan_desc(fhp, rr_msg.payload.imm_ass.chan_desc);
+
+ /* Make sure that the Mobile Allocation IE matches */
+ f_TC_fh_params_match_ma(fhp, rr_msg.payload.imm_ass.chan_desc.chan_nr.tn,
+ rr_msg.payload.imm_ass.mobile_allocation);
+ }
+
+ /* Disable frequency hopping */
+ f_TC_fh_params_unset(fhp);
+
+ f_shutdown_helper();
+}
+
+/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Assignment Command */
+testcase TC_fh_params_assignment_cmd() runs on test_CT {
+ var FHParamsTrx fhp := f_TC_fh_params_gen();
+ var RSL_Message rsl_msg;
+ var RSL_IE_Body ie;
+
+ f_init_vty();
+
+ f_TC_fh_params_set(fhp); /* Enable frequency hopping */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1);
+
+ /* HACK: work around "Couldn't find Expect for CRCX" */
+ vc_MGCP[0].stop;
+
+ var template PDU_BSSAP ass_cmd := f_gen_ass_req();
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := ts_BSSMAP_IE_CodecList({ts_CodecFR});
+
+ /* CS domain (TCH): 4 (TCH/F) + 2 (TCH/H) channels available
+ * NOTE: only 3 SDCCH/4 channels are available on CCCH+SDCCH4+CBCH */
+ for (var integer i := 0; i < 3; i := i + 1) {
+ /* Establish a dedicated channel, so we can trigger (late) TCH assignment */
+ var DchanTuple dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+
+ /* Send a BSSMAP Assignment Command, expect CHANnel ACTIVation */
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+ /* ACKnowledge CHANnel ACTIVation, expect RSL DATA REQuest */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33));
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
+
+ /* Make sure that L3 Information IE is present */
+ if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
+ setverdict(fail, "RSL L3 Information IE is absent");
+ continue;
+ }
+
+ /* Decode the L3 message and make sure it is (RR) Assignment Command */
+ var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
+ if (not match(l3_msg.header, t_RrL3Header(ASSIGNMENT_COMMAND))) {
+ setverdict(fail, "Failed to match Assignment Command: ", l3_msg);
+ continue;
+ }
+
+ /* Make sure that hopping parameters (HSN/MAIO) match */
+ var ChannelDescription chan_desc := l3_msg.payload.ass_cmd.chan_desc;
+ f_TC_fh_params_match_chan_desc(fhp, chan_desc);
+
+ /* Make sure that Cell Channel Description IE is present if FH is enabled */
+ if (chan_desc.h and not ispresent(l3_msg.payload.ass_cmd.cell_chan_desc)) {
+ setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
+ continue;
+ }
+
+ /* Make sure that the Mobile Allocation IE matches (if present) */
+ var boolean ma_present := ispresent(l3_msg.payload.ass_cmd.mobile_allocation);
+ if (chan_desc.h and ma_present) {
+ f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
+ l3_msg.payload.ass_cmd.mobile_allocation.v);
+ } else if (chan_desc.h and not ma_present) {
+ setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
+ continue;
+ } else if (not chan_desc.h and ma_present) {
+ setverdict(fail, "FH disabled, but Mobile Allocation IE is present");
+ continue;
+ }
+
+ f_perform_clear_test_ct(dt);
+ }
+
+ /* Give the IUT some time to release all channels */
+ f_sleep(3.0);
+
+ /* Disable frequency hopping */
+ f_TC_fh_params_unset(fhp);
+
+ f_shutdown_helper();
+}
+
+/* Verify the hopping parameters (HSN, MAIO, MA) in (RR) Handover Command */
+private function f_TC_fh_params_handover_cmd(in FHParamsTrx fhp)
+runs on test_CT {
+ var RSL_Message rsl_msg;
+ var RSL_IE_Body ie;
+ var DchanTuple dt;
+
+ /* Establish a dedicated channel, so we can trigger handover */
+ dt := f_est_dchan(f_rnd_ra_cs(), 23, gen_l3_valid_payload());
+ f_sleep(0.5);
+
+ /* Trigger handover from BTS0 to BTS1 */
+ f_bts_0_cfg(BSCVTY, { "neighbor bts 1" });
+ f_vty_handover(BSCVTY, 0, 0, dt.rsl_chan_nr, 1);
+
+ /* Expect RSL CHANnel ACTIVation on BTS1/TRX0/TS1 */
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx := {1, 0});
+
+ /* ACKnowledge channel activation and expect (RR) Handover Command */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(rsl_msg.ies[0].body.chan_nr, 33), idx := {1, 0});
+ rsl_msg := f_exp_ipa_rx(tr_RSL_MsgTypeR(RSL_MT_DATA_REQ));
+
+ /* Make sure that L3 Information IE is present */
+ if (not f_rsl_find_ie(rsl_msg, RSL_IE_L3_INFO, ie)) {
+ setverdict(fail, "RSL L3 Information IE is absent");
+ return;
+ }
+
+ /* Decode the L3 message and make sure it is (RR) Handover Command */
+ var GsmRrL3Message l3_msg := dec_GsmRrL3Message(ie.l3_info.payload);
+ if (not match(l3_msg.header, t_RrL3Header(HANDOVER_COMMAND))) {
+ setverdict(fail, "Failed to match Handover Command: ", l3_msg);
+ return;
+ }
+
+ /* Make sure that we've got SDCCH/8 on TS1 (expected to be hopping) */
+ var ChannelDescription chan_desc := l3_msg.payload.ho_cmd.chan_desc;
+ if (not match(chan_desc.chan_nr, t_RslChanNr_SDCCH8(1, ?))) {
+ setverdict(fail, "Unexpected channel number: ", chan_desc.chan_nr);
+ return;
+ }
+
+ /* Make sure that hopping parameters (HSN/MAIO) match */
+ f_TC_fh_params_match_chan_desc(fhp, chan_desc);
+
+ /* Make sure that Cell Channel Description IE is present */
+ if (not ispresent(l3_msg.payload.ho_cmd.cell_chan_desc)) {
+ setverdict(fail, "FH enabled, but Cell Channel Description IE is absent");
+ return;
+ }
+
+ /* Make sure that the Mobile Allocation (after time) IE is present and matches */
+ var boolean ma_present := ispresent(l3_msg.payload.ho_cmd.mobile_allocation);
+ if (ma_present) {
+ f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
+ l3_msg.payload.ho_cmd.mobile_allocation.v);
+ } else {
+ setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
+ return;
+ }
+
+ f_perform_clear_test_ct(dt);
+}
+testcase TC_fh_params_handover_cmd() runs on test_CT {
+ var FHParamsTrx fhp := f_TC_fh_params_gen();
+
+ f_init_vty();
+
+ /* (Re)configure TS0 as BCCH and TS1 as SDCCH8 on BTS1/TRX0 */
+ f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
+
+ f_vty_transceive(BSCVTY, "timeslot 0");
+ f_vty_transceive(BSCVTY, "phys_chan_config ccch");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+
+ f_vty_transceive(BSCVTY, "timeslot 1");
+ f_vty_transceive(BSCVTY, "phys_chan_config sdcch8");
+ f_vty_transceive(BSCVTY, "end"); /* we're done */
+
+ f_TC_fh_params_set(fhp, 1); /* Enable frequency hopping on BTS1 */
+ f_vty_transceive(BSCVTY, "drop bts connection 1 oml");
+
+ f_init(2);
+
+ f_TC_fh_params_handover_cmd(fhp);
+
+ /* Disable frequency hopping on BTS1 */
+ f_TC_fh_params_unset(fhp, 1);
+
+ /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
+ f_vty_enter_cfg_trx(BSCVTY, bts := 1, trx := 0);
+
+ f_vty_transceive(BSCVTY, "timeslot 0");
+ f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+
+ f_vty_transceive(BSCVTY, "timeslot 1");
+ f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
+ f_vty_transceive(BSCVTY, "end"); /* we're done */
+
+ f_shutdown_helper();
+}
+
+/* Verify the hopping parameters in System Information Type 4 */
+testcase TC_fh_params_si4_cbch() runs on test_CT {
+ var FHParamsTrx fhp := f_TC_fh_params_gen(tr_tn := 1);
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ timer T := 5.0;
+
+ f_init_vty();
+
+ /* (Re)configure TS0 as BCCH and TS1 as SDCCH8+CBCH */
+ f_vty_enter_cfg_trx(BSCVTY, trx := 0);
+
+ f_vty_transceive(BSCVTY, "timeslot 0");
+ f_vty_transceive(BSCVTY, "phys_chan_config ccch");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+
+ f_vty_transceive(BSCVTY, "timeslot 1");
+ f_vty_transceive(BSCVTY, "phys_chan_config sdcch8+cbch");
+ f_vty_transceive(BSCVTY, "end"); /* we're done */
+
+ f_TC_fh_params_set(fhp); /* Enable frequency hopping */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1);
+
+ T.start;
+ alt {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_BCCH_INFO(RSL_SYSTEM_INFO_4))) -> value rx_rsl_ud {
+ var RSL_IE_Body ie := rx_rsl_ud.rsl.ies[2].body; /* FULL BCCH Information IE */
+ var SystemInformation si := dec_SystemInformation(ie.other.payload);
+
+ /* Make sure that what we decoded is System Information Type 4 */
+ if (si.header.message_type != SYSTEM_INFORMATION_TYPE_4) {
+ setverdict(fail, "RSL FULL BCCH Information IE contains: ", si);
+ repeat;
+ }
+
+ /* Make sure that CBCH Channel Description IE is present */
+ if (not ispresent(si.payload.si4.cbch_chan_desc)) {
+ setverdict(fail, "CBCH Channel Description IE is absent");
+ break;
+ }
+
+ /* Finally, check the hopping parameters (HSN, MAIO) */
+ var ChannelDescription chan_desc := si.payload.si4.cbch_chan_desc.v;
+ f_TC_fh_params_match_chan_desc(fhp, chan_desc);
+
+ /* 3GPP TS 44.018, section 9.1.36.2 "CBCH Mobile Allocation":
+ * The CBCH Mobile Allocation IE *shall* be present if FH is enabled. */
+ if (chan_desc.h and not ispresent(si.payload.si4.cbch_mobile_alloc)) {
+ setverdict(fail, "FH enabled, but Mobile Allocation IE is absent");
+ break;
+ } else if (chan_desc.h and ispresent(si.payload.si4.cbch_mobile_alloc)) {
+ f_TC_fh_params_match_ma(fhp, chan_desc.chan_nr.tn,
+ si.payload.si4.cbch_mobile_alloc.v);
+ }
+ }
+ [] IPA_RSL[0][0].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL BCCH INFOrmation (SI4)");
+ }
+ }
+
+ /* Disable frequency hopping */
+ f_TC_fh_params_unset(fhp);
+
+ /* (Re)configure TS0 as CCCH+SDCCH4+CBCH and TS1 as TCH/F */
+ f_vty_enter_cfg_trx(BSCVTY, trx := 0);
+
+ f_vty_transceive(BSCVTY, "timeslot 0");
+ f_vty_transceive(BSCVTY, "phys_chan_config ccch+sdcch4+cbch");
+ f_vty_transceive(BSCVTY, "exit"); /* go back */
+
+ f_vty_transceive(BSCVTY, "timeslot 1");
+ f_vty_transceive(BSCVTY, "phys_chan_config tch/f");
+ f_vty_transceive(BSCVTY, "end"); /* we're done */
+
+ f_shutdown_helper();
+}
+
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
+ := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
+
+private function f_match_bsslap(PDU_BSSAP_LE got_bsslap_msg,
+ template (present) BSSLAP_PDU expect_bsslap)
+{
+ var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(got_bsslap_msg.pdu.bssmap.co_info.bsslap_apdu.data);
+ if (not match(bsslap, expect_bsslap)) {
+ log("EXPECTING BSSLAP: ", expect_bsslap);
+ log("GOT BSSLAP: ", bsslap);
+ setverdict(fail, "BSSLAP is not as expected");
+ mtc.stop;
+ }
+ setverdict(pass);
+}
+
+/* GAD: this is an Ellipsoid point with uncertainty circle, encoded as in 3GPP TS 23.032 §7.3.2. */
+const octetstring gad_ell_point_unc_circle := '10b0646d0d5f6627'O;
+
+private function f_expect_bsslap(template (present) BSSLAP_PDU expect_rx_bsslap) runs on MSC_ConnHdlr {
+ var PDU_BSSAP_LE rx_bsslap;
+ BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap);
+ f_match_bsslap(rx_bsslap, expect_rx_bsslap);
+}
+
+/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
+ * Request on Lb interface. Either with or without the SMLC doing a BSSLAP TA Request. */
+private function f_lcs_loc_req_for_active_ms(boolean do_ta_request := false) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_establish_fully(omit, omit);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ if (not do_ta_request) {
+ /* verify TA Layer 3 in APDU. First the APDU type (BSSLAP), then the BSSLAP data contents. */
+ var template BSSMAP_LE_IE_APDU expect_apdu := tr_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, ?);
+ if (not match(plr.pdu.bssmap.perf_loc_req.bsslap_apdu, expect_apdu)) {
+ log("EXPECTING BSSMAP-LE APDU IE ", expect_apdu);
+ log("GOT BSSMAP-LE APDU IE ", plr.pdu.bssmap.perf_loc_req.bsslap_apdu);
+ setverdict(fail, "BSSMAP-LE APDU IE is not as expected");
+ mtc.stop;
+ }
+ var template BSSLAP_PDU expect_ta_layer3 := tr_BSSLAP_TA_Layer3(tr_BSSLAP_IE_TA(0));
+ var BSSLAP_PDU bsslap := dec_BSSLAP_PDU(plr.pdu.bssmap.perf_loc_req.bsslap_apdu.data);
+ if (not match(bsslap, expect_ta_layer3)) {
+ log("EXPECTING BSSLAP TA Layer 3: ", expect_ta_layer3);
+ log("GOT BSSLAP: ", bsslap);
+ setverdict(fail, "BSSLAP is not as expected");
+ mtc.stop;
+ }
+ /* OsmoBSC directly sent the TA as BSSLAP APDU in the BSSMAP-LE Perform Location Request to the SMLC. The SMLC
+ * has no need to request the TA from the BSC and directly responds. */
+ } else {
+ /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
+ f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
+ }
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ /* The LCS was using an active A-interface conn. It should still remain active after this. */
+ f_mo_l3_transceive();
+
+ f_perform_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+
+/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
+ * Request on Lb interface. Without the SMLC doing a BSSLAP TA Request. */
+private function f_tc_lcs_loc_req_for_active_ms(charstring id) runs on MSC_ConnHdlr {
+ f_lcs_loc_req_for_active_ms(false);
+}
+testcase TC_lcs_loc_req_for_active_ms() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* With an active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
+ * Request on Lb interface. With the SMLC doing a BSSLAP TA Request. */
+private function f_tc_lcs_loc_req_for_active_ms_ta_req(charstring id) runs on MSC_ConnHdlr {
+ f_lcs_loc_req_for_active_ms(true);
+}
+testcase TC_lcs_loc_req_for_active_ms_ta_req() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_ta_req), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Clear the A-interface conn only, without doing anything on Abis. Useful for LCS, for cases where there is only an A
+ * conn without an active lchan. */
+private function f_clear_A_conn() runs on MSC_ConnHdlr
+{
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSMAP_ClearCommand(cause));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
+ timer no_more_bssap := 5.0;
+ no_more_bssap.start;
+ alt {
+ [] no_more_bssap.timeout { break; }
+ [] BSSAP.receive(tr_BSSAP_BSSMAP) {
+ setverdict(fail, "Expected no more BSSAP after Clear Complete");
+ mtc.stop;
+ }
+ }
+ setverdict(pass);
+}
+
+/* Verify that the A-interface connection is still working, and then clear it, without doing anything on Abis. Useful
+ * for LCS, for cases where there is only an A conn without an active lchan. */
+private function f_verify_active_A_conn_and_clear() runs on MSC_ConnHdlr
+{
+ f_logp(BSCVTY, "f_verify_active_A_conn_and_clear: test A link, then clear");
+
+ /* When an lchan is active, we can send some L3 data from the BTS side and verify that it shows up on the other
+ * side towards the MSC. When there is no lchan, this is not possible. To probe whether the A-interface
+ * connection is still up, we need something that echos back on the A-interface. Another LCS request! */
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
+
+ /* Right, the Perform Location Request showed up on Lb, now we can clear the A conn. */
+ f_clear_A_conn();
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+}
+
+/* With *no* active lchan, start BSSMAP Perform Location Request on A interface, starting BSSMAP-LE Perform Location
+ * Request on Lb interface. BSC will Page for the subscriber as soon as we (virtual SMLC) request the TA via BSSLAP.
+ */
+private function f_tc_lcs_loc_req_for_idle_ms(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ /* Register to receive the Paging Command */
+ var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
+ g_chan_nr := new_chan_nr;
+ f_rslem_register(0, g_chan_nr);
+
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
+ valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('001'H, '01'H, 1, 0)))));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
+
+ /* OsmoBSC needs to Page */
+ RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi)));
+ f_logp(BSCVTY, "got Paging Command");
+
+ /* MS requests channel. Since the Paging was for LCS, the Paging Response does not trigger a Complete Layer 3 to
+ * the MSC, and releases the lchan directly. */
+ f_perform_compl_l3(RSL, RSL_PROC, ts_PAG_RESP(ts_MI_IMSI_LV(g_pars.imsi)), do_clear := false, expect_bssmap_l3 := false);
+ f_expect_lchan_rel(RSL, RSL_PROC);
+
+ /* From the Paging Response, the TA is now known to the BSC, and it responds to the SMLC. */
+
+ f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ /* The lchan is gone, the A-interface conn was created for the LCS only.
+ * Still it is clearly the MSC's job to decide whether to tear down the conn or not. */
+ f_verify_active_A_conn_and_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_lcs_loc_req_for_idle_ms() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* With no active lchan, start BSSMAP Perform Location Request on A interface, but omit IMSI; expect failure response.
+ */
+private function f_tc_lcs_loc_req_no_subscriber(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ /* provoke an abort by omitting both IMSI and IMEI */
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
+ valueof(ts_BSSMAP_Perform_Location_Request(omit,
+ ts_CellId_CGI('262'H, '42'H, 23, 42)))));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ /* BSC tells MSC about failure */
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
+ locationEstimate := omit, positioningData := omit,
+ lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ)));
+
+ /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
+ f_verify_active_A_conn_and_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_lcs_loc_req_no_subscriber() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_no_subscriber), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
+ * BSSMAP-LE Perform Location Response (before or after sending a BSSLAP TA Request) */
+private function f_lcs_loc_req_for_active_ms_le_timeout(boolean do_ta) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_establish_fully(omit, omit);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ if (do_ta) {
+ /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
+ f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
+ }
+
+ /* SMLC fails to respond, BSC runs into timeout */
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
+ locationEstimate := omit, positioningData := omit,
+ lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_SYSTEM_FAILURE)));
+
+ /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
+ f_verify_active_A_conn_and_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+
+/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
+ * BSSMAP-LE Perform Location Response, without sending a BSSLAP TA Request. */
+private function f_tc_lcs_loc_req_for_active_ms_le_timeout(charstring id) runs on MSC_ConnHdlr {
+ f_lcs_loc_req_for_active_ms_le_timeout(false);
+}
+
+testcase TC_lcs_loc_req_for_active_ms_le_timeout() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* With an active lchan, start a Perform Location Request on the A-interface, but virtual SMLC does not answer with
+ * BSSMAP-LE Perform Location Response, after sending a BSSLAP TA Request. */
+private function f_tc_lcs_loc_req_for_active_ms_le_timeout2(charstring id) runs on MSC_ConnHdlr {
+ f_lcs_loc_req_for_active_ms_le_timeout(true);
+}
+
+testcase TC_lcs_loc_req_for_active_ms_le_timeout2() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_active_ms_le_timeout2), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* With *no* active lchan, start a Perform Location Request, expecting that the MS will be Paged. */
+private function f_tc_lcs_loc_req_for_idle_ms_no_pag_resp(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ /* Register to receive the Paging Command */
+ var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
+ g_chan_nr := new_chan_nr;
+ f_rslem_register(0, g_chan_nr);
+
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
+ valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('001'H, '01'H, 1, 0)))));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
+
+ /* OsmoBSC needs to Page */
+ var PDU_BSSAP_LE rx_bsslap;
+ alt {
+ [] RSL.receive(tr_RSL_PAGING_CMD(tr_MI_IMSI(g_pars.imsi))) {
+ f_logp(BSCVTY, "got Paging Command");
+ repeat;
+ }
+ [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
+ /* MS does not respond to Paging, TA Req runs into timeout. */
+ f_match_bsslap(rx_bsslap, tr_BSSLAP_Abort(?));
+ }
+ }
+
+ /* SMLC responds with failure */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+
+ /* BSC tells MSC about failure */
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(
+ locationEstimate := omit, positioningData := omit,
+ lCS_Cause := tr_BSSMAP_LcsCause(BSSMAP_LCS_CAUSE_REQUEST_ABORTED)));
+
+ /* There is no lchan. Still the MSC's job to decide whether to tear down the conn or not. */
+ f_verify_active_A_conn_and_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_lcs_loc_req_for_idle_ms_no_pag_resp() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_lcs_loc_req_for_idle_ms_no_pag_resp), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* During an ongoing Location Request, the MS sends a CM Service Request. Expect the same A-conn to be re-used / taken
+ * over. */
+private function f_tc_cm_service_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ /* Register to receive the Paging Command */
+ var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
+ g_chan_nr := new_chan_nr;
+ f_rslem_register(0, g_chan_nr);
+
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc,
+ valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('001'H, '01'H, 1, 0)))));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ /* As the A-interface conn was established for LCS, the MS coincidentally decides to issue a CM Service Request
+ * and establish Layer 3. It should use the existing A-interface conn. */
+ f_perform_compl_l3(RSL, RSL_PROC, valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(ts_MI_IMSI_LV(g_pars.imsi)))),
+ do_clear := false, expect_bssmap_l3 := true);
+
+ /* SMLC wants to ask the TA from the BSC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Req));
+
+ /* OsmoBSC already has an lchan, no need to Page, just returns the TA */
+ f_expect_bsslap(tr_BSSLAP_TA_Resp(?, ?));
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ /* The lchan should still exist, it was from a CM Service Request. */
+ f_mo_l3_transceive();
+
+ f_perform_clear();
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_cm_service_during_lcs_loc_req() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_cm_service_during_lcs_loc_req), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* During an ongoing Perform Location Request, do a Handover, an expect a BSSLAP Reset message from the BSC to indicate
+ * the new lchan after handover. */
+private function f_tc_ho_during_lcs_loc_req(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_establish_fully(omit, omit);
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+
+ var PDU_BSSAP_LE plr;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?)) -> value(plr);
+
+ /* SMLC ponders the Location Request, in the meantime the BSC decides to handover */
+ f_bts_0_cfg(BSCVTY, {"neighbor bts 1"});
+
+ var HandoverState hs := {
+ rr_ho_cmpl_seen := false,
+ handover_done := false,
+ old_chan_nr := -,
+ expect_target_tsc := c_BtsParams[1].tsc
+ };
+ /* issue hand-over command on VTY */
+ f_vty_handover(BSCVTY, 0, 0, g_chan_nr, 1);
+ /* temporarily suspend DChan processing on BTS1 to avoid race with RSLEM_register */
+ f_rslem_suspend(RSL1_PROC);
+
+ /* From the MGW perspective, a handover is is characterized by
+ * performing one MDCX operation with the MGW. So we expect to see
+ * one more MDCX during handover. */
+ g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].crcx_seen_exp + 1;
+
+ alt {
+ [] as_handover(hs);
+ }
+
+ var PDU_BSSAP_LE rx_bsslap;
+
+ interleave {
+ /* Expect the BSC to inform the MSC about the handover */
+ [] BSSAP.receive(tr_BSSMAP_HandoverPerformed);
+
+ /* Expect the BSC to inform the SMLC about the handover */
+ [] BSSAP_LE.receive(tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, ?)) -> value(rx_bsslap) {
+ f_match_bsslap(rx_bsslap, tr_BSSLAP_Reset(BSSLAP_CAUSE_INTRA_BSS_HO));
+ }
+ }
+
+ /* SMLC now responds with geo information data. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ /* lchan still active */
+ f_mo_l3_transceive(RSL1);
+
+ /* MSC decides it is done now. */
+ f_perform_clear(RSL1, RSL1_PROC);
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_ho_during_lcs_loc_req() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(2, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_tc_ho_during_lcs_loc_req), pars);
+ vc_conn.done;
+ f_shutdown_helper(ho := true);
+}
+
+private function f_tc_emerg_call_and_lcs_loc_req(charstring id) runs on MSC_ConnHdlr
+{
+ /* Make sure the CHAN RQD indicates an emergency call (0b101xxxxx). The difference is that osmo-bsc directly
+ * assigns a TCH lchan and establishing voice for the emergency call will use Mode Modify, not reassignment to
+ * another lchan. */
+ g_pars.ra := f_rnd_ra_emerg();
+ f_assignment_emerg_setup();
+ f_assignment_emerg_setup_exp_bssap();
+
+ /* Here would usually be a CC Call Proceeding from the MSC, but what does the BSC care about DTAP. */
+
+ /* Do a Location Request in-between the CC call setup */
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ f_assignment_emerg_setup_voice();
+
+ setverdict(pass);
+ f_perform_clear();
+}
+
+testcase TC_emerg_call_and_lcs_loc_req() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+ vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private altstep no_bssmap_clear_req() runs on MSC_ConnHdlr {
+ [] BSSAP.receive(tr_BSSMAP_ClearRequest) {
+ setverdict(fail, "unexpected BSSMAP Clear Request");
+ mtc.stop;
+ }
+}
+
+private type enumerated RslRel {
+ RSLREL_REL_IND,
+ RSLREL_CONN_FAIL
+};
+
+private function f_emerg_call_and_lcs_loc_req_early_lchan_release(RslRel rsl_rel) runs on MSC_ConnHdlr
+{
+ g_pars.ra := f_rnd_ra_emerg();
+ f_assignment_emerg_setup();
+ f_assignment_emerg_setup_exp_bssap();
+
+ /* Start a Location Request to locate the emergency */
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+ BSSAP.send(valueof(ts_BSSMAP_Perform_Location_Request(ts_BSSMAP_Imsi(g_pars.imsi),
+ ts_CellId_CGI('262'H, '42'H, 23, 42))));
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, ?, ?));
+
+ /* As long as this LCS is going on, the BSC should not send any Clear Request. Later on, it is up to the MSC to
+ * do a Clear Command when the Location Response arrives. */
+ activate(no_bssmap_clear_req());
+
+ /* the lchan gets interrupted while the Location Request has no response */
+ select (rsl_rel) {
+ case (RSLREL_REL_IND) {
+ RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
+ f_expect_lchan_rel(RSL, RSL_PROC);
+ }
+ case (RSLREL_CONN_FAIL) {
+ RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_RADIO_LINK_FAIL));
+ }
+ case else {
+ setverdict(fail, "Unknown RslRel type");
+ mtc.stop;
+ }
+ }
+
+ /* Still expect the Location Response to find its way to the MSC. */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocResp(gad_ell_point_unc_circle, omit));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_IND);
+ BSSAP.receive(tr_BSSMAP_Perform_Location_Response(tr_BSSMAP_IE_LocationEstimate(gad_ell_point_unc_circle)));
+
+ setverdict(pass);
+
+ select (rsl_rel) {
+ case (RSLREL_REL_IND) {
+ f_perform_clear_no_lchan();
+ }
+ case (RSLREL_CONN_FAIL) {
+ f_perform_clear();
+ }
+ }
+}
+
+private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind(charstring id) runs on MSC_ConnHdlr
+{
+ f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_REL_IND);
+}
+
+testcase TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+ vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_rel_ind), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail(charstring id) runs on MSC_ConnHdlr
+{
+ f_emerg_call_and_lcs_loc_req_early_lchan_release(RSLREL_CONN_FAIL);
+}
+
+testcase TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+ f_sleep(1.0);
+ f_vty_allow_emerg_msc(true);
+ f_vty_allow_emerg_bts(true, 0);
+ vc_conn := f_start_handler(refers(f_tc_emerg_call_and_lcs_loc_req_early_lchan_conn_fail), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Attempt Complete Layer 3 without any MSC available (OS#4832) */
+private function f_tc_no_msc(charstring id) runs on MSC_ConnHdlr {
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+
+ /* Also disable attach for the single connected MSC */
+ f_vty_msc_allow_attach(BSCVTY, { false });
+
+ var octetstring l3_enc := enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(ts_MI_IMSI_LV('001010000100001'H)), '00F110'O) ));
+ f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
+
+ /* No MSC is found, expecting a proper release on RSL */
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {
+ f_logp(BSCVTY, "Got RSL RR Release");
+ }
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL Deact SACCH");
+ }
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ f_logp(BSCVTY, "Got RSL RF Chan Rel, sending Rel Ack");
+ RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr);
+ }
+ }
+ setverdict(pass);
+}
+testcase TC_no_msc() runs on test_CT {
+
+ f_init(1, true);
+ f_sleep(1.0);
+ var MSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_ctrs_bsc_init(counternames_bsc_mscpool);
+
+ vc_conn := f_start_handler(refers(f_tc_no_msc), pars);
+ vc_conn.done;
+
+ f_ctrs_bsc_add("mscpool:subscr:no_msc");
+ f_ctrs_bsc_verify();
+ f_shutdown_helper();
+}
+
/* Dyn PDCH todo:
* activate OSMO as TCH/F
* activate OSMO as TCH/H
@@ -5952,10 +10969,1614 @@ testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
* is the info correct on delayed PCU (re)connect?
*/
+private function f_TC_refuse_mode_modif_to_vamos(charstring id) runs on MSC_ConnHdlr {
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+
+ /* puzzle together the ASSIGNMENT REQ for given codec[s] */
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+ g_pars.ass_codec_list.codecElements[0];
+ if (isvalue(g_pars.expect_mr_s0_s7)) {
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+ g_pars.expect_mr_s0_s7;
+ }
+ }
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+ f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+ log("expecting ASS COMPL like this: ", exp_compl);
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 modify vamos tsc 2 3");
+
+ var RSL_Message rsl;
+
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+ log("Rx L3 from net: ", l3);
+ if (ischosen(l3.msgs.rrm.channelModeModify)) {
+ setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
+ mtc.stop;
+ }
+ }
+ [] RSL.receive(tr_RSL_MODE_MODIFY_REQ(g_chan_nr, ?)) -> value rsl {
+ setverdict(fail, "Mode Modify to VAMOS succeeded even though BTS does not support VAMOS");
+ mtc.stop;
+ }
+ [] T.timeout {
+ /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related Mode Modify should happen. */
+ setverdict(pass);
+ }
+ }
+ T.stop;
+
+ f_perform_clear();
+}
+
+/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel Mode Modify to VAMOS mode is refused by
+ * osmo-bsc. */
+testcase TC_refuse_mode_modif_to_vamos() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ vc_conn := f_start_handler(refers(f_TC_refuse_mode_modif_to_vamos), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* The BSC does *not* indicate BTS_FEAT_VAMOS; make sure that a channel activation to VAMOS mode is refused by osmo-bsc.
+ */
+testcase TC_refuse_chan_act_to_vamos() runs on test_CT {
+ f_init_vty();
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
+
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ timer T := 5.0;
+
+ T.start;
+ alt {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(?, IPAC_PROTO_RSL_TRX0)) -> value rx_rsl_ud {
+ if (rx_rsl_ud.rsl.msg_type == RSL_MT_CHAN_ACTIV) {
+ T.stop;
+ setverdict(fail, "CHANnel ACTivate in VAMOS mode succeeded even though BTS does not support VAMOS");
+ mtc.stop;
+ }
+ repeat;
+ }
+ [] T.timeout {
+ /* The BTS does not exhibit BTS_FEAT_VAMOS, so no VAMOS related CHANnel ACTivate should happen. */
+ setverdict(pass);
+ }
+ }
+}
+
+private function f_TC_reassignment_codec(charstring id) runs on MSC_ConnHdlr {
+ /* First fully set up a speech lchan */
+ f_assignment_codec(id, do_perform_clear := false);
+
+ /* Trigger re-assignment to another lchan */
+ var AssignmentState assignment_st := valueof(ts_AssignmentStateInit);
+
+ /* Re-Assignment should tell the MGW endpoint the new lchan's RTP address and port, so expecting to see exactly
+ * one MDCX on MGCP. */
+ g_media.mgcp_conn[0].mdcx_seen_exp := g_media.mgcp_conn[0].mdcx_seen_exp + 1;
+
+ /* The new lchan will see all-new IPAC_CRCX and IPAC_MDCX messages telling the BTS the same RTP address and port
+ * as the old lchan used. */
+ g_media.bts.ipa_crcx_seen := false;
+ g_media.bts.ipa_mdcx_seen := false;
+
+ /* Send different BTS side RTP port number for the new lchan */
+ g_media.bts.bts.port_nr := 4223;
+
+ f_rslem_register(0, valueof(ts_RslChanNr_Bm(2))); /* <-- FIXME: can we somehow infer the timeslot that will be used? */
+
+ /* Trigger re-assignment. */
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot 0 assignment");
+
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] as_assignment(assignment_st);
+ [] as_Media();
+ [] T.timeout {
+ break;
+ }
+ }
+
+ if (not assignment_st.assignment_done) {
+ setverdict(fail, "Assignment did not complete");
+ mtc.stop;
+ }
+
+ f_check_mgcp_expectations()
+ setverdict(pass);
+
+ f_sleep(2.0);
+ log("show lchan summary: ", f_vty_transceive_ret(BSCVTY, "show lchan summary"));
+
+ /* Instruct BSC to clear channel */
+ var BssmapCause cause := 0;
+ BSSAP.send(ts_BSSMAP_ClearCommand(cause));
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_RRM_RR_RELEASE)) {}
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ RSL.send(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr));
+ f_rslem_unregister(0, g_chan_nr);
+ }
+ [] BSSAP.receive(tr_BSSMAP_ClearComplete) {
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ }
+ }
+ f_expect_dlcx_conns();
+
+ f_sleep(0.5);
+}
+
+testcase TC_reassignment_fr() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_ctrs_bsc_and_bts_handover_init();
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ vc_conn := f_start_handler(refers(f_TC_reassignment_codec), pars);
+ vc_conn.done;
+
+ /* from f_establish_fully() */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ /* from re-assignment */
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper();
+}
+
+const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
+const charstring REEST_CLEAR := "REEST_CLEAR";
+const charstring REEST_CLEAR_DONE := "REEST_CLEAR_DONE";
+
+/* CM Re-Establishment, 3GPP TS 24.008 4.5.1.6.
+ * The MS <-> BTS loses radio connection, MS shows up on second BTS and asks for CM Re-Establishment.
+ * BSC should establish a separate A conn for the same MS, the original A conn is then cleared by
+ * the MSC as the CM Re-Establishment is handled.
+ *
+ * MS bts0 bts1 bsc msc test-component
+ * |<----->|<----------------->|<-0-->| _1 Establish channel on bts 0
+ * | | _1 wait a bit, to settle down
+ * |<-x x--| | _1 "lose connection"
+ * | | REEST_LOST_CONNECTION
+ * |----------------->|------->|--1-->| _2 new A-conn: Chan Rqd, Imm Ass, Compl L3 with CM Re-Establishment Req
+ * | | REEST_CLEAR
+ * | |<-0---| _1 Clear Command on first A-conn
+ * | |--0-->| _1 Clear Complete
+ * | |<----------------->| | _1 Release first channel
+ * | | REEST_CLEAR_DONE
+ * |<-----------------|<-------|<-1---| _2 Chan Activ, Assignment Command
+ * |<-----------------|<-------|<-1---| _2 Clear Command, Release
+ *
+ */
+private function f_tc_cm_reestablishment_1(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ /* The original channel loses connection, MS attemts CM Re-Establishment on another cell, see
+ * f_tc_cm_reestablishment_2(). This established channel stays active until MSC sends a Clear Command. The time
+ * when exactly that happens is determined by f_tc_cm_reestablishment_2(). */
+ f_sleep(2.0);
+ COORD.send(REEST_LOST_CONNECTION);
+
+ alt {
+ [] COORD.receive(REEST_CLEAR);
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {
+ setverdict(fail, "Unexpected channel release");
+ mtc.stop;
+ }
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ setverdict(fail, "Unexpected channel release");
+ mtc.stop;
+ }
+ }
+ f_perform_clear()
+ f_create_mgcp_delete_ep(g_media.mgcp_ep);
+ COORD.send(REEST_CLEAR_DONE);
+}
+
+private function f_tc_cm_reestablishment_2(charstring id) runs on MSC_ConnHdlr {
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, FR_AMR);
+
+ /* The MS lost the connection on the first channel, now establishes another one */
+ COORD.receive(REEST_LOST_CONNECTION);
+
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
+ var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
+
+ f_create_bssmap_exp(l3_enc);
+ RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
+ BSSAP.receive(tr_BSSMAP_ComplL3(l3_enc));
+
+ /* MSC got the CM Re-Establishment request and first off clears the previous conn. */
+ COORD.send(REEST_CLEAR);
+ COORD.receive(REEST_CLEAR_DONE);
+
+ f_sleep(2.0);
+
+ /* Answer the CM Re-Establishment with an Assignment Command. */
+ var template PDU_BSSAP expect_assignment_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ var AssignmentState st := valueof(ts_AssignmentStateInit);
+ st.rtp_stream := true;
+ st.is_assignment := true;
+
+ var ExpectCriteria mgcpcrit := {
+ connid := omit,
+ endpoint := omit,
+ transid := omit
+ };
+ f_create_mgcp_expect(mgcpcrit);
+
+ f_rslem_dchan_queue_enable(RSL1_PROC);
+
+ BSSAP.send(ass_cmd);
+
+ var PDU_BSSAP bssap;
+
+ alt {
+ [] as_assignment(st, rsl_pt := RSL1, rsl_proc_pt := RSL1_PROC);
+ [] as_Media_ipacc(RSL1, RSL2);
+ [] as_Media_mgw();
+ [st.assignment_done] BSSAP.receive(expect_assignment_compl) {
+ break;
+ }
+ }
+
+ f_sleep(3.0);
+
+ f_logp(BSCVTY, "f_tc_cm_reestablishment_2 clearing");
+ f_perform_clear(RSL1, RSL1_PROC);
+}
+
+testcase TC_cm_reestablishment() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.imsi := pars1.imsi;
+ pars2.media_nr := 2;
+ pars2.expect_tsc := c_BtsParams[1].tsc;
+
+ f_init(2, true, guard_timeout := 40.0);
+ f_sleep(1.0);
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_tc_cm_reestablishment_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_tc_cm_reestablishment_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_shutdown_helper();
+}
+
+function f_exp_ipa_rx_nonfatal(template (present) RSL_Message t_rx,
+ boolean ignore_other_rx := true,
+ BtsTrxIdx idx := {0, 0},
+ float Tval := 2.0)
+runs on test_CT return template (omit) RSL_Message {
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ timer T := Tval;
+
+ T.start;
+ alt {
+ [] IPA_RSL[idx.bts][idx.trx].receive(tr_ASP_RSL_UD(t_rx, ?)) -> value rx_rsl_ud {
+ T.stop;
+ }
+ [ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive { repeat; }
+ [not ignore_other_rx] IPA_RSL[idx.bts][idx.trx].receive {
+ log("f_exp_ipa_rx_nonfatal(): Got different message than ", t_rx);
+ T.stop;
+ return omit;
+ }
+ [] T.timeout {
+ return omit;
+ }
+ }
+ return rx_rsl_ud.rsl;
+}
+
+private function f_vty_set_imm_ass(TELNETasp_PT pt, BtsNr bts_nr := 0, charstring imm_ass_setting := "post-chan-ack") {
+ f_vty_enter_cfg_bts(pt, bts_nr);
+ f_vty_transceive(pt, "immediate-assignment " & imm_ass_setting);
+ f_vty_transceive(pt, "exit");
+ f_vty_transceive(pt, "exit");
+ f_vty_transceive(pt, "exit");
+}
+
+private function f_verify_imm_ass(RSL_Message imm_ass, template uint8_t ra := ?, template GsmFrameNumber fn := ?,
+ template (present) RslChannelNr chan_nr := ?,
+ template (present) uint12_t arfcn := ?,
+ template (present) uint3_t tsc := ?)
+{
+ var RSL_IE_Body full_imm_ass_info;
+ if (not f_rsl_find_ie(imm_ass, RSL_IE_FULL_IMM_ASS_INFO, full_imm_ass_info)) {
+ setverdict(fail, "RSL Full Immediate Assign Info IE is absent");
+ mtc.stop;
+ }
+
+ var GsmRrMessage rr_imm_ass := dec_GsmRrMessage(full_imm_ass_info.full_imm_ass_info.payload);
+ var template GsmRrMessage expect_imm_ass := tr_IMM_ASS(ra := ra,
+ fn := fn,
+ ch_desc := tr_ChanDescH0(chan_nr, arfcn, tsc),
+ page_mode := ?);
+ if (not match(rr_imm_ass, expect_imm_ass)) {
+ log("Error: expected ", expect_imm_ass, " got ", rr_imm_ass);
+ setverdict(fail, "Failed to match Immediate Assignment");
+ mtc.stop;
+ }
+}
+
+testcase TC_imm_ass_post_chan_ack() runs on test_CT {
+ var RSL_Message chan_act;
+ var RSL_Message imm_ass;
+ var octetstring l3_payload := gen_l3_valid_payload();
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ /* (should be the default anyway, just to make things clear) */
+ f_vty_set_imm_ass(BSCVTY, 0, "post-chan-ack");
+
+ /* RA containing reason=LU */
+ var GsmFrameNumber fn := 2342;
+ var uint8_t ra := 2;
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
+
+ chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+ /* First send the Chan Act ACK */
+ var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+ var DchanTuple dt := {-, chan_nr, {0, 0}};
+ var RSL_IE_Body chan_ident_ie;
+ if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ mtc.stop;
+ }
+
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn + 10));
+
+ /* Then expect the Immediate Assignment, after we ACKed the chan act */
+ imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+
+ f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
+ chan_ident_ie.chan_ident.ch_desc.v.tsc);
+
+ /* Check that the lchan is working */
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ f_sleep(1.0);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+testcase TC_imm_ass_pre_chan_ack() runs on test_CT {
+ var RSL_Message chan_act;
+ var RSL_Message imm_ass;
+ var octetstring l3_payload := gen_l3_valid_payload();
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
+
+ /* RA containing reason=LU */
+ var GsmFrameNumber fn := 2342;
+ var uint8_t ra := 2;
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
+
+ chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+ var DchanTuple dt := {-, chan_nr, {0, 0}};
+ var RSL_IE_Body chan_ident_ie;
+ if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ mtc.stop;
+ }
+
+ /* (set bts 0 cfg back to default) */
+ f_vty_set_imm_ass(BSCVTY);
+
+ /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
+ imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
+ chan_ident_ie.chan_ident.ch_desc.v.tsc);
+
+ /* Only now send the Chan Act ACK */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
+
+ /* Check that the lchan is working */
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ f_sleep(1.0);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+testcase TC_imm_ass_pre_ts_ack() runs on test_CT {
+ var RSL_Message chan_act;
+ var RSL_Message imm_ass;
+ var octetstring l3_payload := gen_l3_valid_payload();
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
+
+ /* RA containing reason=LU */
+ var GsmFrameNumber fn := 2342;
+ var uint8_t ra := 2;
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
+
+ chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ var RslChannelNr chan_nr := chan_act.ies[0].body.chan_nr;
+ var DchanTuple dt := {-, chan_nr, {0, 0}};
+ var RSL_IE_Body chan_ident_ie;
+ if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ mtc.stop;
+ }
+
+ /* (set bts 0 cfg back to default) */
+ f_vty_set_imm_ass(BSCVTY);
+
+ /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
+ imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
+ chan_ident_ie.chan_ident.ch_desc.v.tsc);
+
+ /* Only now send the Chan Act ACK */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
+
+ /* Check that the lchan is working */
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ f_sleep(1.0);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+testcase TC_imm_ass_pre_chan_ack_dyn_ts() runs on test_CT {
+ /* change Timeslot 6 before f_init() starts RSL */
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ var octetstring l3_payload := gen_l3_valid_payload();
+ var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
+ /* The BSC will activate the dynamic PDCH by default, so confirm that */
+ f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
+
+ /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
+ f_ts_set_chcomb(0, 0, 6, "PDCH");
+
+ /* block all static timeslots so that the dyn TS will be used */
+ f_disable_all_tch_f();
+ f_disable_all_tch_h();
+ f_disable_all_sdcch();
+
+ var RSL_Message chan_act;
+ var RSL_Message imm_ass;
+
+ f_vty_set_imm_ass(BSCVTY, 0, "pre-chan-ack");
+
+ /* RA containing reason=LU */
+ var GsmFrameNumber fn := 2342;
+ var uint8_t ra := 2;
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
+
+ /* Expect the dyn TS to deactivate PDCH first */
+ f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+
+ /* Now activation as SDCCH8 */
+ chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
+ var DchanTuple dt := {-, chan_nr, {0, 0}};
+
+ chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ var RSL_IE_Body chan_ident_ie;
+ if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ mtc.stop;
+ }
+
+ /* *FIRST* expect the Immediate Assignment, before we ACK the chan act */
+ imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+ f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
+ chan_ident_ie.chan_ident.ch_desc.v.tsc);
+
+ /* Only now send the Chan Act ACK */
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
+
+ /* Check that the lchan is working */
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ /* (set bts 0 cfg back to default) */
+ f_vty_set_imm_ass(BSCVTY);
+
+ f_sleep(1.0);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+testcase TC_imm_ass_pre_ts_ack_dyn_ts() runs on test_CT {
+ /* change Timeslot 6 before f_init() starts RSL */
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 6, "TCH/F_TCH/H_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ var octetstring l3_payload := gen_l3_valid_payload();
+ var RslChannelNr chan_nr := valueof(t_RslChanNr_PDCH(6));
+ /* The BSC will activate the dynamic PDCH by default, so confirm that */
+ f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2323));
+
+ /* clean up timeslot 6 config, will only take effect when the OML drops the next time */
+ f_ts_set_chcomb(0, 0, 6, "PDCH");
+
+ /* block all static timeslots so that the dyn TS will be used */
+ f_disable_all_tch_f();
+ f_disable_all_tch_h();
+ f_disable_all_sdcch();
+
+ var RSL_Message chan_act;
+ var RSL_Message imm_ass;
+
+ f_vty_set_imm_ass(BSCVTY, 0, "pre-ts-ack");
+
+ /* RA containing reason=LU */
+ var GsmFrameNumber fn := 2342;
+ var uint8_t ra := 2;
+ f_ipa_tx(ts_RSL_CHAN_RQD(int2oct(ra, 1), fn));
+
+ /* Expect the dyn TS to deactivate PDCH first */
+ f_exp_ipa_rx(tr_RSL_RF_CHAN_REL(chan_nr));
+
+ /* And already the Immediate Assignment even before the PDCH Deact ACK */
+ imm_ass := f_exp_ipa_rx(tr_RSL_IMM_ASSIGN(0));
+
+ /* continue the Osmo style PDCH Deact (usual chan rel) */
+ f_ipa_tx(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+
+ /* Now activation as SDCCH8 */
+ chan_nr := valueof(t_RslChanNr_SDCCH8(tn := 6, sub_slot := 0));
+ var DchanTuple dt := {-, chan_nr, {0, 0}};
+
+ chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+ var RSL_IE_Body chan_ident_ie;
+ if (not f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, chan_ident_ie)) {
+ setverdict(fail, "RSL Channel Identification IE is absent");
+ mtc.stop;
+ }
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, fn+10));
+
+ f_verify_imm_ass(imm_ass, ra, fn, chan_nr, chan_ident_ie.chan_ident.ch_desc.v.arfcn,
+ chan_ident_ie.chan_ident.ch_desc.v.tsc);
+
+ /* Check that the lchan is working */
+ f_ipa_tx(ts_RSL_EST_IND(chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_payload));
+
+ var BSSAP_N_CONNECT_ind rx_c_ind;
+ BSSAP.receive(tr_BSSAP_CONNECT_ind(?, ?, tr_BSSMAP_ComplL3(l3_payload))) -> value rx_c_ind;
+ dt.sccp_conn_id := rx_c_ind.connectionId;
+ BSSAP.send(ts_BSSAP_CONNECT_res(rx_c_ind.connectionId));
+
+ /* (set bts 0 cfg back to default) */
+ f_vty_set_imm_ass(BSCVTY);
+
+ f_sleep(1.0);
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
+}
+
+/* GET and SET the bts.N.trx.M.rf_locked CTRL variable */
+testcase TC_ctrl_trx_rf_locked() runs on test_CT {
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(nr_bts := 2, handler_mode := true, nr_msc := 1);
+ f_sleep(1.0);
+
+ /* BTS 0, 1, 2 are OML unlocked, only BTS 0, 1 are actually connected to RSL. */
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,unlocked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock BTS 1 TRX 0");
+ f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
+ /* give it a moment to settle the FSM status */
+ f_sleep(1.0);
+
+ /* Now BTS 1 TRX 0 should reflect "locked". Note the RF policy stays "on", because this is still handled
+ * globally in osmo-bsc. Probably after sending "rf_locked 1" for a TRX, that TRX should reflect an RF policy
+ * of "off"? But that's for a future patch if at all. */
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,locked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: lock the already locked TRX, nothing should change");
+ f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "1");
+ f_sleep(1.0);
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,locked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock BTS 1 TRX 0");
+ f_ctrl_set(IPA_CTRL, "bts.1.trx.0.rf_locked", "0");
+ f_sleep(1.0);
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,unlocked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an already unlocked TRX, nothing should change");
+ f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
+ f_sleep(1.0);
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,unlocked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_logp(BSCVTY, "TC_ctrl_trx_rf_locked: unlock an inoperational TRX");
+ f_ctrl_set(IPA_CTRL, "bts.3.trx.0.rf_locked", "0");
+ f_sleep(1.0);
+ f_ctrl_get_exp(IPA_CTRL, "rf_states",
+ "0,0,operational,unlocked,on,rsl-up;" &
+ "1,0,operational,unlocked,on,rsl-up;" &
+ "2,0,operational,unlocked,on,rsl-down;" &
+ "2,1,operational,unlocked,on,rsl-down;" &
+ "2,2,operational,unlocked,on,rsl-down;" &
+ "2,3,operational,unlocked,on,rsl-down;" &
+ "3,0,inoperational,locked,on,rsl-down;");
+
+ f_shutdown_helper();
+}
+
+const CounterNameVals counternames_cm_serv_rej := {
+ { "cm_serv_rej", 0 },
+ { "cm_serv_rej:imsi_unknown_in_hlr", 0 },
+ { "cm_serv_rej:illegal_ms", 0 },
+ { "cm_serv_rej:imsi_unknown_in_vlr", 0 },
+ { "cm_serv_rej:imei_not_accepted", 0 },
+ { "cm_serv_rej:illegal_me", 0 },
+ { "cm_serv_rej:plmn_not_allowed", 0 },
+ { "cm_serv_rej:loc_not_allowed", 0 },
+ { "cm_serv_rej:roaming_not_allowed", 0 },
+ { "cm_serv_rej:network_failure", 0 },
+ { "cm_serv_rej:synch_failure", 0 },
+ { "cm_serv_rej:congestion", 0 },
+ { "cm_serv_rej:srv_opt_not_supported", 0 },
+ { "cm_serv_rej:rqd_srv_opt_not_supported", 0 },
+ { "cm_serv_rej:srv_opt_tmp_out_of_order", 0 },
+ { "cm_serv_rej:call_can_not_be_identified", 0 },
+ { "cm_serv_rej:incorrect_message", 0 },
+ { "cm_serv_rej:invalid_mandantory_inf", 0 },
+ { "cm_serv_rej:msg_type_not_implemented", 0 },
+ { "cm_serv_rej:msg_type_not_compatible", 0 },
+ { "cm_serv_rej:inf_eleme_not_implemented", 0 },
+ { "cm_serv_rej:condtional_ie_error", 0 },
+ { "cm_serv_rej:msg_not_compatible", 0 },
+ { "cm_serv_rej:protocol_error", 0 },
+ { "cm_serv_rej:retry_in_new_cell", 0 }
+};
+
+private function f_TC_cm_serv_rej(charstring id) runs on MSC_ConnHdlr
+{
+ f_create_chan_and_exp();
+ /* we should now have a COMPL_L3 at the MSC */
+ BSSAP.send(ts_PDU_DTAP_MT(ts_CM_SERV_REJ('02'O), '00'O));
+ RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, decmatch tr_CM_SERV_REJ));
+ f_perform_clear();
+ f_sleep(1.0);
+}
+testcase TC_cm_serv_rej() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_ctrs_bts_init(1, counternames_cm_serv_rej);
+
+ vc_conn := f_start_handler(refers(f_TC_cm_serv_rej), pars);
+ vc_conn.done;
+
+ f_ctrs_bts_add(0, "cm_serv_rej", 1);
+ f_ctrs_bts_add(0, "cm_serv_rej:imsi_unknown_in_hlr", 1);
+ f_ctrs_bts_verify();
+
+ f_sleep(1.0);
+ f_shutdown_helper();
+}
+
+/* Reproduce a segfault happening when the SDCCH (primary) lchan is lost in-between a TCH Channel Activ and its Channel
+ * Activ Ack (SYS#5627). */
+private function f_TC_lost_sdcch_during_assignment(charstring id) runs on MSC_ConnHdlr {
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ var BSSMAP_FIELD_CodecType codecType;
+ codecType := valueof(ass_cmd.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
+
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
+
+ /* First establish a signalling lchan */
+ f_create_chan_and_exp();
+ f_rslem_dchan_queue_enable();
+
+ /* we should now have a COMPL_L3 at the MSC */
+
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+ activate(as_Media_mgw());
+
+ var RslChannelNr chan_nr := { u := { ch0 := RSL_CHAN_NR_Bm_ACCH }, tn := 1 };
+ f_rslem_register(0, chan_nr);
+
+ f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
+ BSSAP.send(ass_cmd);
+
+
+ /* Wait for the Channel Activ for the TCH channel */
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
+
+ /* make the original SDCCH disappear */
+ RSL.send(ts_RSL_REL_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
+
+ /* and ACK the TCH channel activation. This caused a segfault up to OsmoBSC 1.7.0 (SYS#5627) */
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
+
+ interleave {
+ [] BSSAP.receive(tr_BSSMAP_AssignmentFail);
+ [] BSSAP.receive(tr_BSSMAP_ClearRequest);
+ }
+
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
+ var MgcpCommand mgcp;
+ var MGCP_RecvFrom mrf;
+ var template MgcpMessage msg_dlcx := { command := tr_DLCX };
+ alt {
+ [g_pars.aoip] MGCP.receive(tr_DLCX) -> value mgcp {
+ MGCP.send(ts_DLCX_ACK2(mgcp.line.trans_id));
+ }
+ [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) -> value mrf {
+ MGCP_MULTI.send(t_MGCP_SendToMrf(mrf, MgcpMessage:{
+ response := ts_DLCX_ACK2(mrf.msg.command.line.trans_id)
+ }));
+ }
+ }
+
+ f_sleep(0.5);
+}
+testcase TC_lost_sdcch_during_assignment() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ pars.fail_on_dlcx := false;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ vc_conn := f_start_handler(refers(f_TC_lost_sdcch_during_assignment), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+const CounterNameVals counternames_bsc_bts_all_available_allocated := {
+ { "all_allocated:sdcch", 0 },
+ { "all_allocated:static_sdcch", 0 },
+ { "all_allocated:tch", 0 },
+ { "all_allocated:static_tch", 0 }
+}
+
+private function f_all_allocated_expect_counter_change(charstring_list expect_changed) runs on test_CT
+{
+ /* Make sure counters settle first */
+ f_sleep(1.0);
+
+ /* Take a baseline of counters */
+ f_ctrs_bsc_and_bts_init(1, counternames_bsc_bts_all_available_allocated);
+
+ /* Elapse some time so that we see changes in counters, hopefully where expected */
+ f_sleep(2.0);
+
+ /* Get new counters */
+ var charstring_list all_changed := {};
+ all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bsc", g_ctr_bsc);
+ all_changed := all_changed & f_counter_name_vals_get_changed_n(IPA_CTRL, "bts", g_ctr_bts);
+
+ /* Compare with expectations */
+ var charstring_list all_expect_changed := {};
+ for (var integer i := 0; i < lengthof(expect_changed); i := i + 1) {
+ all_expect_changed := all_expect_changed & { "bsc.0." & expect_changed[i], "bts.0." & expect_changed[i] };
+ }
+ f_counter_name_vals_expect_changed_list(all_changed, all_expect_changed);
+}
+
+testcase TC_ratectr_all_available_allocated() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init(1, guard_timeout := 60.0);
+ f_sleep(1.0);
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ var DchanTuples chan_cleanup := {};
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* Since only bts 0 is connected, expecting all_allocated to become true for both bts 0 and the "global" bsc
+ * level.
+ * All SDCCH are now occupied. */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
+
+ /* Also fill up all remaining (TCH) channels */
+ for (i := 0; i < NUM_TCHF_PER_BTS + NUM_TCHH_PER_BTS; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* All TCH are now also occupied */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(chan_cleanup[i]);
+ }
+
+ f_shutdown_helper();
+}
+
+testcase TC_ratectr_all_available_allocated_dyn() runs on test_CT {
+ var ASP_RSL_Unitdata rsl_ud;
+ var integer i;
+ var integer chreq_total, chreq_nochan;
+
+ f_init_vty();
+ f_ts_set_chcomb(0, 0, 2, "TCH/F_TCH/H_PDCH");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+ /* Now we have 3 TCH/F, 1 OSMO_DYN, 1 TCH/H */
+
+ f_init(1, guard_timeout := 60.0);
+ f_sleep(1.0);
+
+ /* The dyn TS wants to activate PDCH mode, ACK that. */
+ var RslChannelNr chan_nr;
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ /* Exhaust all dedicated SDCCH lchans.
+ /* GSM 44.018 Table 9.1.8.2:
+ * RA = '13'O -> Establishment cause = 0001xxxx (MS dual rate capable and asks for "SDCCH").
+ */
+ var DchanTuples chan_cleanup := {};
+ for (i := 0; i < NUM_SDCCH_PER_BTS; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('13'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* The static SDCCH should now be occupied, while still 3x8 dynamic SDCCH potentially remain. So only
+ * all_allocated:static_sdcch is counted, all_allocated:sdcch remains zero. */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch"});
+
+ /* Request more SDCCH, hence convert the first dyn TS to SDCCH8.
+ * Will release them later, so remember all the DchanTuples. */
+ var DchanTuples dyn_sddch := {};
+ dyn_sddch := dyn_sddch & { f_est_dchan_dyn('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+
+ /* Also occupy the seven other SDCCH of the dyn TS */
+ for (i := 0; i < 7; i := i+1) {
+ dyn_sddch := dyn_sddch & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* Now all dynamic SDCCH are also occupied, so for the first time all_allocated:sdcch will trigger... */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch"});
+
+ /* occupy the remaining TCH, three TCH/F and two TCH/H lchans */
+ for (i := 0; i < 5; i := i+1) {
+ chan_cleanup := chan_cleanup & { f_est_dchan('33'O, NUM_SDCCH_PER_BTS + i, gen_l3_valid_payload()) };
+ }
+
+ /* All TCH lchans are now also occupied, both static and dynamic */
+ f_all_allocated_expect_counter_change({"all_allocated:sdcch", "all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ /* Starting to release the dyn TS: as soon as the first SDCCH gets released, all_allocated:sdcch stops
+ * incrementing. */
+ var BssmapCause cause := 0;
+ var DchanTuple dt := dyn_sddch[0];
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt);
+
+ /* one dyn TS SDCCH is free again, so only the static_sdcch should increment. For tch, both static and dynamic
+ * count as occupied, so those still both increment. */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch",
+ "all_allocated:tch", "all_allocated:static_tch"});
+
+ /* Release the remaining SDCCH of the dyn TS, so it becomes available as TCH again */
+ for (i := 1; i < lengthof(dyn_sddch); i := i+1) {
+ dt := dyn_sddch[i];
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ts_BSSMAP_ClearCommand(cause)));
+ f_exp_chan_rel_and_clear(dt);
+ }
+
+ /* All SDCCH on the dyn TS are released, the dyn TS wants to activate PDCH again */
+ chan_nr := valueof(t_RslChanNr_PDCH(2));
+ f_exp_ipa_rx(tr_RSL_CHAN_ACT_PDCH(chan_nr));
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 2342));
+
+ /* Now all channels are occupied except the dyn TS, so expecting only the static counters to increment */
+ f_all_allocated_expect_counter_change({"all_allocated:static_sdcch", "all_allocated:static_tch"});
+
+ /* Clean up SDCCH lchans */
+ for (i := 0; i < lengthof(chan_cleanup); i := i + 1) {
+ f_perform_clear_test_ct(chan_cleanup[i]);
+ }
+
+ /* clean up config */
+ f_ts_reset_chcomb(0);
+
+ f_shutdown_helper();
+}
+
+private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
+runs on test_CT {
+ /* MSC sends an Assignment Request */
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
+
+ /* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
+ var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
+ /* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
+ f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
+ /* Expect to receive an Assignment Failure */
+ BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
+}
+
+testcase TC_chan_alloc_algo_ascending() runs on test_CT {
+ /* We need to access BTS2, which has 4 TRXs */
+ f_init(nr_bts := 3);
+
+ /* HACK: work around "Couldn't find Expect for CRCX" */
+ vc_MGCP[0].stop;
+
+ f_vty_enter_cfg_bts(BSCVTY, 2);
+ f_vty_transceive(BSCVTY, "channel allocator ascending");
+ f_vty_transceive(BSCVTY, "end");
+
+ /* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
+ for (var integer i := 0; i < 4; i := i + 1) {
+ var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
+ f_TC_chan_alloc_algo(dt, {2, 0});
+ f_perform_clear_test_ct(dt);
+ }
+
+ /* At this point all 4 x TCH/F channels are BORKEN, but they will be
+ * resurrected upon the A-bis/OML link re-establishment. */
+ f_shutdown_helper();
+}
+
+testcase TC_chan_alloc_algo_descending() runs on test_CT {
+ /* We need to access BTS2, which has 4 TRXs */
+ f_init(nr_bts := 3);
+
+ /* HACK: work around "Couldn't find Expect for CRCX" */
+ vc_MGCP[0].stop;
+
+ f_vty_enter_cfg_bts(BSCVTY, 2);
+ f_vty_transceive(BSCVTY, "channel allocator descending");
+ f_vty_transceive(BSCVTY, "end");
+
+ /* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
+ for (var integer i := 0; i < 5; i := i + 1) {
+ var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), {2, 0});
+ f_TC_chan_alloc_algo(dt, {2, 3});
+ f_perform_clear_test_ct(dt);
+ }
+
+ /* At this point all 5 x TCH/F channels are BORKEN, but they will be
+ * resurrected upon the A-bis/OML link re-establishment. */
+ f_shutdown_helper();
+}
+
+testcase TC_chan_alloc_algo_ass_dynamic() runs on test_CT {
+ const BtsTrxIdx TRX0 := {2, 0};
+ const BtsTrxIdx TRX3 := {2, 3};
+
+ /* We need to access BTS2, which has 4 TRXs */
+ f_init(nr_bts := 3);
+
+ /* HACK: work around "Couldn't find Expect for CRCX" */
+ vc_MGCP[0].stop;
+
+ f_vty_enter_cfg_bts(BSCVTY, 2);
+ f_vty_transceive(BSCVTY, "channel allocator mode assignment dynamic");
+ f_vty_transceive(BSCVTY, "channel allocator dynamic-param ul-rxlev thresh 50 avg-num 2");
+ f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 0");
+ f_vty_transceive(BSCVTY, "end");
+
+ var DchanTuple dt;
+
+ f_logp(BSCVTY, "Case a) Unknown Uplink RxLev, fall-back to ascending");
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
+ f_TC_chan_alloc_algo(dt, TRX0);
+ f_perform_clear_test_ct(dt);
+
+ f_logp(BSCVTY, "Case b) Not enough RxLev samples, use ascending");
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
+ ts_RSL_IE_UplinkMeas(30, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_sleep(0.3); /* give the IUT some time to process sent MRs */
+ f_TC_chan_alloc_algo(dt, TRX0);
+ f_perform_clear_test_ct(dt);
+
+ f_logp(BSCVTY, "Case c) Uplink RxLev below the threshold, use ascending");
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
+ ts_RSL_IE_UplinkMeas(45, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
+ ts_RSL_IE_UplinkMeas(48, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_sleep(0.3); /* give the IUT some time to process sent MRs */
+ f_TC_chan_alloc_algo(dt, TRX0);
+ f_perform_clear_test_ct(dt);
+
+ f_logp(BSCVTY, "Case d) Uplink RxLev above the threshold, use descending");
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
+ ts_RSL_IE_UplinkMeas(50, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
+ ts_RSL_IE_UplinkMeas(58, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_sleep(0.3); /* give the IUT some time to process sent MRs */
+ f_TC_chan_alloc_algo(dt, TRX3);
+ f_perform_clear_test_ct(dt);
+
+ f_vty_enter_cfg_bts(BSCVTY, 2);
+ f_vty_transceive(BSCVTY, "channel allocator dynamic-param c0-chan-load thresh 90");
+ f_vty_transceive(BSCVTY, "end");
+
+ f_logp(BSCVTY, "Case e) Uplink RxLev above the threshold, but C0 load is not");
+ dt := f_est_dchan('23'O, 23, gen_l3_valid_payload(), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 0,
+ ts_RSL_IE_UplinkMeas(50, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_ipa_tx(ts_RSL_MEAS_RES_EMPTY(dt.rsl_chan_nr, 1,
+ ts_RSL_IE_UplinkMeas(58, 0),
+ ts_RSL_IE_BS_Power(0)), TRX0);
+ f_sleep(0.3); /* give the IUT some time to process sent MRs */
+ f_TC_chan_alloc_algo(dt, TRX0);
+ f_perform_clear_test_ct(dt);
+
+ f_vty_enter_cfg_bts(BSCVTY, 2);
+ f_vty_transceive(BSCVTY, "channel allocator ascending");
+ f_vty_transceive(BSCVTY, "end");
+
+ /* At this point some TCH/F channels are BORKEN, but they will be
+ * resurrected upon the A-bis/OML link re-establishment. */
+ f_shutdown_helper();
+}
+
+private function f_vty_mgw_enable(integer mgw_nr := 1) runs on test_CT {
+ var rof_charstring cmds := {
+ "remote-ip " & mp_test_ip,
+ "remote-port " & int2str(2427 + mgw_nr)
+ };
+ f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
+ f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " reconnect")
+}
+private function f_vty_mgw_disable(integer mgw_nr := 1) runs on test_CT {
+ f_vty_config3(BSCVTY, {"network"}, { "no mgw " &int2str(mgw_nr) });
+}
+private function f_vty_mgw_block(integer mgw_nr := 1, boolean blocked := true) runs on test_CT {
+ var charstring arg;
+ if (blocked) {
+ arg := "block";
+ } else {
+ arg := "unblock";
+ }
+ f_vty_transceive(BSCVTY, "mgw " & int2str(mgw_nr) & " " & arg);
+}
+private function f_vty_mgw_cfg_keepalive(integer mgw_nr := 1, integer req_intval := 0, charstring req_endp := "null", integer rx_timeout := 0) runs on test_CT {
+ var charstring arg;
+ var rof_charstring cmds := {
+ "keepalive request-interval " & int2str(req_intval),
+ "keepalive request-endpoint " & req_endp,
+ "keepalive timeout " & int2str(rx_timeout)
+ };
+ f_vty_config3(BSCVTY, {"network", "mgw " & int2str(mgw_nr)}, cmds);
+}
+private const charstring COORD_CMD_ESTABLISHED := "COORD_CMD_ESTABLISHED";
+private function f_TC_mgwpool_call_seq_1(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 0);
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+ COORD.send(COORD_CMD_ESTABLISHED);
+
+ COORD.receive(COORD_CMD_ESTABLISHED);
+ f_perform_clear()
+ f_create_mgcp_delete_ep(g_media.mgcp_ep);
+}
+private function f_TC_mgwpool_call_seq_2(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(ass_cid := 1);
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+
+ COORD.receive(COORD_CMD_ESTABLISHED);
+ f_establish_fully(ass_cmd, exp_compl);
+ COORD.send(COORD_CMD_ESTABLISHED);
+
+ f_perform_clear()
+ f_create_mgcp_delete_ep(g_media.mgcp_ep);
+}
+/* Test load is spread around 2 available MGWs */
+testcase TC_mgwpool_all_used() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+ pars1.mgwpool_idx := 0;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.mgwpool_idx := 1;
+ pars2.media_nr := 2;
+
+ f_init(1, true, nr_mgw := 2);
+ f_sleep(1.0);
+
+ f_vty_mgw_enable(1);
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_vty_mgw_disable(1);
+
+ f_shutdown_helper();
+}
+
+/* Test blocked MGW in the pool are not selected */
+testcase TC_mgwpool_blocked_not_used() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+ pars1.mgwpool_idx := 0;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.mgwpool_idx := 0; /* expect it in the first one, since the second will be blocked */
+ pars2.media_nr := 2;
+
+ f_init(1, true, nr_mgw := 2);
+ f_sleep(1.0);
+
+ f_vty_mgw_enable(1);
+ f_vty_mgw_block(1, true);
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_vty_mgw_disable(1);
+
+ f_shutdown_helper();
+}
+
+/* Test BTS pinning to an MGW is applied */
+testcase TC_mgwpool_pin_bts() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+ pars1.mgwpool_idx := 0;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.mgwpool_idx := 0; /* expect it in the first one, since the BTS is pinned to the first MGW */
+ pars2.media_nr := 2;
+
+ f_init(1, true, nr_mgw := 2);
+ f_sleep(1.0);
+
+ f_vty_mgw_enable(1);
+ f_vty_cfg_bts(BSCVTY, 0, { "mgw pool-target 0" });
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_call_seq_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_call_seq_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_vty_cfg_bts(BSCVTY, 0, { "no mgw pool-target" } );
+ f_vty_mgw_disable(1);
+
+ f_shutdown_helper();
+}
+
+/* Test keepalive procedure on the MGW */
+private function f_TC_mgwpool_keepalive_mgw0(charstring id) runs on MSC_ConnHdlr {
+ /* Make sure the MGW is considered DOWN by the keepalive. See "timeout"
+ * param in TC_mgwpool_keepalive. */
+ f_sleep(3.0);
+
+ COORD.send(COORD_CMD_ESTABLISHED);
+
+ /* Wait for signal that call was established successfully over the other MSC/MGW: */
+ COORD.receive(COORD_CMD_ESTABLISHED);
+}
+private function f_TC_mgwpool_keepalive_mgw1(charstring id) runs on MSC_ConnHdlr {
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ /* Wait for other MSC/MGW component to tell us the timeout is done and
+ * we can start the call, which will be assigned to use because the other
+ * MGW will be seen as DOWN. */
+ COORD.receive(COORD_CMD_ESTABLISHED);
+ f_establish_fully(ass_cmd, exp_compl);
+ /* signal that call was established successfully over the other MSC/MGW: */
+ COORD.send(COORD_CMD_ESTABLISHED);
+
+ f_perform_clear()
+ f_create_mgcp_delete_ep(g_media.mgcp_ep);
+}
+testcase TC_mgwpool_keepalive_down_not_used() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+ pars1.mgwpool_idx := 0;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.mgwpool_idx := 1; /* expect it in the second one, since the first will be considered DOWN */
+ pars2.media_nr := 2;
+
+ f_init(1, true, nr_mgw := 2);
+ f_sleep(1.0);
+
+ f_vty_mgw_cfg_keepalive(0, req_intval := 1, req_endp := "null", rx_timeout := 3);
+ f_vty_mgw_enable(1);
+ f_vty_mgw_block(1, false);
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_TC_mgwpool_keepalive_mgw0), pars1);
+ f_start_handler_run(vc_conn2, refers(f_TC_mgwpool_keepalive_mgw1), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_vty_mgw_disable(1);
+ /* disable keepalive (default status): */
+ f_vty_mgw_cfg_keepalive(0, req_intval := 0, req_endp := "null", rx_timeout := 0);
+
+ f_shutdown_helper();
+}
+
+private function f_tc_ho_meas_rep_multi_band(charstring id) runs on MSC_ConnHdlr {
+ g_pars := f_gen_test_hdlr_pars();
+ var PDU_BSSAP ass_req := f_gen_ass_req();
+ ass_req.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_req.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ f_establish_fully(ass_req, exp_compl);
+
+ /* Send a measurement report with bad rxlev except on 3rd entry. The
+ * measurement report is divided into two sub lists, as described in
+ * 3GPP TS 04.08 § 10.5.2.20. */
+ var NcellReports neighbor_rep := {
+ /* Sub list 1: same band */
+ { rxlev := 0, bcch_freq := 0, bsic := 12 }, /* ARFCN 800, band 1800, LAC 98 */
+ /* Sub list 2: different band */
+ { rxlev := 0, bcch_freq := 1, bsic := 13 }, /* ARFCN 200, band 850, LAC 97 */
+ { rxlev := 40, bcch_freq := 2, bsic := 14 }, /* ARFCN 1000, band 900, LAC 99 */
+ { rxlev := 0, bcch_freq := 3, bsic := 11 } /* ARFCN 0, band 900, LAC 96 */
+ };
+ var octetstring l3_mr := enc_GsmRrL3Message(valueof(ts_MEAS_REP(true, 8, 8, reps := neighbor_rep)));
+ RSL.send(ts_RSL_MEAS_RES(g_chan_nr, 0, ts_RSL_IE_UplinkMeas, ts_RSL_IE_BS_Power(0), ts_RSL_IE_L1Info,
+ l3_mr, 0));
+
+ /* Expect a handover to the third entry. If the BSC parsed the report
+ * correctly, the third entry has LAC 99. */
+ var template BSSMAP_FIELD_CellIdentificationList cid_list := {
+ cIl_LAC := { ts_BSSMAP_CI_LAC(99) }
+ };
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequired(cid_list := cid_list)) {
+ setverdict(pass);
+ }
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequired()) {
+ setverdict(fail, "Handover has unexpected LAC in Cell Identification List. The BSC probably"
+ & " didn't parse the multi-band measurement report correctly.");
+ }
+ }
+
+ f_ho_out_of_this_bsc(skip_meas_rep := true);
+}
+testcase TC_ho_meas_rep_multi_band() runs on test_CT {
+ /* Verify that the BSC parses the measurement report correctly when
+ * neighbors in multiple bands are configured (OS#5717). See
+ * gsm_arfcn2band_rc() in libosmocore src/gsm/gsm_utils.c for the
+ * ARFCN -> band mapping. The MS is connected to band 1800. */
+ var MSC_ConnHdlr vc_conn;
+
+ f_init_vty();
+ f_bts_0_cfg(BSCVTY,
+ {"neighbor-list mode automatic",
+ "handover 1",
+ "handover algorithm 2",
+ "handover2 window rxlev averaging 1",
+ "no neighbors",
+ "neighbor lac 99 arfcn 1000 bsic any", /* band 900 */
+ "neighbor lac 98 arfcn 800 bsic any", /* band 1800 */
+ "neighbor lac 97 arfcn 200 bsic any", /* band 850 */
+ "neighbor lac 96 arfcn 0 bsic any"}); /* band 900 */
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ f_ctrs_bsc_and_bts_handover_init();
+
+ vc_conn := f_start_handler(refers(f_tc_ho_meas_rep_multi_band));
+ vc_conn.done;
+
+ f_ctrs_bsc_and_bts_add(0, "assignment:attempted");
+ f_ctrs_bsc_and_bts_add(0, "assignment:completed");
+ f_ctrs_bsc_and_bts_add(0, "handover:attempted");
+ f_ctrs_bsc_and_bts_add(0, "handover:completed");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:attempted");
+ f_ctrs_bsc_and_bts_add(0, "interbsc_ho_out:completed");
+ f_ctrs_bsc_and_bts_verify();
+ f_shutdown_helper(ho := true);
+}
+
+private function f_vty_expect_borken(TELNETasp_PT pt, boolean expect_borken)
+{
+ var charstring lchan_summary;
+ lchan_summary := f_vty_transceive_ret(pt, "show lchan summary");
+ var boolean found_borken := (f_strstr(lchan_summary, "State BORKEN") >= 0);
+ if (found_borken != expect_borken) {
+ if (expect_borken) {
+ setverdict(fail, "Expected 'BORKEN' state in ", lchan_summary);
+ } else {
+ setverdict(fail, "Expected no 'BORKEN' state in ", lchan_summary);
+ }
+ mtc.stop;
+ }
+}
+
+private function f_tc_unbreak_lchan_after_missing_rel_ack(integer test_variant) runs on MSC_ConnHdlr {
+
+ /* Establish a channel, so we can mess with the release of it. */
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ /* shorten X28, the time after which a BORKEN lchan recovers, from 30s to something short */
+ f_vty_enter_cfg_network(BSCVTY);
+ f_vty_transceive(BSCVTY, "timer X28 3");
+ f_vty_transceive(BSCVTY, "end");
+
+ /* Allow us to include handling of Channel Activation in this component, to test recovery from BORKEN */
+ f_rslem_set_auto_chan_act_ack(RSL_PROC, false);
+
+ /* give a moment before releasing */
+ f_sleep(2.0);
+
+ /* Perform a channel release, but omit the RF CHAN REL ACK. The aim is to get the lchan to go BORKEN. */
+ f_perform_clear(send_rel_ack := false);
+
+ f_vty_expect_borken(BSCVTY, false);
+
+ /* After a timeout of X6, the lchan ends up in LCHAN_ST_BORKEN */
+ f_sleep(6.0);
+
+ f_vty_expect_borken(BSCVTY, true);
+
+ /* Now within two seconds, we expect OsmoBSC to attempt recovering from the broken state.
+ *
+ * test_variant == 1:
+ * It will first attempt a Channel Activation. If the BTS accepts that, it means the state is back in sync.
+ * Then OsmoBSC releases the lchan again and makes it available for use.
+ *
+ * test_variant == 2:
+ * It will first attempt a Channel Activation and the BTS NACKs that.
+ * It will then attempt a release, which we ACK, and the channel will be available again.
+ */
+
+ /* Receive the Channel Activation */
+ var ASP_RSL_Unitdata rx_rsl_ud;
+ RSL.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl_ud;
+
+ var RslChannelNr chan_nr;
+ var RSL_IE_Body ie;
+ if (f_rsl_find_ie(rx_rsl_ud.rsl, RSL_IE_CHAN_NR, ie) == true) {
+ chan_nr := ie.chan_nr;
+ } else {
+ setverdict(fail, "Unable to find RSL_IE_CHAN_NR in ", rx_rsl_ud);
+ return;
+ }
+
+ if (test_variant == 1) {
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl_ud.streamId));
+
+ /* Back in sync, receive the Channel Release */
+ RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr));
+ RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+ } else if (test_variant == 2) {
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_NACK(chan_nr, RSL_ERR_EQUIPMENT_FAIL), rx_rsl_ud.streamId));
+
+ /* Instead tries a release */
+ RSL.receive(tr_RSL_RF_CHAN_REL(chan_nr));
+ RSL.send(ts_RSL_RF_CHAN_REL_ACK(chan_nr));
+ /* That worked, channel usable again */
+ } else {
+ setverdict(fail, "undefined test_variant ", test_variant);
+ }
+
+ f_vty_expect_borken(BSCVTY, false);
+ setverdict(pass);
+}
+
+/* Test recovery path from a BORKEN lchan */
+private function f_TC_unbreak_lchan_after_missing_rel_ack_1(charstring id) runs on MSC_ConnHdlr {
+ f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 1);
+}
+testcase TC_unbreak_lchan_after_missing_rel_ack_1() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_1), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_TC_unbreak_lchan_after_missing_rel_ack_2(charstring id) runs on MSC_ConnHdlr {
+ f_tc_unbreak_lchan_after_missing_rel_ack(test_variant := 2);
+}
+testcase TC_unbreak_lchan_after_missing_rel_ack_2() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+ f_init(1, true);
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_TC_unbreak_lchan_after_missing_rel_ack_2), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
control {
/* CTRL interface testing */
execute( TC_ctrl_msc_connection_status() );
execute( TC_ctrl_msc0_connection_status() );
+ /* In SCCPlite tests, only one MSC is configured. These tests assume that three MSCs are configured, so only run
+ * these in the AoIP test suite. */
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ execute( TC_stat_num_msc_connected_1() );
+ execute( TC_stat_num_msc_connected_2() );
+ execute( TC_stat_num_msc_connected_3() );
+ }
+ execute( TC_stat_num_bts_connected_1() );
+ execute( TC_stat_num_bts_connected_2() );
+ execute( TC_stat_num_bts_connected_3() );
execute( TC_ctrl() );
if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_SCCPlite_SERVER) {
execute( TC_ctrl_location() );
@@ -5975,12 +12596,15 @@ control {
execute( TC_si2quater_48_earfcns() );
execute( TC_si2quater_49_earfcns() );
execute( TC_si_acc_rotate() );
- execute (TC_si_acc_ramp_rotate() );
+ execute( TC_si_acc_ramp_rotate() );
+ execute( TC_si2_ncc_permitted() ); /* TODO: test in SI6 too */
/* RSL DCHAN Channel ACtivation / Deactivation */
execute( TC_chan_act_noreply() );
execute( TC_chan_act_counter() );
execute( TC_chan_act_ack_noest() );
+ execute( TC_chan_act_ack_noest_emerg() );
+ execute( TC_chan_rqd_emerg_deny() );
execute( TC_chan_act_ack_est_ind_noreply() );
execute( TC_chan_act_ack_est_ind_refused() );
execute( TC_chan_act_nack() );
@@ -5989,11 +12613,14 @@ control {
execute( TC_chan_rel_rll_rel_ind() );
execute( TC_chan_rel_conn_fail() );
execute( TC_chan_rel_hard_clear() );
+ execute( TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb() );
+ execute( TC_chan_rel_last_eutran_plmn_hard_clear_csfb() );
execute( TC_chan_rel_hard_clear_csfb() );
execute( TC_chan_rel_hard_rlsd() );
execute( TC_chan_rel_hard_rlsd_ms_dead() );
execute( TC_chan_rel_a_reset() );
execute( TC_chan_rel_sccp_tiar_timeout() );
+ execute( TC_chan_rel_rr_cause() );
execute( TC_outbound_connect() );
@@ -6002,6 +12629,9 @@ control {
execute( TC_assignment_csd() );
execute( TC_assignment_ctm() );
execute( TC_assignment_sign() );
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ execute( TC_assignment_aoip_tla_v6() );
+ }
execute( TC_assignment_fr_a5_0() );
execute( TC_assignment_fr_a5_1() );
if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
@@ -6009,11 +12639,17 @@ control {
}
execute( TC_assignment_fr_a5_3() );
execute( TC_assignment_fr_a5_4() );
+ execute( TC_assignment_fr_a5_4_fail() );
+ execute( TC_assignment_fr_a5_not_sup() );
execute( TC_ciph_mode_a5_0() );
execute( TC_ciph_mode_a5_1() );
+ execute( TC_ciph_mode_a5_2_0() );
+ execute( TC_ciph_mode_a5_2_1() );
execute( TC_ciph_mode_a5_3() );
+ execute( TC_ciph_mode_a5_4() );
execute( TC_assignment_codec_fr() );
+ execute( TC_assignment_codec_fr_by_mode_modify() );
execute( TC_assignment_codec_hr() );
execute( TC_assignment_codec_efr() );
execute( TC_assignment_codec_amr_f() );
@@ -6037,6 +12673,11 @@ control {
execute( TC_assignment_codec_amr_f_zero() );
execute( TC_assignment_codec_amr_f_unsupp() );
execute( TC_assignment_codec_amr_h_S7() );
+ execute( TC_assignment_codec_amr_f_start_mode_auto() );
+ execute( TC_assignment_codec_amr_h_start_mode_auto() );
+ execute( TC_assignment_codec_amr_f_start_mode_4() );
+ execute( TC_assignment_codec_amr_h_start_mode_4() );
+ execute( TC_assignment_codec_amr_startmode_cruft() );
}
execute( TC_assignment_codec_fr_exhausted_req_hr() );
@@ -6049,10 +12690,14 @@ control {
execute( TC_assignment_codec_hr_exhausted_req_fr_hr() );
execute( TC_assignment_codec_req_hr_fr() );
execute( TC_assignment_codec_req_fr_hr() );
+ execute( TC_assignment_sdcch_exhausted_req_signalling() );
+ execute( TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden() );
+ execute( TC_assignment_sdcch_exhausted_req_voice_tch_forbidden() );
- if (mp_enable_osmux_test) {
- execute( TC_assignment_osmux() );
- }
+ execute( TC_assignment_codec_hr_osmux_on() );
+ execute( TC_assignment_osmux() );
+ execute( TC_assignment_osmux_cn() );
+ execute( TC_assignment_osmux_bts() );
/* RLL Establish Indication on inactive DCHAN / SAPI */
execute( TC_rll_est_ind_inact_lchan() );
@@ -6060,6 +12705,15 @@ control {
execute( TC_rll_est_ind_inval_sapi3() );
execute( TC_rll_est_ind_inval_sacch() );
+ /* DLCI / RSL Link ID conversion for MO/MT messages on SAPI0/SAPI3 */
+ execute( TC_tch_dlci_link_id_sapi() );
+
+ /* SAPI N Reject triggered by RLL establishment failures */
+ execute( TC_rll_rel_ind_sapi_n_reject() );
+ execute( TC_rll_err_ind_sapi_n_reject() );
+ execute( TC_rll_timeout_sapi_n_reject() );
+ execute( TC_rll_sapi_n_reject_dlci_cc() );
+
/* Paging related tests */
execute( TC_paging_imsi_nochan() );
execute( TC_paging_tmsi_nochan() );
@@ -6083,6 +12737,9 @@ control {
execute( TC_paging_imsi_load() );
execute( TC_paging_counter() );
execute( TC_paging_resp_unsol() );
+ execute( TC_paging_500req() );
+ execute( TC_paging_450req_no_paging_load_ind() );
+ execute( TC_paging_imsi_nochan_ci_resp_invalid_mi() );
execute( TC_rsl_drop_counter() );
execute( TC_rsl_unknown_unit_id() );
@@ -6098,17 +12755,41 @@ control {
execute( TC_err_84_unknown_msg() );
execute( TC_ho_int() );
+ execute( TC_ho_int_a5_0() );
+ execute( TC_ho_int_a5_1() );
+ execute( TC_ho_int_a5_3() );
+ execute( TC_ho_int_a5_4() );
+ execute( TC_ho_int_radio_link_failure() );
- execute( TC_ho_out_of_this_bsc() );
+ /* TC_ho_out_of_this_bsc is run last, see comment below */
execute( TC_ho_out_fail_no_msc_response() );
execute( TC_ho_out_fail_rr_ho_failure() );
execute( TC_ho_out_fail_no_result_after_ho_cmd() );
execute( TC_ho_into_this_bsc() );
+ execute( TC_ho_into_this_bsc_a5_0() );
+ execute( TC_ho_into_this_bsc_a5_1() );
+ execute( TC_ho_into_this_bsc_a5_3() );
+ execute( TC_ho_into_this_bsc_a5_4() );
+ execute( TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg() );
+ execute( TC_ho_into_this_bsc_a5_1_3() );
+ execute( TC_ho_into_this_bsc_a5_mismatch() );
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ execute( TC_ho_into_this_bsc_tla_v6() );
+ }
+ execute( TC_srvcc_eutran_to_geran() );
+ execute( TC_srvcc_eutran_to_geran_a5_3() );
+ execute( TC_srvcc_eutran_to_geran_src_sai() );
+ execute( TC_srvcc_eutran_to_geran_ho_out() );
+ execute( TC_srvcc_eutran_to_geran_forbid_fast_return() );
+ execute( TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return() );
execute( TC_ho_in_fail_msc_clears() );
execute( TC_ho_in_fail_msc_clears_after_ho_detect() );
execute( TC_ho_in_fail_no_detect() );
execute( TC_ho_in_fail_no_detect2() );
+ execute( TC_ho_in_fail_mgw_mdcx_timeout() );
+ execute( TC_ho_in_fail_ipa_crcx_timeout() );
+ execute( TC_ho_into_this_bsc_sccp_cr_without_bssap() );
execute( TC_ho_neighbor_config_1() );
execute( TC_ho_neighbor_config_2() );
@@ -6126,12 +12807,17 @@ control {
execute( TC_dyn_pdch_ipa_act_nack() );
execute( TC_dyn_pdch_osmo_act_deact() );
execute( TC_dyn_pdch_osmo_act_nack() );
+ execute( TC_dyn_ts_sdcch8_act_deact() );
+ execute( TC_dyn_ts_sdcch8_all_subslots_used() );
+ execute( TC_dyn_ts_sdcch8_tch_call_act_deact() );
+ execute( TC_dyn_ts_sdcch8_act_nack() );
execute( TC_chopped_ipa_ping() );
execute( TC_chopped_ipa_payload() );
/* Power control related */
execute( TC_assignment_verify_ms_power_params_ie() );
+ execute( TC_c0_power_red_mode() );
/* MSC pooling */
/* FIXME: in SCCPlite, indicating how many MSCs should be connected does currently not work. Since
@@ -6152,12 +12838,87 @@ control {
execute( TC_mscpool_paging_and_response_tmsi() );
execute( TC_mscpool_no_allow_attach_round_robin() );
execute( TC_mscpool_no_allow_attach_valid_nri() );
+
+ execute( TC_mscpool_sccp_n_pcstate_detaches_msc() );
+ execute( TC_mscpool_sccp_n_pcstate_attaches_msc() );
}
- /* at bottom as they might crash OsmoBSC before OS#3182 is fixed */
execute( TC_early_conn_fail() );
execute( TC_late_conn_fail() );
+ execute( TC_stats_conn_fail() );
+
+ /* Emergency call handling (deny / allow) */
+ execute( TC_assignment_emerg_setup_allow() );
+ execute( TC_assignment_emerg_setup_allow_imei() );
+ execute( TC_assignment_emerg_setup_deny_msc() );
+ execute( TC_assignment_emerg_setup_deny_bts() );
+ execute( TC_emerg_premption() );
+
+ /* Frequency hopping parameters handling */
+ execute( TC_fh_params_chan_activ() );
+ execute( TC_fh_params_imm_ass() );
+ execute( TC_fh_params_assignment_cmd() );
+ execute( TC_fh_params_handover_cmd() );
+ execute( TC_fh_params_si4_cbch() );
+
+ if (mp_enable_lcs_tests) {
+ execute( TC_lcs_loc_req_for_active_ms() );
+ execute( TC_lcs_loc_req_for_active_ms_ta_req() );
+ execute( TC_lcs_loc_req_for_idle_ms() );
+ execute( TC_lcs_loc_req_no_subscriber() );
+ execute( TC_lcs_loc_req_for_active_ms_le_timeout() );
+ execute( TC_lcs_loc_req_for_active_ms_le_timeout2() );
+ execute( TC_lcs_loc_req_for_idle_ms_no_pag_resp() );
+ execute( TC_cm_service_during_lcs_loc_req() );
+ execute( TC_ho_during_lcs_loc_req() );
+ execute( TC_emerg_call_and_lcs_loc_req() );
+ execute( TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind() );
+ execute( TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail() );
+ }
+
+ execute( TC_no_msc() );
+
+ execute( TC_refuse_chan_act_to_vamos() );
+ execute( TC_refuse_mode_modif_to_vamos() );
+
+ execute( TC_reassignment_fr() );
+
+ execute( TC_cm_reestablishment() );
+
+ execute( TC_imm_ass_post_chan_ack() );
+ execute( TC_imm_ass_pre_chan_ack() );
+ execute( TC_imm_ass_pre_ts_ack() );
+ execute( TC_imm_ass_pre_chan_ack_dyn_ts() );
+ execute( TC_imm_ass_pre_ts_ack_dyn_ts() );
+
+ execute( TC_ctrl_trx_rf_locked() );
+
+ execute( TC_ratectr_all_available_allocated() );
+ execute( TC_ratectr_all_available_allocated_dyn() );
+
+ execute( TC_cm_serv_rej() );
+
+ execute( TC_lost_sdcch_during_assignment() );
+
+ /* Channel allocator */
+ execute( TC_chan_alloc_algo_ascending() );
+ execute( TC_chan_alloc_algo_descending() );
+ execute( TC_chan_alloc_algo_ass_dynamic() );
+
+ /* MGW pool */
+ execute( TC_mgwpool_all_used() );
+ execute( TC_mgwpool_blocked_not_used() );
+ execute( TC_mgwpool_pin_bts() );
+ execute( TC_mgwpool_keepalive_down_not_used() );
+
+ execute( TC_ho_meas_rep_multi_band() );
+
+ /* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
+ * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
+ execute( TC_ho_out_of_this_bsc() );
+ execute( TC_unbreak_lchan_after_missing_rel_ack_1() );
+ execute( TC_unbreak_lchan_after_missing_rel_ack_2() );
}
}
diff --git a/bsc/BSC_Tests_ASCI.ttcn b/bsc/BSC_Tests_ASCI.ttcn
new file mode 100644
index 00000000..a97e0db7
--- /dev/null
+++ b/bsc/BSC_Tests_ASCI.ttcn
@@ -0,0 +1,808 @@
+module BSC_Tests_ASCI {
+
+/* Integration Tests for OsmoBSC
+ * (C) 2023 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ *
+ * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from Misc_Helpers all;
+
+import from BSC_Tests all;
+import from BSSAP_Types all;
+import from BSSAP_CodecPort all;
+import from BSSMAP_Templates all;
+import from RSL_Types all;
+import from RSL_Emulation all;
+import from MGCP_Emulation all;
+
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_Types all;
+import from L3_Templates all;
+import from GSM_RR_Types all;
+
+import from MSC_ConnectionHandler all;
+import from RAN_Adapter all;
+import from RAN_Emulation all;
+
+const charstring COORD_VGCS_CALL_EST := "VGCS_CALL_EST";
+const charstring COORD_VGCS_CALL_REL := "VGCS_CALL_REL";
+const charstring COORD_VGCS_CHANNEL_REL := "VGCS_CHANNEL_REL";
+const charstring COORD_VGCS_UPLINK_FREE := "VGCS_UPLINK_FREE";
+const charstring COORD_VGCS_UPLINK_BUSY := "VGCS_UPLINK_BUSY";
+const charstring COORD_VGCS_ASSIGN_RES := "VGCS_ASSIGN_RES";
+const charstring COORD_VGCS_ASSIGN_FAIL := "VGCS_ASSIGN_FAIL";
+const charstring COORD_UPLINK_REQUEST_CONFIRM := "UPLINK_REQUEST_CONFIRM";
+
+template (value) DescriptiveGroupOrBroadcastCallReference_V
+ ts_BSSMAP_IE_GroupCallRef(integer cr,
+ BIT1 sf,
+ BIT1 af,
+ BIT3 prio,
+ BIT4 ci) := {
+ binaryCodingOfGroupOrBroadcastCallReference := int2bit(cr, 27),
+ sF := sf,
+ aF := af,
+ callPriority := prio,
+ cipheringInformation := ci,
+ spare := '0000'B
+}
+
+function f_gen_asci_ass_req(integer bssap_idx := 0,
+ template (value) BSSMAP_IE_ChannelType ch_type := ts_BSSMAP_IE_ChannelType,
+ template (value) OCT1 ass_requirement := '00'O,
+ template (value) BSSMAP_IE_CellIdentifier cell_id := ts_CellId_CI(0),
+ template (value) GroupCallRef group_call_ref := '0000001000'O,
+ charstring aoip_tla :="1.2.3.4")
+runs on MSC_ConnHdlr return template (value) PDU_BSSAP {
+ if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
+ var template (value) BSSMAP_IE_AoIP_TransportLayerAddress tla :=
+ f_ts_BSSMAP_IE_AoIP_TLA(aoip_tla, 2342);
+ var template (value) BSSMAP_IE_SpeechCodecList codec_list :=
+ ts_BSSMAP_IE_CodecList({ts_CodecFR});
+ return ts_BSSMAP_VGCS_VBS_AssignmentReq(ch_type, ass_requirement, cell_id,
+ group_call_ref, omit, tla, omit, codec_list);
+ } else {
+ var template (value) BSSMAP_IE_CircuitIdentityCode cic := ts_BSSMAP_IE_CIC(0,1);
+ return ts_BSSMAP_VGCS_VBS_AssignmentReq(ch_type, ass_requirement, cell_id,
+ group_call_ref, cic, omit, omit, omit);
+ }
+}
+
+/*
+ * VGCS/VBS call controling connection
+ */
+
+private function f_delay_msc() runs on MSC_ConnHdlr {
+ var PDU_BSSAP rx_bssap;
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSAP_BSSMAP) -> value rx_bssap {
+ setverdict(fail, "Got BSSAP message from BSC. This is unexpected:", rx_bssap);
+ }
+ [] T.timeout { }
+ }
+}
+
+private function f_tc_vgcs_vbs_setup(charstring id) runs on MSC_ConnHdlr {
+ var PDU_BSSAP rx_bssap;
+ var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
+ ts_BSSMAP_IE_GroupCallRef(11, '1'B, '0'B, '000'B, '0000'B);
+ var template (value) PDU_BSSAP setup_req := ts_BSSMAP_VGCS_VBS_Setup(bit2oct(encvalue(callref)), omit);
+ var boolean uplink_free := false;
+ var boolean uplink_busy := false;
+ var boolean uplink_req := false;
+ var boolean uplink_req_conf := false;
+ var boolean uplink_rel_ind := false;
+ var boolean uplink_rel_ind_failure := false;
+ var boolean assign_res := false;
+ var boolean assign_fail := false;
+ /* Note: This timer is used to receive messages after the expected event.
+ * After timeout, the outcome of the test is checked.
+ * The timeout must be large enough, so all the messages pass before checking the outcome. */
+ timer T := 1.0;
+
+ /* Wait for the COORD ports to be connected. */
+ f_sleep(1.0);
+
+ /* VGCS/VBS SETUP REQ in SCCP CR (must be the first message) */
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, setup_req));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_VGCS_VBS_SetupAck) -> value rx_bssap {
+ log("VGCS: got setup ack");
+ if (not g_pars.asci_test.vgcs_setup_ok) {
+ COORD.send(COORD_VGCS_CALL_EST);
+ repeat;
+ }
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ setverdict(pass);
+ return;
+ }
+ [] BSSAP.receive(tr_BSSMAP_VGCS_VBS_SetupRefuse) -> value rx_bssap {
+ log("VGCS: got setup refuse");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Expected ASCI Setup to succeed, but got fail");
+ return;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkReq) -> value rx_bssap {
+ log("VGCS: received uplink req");
+ uplink_req := true;
+ if (g_pars.asci_test.delay_msc) {
+ log("VGCS: delay uplink req ack");
+ f_delay_msc();
+ }
+ if (g_pars.asci_test.vgcs_uplink_reject) {
+ log("VGCS: sending uplink rej cmd");
+ BSSAP.send(ts_BSSMAP_UplinkRejCmd(9));
+ } else {
+ log("VGCS: sending uplink req ack");
+ BSSAP.send(ts_BSSMAP_UplinkReqAck(omit));
+ }
+ if (g_pars.asci_test.vgcs_talker_req or
+ g_pars.asci_test.vgcs_uplink_reject) {
+ T.start;
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkReqConf(?, omit, '1234'O)) -> value rx_bssap {
+ log("VGCS: received uplink req confirm");
+ uplink_req_conf := true;
+ COORD.send(COORD_UPLINK_REQUEST_CONFIRM);
+ if (g_pars.asci_test.vgcs_talker_est) {
+ T.start;
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkRelInd(GSM0808_CAUSE_CALL_CONTROL, omit)) -> value rx_bssap {
+ log("VGCS: received uplink rel ind");
+ uplink_rel_ind := true;
+ if (g_pars.asci_test.vgcs_talker_rel) {
+ T.start;
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkRelInd(GSM0808_CAUSE_RADIO_INTERFACE_FAILURE, omit)) -> value rx_bssap {
+ log("VGCS: received uplink rel ind, caused by failure");
+ uplink_rel_ind_failure := true;
+ if (g_pars.asci_test.vgcs_talker_fail) {
+ T.start;
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkRelInd(?, omit)) -> value rx_bssap {
+ setverdict(fail, "VGCS: received uplink rel ind, caused by failure with invalid cause: ", rx_bssap);
+ }
+ [] COORD.receive(COORD_VGCS_ASSIGN_RES) {
+ log("VGCS: got assignment result at call control");
+ assign_res := true;
+ if (g_pars.asci_test.vgcs_assign_ok) {
+ T.start;
+ }
+ if (g_pars.asci_test.vgcs_uplink_seized or
+ g_pars.asci_test.vgcs_uplink_release) {
+ log("VGCS: sending Uplink Seized Cmd");
+ BSSAP.send(ts_BSSMAP_UplinkSeizedCmd(9, omit, omit, omit));
+ T.start;
+ }
+ if (g_pars.asci_test.vgcs_uplink_release) {
+ log("VGCS: sending Uplink Release Cmd");
+ BSSAP.send(ts_BSSMAP_UplinkRelCmd(9));
+ T.start;
+ }
+ if (g_pars.asci_test.vgcs_uplink_seized or
+ g_pars.asci_test.vgcs_uplink_release) {
+ T.start;
+ }
+ repeat;
+ }
+ [] COORD.receive(COORD_VGCS_ASSIGN_FAIL) {
+ log("VGCS: got assignment failure at call control");
+ assign_fail := true;
+ if (g_pars.asci_test.vgcs_assign_fail) {
+ T.start;
+ }
+ repeat;
+ }
+ [] COORD.receive(COORD_VGCS_UPLINK_FREE) {
+ log("VGCS: Got UPLINK FREE at call control");
+ uplink_busy := false;
+ uplink_free := true;
+ repeat;
+ }
+ [] COORD.receive(COORD_VGCS_UPLINK_BUSY) {
+ log("VGCS: Got UPLINK BUSY at call control");
+ uplink_busy := true;
+ uplink_free := false;
+ repeat;
+ }
+ [] T.timeout { }
+ }
+
+ /* After timeout: Release Channel and Call and see if the outcome of the test is as expected. */
+ COORD.send(COORD_VGCS_CHANNEL_REL);
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+
+ if (g_pars.asci_test.vgcs_assign_ok) {
+ if (not assign_res) {
+ setverdict(fail, "VGCS: Assignment did not pass as expected!");
+ return;
+ }
+ if (not uplink_free) {
+ setverdict(fail, "VGCS: Uplink not free as expected!");
+ return;
+ }
+ log("VGCS: Channel assigned and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_assign_fail) {
+ if (not assign_fail) {
+ setverdict(fail, "VGCS: Assignment did not fail as expected!");
+ return;
+ }
+ log("VGCS: Channel assignment failed as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_talker_req) {
+ if (not uplink_req) {
+ setverdict(fail, "VGCS: No uplink request as expected!");
+ return;
+ }
+ /* UPLINK BUSY is automatically sent by BTS, but not by BSC. */
+ if (uplink_busy) {
+ setverdict(fail, "VGCS: Uplink set to busy, this is not expected!");
+ return;
+ }
+ log("VGCS: Uplink requested and uplink marked busy as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_talker_fail) {
+ if (not uplink_rel_ind_failure) {
+ setverdict(fail, "VGCS: No uplink release indication as expected!");
+ return;
+ }
+ if (not uplink_free) {
+ setverdict(fail, "VGCS: Uplink not free as expected!");
+ return;
+ }
+ log("VGCS: Uplink release and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_talker_est) {
+ if (not uplink_req_conf) {
+ setverdict(fail, "VGCS: No uplink request confirm as expected!");
+ return;
+ }
+ /* UPLINK BUSY is automatically sent by BTS, but not by BSC. */
+ if (uplink_busy) {
+ setverdict(fail, "VGCS: Uplink set to busy, this is not expected!");
+ return;
+ }
+ log("VGCS: Uplink established and uplink marked busy as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_talker_rel) {
+ if (not uplink_rel_ind) {
+ setverdict(fail, "VGCS: No uplink release indication as expected!");
+ return;
+ }
+ if (not uplink_free) {
+ setverdict(fail, "VGCS: Uplink not free as expected!");
+ return;
+ }
+ log("VGCS: Uplink established+released and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_uplink_seized) {
+ if (not uplink_busy) {
+ setverdict(fail, "VGCS: Uplink not busy as expected!");
+ return;
+ }
+ log("VGCS: Uplink established+released and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_uplink_release) {
+ if (not uplink_free) {
+ setverdict(fail, "VGCS: Uplink not free as expected!");
+ return;
+ }
+ log("VGCS: Uplink established+released and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+ if (g_pars.asci_test.vgcs_uplink_reject) {
+ if (not uplink_free) {
+ setverdict(fail, "VGCS: Uplink not free as expected!");
+ return;
+ }
+ log("VGCS: Uplink rejected and uplink marked free as expected!");
+ setverdict(pass);
+ return;
+ }
+}
+
+/*
+ * VGCS/VBS resource controling connection
+ */
+
+private altstep as_eat_rsl_data() runs on MSC_ConnHdlr {
+ [] RSL.receive(tr_RSL_UNITDATA_REQ(g_chan_nr, ?, ?)) {
+ log("VGCS: Got RSL UNITDATA REQ on channel");
+ repeat;
+ }
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, ?, ?)) {
+ log("VGCS: Got RSL DATA REQ on channel");
+ repeat;
+ }
+}
+
+private function f_delay_bts() runs on MSC_ConnHdlr {
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] COORD.receive(COORD_UPLINK_REQUEST_CONFIRM) {
+ setverdict(fail, "Got UPLINK REQUEST CONFIRM from BSC. This is unexpected.");
+ }
+ [] T.timeout { }
+ }
+}
+
+private function f_tc_asci_assignment(charstring id) runs on MSC_ConnHdlr {
+ var PDU_BSSAP rx_bssap;
+ /* Hack: the proper way would be to wait for the BSSMAP VGCS Assignment Result and extract the
+ * actual assigned chan_nr from it. But osmo-bsc starts acting on the lchan even before we get a
+ * chance to evaluate the BSSMAP Handover Request ACK. So we need to assume that osmo-bsc will
+ * activate TS 1 and already set up this lchan's RSL emulation
+ * before we get started. */
+ var RslChannelNr new_chan_nr := valueof(t_RslChanNr0(1, RSL_CHAN_NR_Bm_ACCH));
+ f_rslem_register(0, new_chan_nr);
+ g_chan_nr := new_chan_nr;
+ var uint3_t expect_target_tsc := c_BtsParams[0].tsc;
+ var default eat_rsl_data;
+
+ /* Wait for the COORD ports to be connected. */
+ f_sleep(1.0);
+
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+ f_MscConnHdlr_init(g_pars.media_nr, "127.0.0.2", "127.0.0.3", FR_AMR);
+ var default as_media := activate(as_Media());
+
+ log("VGCS: wait for establishment of call controling connection");
+ COORD.receive(COORD_VGCS_CALL_EST);
+ log("VGCS: got establishment of call controling connection");
+
+ /* TODO: Encryption */
+ var template (value) BSSMAP_IE_ChannelType req_ch_type := ts_BSSMAP_IE_ChannelType;
+ var template BSSMAP_IE_ChannelType res_ch_type := tr_BSSMAP_IE_ChannelType('0001'B, ChRate_TCHF, Spdi_TCHF_FR);
+ var template (value) BSSMAP_IE_CellIdentifier req_cell_id := ts_CellId_CI(0);
+ var template BSSMAP_IE_CellIdentifier res_cell_id := tr_CellId_CI(0);
+ var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
+ ts_BSSMAP_IE_GroupCallRef(11, '1'B, '0'B, '000'B, '0000'B);
+ if (g_pars.asci_test.vgcs_assign_fail) {
+ callref := ts_BSSMAP_IE_GroupCallRef(10, '1'B, '0'B, '000'B, '0000'B);
+ }
+ var template (value) PDU_BSSAP ass_req := f_gen_asci_ass_req(ch_type := req_ch_type, cell_id := req_cell_id,
+ group_call_ref := bit2oct(encvalue(callref)));
+ /* VGCS/VBS ASS REQ in SCCP CR (must be the first message) */
+ BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_bsc, g_pars.sccp_addr_msc, ass_req));
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND);
+
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_VGCS_VBS_AssignmentRes(res_ch_type, res_cell_id)) -> value rx_bssap {
+ log("VGCS: got assignment result on channel");
+ COORD.send(COORD_VGCS_ASSIGN_RES);
+ if (g_pars.asci_test.vgcs_talker_req or
+ g_pars.asci_test.vgcs_talker_fail or
+ g_pars.asci_test.vgcs_talker_est or
+ g_pars.asci_test.vgcs_talker_rel or
+ g_pars.asci_test.vgcs_uplink_reject) {
+ log("VGCS: sending talker det");
+ RSL.send(ts_RSL_TALKER_DET(g_chan_nr));
+ }
+ if (g_pars.asci_test.vgcs_talker_fail) {
+ if (g_pars.asci_test.delay_bts) {
+ log("VGCS: delay sending RSL failure ind");
+ f_delay_bts();
+ }
+ log("VGCS: sending RSL failure ind");
+ RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_TALKER_ACC_FAIL));
+ }
+ if (g_pars.asci_test.vgcs_talker_est or
+ g_pars.asci_test.vgcs_talker_rel) {
+ if (g_pars.asci_test.delay_bts) {
+ log("VGCS: delay sending RSL estblish ind");
+ f_delay_bts();
+ }
+ log("VGCS: sending RSL etabish ind");
+ RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_DCCH(0), '1234'O));
+ }
+ if (g_pars.asci_test.vgcs_talker_rel) {
+ log("VGCS: sending RSL release ind");
+ RSL.send(ts_RSL_REL_IND(g_chan_nr, ts_RslLinkID_DCCH(0)));
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_VGCS_VBS_AssignmentFail) -> value rx_bssap {
+ log("VGCS: got assignment failure on channel");
+ COORD.send(COORD_VGCS_ASSIGN_FAIL);
+ log("VGCS: got release order after assignment failure");
+ COORD.receive(COORD_VGCS_CHANNEL_REL);
+ BSSAP.send(ts_BSSMAP_ClearCommand(0));
+ BSSAP.receive(tr_BSSMAP_ClearComplete);
+ BSSAP.send(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ);
+ return;
+ }
+ [] COORD.receive(COORD_VGCS_CHANNEL_REL) {
+ log("VGCS: got release order of resource controling connection");
+ eat_rsl_data := activate(as_eat_rsl_data());
+ f_perform_clear_no_rr_rel();
+ deactivate(eat_rsl_data);
+ return;
+ }
+ [] RSL.receive(tr_RSL_UNITDATA_REQ(g_chan_nr, ?, '082B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O)) {
+ log("VGCS: Got UPLINK FREE on channel");
+ COORD.send(COORD_VGCS_UPLINK_FREE);
+ repeat;
+ }
+ [] RSL.receive(tr_RSL_UNITDATA_REQ(g_chan_nr, ?, '062A'O)) {
+ log("VGCS: Got UPLINK BUSY on channel");
+ COORD.send(COORD_VGCS_UPLINK_BUSY);
+ repeat;
+ }
+ [] COORD.receive(COORD_UPLINK_REQUEST_CONFIRM) { repeat; }
+ }
+
+ /* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
+
+ /* we're sure that the channel activation is done now, verify the parameters in it */
+ var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
+ /* TODO: Encryption */
+ f_chan_act_verify_tsc(chan_act, expect_target_tsc);
+
+ if (ispresent(rx_bssap.pdu.bssmap.vGCS_VBSAssignmentResult.speechCodec)) {
+ if (not g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Expected no Speech Codec (Chosen)");
+ }
+ } else {
+ if (g_pars.aoip) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Expected Speech Codec (Chosen)");
+ }
+ }
+
+}
+
+testcase TC_vgcs_vbs_setup_only() runs on test_CT {
+ var MSC_ConnHdlr call_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_setup_ok := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+
+ call_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_assignment() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_assign_ok := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_assignment_fail() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_assign_fail := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_req() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_talker_req := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_fail() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ /* MSC sends acknowledge before link on BTS fail. */
+ pars.asci_test.vgcs_talker_fail := true;
+ pars.asci_test.delay_bts := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_fail_late_msc() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ /* MSC sends acknowledge after link on BTS fail. */
+ pars.asci_test.vgcs_talker_fail := true;
+ pars.asci_test.delay_msc := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_est() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ /* MSC sends acknowledge before BTS establishes the uplink. */
+ pars.asci_test.vgcs_talker_est := true;
+ pars.asci_test.delay_bts := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_est_late_msc() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ /* MSC sends acknowledge after BTS established the uplink. */
+ pars.asci_test.vgcs_talker_est := true;
+ pars.asci_test.delay_msc := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_rel() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_talker_rel := true;
+ pars.asci_test.delay_bts := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_rel_late_msc() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_talker_rel := true;
+ pars.asci_test.delay_msc := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_uplink_reject() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_uplink_reject := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_uplink_seized() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_uplink_seized := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_uplink_release() runs on test_CT {
+ var MSC_ConnHdlr call_conn, chan_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1, true);
+
+ pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+ pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+ pars.asci_test.vgcs_uplink_release := true;
+
+ call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+ chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+ /* Connect COORD ports of both functions. The functions will delay before using them. */
+ connect(call_conn:COORD, chan_conn:COORD);
+
+ call_conn.done;
+ chan_conn.done;
+
+ f_shutdown_helper();
+}
+
+control {
+ execute( TC_vgcs_vbs_setup_only() );
+ execute( TC_vgcs_vbs_assignment() );
+ execute( TC_vgcs_vbs_assignment_fail() );
+ execute( TC_vgcs_vbs_talker_req() );
+ execute( TC_vgcs_vbs_talker_fail() );
+ execute( TC_vgcs_vbs_talker_fail_late_msc() );
+ execute( TC_vgcs_vbs_talker_est() );
+ execute( TC_vgcs_vbs_talker_est_late_msc() );
+ execute( TC_vgcs_vbs_talker_rel() );
+ execute( TC_vgcs_vbs_talker_rel_late_msc() );
+ execute( TC_vgcs_vbs_uplink_reject() );
+ execute( TC_vgcs_vbs_uplink_seized() );
+ execute( TC_vgcs_vbs_uplink_release() );
+}
+
+
+}
diff --git a/bsc/BSC_Tests_CBSP.ttcn b/bsc/BSC_Tests_CBSP.ttcn
index acd0b99c..3f1eff02 100644
--- a/bsc/BSC_Tests_CBSP.ttcn
+++ b/bsc/BSC_Tests_CBSP.ttcn
@@ -12,6 +12,8 @@ module BSC_Tests_CBSP {
* This test suite tests OsmoBSC while emulating the CBC (Cell Broadcast Centre)
*/
+import from BSC_Tests all;
+
import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
@@ -19,8 +21,6 @@ import from IPL4asp_Types all;
import from BSSAP_Types all;
import from BSSMAP_Templates all;
-import from BSC_Tests all;
-
import from IPA_Emulation all;
import from IPA_CodecPort all;
import from IPA_Types all;
@@ -37,10 +37,22 @@ import from CBSP_Templates all;
import from CBSP_Adapter all;
import from CBSP_CodecPort all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
modulepar {
- charstring mp_cbc_ip := "0.0.0.0";
+ charstring mp_cbc_ip := "127.0.0.1";
+ charstring mp_cbc_ip6 := "::1";
integer mp_cbc_port := 48049;
+ charstring mp_bsc_cbsp_ip := "127.0.0.1";
+ charstring mp_bsc_cbsp_ip6 := "::1";
integer mp_bsc_cbsp_port := 48050;
+ /* port number to which to establish the IPA CTRL connection */
+ integer mp_bsc_ctrl_port := 4249;
/* BTS 0: 001-01-1-0 with CBCH
* BTS 1: 001-01-1-1 with CBCH
@@ -52,6 +64,28 @@ modulepar {
GsmCgiAbstract mp_cgi_bts3 := { '001'H, '01'H, 2, 3 };
}
+type record CBSP_Pars {
+ boolean tcp_client,
+ charstring local_ip,
+ integer local_port,
+ charstring remote_ip,
+ integer remote_port,
+ uint16_t cbsp_msg_id optional, /*server mode only */
+ uint16_t cbsp_ser_no optional /*server mode only */
+};
+
+private template (value) CBSP_Pars ts_CBSP_Pars_default(boolean tcp_client := true,
+ template (omit) uint16_t cbsp_msg_id := omit,
+ template (omit) uint16_t cbsp_ser_no := omit) := {
+ tcp_client := tcp_client,
+ local_ip := mp_cbc_ip,
+ local_port := mp_cbc_port,
+ remote_ip := mp_bsc_cbsp_ip,
+ remote_port := mp_bsc_cbsp_port,
+ cbsp_msg_id := cbsp_msg_id,
+ cbsp_ser_no := cbsp_ser_no
+};
+
private type record GsmCgiAbstract {
GsmMcc mcc,
GsmMnc mnc,
@@ -68,50 +102,93 @@ private template (value) OCT2 bssmap_lac(GsmCgiAbstract cgi) := ts_BSSMAP_CI_LAC
private template (value) OCT2 bssmap_ci(GsmCgiAbstract cgi) := ts_BSSMAP_CI_CI(cgi.ci);
type component cbsp_test_CT extends test_CT, CBSP_Adapter_CT {
+ var CBSP_Pars g_pars;
+ var uint16_t g_cbsp_msg_id := 0;
+ var uint16_t g_cbsp_ser_no := 0;
}
-private altstep as_IgnRSL(template RSL_Message tr) runs on cbsp_test_CT {
-[] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr)) { repeat; }
-[] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr)) { repeat; }
-[] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr)) { repeat; }
+private function f_g_cbsp_next_msg_id_ser_no() runs on cbsp_test_CT
+{
+ g_cbsp_msg_id := g_cbsp_msg_id + 1;
+ g_cbsp_ser_no := g_cbsp_ser_no + 1;
+ log("g_cbsp_msg_id=", g_cbsp_msg_id, " g_cbsp_ser_no=", g_cbsp_ser_no);
+}
+
+private altstep as_IgnRSL(template (present) RSL_Message tr) runs on cbsp_test_CT {
+[] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr)) { repeat; }
+[] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr)) { repeat; }
+[] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr)) { repeat; }
}
private altstep as_FailRSL() runs on cbsp_test_CT {
-var template RSL_Message tr := (tr_RSL_SMSCB_CMD);
+var template (present) RSL_Message tr := (tr_RSL_SMSCB_CMD);
var ASP_RSL_Unitdata rx;
-[] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr)) -> value rx {
+[] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr)) -> value rx {
setverdict(fail, "Received unexpected RSL ", rx);
mtc.stop;
}
-[] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr)) -> value rx {
+[] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr)) -> value rx {
setverdict(fail, "Received unexpected RSL ", rx);
mtc.stop;
}
-[] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr)) -> value rx {
+[] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr)) -> value rx {
setverdict(fail, "Received unexpected RSL ", rx);
mtc.stop;
}
}
-private function f_init() runs on cbsp_test_CT {
- BSC_Tests.f_init();
+private function f_vty_configure_cbsp() runs on cbsp_test_CT {
+ f_vty_enter_config(BSCVTY);
+ f_vty_transceive(BSCVTY, "cbc");
+ /* Move to disabled in order to force socker recreating later */
+ f_vty_transceive(BSCVTY, "mode disabled");
+
+ /* Configure IP addresses */
+
+ if (g_pars.tcp_client) {
+ f_vty_transceive(BSCVTY, "server");
+ f_vty_transceive(BSCVTY, "local-ip " & g_pars.remote_ip);
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "mode server");
+ } else {
+ f_vty_transceive(BSCVTY, "client");
+ f_vty_transceive(BSCVTY, "local-ip " & g_pars.remote_ip);
+ f_vty_transceive(BSCVTY, "remote-ip " & g_pars.local_ip);
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "mode client");
+ }
+
+ f_vty_transceive(BSCVTY, "exit");
+ f_vty_transceive(BSCVTY, "exit");
+}
+
+private function f_init(float guard_timeout := 30.0) runs on cbsp_test_CT {
+ BSC_Tests.f_init(guard_timeout := guard_timeout);
activate(as_IgnRSL((tr_RSL_BCCH_INFO, tr_RSL_SACCH_FILL,
tr_RSL_NO_BCCH_INFO, tr_RSL_NO_SACCH_FILL,
tr_RSL_MsgTypeD(?))));
activate(as_FailRSL());
+
+ f_vty_configure_cbsp();
+
+ if (g_pars.tcp_client) {
+ f_cbsp_init_client();
+ } else {
+ f_cbsp_init_server();
+ }
+
}
private function f_cbsp_init_client() runs on cbsp_test_CT {
- f_init();
- CBSP_Adapter.f_connect(mp_bsc_ip, mp_bsc_cbsp_port, "", -1);
- f_cbsp_init_tail();
+ CBSP_Adapter.f_connect(g_pars.remote_ip, g_pars.remote_port, g_pars.local_ip, 0);
+ CBSP[0].receive(tr_CBSP_Recv(?, tr_CBSP_RESTART(?, CBSP_BC_MSGT_CBS, ?)));
+ setverdict(pass);
}
-private function f_cbsp_init_server() runs on cbsp_test_CT {
+private function f_cbsp_init_server(float guard_timeout := 30.0) runs on cbsp_test_CT {
var ASP_Event asp_evt;
timer T := 10.0;
- f_init();
- CBSP_Adapter.f_bind(mp_cbc_ip, mp_cbc_port);
+ CBSP_Adapter.f_bind(g_pars.local_ip, g_pars.local_port);
T.start;
alt {
@@ -123,9 +200,15 @@ private function f_cbsp_init_server() runs on cbsp_test_CT {
mtc.stop;
}
}
- f_cbsp_init_tail();
+ f_expect_cbsp_restart();
+
+ g_cbsp_msg_id := g_pars.cbsp_msg_id;
+ g_cbsp_ser_no := g_pars.cbsp_ser_no;
+ log("g_cbsp_msg_id=", g_cbsp_msg_id, " g_cbsp_ser_no=", g_cbsp_ser_no);
+
+ f_cbsp_reset_bss(0);
}
-private function f_cbsp_init_tail() runs on cbsp_test_CT {
+private function f_expect_cbsp_restart() runs on cbsp_test_CT {
interleave {
[] CBSP[0].receive(tr_CBSP_Recv(?, tr_CBSP_RESTART(?, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST)));
/* should we also expect a restart for emergency related messages? */
@@ -133,13 +216,25 @@ private function f_cbsp_init_tail() runs on cbsp_test_CT {
}
}
-function f_gen_page() return CBSP_IE {
- var integer len := f_rnd_int(82);
- var octetstring payload := f_rnd_octstring(len);
- return valueof(ts_CbspMsgContent(payload, len));
+/* Generate a CBSP payload: random size for payload_len == 0, or specific fixed size for payload_len > 0. */
+function f_gen_page(integer payload_len := 0) return CBSP_IE {
+ if (payload_len < 1) {
+ /* The maximum CBSP page payload space is 88, but 6 bytes of payload header are added in the first page:
+ * the maximum length generated here thus is 82. The minimum generated length is 1 (avoiding zero
+ * length). Note, f_rnd_int(82) returns [0..81], so this results in a len ranging [1..82]: */
+ payload_len := 1 + f_rnd_int(82);
+ }
+ log("Generating CBSP payload: ", payload_len, " octets");
+ var octetstring payload := f_rnd_octstring(payload_len);
+ return valueof(ts_CbspMsgContent(payload, payload_len));
}
-function f_cbsp_reset_bss(integer idx) runs on CBSP_Adapter_CT {
+function f_cbsp_reset_bss(integer idx) runs on cbsp_test_CT {
+ /* Make sure no CBSP ETWS commands from a previous CBSP test remain in the RSL queue */
+ IPA_RSL[0][0].clear;
+ IPA_RSL[1][0].clear;
+ IPA_RSL[2][0].clear;
+
var template (value) CBSP_PDU tx;
timer T := 3.0;
tx := ts_CBSP_RESET(cell_list := ts_BSSMAP_CIL_BSS);
@@ -157,6 +252,18 @@ function f_cbsp_reset_bss(integer idx) runs on CBSP_Adapter_CT {
mtc.stop;
}
}
+
+ f_cbsp_expect_disable_etws_pn_broadcast();
+}
+
+function f_cbsp_expect_disable_etws_pn_broadcast() runs on cbsp_test_CT
+{
+ var template ASP_RSL_Unitdata zero_payload := tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(t_RslChanNr_PCH_AGCH(0), ''O));
+ interleave {
+ [] IPA_RSL[0][0].receive(zero_payload) { log("CBSP: disabled ETWS PN broadcast on bts 0"); }
+ [] IPA_RSL[1][0].receive(zero_payload) { log("CBSP: disabled ETWS PN broadcast on bts 1"); }
+ [] IPA_RSL[2][0].receive(zero_payload) { log("CBSP: disabled ETWS PN broadcast on bts 2"); }
+ }
}
/* send a WRITE CBS to the BSC; expect either COMPLETE or FAILURE in response*/
@@ -174,9 +281,9 @@ function f_cbsp_write_emerg(uint16_t msg_id, uint16_t ser_no,
tx := ts_CBSP_WRITE_EMERG(msg_id, ser_no, cell_list, emerg_ind, warn_type, warn_per);
CBSP[0].send(ts_CBSP_Send(g_cbsp_conn_id[0], tx));
if (istemplatekind(fail_list, "omit")) {
- rx := tr_CBSP_WRITE_CBS_COMPL(msg_id, ser_no, success_list, omit);
+ rx := tr_CBSP_WRITE_EMERG_COMPL(msg_id, ser_no, success_list);
} else {
- rx := tr_CBSP_WRITE_CBS_FAIL(msg_id, ser_no, fail_list, *, success_list, omit);
+ rx := tr_CBSP_WRITE_EMERG_FAIL(msg_id, ser_no, fail_list, *, success_list);
}
alt {
[] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx)) {
@@ -219,6 +326,36 @@ function f_cbsp_write(uint16_t msg_id, uint16_t ser_no,
}
}
+/* send a REPLACE emergency to the BSC; expect either COMPLETE or FAILURE in response*/
+function f_cbsp_replace_emerg(uint16_t msg_id, uint16_t new_ser_no, uint16_t old_ser_no,
+ template (value) BSSMAP_FIELD_CellIdentificationList cell_list := ts_BSSMAP_CIL_BSS,
+ template (value) uint8_t emerg_ind := 1,
+ template (value) uint16_t warn_type := oct2int('0780'O),
+ template (value) uint16_t warn_per := 5,
+ template BSSMAP_FIELD_CellIdentificationList success_list := ?,
+ template CBSP_FailureListItems fail_list := omit) runs on cbsp_test_CT {
+ var template (value) CBSP_PDU tx;
+ var template CBSP_PDU rx;
+ var CBSP_IEs pages := {f_gen_page()};
+
+ tx := ts_CBSP_REPLACE_EMERG(msg_id, new_ser_no, old_ser_no, cell_list, emerg_ind, warn_type, warn_per);
+ CBSP[0].send(ts_CBSP_Send(g_cbsp_conn_id[0], tx));
+ if (istemplatekind(fail_list, "omit")) {
+ rx := tr_CBSP_REPLACE_EMERG_COMPL(msg_id, new_ser_no, old_ser_no, success_list);
+ } else {
+ rx := tr_CBSP_REPLACE_EMERG_FAIL(msg_id, new_ser_no, old_ser_no, fail_list, omit, success_list);
+ }
+ alt {
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx)) {
+ setverdict(pass);
+ }
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], ?)) {
+ setverdict(fail, "Received unexpected CBSP");
+ mtc.stop;
+ }
+ }
+}
+
/* send a REPLACE CBS to the BSC; expect either COMPLETE or FAILURE in response*/
function f_cbsp_replace(uint16_t msg_id, uint16_t new_ser_no, uint16_t old_ser_no,
template (value) BSSMAP_FIELD_CellIdentificationList cell_list := ts_BSSMAP_CIL_BSS,
@@ -254,6 +391,7 @@ function f_cbsp_replace(uint16_t msg_id, uint16_t new_ser_no, uint16_t old_ser_n
function f_cbsp_kill(uint16_t msg_id, uint16_t ser_no, template (omit) uint8_t channel_ind := 0,
template (value) BSSMAP_FIELD_CellIdentificationList cell_list := ts_BSSMAP_CIL_BSS,
template BSSMAP_FIELD_CellIdentificationList success_list := ?,
+ template CBSP_IE_NumBcastComplList compl_list := *,
template CBSP_FailureListItems fail_list := omit) runs on cbsp_test_CT
{
var template (value) CBSP_PDU tx;
@@ -262,10 +400,10 @@ function f_cbsp_kill(uint16_t msg_id, uint16_t ser_no, template (omit) uint8_t c
tx := ts_CBSP_KILL(msg_id, ser_no, cell_list, channel_ind);
CBSP[0].send(ts_CBSP_Send(g_cbsp_conn_id[0], tx));
if (istemplatekind(fail_list, "omit")) {
- rx := tr_CBSP_KILL_COMPL(msg_id, ser_no, compl_list:=*, cell_list:=success_list,
+ rx := tr_CBSP_KILL_COMPL(msg_id, ser_no, compl_list:=compl_list, cell_list:=success_list,
channel_ind:=channel_ind);
} else {
- rx := tr_CBSP_KILL_FAIL(msg_id, ser_no, fail_list, compl_list:=*, cell_list:=success_list,
+ rx := tr_CBSP_KILL_FAIL(msg_id, ser_no, fail_list, compl_list:=compl_list, cell_list:=success_list,
channel_ind:=channel_ind);
}
alt {
@@ -279,6 +417,34 @@ function f_cbsp_kill(uint16_t msg_id, uint16_t ser_no, template (omit) uint8_t c
}
}
+/* send a KILL CBS to the BSC; expect either COMPLETE or FAILURE in response*/
+function f_cbsp_msg_status_query(uint16_t msg_id, uint16_t ser_no, template (value) uint8_t channel_ind := 0,
+ template (value) BSSMAP_FIELD_CellIdentificationList cell_list := ts_BSSMAP_CIL_BSS,
+ template CBSP_IE_NumBcastComplList compl_list := ?,
+ template CBSP_FailureListItems fail_list := omit) runs on cbsp_test_CT
+{
+ var template (value) CBSP_PDU tx;
+ var template CBSP_PDU rx;
+
+ tx := ts_CBSP_MSG_STATUS_QUERY(msg_id, ser_no, cell_list, channel_ind);
+ CBSP[0].send(ts_CBSP_Send(g_cbsp_conn_id[0], tx));
+ if (istemplatekind(fail_list, "omit")) {
+ rx := tr_CBSP_MSG_STATUS_QUERY_COMPL(msg_id, ser_no, compl_list:=compl_list, channel_ind:=channel_ind);
+ } else {
+ rx := tr_CBSP_MSG_STATUS_QUERY_FAIL(msg_id, ser_no, fail_list, channel_ind:=channel_ind,
+ compl_list:=compl_list);
+ }
+ alt {
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx)) {
+ setverdict(pass);
+ }
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], ?)) {
+ setverdict(fail, "Received unexpected CBSP");
+ mtc.stop;
+ }
+ }
+}
+
template (present) RSL_IE_CbCommandType
tr_RslCbCmdType(template (present) uint2_t lblock := ?, template (present) RSL_CbCommand cmd := ?) := {
command := cmd,
@@ -287,17 +453,43 @@ tr_RslCbCmdType(template (present) uint2_t lblock := ?, template (present) RSL_C
last_block := lblock
}
+/* translate blocks count to RSL_CB_CMD_LASTBLOCK_1..4 values */
+private function f_cbsp_block_count_enc(integer num_blocks) return integer
+{
+ if (num_blocks < 1 or num_blocks > 4) {
+ setverdict(fail, "Invalid num_blocks: ", num_blocks);
+ mtc.stop;
+ }
+ if (num_blocks == 4) {
+ return 0;
+ }
+ return num_blocks;
+}
+
/* build a RSL_Message receive template from a CBSP page */
-private function f_page2rsl(CBSP_IE page, uint16_t msg_id, uint16_t ser_no, boolean ext_cbch := false)
+private function f_page2rsl(CBSP_IE page, uint16_t msg_id, uint16_t ser_no, boolean ext_cbch := false,
+ template (present) integer expect_blocks := ?)
return template (present) RSL_Message
{
- var template RSL_Message tr;
- var integer lblock := page.body.msg_content.user_len / 22;
+ var template (present) RSL_Message tr;
+ var integer len;
+ var integer num_blocks;
var octetstring payload;
- if (page.body.msg_content.user_len mod 22 > 0) {
- lblock := lblock + 1;
- }
+
payload := int2oct(ser_no, 2) & int2oct(msg_id, 2) & '0011'O & page.body.msg_content.val;
+ len := lengthof(payload);
+ num_blocks := len / 22;
+ if (len mod 22 > 0) {
+ num_blocks := num_blocks + 1;
+ }
+
+ if (not istemplatekind(expect_blocks, "omit") and not match(num_blocks, expect_blocks)) {
+ setverdict(fail, "mismatch: CBSP page expect_blocks == ", expect_blocks, ", but generated num_blocks == ", num_blocks);
+ mtc.stop;
+ }
+
+ var integer lblock := f_cbsp_block_count_enc(num_blocks);
+
tr := tr_RSL_SMSCB_CMD(tr_RslCbCmdType(lblock), f_pad_oct(payload, 88, '00'O));
if (ext_cbch) {
tr.ies[3] := tr_RSL_IE(RSL_IE_Body:{smscb_chan_ind := 1});
@@ -310,30 +502,170 @@ return template (present) RSL_Message
* Test Cases
***********************************************************************/
-/* Test if BSC (server) accepts connections from CBC (client) */
+/* Test if BSC (server) accepts connections from CBC (client, IPv4) */
testcase TC_cbsp_bsc_server() runs on cbsp_test_CT {
- f_cbsp_init_client();
- setverdict(pass);
+ g_pars := valueof(ts_CBSP_Pars_default(tcp_client := true));
+ f_init();
+ f_shutdown_helper();
+}
+
+/* Test if BSC (server) accepts connections from CBC (client, IPv6) */
+testcase TC_cbsp_bsc_server_ipv6() runs on cbsp_test_CT {
+ g_pars := valueof(ts_CBSP_Pars_default(tcp_client := true));
+ g_pars.local_ip := mp_cbc_ip6;
+ g_pars.remote_ip := mp_bsc_cbsp_ip6;
+ f_init();
+ f_shutdown_helper();
}
-/* Test if BSC (client) is connecting to CBC (server) */
+/* Test if BSC (client) is connecting to CBC (server, IPv4) */
testcase TC_cbsp_bsc_client() runs on cbsp_test_CT {
- f_cbsp_init_server();
- setverdict(pass);
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ f_init();
+ f_shutdown_helper();
+}
+
+/* Test if BSC (client) is connecting to CBC (server, IPv6) */
+testcase TC_cbsp_bsc_client_ipv6() runs on cbsp_test_CT {
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ g_pars.local_ip := mp_cbc_ip6;
+ g_pars.remote_ip := mp_bsc_cbsp_ip6;
+ f_init();
+ f_shutdown_helper();
}
/* Test if a BSS-global RESET is executed successfully */
testcase TC_cbsp_reset_bss() runs on cbsp_test_CT {
- f_cbsp_init_server();
-
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ f_init();
f_cbsp_reset_bss(0);
+ f_shutdown_helper();
+}
+
+/* Test if a LAC_CI FAILURE Ind is sent when TRX holding the CBCH is locked
+ * (becomes unavailable). LAC_CI RESTART Ind should be sent when the TRX becomes
+ * unlocked again. */
+testcase TC_cbsp_cell_rflock_failure_restart() runs on cbsp_test_CT {
+ var template CBSP_PDU rx_cbs;
+ var template CBSP_PDU rx_emerg;
+ var boolean received_cbs := false;
+ var boolean received_emerg := false;
+ var template (present) CBSP_FailureListItem fli_exp;
+ var template (present) BSSMAP_FIELD_CellIdentificationList cil_exp;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ f_init();
+
+ /* Lock the TRX, CBCH should become unavailable and BSC send FAILURE */
+ f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "1");
+
+ /* Expect receiving either CGI or LAC+CI: */
+ fli_exp := (CBSP_FailureListItem_CGI(bssmap_cgi(mp_cgi_bts0),
+ CBSP_CAUSE_CB_NOT_OPERATIONAL),
+ CBSP_FailureListItem_LAC_CI(bssmap_lac_ci(mp_cgi_bts0),
+ CBSP_CAUSE_CB_NOT_OPERATIONAL));
+ rx_cbs := tr_CBSP_FAILURE({fli_exp}, CBSP_BC_MSGT_CBS);
+ rx_emerg := tr_CBSP_FAILURE({fli_exp}, CBSP_BC_MSGT_EMERG);
+ alt {
+ [not received_cbs] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_cbs)) {
+ received_cbs := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [not received_emerg] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_emerg)) {
+ received_emerg := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], ?)) {
+ setverdict(fail, "Received unexpected CBSP");
+ mtc.stop;
+ }
+ }
setverdict(pass);
+
+ /* Unlock the TRX, CBCH should become available and BSC send RESTART */
+ f_ctrl_set(IPA_CTRL, "bts.0.trx.0.rf_locked", "0");
+ /* Expect receiving either CGI or LAC+CI: */
+ cil_exp := (ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)}),
+ ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)}));
+ rx_cbs := tr_CBSP_RESTART(cil_exp, CBSP_BC_MSGT_CBS, ?);
+ rx_emerg := tr_CBSP_RESTART(cil_exp, CBSP_BC_MSGT_EMERG, ?);
+ received_cbs := false;
+ received_emerg := false;
+ alt {
+ [not received_cbs] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_cbs)) {
+ received_cbs := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [not received_emerg] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_emerg)) {
+ received_emerg := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], ?)) {
+ setverdict(fail, "Received unexpected CBSP");
+ mtc.stop;
+ }
+ }
+
+ f_shutdown_helper();
+}
+
+/* Test if a LAC_CI FAILURE Ind is sent when conn of TRX holding the CBCH goes down. */
+testcase TC_cbsp_cell_rsl_down_failure() runs on cbsp_test_CT {
+ var template CBSP_PDU rx_cbs;
+ var template CBSP_PDU rx_emerg;
+ var boolean received_cbs := false;
+ var boolean received_emerg := false;
+ var template (present) CBSP_FailureListItem fli_exp;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ f_init();
+
+ /* Drop RSL link of the TRX holding the CBCH: */
+ f_ipa_rsl_stop(bts[0][0].rsl);
+
+ /* Expect receiving either CGI or LAC+CI: */
+ fli_exp := (CBSP_FailureListItem_CGI(bssmap_cgi(mp_cgi_bts0),
+ CBSP_CAUSE_CB_NOT_OPERATIONAL),
+ CBSP_FailureListItem_LAC_CI(bssmap_lac_ci(mp_cgi_bts0),
+ CBSP_CAUSE_CB_NOT_OPERATIONAL));
+ rx_cbs := tr_CBSP_FAILURE({fli_exp}, CBSP_BC_MSGT_CBS);
+ rx_emerg := tr_CBSP_FAILURE({fli_exp}, CBSP_BC_MSGT_EMERG);
+ alt {
+ [not received_cbs] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_cbs)) {
+ received_cbs := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [not received_emerg] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], rx_emerg)) {
+ received_emerg := true;
+ if (not received_cbs or not received_emerg) {
+ repeat;
+ }
+ }
+ [] CBSP[0].receive(tr_CBSP_Recv(g_cbsp_conn_id[0], ?)) {
+ setverdict(fail, "Received unexpected CBSP");
+ mtc.stop;
+ }
+ }
+
+ /* TODO: call f_init() again to reconnect? */
+ f_shutdown_helper();
}
testcase TC_cbsp_write() runs on cbsp_test_CT {
var template (value) CBSP_PDU tx;
var CBSP_IEs pages := {f_gen_page()};
- f_cbsp_init_server();
+ g_pars := valueof(ts_CBSP_Pars_default(false, 0, 0));
+ f_init();
tx := ts_CBSP_WRITE_CBS(msg_id:=23, new_ser_nr:=42, cell_list:=ts_BSSMAP_CIL_BSS,
channel_ind:=0, category:=CBSP_CATEG_NORMAL,
@@ -342,132 +674,259 @@ testcase TC_cbsp_write() runs on cbsp_test_CT {
CBSP[0].send(ts_CBSP_Send(g_cbsp_conn_id[0], tx));
f_sleep(10.0);
+ f_shutdown_helper();
}
/* Write to entire BSS; three cells succeed; one fails (no CBCH) */
-testcase TC_cbsp_write_bss() runs on cbsp_test_CT {
- var CBSP_IEs pages := {f_gen_page()};
+function f_tc_cbsp_write_bss(integer payload_len := -1, template (present) integer expect_blocks) runs on cbsp_test_CT {
+ var CBSP_IEs pages := {f_gen_page(payload_len := payload_len)};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
cell_list := ts_BSSMAP_CIL_BSS;
- f_cbsp_init_server();
- f_cbsp_write(1, 1001, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=tr_BSSMAP_CIL_CGI({?,?,?}), fail_list:={?});
- var template RSL_Message tr := f_page2rsl(pages[0], 1, 1001);
+ var template (present) RSL_Message tr := f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no, expect_blocks := expect_blocks);
+ log("RSL[0,1,2] EXPECTING ", tr_ASP_RSL_UD(tr));
interleave {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr)) {}
- [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr)) {}
- [] IPA_RSL[2].receive(tr_ASP_RSL_UD(tr)) {}
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr)) { log("Got SMSCB CMD on RSL[0]"); }
+ [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr)) { log("Got SMSCB CMD on RSL[1]"); }
+ [] IPA_RSL[2][0].receive(tr_ASP_RSL_UD(tr)) { log("Got SMSCB CMD on RSL[2]"); }
}
+ setverdict(pass);
+
+ /* Make the next test run (if any) use different msg_id and ser_no */
+ f_g_cbsp_next_msg_id_ser_no();
+}
+testcase TC_cbsp_write_bss() runs on cbsp_test_CT {
+ g_pars := valueof(ts_CBSP_Pars_default(false, 1001, 1501));
+ f_init(guard_timeout := 60.0);
+ /* In the SMSCB message, there is a head followed by payload,
+ * and the resulting data is segmented in blocks of 22 octets (<= 4 blocks).
+ *
+ * [head][...payload....]|[....................]|[....................]|[....................]
+ * 0 |16 |38 |60 |82
+ * 0 5 |22 |44 |66 |88
+ *
+ * blocks count: 1 | 2 | 3 | 4
+ * payload octets count: 1..16 | 17..38 | 39..60 | 61..82
+ */
+ f_tc_cbsp_write_bss(payload_len := 1, expect_blocks := 1);
+ f_tc_cbsp_write_bss(payload_len := 2, expect_blocks := 1);
+ f_tc_cbsp_write_bss(payload_len := 16, expect_blocks := 1);
+ f_tc_cbsp_write_bss(payload_len := 17, expect_blocks := 2);
+ f_tc_cbsp_write_bss(payload_len := 23, expect_blocks := 2);
+ f_tc_cbsp_write_bss(payload_len := 38, expect_blocks := 2);
+ f_tc_cbsp_write_bss(payload_len := 39, expect_blocks := 3);
+ f_tc_cbsp_write_bss(payload_len := 42, expect_blocks := 3);
+ f_tc_cbsp_write_bss(payload_len := 60, expect_blocks := 3);
+ f_tc_cbsp_write_bss(payload_len := 61, expect_blocks := 4);
+ f_tc_cbsp_write_bss(payload_len := 77, expect_blocks := 4);
+ f_tc_cbsp_write_bss(payload_len := 82, expect_blocks := 4);
+ f_shutdown_helper();
}
/* Write to single BTS supporting CBCH: success */
testcase TC_cbsp_write_bts_cgi() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 2001, 2501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(2, 1002, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=cell_list, fail_list:=omit);
- var template RSL_Message tr := f_page2rsl(pages[0], 1, 1001);
- IPA_RSL[0].receive(tr_ASP_RSL_UD(tr));
+ var template (present) RSL_Message tr := f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no);
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr));
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to single BTS not supporting CBCH: failure */
testcase TC_cbsp_write_bts_no_cbch() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 3001, 3501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts3)});
- f_cbsp_init_server();
- f_cbsp_write(3, 1003, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=omit, fail_list:={?});
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to single non-existant BTS */
testcase TC_cbsp_write_unknown_bts() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 4001, 4501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CGI({ts_BSSMAP_CI_CGI(mp_cgi_bts0.mcc, mp_cgi_bts1.mnc, 22222, 33333)});
- f_cbsp_init_server();
- f_cbsp_write(4, 1004, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=omit, fail_list:={?});
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to single BTS using LAC+CI */
testcase TC_cbsp_write_lac_ci() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 5001, 5501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(5, 1005, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=?, fail_list:=omit);
- IPA_RSL[0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], 5, 1005)));
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no)));
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to single BTS using CI */
testcase TC_cbsp_write_ci() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 6001, 6501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CI({bssmap_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(6, 1006, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=?, fail_list:=omit);
- IPA_RSL[0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], 6, 1006)));
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no)));
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to single BTS using LAI */
testcase TC_cbsp_write_lai() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
- cell_list := ts_BSSMAP_CIL_LAI({bssmap_lai(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(7, 1007, cell_list, content:=pages,
+ g_pars := valueof(ts_CBSP_Pars_default(false, 7001, 7501));
+ f_init();
+
+ /* bts0 and bts1 have the same LAI (only differ in cell identity).
+ * bts2 and bts3 also have the same LAI, but only bts2 has a CBCH.
+ * Target only bts2.
+ */
+ cell_list := ts_BSSMAP_CIL_LAI({bssmap_lai(mp_cgi_bts2)});
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=?, fail_list:=omit);
- IPA_RSL[0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], 7, 1007)));
+ IPA_RSL[2][0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no)));
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write to two BTS using LAC */
testcase TC_cbsp_write_lac() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 8001, 8501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC({bssmap_lac(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(8, 1008, cell_list, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages,
success_list:=?, fail_list:=omit);
- var template RSL_Message tr := f_page2rsl(pages[0], 8, 1008);
+ var template (present) RSL_Message tr := f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no);
interleave {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr));
- [] IPA_RSL[1].receive(tr_ASP_RSL_UD(tr));
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr));
+ [] IPA_RSL[1][0].receive(tr_ASP_RSL_UD(tr));
}
f_sleep(5.0);
+ f_shutdown_helper();
}
/* Write a message, then replace it */
testcase TC_cbsp_write_then_replace() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 9001, 9501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(9, 1009, cell_list, num_bcast_req:=10, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, num_bcast_req:=10, content:=pages,
success_list:=?, fail_list:=omit);
- f_cbsp_replace(9, 2009, 1009, cell_list, content:=pages,
+
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no)));
+
+ /* Replace: keep the same msg_id, use a new ser_no */
+ var uint16_t old_ser_no := g_cbsp_ser_no;
+ g_cbsp_ser_no := g_cbsp_ser_no + 1;
+ f_cbsp_replace(g_cbsp_msg_id, g_cbsp_ser_no, old_ser_no, cell_list, content:=pages,
success_list:=?, fail_list:=omit);
+
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no)));
+ f_sleep(1.0);
+ f_shutdown_helper();
+}
+
+/* Verify handling of the Repetition Period and the Number of Broadcasts */
+testcase TC_cbsp_write_rep_period_num() runs on cbsp_test_CT {
+ var CBSP_IE page := f_gen_page();
+ const integer rep_period := 2; /* units of 1.883s */
+ const integer rep_number := 5;
+ var integer msg_count := 0;
+ var float last_time := 0.0;
+ timer T;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 9001, 9501));
+ f_init(guard_timeout := 60.0);
+
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no,
+ cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)}),
+ rep_period := rep_period, num_bcast_req := rep_number,
+ content := { page }, success_list := ?, fail_list := omit);
+
+ /* Count SMSCB messages during N=rep_number+2 repetition periods */
+ T.start(int2float(rep_period * (rep_number + 2)) * 1.883);
+ alt {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(f_page2rsl(page, g_cbsp_msg_id, g_cbsp_ser_no))) {
+ var float exp_period := int2float(rep_period) * 1.883;
+ var float calc_period := T.read - last_time;
+
+ log("Rx SMSCB message: count := ", msg_count + 1, ", ",
+ "elapsed := ", T.read, "s, diff := ", calc_period, "s");
+
+ if (msg_count > 0) {
+ /* Check the actual repetition period (+/- 0.5s) */
+ var template float tr_exp_period := (exp_period - 0.5 .. exp_period + 0.5);
+ if (not match(calc_period, tr_exp_period)) {
+ setverdict(fail, "Repetition period mismatch: ",
+ "calculated := ", calc_period, "s vs ",
+ "expected := ", tr_exp_period, "s");
+ }
+ }
+
+ msg_count := msg_count + 1;
+ last_time := T.read;
+ repeat;
+ }
+ [] T.timeout {
+ log("Received ", msg_count, " messages during ", last_time, "s");
+ }
+ }
+
+ if (msg_count != rep_number) {
+ setverdict(fail, "Received ", msg_count, " messages, ",
+ "while we expected ", rep_number);
+ }
+
+ f_sleep(1.0);
+ f_shutdown_helper();
}
/* Replace a message that doesn't exist: failure */
testcase TC_cbsp_replace_nonexist() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 10001, 10501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_replace(10, 2010, 1010, cell_list, content:=pages,
+ f_cbsp_replace(10, 10023, 10042, cell_list, content:=pages,
success_list:=omit, fail_list:=?);
+ f_shutdown_helper();
}
/* Write more messages than can be scheduled */
@@ -475,38 +934,55 @@ testcase TC_cbsp_write_too_many() runs on cbsp_test_CT {
/* repeating three pages at an interval of 1 is impossible */
var CBSP_IEs pages := {f_gen_page(), f_gen_page(), f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 11001, 11501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(11, 1011, cell_list, rep_period:=1, content:=pages,
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, rep_period:=1, content:=pages,
success_list:=omit, fail_list:=?);
+ f_shutdown_helper();
}
/* Kill message that doesn't exist: failure */
testcase TC_cbsp_kill_nonexist() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 12001, 12501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_kill(12, 1012, 0, cell_list, success_list:=omit, fail_list:=?);
+ f_cbsp_kill(g_cbsp_msg_id, g_cbsp_ser_no, 0, cell_list, success_list:=omit, compl_list:=omit, fail_list:=?);
+ f_shutdown_helper();
}
/* Write a message, then kill it */
testcase TC_cbsp_write_then_kill() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 13001, 13501));
+ f_init();
+
+ /* write message, request more than one transmission on BTS0 */
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(13, 1013, cell_list, content:=pages, success_list:=?, fail_list:=omit);
- f_cbsp_kill(13, 1013, 0, cell_list, success_list:=?, fail_list:=omit);
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, num_bcast_req := 5, content:=pages, success_list:=?, fail_list:=omit);
+ /* expect to receive it once on the BTS */
+ var template (present) RSL_Message tr := f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no);
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr));
+ /* kill it, expecting non-empty completion list; success must be empty in case of CBS! */
+ f_cbsp_kill(g_cbsp_msg_id, g_cbsp_ser_no, 0, cell_list, success_list:=omit, compl_list:=?, fail_list:=omit);
+ f_shutdown_helper();
}
/* Write a message, then reset all messages */
testcase TC_cbsp_write_then_reset() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 14001, 14501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_LAC_CI({bssmap_lac_ci(mp_cgi_bts0)});
- f_cbsp_init_server();
- f_cbsp_write(14, 1014, cell_list, content:=pages, success_list:=?, fail_list:=omit);
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, content:=pages, success_list:=?, fail_list:=omit);
f_cbsp_reset_bss(0);
+ f_shutdown_helper();
}
private const octetstring c_ETWS_sec_default :=
@@ -523,19 +999,21 @@ testcase TC_cbsp_emerg_write_bts_cgi_dchan() runs on cbsp_test_CT {
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
var ASP_RSL_Unitdata rx_rsl_ud;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 15001, 15501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
- f_cbsp_init_server();
/* first establish a dedicated channel */
- var DchanTuple dt := f_est_dchan('23'O, 23, '00010203040506'O);
+ var DchanTuple dt := f_est_dchan('23'O, 23, gen_l3_valid_payload());
/* then send ETWS PN */
- f_cbsp_write_emerg(15, 1015, cell_list);
- var template (present) octetstring tr_apdu := f_gen_etws_pn(1015, 15);
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list);
+ var template (present) octetstring tr_apdu := f_gen_etws_pn(g_cbsp_msg_id, g_cbsp_ser_no);
timer T := 5.0;
T.start;
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(dt.rsl_chan_nr, ?, ?))) -> value rx_rsl_ud {
+ [] IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr_RSL_DATA_REQ(dt.rsl_chan_nr, ?, ?))) -> value rx_rsl_ud {
var RSL_IE_Body l3_ie;
if (f_rsl_find_ie(rx_rsl_ud.rsl, RSL_IE_L3_INFO, l3_ie) == false) {
setverdict(fail, "RSL DATA REQ without L3?");
@@ -552,96 +1030,208 @@ testcase TC_cbsp_emerg_write_bts_cgi_dchan() runs on cbsp_test_CT {
setverdict(pass);
}
}
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[0][0].receive { repeat; }
[] T.timeout {
setverdict(fail, "Waiting for APP INFO");
}
}
+
+ f_perform_clear_test_ct(dt);
+ f_shutdown_helper();
}
-/* Write ETWS PN to single BTS; verify it arrives on CCHAN */
-testcase TC_cbsp_emerg_write_bts_cgi_cchan() runs on cbsp_test_CT {
- var CBSP_IEs pages := {f_gen_page()};
- var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
- var ASP_RSL_Unitdata rx_rsl_ud;
+private function f_exp_rsl_etws(integer rsl_idx := 0, boolean enabled) runs on cbsp_test_CT {
+ var template (present) octetstring tr_apdu;
+ timer T := 5.0 + 0.5; /* +0.5s guard */
- cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
- f_cbsp_init_server();
+ if (enabled) {
+ tr_apdu := f_gen_etws_pn(g_cbsp_ser_no, g_cbsp_msg_id);
+ } else {
+ tr_apdu := ''O;
+ }
- f_cbsp_write_emerg(16, 1016, cell_list);
- var template (present) octetstring tr_apdu := f_gen_etws_pn(1016, 16);
- timer T := 5.0;
T.start;
alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(t_RslChanNr_PCH_AGCH(0), tr_apdu))) {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(t_RslChanNr_PCH_AGCH(0), tr_apdu))) {
setverdict(pass);
}
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(?,?))) {
+ [] IPA_RSL[rsl_idx][0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(?,?))) {
setverdict(fail, "Received unexpected OSMO_ETWS_CMD");
mtc.stop;
}
- [] IPA_RSL[0].receive { repeat; }
+ [] IPA_RSL[rsl_idx][0].receive { repeat; }
[] T.timeout {
- setverdict(fail, "Timeout waiting for RSL_OSMO_ETWS_CMD");
+ if (enabled) {
+ setverdict(fail, "Timeout waiting for RSL_OSMO_ETWS_CMD (enable)");
+ } else {
+ setverdict(fail, "Timeout waiting for RSL_OSMO_ETWS_CMD (disable)");
+ }
mtc.stop;
}
}
}
/* Write ETWS PN to single BTS; verify it arrives on CCHAN */
-testcase TC_cbsp_emerg_write_bts_cgi_cchan_disable() runs on cbsp_test_CT {
+testcase TC_cbsp_emerg_write_bts_cgi_cchan() runs on cbsp_test_CT {
var CBSP_IEs pages := {f_gen_page()};
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
var ASP_RSL_Unitdata rx_rsl_ud;
+ g_pars := valueof(ts_CBSP_Pars_default(false, 16001, 16501));
+ f_init();
+
cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
- f_cbsp_init_server();
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list);
- f_cbsp_write_emerg(16, 1016, cell_list);
+ f_exp_rsl_etws(0, true);
+ f_shutdown_helper();
+}
+
+/* Write ETWS PN to single BTS; verify it arrives on CCHAN */
+testcase TC_cbsp_emerg_write_bts_cgi_cchan_disable() runs on cbsp_test_CT {
+ var CBSP_IEs pages := {f_gen_page()};
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ var ASP_RSL_Unitdata rx_rsl_ud;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 17001, 17501));
+ f_init();
+
+ cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list);
/* first expect the PN to be enabled */
- var template (present) octetstring tr_apdu := f_gen_etws_pn(1016, 16);
- timer T := 5.0;
- T.start;
- alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(t_RslChanNr_PCH_AGCH(0), tr_apdu))) {
- setverdict(pass);
- }
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(?,?))) {
- setverdict(fail, "Received unexpected OSMO_ETWS_CMD");
- mtc.stop;
- }
- [] IPA_RSL[0].receive { repeat; }
- [] T.timeout {
- setverdict(fail, "Timeout waiting for RSL_OSMO_ETWS_CMD (enable)");
- mtc.stop;
- }
- }
+ f_exp_rsl_etws(0, true);
/* then expect it to be disabled after the warning period (5s) */
- T.start;
- alt {
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(t_RslChanNr_PCH_AGCH(0), ''O))) {
- setverdict(pass);
- }
- [] IPA_RSL[0].receive(tr_ASP_RSL_UD(tr_RSL_OSMO_ETWS_CMD(?,?))) {
- setverdict(fail, "Received unexpected OSMO_ETWS_CMD");
- mtc.stop;
- }
- [] IPA_RSL[0].receive { repeat; }
- [] T.timeout {
- setverdict(fail, "Timeout waiting for RSL_OSMO_ETWS_CMD (disable)");
- mtc.stop;
+ f_exp_rsl_etws(0, false);
+ f_shutdown_helper();
+}
+
+/* Write (!replace) ETWS PN to a single BTS which already has an ongoing PN; expect failure (OS#5539) */
+testcase TC_cbsp_emerg_write_bts_cgi_noreplace() runs on cbsp_test_CT {
+ var CBSP_IEs pages := {f_gen_page()};
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ var ASP_RSL_Unitdata rx_rsl_ud;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 18001, 18501));
+ f_init();
+
+ cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list);
+
+ /* first expect the PN to be enabled */
+ f_exp_rsl_etws(0, true);
+
+ /* write another emergency while first one is still ongoing; expect it to fail */
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no+1, cell_list, success_list:=omit, fail_list:=?);
+
+ /* then expect first one to be disabled after the warning period (5s) */
+ f_exp_rsl_etws(0, false);
+
+ /* write another emergency after the first one has expired; expect it to succeed */
+ g_cbsp_ser_no := g_cbsp_ser_no + 2;
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, success_list:=?, fail_list:=omit);
+ f_exp_rsl_etws(0, true);
+ f_shutdown_helper();
+}
+
+/* Replace ETWS PN to a single BTS which already has an ongoing PN; expect success */
+testcase TC_cbsp_emerg_write_bts_cgi_replace() runs on cbsp_test_CT {
+ var CBSP_IEs pages := {f_gen_page()};
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ var ASP_RSL_Unitdata rx_rsl_ud;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 19001, 19501));
+ f_init();
+
+ cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list);
+
+ /* first expect the PN to be enabled */
+ f_exp_rsl_etws(0, true);
+
+ /* write another emergency while first one is still ongoing; expect it to fail */
+ f_cbsp_replace_emerg(g_cbsp_msg_id, g_cbsp_ser_no+1, g_cbsp_ser_no, cell_list);
+ f_shutdown_helper();
+}
+
+/* Write ETWS PN to a single BTS, then kill it during its lifetime (OS#5540) */
+testcase TC_cbsp_emerg_write_bts_cgi_kill() runs on cbsp_test_CT {
+ var CBSP_IEs pages := {f_gen_page()};
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ var ASP_RSL_Unitdata rx_rsl_ud;
+
+ g_pars := valueof(ts_CBSP_Pars_default(false, 20001, 20501));
+ f_init();
+
+ cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
+ f_cbsp_write_emerg(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, warn_per := 10);
+
+ /* first expect the PN to be enabled */
+ f_exp_rsl_etws(0, true);
+
+ /* kill it; expect non-zero success list, and no completion or failure lists */
+ f_cbsp_kill(g_cbsp_msg_id, g_cbsp_ser_no, omit, cell_list, success_list:=cell_list,
+ compl_list:=omit, fail_list:=omit);
+
+ /* then expect it to be disabled */
+ f_exp_rsl_etws(0, false);
+ f_shutdown_helper();
+}
+
+
+
+/* Send a MSG STATUS QUERY for an unknown message; expect no completion list and present failure list */
+testcase TC_cbsp_status_q_empty() runs on cbsp_test_CT {
+ g_pars := valueof(ts_CBSP_Pars_default(false, 21001, 21501));
+ f_init();
+
+ f_cbsp_msg_status_query(g_cbsp_msg_id, g_cbsp_ser_no, compl_list := omit, fail_list := ?);
+ f_shutdown_helper();
+}
+
+/* Send a SMSCB to entire BSS followed by MSG_STATUS_QUERY; expect completion list and no failure list */
+testcase TC_cbsp_status_q_bts_cgi() runs on cbsp_test_CT {
+ g_pars := valueof(ts_CBSP_Pars_default(false, 22001, 22501));
+ f_init();
+
+ var CBSP_IEs pages := {f_gen_page()};
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ cell_list := ts_BSSMAP_CIL_CGI({bssmap_cgi(mp_cgi_bts0)});
+ /* request 5 transmissions */
+ f_cbsp_write(g_cbsp_msg_id, g_cbsp_ser_no, cell_list, num_bcast_req := 5, content:=pages,
+ success_list:=cell_list, fail_list:=omit);
+ var template (present) RSL_Message tr := f_page2rsl(pages[0], g_cbsp_msg_id, g_cbsp_ser_no);
+ /* wait for first transmission */
+ IPA_RSL[0][0].receive(tr_ASP_RSL_UD(tr));
+ var template (present) CBSP_IE_NumBcastComplList compl_list := {
+ len := ?,
+ spare1_4 := ?,
+ cell_id_discr := ?,
+ list := {
+ cI_CGI := {
+ ci := bssmap_cgi(mp_cgi_bts0),
+ num_bcast_compl := (1 .. 5),
+ num_bcast_info := CBSP_NUM_BCAST_INFO_VALID,
+ spare1_4 := '0000'B
+ }
}
- }
+ };
+ f_cbsp_msg_status_query(g_cbsp_msg_id, g_cbsp_ser_no, cell_list:=cell_list, compl_list := compl_list, fail_list := omit);
+ f_shutdown_helper();
}
+
control {
execute( TC_cbsp_bsc_server() );
+ execute( TC_cbsp_bsc_server_ipv6() );
execute( TC_cbsp_bsc_client() );
+ execute( TC_cbsp_bsc_client_ipv6() );
execute( TC_cbsp_reset_bss() );
+ execute( TC_cbsp_cell_rflock_failure_restart() );
+ execute( TC_cbsp_cell_rsl_down_failure() );
/* test various different types of Cell Identities */
execute( TC_cbsp_write_bss() );
@@ -654,15 +1244,22 @@ control {
execute( TC_cbsp_write_lac() );
execute( TC_cbsp_write_then_replace() );
+ execute( TC_cbsp_write_rep_period_num() );
execute( TC_cbsp_replace_nonexist() );
execute( TC_cbsp_write_too_many() );
execute( TC_cbsp_kill_nonexist() );
execute( TC_cbsp_write_then_kill() );
execute( TC_cbsp_write_then_reset() );
+ execute( TC_cbsp_status_q_empty() );
+ execute( TC_cbsp_status_q_bts_cgi() );
+
execute( TC_cbsp_emerg_write_bts_cgi_dchan() );
execute( TC_cbsp_emerg_write_bts_cgi_cchan() );
execute( TC_cbsp_emerg_write_bts_cgi_cchan_disable() );
+ execute( TC_cbsp_emerg_write_bts_cgi_noreplace() );
+ execute( TC_cbsp_emerg_write_bts_cgi_replace() );
+ execute( TC_cbsp_emerg_write_bts_cgi_kill() );
}
diff --git a/bsc/BSC_Tests_LCLS.ttcn b/bsc/BSC_Tests_LCLS.ttcn
index 72fb525b..2b9886b8 100644
--- a/bsc/BSC_Tests_LCLS.ttcn
+++ b/bsc/BSC_Tests_LCLS.ttcn
@@ -38,6 +38,7 @@ import from MGCP_Types all;
import from MGCP_Emulation all;
import from MGCP_Templates all;
import from SDP_Types all;
+import from SDP_Templates all;
import from Native_Functions all;
import from Osmocom_CTRL_Functions all;
@@ -160,18 +161,19 @@ runs on LCLS_MSC_ConnHdlr {
}
/* helper function to create and connect a MSC_ConnHdlr component */
-/* FIXME: Why can't we use BSC_Tests.f_connect_andler() ?!? */
-private function f_connect_handler(inout LCLS_MSC_ConnHdlr vc_conn, integer bssap_idx := 0) runs on lcls_test_CT {
+/* FIXME: Why can't we use BSC_Tests.f_connect_andler() ?!?
+ * TODO: allow connecting to TRX1..N, not only TRX0 */
+private function f_connect_handler(inout LCLS_MSC_ConnHdlr vc_conn, integer bssap_idx := 0, integer mgwpool_idx := 0) runs on lcls_test_CT {
connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC);
- connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
- connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
- connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
- if (isvalue(bts[1])) {
- connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
- connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
+ connect(vc_conn:RSL, bts[0][0].rsl.vc_RSL:CLIENT_PT);
+ connect(vc_conn:RSL_PROC, bts[0][0].rsl.vc_RSL:RSL_PROC);
+ if (isvalue(bts[1][0])) {
+ connect(vc_conn:RSL1, bts[1][0].rsl.vc_RSL:CLIENT_PT);
+ connect(vc_conn:RSL1_PROC, bts[1][0].rsl.vc_RSL:RSL_PROC);
}
connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
- connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
+ connect(vc_conn:MGCP_PROC, vc_MGCP[mgwpool_idx]:MGCP_PROC);
+ connect(vc_conn:MGCP, vc_MGCP[mgwpool_idx]:MGCP_CLIENT);
}
/* function creating the two ConnHdlrs, connecting them + starting them */
@@ -248,7 +250,7 @@ private function f_lcls_init(boolean bts_mode := false, integer nr_bts := 1) run
/* Send an ASSIGNMENT REQ with LCLS GCR only, without LCLS CFG or CSC */
testcase TC_lcls_gcr_only() runs on lcls_test_CT {
- var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
var MSC_ConnHdlr vc_conn;
f_lcls_init();
@@ -303,7 +305,7 @@ private function f_tc_lcls_ack_rsl_mdcx(RSL_Message rsl_msg, boolean send_on_a)
/* mandatory fields */
fixme_unused := f_rsl_find_ie(rsl_msg, RSL_IE_IPAC_REMOTE_IP, ie);
- host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+ host := f_inet_ntoa(ie.ipa_remote_ip);
fixme_unused := f_rsl_find_ie(rsl_msg, RSL_IE_IPAC_REMOTE_PORT, ie);
port_num := ie.ipa_remote_port;
@@ -315,9 +317,9 @@ private function f_tc_lcls_ack_rsl_mdcx(RSL_Message rsl_msg, boolean send_on_a)
}
if (send_on_a == true) {
- CONN_A.send(ts_RSL_IPA_MDCX_ACK(chan_nr, conn_id, oct2int(f_inet_addr(host)), port_num, rtp_pt));
+ CONN_A.send(ts_RSL_IPA_MDCX_ACK(chan_nr, conn_id, f_inet_addr(host), port_num, rtp_pt));
} else {
- CONN_B.send(ts_RSL_IPA_MDCX_ACK(chan_nr, conn_id, oct2int(f_inet_addr(host)), port_num, rtp_pt));
+ CONN_B.send(ts_RSL_IPA_MDCX_ACK(chan_nr, conn_id, f_inet_addr(host), port_num, rtp_pt));
}
}
@@ -334,7 +336,7 @@ private function f_tc_lcls_recv_ls_exp_rsl() runs on lcls_test_CT {
}
private function f_tc_lcls_gcr_bway_connect(boolean hr, boolean bts_mode := false) runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
@@ -392,7 +394,7 @@ testcase TC_lcls_bts_gcr_bway_connect_hr() runs on lcls_test_CT {
/* Unless explicitly enabled, osmo-bsc will avoid LCLSs when the codecs or rates
* of both legs are different */
testcase TC_lcls_gcr_bway_codec_mismatch() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
var MgcpCommand mgcp_cmd;
@@ -427,7 +429,7 @@ testcase TC_lcls_gcr_bway_codec_mismatch() runs on lcls_test_CT {
/* Send an ASSIGNMENT REQ with LCLS CFG+CSC enabling LCLS but GCR doesn't match! */
testcase TC_lcls_gcr_nomatch_bway_connect() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
var MgcpCommand mgcp_cmd;
@@ -461,7 +463,7 @@ private function f_lcls_not_yet_ls() runs on lcls_test_CT {
/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
testcase TC_lcls_gcr_bway_dont_connect() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
@@ -486,7 +488,7 @@ testcase TC_lcls_gcr_bway_dont_connect() runs on lcls_test_CT {
/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
testcase TC_lcls_gcr_unsuppported_cfg() runs on lcls_test_CT {
- var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
var MSC_ConnHdlr vc_conn;
f_lcls_init();
@@ -507,7 +509,7 @@ testcase TC_lcls_gcr_unsuppported_cfg() runs on lcls_test_CT {
/* Send an ASSIGNMENT REQ with LCLS GCR+CFG+CSC; expect no connect */
testcase TC_lcls_gcr_unsuppported_csc() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
@@ -567,7 +569,7 @@ private function f_lcls_sts_rsl(BIT4 expected_status) runs on lcls_test_CT {
/* Send an ASSIGNMENT REQ with "do not connect" and enable later using LCLS CTRL */
testcase TC_lcls_gcr_bway_dont_connect_csc() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
var MgcpCommand mgcp_cmd;
@@ -619,7 +621,7 @@ private function f_build_mdcx_rsp(MgcpCommand mdcx) return MgcpResponse
}
private function f_lcls_connect_break(boolean bts_mode := false) runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
@@ -675,7 +677,7 @@ testcase TC_lcls_bts_connect_break() runs on lcls_test_CT {
/* Establish LCLS "connect" followed by a SCCP-level release of one leg */
testcase TC_lcls_connect_clear() runs on lcls_test_CT {
- var TestHdlrParams pars_a := valueof(t_def_TestHdlrPars);
+ var TestHdlrParams pars_a := f_gen_test_hdlr_pars();
var TestHdlrParams pars_b;
var MSC_ConnHdlr vc_conn;
var MgcpCommand mgcp_cmd;
diff --git a/bsc/BSC_Tests_OML.ttcn b/bsc/BSC_Tests_OML.ttcn
new file mode 100644
index 00000000..feacd1e4
--- /dev/null
+++ b/bsc/BSC_Tests_OML.ttcn
@@ -0,0 +1,374 @@
+module BSC_Tests_OML {
+
+/* Integration Tests for OsmoBSC A-bis OML (Organization & Maintenance Link)
+ *
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Alexander Couzens <acouzens@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
+ */
+
+/* The tests only require a BSC with VTY and OML to be present. */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from AbisOML_Types all;
+import from IPA_Emulation all;
+import from IPA_Types all;
+import from Misc_Helpers all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from BSC_Tests all;
+
+const integer NUM_TRX := 8;
+
+type record of uint16_t ArfcnList;
+type record length(3) of IPA_CCM_Parameters IPA_CCM_Parameters_multiple;
+
+modulepar {
+ charstring mp_oml_ip := "127.0.0.1";
+ integer mp_oml_port := 3002;
+ ArfcnList mp_arfcn := { 100, 101, 102, 103, 104, 105, 106, 107 };
+ OML_FOM_T200 mp_t200 := {
+ sdcch_5ms := 30,
+ facch_f_5ms := 36,
+ facch_h_5ms := 36,
+ sacch_tch_sapi0_10ms := 168,
+ sacch_sdcch_10ms := 52,
+ sdcch_sapi3_5ms := 33,
+ sacch_rch_sapi3_10ms := 168
+ };
+ uint8_t mp_max_ta := 63;
+ uint8_t mp_load_threshold := 10;
+ uint8_t mp_load_ind_period := 1;
+ uint8_t mp_rach_b_thresh := 90;
+ uint16_t mp_loadavg_slots := 1000;
+ uint8_t mp_air_timer := 100;
+ uint8_t mp_ny1 := 10;
+ uint8_t mp_bsic := 63;
+
+ IPA_CCM_Parameters_multiple mp_ccm_pars := {
+ {
+ ser_nr := "",
+ name := "",
+ location1 := "",
+ location2 := "",
+ equip_version := "",
+ sw_version := "",
+ ip_addr := "",
+ mac_addr := "",
+ unit_id := "1234/0/0",
+ osmo_rand := ""
+ },
+ {
+ ser_nr := "",
+ name := "",
+ location1 := "",
+ location2 := "",
+ equip_version := "",
+ sw_version := "",
+ ip_addr := "",
+ mac_addr := "",
+ unit_id := "1235/0/0",
+ osmo_rand := ""
+ },
+ {
+ ser_nr := "",
+ name := "",
+ location1 := "",
+ location2 := "",
+ equip_version := "",
+ sw_version := "",
+ ip_addr := "",
+ mac_addr := "",
+ unit_id := "1236/0/0",
+ osmo_rand := ""
+ }
+ };
+};
+
+/* BSC side OML component */
+type component BTS_OML_CT {
+ /* IPA client */
+ var IPA_Client client[3];
+
+ /* Port for OML */
+ port IPA_OML_PT OML[3];
+
+ /* VTY */
+ port TELNETasp_PT BSCVTY;
+
+ /* As rxed by Get Attributes Response NM_ATT_MANUF_ID IE, see f_oml_getattr() */
+ var bitstring g_bts_features[3];
+
+ /* global test case guard timer */
+ timer T_oml_guard := 60.0;
+};
+
+private altstep as_Tguard() runs on BTS_OML_CT {
+ [] T_oml_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+private altstep as_IPA_evt(integer idx := 0) runs on BTS_OML_CT {
+ var ASP_IPA_Event evt;
+ [] OML[idx].receive(ASP_IPA_Event:?) -> value evt {
+ log("Ignoring ", evt);
+ repeat;
+ }
+}
+
+function f_init_vty() runs on BTS_OML_CT {
+ if (BSCVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:BSCVTY, system:BSCVTY);
+ f_vty_set_prompts(BSCVTY);
+ f_vty_transceive(BSCVTY, "enable");
+
+ f_vty_enter_config(BSCVTY);
+ f_vty_transceive(BSCVTY, "bsc");
+ f_vty_transceive(BSCVTY, "no bts-setup-ramping");
+ f_vty_transceive(BSCVTY, "end");
+}
+
+function f_init_oml(charstring id, integer num_instance := 1) runs on BTS_OML_CT {
+ activate(as_Tguard());
+ for (var uint8_t idx := 0; idx < num_instance; idx := idx + 1) {
+ client[idx].id := id & "-" & int2str(idx);
+ client[idx].vc_IPA := IPA_Emulation_CT.create(id & "-IPA-" & int2str(idx)) alive;
+ client[idx].ccm_pars := mp_ccm_pars[idx];
+
+ map(client[idx].vc_IPA:IPA_PORT, system:IPA);
+ connect(client[idx].vc_IPA:IPA_OML_PORT, self:OML[idx]);
+ client[idx].vc_IPA.start(IPA_Emulation.main_client(mp_oml_ip, mp_oml_port, "", 10000 + idx, client[idx].ccm_pars));
+
+ T_oml_guard.start;
+
+ OML[idx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP));
+ OML[idx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK));
+
+ activate(as_IPA_evt(idx));
+ }
+}
+
+function f_oml_send_swact(integer idx := 0) runs on BTS_OML_CT
+{
+ OML[idx].send(ts_OML_SwActivatedRep(NM_OC_SITE_MANAGER, {255, 255, 255}));
+ OML[idx].send(ts_OML_SwActivatedRep(NM_OC_BTS, {0, 255, 255}));
+ OML[idx].send(ts_OML_SwActivatedRep(NM_OC_BASEB_TRANSC, {0, 0, 255}));
+ OML[idx].send(ts_OML_SwActivatedRep(NM_OC_RADIO_CARRIER, {0, 0, 255}));
+ for (var uint8_t i := 0; i < 8; i := i + 1) {
+ OML[idx].send(ts_OML_SwActivatedRep(NM_OC_CHANNEL, {0, 0, i}));
+ }
+}
+
+function f_oml_send_state_chg_evt_rep(
+ integer idx,
+ template (value) OML_FOM_OperationalState opstate,
+ template (value) OML_FOM_AvailabilityStatus avstate) runs on BTS_OML_CT
+{
+ OML[idx].send(ts_OML_StateChgEvtRep(NM_OC_SITE_MANAGER, {255, 255, 255}, opstate, avstate));
+ OML[idx].send(ts_OML_StateChgEvtRep(NM_OC_BTS, {0, 255, 255}, opstate, avstate));
+ OML[idx].send(ts_OML_StateChgEvtRep(NM_OC_BASEB_TRANSC, {0, 0, 255}, opstate, avstate));
+ OML[idx].send(ts_OML_StateChgEvtRep(NM_OC_RADIO_CARRIER, {0, 0, 255}, opstate, avstate));
+ for (var uint8_t i := 0; i < 8; i := i + 1) {
+ OML[idx].send(ts_OML_StateChgEvtRep(NM_OC_CHANNEL, {0, 0, i}, opstate, avstate));
+ }
+}
+
+
+/* Send an OML message and expect no response at all */
+private function f_oml_send_exp_no_resp(template (value) OML_PDU tx, charstring err_msg,
+ float tout := 5.0, integer idx := 0) runs on BTS_OML_CT
+{
+ timer T := tout;
+
+ OML[idx].send(tx);
+ T.start;
+ alt {
+ [] OML[idx].receive {
+ setverdict(fail, err_msg);
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+}
+
+private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg, integer idx := 0)
+ runs on BTS_OML_CT return OML_PDU
+{
+ var OML_PDU rx;
+ timer T := 5.0;
+
+ T.start;
+ alt {
+ [] OML[idx].receive(exp_rx) -> value rx {
+ setverdict(pass);
+ }
+ [] OML[idx].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ", err_msg);
+ }
+ }
+ return rx;
+}
+
+/* Send an OML message and expect a failure event report in response */
+private function f_oml_send_exp_fail_rep(template (value) OML_PDU tx, charstring err_msg,
+ template OML_FOM_EventType evt := ?,
+ template OML_FOM_Severity severity := ?,
+ template OML_FOM_ProbableCause cause := ?,
+ float tout := 5.0, integer idx := 0) runs on BTS_OML_CT
+{
+ var template OML_FOM_ObjectClass obj_class := ?;
+ var template OML_FOM_ObjectInstance obj_inst := ?;
+ if (ischosen(tx.u.fom)) {
+ obj_class := tx.u.fom.hdr.obj_class;
+ obj_inst := tx.u.fom.hdr.obj_inst;
+ }
+ var template OML_PDU exp_fail := tr_OML_FailureEvtRep(obj_class,obj_inst, evt, severity, cause);
+
+ OML[idx].send(tx);
+ f_oml_exp_rx(exp_fail, "Failure Event Report");
+}
+
+/* Send an OML message and expect it to be NACKed with specified cause */
+private function f_oml_send_exp_nack(template (value) OML_PDU tx, template OML_FOM_NackCause exp_cause,
+ float tout := 5.0, integer idx := 0) runs on BTS_OML_CT
+{
+ timer T := 5.0;
+
+ var template OML_PDU exp_nack := f_OML_make_nack_exp(valueof(tx), exp_cause);
+ var template OML_PDU exp_ack := f_OML_make_ack_exp(valueof(tx));
+ var OML_PDU rx;
+
+ OML[idx].send(tx);
+ T.start;
+ alt {
+ [] OML[idx].receive(exp_ack) -> value rx {
+ setverdict(fail, "Unexpected ACK ", rx);
+ }
+ [] OML[idx].receive(exp_nack) -> value rx {
+ setverdict(pass);
+ }
+ [] OML[idx].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for NACK ", exp_nack);
+ }
+ }
+}
+
+testcase TC_oml_nothing() runs on BTS_OML_CT {
+ f_init_oml(testcasename());
+ f_sleep(40.0);
+ setverdict(pass);
+}
+
+/* Test bts setup ramping.
+ * Enable bts setup ramping (limit how many BTS will be setuped within a time interval.
+ * 1. Send 3x BTS to configure
+ * 2. Wait until BTS0 and BTS1 is configured (need both to be sure, when the bts setup ramp interval got restartet).
+ * 3. BTS2 must setup within a time window (it should be 10 seconds, but have -+ 3 seconds to be on the save side).
+ */
+testcase TC_oml_bts_setup_ramp() runs on BTS_OML_CT {
+ var template (value) OML_PDU ts_nm_site_change_event := ts_OML_StateChgEvtRep(NM_OC_SITE_MANAGER, {255, 255, 255}, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+ var template OML_PDU tr_nm_site_op_start := tr_OML_Opstart(NM_OC_SITE_MANAGER, {255, 255, 255});
+
+ f_init_vty();
+
+ f_vty_enter_config(BSCVTY);
+ f_vty_transceive(BSCVTY, "bsc");
+ f_vty_transceive(BSCVTY, "bts-setup-ramping");
+ f_vty_transceive(BSCVTY, "bts-setup-ramping-step-size 1");
+ f_vty_transceive(BSCVTY, "bts-setup-ramping-step-interval 10");
+ f_vty_transceive(BSCVTY, "end");
+
+ f_init_oml(testcasename(), 3);
+
+ f_oml_send_swact(0);
+ f_oml_send_swact(1);
+ f_oml_send_swact(2);
+ f_sleep(1.0);
+ OML[0].send(ts_nm_site_change_event);
+ OML[1].send(ts_nm_site_change_event);
+ OML[2].send(ts_nm_site_change_event);
+ OML[0].receive(tr_nm_site_op_start);
+
+ /* OML[2]: we expect at least no OP start for 7 seconds */
+ timer T_no_op := 7.0;
+ /* OML[2] we expect at least the OP start within 13 seconds */
+ timer T_op := 13.0;
+ alt {
+ [] OML[1].receive(tr_nm_site_op_start) { T_no_op.start; T_op.start; repeat; }
+ [] OML[2].receive(tr_nm_site_op_start) {
+ if (T_no_op.running) {
+ setverdict(fail, "OP Start came to early. T_no_op is still running");
+ } else if (T_op.running) {
+ setverdict(pass);
+ } else {
+ setverdict(fail, "OP Start came far too early.");
+ }
+ }
+ [] T_op.timeout { setverdict(fail, "Timeout. No OP Start PDU for OML[2]."); }
+ }
+}
+
+control {
+ /* execute( TC_oml_nothing() ); */
+ execute( TC_oml_bts_setup_ramp() );
+}
+
+/* BTS:
+ * - Evt: Disabled/Locked
+ * - SW ACT
+ * - Evt: Disabled/Dependency
+ * - SET BTS ATTR
+ * - Opstart
+ * - Chg Adm State Unlocked
+ * - Evt: Disabled/Dependency/Unlocked
+ * - Evt: Enabled/0 (after last channel unlocked?)
+ */
+
+/* Radio Carrier:
+ * - Evt: Disabled/Offline after SW ACT
+ * - Set Radio Carrier Attributes ? (->NACL)
+ * - Evt: Disabled/Dependency
+ * - Set Radio Carrier Attributes ?
+ * - Opstart
+ * - Chg Adm State Unlocked
+ * - Evt:
+ */
+
+/* Baseband Transceiver:
+ * - Evt: Disabled/Locked
+ * - SW Activation
+ * - Evt: Disabled/Dependency after SW ACT
+ * - IPA RSL Connect
+ * - Opstart
+ * - Chg Admin Unlocked
+ * - Evt: Disabled/Dependency/Unlocked
+ */
+
+/* Channel:
+ * - Evt: Not Installed/Locked
+ * - Evt: Disabled/Dependency (after SW ACT Rep on BB Transc)
+ * - Set Channel Attr
+ * - Opstart
+ * - Evt: Disabled/Offline
+ * - Chg Admin Unlocked
+ * - Evt: Disabled/OK/Unlocked
+ * - Evt: Enabled/OK (after BB TRANSC Opstart)
+ */
+
+};
diff --git a/bsc/BSC_Tests_SCCPlite.cfg b/bsc/BSC_Tests_SCCPlite.cfg
new file mode 100644
index 00000000..00f44b37
--- /dev/null
+++ b/bsc/BSC_Tests_SCCPlite.cfg
@@ -0,0 +1,35 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./BSC_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+*.ConsoleMask := LOG_ALL | TTCN_MATCHING;
+*.FileMask := LOG_ALL | TTCN_MATCHING;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+BSC_Tests.mp_bssap_cfg := {
+ {
+ transport := BSSAP_TRANSPORT_SCCPlite_SERVER,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 5000, "127.0.0.1", -1, "" },
+ own_pc := 185, /* 0.23.1 first MSC emulation */
+ own_ssn := 254,
+ peer_pc := 187, /* 0.23.3 osmo-bsc */
+ peer_ssn := 254,
+ sio := '83'O,
+ rctx := 0
+ }
+};
+BSC_Tests.mp_enable_lcs_tests := false;
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+BSC_Tests.control
+BSC_Tests_2.control
diff --git a/bsc/BSC_Tests_VAMOS.cfg b/bsc/BSC_Tests_VAMOS.cfg
new file mode 100644
index 00000000..d8ea2076
--- /dev/null
+++ b/bsc/BSC_Tests_VAMOS.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./BSC_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+BSC_Tests_VAMOS.control
diff --git a/bsc/BSC_Tests_VAMOS.ttcn b/bsc/BSC_Tests_VAMOS.ttcn
new file mode 100644
index 00000000..1dc49106
--- /dev/null
+++ b/bsc/BSC_Tests_VAMOS.ttcn
@@ -0,0 +1,796 @@
+module BSC_Tests_VAMOS {
+
+/* Integration Tests for OsmoBSC
+ * (C) 2021 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
+ *
+ * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
+ * level testing.
+ */
+
+import from BSC_Tests all;
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from IPL4asp_Types all;
+
+import from BSSAP_Types all;
+import from RAN_Adapter all;
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSLAP_Types all;
+import from BSSAP_CodecPort all;
+import from BSSMAP_Templates all;
+import from IPA_Emulation all;
+import from IPA_CodecPort all;
+import from IPA_Types all;
+import from IPA_Testing all;
+import from RSL_Types all;
+import from RSL_Emulation all;
+import from MGCP_Emulation all;
+import from MGCP_Templates all;
+import from MGCP_Types all;
+import from MGCP_CodecPort all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_Types all;
+import from MobileL3_RRM_Types all;
+import from L3_Templates all;
+import from GSM_RR_Types all;
+
+import from SCCP_Templates all;
+import from BSSMAP_Templates all;
+import from BSSMAP_LE_Templates all;
+
+import from SCCPasp_Types all;
+
+import from GSM_SystemInformation all;
+import from GSM_RestOctets all;
+import from TCCConversion_Functions all;
+
+import from RAN_Emulation all;
+import from MSC_ConnectionHandler all;
+
+import from Native_Functions all;
+
+const integer NUM_BTS := 3;
+const integer NUM_MSC := 3;
+
+private function f_rsl_chan_nr_to_subslot(RslChannelNr chan_nr, boolean use_vamos_subslot_nr := false)
+return integer
+{
+ var integer subslot;
+ select (chan_nr) {
+ case (t_RslChanNr_Bm(?)) {
+ /* TCH/F, always subslot 0 */
+ subslot := 0;
+ }
+ case (t_RslChanNr_Lm(?, ?)) {
+ /* TCH/H */
+ subslot := chan_nr.u.lm.sub_chan;
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+ /* TCH/F shadow */
+ if (use_vamos_subslot_nr) {
+ subslot := 1;
+ } else {
+ subslot := 0;
+ }
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+ /* TCH/H shadow */
+ subslot := chan_nr.u.lm.sub_chan;
+ if (use_vamos_subslot_nr) {
+ subslot := subslot + 2;
+ }
+ }
+ case else {
+ setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_subslot()");
+ mtc.stop;
+ }
+ }
+ return subslot;
+}
+
+private function f_rsl_chan_nr_to_rsl_cbits(RslChannelNr chan_nr)
+return BIT5
+{
+ var BIT5 rsl_cbits;
+ select (chan_nr) {
+ case (t_RslChanNr_Bm(?)) {
+ rsl_cbits := '00001'B;
+ }
+ case (t_RslChanNr_Lm(?, ?)) {
+ rsl_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+ rsl_cbits := '11101'B;
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+ rsl_cbits := int2bit(30 + chan_nr.u.lm.sub_chan, 5); /* '1111x'B */
+ }
+ case else {
+ setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_rsl_cbits()");
+ mtc.stop;
+ }
+ }
+ return rsl_cbits;
+}
+
+private function f_rsl_chan_nr_to_rr_cbits(RslChannelNr chan_nr)
+return BIT5
+{
+ var BIT5 rr_cbits;
+ select (chan_nr) {
+ case (t_RslChanNr_Bm(?)) {
+ rr_cbits := '00001'B;
+ }
+ case (t_RslChanNr_Lm(?, ?)) {
+ rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+ rr_cbits := '00001'B;
+ /* In RR, there must *not* be Osmocom specific cbits */
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+ rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* '0001x'B */
+ /* In RR, there must *not* be Osmocom specific cbits */
+ }
+ case else {
+ setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_rr_cbits()");
+ mtc.stop;
+ }
+ }
+ return rr_cbits;
+}
+
+private function f_rsl_chan_nr_to_chrt(RslChannelNr chan_nr, boolean vamos)
+return RSL_ChanRateType
+{
+ var boolean fr;
+ select (chan_nr) {
+ case (t_RslChanNr_Bm(?)) {
+ fr := true;
+ }
+ case (t_RslChanNr_Lm(?, ?)) {
+ fr := false;
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+ fr := true;
+ }
+ case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+ fr := false;
+ }
+ case else {
+ setverdict(fail, "unsupported RslChannelNr type in f_rsl_chan_nr_to_chrt()");
+ mtc.stop;
+ }
+ }
+ if (fr) {
+ if (vamos) {
+ return RSL_CHRT_OSMO_TCH_F_VAMOS;
+ } else {
+ return RSL_CHRT_TCH_F;
+ }
+ } else {
+ if (vamos) {
+ return RSL_CHRT_OSMO_TCH_H_VAMOS;
+ } else {
+ return RSL_CHRT_TCH_H;
+ }
+ }
+}
+
+private function f_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr chan_nr, boolean use_vamos_subslot_nr := false)
+return charstring
+{
+ var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr, use_vamos_subslot_nr := use_vamos_subslot_nr);
+ return "lchan " & int2str(bts_nr) & " " & int2str(trx_nr) & " " & int2str(chan_nr.tn) & " " & int2str(subslot);
+}
+
+private function f_long_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr chan_nr)
+return charstring
+{
+ var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr);
+ return "bts " & int2str(bts_nr) & " trx " & int2str(trx_nr) & " timeslot " & int2str(chan_nr.tn) & " sub-slot " & int2str(subslot);
+}
+
+private function f_lchan_ensure_established(TELNETasp_PT vty, integer bts_nr, integer trx_nr, RslChannelNr chan_nr)
+{
+ var charstring lchan_str := f_lchan_str(bts_nr, trx_nr, chan_nr, use_vamos_subslot_nr := true);
+ var charstring lchan_info := f_vty_transceive_ret(vty, "show " & lchan_str);
+ if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+ log("'show lchan' replied: ", lchan_info);
+ setverdict(fail, "lchan " & lchan_str & " is not in state ESTABLISHED");
+ mtc.stop;
+ }
+ setverdict(pass);
+}
+
+/* Activate a primary lchan in VAMOS speech mode */
+testcase TC_chan_act_to_vamos() runs on test_CT {
+ f_init_vty();
+
+ f_logp(BSCVTY, "TC_chan_act_to_vamos");
+
+ f_init(1, false);
+ f_sleep(1.0);
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 activate-vamos fr");
+
+ var RSL_Message rsl;
+
+ rsl := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+ var RSL_IE_Body chan_mode_ie;
+ if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, chan_mode_ie) == false) {
+ setverdict(fail, "Cannot find RSL_IE_CHAN_MODE");
+ mtc.stop;
+ }
+ if (chan_mode_ie.chan_mode.ch_rate_type != RSL_CHRT_OSMO_TCH_F_VAMOS) {
+ setverdict(fail, "expected chan_mode.ch_rate_type == RSL_CHRT_OSMO_TCH_F_VAMOS");
+ mtc.stop;
+ }
+
+ var RSL_IE_Body osmo_tsc_ie;
+ if (f_rsl_find_ie(rsl, RSL_IE_OSMO_TRAINING_SEQUENCE, osmo_tsc_ie) == false) {
+ setverdict(fail, "Cannot find RSL_IE_OSMO_TRAINING_SEQUENCE");
+ mtc.stop;
+ }
+
+ var RslChannelNr chan_nr := rsl.ies[0].body.chan_nr;
+ f_ipa_tx(ts_RSL_CHAN_ACT_ACK(chan_nr, 23+10));
+
+ f_sleep(1.0);
+ f_lchan_ensure_established(BSCVTY, 0, 0, chan_nr);
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 deactivate");
+
+ f_shutdown_helper();
+}
+
+/* verify that DTAP passes through both ways with the right cbits */
+private function f_verify_dtap() runs on MSC_ConnHdlr
+{
+ var PDU_BSSAP rx_bssap_dtap;
+ var octetstring l3_data := gen_l3_valid_payload();
+
+ /* MS to NW */
+ RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), l3_data));
+ BSSAP.receive(tr_BSSAP_DTAP) -> value rx_bssap_dtap;
+ if (not match(rx_bssap_dtap.pdu.dtap, l3_data)) {
+ setverdict(fail, "unexpected L3 data");
+ mtc.stop;
+ }
+
+ /* NW to MS */
+ l3_data := '0800dcba9876543210'O;
+ BSSAP.send(ts_BSSAP_DTAP(l3_data, '00'O));
+ RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, tr_RslLinkID_DCCH(0), l3_data));
+}
+
+
+private function f_est_lchan_and_mode_modify_to_vamos() runs on MSC_ConnHdlr {
+ var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux_cn);
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+
+ /* puzzle together the ASSIGNMENT REQ for given codec[s] */
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+ g_pars.ass_codec_list.codecElements[0];
+ if (isvalue(g_pars.expect_mr_s0_s7)) {
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+ g_pars.expect_mr_s0_s7;
+ }
+ }
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+ f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+ log("expecting ASS COMPL like this: ", exp_compl);
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+
+ var charstring current_long_lchan_str := f_long_lchan_str(0, 0, g_chan_nr);
+ f_vty_transceive(BSCVTY, current_long_lchan_str & " modify vamos tsc 2 3");
+
+ var RSL_Message rsl_rr;
+ RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl_rr;
+
+ var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl_rr.ies[2].body.l3_info.payload);
+
+ var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+ template PDU_ML3_NW_MS expect_rr_modify := tr_RRM_ModeModify(
+ tr_ChannelDescription2_V(timeslotNumber := int2bit(g_chan_nr.tn, 3)),
+ tr_ChannelMode_V(mode := 'C1'O /* 1 1 0 0 0 0 0 1 speech full rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
+ extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet := '01'B));
+
+ if (not match(l3, expect_rr_modify)) {
+ log("expected: ", expect_rr_modify);
+ log("got: ", l3);
+ setverdict(fail, "RR channelModeModify message is not as expected");
+ mtc.stop;
+ }
+ f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
+ l3.msgs.rrm.channelModeModify.channelMode,
+ l3.msgs.rrm.channelModeModify.extendedTSCSet), rsl_rr);
+
+ var RSL_Message rsl;
+ RSL.receive(tr_RSL_MODE_MODIFY_REQ_with_OSMO_TSC(g_chan_nr, tr_RSL_ChanMode(f_rsl_chan_nr_to_chrt(g_chan_nr, true), RSL_CMOD_SP_GSM1),
+ tsc_set := 1, /* 1 means TSC Set 2 (range 1-4 in spec tables and naming, 0-3 on the wire) */
+ tsc := 3));
+ RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
+ f_sleep(1.0);
+
+ f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+ f_verify_dtap();
+}
+
+private function f_TC_mode_modify_to_vamos(charstring id) runs on MSC_ConnHdlr {
+ f_est_lchan_and_mode_modify_to_vamos();
+ f_perform_clear(RSL);
+}
+
+/* Modify a primary lchan into VAMOS speech mode */
+testcase TC_mode_modify_to_vamos_fr() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Modify a primary lchan into VAMOS speech mode */
+testcase TC_mode_modify_to_vamos_hr() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+ vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
+private function f_reassign_secondary_to_primary_lchan(RslChannelNr new_chan_nr) runs on MSC_ConnHdlr
+{
+ var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+ var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
+ var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
+
+ activate(as_Media_mgw());
+
+ f_rslem_register(0, new_chan_nr, RSL_PROC);
+ log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " vamos-sub-slot " & int2str(current_subslot)
+ & " reassign-to trx 0 timeslot " & int2str(new_chan_nr.tn) & " sub-slot " & int2str(new_subslot));
+ /* RSL CHAN ACT is ACKed by RSL emulation */
+
+ var RSL_Message rsl;
+ var RSL_IE_Body ie;
+ var boolean b_unused;
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+ var template PDU_ML3_NW_MS expect_rr_assignment := tr_RR_AssignmentCommand(
+ desc := tr_ChannelDescription2_V(timeslotNumber := int2bit(new_chan_nr.tn, 3),
+ channelTypeandTDMAOffset := new_rr_cbits),
+ mode := tr_ChannelMode_TV(mode := '01'O
+ /* 0 0 0 0 0 0 0 1 speech full rate or half rate version 1 (3GPP TS 44.018) */),
+ extendedTSCSet := omit);
+ if (not match(l3, expect_rr_assignment)) {
+ log("expected: ", expect_rr_assignment);
+ log("got: ", l3);
+ setverdict(fail, "RR assignmentCommand message is not as expected");
+ mtc.stop;
+ }
+
+ var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
+ RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
+ enc_PDU_ML3_MS_NW(l3_tx)));
+
+ }
+ [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
+ var uint7_t rtp_pt := 0;
+ if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+ rtp_pt := ie.ipa_rtp_pt;
+ }
+ RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
+ f_inet_addr("1.2.3.4"),
+ 4321,
+ rtp_pt));
+ }
+ [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
+ /* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+ var uint16_t conn_id := ie.ipa_conn_id;
+ /* mandatory */
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+ var HostPort peer;
+ peer.host := f_inet_ntoa(ie.ipa_remote_ip);
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+ peer.port_nr := ie.ipa_remote_port;
+ var uint7_t rtp_pt := 0;
+ /* optional */
+ if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+ rtp_pt := ie.ipa_rtp_pt;
+ }
+ RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
+ f_inet_addr(peer.host),
+ peer.port_nr,
+ rtp_pt));
+ }
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
+ IPAC_PROTO_RSL_TRX0));
+ f_rslem_unregister(0, g_chan_nr, RSL_PROC);
+ g_chan_nr := new_chan_nr;
+ }
+ /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
+ }
+
+ setverdict(pass);
+
+ f_sleep(1.0);
+ f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+
+ f_verify_dtap();
+}
+
+private function f_est_and_reassign_to_secondary_lchan(RslChannelNr new_chan_nr) runs on MSC_ConnHdlr
+{
+ var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
+ var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
+
+ var PDU_BSSAP ass_cmd := f_gen_ass_req();
+ var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+
+ /* puzzle together the ASSIGNMENT REQ for given codec[s] */
+ if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+ ass_cmd.pdu.bssmap.assignmentRequest.codecList := g_pars.ass_codec_list;
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+ g_pars.ass_codec_list.codecElements[0];
+ if (isvalue(g_pars.expect_mr_s0_s7)) {
+ exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+ g_pars.expect_mr_s0_s7;
+ }
+ }
+ ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+ f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+ log("expecting ASS COMPL like this: ", exp_compl);
+
+ f_establish_fully(ass_cmd, exp_compl);
+
+ var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+ f_sleep(1.0);
+
+ activate(as_Media_mgw());
+
+ f_rslem_register(0, new_chan_nr, RSL_PROC);
+ log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
+
+ f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & int2str(g_chan_nr.tn) & " sub-slot " & int2str(current_subslot)
+ & " reassign-to trx 0 timeslot " & int2str(new_chan_nr.tn) & " vamos-sub-slot " & int2str(new_subslot) & " tsc 4 2");
+ /* RSL CHAN ACT is ACKed by RSL emulation */
+
+ var RSL_Message rsl;
+ var RSL_IE_Body ie;
+ var boolean b_unused;
+ interleave {
+ [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+ var template PDU_ML3_NW_MS expect_rr_assignment := tr_RR_AssignmentCommand(
+ desc := tr_ChannelDescription2_V(timeslotNumber := int2bit(new_chan_nr.tn, 3),
+ channelTypeandTDMAOffset := new_rr_cbits),
+ mode := tr_ChannelMode_TV(mode := 'C1'O
+ /* 1 1 0 0 0 0 0 1 speech full rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
+ extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet := '11'B
+ /* 3 means TSC Set 4 (range 1-4 in spec tables and naming, 0-3 on the wire) */));
+ if (not match(l3, expect_rr_assignment)) {
+ log("expected: ", expect_rr_assignment);
+ log("got: ", l3);
+ setverdict(fail, "RR assignmentCommand message is not as expected");
+ mtc.stop;
+ }
+
+ var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
+ RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
+ enc_PDU_ML3_MS_NW(l3_tx)));
+
+ }
+ [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
+ var uint7_t rtp_pt := 0;
+ if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+ rtp_pt := ie.ipa_rtp_pt;
+ }
+ RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
+ f_inet_addr("1.2.3.4"),
+ 4321,
+ rtp_pt));
+ }
+ [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
+ /* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+ var uint16_t conn_id := ie.ipa_conn_id;
+ /* mandatory */
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+ var HostPort peer;
+ peer.host := f_inet_ntoa(ie.ipa_remote_ip);
+ b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+ peer.port_nr := ie.ipa_remote_port;
+ var uint7_t rtp_pt := 0;
+ /* optional */
+ if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+ rtp_pt := ie.ipa_rtp_pt;
+ }
+ RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
+ f_inet_addr(peer.host),
+ peer.port_nr,
+ rtp_pt));
+ }
+ [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+ [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
+ IPAC_PROTO_RSL_TRX0));
+ f_rslem_unregister(0, g_chan_nr, RSL_PROC);
+ g_chan_nr := new_chan_nr;
+ }
+ /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
+ }
+
+ setverdict(pass);
+
+ f_sleep(1.0);
+ f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+ f_verify_dtap();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan.
+ * Also re-assign back to a primary lchan. */
+private function f_TC_assign_to_secondary_lchan_fr(charstring id) runs on MSC_ConnHdlr {
+ f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(2)));
+ f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Bm(3)));
+ f_perform_clear(RSL);
+ f_sleep(1.0);
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
+testcase TC_assign_to_secondary_lchan_fr() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_fr), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan.
+ * Also re-assign back to a primary lchan. */
+private function f_TC_assign_to_secondary_lchan_hr(charstring id) runs on MSC_ConnHdlr {
+ f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(6, 0)));
+ f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Lm(6, 1)));
+ f_perform_clear(RSL);
+ f_sleep(1.0);
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow lchan. */
+testcase TC_assign_to_secondary_lchan_hr() runs on test_CT {
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+ vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_hr), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+const charstring PRIMARY_LCHAN_DONE := "PRIMARY_LCHAN_DONE";
+const charstring MULTIPLEX_DONE := "MULTIPLEX_DONE";
+
+/* First, primary lchan of TC_vamos_multiplex_tch_f_tch_f() */
+private function f_TC_vamos_multiplex_tch_f_tch_f1(charstring id) runs on MSC_ConnHdlr {
+ f_est_lchan_and_mode_modify_to_vamos();
+ f_sleep(1.0);
+ COORD.send(PRIMARY_LCHAN_DONE);
+ f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+ COORD.receive(MULTIPLEX_DONE);
+ f_perform_clear(RSL);
+}
+
+/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_f_tch_f() */
+private function f_TC_vamos_multiplex_tch_f_tch_f2(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+ COORD.receive(PRIMARY_LCHAN_DONE);
+ f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(1)));
+ f_sleep(1.0);
+ COORD.send(MULTIPLEX_DONE);
+ f_perform_clear(RSL);
+}
+
+/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
+ * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
+ * first primary lchan. */
+testcase TC_vamos_multiplex_tch_f_tch_f() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.imsi := '001014234234234'H;
+ pars2.media_nr := 2;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+ pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+ vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f1), pars1);
+ vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f2), pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+
+ vc_conn1.done;
+ vc_conn2.done;
+
+ f_shutdown_helper();
+}
+
+const charstring DONE := "DONE";
+
+/*
+ * f1 f2 f3 f4
+ * COORD <--> COORD | COORD2 <--> COORD | COORD2 <--> COORD
+ * ---DONE-----> ---DONE-----> ---DONE----->
+ * <----DONE---- <----DONE---- <----DONE----
+ */
+
+/* First, primary lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() */
+private function f_TC_vamos_multiplex_tch_h_tch_h1(charstring id) runs on MSC_ConnHdlr {
+ f_est_lchan_and_mode_modify_to_vamos();
+ f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+ COORD.send(DONE);
+ COORD.receive(DONE);
+ f_perform_clear(RSL);
+}
+
+/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() */
+private function f_TC_vamos_multiplex_tch_h_tch_h2(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+ COORD.receive(DONE);
+ f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 0)));
+ COORD2.send(DONE);
+ COORD2.receive(DONE)
+ COORD.send(DONE);
+ f_perform_clear(RSL);
+}
+
+private function f_TC_vamos_multiplex_tch_h_tch_h3(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+ COORD.receive(DONE);
+ f_est_lchan_and_mode_modify_to_vamos();
+ f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+ COORD2.send(DONE);
+ COORD2.receive(DONE);
+ COORD.send(DONE);
+ f_perform_clear(RSL);
+}
+
+private function f_TC_vamos_multiplex_tch_h_tch_h4(charstring id) runs on MSC_ConnHdlr {
+ f_sleep(1.0);
+ COORD.receive(DONE);
+ f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 1)));
+ COORD.send(DONE);
+ f_perform_clear(RSL);
+}
+
+/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
+ * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
+ * first primary lchan. */
+testcase TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() runs on test_CT {
+ var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn1;
+ pars1.imsi := '001011111111111'H;
+ pars1.media_nr := 1;
+
+ var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn2;
+ pars2.imsi := '001012222222222'H;
+ pars2.media_nr := 2;
+
+ var TestHdlrParams pars3 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn3;
+ pars3.imsi := '001013333333333'H;
+ pars3.media_nr := 3;
+
+ var TestHdlrParams pars4 := f_gen_test_hdlr_pars();
+ var MSC_ConnHdlr vc_conn4;
+ pars4.imsi := '001014444444444'H;
+ pars4.media_nr := 4;
+
+ f_init(1, true);
+ f_sleep(1.0);
+
+ pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+ pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+ pars3.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+ pars4.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+
+ vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h1), pars1);
+ vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h2), pars2);
+
+ /* Also fill up the second subslot of the TCH/H timeslot */
+ vc_conn3 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h3), pars3);
+ vc_conn4 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h4), pars4);
+
+ /* see diagram above (search for "---DONE") */
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ connect(vc_conn2:COORD2, vc_conn3:COORD);
+ connect(vc_conn3:COORD2, vc_conn4:COORD);
+
+ vc_conn1.done;
+ vc_conn2.done;
+ vc_conn3.done;
+ vc_conn4.done;
+
+ f_shutdown_helper();
+}
+
+control {
+ execute( TC_chan_act_to_vamos() );
+ execute( TC_mode_modify_to_vamos_fr() );
+ execute( TC_mode_modify_to_vamos_hr() );
+ execute( TC_assign_to_secondary_lchan_fr() );
+ execute( TC_assign_to_secondary_lchan_hr() );
+ execute( TC_vamos_multiplex_tch_f_tch_f() );
+ execute( TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() );
+}
+
+}
diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn
index 7d8fce15..88a1b58f 100644
--- a/bsc/MSC_ConnectionHandler.ttcn
+++ b/bsc/MSC_ConnectionHandler.ttcn
@@ -19,6 +19,9 @@ import from IPA_Emulation all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from RAN_Emulation all;
+import from BSSAP_LE_Emulation all;
+import from BSSAP_LE_Types all;
+import from BSSMAP_LE_Templates all;
import from BSSMAP_Templates all;
import from IPL4asp_Types all;
@@ -29,6 +32,9 @@ import from MGCP_Types all;
import from MGCP_Templates all;
import from MGCP_Emulation all;
import from SDP_Types all;
+import from SDP_Templates all;
+
+import from StatsD_Checker all;
import from RSL_Emulation all;
import from RSL_Types all;
@@ -40,12 +46,16 @@ import from L3_Templates all;
import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;
+import from TCCConversion_Functions all;
/***********************************************************************
* Media related handling
***********************************************************************/
+/* TODO: import OSMUX_Types.ttcn */
+type INT1 OsmuxCID (0 .. 255);
+
/* Get the matching payload type for a specified BSSAP codec type
* (see also: BSSAP_Types.ttcn */
private function f_get_mgcp_pt(BSSMAP_FIELD_CodecType codecType) return SDP_FIELD_PayloadType {
@@ -82,7 +92,9 @@ type record MgcpConnState {
integer ptime, /* 20 */
uint7_t rtp_pt, /* RTP Payload Type */
HostPort mgw, /* MGW side */
- HostPort peer /* CA side */
+ HostPort peer, /* CA side */
+ OsmuxCID local_osmux_cid optional,
+ OsmuxCID remote_osmux_cid optional
};
/* BTS media state */
@@ -92,7 +104,9 @@ type record BtsMediaState {
uint16_t conn_id,
uint7_t rtp_pt,
HostPort bts,
- HostPort peer
+ HostPort peer,
+ OsmuxCID local_osmux_cid optional,
+ OsmuxCID remote_osmux_cid optional
};
type record MediaState {
@@ -113,7 +127,9 @@ function f_MediaState_init(inout MediaState g_media, integer nr, HostName bts, H
host := bts,
port_nr := 9000 + nr*2
},
- peer := -
+ peer := -,
+ local_osmux_cid := nr,
+ remote_osmux_cid := omit
}
g_media.bts1 := {
@@ -125,7 +141,9 @@ function f_MediaState_init(inout MediaState g_media, integer nr, HostName bts, H
host := bts, /* FIXME */
port_nr := 9000 + nr*2
},
- peer := -
+ peer := -,
+ local_osmux_cid := nr,
+ remote_osmux_cid := omit
}
g_media.mgcp_ep := "rtpbridge/" & int2str(nr) & "@mgw";
@@ -140,6 +158,8 @@ function f_MediaState_init(inout MediaState g_media, integer nr, HostName bts, H
g_media.mgcp_conn[i].crcx_seen_exp := 0;
g_media.mgcp_conn[i].mdcx_seen_exp := 0;
g_media.mgcp_conn[i].conn_id := f_mgcp_alloc_conn_id();
+ g_media.mgcp_conn[i].local_osmux_cid := i;
+ g_media.mgcp_conn[i].remote_osmux_cid := omit;
}
g_media.mgcp_conn[0].mgw := {
@@ -179,13 +199,35 @@ private function f_get_mgcp_conn(MgcpConnectionId cid) runs on MSC_ConnHdlr retu
return -1;
}
+/* Verify that CSD CRCX/MDCX has the RSL_IE_IPAC_RTP_CSD_FMT IE, and that
+ * inside it the D value is set to RSL_IPA_RTP_CSD_TRAU_BTS. */
+private function f_ipacc_crcx_mdcx_check_rtp_pt_csd(RSL_Message rsl) runs on MSC_ConnHdlr {
+ var SDP_FIELD_PayloadType pt_csd := PT_CSD;
+ var RSL_IE_Body ie;
+
+ if (g_media.bts.rtp_pt != enum2int(pt_csd)) {
+ return;
+ }
+
+ if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_CSD_FMT, ie)) {
+ if (ie.ipa_rtp_csd_fmt.d != RSL_IPA_RTP_CSD_TRAU_BTS) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx unexpected IPAC CRCX for CSD with RTP_CSD_FMT IE");
+ }
+ return;
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx unexpected IPAC CRCX for CSD without RTP_CSD_FMT IE");
+}
+
/* altstep for handling of IPACC media related commands. Activated by as_Media() to test
* RSL level media handling */
-altstep as_Media_ipacc() runs on MSC_ConnHdlr {
+altstep as_Media_ipacc(RSL_DCHAN_PT rsl_pt := RSL, RSL_DCHAN_PT rsl_pt_ho_target := RSL1) runs on MSC_ConnHdlr {
var RSL_Message rsl;
var RSL_IE_Body ie;
var boolean b_unused;
- [not g_media.bts.ipa_crcx_seen] RSL.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
+ [not g_media.bts.ipa_crcx_seen] rsl_pt.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
/* Extract parameters from request + use in response */
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
g_media.bts.rtp_pt := ie.ipa_rtp_pt;
@@ -193,14 +235,28 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
g_media.bts.rtp_pt := ie.ipa_rtp_pt2;
}
- RSL.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, g_media.bts.conn_id,
- oct2int(f_inet_addr(g_media.bts.bts.host)),
+ if (f_rsl_find_ie(rsl, RSL_IE_OSMO_OSMUX_CID, ie)) {
+ if (not g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC CRCX with Osmux CID IE");
+ }
+ g_media.bts.remote_osmux_cid := ie.osmux_cid.cid;
+ } else {
+ if (g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC CRCX without Osmux CID IE");
+ }
+ g_media.bts.local_osmux_cid := omit;
+ g_media.bts.remote_osmux_cid := omit;
+ }
+ f_ipacc_crcx_mdcx_check_rtp_pt_csd(rsl);
+ rsl_pt.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, g_media.bts.conn_id,
+ f_inet_addr(g_media.bts.bts.host),
g_media.bts.bts.port_nr,
- g_media.bts.rtp_pt));
+ g_media.bts.rtp_pt,
+ g_media.bts.local_osmux_cid));
g_media.bts.ipa_crcx_seen := true;
repeat;
}
- [g_media.bts.ipa_crcx_seen] RSL.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
+ [g_media.bts.ipa_crcx_seen] rsl_pt.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
/* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
if (g_media.bts.conn_id != ie.ipa_conn_id) {
@@ -208,7 +264,7 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
}
/* mandatory */
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
- g_media.bts.peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+ g_media.bts.peer.host := f_inet_ntoa(ie.ipa_remote_ip);
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
g_media.bts.peer.port_nr := ie.ipa_remote_port;
/* optional */
@@ -218,16 +274,30 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
g_media.bts.rtp_pt := ie.ipa_rtp_pt2;
}
- RSL.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, g_media.bts.conn_id,
- oct2int(f_inet_addr(g_media.bts.peer.host)),
+ if (f_rsl_find_ie(rsl, RSL_IE_OSMO_OSMUX_CID, ie)) {
+ if (not g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC MDCX with Osmux CID IE");
+ }
+ g_media.bts.remote_osmux_cid := ie.osmux_cid.cid;
+ } else {
+ if (g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC MDCX without Osmux CID IE");
+ }
+ g_media.bts.local_osmux_cid := omit;
+ g_media.bts.remote_osmux_cid := omit;
+ }
+ f_ipacc_crcx_mdcx_check_rtp_pt_csd(rsl);
+ rsl_pt.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, g_media.bts.conn_id,
+ f_inet_addr(g_media.bts.peer.host),
g_media.bts.peer.port_nr,
- g_media.bts.rtp_pt));
+ g_media.bts.rtp_pt,
+ g_media.bts.local_osmux_cid));
g_media.bts.ipa_mdcx_seen := true;
repeat;
}
/* on second (new) BTS during hand-over */
- [not g_media.bts1.ipa_crcx_seen] RSL1.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
+ [not g_media.bts1.ipa_crcx_seen] rsl_pt_ho_target.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
/* Extract parameters from request + use in response */
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
g_media.bts1.rtp_pt := ie.ipa_rtp_pt;
@@ -235,15 +305,28 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
g_media.bts1.rtp_pt := ie.ipa_rtp_pt2;
}
- RSL1.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, g_media.bts1.conn_id,
- oct2int(f_inet_addr(g_media.bts1.bts.host)),
+ if (f_rsl_find_ie(rsl, RSL_IE_OSMO_OSMUX_CID, ie)) {
+ if (not g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC CRCX with Osmux CID IE");
+ }
+ g_media.bts.remote_osmux_cid := ie.osmux_cid.cid;
+ } else {
+ if (g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC CRCX without Osmux CID IE");
+ }
+ g_media.bts.local_osmux_cid := omit;
+ g_media.bts.remote_osmux_cid := omit;
+ }
+ rsl_pt_ho_target.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, g_media.bts1.conn_id,
+ f_inet_addr(g_media.bts1.bts.host),
g_media.bts1.bts.port_nr,
- g_media.bts1.rtp_pt));
+ g_media.bts1.rtp_pt,
+ g_media.bts.local_osmux_cid));
g_media.bts1.ipa_crcx_seen := true;
repeat;
}
/* on second (new) BTS during hand-over */
- [g_media.bts1.ipa_crcx_seen] RSL1.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
+ [g_media.bts1.ipa_crcx_seen] rsl_pt_ho_target.receive(tr_RSL_IPA_MDCX(g_chan_nr, ?)) -> value rsl{
/* Extract conn_id, ip, port, rtp_pt2 from request + use in response */
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
if (g_media.bts1.conn_id != ie.ipa_conn_id) {
@@ -251,7 +334,7 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
}
/* mandatory */
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
- g_media.bts1.peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+ g_media.bts1.peer.host := f_inet_ntoa(ie.ipa_remote_ip);
b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
g_media.bts1.peer.port_nr := ie.ipa_remote_port;
/* optional */
@@ -261,10 +344,23 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
g_media.bts1.rtp_pt := ie.ipa_rtp_pt2;
}
- RSL1.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, g_media.bts1.conn_id,
- oct2int(f_inet_addr(g_media.bts1.peer.host)),
+ if (f_rsl_find_ie(rsl, RSL_IE_OSMO_OSMUX_CID, ie)) {
+ if (not g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC MDCX with Osmux CID IE");
+ }
+ g_media.bts.remote_osmux_cid := ie.osmux_cid.cid;
+ } else {
+ if (g_pars.use_osmux_bts) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected IPAC MDCX without Osmux CID IE");
+ }
+ g_media.bts.local_osmux_cid := omit;
+ g_media.bts.remote_osmux_cid := omit;
+ }
+ rsl_pt_ho_target.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, g_media.bts1.conn_id,
+ f_inet_addr(g_media.bts1.peer.host),
g_media.bts1.peer.port_nr,
- g_media.bts1.rtp_pt));
+ g_media.bts1.rtp_pt,
+ g_media.bts.local_osmux_cid));
g_media.bts1.ipa_mdcx_seen := true;
repeat;
}
@@ -274,9 +370,17 @@ altstep as_Media_ipacc() runs on MSC_ConnHdlr {
function f_rx_crcx(MgcpCommand mgcp_cmd)
runs on MSC_ConnHdlr return template MgcpResponse {
- var MgcpOsmuxCID osmux_cid;
var SDP_Message sdp;
var integer cid := f_get_free_mgcp_conn();
+ var charstring local_rtp_addr;
+ var MgcpOsmuxCID osmux_cid;
+
+ if (g_pars.media_mgw_offer_ipv6 == true) {
+ local_rtp_addr := host_mgw_rtp_v6; /* Use IPv6 by default if no remote addr is provided by client */
+ } else {
+ local_rtp_addr := host_mgw_rtp_v4; /* Use IPv4 by default if no remote addr is provided by client */
+ }
+
if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard)) {
if (cid != 0) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MGCP wildcard EP only works in first CRCX");
@@ -290,18 +394,27 @@ function f_rx_crcx(MgcpCommand mgcp_cmd)
sdp := mgcp_cmd.sdp;
g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
+ if (sdp.connection.addr_type == "IP6") {
+ local_rtp_addr := host_mgw_rtp_v6;
+ } else {
+ local_rtp_addr := host_mgw_rtp_v4;
+ }
}
var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
- sdp := valueof(ts_SDP(mgcp_conn.mgw.host, mgcp_conn.mgw.host, "foo", "21",
+ sdp := valueof(ts_SDP(mgcp_conn.mgw.host, local_rtp_addr, "foo", "21",
mgcp_conn.mgw.port_nr, { int2str(mgcp_conn.rtp_pt) },
{valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
mgcp_conn.mime_type & "/" &
int2str(mgcp_conn.sample_rate))),
valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
var template MgcpResponse mgcp_resp;
- if (g_pars.use_osmux and f_MgcpCmd_contains_par(mgcp_cmd, "X-OSMUX")) {
+ if ((g_pars.use_osmux_cn or g_pars.use_osmux_bts) and
+ f_MgcpCmd_contains_par(mgcp_cmd, "X-OSMUX")) {
osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
- mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, osmux_cid, sdp);
+ if (osmux_cid != -1) {
+ mgcp_conn.remote_osmux_cid := osmux_cid;
+ }
+ mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, mgcp_conn.local_osmux_cid, sdp);
} else {
mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, mgcp_conn.conn_id, sdp);
}
@@ -314,15 +427,21 @@ function f_rx_mdcx(MgcpCommand mgcp_cmd)
runs on MSC_ConnHdlr return template MgcpResponse {
var SDP_Message sdp;
var integer cid := f_get_mgcp_conn(f_MgcpCmd_extract_conn_id(mgcp_cmd));
+ var charstring local_rtp_addr;
if (isvalue(mgcp_cmd.sdp)) {
sdp := mgcp_cmd.sdp;
g_media.mgcp_conn[cid].peer.host := sdp.connection.conn_addr.addr;
g_media.mgcp_conn[cid].peer.port_nr := sdp.media_list[0].media_field.ports.port_number;
+ if (sdp.connection.addr_type == "IP6") {
+ local_rtp_addr := host_mgw_rtp_v6;
+ } else {
+ local_rtp_addr := host_mgw_rtp_v4;
+ }
} else {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "MDCX has no [recognizable] SDP");
}
var MgcpConnState mgcp_conn := g_media.mgcp_conn[cid];
- sdp := valueof(ts_SDP(mgcp_conn.peer.host, mgcp_conn.peer.host, "foo", "21",
+ sdp := valueof(ts_SDP(mgcp_conn.peer.host, local_rtp_addr, "foo", "21",
mgcp_conn.peer.port_nr, { int2str(mgcp_conn.rtp_pt) },
{valueof(ts_SDP_rtpmap(mgcp_conn.rtp_pt,
mgcp_conn.mime_type & "/" &
@@ -358,6 +477,9 @@ altstep as_Media_mgw(boolean norepeat := false) runs on MSC_ConnHdlr {
var template MgcpMessage msg_mdcx := {
command := tr_MDCX
}
+ var template MgcpMessage msg_dlcx := {
+ command := tr_DLCX
+ }
var template MgcpMessage msg_resp;
[g_pars.aoip] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
@@ -379,7 +501,7 @@ altstep as_Media_mgw(boolean norepeat := false) runs on MSC_ConnHdlr {
}
}
- [g_pars.aoip] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
+ [g_pars.aoip and not g_pars.ignore_mgw_mdcx] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
mgcp_resp := f_rx_mdcx(mgcp_cmd);
MGCP.send(mgcp_resp);
if(norepeat == false) {
@@ -387,7 +509,8 @@ altstep as_Media_mgw(boolean norepeat := false) runs on MSC_ConnHdlr {
}
}
- [not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_mdcx)) -> value mrf {
+ [not g_pars.aoip and not g_pars.ignore_mgw_mdcx]
+ MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_mdcx)) -> value mrf {
mgcp_resp := f_rx_mdcx(mrf.msg.command);
msg_resp := {
response := mgcp_resp
@@ -397,25 +520,40 @@ altstep as_Media_mgw(boolean norepeat := false) runs on MSC_ConnHdlr {
repeat;
}
}
+
+ [g_pars.fail_on_dlcx and g_pars.aoip] MGCP.receive(tr_DLCX) {
+ setverdict(fail, "Unexpected DLCX received");
+ }
+
+ [g_pars.fail_on_dlcx and not g_pars.aoip] MGCP_MULTI.receive(tr_MGCP_RecvFrom_any(msg_dlcx)) {
+ setverdict(fail, "Unexpected DLCX received");
+ }
}
/* Altsteps for handling of media related commands. Can be activated by a given
* test case if it expects to see media related handling (i.e. voice calls) */
altstep as_Media() runs on MSC_ConnHdlr {
- [] as_Media_ipacc();
+ [not g_pars.ignore_ipa_media] as_Media_ipacc();
[] as_Media_mgw();
}
+type port Coord_PT message
+{
+ inout charstring;
+} with { extension "internal" };
+
/* this component represents a single subscriber connection at the MSC.
* There is a 1:1 mapping between SCCP connections and RAN_ConnHdlr components.
* We inherit all component variables, ports, functions, ... from RAN_ConnHdlr */
-type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr {
+type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr, BSSAP_LE_ConnHdlr, StatsD_ConnHdlr {
/* SCCP Connecction Identifier for the underlying SCCP connection */
var integer g_sccp_conn_id;
/* procedure port back to our parent (RAN_Emulation_CT) for control */
port RAN_PROC_PT RAN;
port TELNETasp_PT BSCVTY;
+ port Coord_PT COORD;
+ port Coord_PT COORD2;
/* Proxy MGCP-over-IPA and MGCP-over-UDP */
port IPA_MGCP_PT MGCP_MSC_CLIENT;
@@ -425,7 +563,9 @@ type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr {
var TestHdlrParams g_pars;
var charstring host_bts := "127.0.0.2";
- var charstring host_mgw := "127.0.0.3";
+ var charstring host_mgw_mgcp := "127.0.0.3";
+ var charstring host_mgw_rtp_v4 := "127.0.0.5";
+ var charstring host_mgw_rtp_v6 := "::1";
var charstring host_msc := "127.0.0.4";
var boolean g_vty_initialized := false;
@@ -442,6 +582,7 @@ function f_MscConnHdlr_init_vty() runs on MSC_ConnHdlr {
/* initialize all parameters */
function f_MscConnHdlr_init(integer i, HostName bts, HostName mgw, BSSMAP_FIELD_CodecType codecType) runs on MSC_ConnHdlr {
+ g_trans_id := i * 1000; /* Avoid different MscConnHdlr submitting same trans_id over MGCP-IPA */
f_MediaState_init(g_media, i, bts, mgw, codecType);
f_MscConnHdlr_init_vty();
}
@@ -468,6 +609,20 @@ runs on RAN_Emulation_CT return template PDU_BSSAP {
return resp;
}
+/* Callback function from general BSSAP_LE_Emulation whenever a connectionless
+ * BSSAP_LE message arrives. Can return a PDU_BSSAP_LE that should be sent in return */
+private function BSSAP_LE_UnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
+ var template PDU_BSSAP_LE resp := omit;
+
+ /* answer all RESET with a RESET ACK */
+ if (match(bssap, tr_BSSMAP_LE_Reset)) {
+ resp := ts_BSSMAP_LE_ResetAck;
+ }
+
+ return resp;
+}
+
const RanOps MSC_RanOps := {
create_cb := refers(RAN_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(UnitdataCallback),
@@ -476,6 +631,16 @@ const RanOps MSC_RanOps := {
protocol := RAN_PROTOCOL_BSSAP,
transport := BSSAP_TRANSPORT_AoIP,
use_osmux := false,
+ bssap_reset_retries := 1,
+ sccp_addr_local := omit,
+ sccp_addr_peer := omit
+}
+
+const BssapLeOps SMLC_BssapLeOps := {
+ create_cb := refers(BSSAP_LE_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(BSSAP_LE_UnitdataCallback),
+ decode_dtap := false,
+ role_ms := false,
sccp_addr_local := omit,
sccp_addr_peer := omit
}
@@ -493,13 +658,83 @@ function f_create_bssmap_exp(octetstring l3_enc) runs on MSC_ConnHdlr {
}
type record TestHdlrEncrParams {
- OCT1 enc_alg,
- octetstring enc_key
+ /* A mask of multiple encryption algorithms, for Encryption Information IE. */
+ OCT1 enc_alg_permitted,
+ /* Expect this encryption algorithm in Channel Activation from the BSC.
+ * To expect no encryption, set to '01'O == A5/0. */
+ OCT1 enc_alg_expect,
+ /* In BSSMAP, the Chosen Encryption Algorithm IE that the test sends to the BSC.
+ * When set to omit, the MSC will not send a Chosen Encryption Algorithm IE. */
+ OCT1 enc_alg_chosen optional,
+ octetstring enc_key,
+ octetstring enc_kc128 optional
};
-template (value) TestHdlrEncrParams t_EncrParams(OCT1 alg, octetstring key) := {
- enc_alg := alg,
- enc_key := key
+template (value) TestHdlrEncrParams t_EncrParams(OCT1 alg_permitted,
+ octetstring key, template (omit) octetstring kc128 := omit) := {
+ enc_alg_permitted := alg_permitted,
+ enc_alg_expect := alg_permitted, /* <- for compat with tests before enc_alg_expect was added */
+ enc_alg_chosen := alg_permitted, /* <- for compat with tests before enc_alg_chosen was added */
+ enc_key := key,
+ enc_kc128 := kc128
+}
+
+template (value) TestHdlrEncrParams t_EncrParams2(OCT1 alg_permitted,
+ OCT1 alg_expect,
+ template(omit) OCT1 alg_chosen,
+ octetstring key,
+ template (omit) octetstring kc128 := omit) := {
+ enc_alg_permitted := alg_permitted,
+ enc_alg_expect := alg_expect,
+ enc_alg_chosen := alg_chosen,
+ enc_key := key,
+ enc_kc128 := kc128
+}
+
+/* Convenience for common t_EncrParams2 usage.
+ *
+ * To test a scenario where only A5/3 is permitted:
+ * f_encr_params('08'O);
+ * To test a scenario where A5/3 is chosen from A5/0,A5/1,A5/3 (1 | 2 | 8 = 11 = 0xb):
+ * f_encr_params('0b'O, '08'O);
+ * To test the same, but the Chosen Encryption Algorithm IE should reflect A5/1:
+ * f_encr_params('0b'O, '08'O, '02'O);
+ * To test the same, but the MSC sends no Chosen Encryption Algorithm IE:
+ * f_encr_params('0b'O, '08'O, omit);
+ *
+ * Set alg_chosen and alg_expect magically when == '00'O:
+ * - enc_alg_expect is set to alg_chosen if present, else to alg_permitted.
+ * - enc_alg_chosen is set to alg_permitted.
+ * When only alg_permitted is given, alg_permitted must reflect only one algorithm, or f_cipher_mode_bssmap_to_rsl()
+ * will fail.
+ * When alg_chosen is passed as omit, the messages from the MSC will not contain a Chosen Encryption Algorithm IE.
+ */
+function f_encr_params(OCT1 alg_permitted, OCT1 alg_expect := '00'O, template (omit) OCT1 alg_chosen := '00'O,
+ boolean kc128 := false)
+ return TestHdlrEncrParams
+{
+ if (not istemplatekind(alg_chosen, "omit")) {
+ if (valueof(alg_chosen) == '00'O) {
+ if (alg_expect != '00'O) {
+ alg_chosen := alg_expect;
+ } else {
+ /* In this case, alg_permitted should have only one permitted algo */
+ alg_chosen := alg_permitted;
+ }
+ }
+ if (alg_expect == '00'O) {
+ alg_expect := valueof(alg_chosen);
+ }
+ }
+ if (alg_expect == '00'O) {
+ /* In this case, alg_permitted should have only one permitted algo */
+ alg_expect := valueof(alg_permitted);
+ }
+ var template (omit) octetstring kc := omit;
+ if (kc128) {
+ kc := f_rnd_octstring(16);
+ }
+ return valueof(t_EncrParams2(alg_permitted, alg_expect, alg_chosen, f_rnd_octstring(8), kc));
}
type record TestHdlrParamsLcls {
@@ -519,10 +754,26 @@ type record TestHdlrParamsMSCPool {
PDU_ML3_MS_NW l3_info optional
}
+type record ASCITest {
+ boolean vgcs_setup_ok,
+ boolean vgcs_assign_ok,
+ boolean vgcs_assign_fail,
+ boolean vgcs_talker_req,
+ boolean vgcs_talker_fail,
+ boolean vgcs_talker_est,
+ boolean vgcs_talker_rel,
+ boolean vgcs_uplink_reject,
+ boolean vgcs_uplink_seized,
+ boolean vgcs_uplink_release,
+ boolean delay_bts,
+ boolean delay_msc
+};
+
type record TestHdlrParams {
OCT1 ra,
GsmFrameNumber fn,
- hexstring imsi,
+ hexstring imsi optional,
+ hexstring imei optional,
RslLinkId link_id,
integer media_nr, /* determins MGCP EP, port numbers */
BSSMAP_IE_SpeechCodecList ass_codec_list optional,
@@ -535,8 +786,24 @@ type record TestHdlrParams {
uint5_t exp_ms_power_level,
boolean exp_ms_power_params,
boolean aoip,
- boolean use_osmux,
- TestHdlrParamsMSCPool mscpool
+ boolean use_osmux_cn,
+ boolean use_osmux_bts,
+ charstring host_aoip_tla,
+ TestHdlrParamsMSCPool mscpool,
+ integer mgwpool_idx, /* MGCP_Emulation_CT (vc_MGCP) to use for this MSC ConnHdlr */
+ boolean media_mgw_offer_ipv6,
+ OCT3 last_used_eutran_plmn optional,
+ boolean exp_fast_return, /* RR Release expected to contain CellSelectInd ? */
+ boolean expect_channel_mode_modify,
+ uint3_t expect_tsc optional,
+ BSSMAP_IE_CellIdentifier cell_id_source,
+ boolean expect_ho_fail,
+ boolean expect_ho_fail_lchan_est,
+ boolean inter_bsc_ho_in__ho_req_in_initial_sccp_cr,
+ boolean ignore_mgw_mdcx,
+ boolean fail_on_dlcx,
+ boolean ignore_ipa_media,
+ ASCITest asci_test
};
/* Note: Do not use valueof() to get a value of this template, use
@@ -545,7 +812,8 @@ type record TestHdlrParams {
template (value) TestHdlrParams t_def_TestHdlrPars := {
ra := '23'O,
fn := 23,
- imsi := '001019876543210'H,
+ imsi := omit, /* set to random in f_gen_test_hdlr_pars() */
+ imei := omit, /* set to random in f_gen_test_hdlr_pars() */
link_id := valueof(ts_RslLinkID_DCCH(0)),
media_nr := 1,
ass_codec_list := omit,
@@ -564,36 +832,104 @@ template (value) TestHdlrParams t_def_TestHdlrPars := {
exp_ms_power_level := 7, /* calculated from osmo-bsc.cfg "ms max power" */
exp_ms_power_params := false,
aoip := true,
- use_osmux := false,
+ use_osmux_cn := false,
+ use_osmux_bts := false,
+ host_aoip_tla := "1.2.3.4",
mscpool := {
bssap_idx := 0,
rsl_idx := 0,
l3_info := omit
+ },
+ mgwpool_idx := 0,
+ media_mgw_offer_ipv6 := true,
+ last_used_eutran_plmn := omit,
+ exp_fast_return := false,
+ expect_channel_mode_modify := false,
+ expect_tsc := omit,
+ cell_id_source := valueof(ts_CellID_LAC_CI(1, 1)),
+ expect_ho_fail := false,
+ expect_ho_fail_lchan_est := false,
+ inter_bsc_ho_in__ho_req_in_initial_sccp_cr := true,
+ ignore_mgw_mdcx := false,
+ fail_on_dlcx := true,
+ ignore_ipa_media := false,
+ asci_test := {
+ vgcs_setup_ok := false,
+ vgcs_assign_ok := false,
+ vgcs_assign_fail := false,
+ vgcs_talker_req := false,
+ vgcs_talker_fail := false,
+ vgcs_talker_est := false,
+ vgcs_talker_rel := false,
+ vgcs_uplink_reject := false,
+ vgcs_uplink_seized := false,
+ vgcs_uplink_release := false,
+ delay_bts := false,
+ delay_msc := false
}
}
-function f_create_chan_and_exp() runs on MSC_ConnHdlr {
- var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
- var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
- var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_info);
+function f_create_chan_and_exp(template (present) PDU_BSSAP exp_l3_compl := ?)
+runs on MSC_ConnHdlr {
+ var MobileIdentityLV mi;
+ var PDU_ML3_MS_NW l3_info;
+ var octetstring l3_enc;
+ var template uint3_t tsc := ?;
+ timer T;
+
+ if (ispresent(g_pars.imsi)) {
+ mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ } else if (ispresent(g_pars.imei)) {
+ mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Either imsi or imei must be set!");
+ }
+ l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
+ l3_enc := enc_PDU_ML3_MS_NW(l3_info);
+
+ if (not istemplatekind(g_pars.expect_tsc, "omit")) {
+ tsc := g_pars.expect_tsc;
+ }
+
+ if (istemplatekind(exp_l3_compl, "?")) {
+ if (g_pars.aoip == false) {
+ exp_l3_compl := tr_BSSMAP_ComplL3(l3_enc, codec_list := omit);
+ } else {
+ exp_l3_compl := tr_BSSMAP_ComplL3(l3_enc, codec_list := ?);
+ }
+ }
- /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
- RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn);
f_create_bssmap_exp(l3_enc);
+ /* call helper function for CHAN_RQD -> IMM ASS ->EST_IND */
+ RSL_Emulation.f_chan_est(g_pars.ra, l3_enc, g_pars.link_id, g_pars.fn, tsc);
+ /* wait for a COMPL_L3 from the BSC to ensure that the SCCP connection is up */
+ T.start(2.0);
+ alt {
+ [] BSSAP.receive(exp_l3_compl);
+ [] BSSAP.receive(tr_BSSMAP_ComplL3) {
+ setverdict(fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
}
function f_rsl_send_l3(template PDU_ML3_MS_NW l3, template (omit) RslLinkId link_id := omit,
- template (omit) RslChannelNr chan_nr := omit) runs on MSC_ConnHdlr {
+ template (omit) RslChannelNr chan_nr := omit, RSL_DCHAN_PT rsl_pt := RSL) runs on MSC_ConnHdlr {
if (not isvalue(link_id)) {
link_id := ts_RslLinkID_DCCH(0);
}
if (not isvalue(chan_nr)) {
chan_nr := g_chan_nr;
}
- RSL.send(ts_RSL_DATA_IND(valueof(chan_nr), valueof(link_id), enc_PDU_ML3_MS_NW(valueof(l3))));
+ rsl_pt.send(ts_RSL_DATA_IND(valueof(chan_nr), valueof(link_id), enc_PDU_ML3_MS_NW(valueof(l3))));
}
-function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig) runs on MSC_ConnHdlr {
+function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig, RSL_DCHAN_PT rsl_pt := RSL) runs on MSC_ConnHdlr {
var RslChannelNr chan_nr := orig.ies[0].body.chan_nr;
var RslLinkId link_id;
if (orig.msg_type == RSL_MT_ENCR_CMD) {
@@ -601,81 +937,138 @@ function f_rsl_reply(template PDU_ML3_MS_NW l3, RSL_Message orig) runs on MSC_Co
} else {
link_id := orig.ies[1].body.link_id;
}
- f_rsl_send_l3(l3, link_id, chan_nr);
+ f_rsl_send_l3(l3, link_id, chan_nr, rsl_pt := rsl_pt);
}
-/* Convert the chipher representation on BSSMAP to the representation used on RSL */
-function f_chipher_mode_bssmap_to_rsl(OCT1 alg_bssmap) return RSL_AlgId
+/* Convert the cipher representation on BSSMAP to the representation used on RSL */
+function f_cipher_mode_bssmap_to_rsl(OCT1 alg_bssmap) return RSL_AlgId
{
- /* A5 0 */
- if (alg_bssmap == '01'O) {
+ select (alg_bssmap) {
+ case ('01'O) { return RSL_ALG_ID_A5_0; }
+ case ('02'O) { return RSL_ALG_ID_A5_1; }
+ case ('04'O) { return RSL_ALG_ID_A5_2; }
+ case ('08'O) { return RSL_ALG_ID_A5_3; }
+ case ('10'O) { return RSL_ALG_ID_A5_4; }
+ case ('20'O) { return RSL_ALG_ID_A5_5; }
+ case ('40'O) { return RSL_ALG_ID_A5_6; }
+ case ('80'O) { return RSL_ALG_ID_A5_7; }
+ case else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Encryption Algorithm: " &
+ oct2str(alg_bssmap));
return RSL_ALG_ID_A5_0;
+ }
}
- /* A5 1 */
- else if (alg_bssmap == '02'O) {
- return RSL_ALG_ID_A5_1;
- }
- /* A5 2 */
- else if (alg_bssmap == '04'O) {
- return RSL_ALG_ID_A5_2;
- }
- /* A5 3 */
- else if (alg_bssmap == '08'O) {
- return RSL_ALG_ID_A5_3;
+}
+
+/* Convert the cipher representation on BSSMAP to the one used on RR (3GPP TS 44.018) */
+function f_cipher_mode_bssmap_to_rr(OCT1 alg_bssmap) return BIT3
+{
+ select (alg_bssmap) {
+ case ('01'O) /* A5/0 */ { return '000'B; } /* SC=0 */
+ case ('02'O) /* A5/1 */ { return '000'B; } /* SC=1 */
+ case ('04'O) /* A5/2 */ { return '001'B; } /* SC=1 */
+ case ('08'O) /* A5/3 */ { return '010'B; } /* SC=1 */
+ case ('10'O) /* A5/4 */ { return '011'B; } /* SC=1 */
+ case ('20'O) /* A5/5 */ { return '100'B; } /* SC=1 */
+ case ('40'O) /* A5/6 */ { return '101'B; } /* SC=1 */
+ case ('80'O) /* A5/7 */ { return '110'B; } /* SC=1 */
+ case else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Encryption Algorithm: " &
+ oct2str(alg_bssmap));
+ return '000'B;
+ }
}
- /* A5 4 */
- else if (alg_bssmap == '10'O) {
- return RSL_ALG_ID_A5_4;
+}
+
+function f_verify_encr_info(RSL_Message rsl) runs on MSC_ConnHdlr {
+ var RSL_IE_Body encr_info;
+ var RSL_AlgId alg_rsl;
+ var template octetstring expect_kc;
+
+ /* If no encryption is enabled, then make sure there is no RSL_IE_ENCR_INFO */
+ if (not ispresent(g_pars.encr)) {
+ if (f_rsl_find_ie(rsl, RSL_IE_ENCR_INFO, encr_info)) {
+ setverdict(fail, "Found Encryption IE, but expected no encryption in ", rsl.msg_type);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ return;
+ }
+ setverdict(pass);
+ return;
}
- /* A5 5 */
- else if (alg_bssmap == '20'O) {
- return RSL_ALG_ID_A5_5;
+
+ /* RSL uses a different representation of the encryption algorithm,
+ * so we need to convert first */
+ alg_rsl := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect);
+
+ if (alg_rsl == RSL_ALG_ID_A5_4 and ispresent(g_pars.encr.enc_kc128)) {
+ expect_kc := g_pars.encr.enc_kc128;
+ } else if (alg_rsl == RSL_ALG_ID_A5_0) {
+ /* When A5/0 is chosen, no encryption is active, so technically, no key is needed. However, 3GPP TS
+ * 48.058 9.3.7 Encryption Information stays quite silent about presence or absence of a key for A5/0.
+ * The only thing specified is how to indicate the length of the key; the possibility that the key may
+ * be zero length is not explicitly mentioned. So it seems that we should always send the key along,
+ * even for A5/0. Still, let's also allow a zero length key for A5/0. */
+ expect_kc := (g_pars.encr.enc_key, ''O);
+ } else {
+ expect_kc := g_pars.encr.enc_key;
}
- /* A5 6 */
- else if (alg_bssmap == '40'O) {
- return RSL_ALG_ID_A5_6;
+ log("for encryption algo ", alg_rsl, " expect kc = ", expect_kc);
+
+ if (not f_rsl_find_ie(rsl, RSL_IE_ENCR_INFO, encr_info)) {
+ if (alg_rsl == RSL_ALG_ID_A5_0) {
+ /* For A5/0, encryption is not active. It is fine to omit the Encryption Information in this
+ * case. Note that the first channel may see an RSL Encryption Command with A5/0 indicated, and
+ * a subsequent handover may activate a new channel without any Encryption Information. */
+ setverdict(pass);
+ return;
+ }
+ setverdict(fail, "Missing Encryption Information IE in ", rsl.msg_type);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ return;
}
- /* A5 7 */
- else if (alg_bssmap == '80'O) {
- return RSL_ALG_ID_A5_7;
- } else {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Encryption Algorithm");
- return RSL_ALG_ID_A5_0;
+
+ if (not match(encr_info, tr_EncrInfo(alg_rsl, expect_kc))) {
+ setverdict(fail, "Unexpected Kc in Encryption Information IE in ", rsl.msg_type);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ return;
}
+ setverdict(pass);
}
-function f_cipher_mode(OCT1 alg, OCT8 key, template OCT16 kc128 := omit, boolean exp_fail := false)
+function f_cipher_mode(TestHdlrEncrParams enc, boolean exp_fail := false,
+ RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
runs on MSC_ConnHdlr {
var PDU_BSSAP bssap;
var RSL_Message rsl;
- var RSL_AlgId alg_rsl;
- if (isvalue(kc128)) {
- BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(alg, key, valueof(kc128)));
+ if (isvalue(enc.enc_kc128)) {
+ BSSAP.send(ts_BSSMAP_CipherModeCmdKc128(enc.enc_alg_permitted, enc.enc_key, valueof(enc.enc_kc128)));
} else {
- BSSAP.send(ts_BSSMAP_CipherModeCmd(alg, key));
+ BSSAP.send(ts_BSSMAP_CipherModeCmd(enc.enc_alg_permitted, enc.enc_key));
}
- /* RSL uses a different representation of the encryption algorithm,
- * so we need to convert first */
- alg_rsl := f_chipher_mode_bssmap_to_rsl(alg);
-
alt {
/* RSL/UE Side */
- [] RSL.receive(tr_RSL_ENCR_CMD(g_chan_nr, ?, alg_rsl, key)) -> value rsl {
+ [] rsl_pt.receive(tr_RSL_ENCR_CMD(g_chan_nr)) -> value rsl {
var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[3].body.l3_info.payload);
log("Rx L3 from net: ", l3);
+
+ f_verify_encr_info(rsl);
+
if (ischosen(l3.msgs.rrm.cipheringModeCommand)) {
- f_rsl_reply(ts_RRM_CiphModeCompl, rsl);
+ f_rsl_reply(ts_RRM_CiphModeCompl, rsl, rsl_pt := rsl_pt);
}
repeat;
}
[] BSSAP.receive(tr_BSSMAP_CipherModeCompl) -> value bssap {
- // bssap.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algoritmhIdentifier
if (exp_fail == true) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected Cipher Mode Complete");
} else {
setverdict(pass);
+ var RSL_AlgId alg_rsl := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect);
+ if (oct2int(bssap.pdu.bssmap.cipherModeComplete.chosenEncryptionAlgorithm.algorithmIdentifier) != enum2int(alg_rsl)) {
+ setverdict(fail, "Unexpected Encryption Algorithm ID in BSSMAP Cipher Mode Complete");
+ }
}
}
[] BSSAP.receive(tr_BSSMAP_CipherModeRej) -> value bssap {
@@ -693,20 +1086,28 @@ function f_ChDesc2RslChanNr(ChannelDescription2_V ch_desc, out RslChannelNr chan
var BIT5 inp := ch_desc.channelTypeandTDMAOffset;
var uint3_t tn := bit2int(ch_desc.timeslotNumber);
- if (match(inp, '00001'B)) { /* TCH/F */
+ select (inp) {
+ case ('00001'B) { /* TCH/F */
chan_nr := valueof(t_RslChanNr_Bm(tn));
- }
- else if (match(inp, '0001?'B)) { /* TCH/H */
+ }
+ case ('11101'B) { /* VAMOS TCH/F */
+ chan_nr := valueof(t_RslChanNr_Osmo_VAMOS_Bm(tn));
+ }
+ case ('0001?'B) { /* TCH/H */
chan_nr := valueof(t_RslChanNr_Lm(tn, bit2int(substr(inp, 4, 1))));
- }
- else if (match(inp, '001??'B)) { /* SDCCH/4 */
+ }
+ case ('1111?'B) { /* VAMOS TCH/H */
+ chan_nr := valueof(t_RslChanNr_Osmo_VAMOS_Lm(tn, bit2int(substr(inp, 4, 1))));
+ }
+ case ('001??'B) { /* SDCCH/4 */
chan_nr := valueof(t_RslChanNr_SDCCH4(tn, bit2int(substr(inp, 3, 2))));
- }
- else if (match(inp, '01???'B)) { /* SDCCH/8 */
+ }
+ case ('01???'B) { /* SDCCH/8 */
chan_nr := valueof(t_RslChanNr_SDCCH8(tn, bit2int(substr(inp, 2, 3))));
- }
- else {
+ }
+ case else {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknown ChDesc!");
+ }
}
if (ch_desc.octet3 and4b '10'O == '10'O) {
@@ -719,7 +1120,7 @@ function f_ChDesc2RslChanNr(ChannelDescription2_V ch_desc, out RslChannelNr chan
type record AssignmentState {
/* global */
- boolean voice_call,
+ boolean rtp_stream,
boolean is_assignment,
/* Assignment related bits */
boolean rr_ass_cmpl_seen,
@@ -728,19 +1129,23 @@ type record AssignmentState {
boolean assignment_done,
RslChannelNr old_chan_nr,
/* Modify related bits */
+ PDU_ML3_NW_MS rr_channel_mode_modify_msg optional,
boolean rr_modify_seen,
+ RSL_Message rsl_mode_modify_msg optional,
boolean modify_done
}
template (value) AssignmentState ts_AssignmentStateInit := {
- voice_call := false,
+ rtp_stream := false,
is_assignment := false,
rr_ass_cmpl_seen := false,
old_lchan_deact_sacch_seen := false,
old_lchan_rll_rel_req_seen := false,
assignment_done := false,
old_chan_nr := -,
+ rr_channel_mode_modify_msg := omit,
rr_modify_seen := false,
+ rsl_mode_modify_msg := omit,
modify_done := false
}
@@ -758,13 +1163,20 @@ private function f_check_chan_act(AssignmentState st, RSL_Message chan_act) runs
var RSL_IE_Body ms_power_param;
var RSL_IE_Body ms_power;
- if (ispresent(g_pars.encr) and g_pars.encr.enc_alg != '01'O) {
+ if (ispresent(g_pars.encr) and g_pars.encr.enc_alg_permitted != '01'O) {
if (not f_rsl_find_ie(chan_act, RSL_IE_ENCR_INFO, encr_info)) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Missing Encryption IE in CHAN ACT");
} else {
- var RSL_AlgId alg := f_chipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg);
- if (not match(encr_info, tr_EncrInfo(alg, g_pars.encr.enc_key))) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Wrong Encryption IE in CHAN ACT");
+ var RSL_AlgId alg := f_cipher_mode_bssmap_to_rsl(g_pars.encr.enc_alg_expect);
+ var octetstring expect_key;
+ if (alg == RSL_ALG_ID_A5_4) {
+ expect_key := g_pars.encr.enc_kc128;
+ } else {
+ expect_key := g_pars.encr.enc_key;
+ }
+ if (not match(encr_info, tr_EncrInfo(alg, expect_key))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected Kc in Encryption IE in RSL ENCR CMD");
}
}
} else {
@@ -791,33 +1203,51 @@ private function f_check_chan_act(AssignmentState st, RSL_Message chan_act) runs
}
-altstep as_assignment(inout AssignmentState st) runs on MSC_ConnHdlr {
+function rr_chan_desc_tsc(ChannelDescription2_V cd2)
+ return uint3_t
+{
+ var uint3_t tsc := oct2int(cd2.octet3);
+ tsc := tsc / 32; /* shl 5 */
+ return tsc;
+}
+
+altstep as_assignment(inout AssignmentState st, RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC) runs on MSC_ConnHdlr {
var RSL_Message rsl;
- [not st.rr_ass_cmpl_seen] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ [not st.rr_ass_cmpl_seen] rsl_pt.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
log("Rx L3 from net: ", l3);
if (ischosen(l3.msgs.rrm.assignmentCommand)) {
var RslChannelNr new_chan_nr;
var GsmArfcn arfcn;
+
+ if (not istemplatekind(g_pars.expect_tsc, "omit")) {
+ var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.assignmentCommand.descrOf1stChAfterTime);
+ if (not match(got_tsc, g_pars.expect_tsc)) {
+ setverdict(fail, "RR Assignment: unexpected TSC in Channel Description: expected ",
+ g_pars.expect_tsc, " got ", got_tsc);
+ mtc.stop;
+ }
+ }
+
f_ChDesc2RslChanNr(l3.msgs.rrm.assignmentCommand.descrOf1stChAfterTime,
new_chan_nr, arfcn);
/* FIXME: Determine TRX NR by ARFCN, instead of hard-coded TRX0! */
/* register our component for this channel number at the RSL Emulation */
- f_rslem_register(0, new_chan_nr);
+ f_rslem_register(0, new_chan_nr, PT := rsl_proc_pt);
/* dispatch queued messages for this channel (if any) */
- f_rslem_dchan_queue_dispatch();
+ f_rslem_dchan_queue_dispatch(PT := rsl_proc_pt);
var PDU_ML3_MS_NW l3_tx := valueof(ts_RRM_AssignmentComplete('00'O));
/* send assignment complete over the new channel */
- RSL.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
+ rsl_pt.send(ts_RSL_EST_IND(new_chan_nr, valueof(ts_RslLinkID_DCCH(0)),
enc_PDU_ML3_MS_NW(l3_tx)));
/* by default, send via the new channel from now */
st.old_chan_nr := g_chan_nr;
g_chan_nr := new_chan_nr;
st.rr_ass_cmpl_seen := true;
/* obtain channel activation from RSL_Emulation for new channel */
- var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
+ var RSL_Message chan_act := f_rslem_get_last_act(rsl_proc_pt, 0, g_chan_nr);
/* check it (e.g. for correct ciphering parameters) */
f_check_chan_act(st, chan_act);
repeat;
@@ -825,20 +1255,20 @@ altstep as_assignment(inout AssignmentState st) runs on MSC_ConnHdlr {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected L3 received", l3));
}
}
- [st.rr_ass_cmpl_seen] RSL.receive(tr_RSL_DEACT_SACCH(st.old_chan_nr)) {
+ [st.rr_ass_cmpl_seen] rsl_pt.receive(tr_RSL_DEACT_SACCH(st.old_chan_nr)) {
st.old_lchan_deact_sacch_seen := true;
repeat;
}
- [st.rr_ass_cmpl_seen] RSL.receive(tr_RSL_REL_REQ(st.old_chan_nr, tr_RslLinkID_DCCH(0))) {
+ [st.rr_ass_cmpl_seen] rsl_pt.receive(tr_RSL_REL_REQ(st.old_chan_nr, tr_RslLinkID_DCCH(0))) {
st.old_lchan_rll_rel_req_seen := true;
- RSL.send(ts_RSL_REL_CONF(st.old_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
+ rsl_pt.send(ts_RSL_REL_CONF(st.old_chan_nr, valueof(ts_RslLinkID_DCCH(0))));
repeat;
}
- [st.rr_ass_cmpl_seen] RSL.receive(tr_RSL_RF_CHAN_REL(st.old_chan_nr)) {
- RSL.send(ts_RSL_RF_CHAN_REL_ACK(st.old_chan_nr));
+ [st.rr_ass_cmpl_seen] rsl_pt.receive(tr_RSL_RF_CHAN_REL(st.old_chan_nr)) {
+ rsl_pt.send(ts_RSL_RF_CHAN_REL_ACK(st.old_chan_nr));
/* unregister for old channel number in RSL emulation */
/* FIXME: Determine TRX NR by ARFCN, instead of hard-coded TRX0! */
- f_rslem_unregister(0, st.old_chan_nr);
+ f_rslem_unregister(0, st.old_chan_nr, PT := rsl_proc_pt);
st.assignment_done := true;
repeat;
}
@@ -848,17 +1278,19 @@ altstep as_modify(inout AssignmentState st) runs on MSC_ConnHdlr {
/* no assignment, just mode modify */
var RSL_Message rsl;
- [st.voice_call and not st.rr_modify_seen] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+ [st.rtp_stream and not st.rr_modify_seen] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
var PDU_ML3_NW_MS l3 := dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
log("Rx L3 from net: ", l3);
if (ischosen(l3.msgs.rrm.channelModeModify)) {
+ st.rr_channel_mode_modify_msg := l3;
f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
l3.msgs.rrm.channelModeModify.channelMode), rsl);
st.rr_modify_seen := true;
}
repeat;
}
- [st.voice_call and st.rr_modify_seen] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_MODE_MODIFY_REQ)) -> value rsl {
+ [st.rtp_stream and st.rr_modify_seen] RSL.receive(tr_RSL_MsgTypeD(RSL_MT_MODE_MODIFY_REQ)) -> value rsl {
+ st.rsl_mode_modify_msg := rsl;
RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
st.modify_done := true;
repeat;
@@ -900,21 +1332,30 @@ return boolean {
/* Determine if the channel mode specified within rsl_chan_nr requires a
* MODE MODIFY in to match the channel mode specified by given BSSMAP
* ChannelType */
-function f_channel_needs_modify(BSSMAP_IE_ChannelType bssmap, RslChannelNr rsl_chan_nr)
+function f_channel_needs_modify(TELNETasp_PT vty, BSSMAP_IE_ChannelType bssmap, RslChannelNr rsl_chan_nr)
return boolean {
- /* FIXME: This tests the rsl_chan_nr to determine if we are on a
- * signalling channel or not. Unfortunately this may lead to false
- * results if we are on a TCH. The problem is that a TCH may be also
- * used in signalling mode, but this function assumes that only SDCCH4
- * and SDCCH8 are used as signalling channels at all. */
-
var boolean current_signalling := false;
var boolean desired_signalling := false;
select (rsl_chan_nr) {
case (t_RslChanNr_SDCCH4(?, ?)) { current_signalling := true; }
case (t_RslChanNr_SDCCH8(?, ?)) { current_signalling := true; }
+ case (t_RslChanNr_Bm(?)) {
+ /* TCH/F, always subslot 0 */
+ var charstring res := f_vty_transceive_ret(vty, "show lchan 0 0 " & int2str(rsl_chan_nr.tn) & " 0");
+ if (f_strstr(res, "Channel Mode / Codec: SIGNALLING", 0) >= 0) {
+ current_signalling := true;
+ }
+ }
+ case (t_RslChanNr_Lm(?, ?)) {
+ /* TCH/H */
+ var charstring res := f_vty_transceive_ret(vty, "show lchan 0 0 " & int2str(rsl_chan_nr.tn)
+ & " " & int2str(rsl_chan_nr.u.lm.sub_chan));
+ if (f_strstr(res, "Channel Mode / Codec: SIGNALLING", 0) >= 0) {
+ current_signalling := true;
+ }
+ }
}
if (bssmap.speechOrDataIndicator == '0011'B) {
@@ -1005,7 +1446,7 @@ runs on MSC_ConnHdlr {
var BSSMAP_FIELD_CodecType codecType;
timer T := 10.0;
- if (isvalue(ass_tpl.pdu.bssmap.assignmentRequest.codecList)) {
+ if (not istemplatekind(ass_tpl, "omit") and isvalue(ass_tpl.pdu.bssmap.assignmentRequest.codecList)) {
codecType := valueof(ass_tpl.pdu.bssmap.assignmentRequest.codecList.codecElements[0].codecType);
} else {
/* Make sure a meaningful default is assigned in case the
@@ -1013,35 +1454,16 @@ runs on MSC_ConnHdlr {
codecType := FR_AMR;
}
- f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw, codecType);
+ f_MscConnHdlr_init(g_pars.media_nr, host_bts, host_mgw_mgcp, codecType);
/* patch in the LCLS related items, as needed */
f_ass_patch_lcls(ass_tpl, exp_ass_cpl);
f_create_chan_and_exp();
- /* we should now have a COMPL_L3 at the MSC */
-
- var template PDU_BSSAP exp_l3_compl;
- exp_l3_compl := tr_BSSMAP_ComplL3()
- if (g_pars.aoip == false) {
- exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := omit;
- } else {
- exp_l3_compl.pdu.bssmap.completeLayer3Information.codecList := ?;
- }
- T.start;
- alt {
- [] BSSAP.receive(exp_l3_compl);
- [] BSSAP.receive(tr_BSSMAP_ComplL3) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received non-matching COMPLETE LAYER 3 INFORMATION");
- }
- [] T.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for COMPLETE LAYER 3 INFORMATION");
- }
- }
/* start ciphering, if requested */
if (ispresent(g_pars.encr)) {
- f_cipher_mode(g_pars.encr.enc_alg, g_pars.encr.enc_key);
+ f_cipher_mode(g_pars.encr);
}
/* bail out early if no assignment requested */
@@ -1061,9 +1483,9 @@ runs on MSC_ConnHdlr {
transid := omit
};
var AssignmentState st := valueof(ts_AssignmentStateInit);
- /* if the channel type is SIGNAL, we're not handling a voice call */
+ /* if the channel type is SIGNAL, we're not handling an rtp stream */
if (ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechOrDataIndicator != '0011'B) {
- st.voice_call := true;
+ st.rtp_stream := true;
exp_modify := true;
}
@@ -1079,7 +1501,8 @@ runs on MSC_ConnHdlr {
* channel, we must now check if the mode of the current
* channel is compatible. If not we expect the BSC to modify
* the mode */
- exp_modify := f_channel_needs_modify(ass_cmd.pdu.bssmap.assignmentRequest.channelType, g_chan_nr);
+ st.is_assignment := false;
+ exp_modify := f_channel_needs_modify(BSCVTY, ass_cmd.pdu.bssmap.assignmentRequest.channelType, g_chan_nr);
}
/* Some test situations will involve MGCP transactions on a media
@@ -1092,8 +1515,8 @@ runs on MSC_ConnHdlr {
g_media.mgcp_conn[0].mdcx_seen_exp := 0;
g_media.mgcp_conn[1].crcx_seen_exp := 0;
g_media.mgcp_conn[1].mdcx_seen_exp := 0;
- } else if (st.voice_call) {
- /* For voice calls we expect the following MGCP activity */
+ } else if (st.rtp_stream) {
+ /* For RTP streams we expect the following MGCP activity */
g_media.mgcp_conn[0].crcx_seen_exp := 1;
g_media.mgcp_conn[0].mdcx_seen_exp := 1;
g_media.mgcp_conn[1].crcx_seen_exp := 1;
@@ -1120,8 +1543,8 @@ runs on MSC_ConnHdlr {
/* modify related bits */
[not st.is_assignment and exp_modify] as_modify(st);
- /* voice call related bits (IPA CRCX/MDCX + MGCP) */
- [st.voice_call] as_Media();
+ /* RTP stream related bits (IPA CRCX/MDCX + MGCP) */
+ [st.rtp_stream] as_Media();
/* if we receive exactly what we expected, always return + pass */
[st.is_assignment and st.assignment_done or (not st.is_assignment and (st.modify_done or not exp_modify))] BSSAP.receive(exp_ass_cpl) -> value bssap {
@@ -1153,6 +1576,65 @@ runs on MSC_ConnHdlr {
mtc.stop;
}
+ if (exp_modify) {
+ /* Verify that the RR Channel Mode Modify and RSL MODE MODIFY message asked for the expected channel
+ * mode. */
+ /* TODO: more precisely expect the different types of speech? */
+ var OCT1 rr_channel_mode := st.rr_channel_mode_modify_msg.msgs.rrm.channelModeModify.channelMode.mode;
+
+ if (st.rtp_stream and rr_channel_mode == '00'O) {
+ setverdict(fail, "f_establish_fully(): Expected RR Channel Mode Modify",
+ " to a speech mode, but got channelMode == ", rr_channel_mode);
+ mtc.stop;
+ } else if (not st.rtp_stream and rr_channel_mode != '00'O) {
+ setverdict(fail, "f_establish_fully(): Expected RR Channel Mode Modify",
+ " to signalling mode, but got channelMode == ", rr_channel_mode);
+ mtc.stop;
+ }
+
+ var RSL_IE_Body chan_mode_ie;
+ if (not f_rsl_find_ie(st.rsl_mode_modify_msg, RSL_IE_CHAN_MODE, chan_mode_ie)) {
+ setverdict(fail, "RSL MODE MODIFY message lacks a Channel Mode IE");
+ mtc.stop;
+ }
+ var RSL_SpeechDataInd rsl_spd_ind := chan_mode_ie.chan_mode.spd_ind;
+ if (st.rtp_stream and rsl_spd_ind != RSL_SPDI_SPEECH) {
+ setverdict(fail, "f_establish_fully(): Expected RSL MODE MODIFY",
+ " to a speech mode, but got spd_ind == ", rsl_spd_ind);
+ mtc.stop;
+ } else if (not st.rtp_stream and rsl_spd_ind != RSL_SPDI_SIGN) {
+ setverdict(fail, "f_establish_fully(): Expected RSL MODE MODIFY",
+ " to signalling mode, but got spd_ind == ", rsl_spd_ind);
+ mtc.stop;
+ }
+
+ if (not istemplatekind(g_pars.expect_tsc, "omit")) {
+ var uint3_t got_tsc := rr_chan_desc_tsc(st.rr_channel_mode_modify_msg.msgs.rrm.channelModeModify.channelDescription);
+ if (not match(got_tsc, g_pars.expect_tsc)) {
+ setverdict(fail, "RR Channel Mode Modify: unexpected TSC in Channel Description: expected ",
+ g_pars.expect_tsc, " got ", got_tsc);
+ mtc.stop;
+ }
+ }
+
+ } else {
+ /* not exp_modify, so this did a Channel Activate */
+
+ /* Check the TSC */
+ if (not istemplatekind(g_pars.expect_tsc, "omit")) {
+ var RSL_Message chan_act := f_rslem_get_last_act(RSL_PROC, 0, g_chan_nr);
+ var RSL_IE_Body ie;
+ if (f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, ie)) {
+ var uint3_t got_tsc := ie.chan_ident.ch_desc.v.tsc;
+ if (not match(got_tsc, g_pars.expect_tsc)) {
+ setverdict(fail, "RSL CHANnel ACTIVation: unexpected TSC in Channel Description: expected ",
+ g_pars.expect_tsc, " got ", got_tsc);
+ mtc.stop;
+ }
+ }
+ }
+ }
+
/* When the BSC detects that LCLS is possible it will cross the
* connetions that point to the PBX side of the MGW. In our case this
* is mgcp_conn[1]. The BSC performs this operation already before the
@@ -1165,24 +1647,24 @@ runs on MSC_ConnHdlr {
}
}
- if (not exp_fail and st.voice_call and not g_pars.aoip) {
+ if (not exp_fail and st.rtp_stream and not g_pars.aoip) {
/* With SCCPLite, connect to BSC-located MGW using a CRCX + SDP.
It is sent in MGCP over IPA in the BSC<->MSC (BSC-NAT)
connection. BSC will forward it to its MGW. */
var template MgcpCommand cmd;
var template MgcpResponse resp;
var integer cic := f_bssmap_ie_cic_2_int(ass_cmd.pdu.bssmap.assignmentRequest.circuitIdentityCode);
- var MgcpEndpoint ep := int2str(cic) & "@mgw"; /* 1: matches value configured in BSC_Tests.ttcn pass in AssignReq */
+ var MgcpEndpoint ep := int2str(cic) & "@mgw"; /* matches value configured in BSC_Tests.ttcn pass in AssignReq */
var MgcpCallId call_id := '51234'H;
var SDP_attribute_list attributes := { valueof(ts_SDP_ptime(20)) };
- if (g_pars.use_osmux) {
+ if (g_pars.use_osmux_cn) {
cmd := ts_CRCX_osmux(get_next_trans_id(), ep, "sendrecv", call_id, cic);
resp := tr_CRCX_ACK_osmux;
} else {
cmd := ts_CRCX(get_next_trans_id(), ep, "sendrecv", call_id);
resp := tr_CRCX_ACK;
}
- cmd.sdp := ts_SDP(host_msc, host_mgw, "23", "42",
+ cmd.sdp := ts_SDP(host_msc, host_mgw_rtp_v4, "23", "42",
14000, { int2str(g_media.mgcp_conn[1].rtp_pt) },
{ valueof(ts_SDP_ptime(20)) });
mgcp_transceive_mgw(cmd, resp);
@@ -1200,6 +1682,13 @@ runs on MSC_ConnHdlr {
" released properly: saw an RLL Release on the old lchan, but expecting none.");
}
}
+
+ var charstring lchan_info := f_vty_transceive_ret(BSCVTY, "show lchan 0 0 " & int2str(g_chan_nr.tn) & " 0");
+ if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+ log("after f_establish_fully(), 'show lchan' replied: ", lchan_info);
+ setverdict(fail, "lchan is not in state ESTABLISHED");
+ mtc.stop;
+ }
}
type record HandoverState {
@@ -1207,7 +1696,8 @@ type record HandoverState {
boolean rr_ho_cmpl_seen,
integer mdcx_seen_before_ho,
boolean handover_done,
- RslChannelNr old_chan_nr
+ RslChannelNr old_chan_nr,
+ uint3_t expect_target_tsc optional
};
altstep as_handover(inout HandoverState st) runs on MSC_ConnHdlr {
@@ -1222,6 +1712,19 @@ altstep as_handover(inout HandoverState st) runs on MSC_ConnHdlr {
new_chan_nr, arfcn);
/* FIXME: Determine TRX NR by ARFCN, instead of hard-coded TRX0! */
+ /* Verify correct TSC in handoverCommand */
+ if (ispresent(st.expect_target_tsc)) {
+ var uint3_t got_tsc := rr_chan_desc_tsc(l3.msgs.rrm.handoverCommand.channelDescription2);
+ if (not match(got_tsc, st.expect_target_tsc)) {
+ setverdict(fail, "RR Handover Command: unexpected TSC in Channel Description: expected ",
+ st.expect_target_tsc, " got ", got_tsc);
+ mtc.stop;
+ } else {
+ log("handoverCommand: verified TSC = ", got_tsc, " (matches ",
+ st.expect_target_tsc, ")");
+ }
+ }
+
/* register our component for this channel number at the RSL Emulation */
f_rslem_register(0, new_chan_nr, RSL1_PROC);
@@ -1251,7 +1754,7 @@ altstep as_handover(inout HandoverState st) runs on MSC_ConnHdlr {
}
}
[st.rr_ho_cmpl_seen] as_Media_ipacc();
- [st.rr_ho_cmpl_seen] as_Media_mgw(true);
+ [st.rr_ho_cmpl_seen] as_Media_mgw();
[st.rr_ho_cmpl_seen] RSL.receive(tr_RSL_DEACT_SACCH(st.old_chan_nr)) {
repeat;
}
@@ -1270,9 +1773,11 @@ altstep as_handover(inout HandoverState st) runs on MSC_ConnHdlr {
* time. When we receive the RSL_RF_CHAN_REL command the media negotiation on
* IPACC or MGCP level may be still in progress. In order to make sure that
* we do only stop when we have seen an MDCX on MGCP level and another a CRCX
- * as well as an MDCX on IPACC level. */
- if (g_media.mgcp_conn[0].mdcx_seen <= st.mdcx_seen_before_ho or
- g_media.bts1.ipa_mdcx_seen == false or g_media.bts1.ipa_crcx_seen == false) {
+ * as well as an MDCX on IPACC level.
+ * If ipa_crcx_seen is false, this is not a voice channel and we need not check MGCP at all.. */
+ if (g_media.bts.ipa_crcx_seen
+ and (g_media.mgcp_conn[0].mdcx_seen <= st.mdcx_seen_before_ho or
+ g_media.bts1.ipa_mdcx_seen == false or g_media.bts1.ipa_crcx_seen == false)) {
repeat;
} else {
st.handover_done := true;
diff --git a/bsc/README.md b/bsc/README.md
index 015687cc..47714e9e 100644
--- a/bsc/README.md
+++ b/bsc/README.md
@@ -8,6 +8,7 @@
* MGW side: MGCP (emulates MGW side)
* VTY
* CTRL
+ * StatsD
{% dot bsc_tests.svg
digraph G {
@@ -22,6 +23,7 @@ digraph G {
ATS -> BSC [label="A-bis RSL"];
ATS -> BSC [label="CTRL"];
ATS -> BSC [label="VTY"];
+ BSC -> ATS [label="StatsD"];
ATS -> STP [label="A BSSAP\nSCCP/M3UA"];
BSC -> STP [label="A BSSAP\nSCCP/M3UA"];
}
@@ -39,6 +41,7 @@ digraph G {
ATS -> BSC [label="A-bis RSL"];
ATS -> BSC [label="CTRL"];
ATS -> BSC [label="VTY"];
+ BSC -> ATS [label="StatsD"];
ATS -> BSC [label="A BSSAP\nSCCP/IPA"];
}
%}
diff --git a/bsc/README.txt b/bsc/README.txt
index aa785ada..e992dba3 100644
--- a/bsc/README.txt
+++ b/bsc/README.txt
@@ -62,7 +62,7 @@ x supported/unsupported/invalid ciphers
x no response to CHAN ACT
x CONN FAIL IND from BTS
-** verify counter increment of BTS_CTR_CHAN_RF_FAIL
+xx verify counter increment of BTS_CTR_CHAN_RF_FAIL
* no (or late?) response to RF CHAN REL
* no (or late?) response to RLL RELEASE REQ
x RLL messages on not-activated channels
diff --git a/bsc/expected-results.xml b/bsc/expected-results.xml
index 1d4f5d75..2d69eee9 100644
--- a/bsc/expected-results.xml
+++ b/bsc/expected-results.xml
@@ -1,11 +1,35 @@
<?xml version="1.0"?>
-<testsuite name='BSC_Tests' tests='163' failures='11' errors='1' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='BSC_Tests' tests='317' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='BSC_Tests' name='TC_ctrl_msc_connection_status' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ctrl_msc0_connection_status' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_msc_connected_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_msc_connected_2' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_msc_connected_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_bts_connected_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_bts_connected_2' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stat_num_bts_connected_3' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ctrl' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si_default' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_2_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_3_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_4_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_5_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_6_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_12_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_23_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_32_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_33_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_42_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_48_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2quater_49_earfcns' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si_acc_rotate' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si_acc_ramp_rotate' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_si2_ncc_permitted' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_noreply' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_counter' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_ack_noest' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_act_ack_noest_emerg' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_rqd_emerg_deny' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_ack_est_ind_noreply' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_ack_est_ind_refused' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_act_nack' time='MASKED'/>
@@ -14,25 +38,35 @@
<testcase classname='BSC_Tests' name='TC_chan_rel_rll_rel_ind' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_conn_fail' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_hard_clear' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_rel_last_eutran_plmn_hard_clear_no_csfb' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_rel_last_eutran_plmn_hard_clear_csfb' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_hard_clear_csfb' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_hard_rlsd' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_hard_rlsd_ms_dead' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_a_reset' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chan_rel_sccp_tiar_timeout' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_rel_rr_cause' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_outbound_connect' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_cic_only' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_csd' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_ctm' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_sign' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_aoip_tla_v6' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_fr_a5_0' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_fr_a5_1' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_fr_a5_1_codec_missing' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_fr_a5_3' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_fr_a5_4' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_fr_a5_4_fail' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_fr_a5_not_sup' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ciph_mode_a5_0' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ciph_mode_a5_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ciph_mode_a5_2_0' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ciph_mode_a5_2_1' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ciph_mode_a5_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ciph_mode_a5_4' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_fr' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_fr_by_mode_modify' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_hr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_efr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_amr_f' time='MASKED'/>
@@ -54,6 +88,11 @@
<testcase classname='BSC_Tests' name='TC_assignment_codec_amr_f_zero' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_amr_f_unsupp' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_amr_h_S7' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_amr_f_start_mode_auto' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_amr_h_start_mode_auto' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_amr_f_start_mode_4' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_amr_h_start_mode_4' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_amr_startmode_cruft' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_fr_exhausted_req_hr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_fr_exhausted_req_fr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_fr_exhausted_req_fr_hr' time='MASKED'/>
@@ -64,11 +103,22 @@
<testcase classname='BSC_Tests' name='TC_assignment_codec_hr_exhausted_req_fr_hr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_req_hr_fr' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_codec_req_fr_hr' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_sdcch_exhausted_req_signalling' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_sdcch_exhausted_req_signalling_tch_forbidden' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_sdcch_exhausted_req_voice_tch_forbidden' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_codec_hr_osmux_on' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_osmux' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_osmux_cn' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_osmux_bts' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rll_est_ind_inact_lchan' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rll_est_ind_inval_sapi1' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rll_est_ind_inval_sapi3' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rll_est_ind_inval_sacch' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_tch_dlci_link_id_sapi' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_rll_rel_ind_sapi_n_reject' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_rll_err_ind_sapi_n_reject' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_rll_timeout_sapi_n_reject' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_rll_sapi_n_reject_dlci_cc' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_paging_imsi_nochan' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_paging_tmsi_nochan' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_paging_tmsi_any' time='MASKED'/>
@@ -91,25 +141,50 @@
<testcase classname='BSC_Tests' name='TC_paging_imsi_load' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_paging_counter' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_paging_resp_unsol' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_paging_500req' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_paging_450req_no_paging_load_ind' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_paging_imsi_nochan_ci_resp_invalid_mi' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rsl_drop_counter' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_rsl_unknown_unit_id' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_oml_unknown_unit_id' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_classmark' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_common_id' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_unsol_ass_fail' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_unsol_ass_compl' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_unsol_ho_fail' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_err_82_short_msg' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_err_84_unknown_msg' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_int' time='MASKED'/>
- <testcase classname='BSC_Tests' name='TC_ho_out_of_this_bsc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_int_a5_0' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_int_a5_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_int_a5_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_int_a5_4' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_int_radio_link_failure' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_out_fail_no_msc_response' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_out_fail_rr_ho_failure' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_out_fail_no_result_after_ho_cmd' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_into_this_bsc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_0' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_4' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_1_3_no_chosen_enc_alg' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_1_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_a5_mismatch' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_tla_v6' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran_a5_3' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran_src_sai' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran_ho_out' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran_forbid_fast_return' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_srvcc_eutran_to_geran_ho_out_forbid_fast_return' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_in_fail_msc_clears' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_in_fail_msc_clears_after_ho_detect' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_in_fail_no_detect' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_in_fail_no_detect2' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_in_fail_mgw_mdcx_timeout' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_in_fail_ipa_crcx_timeout' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_into_this_bsc_sccp_cr_without_bssap' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_neighbor_config_1' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_neighbor_config_2' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_ho_neighbor_config_3' time='MASKED'/>
@@ -124,11 +199,80 @@
<testcase classname='BSC_Tests' name='TC_dyn_pdch_ipa_act_nack' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_dyn_pdch_osmo_act_deact' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_dyn_pdch_osmo_act_nack' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_dyn_ts_sdcch8_act_deact' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_dyn_ts_sdcch8_all_subslots_used' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_dyn_ts_sdcch8_tch_call_act_deact' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_dyn_ts_sdcch8_act_nack' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chopped_ipa_ping' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_chopped_ipa_payload' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_assignment_verify_ms_power_params_ie' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_c0_power_red_mode' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Compl_on_1_msc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Complete_by_imsi_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_LU_by_tmsi_null_nri_0_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_LU_by_tmsi_null_nri_1_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_2' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_LU_by_tmsi_from_other_PLMN' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_paging_and_response_imsi' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_paging_and_response_tmsi' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_no_allow_attach_round_robin' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_no_allow_attach_valid_nri' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_sccp_n_pcstate_detaches_msc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mscpool_sccp_n_pcstate_attaches_msc' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_early_conn_fail' time='MASKED'/>
<testcase classname='BSC_Tests' name='TC_late_conn_fail' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_stats_conn_fail' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_emerg_setup_allow' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_emerg_setup_allow_imei' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_emerg_setup_deny_msc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_assignment_emerg_setup_deny_bts' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_emerg_premption' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_fh_params_chan_activ' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_fh_params_imm_ass' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_fh_params_assignment_cmd' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_fh_params_handover_cmd' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_fh_params_si4_cbch' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_active_ms' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_active_ms_ta_req' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_idle_ms' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_no_subscriber' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_active_ms_le_timeout' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_active_ms_le_timeout2' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lcs_loc_req_for_idle_ms_no_pag_resp' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_cm_service_during_lcs_loc_req' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_during_lcs_loc_req' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_emerg_call_and_lcs_loc_req' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_emerg_call_and_lcs_loc_req_early_lchan_rel_ind' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_emerg_call_and_lcs_loc_req_early_lchan_conn_fail' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_no_msc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_refuse_chan_act_to_vamos' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_refuse_mode_modif_to_vamos' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_reassignment_fr' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_cm_reestablishment' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_imm_ass_post_chan_ack' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_imm_ass_pre_chan_ack' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_imm_ass_pre_ts_ack' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_imm_ass_pre_chan_ack_dyn_ts' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_imm_ass_pre_ts_ack_dyn_ts' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ctrl_trx_rf_locked' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ratectr_all_available_allocated' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ratectr_all_available_allocated_dyn' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_cm_serv_rej' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_lost_sdcch_during_assignment' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_alloc_algo_ascending' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_alloc_algo_descending' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_chan_alloc_algo_ass_dynamic' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mgwpool_all_used' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mgwpool_blocked_not_used' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mgwpool_pin_bts' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_mgwpool_keepalive_down_not_used' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_meas_rep_multi_band' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_ho_out_of_this_bsc' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_unbreak_lchan_after_missing_rel_ack_1' time='MASKED'/>
+ <testcase classname='BSC_Tests' name='TC_unbreak_lchan_after_missing_rel_ack_2' time='MASKED'/>
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_gcr_only' time='MASKED'/>
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_gcr_bway_connect' time='MASKED'/>
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_gcr_bway_connect_hr' time='MASKED'/>
@@ -143,81 +287,34 @@
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_bts_gcr_bway_connect' time='MASKED'/>
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_bts_gcr_bway_connect_hr' time='MASKED'/>
<testcase classname='BSC_Tests_LCLS' name='TC_lcls_bts_connect_break' time='MASKED'/>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_bsc_server' time='MASKED'>
- <failure type='fail-verdict'>Could not connect to CBSP port, check your configuration
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_bsc_server testcase
- </failure>
- </testcase>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_bsc_server' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_bsc_server_ipv6' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_bsc_client' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_bsc_client_ipv6' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_reset_bss' time='MASKED'/>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_bss' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_bss testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_bts_cgi' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_bts_cgi testcase
- </failure>
- </testcase>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_cell_rflock_failure_restart' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_cell_rsl_down_failure' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_bss' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_bts_cgi' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_bts_no_cbch' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_unknown_bts' time='MASKED'/>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lac_ci' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_lac_ci testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_ci' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_ci testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lai' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_lai testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lac' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_lac testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_replace' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_then_replace testcase
- </failure>
- </testcase>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lac_ci' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_ci' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lai' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_lac' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_replace' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_rep_period_num' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_replace_nonexist' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_too_many' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_kill_nonexist' time='MASKED'/>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_kill' time='MASKED'>
- <error type='DTE'>Dynamic test case error: Performing lengthof() operation on a template of type @CBSP_Types.CBSP_IEs with no exact length.</error>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_reset' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected CBSP
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_write_then_reset testcase
- </failure>
- </testcase>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_kill' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_write_then_reset' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_status_q_empty' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_status_q_bts_cgi' time='MASKED'/>
<testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_dchan' time='MASKED'/>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_cchan' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected OSMO_ETWS_CMD
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_emerg_write_bts_cgi_cchan testcase
- </failure>
- </testcase>
- <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_cchan_disable' time='MASKED'>
- <failure type='fail-verdict'>Received unexpected OSMO_ETWS_CMD
- BSC_Tests_CBSP.ttcn:MASKED BSC_Tests_CBSP control part
- BSC_Tests_CBSP.ttcn:MASKED TC_cbsp_emerg_write_bts_cgi_cchan_disable testcase
- </failure>
- </testcase>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_cchan' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_cchan_disable' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_noreplace' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_replace' time='MASKED'/>
+ <testcase classname='BSC_Tests_CBSP' name='TC_cbsp_emerg_write_bts_cgi_kill' time='MASKED'/>
</testsuite>
diff --git a/bsc/gen_links.sh b/bsc/gen_links.sh
index 343cc1cd..cb9f12f9 100755
--- a/bsc/gen_links.sh
+++ b/bsc/gen_links.sh
@@ -67,9 +67,13 @@ FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn RAN_Emulation.ttcnpp RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn RAN_Adapter.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn IPA_Testing.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn "
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn RAN_Emulation.ttcnpp RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn SDP_Templates.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn RAN_Adapter.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn IPA_Testing.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn "
FILES+="CBSP_Types.ttcn CBSP_Templates.ttcn "
FILES+="CBSP_CodecPort.ttcn CBSP_CodecPort_CtrlFunct.ttcn CBSP_CodecPort_CtrlFunctdef.cc CBSP_Adapter.ttcn "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="BSSAP_LE_CodecPort.ttcn BSSAP_LE_Emulation.ttcn BSSAP_LE_Types.ttcn BSSAP_LE_Adapter.ttcn BSSLAP_Types.ttcn BSSMAP_LE_Templates.ttcn "
+FILES+="AbisOML_Types.ttcn"
+
gen_links $DIR $FILES
ignore_pp_results
diff --git a/bsc/osmo-bsc-sccplite.cfg b/bsc/osmo-bsc-sccplite.cfg
new file mode 100644
index 00000000..05934ed2
--- /dev/null
+++ b/bsc/osmo-bsc-sccplite.cfg
@@ -0,0 +1,366 @@
+!
+! OsmoBSC (1.0.1.122-630df) configuration saved from vty
+!!
+password foo
+!
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
+!
+line vty
+ no login
+ bind 127.0.0.1
+!
+e1_input
+ e1_line 0 driver ipa
+ e1_line 0 port 0
+ no e1_line 0 keepalive
+cs7 instance 0
+ point-code 0.23.3
+ asp asp-clnt-msc-0 5000 0 ipa
+ remote-ip 127.0.0.1
+ role asp
+ sctp-role client
+ as as-clnt-msc-0 ipa
+ asp asp-clnt-msc-0
+ routing-key 0 0.23.3
+ point-code override dpc 0.23.1
+network
+ network country code 1
+ mobile network code 1
+ encryption a5 0 1 3
+ neci 1
+ paging any use tch 0
+ handover 1
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3113 10
+ timer t3212 30
+ mgw 0
+ mgw remote-ip 127.0.0.1
+ bts 0
+ type osmo-bts
+ band DCS1800
+ cell_identity 0
+ location_area_code 1
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 10
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1234 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1234
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1234
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1234
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 1
+ type osmo-bts
+ band DCS1800
+ cell_identity 1
+ location_area_code 1
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 11
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1235 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1235
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1235
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1235
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 2
+ type osmo-bts
+ band DCS1800
+ cell_identity 1
+ location_area_code 2
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 12
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1236 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1236
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1236
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1236
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 3
+ type osmo-bts
+ band DCS1800
+ cell_identity 3
+ location_area_code 3
+ # re-use bts 2's ARFCN 871 and BSIC 12 (to test handover config)
+ base_station_id_code 12
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4
+ timeslot 1
+ phys_chan_config TCH/F
+ timeslot 2
+ phys_chan_config TCH/F
+ timeslot 3
+ phys_chan_config TCH/F
+ timeslot 4
+ phys_chan_config TCH/F
+ timeslot 5
+ phys_chan_config TCH/H
+ timeslot 6
+ phys_chan_config PDCH
+ timeslot 7
+ phys_chan_config PDCH
+msc 0
+ allow-emergency allow
+ amr-config 12_2k forbidden
+ amr-config 10_2k forbidden
+ amr-config 7_95k forbidden
+ amr-config 7_40k forbidden
+ amr-config 6_70k forbidden
+ amr-config 5_90k allowed
+ amr-config 5_15k forbidden
+ amr-config 4_75k forbidden
+ codec-list fr1 fr2 fr3 hr1 hr3
+ asp-protocol ipa
+bsc
+ mid-call-timeout 0
+ no missing-msc-text
+ctrl
+ bind 127.0.0.1
diff --git a/bsc/osmo-bsc-vamos.cfg b/bsc/osmo-bsc-vamos.cfg
new file mode 100644
index 00000000..73cafe7e
--- /dev/null
+++ b/bsc/osmo-bsc-vamos.cfg
@@ -0,0 +1,418 @@
+!
+! OsmoBSC (1.0.1.122-630df) configuration saved from vty
+!!
+password foo
+!
+log stderr
+ logging filter all 1
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
+ logging print category 1
+ logging print level 1
+ logging timestamp 1
+ logging color 1
+!
+ logging level set-all notice
+ logging level rll notice
+ logging level mm notice
+ logging level rr notice
+ logging level rsl notice
+ logging level nm info
+ logging level pag notice
+ logging level meas notice
+ logging level msc notice
+ logging level ho notice
+ logging level ref notice
+ logging level ctrl notice
+ logging level filter debug
+ logging level pcu debug
+!
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
+!
+line vty
+ no login
+ bind 127.0.0.1
+!
+e1_input
+ e1_line 0 driver ipa
+ e1_line 0 port 0
+ no e1_line 0 keepalive
+cs7 instance 0
+ asp asp-clnt-msc-0 2905 1905 m3ua
+ remote-ip 127.0.0.1
+ role asp
+ sctp-role client
+ sccp-address msc2
+ point-code 0.0.2
+ sccp-address msc3
+ point-code 0.0.3
+network
+ network country code 1
+ mobile network code 1
+ encryption a5 0 1 3
+ neci 1
+ paging any use tch 0
+ handover 1
+ handover window rxlev averaging 10
+ handover window rxqual averaging 1
+ handover window rxlev neighbor averaging 10
+ handover power budget interval 6
+ handover power budget hysteresis 3
+ handover maximum distance 9999
+ timer t3113 10
+ timer t3212 30
+ mgw 0
+ mgw remote-ip 127.0.0.1
+ bts 0
+ type osmo-bts
+ band DCS1800
+ cell_identity 0
+ location_area_code 1
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 10
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1234 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1234
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1234
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1234
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 1
+ type osmo-bts
+ band DCS1800
+ cell_identity 1
+ location_area_code 1
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 11
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1235 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1235
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1235
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1235
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 2
+ type osmo-bts
+ band DCS1800
+ cell_identity 1
+ location_area_code 2
+ dtx uplink force
+ dtx downlink
+ base_station_id_code 12
+ ms max power 15
+ cell reselection hysteresis 4
+ rxlev access min 0
+ radio-link-timeout 32
+ channel allocator ascending
+ rach tx integer 9
+ rach max transmission 7
+ channel-descrption attach 1
+ channel-descrption bs-pa-mfrms 5
+ channel-descrption bs-ag-blks-res 1
+ early-classmark-sending forbidden
+ ip.access unit_id 1236 0
+ oml ip.access stream_id 255 line 0
+ neighbor-list mode manual-si5
+ neighbor-list add arfcn 100
+ neighbor-list add arfcn 200
+ si5 neighbor-list add arfcn 10
+ si5 neighbor-list add arfcn 20
+ codec-support fr hr efr amr
+ gprs mode gprs
+ gprs routing area 0
+ gprs network-control-order nc0
+ gprs cell bvci 1236
+ gprs cell timer blocking-timer 3
+ gprs cell timer blocking-retries 3
+ gprs cell timer unblocking-retries 3
+ gprs cell timer reset-timer 3
+ gprs cell timer reset-retries 3
+ gprs cell timer suspend-timer 10
+ gprs cell timer suspend-retries 3
+ gprs cell timer resume-timer 10
+ gprs cell timer resume-retries 3
+ gprs cell timer capability-update-timer 10
+ gprs cell timer capability-update-retries 3
+ gprs nsei 1236
+ gprs ns timer tns-block 3
+ gprs ns timer tns-block-retries 3
+ gprs ns timer tns-reset 3
+ gprs ns timer tns-reset-retries 3
+ gprs ns timer tns-test 30
+ gprs ns timer tns-alive 3
+ gprs ns timer tns-alive-retries 10
+ gprs nsvc 0 nsvci 1236
+ gprs nsvc 0 local udp port 23000
+ gprs nsvc 0 remote udp port 23000
+ gprs nsvc 0 remote ip 192.168.100.239
+ gprs nsvc 1 nsvci 0
+ gprs nsvc 1 local udp port 0
+ gprs nsvc 1 remote udp port 0
+ gprs nsvc 1 remote ip 0.0.0.0
+ no force-combined-si
+ si2quater neighbor-list add earfcn 111 thresh-hi 20 thresh-lo 10 prio 3 qrxlv 22 meas 3
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ bts 3
+ type osmo-bts
+ band DCS1800
+ cell_identity 3
+ location_area_code 3
+ # re-use bts 2's ARFCN 871 and BSIC 12 (to test handover config)
+ base_station_id_code 12
+ trx 0
+ rf_locked 0
+ arfcn 871
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config CCCH+SDCCH4
+ timeslot 1
+ phys_chan_config TCH/F
+ timeslot 2
+ phys_chan_config TCH/F
+ timeslot 3
+ phys_chan_config TCH/F
+ timeslot 4
+ phys_chan_config TCH/F
+ timeslot 5
+ phys_chan_config TCH/H
+ timeslot 6
+ phys_chan_config PDCH
+ timeslot 7
+ phys_chan_config PDCH
+msc 0
+ allow-emergency allow
+ amr-config 12_2k forbidden
+ amr-config 10_2k forbidden
+ amr-config 7_95k forbidden
+ amr-config 7_40k forbidden
+ amr-config 6_70k forbidden
+ amr-config 5_90k allowed
+ amr-config 5_15k forbidden
+ amr-config 4_75k forbidden
+ codec-list fr1 fr2 fr3 hr1 hr3
+ lcls-mode mgw-loop
+msc 1
+ msc-addr msc2
+msc 2
+ msc-addr msc3
+
+network
+ nri bitlen 10
+ # a NULL NRI that is outside the NRI ranges used by the MSCs:
+ nri null add 0
+ # a NULL NRI that is also used by an MSC:
+ nri null add 1
+msc 0
+ nri add 1 255
+msc 1
+ nri add 256 511
+msc 2
+ nri add 512 767
+ # range 768-1024 is not assigned to any MSC on purpose
+
+bsc
+ mid-call-timeout 0
+ctrl
+ bind 127.0.0.1
+cbc
+ mode disabled
+ client
+ remote-ip 127.0.0.1
+ remote-port 48049
+ server
+ local-ip 127.0.0.1
+ local-port 48050
+smlc
+ enable
diff --git a/bsc/osmo-bsc.cfg b/bsc/osmo-bsc.cfg
index a4c767a6..43f78334 100644
--- a/bsc/osmo-bsc.cfg
+++ b/bsc/osmo-bsc.cfg
@@ -5,16 +5,20 @@ password foo
!
log stderr
logging filter all 1
- logging color 1
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging print extended-timestamp 1
- logging level all everything
+ logging color 1
+!
+ logging level set-all notice
logging level rll notice
logging level mm notice
logging level rr notice
logging level rsl notice
- logging level nm info
+ logging level nm notice
logging level pag notice
logging level meas notice
logging level msc notice
@@ -23,25 +27,16 @@ log stderr
logging level ctrl notice
logging level filter debug
logging level pcu debug
- logging level lglobal notice
- logging level llapd notice
- logging level linp notice
- logging level lmux notice
- logging level lmi notice
- logging level lmib notice
- logging level lsms notice
- logging level lctrl notice
- logging level lgtp notice
- logging level lstats notice
- logging level lgsup notice
- logging level loap notice
- logging level lss7 notice
- logging level lsccp notice
- logging level lsua notice
- logging level lm3ua notice
- logging level lmgcp notice
!
-stats interval 5
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
!
line vty
no login
@@ -54,6 +49,8 @@ e1_input
cs7 instance 0
asp asp-clnt-msc-0 2905 1905 m3ua
remote-ip 127.0.0.1
+ role asp
+ sctp-role client
sccp-address msc2
point-code 0.0.2
sccp-address msc3
@@ -73,8 +70,10 @@ network
handover maximum distance 9999
timer t3113 10
timer t3212 30
+ mgw 0
+ mgw remote-ip 127.0.0.1
bts 0
- type sysmobts
+ type osmo-bts
band DCS1800
cell_identity 0
location_area_code 1
@@ -100,6 +99,18 @@ network
si5 neighbor-list add arfcn 10
si5 neighbor-list add arfcn 20
codec-support fr hr efr amr
+ amr tch-f modes 0 2 4 7
+ amr tch-f threshold ms 32 32 32
+ amr tch-f hysteresis ms 8 8 8
+ amr tch-f threshold bts 32 32 32
+ amr tch-f hysteresis bts 8 8 8
+ amr tch-f start-mode auto
+ amr tch-h modes 0 2 4
+ amr tch-h threshold ms 32 32
+ amr tch-h hysteresis ms 8 8
+ amr tch-h threshold bts 32 32
+ amr tch-h hysteresis bts 8 8
+ amr tch-h start-mode auto
gprs mode gprs
gprs routing area 0
gprs network-control-order nc0
@@ -140,7 +151,7 @@ network
max_power_red 20
rsl e1 tei 0
timeslot 0
- phys_chan_config CCCH+SDCCH4
+ phys_chan_config CCCH+SDCCH4+CBCH
hopping enabled 0
timeslot 1
phys_chan_config TCH/F
@@ -164,7 +175,7 @@ network
phys_chan_config PDCH
hopping enabled 0
bts 1
- type sysmobts
+ type osmo-bts
band DCS1800
cell_identity 1
location_area_code 1
@@ -230,7 +241,7 @@ network
max_power_red 20
rsl e1 tei 0
timeslot 0
- phys_chan_config CCCH+SDCCH4
+ phys_chan_config CCCH+SDCCH4+CBCH
hopping enabled 0
timeslot 1
phys_chan_config TCH/F
@@ -254,7 +265,7 @@ network
phys_chan_config PDCH
hopping enabled 0
bts 2
- type sysmobts
+ type osmo-bts
band DCS1800
cell_identity 1
location_area_code 2
@@ -320,7 +331,97 @@ network
max_power_red 20
rsl e1 tei 0
timeslot 0
- phys_chan_config CCCH+SDCCH4
+ phys_chan_config CCCH+SDCCH4+CBCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ trx 1
+ rf_locked 0
+ arfcn 873
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ trx 2
+ rf_locked 0
+ arfcn 875
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ trx 3
+ rf_locked 0
+ arfcn 877
+ nominal power 23
+ max_power_red 20
+ rsl e1 tei 0
+ timeslot 0
+ phys_chan_config TCH/F
hopping enabled 0
timeslot 1
phys_chan_config TCH/F
@@ -344,7 +445,7 @@ network
phys_chan_config PDCH
hopping enabled 0
bts 3
- type sysmobts
+ type osmo-bts
band DCS1800
cell_identity 3
location_area_code 3
@@ -373,10 +474,6 @@ network
timeslot 7
phys_chan_config PDCH
msc 0
- no bsc-welcome-text
- no bsc-msc-lost-text
- no bsc-grace-text
- type normal
allow-emergency allow
amr-config 12_2k forbidden
amr-config 10_2k forbidden
@@ -387,14 +484,11 @@ msc 0
amr-config 5_15k forbidden
amr-config 4_75k forbidden
codec-list fr1 fr2 fr3 hr1 hr3
- mgw remote-ip 127.0.0.1
lcls-mode mgw-loop
msc 1
msc-addr msc2
- mgw remote-ip 127.0.0.1
msc 2
msc-addr msc3
- mgw remote-ip 127.0.0.1
network
nri bitlen 10
@@ -412,10 +506,15 @@ msc 2
bsc
mid-call-timeout 0
- no missing-msc-text
ctrl
bind 127.0.0.1
cbc
- remote-ip 127.0.0.1
- remote-port 48049
- listen-port 48050
+ mode disabled
+ client
+ remote-ip 127.0.0.1
+ remote-port 48049
+ server
+ local-ip 127.0.0.1
+ local-port 48050
+smlc
+ enable
diff --git a/bsc/osmo-stp.cfg b/bsc/osmo-stp.cfg
index 8b8ccdba..d936d4f3 100644
--- a/bsc/osmo-stp.cfg
+++ b/bsc/osmo-stp.cfg
@@ -4,28 +4,19 @@
!
log stderr
logging filter all 1
- logging color 1
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging print extended-timestamp 1
- logging level all everything
- logging level lglobal notice
- logging level llapd notice
- logging level linp notice
- logging level lmux notice
- logging level lmi notice
- logging level lmib notice
- logging level lsms notice
- logging level lctrl notice
- logging level lgtp notice
- logging level lstats notice
- logging level lgsup notice
- logging level loap notice
+ logging color 1
+!
+ logging level set-all notice
logging level lss7 debug
logging level lsccp debug
logging level lsua debug
logging level lm3ua debug
- logging level lmgcp notice
!
line vty
no login
@@ -35,6 +26,8 @@ cs7 instance 0
asp virt-msc0-0 23905 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as mahlzeit ipa
routing-key 0 0.23.4
point-code override dpc 0.23.1
@@ -45,6 +38,8 @@ cs7 instance 0
asp virt-msc1-0 23906 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as virt-msc1 m3ua
asp virt-msc1-0
routing-key 2 0.0.2
@@ -52,14 +47,24 @@ cs7 instance 0
asp virt-msc2-0 23907 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as virt-msc2 m3ua
asp virt-msc2-0
routing-key 3 0.0.3
+ asp virt-smlc-0 23908 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ as virt-smlc m3ua
+ asp virt-smlc-0
+ routing-key 6 0.23.6
+
route-table system
update route 0.23.1 7.255.7 linkset virt-msc0
update route 0.0.2 7.255.7 linkset virt-msc1
update route 0.0.3 7.255.7 linkset virt-msc2
+ update route 0.23.6 7.255.7 linkset virt-smlc
listen m3ua 2905
accept-asp-connections dynamic-permitted
listen ipa 5000
diff --git a/bsc/regen_makefile.sh b/bsc/regen_makefile.sh
index def4a3fe..fc53e304 100755
--- a/bsc/regen_makefile.sh
+++ b/bsc/regen_makefile.sh
@@ -1,9 +1,38 @@
#!/bin/sh
-MAIN=BSC_Tests.ttcn
+NAME=BSC_Tests
-FILES="*.ttcn *.ttcnpp IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc SCTPasp_PT.cc RTP_EncDec.cc SDP_EncDec.cc RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc IuUP_EncDec.cc Native_FunctionDefs.cc TELNETasp_PT.cc CBSP_CodecPort_CtrlFunctdef.cc *.c"
+FILES="
+ *.c
+ *.ttcn
+ *.ttcnpp
+ CBSP_CodecPort_CtrlFunctdef.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IuUP_EncDec.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SCTPasp_PT.cc
+ SDP_EncDec.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSL -DIPA_EMULATION_MGCP -DIPA_EMULATION_CTRL -DIPA_EMULATION_SCCP -DRAN_EMULATION_BSSAP -DRAN_EMULATION_MGCP -DRAN_EMULATION_CTRL -DUSE_MTP3_DISTRIBUTOR"
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_MGCP
+ -DIPA_EMULATION_RSL
+ -DIPA_EMULATION_OML
+ -DIPA_EMULATION_SCCP
+ -DRAN_EMULATION_BSSAP
+ -DRAN_EMULATION_CTRL
+ -DRAN_EMULATION_MGCP
+ -DUSE_MTP3_DISTRIBUTOR
+"
-../regen-makefile.sh $MAIN $FILES
+../regen-makefile.sh -e $NAME $FILES
diff --git a/bts/BTS_Tests.cfg b/bts/BTS_Tests.cfg
index ed041639..fb78ebae 100644
--- a/bts/BTS_Tests.cfg
+++ b/bts/BTS_Tests.cfg
@@ -12,28 +12,33 @@
#*.BTSVTY.CTRL_HOSTNAME := "10.9.1.191" # sysmoBTS Max
#*.BTSVTY.CTRL_HOSTNAME := "10.9.1.162" # sysmoBTS Pau
#*.BTSVTY.CTRL_HOSTNAME := "192.168.100.130" # sysmoBTS home
-*.BTSVTY.CTRL_HOSTNAME := "127.0.0.20" # osmo-bts-trx
-*.BSCVTY.CTRL_HOSTNAME := "127.0.0.11" # osmo-bsc
+#*.BTSVTY.CTRL_HOSTNAME := "127.0.0.20" # osmo-bts-trx
+#*.BSCVTY.CTRL_HOSTNAME := "127.0.0.11" # osmo-bsc
[MODULE_PARAMETERS]
L1CTL_PortType.m_l1ctl_sock_path := "/tmp/osmocom_l2"
#BTS_Tests.mp_rsl_ip := "10.9.1.2" # office
#BTS_Tests.mp_rsl_ip := "192.168.100.2" # home
-BTS_Tests.mp_rsl_ip := "127.0.0.10"
+#BTS_Tests.mp_rsl_ip := "127.0.0.10"
BTS_Tests.mp_pcu_socket := "/tmp/pcu_sock"
-BTS_Tests.mp_bts_trxc_ip := "127.0.0.21"
-BTS_Tests.mp_ctrl_ip := "127.0.0.20"
+#BTS_Tests.mp_bts_trxc_ip := "127.0.0.21"
+#BTS_Tests.mp_ctrl_ip := "127.0.0.20"
#BTS_Tests_OML.mp_oml_ip := "192.168.102.239" # home
#BTS_Tests_OML.mp_oml_port := 3002
+BTS_Tests.mp_l1_supports_gprs := true
# real BTS / RF
#BTS_Tests.mp_bb_trxc_port := -1
#BTS_Tests.mp_tolerance_rxlev := 10;
#BTS_Tests.mp_tolerance_rxqual := 1;
+BTS_Tests_OML.mp_pcu_socket := "/tmp/pcu_sock"
[MAIN_CONTROLLER]
[EXECUTE]
BTS_Tests.control
BTS_Tests_SMSCB.control
+BTS_Tests_LAPDm.control
+BTS_Tests_VAMOS.control
+BTS_Tests_ASCI.control
diff --git a/bts/BTS_Tests.default b/bts/BTS_Tests.default
index 920f5d00..578aa367 100644
--- a/bts/BTS_Tests.default
+++ b/bts/BTS_Tests.default
@@ -29,5 +29,62 @@ mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
[MODULE_PARAMETERS]
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoBTS";
+PCUIF_Types.mp_pcuif_version := 12;
+
+# Configuration for each individual transceiver
+BTS_Tests.mp_trx_pars := {
+ { # TRX0
+ arfcn := 871,
+ ts := {
+ { config := GSM_PCHAN_CCCH_SDCCH4 },
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_TCHF_PDCH },
+ { config := GSM_PCHAN_TCHH_TCHF_PDCH },
+ { config := GSM_PCHAN_TCHH },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_PDCH }
+ }
+ },
+ { # TRX1
+ arfcn := 873,
+ ts := {
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_TCHH_TCHF_PDCH },
+ { config := GSM_PCHAN_TCHF_PDCH },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_PDCH }
+ }
+ },
+ { # TRX2
+ arfcn := 875,
+ ts := {
+ { config := GSM_PCHAN_TCHH },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_PDCH }
+ }
+ },
+ { # TRX3
+ arfcn := 877,
+ ts := {
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_TCHH },
+ { config := GSM_PCHAN_TCHH },
+ { config := GSM_PCHAN_SDCCH8 },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_TCHF },
+ { config := GSM_PCHAN_PDCH },
+ { config := GSM_PCHAN_SDCCH8 }
+ }
+ }
+};
[EXECUTE]
diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn
index 1c8127bd..29879b93 100644
--- a/bts/BTS_Tests.ttcn
+++ b/bts/BTS_Tests.ttcn
@@ -35,14 +35,24 @@ import from L1CTL_PortType all;
import from L1CTL_Types all;
import from LAPDm_Types all;
import from LAPDm_RAW_PT all;
+import from Native_Functions all;
import from Osmocom_CTRL_Adapter all;
import from Osmocom_CTRL_Functions all;
import from RSL_Types all;
+import from RTP_Types all;
import from IPA_Types all;
import from IPA_Emulation all;
import from IPA_Testing all;
import from RSL_Emulation all;
+import from RTP_Emulation all;
+
+import from AMR_Types all;
+
+import from OSMUX_Types all;
+import from OSMUX_CodecPort all;
+import from OSMUX_CodecPort_CtrlFunct all;
+import from OSMUX_Emulation all;
import from IPL4asp_Types all;
import from TRXC_Types all;
@@ -64,10 +74,13 @@ import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType all;
import from BTS_Tests_LAPDm all;
+friend module BTS_Tests_ASCI;
friend module BTS_Tests_SMSCB;
+friend module BTS_Tests_VAMOS;
friend module BTS_Tests_virtphy;
friend module BTS_Tests_LAPDm;
friend module BTS_Tests_perf;
+friend module BTS_Tests_OML;
/* The tests assume a BTS with the following timeslot configuration:
* TS0 : Combined CCCH + SDCCH/4
@@ -83,10 +96,6 @@ friend module BTS_Tests_perf;
modulepar {
charstring mp_rsl_ip := "127.0.0.2";
integer mp_rsl_port := 3003;
- integer mp_trx0_arfcn := 871;
- integer mp_trx1_arfcn := 873;
- integer mp_trx2_arfcn := 875;
- integer mp_trx3_arfcn := 877;
charstring mp_bts_trxc_ip := "127.0.0.1";
integer mp_bts_trxc_port := 5701;
charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
@@ -94,6 +103,10 @@ modulepar {
integer mp_ctrl_port := 4238;
charstring mp_bsc_ctrl_ip := "127.0.0.1";
integer mp_bsc_ctrl_port := 4249;
+ charstring mp_rtpem_bind_ip := "127.0.0.1";
+ integer mp_rtpem_bind_port := 6766;
+ charstring mp_osmuxem_bind_ip := "127.0.0.1";
+ integer mp_osmuxem_bind_port := 1984;
integer mp_tolerance_rxqual := 1;
integer mp_tolerance_rxlev := 3;
integer mp_tolerance_timing_offset_256syms := 0;
@@ -104,6 +117,8 @@ modulepar {
integer mp_bts_tx_pwr_att_exp := 20; /* Expected Tx Power attenuation wrt to Tx Nominal Output Power, in dB */
integer mp_ms_actual_ta_exp := 0;
integer mp_timing_offset_256syms_exp := 512;
+ integer mp_uplink_power_target := -75;
+ integer mp_uplink_power_hysteresis := 8; /* -83 .. -67 */
/* Time to wait for RSL conn from BTS during startup of test */
float mp_ipa_up_timeout := 15.0;
float mp_ipa_up_delay := 0.0;
@@ -115,6 +130,25 @@ modulepar {
boolean mp_freq_hop_enabled := false;
/* frequency hopping parameters */
FreqHopConfig mp_fh_config;
+ /* configuration for each individual transceiver */
+ TrxPars mp_trx_pars; /* see BTS_Tests.default */
+ /* default Training Sequence Code */
+ GsmTsc mp_tsc_def := 7;
+ /* Default interference boundaries in osmo-bsc (in dBm):
+ * 0(-115) X1(-109) X2(-103) X3(-97) X4(-91) X5(-85)
+ * Default interference level reported by fake_trx.py:
+ * 0: -109 < -115 dBm
+ * X1: -109 < -109 dBm
+ * X2: -109 < -103 dBm <-- stop here
+ * X3: -109 < -97 dBm
+ * X4: -109 < -91 dBm
+ * X5: -109 < -85 dBm
+ * So all channels should be in band 2. */
+ uint3_t mp_interf_band := 2;
+ /* T3105 timer (see 3GPP TS 44.018, section 11.1.2) */
+ integer mp_ho_t3105_ms := 100;
+ /* Ny1 counter (see 3GPP TS 44.018, section 11.1.3) */
+ integer mp_ho_ny1 := 10;
}
type record of RslChannelNr ChannelNrs;
@@ -189,12 +223,22 @@ type component ConnHdlr extends RSL_DchanHdlr, lapdm_test_CT {
/* PCU Interface of BTS */
port PCUIF_CODEC_PT PCU;
+
+ var RTP_Emulation_CT vc_RTPEM;
+ port RTPEM_CTRL_PT RTPEM_CTRL;
+ port RTPEM_DATA_PT RTPEM_DATA;
+ var OSMUX_Emulation_CT vc_OsmuxEM;
+ port OsmuxEM_CTRL_PT OsmuxEM_CTRL;
+ port OsmuxEM_DATA_PT OsmuxEM_DATA;
}
private function f_init_rsl(charstring id) runs on test_CT {
var bitstring trx_mask := '00000000'B;
+ var bitstring rfind_mask := '00000000'B;
var integer trx_count := 0;
+ var integer rfind_count := 0;
var RSLEm_Event ev;
+ var ASP_RSL_Unitdata rx_ud;
timer T;
vc_IPA := IPA_Emulation_CT.create(id & "-RSL-IPA");
@@ -219,14 +263,28 @@ private function f_init_rsl(charstring id) runs on test_CT {
log2str("Duplicate RSL stream ID (", ev.sid, ")"));
}
- /* This message (RF RESource INDication) is sent by the IUT itself */
- RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RF_RES_IND, ev.sid));
trx_mask[enum2int(ev.sid)] := '1'B;
trx_count := trx_count + 1;
log(trx_count, "/", mp_transceiver_num, " transceiver(s) connected");
- if (trx_count < mp_transceiver_num) { repeat; }
+ repeat;
}
+ /* This message (RF RESource INDication) is sent by the IUT itself */
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RF_RES_IND, ?)) -> value rx_ud {
+ if (trx_mask[enum2int(rx_ud.streamId)] == '0'B) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Got RF Resource Indication before RSLEM_EV_TRX_UP (", rx_ud.streamId, ")"));
+ }
+ if (rfind_mask[enum2int(rx_ud.streamId)] == '1'B) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Duplicate RF Resource Indication ID (", rx_ud.streamId, ")"));
+ }
+
+ rfind_mask[enum2int(rx_ud.streamId)] := '1'B;
+ rfind_count := rfind_count + 1;
+ log(rfind_count, "/", mp_transceiver_num, " RF Resource Indication(s) received");
+ if (rfind_count < mp_transceiver_num) { repeat; }
+ }
/* osmo-bts may send us CCCH LOAD INDication or whatever else */
[] RSL_CCHAN.receive(ASP_RSL_Unitdata:?) { repeat; }
[] T.timeout {
@@ -236,26 +294,51 @@ private function f_init_rsl(charstring id) runs on test_CT {
}
}
+friend type record length(1 .. 256) of TrxParsItem TrxPars;
+friend type record TrxParsItem {
+ GsmArfcn arfcn,
+ TrxTsPars ts
+};
+
+friend type record length(8) of TrxTsParsItem TrxTsPars;
+friend type record TrxTsParsItem {
+ PchanConfig config
+};
+
+friend type record FreqHopPars {
+ /* Whether frequency hopping is in use */
+ boolean enabled,
+ /* Mobile Allocation Index Offset / Hopping Sequence Number */
+ MaioHsn maio_hsn,
+ /* MA bitmap to be indicated in RR Immediate Assignment */
+ MobileAllocationLV ma_map,
+ /* The actual Mobile Allocation (ARFCN list) to be used */
+ L1ctlMA ma
+};
+
type record ConnHdlrPars {
+ uint8_t trx_nr,
RslChannelNr chan_nr,
RSL_IE_ChannelMode chan_mode,
+ RSL_IE_MultirateCfg mr_conf optional,
float t_guard,
ConnL1Pars l1_pars,
TestSpecUnion spec optional,
RSL_IE_EncryptionInfo encr optional,
BtsBand bts0_band optional,
- /* Frequency hopping parameters (disabled if absent) */
- MaioHsn maio_hsn optional,
- /* MA bitmap to be indicated in RR Immediate Assignment */
- MobileAllocation ma_map,
- /* The actual Mobile Allocation (ARFCN list) to be used */
- L1ctlMA ma
-}
+ /* Training Sequence Code */
+ GsmTsc tsc,
+ /* Frequency hopping parameters */
+ FreqHopPars fhp,
+ OsmuxCID loc_osmux_cid,
+ OsmuxCID rem_osmux_cid optional
+};
/* Test-specific parameters */
-private type union TestSpecUnion {
- RllTestCase rll
+friend type union TestSpecUnion {
+ RllTestCase rll,
+ TopTestCase top
}
private template (value) RachControlParameters ts_RachCtrl_default := {
@@ -388,7 +471,7 @@ friend function f_connhdlr_init_vty_bsc() runs on ConnHdlr {
}
/* PCU socket may at any time receive a new INFO.ind */
-private altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
+friend altstep as_pcu_info_ind(PCUIF_CODEC_PT pt, integer pcu_conn_id,
out PCUIF_Message pcu_last_info) {
var PCUIF_send_data sd;
[] pt.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(0, ?))) -> value sd {
@@ -432,26 +515,53 @@ private function f_init_trxc(TRXC_CODEC_PT pt, charstring id,
trxc_conn_id := res.connId;
}
-/* global init function */
-friend function f_init() runs on test_CT {
+private function f_gen_chans_for_ts(uint3_t tn, PchanConfig config)
+return ChannelNrs
+{
+ select (config) {
+ case (GSM_PCHAN_CCCH_SDCCH4) {
+ return { valueof(ts_RslChanNr_SDCCH4(tn, 0)),
+ valueof(ts_RslChanNr_SDCCH4(tn, 1)),
+ valueof(ts_RslChanNr_SDCCH4(tn, 2)),
+ valueof(ts_RslChanNr_SDCCH4(tn, 3)) };
+ }
+ case (GSM_PCHAN_SDCCH8) {
+ return { valueof(ts_RslChanNr_SDCCH8(tn, 0)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 1)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 2)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 3)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 4)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 5)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 6)),
+ valueof(ts_RslChanNr_SDCCH8(tn, 7)) };
+ }
+ case (GSM_PCHAN_TCHH_TCHF_PDCH) {
+ return { valueof(ts_RslChanNr_Lm(tn, 0)),
+ valueof(ts_RslChanNr_Lm(tn, 1)),
+ valueof(ts_RslChanNr_Bm(tn)) };
+ }
+ case (GSM_PCHAN_TCHH) {
+ return { valueof(ts_RslChanNr_Lm(tn, 0)),
+ valueof(ts_RslChanNr_Lm(tn, 1)) };
+ }
+ case (GSM_PCHAN_TCHF,
+ GSM_PCHAN_TCHF_PDCH) {
+ return { valueof(ts_RslChanNr_Bm(tn)) };
+ }
+ }
+
+ return { };
+}
+
+/* global init function (without PCUIF connection) */
+friend function f_init(uint8_t trx_nr := 0)
+runs on test_CT
+{
+ var TrxParsItem trx_pars := mp_trx_pars[trx_nr];
var charstring id := testcasename();
- g_AllChannels := {
- /* TS 1..4: TCH/F */
- valueof(ts_RslChanNr_Bm(1)), valueof(ts_RslChanNr_Bm(2)),
- valueof(ts_RslChanNr_Bm(3)), valueof(ts_RslChanNr_Bm(4)),
- /* TS 5: TCH/H */
- valueof(ts_RslChanNr_Lm(5,0)), valueof(ts_RslChanNr_Lm(5,1)),
- /* TS 0: SDCCH/4 */
- valueof(ts_RslChanNr_SDCCH4(0,0)), valueof(ts_RslChanNr_SDCCH4(0,1)),
- valueof(ts_RslChanNr_SDCCH4(0,2)), valueof(ts_RslChanNr_SDCCH4(0,3)),
- /* TS 6: SDCCH/8 */
- valueof(ts_RslChanNr_SDCCH8(6,0)), valueof(ts_RslChanNr_SDCCH8(6,1)),
- valueof(ts_RslChanNr_SDCCH8(6,2)), valueof(ts_RslChanNr_SDCCH8(6,3)),
- valueof(ts_RslChanNr_SDCCH8(6,4)), valueof(ts_RslChanNr_SDCCH8(6,5)),
- valueof(ts_RslChanNr_SDCCH8(6,6)), valueof(ts_RslChanNr_SDCCH8(6,7))
- };
- /* FIXME: FACCH/H is unreliable with calypso firmware, see OS#3653 */
+ /* FIXME: FACCH/H is unreliable with calypso firmware, see OS#3653.
+ * TODO: also generate this list dynamically from module parameters. */
if (mp_bts_trxc_port != -1) {
g_AllChanTypes := {
/* TS 1..4: TCH/F */
@@ -473,10 +583,19 @@ friend function f_init() runs on test_CT {
valueof(ts_RslChanNr_SDCCH8(6,4))
};
}
+
+ g_AllChannels := { };
+
+ /* Generate list of all logical channels from module parameters */
+ for (var integer tn := 0; tn < lengthof(trx_pars.ts); tn := tn + 1) {
+ var PchanConfig config := trx_pars.ts[tn].config;
+ g_AllChannels := g_AllChannels & f_gen_chans_for_ts(tn, config);
+ }
+
f_init_rsl(id);
f_sleep(0.5); /* workaround for OS#3000 */
f_init_vty(id);
- f_ipa_ctrl_start(mp_ctrl_ip, mp_ctrl_port);
+ f_ipa_ctrl_start_client(mp_ctrl_ip, mp_ctrl_port);
/* Send SI3 to the BTS, it is needed for various computations */
f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
@@ -484,9 +603,6 @@ friend function f_init() runs on test_CT {
f_rsl_bcch_fill(RSL_SYSTEM_INFO_2, ts_SI2_default);
f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
- map(self:PCU, system:PCU);
- f_init_pcu(PCU, id, g_pcu_conn_id, g_pcu_last_info);
-
if (mp_bts_trxc_port != -1) {
var TrxcMessage ret;
@@ -495,10 +611,10 @@ friend function f_init() runs on test_CT {
f_init_trxc(BTS_TRXC, id, g_bts_trxc_conn_id);
/* Start with a default moderate timing offset equalling TA=2, and RSSI=-60 */
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(2*256)));
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(-60)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_TIMING(2*256));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_RSSI(-60));
/* OsmoBTS may have different AB / NB threshold (see MIN_QUAL_NORM, MIN_QUAL_RACH) */
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_CI(60)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_CI(60));
}
/* Wait some extra time to make sure the BTS emits a stable carrier.
@@ -512,7 +628,7 @@ friend function f_init_l1ctl() runs on test_CT {
f_connect_reset(L1CTL);
}
-private type function void_fn(charstring id) runs on ConnHdlr;
+friend type function void_fn(charstring id) runs on ConnHdlr;
private type record length(8) of FreqHopGroups FreqHopConfig;
@@ -528,30 +644,41 @@ private type record FreqHopGroupItem {
uint6_t maio
};
-friend function f_resolve_fh_params(inout ConnHdlrPars pars, uint8_t trx_nr := 0)
+friend function f_resolve_fh_params(inout FreqHopPars fhp, uint8_t tn,
+ uint8_t trx_nr := 0)
{
- var FreqHopGroups groups := mp_fh_config[pars.chan_nr.tn];
+ var FreqHopGroups groups := mp_fh_config[tn];
var integer i, j;
+ fhp.enabled := false;
+
for (i := 0; i < lengthof(groups); i := i + 1) {
var FreqHopGroup g := groups[i];
for (j := 0; j < lengthof(g.trx_maio); j := j + 1) {
var FreqHopGroupItem gi := g.trx_maio[j];
if (gi.trx_nr == trx_nr) {
- pars.maio_hsn := valueof(ts_HsnMaio(g.hsn, gi.maio));
- pars.ma := { }; /* to be composed below */
+ fhp.maio_hsn.maio := gi.maio;
+ fhp.maio_hsn.hsn := g.hsn;
+ fhp.enabled := true;
break;
}
}
- if (ispresent(pars.maio_hsn)) {
- /* Compose the Mobile Allocation */
+ if (fhp.enabled) {
+ /* Prepare the Mobile Allocation bitmask (length & padding) */
+ fhp.ma_map.len := (mp_transceiver_num + 8 - 1) / 8; /* in bytes */
+ fhp.ma_map.ma := f_pad_bit('0'B, fhp.ma_map.len * 8, '0'B);
+ fhp.ma := { }; /* to be composed below */
+
+ /* Compose the actual Mobile Allocation and the bitmask */
for (j := 0; j < lengthof(g.trx_maio); j := j + 1) {
var FreqHopGroupItem gi := g.trx_maio[j];
- pars.ma := pars.ma & { l1ctl_ma_def[gi.trx_nr] };
+ var GsmArfcn arfcn := mp_trx_pars[gi.trx_nr].arfcn;
+ fhp.ma := fhp.ma & { valueof(ts_GsmBandArfcn(arfcn)) };
+ fhp.ma_map.ma[gi.trx_nr] := '1'B;
}
- log("Freq. hopping parameters: ", pars.maio_hsn, pars.ma);
+ log("Freq. hopping parameters: ", fhp);
break; /* We're done */
}
}
@@ -560,7 +687,8 @@ friend function f_resolve_fh_params(inout ConnHdlrPars pars, uint8_t trx_nr := 0
/* create a new test component */
friend function f_start_handler(void_fn fn, ConnHdlrPars pars,
boolean pcu_comp := false,
- boolean trxc_comp := false)
+ boolean trxc_comp := false,
+ boolean l1ctl := true)
runs on test_CT return ConnHdlr {
var charstring id := testcasename();
var ConnHdlr vc_conn;
@@ -581,10 +709,13 @@ runs on test_CT return ConnHdlr {
unmap(self:BTS_TRXC, system:BTS_TRXC);
map(vc_conn:BTS_TRXC, system:BTS_TRXC);
}
+ if (l1ctl) {
+ map(vc_conn:L1CTL, system:L1CTL);
+ }
/* Obtain frequency hopping parameters for a given timeslot */
if (mp_freq_hop_enabled and mp_transceiver_num > 1) {
- f_resolve_fh_params(pars);
+ f_resolve_fh_params(pars.fhp, pars.chan_nr.tn);
}
vc_conn.start(f_handler_init(fn, id, pars));
@@ -598,17 +729,18 @@ private altstep as_Tguard() runs on ConnHdlr {
}
friend function f_l1_tune(L1CTL_PT L1CTL, L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED) {
- f_L1CTL_FBSB(L1CTL, { false, mp_trx0_arfcn }, ccch_mode, mp_rxlev_exp);
+ var GsmBandArfcn arfcn := valueof(ts_GsmBandArfcn(mp_trx_pars[0].arfcn));
+ f_L1CTL_FBSB(L1CTL, arfcn, ccch_mode, mp_rxlev_exp);
}
private function f_trxc_fake_rssi(TRXC_RSSI rssi) runs on ConnHdlr {
var TrxcMessage ret;
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_RSSI(rssi)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_RSSI(rssi));
}
private function f_trxc_fake_toffs256(int16_t toffs256) runs on ConnHdlr {
var TrxcMessage ret;
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_TIMING(toffs256));
}
/* first function started in ConnHdlr component */
@@ -617,8 +749,9 @@ runs on ConnHdlr {
g_pars := pars;
g_chan_nr := pars.chan_nr;
- map(self:L1CTL, system:L1CTL);
- f_connect_reset(L1CTL);
+ if (L1CTL.checkstate("Mapped")) {
+ f_connect_reset(L1CTL);
+ }
if (mp_bts_trxc_port != -1 and BTS_TRXC.checkstate("Mapped")) {
f_init_trxc(BTS_TRXC, id, g_bts_trxc_conn_id);
@@ -627,7 +760,7 @@ runs on ConnHdlr {
g_Tguard.start(pars.t_guard);
activate(as_Tguard());
- f_rslem_register(0, pars.chan_nr);
+ f_rslem_register(pars.trx_nr, pars.chan_nr);
/* call the user-supplied test case function */
fn.apply(id);
@@ -648,11 +781,15 @@ runs on ConnHdlr return RSL_Message {
[] T.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout expecting " & id);
}
- [not ignore_other] as_l1_sacch();
+ [not ignore_other] as_l1_sacch_loop();
[not ignore_other] as_meas_res();
- [not ignore_other] as_l1_dcch();
+ [not ignore_other] as_l1_dcch_loop();
+ [not ignore_other] as_l1_tch_loop();
+ [not ignore_other] RSL.receive(RSL_Message:?) -> value rx {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx unexpected RSL port message: ", rx));
+ }
[not ignore_other] RSL.receive {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RSL message received");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx unexpected RSL port message");
}
[ignore_other] RSL.receive { repeat; }
}
@@ -665,6 +802,68 @@ runs on ConnHdlr {
var RSL_Message rx := f_rsl_transceive_ret(tx, exp_rx, id, ignore_other);
}
+/* Send the given measurement results to the IUT over the Um interface */
+friend function f_send_meas_rep(template (value) MeasurementResults meas_res)
+runs on ConnHdlr {
+ var template (value) SacchL1Header l1h;
+
+ l1h := ts_SacchL1Header(g_pars.l1_pars.ms_power_level, g_pars.l1_pars.ms_actual_ta);
+ f_send_meas_rep_l1h(meas_res, l1h);
+}
+
+/* Send the given measurement results and L1H to the IUT over the Um interface */
+friend function f_send_meas_rep_l1h(template (value) MeasurementResults meas_res,
+ template (value) SacchL1Header l1h)
+runs on ConnHdlr {
+ var octetstring l2;
+
+ /* RR Measurement Report to be sent */
+ var GsmRrL3Message meas_rep := {
+ header := valueof(t_RrL3Header(MEASUREMENT_REPORT)),
+ payload := { meas_rep := { meas_res := valueof(meas_res) } }
+ };
+
+ /* TITAN has weird (and often unusable) padding model, so we pad here manaully */
+ l2 := f_pad_oct(enc_LapdmFrameAB(valueof(ts_LAPDm_AB(0, meas_rep))), 21, '00'O);
+
+ log(%definitionId, "(): Tx SACCH L1 header: ", l1h);
+
+ /* Send RR Measurement Report over the Um interface */
+ L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), l1h, l2));
+}
+
+/* Send the given measurement results to the IUT over the Um interface,
+ * wait for the IUT to receive then and forward over the A-bis/RSL interface. */
+friend function f_transceive_meas_rep(template (value) MeasurementResults meas_res)
+runs on ConnHdlr {
+ var octetstring l3;
+ timer T;
+
+ /* RR Measurement Report to be sent */
+ var GsmRrL3Message meas_rep := {
+ header := valueof(t_RrL3Header(MEASUREMENT_REPORT)),
+ payload := { meas_rep := { meas_res := valueof(meas_res) } }
+ };
+
+ /* TITAN has weird (and often unusable) padding model, so we pad here manaully */
+ l3 := f_pad_oct(enc_GsmRrL3Message(meas_rep), 18, '00'O);
+
+ f_send_meas_rep(meas_res);
+
+ /* Expect MEASurement RESult on the A-bis/RSL interface */
+ T.start(2.0);
+ alt {
+ [] RSL.receive(tr_RSL_MEAS_RES_OSMO(g_chan_nr, l3_info := l3)) {
+ setverdict(pass);
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL MEASurement RESult");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+}
+
friend function f_rsl_chan_act(RSL_IE_ChannelMode mode,
boolean encr_enable := false,
RSL_IE_List more_ies := {},
@@ -678,6 +877,10 @@ runs on ConnHdlr {
ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_ENCR_INFO, RSL_IE_Body:{encr_info :=
encr_info})) };
}
+ if (ischosen(mode.u.speech) and mode.u.speech == RSL_CMOD_SP_GSM3) {
+ ch_act.ies := ch_act.ies & { valueof(t_RSL_IE(RSL_IE_MR_CONFIG,
+ RSL_IE_Body:{multirate_cfg := g_pars.mr_conf})) };
+ }
ch_act.ies := ch_act.ies & more_ies;
f_rsl_transceive(ch_act, tr_RSL_CHAN_ACT_ACK(g_chan_nr), "RSL CHAN ACT");
}
@@ -687,20 +890,19 @@ friend function f_rsl_chan_deact() runs on ConnHdlr {
"RF CHAN REL", true);
}
-/* Default Mobile Allocation to be used for frequency hopping */
-private const L1ctlMA l1ctl_ma_def := { { false, mp_trx0_arfcn }, { false, mp_trx1_arfcn },
- { false, mp_trx2_arfcn }, { false, mp_trx3_arfcn } };
-
friend template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
- template RSL_IE_ChannelMode chan_mode,
- template (omit) MaioHsn maio_hsn := omit,
- float t_guard := 20.0) := {
+ template RSL_IE_ChannelMode chan_mode,
+ template (omit) TestSpecUnion spec := omit,
+ uint8_t trx_nr := 0, float t_guard := 20.0) := {
+ trx_nr := trx_nr,
chan_nr := valueof(chan_nr),
chan_mode := valueof(chan_mode),
+ mr_conf := omit,
t_guard := t_guard,
l1_pars := {
dtx_enabled := false,
toa256_enabled := false,
+ meas_valid := true,
meas_ul := {
full := {
rxlev := mp_ul_rxlev_exp,
@@ -714,14 +916,98 @@ friend template ConnHdlrPars t_Pars(template RslChannelNr chan_nr,
timing_offset_256syms := mp_timing_offset_256syms_exp,
bs_power_level := 0,
ms_power_level := mp_ms_power_level_exp,
- ms_actual_ta := mp_ms_actual_ta_exp
+ ms_actual_ta := mp_ms_actual_ta_exp,
+ facch_enabled := false
},
- spec := omit,
+ spec := spec,
encr := omit,
bts0_band := omit,
- maio_hsn := maio_hsn,
- ma_map := c_MA_null,
- ma := l1ctl_ma_def
+ tsc := mp_tsc_def,
+ fhp := {
+ enabled := false,
+ maio_hsn := ts_HsnMaio(0, 0),
+ ma_map := c_MA_null,
+ ma := { }
+ },
+ loc_osmux_cid := trx_nr,
+ rem_osmux_cid := omit
+}
+
+/* This altstep triggers on receipt of a L1CTL DATA.ind matching the given
+ * RSL chan_nr/link_id and data templates. Used as a base for other altsteps. */
+private altstep as_l1ctl_dl_msg(out L1ctlMessage msg,
+ template (present) octetstring tr_data := ?,
+ template (present) RslChannelNr chan_nr := ?,
+ template (present) RslLinkId link_id := ?)
+runs on ConnHdlr {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(chan_nr, link_id, tr_data)) -> value msg;
+}
+
+/* This altstep is built on top of as_l1ctl_dl_msg(), and triggers on receipt
+ * of dummy LAPDm func=UI frames with empty payload. Repeats by default. */
+private altstep as_dl_lapdm_dummy(template (present) RslChannelNr chan_nr := ?,
+ template (present) RslLinkId link_id := ?,
+ template (present) LapdmSapi sapi := ?,
+ boolean do_repeat := true)
+runs on ConnHdlr {
+ template (present) LapdmFrame tr_frame := tr_LAPDm_UI(sapi, true, ''O);
+ var L1ctlMessage dl_msg;
+
+ [] as_l1ctl_dl_msg(dl_msg, decmatch tr_frame, chan_nr, link_id) {
+ if (do_repeat) {
+ repeat;
+ }
+ }
+}
+
+/* This altstep triggers on receipt of a Downlink DCCH containing a L2 payload
+ * that matches the given LAPDm frame. The L2 is treated as LapdmFrameAB. */
+private altstep as_dl_dcch_lapdm_ab(out LapdmFrameAB frame,
+ template (present) LapdmFrameAB tr_frame := ?,
+ template (present) RslLinkId link_id := ?)
+runs on ConnHdlr {
+ var L1ctlMessage dl_msg;
+
+ [] as_l1ctl_dl_msg(dl_msg, decmatch tr_frame, g_chan_nr, link_id) {
+ frame := dec_LapdmFrameAB(dl_msg.payload.data_ind.payload);
+ }
+}
+
+/* This altstep triggers on receipt of a Downlink SACCH containing a L2 payload
+ * that matches the given LAPDm frame, as well as the given SACCH L1 header. */
+private altstep as_dl_sacch_lapdm_ab(out SacchL1Header l1h, out LapdmFrameAB frame,
+ template (present) LapdmFrameAB tr_frame := ?,
+ template (present) SacchL1Header tr_l1h := ?,
+ template (present) GsmSapi sapi := ?)
+runs on ConnHdlr {
+ var L1ctlMessage dl_msg;
+ template (present) RslLinkId link_id := tr_RslLinkID_SACCH(sapi);
+ template (present) L1ctlDataReq tr_data := {
+ l1header := tr_l1h,
+ l2_payload := decmatch tr_frame
+ };
+
+ [] as_l1ctl_dl_msg(dl_msg, decmatch tr_data, g_chan_nr, link_id) {
+ var octetstring data := dl_msg.payload.data_ind.payload;
+ l1h := dec_SacchL1Header(substr(data, 0, 2));
+ frame := dec_LapdmFrameAB(substr(data, 2, lengthof(data) - 2));
+ }
+}
+
+/* This altstep is built on top of as_dl_dcch_lapdm_ab(), and triggers on receipt
+ * of a LAPDm AB frame with a L3 payload matching the given template. The L3
+ * payload is treated as PDU_ML3_NW_MS. */
+private altstep as_dl_dcch_pdu(out PDU_ML3_NW_MS pdu,
+ template (present) PDU_ML3_NW_MS tr_pdu := ?,
+ template (present) GsmSapi sapi := 0)
+runs on ConnHdlr {
+ template (present) LapdmFrame tr_frame := tr_LAPDm_UI(sapi, true, decmatch tr_pdu);
+ template (present) RslLinkId link_id := tr_RslLinkID_DCCH(sapi);
+ var LapdmFrameAB lapdm_frame;
+
+ [] as_dl_dcch_lapdm_ab(lapdm_frame, tr_frame.ab, link_id) {
+ pdu := dec_PDU_ML3_NW_MS(lapdm_frame.payload);
+ }
}
/***********************************************************************
@@ -925,9 +1211,10 @@ testcase TC_deact_sacch() runs on test_CT {
}
/* verify that given SACCH payload is present */
-private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
- var L1ctlDlMessage dl;
- /* check that the specified SI5 value is actually sent */
+private function f_sacch_present(template octetstring l3_exp,
+ boolean do_fail := true)
+runs on ConnHdlr {
+ var L1ctlMessage dl;
timer T_sacch := 3.0;
L1CTL.clear;
T_sacch.start;
@@ -941,16 +1228,19 @@ private function f_sacch_present(template octetstring l3_exp) runs on ConnHdlr {
}
}
[] L1CTL.receive { repeat; }
- [] T_sacch.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Timeout waiting for SACCH ", l3_exp));
+ [not do_fail] T_sacch.timeout {
+ log("Timeout waiting for SACCH ", l3_exp);
+ }
+ [do_fail] T_sacch.timeout {
+ setverdict(fail, "Timeout waiting for SACCH ", l3_exp);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
}
}
/* verify that given SACCH payload is not present */
private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
- var L1ctlDlMessage dl;
- /* check that the specified SI5 value is actually sent */
+ var L1ctlMessage dl;
timer T_sacch := 3.0;
L1CTL.clear;
T_sacch.start;
@@ -958,7 +1248,8 @@ private function f_sacch_missing(template octetstring l3_exp) runs on ConnHdlr {
[] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(0))) -> value dl {
var octetstring l3 := substr(dl.payload.data_ind.payload, 4, 19);
if (match(l3, l3_exp)) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Received unexpected SACCH ", dl));
+ setverdict(fail, "Received unexpected SACCH ", dl);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
} else {
repeat;
}
@@ -1191,14 +1482,22 @@ testcase TC_sacch_chan_act() runs on test_CT {
* see section 4.1.3 of 3GPP TS 48.058 */
private function f_TC_sacch_chan_act_ho_async(charstring id) runs on ConnHdlr {
var octetstring si5 := f_rnd_octstring(19);
+ RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
f_l1_tune(L1CTL);
RSL.clear;
/* Step 1: Activate ASYNC HO channel without MS power IE */
+ var integer ho_ref := oct2int(f_rnd_octstring(1));
+ var RSL_IE ho_ref_ie := valueof(t_RSL_IE(RSL_IE_HANDO_REF,
+ RSL_IE_Body:{ handover_ref := ho_ref }));
+ var RSL_IE_List addl_ies := {
+ ho_ref_ie
+ };
+
/* Activate channel on BTS side */
- f_rsl_chan_act(g_pars.chan_mode, act_type := t_RSL_IE_ActType_HO_ASYNC);
+ f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_ASYNC);
/* don't perform immediate assignment here, as we're testing non-IA case */
/* enable dedicated mode */
f_l1ctl_est_dchan(L1CTL, g_pars);
@@ -1206,14 +1505,24 @@ private function f_TC_sacch_chan_act_ho_async(charstring id) runs on ConnHdlr {
/* Verify that no DL SACCH is being received */
f_sacch_missing(?);
+ /* Send handover Access Burst and expect SACCH to start */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ f_sacch_present(si5);
+
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_L1CTL_RESET(L1CTL);
+
+ /* Tune back to CCCH/BCCH */
+ f_l1_tune(L1CTL);
/* Step 2: Activate ASYNC HO channel with MS power IE */
/* Activate channel on BTS side */
- var RSL_IE_List addl_ies := {
+ addl_ies := {
+ ho_ref_ie,
valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
};
f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_ASYNC);
@@ -1221,7 +1530,13 @@ private function f_TC_sacch_chan_act_ho_async(charstring id) runs on ConnHdlr {
/* enable dedicated mode */
f_l1ctl_est_dchan(L1CTL, g_pars);
- /* Verify that DL SACCH is being received */
+ /* 4.1.3 "If the MS Power IE is present the BTS *may* start transmission
+ * also on the SACCH". "May" does not mean "shall", so osmo-bts does not. */
+ f_sacch_present(si5, do_fail := false);
+
+ /* Send handover Access Burst and expect SACCH to remain present */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
f_sacch_present(si5);
f_rsl_chan_deact();
@@ -1232,9 +1547,9 @@ testcase TC_sacch_chan_act_ho_async() runs on test_CT {
var ConnHdlrPars pars;
f_init();
- for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
- pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
- log(testcasename(), ": Starting for ", g_AllChannels[i]);
+ for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
+ pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
+ log(testcasename(), ": Starting for ", g_AllChanTypes[i]);
vc_conn := f_start_handler(refers(f_TC_sacch_chan_act_ho_async), pars);
vc_conn.done;
}
@@ -1246,6 +1561,8 @@ testcase TC_sacch_chan_act_ho_async() runs on test_CT {
* see section 4.1.4 of 3GPP TS 48.058 */
private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
var octetstring si5 := f_rnd_octstring(19);
+ RSL.send(ts_RSL_SACCH_FILL(RSL_SYSTEM_INFO_5, si5));
+
var RSL_IE_List addl_ies;
f_l1_tune(L1CTL);
@@ -1253,8 +1570,15 @@ private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
/* Step 1: Activate SYNC HO channel without MS power IE */
+ var integer ho_ref := oct2int(f_rnd_octstring(1));
+ var RSL_IE ho_ref_ie := valueof(t_RSL_IE(RSL_IE_HANDO_REF,
+ RSL_IE_Body:{ handover_ref := ho_ref }));
+ addl_ies := {
+ ho_ref_ie
+ };
+
/* Activate channel on BTS side */
- f_rsl_chan_act(g_pars.chan_mode, act_type := t_RSL_IE_ActType_HO_SYNC);
+ f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
/* don't perform immediate assignment here, as we're testing non-IA case */
/* enable dedicated mode */
f_l1ctl_est_dchan(L1CTL, g_pars);
@@ -1262,14 +1586,24 @@ private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
/* Verify that no DL SACCH is being received */
f_sacch_missing(?);
+ /* Send handover Access Burst and expect SACCH to start */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ f_sacch_present(si5);
+
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_L1CTL_RESET(L1CTL);
+
+ /* Tune back to CCCH/BCCH */
+ f_l1_tune(L1CTL);
/* Step 2a: Activate SYNC HO channel with only MS power IE */
/* Activate channel on BTS side */
addl_ies := {
+ ho_ref_ie,
valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
};
f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
@@ -1277,17 +1611,28 @@ private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
/* enable dedicated mode */
f_l1ctl_est_dchan(L1CTL, g_pars);
- /* Verify that no DL SACCH is being received */
- f_sacch_missing(?);
+ /* 4.1.4 "If only the MS Power IE is present the BTS *may* start transmission
+ * also on the SACCH". "May" does not mean "shall", so osmo-bts does not. */
+ f_sacch_present(si5, do_fail := false);
+
+ /* Send handover Access Burst and expect SACCH to remain present */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ f_sacch_present(si5);
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_L1CTL_RESET(L1CTL);
+
+ /* Tune back to CCCH/BCCH */
+ f_l1_tune(L1CTL);
/* Step 2b: Activate SYNC HO channel with TA IE */
/* Activate channel on BTS side */
addl_ies := {
+ ho_ref_ie,
valueof(t_RSL_IE(RSL_IE_TIMING_ADVANCE, RSL_IE_Body:{timing_adv := 0}))
};
f_rsl_chan_act(g_pars.chan_mode, more_ies := addl_ies, act_type := t_RSL_IE_ActType_HO_SYNC);
@@ -1298,14 +1643,24 @@ private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
/* Verify that no DL SACCH is being received */
f_sacch_missing(?);
+ /* Send handover Access Burst and expect SACCH to start */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ f_sacch_present(si5);
+
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_L1CTL_RESET(L1CTL);
+
+ /* Tune back to CCCH/BCCH */
+ f_l1_tune(L1CTL);
/* Step 3: Activate SYNC HO channel with MS power IE and TA IE */
/* Activate channel on BTS side */
addl_ies := {
+ ho_ref_ie,
valueof(t_RSL_IE(RSL_IE_TIMING_ADVANCE, RSL_IE_Body:{timing_adv := 0})),
valueof(t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ms_power := ts_RSL_IE_MS_Power(0)}))
};
@@ -1317,6 +1672,11 @@ private function f_TC_sacch_chan_act_ho_sync(charstring id) runs on ConnHdlr {
/* Verify that DL SACCH is being received */
f_sacch_present(si5);
+ /* Send handover Access Burst and expect SACCH to remain present */
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ f_sacch_present(si5);
+
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
}
@@ -1325,9 +1685,9 @@ testcase TC_sacch_chan_act_ho_sync() runs on test_CT {
var ConnHdlrPars pars;
f_init();
- for (var integer i := 0; i < sizeof(g_AllChannels); i := i+1) {
- pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
- log(testcasename(), ": Starting for ", g_AllChannels[i]);
+ for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i+1) {
+ pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
+ log(testcasename(), ": Starting for ", g_AllChanTypes[i]);
vc_conn := f_start_handler(refers(f_TC_sacch_chan_act_ho_sync), pars);
vc_conn.done;
}
@@ -1340,55 +1700,6 @@ testcase TC_sacch_chan_act_ho_sync() runs on test_CT {
* RACH Handling
***********************************************************************/
-/* like L1SAP_IS_PACKET_RACH */
-private function ra_is_ps(OCT1 ra) return boolean {
- if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
- return true;
- }
- return false;
-}
-
-private function ra_is_emerg(OCT1 ra) return boolean {
- /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
- if ((ra and4b 'E0'O == 'A0'O) and (ra and4b '1F'O != '1F'O)) {
- return true;
- }
- return false;
-}
-
-/* generate a random RACH for circuit-switched */
-private function f_rnd_ra_cs() return OCT1 {
- var OCT1 ra;
- do {
- ra := f_rnd_octstring(1);
- } while (ra_is_ps(ra));
- return ra;
-}
-
-/* generate a random RACH for emergency */
-private function f_rnd_ra_emerg() return OCT1 {
- var OCT1 ra;
- do {
- ra := f_rnd_octstring(1);
- } while (not ra_is_emerg(ra));
- return ra;
-}
-
-/* generate a random RACH for packet-switched */
-private function f_rnd_ra_ps() return OCT1 {
- var OCT1 ra;
- do {
- ra := f_rnd_octstring(1);
- } while (not ra_is_ps(ra));
- return ra;
-}
-
-/* generate a random 11-bit RA (packet-switched only) */
-private function f_rnd_ra11_ps() return BIT11 {
- var integer ra11 := f_rnd_int(bit2int('11111111111'B));
- return int2bit(ra11, 11);
-}
-
/* Send 1000 RACH requests and check their RA+FN on the RSL side */
private function f_TC_rach_content(boolean emerg) runs on test_CT {
f_init();
@@ -1398,7 +1709,7 @@ private function f_TC_rach_content(boolean emerg) runs on test_CT {
var GsmFrameNumber fn_last := 0;
var boolean test_failed := false;
for (var integer i := 0; i < 1000; i := i+1) {
- var OCT1 ra := f_rnd_ra_emerg();
+ var OCT1 ra;
if (emerg == true) {
ra := f_rnd_ra_emerg();
} else {
@@ -1499,6 +1810,12 @@ testcase TC_rach_load_idle_thresh0() runs on test_CT {
f_init();
+ /* Skip the first RACH LOAD IND, as it may not have the full slot count (BTS started less than 1s before) */
+ alt {
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RACH_LOAD_IND(?, ?, ?))) { }
+ [] RSL_CCHAN.receive { repeat }
+ }
+
timer T := 5.0;
T.start;
alt {
@@ -1561,6 +1878,12 @@ testcase TC_rach_load_count() runs on test_CT {
f_sleep(1.0);
f_l1_tune(L1CTL);
+ /* Skip the first RACH LOAD IND, as it may not have the full slot count (BTS started less than 1s before) */
+ alt {
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RACH_LOAD_IND(?, ?, ?))) { }
+ [] RSL_CCHAN.receive { repeat }
+ }
+
var GsmFrameNumber fn_last := 0;
for (var integer i := 0; i < 1000; i := i+1) {
var OCT1 ra := f_rnd_ra_cs();
@@ -1606,7 +1929,7 @@ testcase TC_rach_load_count() runs on test_CT {
private function f_rach_toffs(int16_t toffs256, boolean expect_pass) runs on test_CT {
var TrxcMessage ret;
/* tell fake_trx to use a given timing offset for all bursts */
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, valueof(ts_TRXC_FAKE_TIMING(toffs256)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_TIMING(toffs256));
f_sleep(0.5);
/* Transmit RACH request + wait for confirmation */
@@ -1727,11 +2050,100 @@ testcase TC_ho_rach() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+/* Test sending of the RR Physical Information message on DCCH */
+private function f_TC_ho_physical_info(charstring id) runs on ConnHdlr {
+ var PDU_ML3_NW_MS dcch_pdu;
+ var integer count := 0;
+ var L1ctlMessage dl;
+ timer T;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* Generate a random Handover Reference */
+ var integer ho_ref := oct2int(f_rnd_octstring(1));
+
+ /* Handover Reference IE (see 3GPP TS 48.058, 9.3.9) */
+ var RSL_IE ho_ref_ie := valueof(t_RSL_IE(RSL_IE_HANDO_REF,
+ RSL_IE_Body:{ handover_ref := ho_ref }));
+
+ /* Activate a channel on the BTS side (no encryption) */
+ f_rsl_chan_act(g_pars.chan_mode, more_ies := { ho_ref_ie },
+ act_type := t_RSL_IE_ActType_HO_SYNC);
+
+ /* Switch the MS side (e.g. trxcon) to a dedicated channel without
+ * waiting for Immediate Assignment and sending of an Access Burst. */
+ f_l1ctl_est_dchan(L1CTL, g_pars); /* FIXME: disable Uplink Tx */
+
+ /* Expect nothing to be transmitted on Downlink DCCH. Nothing in this
+ * context means any L2 frames, not only the RR Physical Information. */
+ T.start(2.0);
+ L1CTL.clear;
+ alt {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value dl {
+ setverdict(fail, "Rx unexpected Downlink DCCH (before handover RACH): ", dl);
+ T.stop;
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout { setverdict(pass); }
+ }
+
+ /* Send handover Access Burst */
+ log("Sending handover Access Burst");
+ f_L1CTL_RACH(L1CTL, ho_ref, chan_nr := g_pars.chan_nr);
+
+ /* Expect RR Physical Information being sent on Downlink DCCH Ny1 times */
+ T.start(int2float(mp_ho_t3105_ms * mp_ho_ny1) / 1000.0 + 1.0);
+ L1CTL.clear;
+ alt {
+ [] as_dl_lapdm_dummy(); /* Ignore empty LAPDm func=UI frames */
+ [] as_dl_dcch_pdu(dcch_pdu, tr_RRM_PhysicalInfo) {
+ log("Rx RR Physical Information: ", dcch_pdu);
+ /* Wait until the count reaches Ny1 */
+ count := count + 1;
+ if (count < mp_ho_ny1)
+ { repeat; }
+ setverdict(pass);
+ }
+ [] as_dl_dcch_pdu(dcch_pdu, ?) {
+ setverdict(fail, "Rx unexpected DCCH PDU: ", dcch_pdu);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RR Physical Information");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Release the channel */
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+}
+testcase TC_ho_physical_info() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i + 1) {
+ pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
+ log(testcasename(), ": Starting for ", g_AllChanTypes[i]);
+ vc_conn := f_start_handler(refers(f_TC_ho_physical_info), pars);
+ vc_conn.done;
+ }
+
+ /* TODO: do the above in parallel, rather than sequentially? */
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/***********************************************************************
* Measurement Processing / Reporting
***********************************************************************/
-private template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) := {
+private template (value) LapdmAddressField
+ts_LapdmAddr(template (value) LapdmSapi sapi,
+ template (value) boolean c_r) := {
spare := '0'B,
lpd := 0,
sapi := sapi,
@@ -1739,39 +2151,70 @@ private template LapdmAddressField ts_LapdmAddr(LapdmSapi sapi, boolean c_r) :=
ea := true
}
-private template LapdmFrameAB ts_LAPDm_AB(LapdmSapi sapi, boolean c_r, boolean p, octetstring pl) := {
+private template (value) LapdmFrameAB
+ts_LAPDm_AB(template (value) LapdmSapi sapi,
+ template (value) GsmRrL3Message l3,
+ template (value) boolean c_r := false,
+ template (value) boolean p := false) := {
addr := ts_LapdmAddr(sapi, c_r),
- ctrl := ts_LapdmCtrlUI(p),
+ ctrl := ts_LapdmCtrlUI(valueof(p)),
len := 0, /* overwritten */
m := false,
el := 1,
- payload := pl
+ payload := enc_GsmRrL3Message(valueof(l3)),
+ padding := ''O
}
/* handle incoming downlink SACCH and respond with uplink SACCH (meas res) */
-private altstep as_l1_sacch() runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+private altstep as_l1_sacch_loop() runs on ConnHdlr {
+ var template (value) LapdmFrameAB lb;
+ var L1ctlMessage l1_dl;
+
[] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
log("SACCH received: ", l1_dl.payload.data_ind.payload);
- var GsmRrL3Message meas_rep := valueof(ts_MEAS_REP(true, mp_rxlev_exp, mp_rxlev_exp, 0, 0, omit));
- var LapdmFrameAB lb := valueof(ts_LAPDm_AB(0, false, false, enc_GsmRrL3Message(meas_rep)));
+
+ lb := ts_LAPDm_AB(0, ts_MEAS_REP(g_pars.l1_pars.meas_valid,
+ g_pars.l1_pars.meas_ul.full.rxlev,
+ g_pars.l1_pars.meas_ul.sub.rxlev,
+ g_pars.l1_pars.meas_ul.full.rxqual,
+ g_pars.l1_pars.meas_ul.sub.rxqual));
log("LAPDm: ", lb);
var template (value) SacchL1Header l1h := ts_SacchL1Header(
- g_pars.l1_pars.ms_power_level, false,
- g_pars.l1_pars.ms_actual_ta);
+ g_pars.l1_pars.ms_power_level, g_pars.l1_pars.ms_actual_ta);
- /* TODO: we can use an extension of TTCN-3 for that, i.e. PADDING('2B'O) */
- var octetstring l2 := f_pad_oct(enc_LapdmFrameAB(lb), 21, '2B'O);
+ /* According to 3GPP TS 44.018, section 10.5.2.20, we should pad with zeroes */
+ var octetstring l2 := f_pad_oct(enc_LapdmFrameAB(valueof(lb)), 21, '00'O);
log("Sending Measurement Report: ", l1h, l2);
L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, ts_RslLinkID_SACCH(0), l1h, l2));
repeat;
}
+ /* dequeue (ignore) L1CTL DATA.cnf for UL SACCH (SAPI=0) */
+ [] L1CTL.receive(tr_L1CTL_DATA_CONF(g_chan_nr, tr_RslLinkID_SACCH(0))) { repeat; }
}
-private altstep as_l1_dcch() runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+/* handle incoming downlink SACCH, decode the L1 header into the given record */
+private altstep as_l1_sacch_l1h(inout SacchL1Header l1h,
+ boolean do_apply := true)
+runs on ConnHdlr
+{
+ var L1ctlMessage l1_dl;
+
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
+ /* Parse the L1 SACCH header (MS Power Level & Timing Advance) */
+ l1h := dec_SacchL1Header(substr(l1_dl.payload.data_ind.payload, 0, 2));
+ log(%definitionId, "(): Rx SACCH L1 header: ", l1h);
+
+ if (do_apply) {
+ /* Update TA and MS power to follow what BTS requests */
+ f_L1CTL_PARAM(L1CTL, l1h.actual_ta, l1h.ms_power_lvl);
+ }
+ }
+}
+
+private altstep as_l1_dcch_loop() runs on ConnHdlr {
+ var L1ctlMessage l1_dl;
[] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_DCCH(?))) -> value l1_dl {
log("DCCH received: ", l1_dl.payload.data_ind.payload);
var octetstring pl := '010301'O;
@@ -1779,6 +2222,30 @@ private altstep as_l1_dcch() runs on ConnHdlr {
f_pad_oct(pl, 23, '2B'O)));
repeat;
}
+ /* dequeue (ignore) L1CTL DATA.cnf for UL DCCH (SAPI=0) */
+ [] L1CTL.receive(tr_L1CTL_DATA_CONF(g_chan_nr, tr_RslLinkID_DCCH(0))) { repeat; }
+}
+
+private altstep as_l1_tch_loop() runs on ConnHdlr {
+ var L1ctlMessage l1_dl;
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr)) -> value l1_dl {
+ var octetstring data := l1_dl.payload.traffic_ind.data;
+ log("TCH received (len=", lengthof(data), "): ", data);
+
+ /* occasionaly inject FACCH frames into the uplink */
+ if (g_pars.l1_pars.facch_enabled == true and l1_dl.dl_info.frame_nr mod 5 == 0) {
+ var octetstring pl := '010301'O;
+ L1CTL.send(ts_L1CTL_DATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0),
+ f_pad_oct(pl, 23, '2B'O)));
+ } else {
+ L1CTL.send(ts_L1CTL_TRAFFIC_REQ(g_chan_nr, l1_dl.dl_info.link_id,
+ l1_dl.payload.traffic_ind.data));
+ }
+
+ repeat;
+ }
+ /* dequeue (ignore) L1CTL TRAFFIC.cnf for UL TCH */
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_CONF(g_chan_nr, tr_RslLinkID_DCCH(0))) { repeat; }
}
private type record MeasElem {
@@ -1794,11 +2261,13 @@ private type record MeasElemFS {
private type record ConnL1Pars {
boolean dtx_enabled,
boolean toa256_enabled,
+ boolean meas_valid,
MeasElemFS meas_ul,
int16_t timing_offset_256syms,
uint4_t bs_power_level,
uint5_t ms_power_level,
- uint8_t ms_actual_ta
+ uint8_t ms_actual_ta,
+ boolean facch_enabled
}
/* Convert tiing offset from 1/256th symbol to RSL Timing Offset */
@@ -2043,64 +2512,224 @@ private function f_rach_req_wait_chan_rqd(integer ra) runs on ConnHdlr return Gs
}
/* Tune to a dedicated channel: L1CTL only */
-private function f_l1ctl_est_dchan(L1CTL_PT pt, ConnHdlrPars pars) {
- if (not ispresent(pars.maio_hsn)) {
- pt.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr,
- 7 /* TODO: mp_tsc */,
- mp_trx0_arfcn));
+friend function f_l1ctl_est_dchan(L1CTL_PT pt, ConnHdlrPars pars) {
+ if (not pars.fhp.enabled) {
+ var TrxParsItem trx_pars := mp_trx_pars[pars.trx_nr];
+ pt.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr, pars.tsc,
+ trx_pars.arfcn));
} else {
- pt.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr,
- 7 /* TODO: mp_tsc */,
- pars.maio_hsn.hsn,
- pars.maio_hsn.maio,
- pars.ma));
+ pt.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr, pars.tsc,
+ pars.fhp.maio_hsn.hsn,
+ pars.fhp.maio_hsn.maio,
+ pars.fhp.ma));
}
}
/* Establish dedicated channel: L1CTL + RSL side */
-private function f_est_dchan(boolean encr_enable := false, RSL_IE_List more_ies := {}) runs on ConnHdlr {
- var GsmFrameNumber fn;
- var ImmediateAssignment imm_ass;
+private function f_est_dchan(boolean encr_enable := false, RSL_IE_List more_ies := {},
+ RSL_IE_ActivationType act_type := t_RSL_IE_ActType_IA) runs on ConnHdlr {
var ChannelDescription ch_desc;
- var integer ra := 23;
-
- /* Send RACH request and wait for ChanReq */
- fn := f_rach_req_wait_chan_rqd(ra);
/* Activate channel on BTS side */
- f_rsl_chan_act(g_pars.chan_mode, encr_enable, more_ies);
+ f_rsl_chan_act(g_pars.chan_mode, encr_enable, more_ies, act_type := act_type);
/* Craft channel description (with or without frequency hopping parameters) */
- if (ispresent(g_pars.maio_hsn)) {
- ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.maio_hsn));
+ if (g_pars.fhp.enabled) {
+ ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.fhp.maio_hsn, g_pars.tsc));
} else {
- ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, mp_trx0_arfcn));
- }
-
- /* Send IMM.ASS via CCHAN */
- var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, g_pars.ma_map));
- RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
-
- /* receive IMM.ASS on MS side */
- var ImmediateAssignment ia_um;
- ia_um := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
-
- /* Make sure that IMM.ASS contains hopping parameters (if enabled) */
- if (ch_desc.h != ia_um.chan_desc.h) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Hopping parameters mismatch");
+ var TrxParsItem trx_pars := mp_trx_pars[g_pars.trx_nr];
+ ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, trx_pars.arfcn, g_pars.tsc));
}
/* enable dedicated mode */
- f_L1CTL_DM_EST_REQ_IA(L1CTL, ia_um, ma := g_pars.ma);
+ f_l1ctl_est_dchan(L1CTL, g_pars);
+
/* enable encryption, if requested */
if (encr_enable) {
var uint8_t alg_id := f_alg_id_to_l1ctl(g_pars.encr.alg_id);
f_L1CTL_CRYPTO_REQ(L1CTL, g_pars.chan_nr, alg_id, g_pars.encr.key);
}
+ /* Send TCH Mode Request to the L1 if needed */
+ if (match(g_pars.chan_mode.spd_ind, (RSL_SPDI_SPEECH, RSL_SPDI_DATA))) {
+ var L1ctlTchMode tch_mode;
+ var uint8_t amr_start_codec := 0;
+ var BIT8 amr_codecs_bitmask := '00000000'B;
+
+ select (g_pars.chan_mode) {
+ case (tr_RSL_ChanMode_SIGN)
+ { tch_mode := L1CTL_CHAN_MODE_SIGN; }
+ /* Speech modes */
+ case (tr_RSL_ChanMode((RSL_CHRT_TCH_F, RSL_CHRT_TCH_H), RSL_CMOD_SP_GSM1))
+ { tch_mode := L1CTL_CHAN_MODE_SPEECH_V1; }
+ case (tr_RSL_ChanMode((RSL_CHRT_TCH_F, RSL_CHRT_TCH_H), RSL_CMOD_SP_GSM2))
+ { tch_mode := L1CTL_CHAN_MODE_SPEECH_V2; }
+ case (tr_RSL_ChanMode((RSL_CHRT_TCH_F, RSL_CHRT_TCH_H), RSL_CMOD_SP_GSM3))
+ { tch_mode := L1CTL_CHAN_MODE_SPEECH_V3;
+ amr_codecs_bitmask := g_pars.mr_conf.codec_modes; }
+ /* Data modes */
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, /* TCH/F14.4 */
+ (RSL_CMOD_CSD_T_14k4, RSL_CMOD_CSD_NT_14k5)))
+ { tch_mode := L1CTL_CHAN_MODE_DATA_14k5; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, /* TCH/F9.6 */
+ (RSL_CMOD_CSD_T_9k6, RSL_CMOD_CSD_NT_12k0)))
+ { tch_mode := L1CTL_CHAN_MODE_DATA_12k0; }
+ case (tr_RSL_ChanMode_DATA((RSL_CHRT_TCH_F, RSL_CHRT_TCH_H), /* TCH/[FH]4.8 */
+ (RSL_CMOD_CSD_T_4k8, RSL_CMOD_CSD_NT_6k0)))
+ { tch_mode := L1CTL_CHAN_MODE_DATA_6k0; }
+ case (tr_RSL_ChanMode_DATA((RSL_CHRT_TCH_F, RSL_CHRT_TCH_H), /* TCH/[FH]2.4 */
+ (RSL_CMOD_CSD_T_2k4, RSL_CMOD_CSD_T_1k2,
+ RSL_CMOD_CSD_T_600, RSL_CMOD_CSD_T_1200_75)))
+ { tch_mode := L1CTL_CHAN_MODE_DATA_3k6; }
+ case else {
+ log("RSL channel mode is not supported by the L1, falling back to signalling");
+ tch_mode := L1CTL_CHAN_MODE_SIGN;
+ }
+ }
+
+ f_L1CTL_TCH_MODE(L1CTL,
+ ts_L1CTL_TCH_MODE_REQ(tch_mode,
+ amr_start_codec := amr_start_codec,
+ amr_codecs_bitmask := amr_codecs_bitmask));
+ }
+
g_first_meas_res := true;
}
+private function get_start_amr_ft() runs on ConnHdlr return integer {
+ var integer start_nth;
+ if (g_pars.mr_conf.icmi) {
+ start_nth := 0; /* FIXME: implement 3GPP TS 45.009 3.4.3 */
+ } else {
+ start_nth := g_pars.mr_conf.start_mode;
+ }
+
+ var integer n := 0;
+ for (var integer i:= 7; i >= 0; i := i - 1) {
+ if (g_pars.mr_conf.codec_modes[i] == '1'B) {
+ if (n == start_nth) {
+ return 7 - i;
+ }
+ n := n + 1;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("mr_conf is wrong! ", g_pars.mr_conf));
+ return 0;
+}
+
+/* Initialize and start the RTP emulation component for a ConnHdlr */
+friend function f_rtpem_activate(RtpemConfig cfg := c_RtpemDefaultCfg,
+ RtpemMode mode := RTPEM_MODE_LOOPBACK,
+ uint7_t rtp_pt := 0)
+runs on ConnHdlr {
+ /* Step 0: initialize, connect and start the emulation component */
+ vc_RTPEM := RTP_Emulation_CT.create(testcasename() & "-RTPEM");
+ map(vc_RTPEM:RTP, system:RTP);
+ map(vc_RTPEM:RTCP, system:RTCP);
+ connect(vc_RTPEM:CTRL, self:RTPEM_CTRL);
+ connect(vc_RTPEM:DATA, self:RTPEM_DATA);
+ vc_RTPEM.start(RTP_Emulation.f_main());
+
+ /* Step 1: configure the RTP parameters */
+ f_rtpem_configure(RTPEM_CTRL, cfg);
+
+ /* Step 2: bind the RTP emulation to the configured address */
+ var PortNumber rtpem_bind_port := mp_rtpem_bind_port;
+ f_rtpem_bind(RTPEM_CTRL, mp_rtpem_bind_ip, rtpem_bind_port);
+
+ /* Step 3a: send CRCX to create an RTP connection at the IUT */
+ var RSL_Message crcx_ack := f_rsl_transceive_ret(
+ /* FIXME (OS#5242): do not include Remote IP/Port IEs because
+ * osmo-bts would respond with nonsense listen addr='0.0.0.0'. */
+ ts_RSL_IPA_CRCX(g_chan_nr, omit, omit),
+ tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?, omit),
+ "IPA CRCX ACK");
+ var uint16_t conn_id := crcx_ack.ies[1].body.ipa_conn_id;
+
+ /* Step 3b: send MDCX with the configured address/port to the IUT */
+ var RSL_Message mdcx_ack := f_rsl_transceive_ret(
+ ts_RSL_IPA_MDCX(g_chan_nr, conn_id,
+ remote_ip := f_inet_addr(mp_rtpem_bind_ip),
+ remote_port := rtpem_bind_port,
+ rtp_pt2 := rtp_pt),
+ tr_RSL_IPA_MDCX_ACK(g_chan_nr, conn_id, ?, ?, ?),
+ "IPA MDCX ACK");
+
+ /* Step 4: connect to the IUT's address/port parsed from MDCX ACK */
+ var HostName bts_bind_ip := f_inet_ntoa(mdcx_ack.ies[2].body.ipa_local_ip);
+ var PortNumber bts_bind_port := mdcx_ack.ies[3].body.ipa_local_port;
+ f_rtpem_connect(RTPEM_CTRL, bts_bind_ip, bts_bind_port);
+
+ /* Step 5: set the given RTP emulation mode */
+ f_rtpem_mode(RTPEM_CTRL, mode);
+}
+
+/* Initialize and start the RTP emulation component for a ConnHdlr */
+friend function f_osmuxem_activate(inout octetstring payload,
+ OsmuxemConfig cfg := c_OsmuxemDefaultCfg,
+ OsmuxemMode mode := OSMUXEM_MODE_BIDIR)
+runs on ConnHdlr {
+ var RSL_IE_Body ie;
+ var OsmuxTxHandle tx_hdl;
+ var OsmuxRxHandle rx_hdl;
+ /* Step 0: initialize, connect and start the emulation component */
+ vc_OsmuxEM := OSMUX_Emulation_CT.create(testcasename() & "-OsmuxEM");
+ map(vc_OsmuxEM:OSMUX, system:OSMUX);
+ connect(vc_OsmuxEM:CTRL, self:OsmuxEM_CTRL);
+ connect(vc_OsmuxEM:DATA, self:OsmuxEM_DATA);
+ vc_OsmuxEM.start(OSMUX_Emulation.f_main());
+
+ /* Step 1: configure the RTP parameters */
+ var integer payload_len := 31;
+ var octetstring hdr := ''O;
+
+ /* Pad the payload to conform the expected length */
+ payload := f_pad_oct(hdr & payload, payload_len, '00'O);
+ cfg.tx_fixed_payload := payload;
+ f_osmuxem_configure(OsmuxEM_CTRL, cfg);
+
+ /* Step 2: bind the RTP emulation to the configured address */
+ var PortNumber osmuxem_bind_port := mp_osmuxem_bind_port;
+ f_osmuxem_bind(OsmuxEM_CTRL, mp_osmuxem_bind_ip, osmuxem_bind_port);
+ rx_hdl := c_OsmuxemDefaultRxHandle;
+ rx_hdl.cid := g_pars.loc_osmux_cid;
+ f_osmuxem_register_rxhandle(OsmuxEM_CTRL, rx_hdl);
+
+ /* Step 3a: send CRCX to create an RTP connection at the IUT */
+ var RSL_Message crcx_ack := f_rsl_transceive_ret(
+ /* FIXME (OS#5242): do not include Remote IP/Port IEs because
+ * osmo-bts would respond with nonsense listen addr='0.0.0.0'. */
+ ts_RSL_IPA_CRCX(g_chan_nr, omit, omit, g_pars.loc_osmux_cid),
+ tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?, ?),
+ "IPA CRCX ACK");
+ var uint16_t conn_id := crcx_ack.ies[1].body.ipa_conn_id;
+ f_rsl_find_ie(crcx_ack, RSL_IE_OSMO_OSMUX_CID, ie);
+ g_pars.rem_osmux_cid := ie.osmux_cid.cid;
+
+
+ /* Step 3b: send MDCX with the configured address/port to the IUT */
+ var RSL_Message mdcx_ack := f_rsl_transceive_ret(
+ ts_RSL_IPA_MDCX(g_chan_nr, conn_id,
+ remote_ip := f_inet_addr(mp_osmuxem_bind_ip),
+ remote_port := osmuxem_bind_port,
+ rtp_pt2 := 0,
+ osmux_cid := g_pars.loc_osmux_cid),
+ tr_RSL_IPA_MDCX_ACK(g_chan_nr, conn_id, ?, ?, ?, g_pars.rem_osmux_cid),
+ "IPA MDCX ACK");
+
+ tx_hdl := valueof(t_TxHandleAMR590(g_pars.rem_osmux_cid));
+ f_osmuxem_register_txhandle(OsmuxEM_CTRL, tx_hdl);
+
+ /* Step 4: connect to the IUT's address/port parsed from MDCX ACK */
+ var HostName bts_bind_ip := f_inet_ntoa(mdcx_ack.ies[2].body.ipa_local_ip);
+ var PortNumber bts_bind_port := mdcx_ack.ies[3].body.ipa_local_port;
+ f_osmuxem_connect(OsmuxEM_CTRL, bts_bind_ip, bts_bind_port);
+
+ /* Step 5: set the given RTP emulation mode */
+ f_osmuxem_mode(OsmuxEM_CTRL, mode);
+}
+
/* establish DChan, verify existance + contents of measurement reports */
private function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
f_l1_tune(L1CTL);
@@ -2118,9 +2747,10 @@ private function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
timer T := 8.0;
T.start;
alt {
- [] as_l1_sacch();
+ [] as_l1_sacch_loop();
[] as_meas_res();
- [] as_l1_dcch();
+ [] as_l1_dcch_loop();
+ [] as_l1_tch_loop();
[] L1CTL.receive { repeat; }
[g_Tmeas_exp.running] T.timeout {
/* as_meas_res() would have done Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail) in case
@@ -2137,7 +2767,7 @@ private function f_TC_meas_res_periodic(charstring id) runs on ConnHdlr {
/* Wait until the BTS has reached full tx power (nominal tx power minus configured attenuation) */
private function f_wait_ramp_up() runs on ConnHdlr return integer {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
var integer max_rx_lvl := mp_bts_tx_nom_pwr_exp - mp_bts_tx_pwr_att_exp;
timer Tup := 10.0;
Tup.start;
@@ -2162,7 +2792,7 @@ private function f_wait_ramp_up() runs on ConnHdlr return integer {
/* verify BTS ramps power up to full tx power (nominal tx power minus configured attenuation) */
private function f_verify_ramp_up() runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
var integer initial_rx_lvl := -1;
var integer last_rx_lvl := -1;
var integer max_rx_lvl := mp_bts_tx_nom_pwr_exp - mp_bts_tx_pwr_att_exp;
@@ -2224,7 +2854,7 @@ private function f_verify_ramp_up() runs on ConnHdlr {
/* verify BTS ramps power down to rx_level 0 */
private function f_verify_ramp_down(integer max_rx_lvl) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
var integer last_rx_lvl := max_rx_lvl;
timer Tdown := 5.0;
@@ -2269,6 +2899,46 @@ private function f_verify_ramp_down(integer max_rx_lvl) runs on ConnHdlr {
}
}
+/* verify BTS power down to rx_level 0 without ramping */
+private function f_verify_power_down(integer max_rx_lvl) runs on ConnHdlr {
+ var L1ctlMessage l1_dl;
+ var boolean first_data_ind := true;
+
+ timer Tdown := 5.0;
+ Tdown.start;
+ alt {
+ [first_data_ind == true] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
+ first_data_ind := false;
+ var GsmRxLev rx_lvl := l1_dl.dl_info.rx_level;
+ log("Received rx_level=", rx_lvl);
+
+ /* The first data indication could still have the original power level */
+ if (rx_lvl != 0 and rx_lvl != max_rx_lvl) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Detected Tx power: ",
+ rx_lvl , " should be 0 or ", max_rx_lvl));
+ }
+ repeat;
+ }
+ [first_data_ind == false] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
+ var GsmRxLev rx_lvl := l1_dl.dl_info.rx_level;
+ log("Received rx_level=", rx_lvl);
+
+ /* Expect immediate power off so either rx_level == 0 or no report at all
+ because TRX was shut down already */
+ if (rx_lvl != 0) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Detected Tx power: ",
+ rx_lvl , " should be 0"));
+ }
+
+ repeat;
+ }
+ [] L1CTL.receive { repeat; }
+ [] Tdown.timeout { }
+ }
+}
+
/* Verify Tx power reduction and ramping up during BTS bring up */
private function f_TC_tx_power_start_ramp_up_bcch(charstring id) runs on ConnHdlr {
f_l1_tune(L1CTL);
@@ -2289,8 +2959,8 @@ testcase TC_tx_power_start_ramp_up_bcch() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
-/* Verify Tx power reduction and ramping downd uring BTS bring shutdown due to Abis link failure */
-private function f_TC_tx_power_start_ramp_down_bcch(charstring id) runs on ConnHdlr {
+/* Verify Tx power reduction without ramping down during BTS shutdown due to Abis link failure */
+private function f_TC_tx_power_down_bcch(charstring id) runs on ConnHdlr {
f_connhdlr_init_vty_bsc();
f_l1_tune(L1CTL);
@@ -2301,16 +2971,16 @@ private function f_TC_tx_power_start_ramp_down_bcch(charstring id) runs on ConnH
log("Reached nominal level ", max_rx_lvl, ", shutting down OML link");
f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
- f_verify_ramp_down(max_rx_lvl);
+ f_verify_power_down(max_rx_lvl);
setverdict(pass);
}
-testcase TC_tx_power_start_ramp_down_bcch() runs on test_CT {
+testcase TC_tx_power_down_bcch() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
f_init();
pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN));
- vc_conn := f_start_handler(refers(f_TC_tx_power_start_ramp_down_bcch), pars,
+ vc_conn := f_start_handler(refers(f_TC_tx_power_down_bcch), pars,
pcu_comp := false, trxc_comp := true);
vc_conn.done;
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
@@ -2321,7 +2991,7 @@ testcase TC_tx_power_start_ramp_down_bcch() runs on test_CT {
* + ramping up during ADM state LOCKED->UNLOCKED
*/
private function f_TC_tx_power_ramp_adm_state_change(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
var integer last_rx_lvl;
f_connhdlr_init_vty_bsc();
@@ -2375,7 +3045,7 @@ private function f_check_meas_bs_power_level(integer level) runs on ConnHdlr {
T.start;
var RSL_Message rsl;
alt {
- [] as_l1_sacch();
+ [] as_l1_sacch_loop();
[] L1CTL.receive { repeat; }
[] RSL.receive(tr_RSL_MEAS_RES(g_chan_nr, ?, ?, ?)) -> value rsl {
if (rsl.ies[3].body.bs_power.power_level == level) {
@@ -2390,8 +3060,8 @@ private function f_check_meas_bs_power_level(integer level) runs on ConnHdlr {
}
}
-/* see if the rsl meas res contains our expeced bs power level
-bs power set during assignment */
+/* See if the RSL MEASurement RESult contains expeced BS power level
+ * set _during_ the CHANnel ACTIVation procedure. */
private function f_TC_rsl_bs_pwr_static_ass(charstring id) runs on ConnHdlr {
f_l1_tune(L1CTL);
RSL.clear;
@@ -2413,8 +3083,8 @@ private function f_TC_rsl_bs_pwr_static_ass(charstring id) runs on ConnHdlr {
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
}
-/* see if the rsl meas res contains our expeced bs power level
-bs power set after assignment */
+/* See if the RSL MEASurement RESult contains expeced BS power level
+ * set _after_ the CHANnel ACTIVation procedure. */
private function f_TC_rsl_bs_pwr_static_power_control(charstring id) runs on ConnHdlr {
f_l1_tune(L1CTL);
RSL.clear;
@@ -2440,35 +3110,37 @@ private function f_TC_rsl_bs_pwr_static_power_control(charstring id) runs on Con
testcase TC_rsl_bs_pwr_static_ass() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
+
f_init();
- for (var integer tn := 1; tn <= 4; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
- vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_ass), pars,
- pcu_comp := false, trxc_comp := true);
- vc_conn.done;
- }
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_ass), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
testcase TC_rsl_bs_pwr_static_power_control() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
+
f_init();
- for (var integer tn := 1; tn <= 4; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
- vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_power_control), pars,
- pcu_comp := false, trxc_comp := true);
- vc_conn.done;
- }
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_rsl_bs_pwr_static_power_control), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
-/* target level -100, first rssi -90, ms power 7, expected increase to 7+6 within 6 seconds,
-second rssi -110, ms power 7+6, expected decrease to 7 within 6 seconds,
-These power levels are valid for all bands and require no special handling */
+/* Target level -100, first rssi -90, ms power 7, expected increase to 7+6 within 6 seconds,
+ * second rssi -110, ms power 7+6, expected decrease to 7 within 6 seconds.
+ * These power levels are valid for all bands and require no special handling. */
private function f_TC_rsl_ms_pwr_dyn_ass_updown(charstring id) runs on ConnHdlr {
var uint5_t pwr_var := 7;
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
f_trxc_fake_rssi(rxlev2dbm(10));
f_l1_tune(L1CTL);
@@ -2491,10 +3163,10 @@ private function f_TC_rsl_ms_pwr_dyn_ass_updown(charstring id) runs on ConnHdlr
timer T2 := 6.0;
T2.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* Update sent MS power to follow what BTS requests */
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, oct2int(l1_dl.payload.data_ind.payload[0]));
- if (oct2int(l1_dl.payload.data_ind.payload[0]) < (pwr_var + 6)) {
+ [] as_l1_sacch_l1h(l1h) {
+ f_send_meas_rep_l1h(ts_MeasurementResults, l1h);
+
+ if (l1h.ms_power_lvl < (pwr_var + 6)) {
repeat;
}
T2.stop;
@@ -2512,10 +3184,10 @@ private function f_TC_rsl_ms_pwr_dyn_ass_updown(charstring id) runs on ConnHdlr
timer T4 := 6.0;
T4.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* Update sent MS power to follow what BTS requests */
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, oct2int(l1_dl.payload.data_ind.payload[0]));
- if (oct2int(l1_dl.payload.data_ind.payload[0]) > pwr_var) {
+ [] as_l1_sacch_l1h(l1h) {
+ f_send_meas_rep_l1h(ts_MeasurementResults, l1h);
+
+ if (l1h.ms_power_lvl > pwr_var) {
repeat;
}
T4.stop;
@@ -2536,7 +3208,7 @@ private function f_TC_rsl_ms_pwr_dyn_ass_updown(charstring id) runs on ConnHdlr
/* check that we do not exceed the max power */
private function f_TC_rsl_ms_pwr_dyn_max(charstring id) runs on ConnHdlr {
var uint5_t pwr_var := 7;
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
/* set a low value to ensure power increases */
f_trxc_fake_rssi(rxlev2dbm(10));
@@ -2557,14 +3229,15 @@ private function f_TC_rsl_ms_pwr_dyn_max(charstring id) runs on ConnHdlr {
timer T1 := 10.0;
T1.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* Update sent MS power to follow what BTS requests */
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, oct2int(l1_dl.payload.data_ind.payload[0]));
+ [] as_l1_sacch_l1h(l1h) {
+ f_send_meas_rep_l1h(ts_MeasurementResults, l1h);
repeat;
}
[] L1CTL.receive { repeat; }
[] T1.timeout {
- if( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var){
+ if (not isbound(l1h)) {
+ setverdict(fail, "No SACCH blocks were received");
+ } else if (l1h.ms_power_lvl != pwr_var) {
setverdict(fail, "Power level in L1 header should not have changed");
}
}
@@ -2577,7 +3250,7 @@ private function f_TC_rsl_ms_pwr_dyn_max(charstring id) runs on ConnHdlr {
/* see if we reach the band max power */
private function f_TC_rsl_ms_pwr_dyn_up(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
var uint5_t pwr_var := 15;
var uint5_t pwr_max_var := f_get_max_power_from_band();
@@ -2599,23 +3272,25 @@ private function f_TC_rsl_ms_pwr_dyn_up(charstring id) runs on ConnHdlr {
48.058 The maximum power to be used is indicated in the BS and MS Power elements respectively. */
RSL.send(ts_RSL_MS_PWR_CTRL_with_pp(g_chan_nr, pwr_max_var));
- /* wait, then check that our power level was reduced */
- timer T1 := 10.0;
+ /* By default, the MS power loop gets triggered every 4th SACCH block (1.92s).
+ * We need 9 * 4 dB steps to get from 0 dBm to 33 dBm, so 9 * 1.92s total.
+ * Add an extra offset to avoid race conditions: +1.92s. */
+ timer T1 := 9.0 * 1.92 + 1.92;
T1.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* Update sent MS power to follow what BTS requests */
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, oct2int(l1_dl.payload.data_ind.payload[0]));
+ [] as_l1_sacch_l1h(l1h) {
+ f_send_meas_rep_l1h(ts_MeasurementResults, l1h);
repeat;
}
[] L1CTL.receive { repeat; }
[] T1.timeout {
- var int8_t rcv := oct2int(l1_dl.payload.data_ind.payload[0]);
- if( f_power_level_is_highest_dbm(rcv) ){
+ if (not isbound(l1h)) {
+ setverdict(fail, "No SACCH blocks were received");
+ } else if (f_power_level_is_highest_dbm(l1h.ms_power_lvl)) {
setverdict(pass, "Power level in L1 header reduced as expected");
} else {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Power Level in L1 header did not reach the expected value, e:",pwr_max_var," r:",rcv));
+ setverdict(fail, "Power level := ", l1h.ms_power_lvl, " did not ",
+ "reach the expected value := ", pwr_max_var);
}
}
}
@@ -2627,7 +3302,7 @@ private function f_TC_rsl_ms_pwr_dyn_up(charstring id) runs on ConnHdlr {
/* see if we reach the band min power */
private function f_TC_rsl_ms_pwr_dyn_down(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
/* set a high value to ensure power decreases */
f_trxc_fake_rssi(rxlev2dbm(50));
@@ -2654,18 +3329,15 @@ private function f_TC_rsl_ms_pwr_dyn_down(charstring id) runs on ConnHdlr {
timer T1 := 10.0;
T1.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* Update sent MS power to follow what BTS requests */
- f_L1CTL_PARAM(L1CTL, g_pars.l1_pars.ms_actual_ta, oct2int(l1_dl.payload.data_ind.payload[0]));
- repeat;
- }
+ [] as_l1_sacch_l1h(l1h) { repeat; }
[] L1CTL.receive { repeat; }
[] T1.timeout {
- if( f_power_level_is_lowest_dbm(oct2int(l1_dl.payload.data_ind.payload[0])) ){
- setverdict(pass, "Power level in L1 header increased to lowest power value");
+ if (not isbound(l1h)) {
+ setverdict(fail, "No SACCH blocks were received");
+ } else if (f_power_level_is_lowest_dbm(l1h.ms_power_lvl)) {
+ setverdict(pass, "Power level increased to lowest power value");
} else {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "Power level in L1 header NOT increased to lowest power value");
+ setverdict(fail, "Power level NOT increased to lowest power value");
}
}
}
@@ -2675,10 +3347,10 @@ private function f_TC_rsl_ms_pwr_dyn_down(charstring id) runs on ConnHdlr {
}
-/* see if we change the power level without receiving power parameters, which should not happen
-rsl chan act WITHOUT power parameters */
+/* See if the power level remains constant when MS Power Parameters IE
+ * is _absent_ in the CHANnel ACTIVation message. */
private function f_TC_rsl_ms_pwr_dyn_active(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
/* set a high value to ensure power decreases */
f_trxc_fake_rssi(rxlev2dbm(50));
@@ -2700,8 +3372,8 @@ private function f_TC_rsl_ms_pwr_dyn_active(charstring id) runs on ConnHdlr {
timer T1 := 10.0;
T1.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- if ( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var) {
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.ms_power_lvl != pwr_var) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
"BS power control should not be active unless we receive a power parameters IE!");
}
@@ -2716,10 +3388,10 @@ private function f_TC_rsl_ms_pwr_dyn_active(charstring id) runs on ConnHdlr {
}
-/* see if we change the power level without receiving power parameters, which should not happen
-ms power control WITHOUT power parameters */
+/* See if the power level remains constant when MS Power Parameters IE
+ * is _absent_ in the CHANnel ACTIVation and MS Power Control messages. */
private function f_TC_rsl_ms_pwr_dyn_active2(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
/* set a high value to ensure power decreases */
f_trxc_fake_rssi(rxlev2dbm(50));
@@ -2744,8 +3416,8 @@ private function f_TC_rsl_ms_pwr_dyn_active2(charstring id) runs on ConnHdlr {
timer T1 := 10.0;
T1.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- if ( oct2int(l1_dl.payload.data_ind.payload[0]) != pwr_var) {
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.ms_power_lvl != pwr_var) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
"BS power control should not be active unless we receive a power parameters IE!");
}
@@ -2761,12 +3433,12 @@ private function f_TC_rsl_ms_pwr_dyn_active2(charstring id) runs on ConnHdlr {
}
private function f_wait_for_l1_power_level(integer level) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
timer T0 := 10.0;
T0.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- if (not (l1_dl.payload.data_ind.payload[0] == int2oct(level, 1))) {
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.ms_power_lvl != level) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
"Power level in L1 header != signaled (RSL) power level.");
}
@@ -2841,13 +3513,16 @@ private function f_power_from_band(in BtsBand band, out IntegerRecord min_dbm_le
min_dbm_level := {15};
max_dbm_level := {30};
}
+ case else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unsupported band: " & band);
+ }
}
return rv;
}
private function f_vty_get_bts0_band() runs on test_CT return BtsBand {
- return f_vty_transceive_match_regex(BTSVTY, "show bts 0", "BTS 0 is of \w+ type in band (\w+),*", 0);
+ return f_vty_transceive_match_regex(BTSVTY, "show bts 0", "BTS 0 is of*type* in band (\w+),*", 0);
}
testcase TC_rsl_ms_pwr_dyn_ass_updown() runs on test_CT {
@@ -2871,7 +3546,7 @@ testcase TC_rsl_ms_pwr_dyn_up() runs on test_CT {
f_init();
f_vty_config(BTSVTY, "phy 0", "osmotrx ms-power-loop -10");
for (var integer tn := 1; tn <= 1; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
+ pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN, t_guard := 30.0));
pars.bts0_band := f_vty_get_bts0_band();
vc_conn := f_start_handler(refers(f_TC_rsl_ms_pwr_dyn_up), pars, trxc_comp := true);
vc_conn.done;
@@ -2940,12 +3615,78 @@ testcase TC_rsl_ms_pwr_dyn_active2() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+function f_TC_meas_res_speech_tchf(boolean facch_enabled) runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+ f_init();
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1);
+ for (var integer tn := 1; tn <= 1; tn := tn + 1) {
+ pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ch_mode));
+ pars.l1_pars.facch_enabled := facch_enabled;
+ vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_meas_res_speech_tchf() runs on test_CT {
+ f_TC_meas_res_speech_tchf(false);
+}
+
+testcase TC_meas_res_speech_tchf_facch() runs on test_CT {
+ f_TC_meas_res_speech_tchf(true);
+}
+
+function f_TC_meas_res_speech_tchh(boolean facch_enabled) runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+ f_init();
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1);
+ for (var integer ss := 0; ss <= 1; ss := ss + 1) {
+ pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ch_mode));
+ pars.l1_pars.facch_enabled := facch_enabled;
+ vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_meas_res_speech_tchh() runs on test_CT {
+ f_TC_meas_res_speech_tchh(false)
+}
+
+testcase TC_meas_res_speech_tchh_facch() runs on test_CT {
+ f_TC_meas_res_speech_tchh(true)
+}
+
+testcase TC_meas_res_speech_tchh_toa256() runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+ f_init();
+ f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1);
+ for (var integer ss := 0; ss <= 1; ss := ss + 1) {
+ pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ch_mode));
+ pars.l1_pars.toa256_enabled := true;
+ vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
+ pcu_comp := false, trxc_comp := true);
+ vc_conn.done;
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
testcase TC_meas_res_sign_tchf() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
f_init();
+ f_vty_config(BTSVTY, "bts 0", "no supp-meas-info toa256");
for (var integer tn := 1; tn <= 4; tn := tn+1) {
- pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN));
+ pars := valueof(t_Pars(t_RslChanNr_Bm(tn), ts_RSL_ChanMode_SIGN(RSL_CHRT_TCH_F)));
vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
pcu_comp := false, trxc_comp := true);
vc_conn.done;
@@ -2956,8 +3697,9 @@ testcase TC_meas_res_sign_tchh() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
f_init();
+ f_vty_config(BTSVTY, "bts 0", "no supp-meas-info toa256");
for (var integer ss := 0; ss <= 1; ss := ss+1) {
- pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
+ pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN(RSL_CHRT_TCH_H)));
vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
pcu_comp := false, trxc_comp := true);
vc_conn.done;
@@ -2968,6 +3710,7 @@ testcase TC_meas_res_sign_sdcch4() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
f_init();
+ f_vty_config(BTSVTY, "bts 0", "no supp-meas-info toa256");
for (var integer ss := 0; ss <= 3; ss := ss+1) {
pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0, ss), ts_RSL_ChanMode_SIGN));
vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
@@ -2980,6 +3723,7 @@ testcase TC_meas_res_sign_sdcch8() runs on test_CT {
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
f_init();
+ f_vty_config(BTSVTY, "bts 0", "no supp-meas-info toa256");
for (var integer ss := 0; ss <= 7; ss := ss+1) {
pars := valueof(t_Pars(t_RslChanNr_SDCCH8(6, ss), ts_RSL_ChanMode_SIGN));
vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
@@ -2994,18 +3738,99 @@ testcase TC_meas_res_sign_tchh_toa256() runs on test_CT {
f_init();
f_vty_config(BTSVTY, "bts 0", "supp-meas-info toa256");
for (var integer ss := 0; ss <= 1; ss := ss+1) {
- pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN));
+ pars := valueof(t_Pars(t_RslChanNr_Lm(5, ss), ts_RSL_ChanMode_SIGN(RSL_CHRT_TCH_H)));
pars.l1_pars.toa256_enabled := true;
- vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars);
+ vc_conn := f_start_handler(refers(f_TC_meas_res_periodic), pars,
+ pcu_comp := false, trxc_comp := true);
vc_conn.done;
}
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+/* Make sure that we always get RSL MEASurement RESult messages regardless
+ * of what is sent on SACCH: (RR) Measurement Report or SAPI=3 data (SMS). */
+private function f_TC_meas_res_sapi3(charstring id) runs on ConnHdlr {
+ timer Texec := 8.0;
+ timer Timpf := 2.0;
+ timer Tmr;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ f_est_dchan();
+ L1CTL.clear;
+
+ /* Establish the main SAPI=0 link on DCCH first */
+ f_tx_lapdm(ts_LAPDm_SABM(0, cr_MO_CMD, true, ''O), ts_RslLinkID_DCCH(0));
+
+ /* Give more time for the first RSL MEASurement RESult */
+ Tmr.start(0.480 * 2.0);
+ Texec.start; /* EXECution timer */
+ Timpf.start; /* IMPFung timer */
+
+ alt {
+ /* We expect RSL MEASurement RESult messages every ~480ms (plus some guard) */
+ [] RSL.receive(tr_RSL_MEAS_RES(g_pars.chan_nr)) {
+ /* Reschedule the MEAS RES timer */
+ Tmr.start(0.480 + 0.120);
+ repeat;
+ }
+ [] RSL.receive { repeat; }
+ [] Tmr.timeout {
+ setverdict(fail, "Timeout waiting for RSL MEAS RES");
+ }
+ /* Inject some SAPI=3 traffic on SACCH every 2 seconds */
+ [] Timpf.timeout {
+ f_tx_lapdm(ts_LAPDm_SABM(3, cr_MO_CMD, true, ''O), ts_RslLinkID_SACCH(3));
+ log("Injected SAPI=3 traffic on SACCH");
+ Timpf.start;
+ repeat;
+ }
+ /* We're good if survived so far */
+ [] Texec.timeout {
+ setverdict(pass);
+ }
+ }
+
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_meas_res_speech_tchf_sapi3() runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var template ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1);
+ pars := t_Pars(t_RslChanNr_Bm(1), ch_mode);
+
+ vc_conn := f_start_handler(refers(f_TC_meas_res_sapi3), valueof(pars));
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_meas_res_speech_tchh_sapi3() runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
+ var template ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1);
+ pars := t_Pars(t_RslChanNr_Lm(5, 0), ch_mode);
+
+ vc_conn := f_start_handler(refers(f_TC_meas_res_sapi3), valueof(pars));
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/* establish DChan, and send MS POWER CONTROL messages via RSL, verify that
* the BTS is forwarding those values to the MS via the SACCH L1 header. */
private function f_tc_rsl_ms_pwr_ctrl(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
+ var SacchL1Header l1h;
var RSL_IE_MS_Power ms_power;
var RSL_Message rsl;
var uint5_t power_level := 0;
@@ -3027,15 +3852,11 @@ private function f_tc_rsl_ms_pwr_ctrl(charstring id) runs on ConnHdlr {
RSL.send(rsl);
alt {
-
- /* Pick all SACCH blocks for checking */
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
-
- /* The first byte of the L1 header contains the power level.
- * The reserved bits and the fpc bit is set to 0, so we may
- * compare directly. */
- if (not (l1_dl.payload.data_ind.payload[0] == int2oct(power_level, 1))) {
- setverdict(fail, "Power level in L1 header does not match the signaled (RSL) power level.");
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.ms_power_lvl != power_level) {
+ setverdict(fail, "Power level := ", l1h.ms_power_lvl, "does not ",
+ "match the signaled (RSL) power level := ", power_level);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
/* Signal a new power level via RSL for the next turn. */
@@ -3076,9 +3897,8 @@ testcase TC_rsl_ms_pwr_ctrl() runs on test_CT {
/* establish DChan, verify that the BTS sets the TA in the first SACCH L1 header.
TA for the IMM ASS messages is still controlled by g_pars.l1_pars.ms_actual_ta! */
private function f_tc_rsl_chan_initial_ta(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
var uint5_t ta_to_test := 16;
-
+ var SacchL1Header l1h;
f_l1_tune(L1CTL);
RSL.clear;
@@ -3090,12 +3910,8 @@ private function f_tc_rsl_chan_initial_ta(charstring id) runs on ConnHdlr {
alt {
-
- /* Pick all SACCH blocks for checking */
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
-
- /* The second byte of the L1 header contains the TA. */
- if (not (l1_dl.payload.data_ind.payload[1] == int2oct(ta_to_test, 1))) {
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.actual_ta != ta_to_test) {
setverdict(fail, "TA in L1 header does not match the signaled (RSL) TA.");
}
@@ -3125,8 +3941,8 @@ testcase TC_rsl_chan_initial_ta() runs on test_CT {
/* establish DChan, verify that the BTS sets MS power in the first SACCH L1 header. */
private function f_tc_rsl_chan_initial_ms_pwr(charstring id) runs on ConnHdlr {
- var L1ctlDlMessage l1_dl;
var uint5_t ms_power_level := 7;
+ var SacchL1Header l1h;
var RSL_IE_MS_Power ms_power;
ms_power.reserved := 0;
@@ -3142,10 +3958,10 @@ private function f_tc_rsl_chan_initial_ms_pwr(charstring id) runs on ConnHdlr {
T.start;
alt {
/* Pick all SACCH blocks for checking */
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
- /* The first byte of the L1 header contains the power level.. */
- if (not (l1_dl.payload.data_ind.payload[0] == int2oct(ms_power_level, 1))) {
- setverdict(fail, "Power Level in L1 header does not match the signaled (RSL) MS Power Level.");
+ [] as_l1_sacch_l1h(l1h, do_apply := false) {
+ if (l1h.ms_power_lvl != ms_power_level) {
+ setverdict(fail, "Power level := ", l1h.ms_power_lvl, "does not ",
+ "match the signaled (RSL) power level := ", ms_power_level);
}
}
/* Ignore all other blocks */
@@ -3172,7 +3988,9 @@ private function f_TC_conn_fail_crit(charstring id) runs on ConnHdlr {
f_est_dchan();
f_sleep(2.0);
- L1CTL.send(ts_L1CTL_DM_REL_REQ(g_chan_nr));
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_L1CTL_RESET(L1CTL);
+ f_l1_tune(L1CTL); /* tune back to BCCH */
timer T := 40.0;
T.start;
@@ -3264,7 +4082,7 @@ private altstep as_l1_count_paging(inout integer num_paging_rcv_msgs,
inout integer num_paging_rcv_ids,
PagingTestCfg cfg)
runs on test_CT {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, c_DummyUI)) {
repeat;
}
@@ -3318,6 +4136,18 @@ private type record PagingTestCfg {
boolean combined_ccch,
integer bs_ag_blks_res,
float load_factor,
+ /* Mix in a paging request through the PCU socket for every Nth (ps_load_modulus)
+ * paging command that is issued via RSL. */
+ integer ps_load_modulus,
+ /* Wait until the paging queue inside the BTS is congested before starting to add
+ * pagings via the PCU socket (0 = disabled) */
+ boolean ps_wait_cong,
+ /* Maximum time to wait until the paging queue is drained at the end of the test.
+ * This usually takes about 15s (size: 200, ~ 13 per s -> 15s), it is recommended
+ * to set this value to 18s, however the draining process may take significantly
+ * longer when the queue contains paging requests for PS as those are implemented
+ * as immediate assignments and require an entire MAC block alone. */
+ float queue_drain_timeout,
boolean exp_load_ind,
boolean exp_overload,
boolean use_tmsi
@@ -3327,20 +4157,34 @@ private type record PagingTestState {
integer num_paging_sent,
integer num_paging_rcv_msgs,
integer num_paging_rcv_ids,
- integer num_overload
+ integer num_overload,
+ /* When free space inside the paging queue reaches more than 2 thirds
+ * of its capacity cong_detected is set to true. */
+ boolean cong_detected
}
/* Helper function for paging related testing */
private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTestState {
- f_init();
+ /* Using the PCU socket affects the timing of the paging processing. We only
+ * activate the PCU socket if we do paging load tests that include additional
+ * paging load that is introduced through the PCU socket. */
+ if (cfg.ps_load_modulus > 0) {
+ f_init_with_pcuif();
+ } else {
+ f_init();
+ }
f_init_l1ctl();
f_l1_tune(L1CTL);
+ var octetstring imm_ass := f_rnd_octstring(23);
+ var ASP_RSL_Unitdata load_ind;
+
var PagingTestState st := {
num_paging_sent := 0,
num_paging_rcv_msgs := 0,
num_paging_rcv_ids := 0,
- num_overload := 0
+ num_overload := 0,
+ cong_detected := false
};
var float max_pch_blocks_per_sec := f_pch_block_rate_est(cfg.combined_ccch, cfg.bs_ag_blks_res);
@@ -3371,14 +4215,28 @@ private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTes
[not cfg.exp_overload] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND(0))) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PCH Overload");
}
- [cfg.exp_load_ind] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND)) {
+ [cfg.exp_load_ind] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND)) -> value load_ind {
log("Rx LOAD_IND");
+
+ /* Detect paging congestion: The logic inside the BTS will diagnose the
+ * paging queue as congested when the fill state is more than 66% (which
+ * is two thirds fill state, or approx. 66 of 200 paging slots. When a
+ * paging congestion is detected pagings that are issued through the PCU
+ * socket (PS) are dropped in order to prefer the CS related pagings. */
+ if (load_ind.rsl.ies[1].body.paging_load < 66) {
+ st.cong_detected := true;
+ }
+
/* FIXME: analyze/verify interval + contents */
repeat;
}
+ /* ignore other RSL messages like RF RESource INDication */
+ [] RSL_CCHAN.receive { repeat; }
/* check if paging requests arrive on Um side */
[] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
[] L1CTL.receive { repeat; }
+ /* Only relevant when testing including with PCU sock connected */
+ [] PCU.receive { repeat; }
[] T_itv.timeout {
/* Send paging cmds based on elapsed time */
var integer new_sent := f_min(pkt_total, float2int(T_total.read * pch_blocks_per_sec) + 1);
@@ -3395,6 +4253,13 @@ private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTes
/* Send RSL PAGING COMMAND */
RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_PAGING_CMD(mi, st.num_paging_sent mod 4)));
+ /* Add additional pagings through the PCU socket interface. */
+ if (cfg.ps_load_modulus > 0 and st.num_paging_sent mod cfg.ps_load_modulus == 0) {
+ if (st.cong_detected == true or cfg.ps_wait_cong == false) {
+ f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H, wait_for_cnf := false);
+ }
+ }
+
st.num_paging_sent := st.num_paging_sent + 1;
}
if (st.num_paging_sent < pkt_total) {
@@ -3415,17 +4280,20 @@ private function f_TC_paging(PagingTestCfg cfg) runs on test_CT return PagingTes
}
}
- /* wait for max 18s for paging queue to drain (size: 200, ~ 13 per s -> 15s) */
- timer T_wait := 18.0;
+ timer T_wait := cfg.queue_drain_timeout
T_wait.start;
alt {
[] as_l1_count_paging(st.num_paging_rcv_msgs, st.num_paging_rcv_ids, cfg);
[] L1CTL.receive { repeat; }
/* 65535 == empty paging queue, we can terminate*/
[] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND(65535))) { }
- [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND)) { repeat; }
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_LOAD_IND)) -> value load_ind { repeat; }
+ /* ignore other RSL messages like RF RESource INDication */
+ [] RSL_CCHAN.receive { repeat; }
+ /* Only relevant when testing including with PCU sock connected */
+ [] PCU.receive { repeat; }
[] T_wait.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Waiting for empty paging queue");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Waiting for paging queue, last detected fill state: ", load_ind.rsl.ies[1].body.paging_load));
}
}
@@ -3444,6 +4312,9 @@ testcase TC_paging_imsi_80percent() runs on test_CT {
combined_ccch := true,
bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
load_factor := 0.8,
+ ps_load_modulus := 0,
+ ps_wait_cong := false,
+ queue_drain_timeout := 18.0,
exp_load_ind := true,
exp_overload := false,
use_tmsi := false
@@ -3468,6 +4339,9 @@ testcase TC_paging_tmsi_80percent() runs on test_CT {
combined_ccch := true,
bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
load_factor := 0.8,
+ ps_load_modulus := 0,
+ ps_wait_cong := false,
+ queue_drain_timeout := 18.0,
exp_load_ind := true,
exp_overload := false,
use_tmsi := true
@@ -3492,6 +4366,9 @@ testcase TC_paging_imsi_200percent() runs on test_CT {
combined_ccch := true,
bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
load_factor := 2.0,
+ ps_load_modulus := 0,
+ ps_wait_cong := false,
+ queue_drain_timeout := 18.0,
exp_load_ind := true,
exp_overload := true,
use_tmsi := false
@@ -3518,6 +4395,9 @@ testcase TC_paging_tmsi_200percent() runs on test_CT {
combined_ccch := true,
bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
load_factor := 2.0,
+ ps_load_modulus := 0,
+ ps_wait_cong := false,
+ queue_drain_timeout := 18.0,
exp_load_ind := true,
exp_overload := true,
use_tmsi := true
@@ -3534,11 +4414,43 @@ testcase TC_paging_tmsi_200percent() runs on test_CT {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
+/* Same as above, but with additional paging load created by PS pagings that
+ * are issued through the PCU socket. The additional load is introduced when
+ * the paging queue is already two thirds full. Since the BTS implements a
+ * prioritization logic that drops the pagings from the PCU under in those
+ * congestive sitautions the behaviour on the PS side is expected to be
+ * unaffected and match the behavior of TC_paging_imsi_200percent() */
+testcase TC_paging_imsi_200percent_with_ps() runs on test_CT {
+ var SystemInformation si3 := valueof(ts_SI3_default);
+ var PagingTestCfg cfg := {
+ combined_ccch := true,
+ bs_ag_blks_res := si3.payload.si3.ctrl_chan_desc.bs_ag_blks_res,
+ load_factor := 2.0,
+ ps_load_modulus := 16,
+ ps_wait_cong := true,
+ queue_drain_timeout := 18.0,
+ exp_load_ind := true,
+ exp_overload := true,
+ use_tmsi := false
+ };
+ var PagingTestState st := f_TC_paging(cfg);
+ /* We expect about 80-85% to pass, given that we can fill the paging buffer of 200
+ * slots and will fully drain that buffer before returning */
+ var template integer tpl := (st.num_paging_sent*78/100 .. st.num_paging_sent *85/100);
+ if (not match(st.num_paging_rcv_ids, tpl)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Expected ", tpl, " pagings but have ", st.num_paging_rcv_ids));
+ } else {
+ setverdict(pass);
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+
/***********************************************************************
* Immediate Assignment / AGCH
***********************************************************************/
-private const MobileAllocation c_MA_null := {
+private const MobileAllocationLV c_MA_null := {
len := 0,
ma := ''B
}
@@ -3550,7 +4462,7 @@ private function f_fmt_ia_stats(integer num_tx, integer num_rx, integer num_del)
}
private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass) runs on test_CT {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
timer T := 10.0;
var integer num_tx := 0;
var integer num_rx := 0;
@@ -3563,7 +4475,9 @@ private function f_TC_imm_ass(integer num_total, float sleep_s, float exp_pass)
f_l1_tune(L1CTL);
for (var integer i := 0; i < num_total; i := i+1) {
- var ChannelDescription ch_desc := valueof(ts_ChanDescH0(t_RslChanNr_SDCCH4(0, 0), mp_trx0_arfcn));
+ var ChannelDescription ch_desc := valueof(ts_ChanDescH0(ts_RslChanNr_SDCCH4(0, 0),
+ mp_trx_pars[0].arfcn,
+ mp_tsc_def));
var GsmRrMessage ia := valueof(ts_IMM_ASS(42, i, 5, ch_desc, c_MA_null));
var octetstring ia_enc := enc_GsmRrMessage(ia);
RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_IMM_ASSIGN(ia_enc, 0)));
@@ -3688,7 +4602,8 @@ private function f_si_vecslot_contains_n_of_m(SystemInformationVector arr,
return boolean {
var integer count := 0;
if (sizeof(arr) < m) {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Error: Insufficient SI in array");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Error: Insufficient SI in array: "
+ & int2str(sizeof(arr)) & " < " & int2str(m));
}
for (var integer i:= 0; i < m; i := i + 1) {
var integer fn_mod51 := arr[i].frame_number mod 51;
@@ -3969,7 +4884,7 @@ private function f_l1_sample_si(L1CTL_PT pt, float duration := 8.0)
return SystemInformationVectorPerTc {
timer T := duration;
var SystemInformationVectorPerTc si_per_tc;
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
/* initialize all per-TC vectors empty */
for (var integer i:= 0; i < sizeof(si_per_tc); i := i+1) {
@@ -4007,13 +4922,13 @@ return SystemInformationVectorPerTc {
/* helper function: Set given SI via RSL + validate scheduling.
* CALLER MUST MAKE SURE TO CHANGE GLOBAL si_cfg! */
-private function f_TC_si_sched() runs on test_CT {
+private function f_TC_si_sched(float duration := 8.0) runs on test_CT {
var SystemInformationVectorPerTc si_per_tc;
f_init_l1ctl();
f_l1_tune(L1CTL);
/* Sample + Validate Scheduling */
- si_per_tc := f_l1_sample_si(L1CTL);
+ si_per_tc := f_l1_sample_si(L1CTL, duration);
f_validate_si_scheduling(si_cfg, si_per_tc);
setverdict(pass);
@@ -4063,13 +4978,15 @@ testcase TC_si_sched_2ter_2bis() runs on test_CT {
testcase TC_si_sched_2quater() runs on test_CT {
f_init();
si_cfg.si2quater_present := true;
- f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
- f_TC_si_sched();
+ f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607b10004864982eddb8d555867ee3c95540b2b2b2b'O);
+ f_TC_si_sched(16.0);
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
testcase TC_si_sched_13() runs on test_CT {
- f_init();
+ /* NOTE: PCUIF connection is not used in this test case, but
+ * without it the IUT would not broadcast SI13 (see OS#3075). */
+ f_init_with_pcuif();
si_cfg.si13_present := true;
f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
f_TC_si_sched();
@@ -4077,16 +4994,18 @@ testcase TC_si_sched_13() runs on test_CT {
}
testcase TC_si_sched_13_2bis_2ter_2quater() runs on test_CT {
- f_init();
+ /* NOTE: PCUIF connection is not used in this test case, but
+ * without it the IUT would not broadcast SI13 (see OS#3075). */
+ f_init_with_pcuif();
si_cfg.si2bis_present := true;
f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2bis, '550602bfe809b3ff00000000000000000000007900002b'O);
si_cfg.si2ter_present := true;
f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2ter, '010603bf66b0aa0a00000002000000000000002b2b2b2b'O);
si_cfg.si2quater_present := true;
- f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607a8a0364aa698d72ff424feee0506d5e7fff02043'O);
+ f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_2quater, '050607b10004864982eddb8d555867ee3c95540b2b2b2b'O);
si_cfg.si13_present := true;
f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, '0106009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O);
- f_TC_si_sched();
+ f_TC_si_sched(16.0);
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
@@ -4277,7 +5196,7 @@ testcase TC_ipa_crcx_twice_not_active() runs on test_CT {
private function f_TC_ipa_crcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
"IPA CRCX ACK");
- var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
+ var OCT4 remote_ip := f_rnd_octstring(4);
var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
var uint7_t rtp_pt2 := f_rnd_int(127);
var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
@@ -4298,7 +5217,7 @@ testcase TC_ipa_crcx_mdcx_dlcx_not_active() runs on test_CT {
private function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on ConnHdlr {
f_rsl_transceive(ts_RSL_IPA_CRCX(g_chan_nr), tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
"IPA CRCX ACK");
- var uint32_t remote_ip := f_rnd_int(c_UINT32_MAX);
+ var OCT4 remote_ip := f_rnd_octstring(4);
var uint16_t remote_port := f_rnd_int(c_UINT16_MAX);
var uint7_t rtp_pt2 := f_rnd_int(127);
var uint16_t fake_conn_id := 23; /* we're too lazy to read it out from the CRCX ACK above */
@@ -4306,7 +5225,7 @@ private function f_TC_ipa_crcx_mdcx_mdcx_dlcx_not_active(charstring id) runs on
tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
"IPA MDCX ACK");
/* Second MDCX */
- remote_ip := f_rnd_int(c_UINT32_MAX);
+ remote_ip := f_rnd_octstring(4);
remote_port := f_rnd_int(c_UINT16_MAX);
f_rsl_transceive(ts_RSL_IPA_MDCX(g_chan_nr, fake_conn_id, remote_ip, remote_port, rtp_pt2),
tr_RSL_IPA_MDCX_ACK(g_chan_nr, ?, ?, ?, rtp_pt2),
@@ -4340,20 +5259,133 @@ testcase TC_ipa_crcx_sdcch_not_active() runs on test_CT {
vc_conn.done;
}
+/* Make sure that CRCX ACK contains a valid listen address (see OS#5242) */
+private function f_TC_ipa_crcx_ack_addr(charstring id) runs on ConnHdlr {
+ var OCT4 bind_ip := f_inet_addr("192.168.1.1");
+ var PortNumber bind_port := 16811;
+ var RSL_Message crcx_ack;
+
+ crcx_ack := f_rsl_transceive_ret(ts_RSL_IPA_CRCX(g_chan_nr, bind_ip, bind_port),
+ tr_RSL_IPA_CRCX_ACK(g_chan_nr, ?, ?, ?),
+ "IPA CRCX ACK");
+ var HostName bts_bind_ip := f_inet_ntoa(crcx_ack.ies[2].body.ipa_local_ip);
+ if (match(bts_bind_ip, "0.0.0.0")) {
+ setverdict(fail, "CRCX ACK indicates nonsense addr ", bts_bind_ip);
+ }
+
+ var uint16_t conn_id := crcx_ack.ies[1].body.ipa_conn_id;
+ f_rsl_transceive(ts_RSL_IPA_DLCX(g_chan_nr, conn_id),
+ tr_RSL_IPA_DLCX_ACK(g_chan_nr, ?, ?),
+ "IPA DLCX ACK");
+}
+testcase TC_ipa_crcx_ack_addr() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_ipa_crcx_ack_addr), pars);
+ vc_conn.done;
+
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_ipa_crcx_ack_addr), pars);
+ vc_conn.done;
+}
+
/***********************************************************************
* PCU Socket related tests
***********************************************************************/
+/* Catch a PCUIF message (without having to use t_SD_PCUIF) */
+private altstep as_pcuif_msg(out PCUIF_Message msg,
+ template (present) PCUIF_Message tr_msg := ?)
+runs on test_CT {
+ var PCUIF_send_data sd;
+
+ [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_msg)) -> value sd {
+ msg := sd.data;
+ }
+}
+
+/* Catch a L1CTL DL BLOCK.ind with the given parameters */
+private altstep as_l1ctl_dl_block_ind(out L1ctlGprsDlBlockInd block_ind,
+ template (present) GsmFrameNumber fn := ?,
+ template (present) uint3_t tn := ?,
+ template (present) uint3_t usf := ?,
+ template (present) octetstring data := ?)
+runs on test_CT {
+ var L1ctlMessage l1_dl;
+
+ [] L1CTL.receive(tr_L1CTL_GPRS_DL_BLOCK_IND(fn, tn, usf, data)) -> value l1_dl {
+ block_ind := l1_dl.payload.dl_block_ind;
+ }
+}
+
+/* tuple of TDMA frame number and timeslot number */
+private type record TdmaFnTn {
+ GsmFrameNumber fn,
+ uint3_t tn
+}
+
+/* Wait for a L1CTL DL BLOCK.ind and send an UL BLOCK.req */
+private function f_TC_pcu_tx_ul_block_req(octetstring data,
+ template (present) uint3_t tn := ?,
+ template (present) uint3_t usf := ?)
+runs on test_CT return TdmaFnTn {
+ var L1ctlGprsDlBlockInd block_ind;
+ timer T;
+
+ T.start(1.0);
+ alt {
+ [] as_l1ctl_dl_block_ind(block_ind, tn := tn, usf := usf) {
+ var integer fn := block_ind.hdr.fn;
+
+ /* Ignore PTCCH/D blocks, their Fn is too far away */
+ if (fn mod 104 == 12) {
+ repeat;
+ }
+
+ /* Every fn % 13 == 12 we have either a PTCCH or an IDLE slot, thus
+ * every fn % 13 == 8 we add 5 frames, or 4 frames othrwise. The
+ * resulting value is first fn of the next block. */
+ if (fn mod 13 == 8) {
+ fn := (fn + 5) mod (2048 * 51 * 26);
+ } else {
+ fn := (fn + 4) mod (2048 * 51 * 26);
+ }
+
+ L1CTL.send(ts_L1CTL_GPRS_UL_BLOCK_REQ(fn, block_ind.hdr.tn, data));
+ return {fn, block_ind.hdr.tn};
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for DL BLOCK.ind (RTS)");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ return {0, 0}; /* make TITAN happy */
+}
+
+/* Tune the L1 to PDCH on the given timeslot number */
+private function f_TC_pcu_l1ctl_est_pdch(uint3_t tn) runs on test_CT {
+ var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_PDCH(tn), ts_RSL_ChanMode_SIGN));
+ if (mp_freq_hop_enabled and mp_transceiver_num > 1)
+ { f_resolve_fh_params(pars.fhp, tn); }
+ f_l1ctl_est_dchan(L1CTL, pars);
+}
+
/* Verify no RTS before ACT_REQ; verify RTS after ACT_REQ */
friend function f_TC_pcu_act_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, boolean exp_success)
runs on test_CT {
+ var PCUIF_Message msg;
timer T := 3.0;
/* we don't expect any RTS.req before PDCH are active */
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr))) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(bts_nr)) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "PCU RTS.req before PDCH active?");
}
[] PCU.receive { repeat; }
@@ -4366,14 +5398,13 @@ runs on test_CT {
/* we now expect RTS.req for this timeslot (only) */
T.start;
alt {
- [exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
+ [exp_success] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr)) {
setverdict(pass);
}
- [not exp_success] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
- tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
+ [not exp_success] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr)) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RTS.req for supposedly failing activation");
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "RTS.req for wrong TRX/TS");
}
[] PCU.receive { repeat; }
@@ -4389,16 +5420,19 @@ runs on test_CT {
/* verify no more RTS after DEACT_REQ */
friend function f_TC_pcu_deact_req(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr)
runs on test_CT {
+ var PCUIF_Message msg;
timer T := 3.0;
/* Send PDCH activate request for known PDCH timeslot */
PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_DEACT_REQ(bts_nr, trx_nr, ts_nr)));
-
+ /* wait for some time as there is no PCUIF_DEACT_RESP or the like, so we don't know
+ * when it will actually have been executed in the BTS */
+ f_sleep(1.0);
PCU.clear;
/* we now expect no RTS.req for this timeslot */
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr))) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr)) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected PCU RTS.req");
}
[] PCU.receive { repeat; }
@@ -4408,42 +5442,44 @@ runs on test_CT {
}
}
-friend function f_init_pcu_test() runs on test_CT {
+friend function f_init_with_pcuif() runs on test_CT {
f_init();
+ map(self:PCU, system:PCU);
+ f_init_pcu(PCU, testcasename(), g_pcu_conn_id, g_pcu_last_info);
PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, testcasename())));
}
/* PDCH activation via PCU socket; check for presence of RTS.req */
testcase TC_pcu_act_req() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 7, true);
}
/* PDCH activation via PCU socket on non-PDCU timeslot */
testcase TC_pcu_act_req_wrong_ts() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 1, false);
}
/* PDCH activation via PCU socket on wrong BTS */
testcase TC_pcu_act_req_wrong_bts() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(23, 0, 7, false);
}
/* PDCH activation via PCU socket on wrong TRX */
testcase TC_pcu_act_req_wrong_trx() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 23, 7, false);
}
/* PDCH deactivation via PCU socket; check for absence of RTS.req */
testcase TC_pcu_deact_req() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
/* Activate PDCH */
f_TC_pcu_act_req(0, 0, 7, true);
@@ -4454,25 +5490,25 @@ testcase TC_pcu_deact_req() runs on test_CT {
/* Attempt to deactivate a PDCH on a non-PDCH timeslot */
testcase TC_pcu_deact_req_wrong_ts() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_deact_req(0, 0, 1);
}
/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
-testcase TC_pcu_ver_si13() runs on test_CT {
- const octetstring si13 := '00010203040506070909'O;
- var PCUIF_send_data sd;
- timer T:= 3.0;
- f_init_pcu_test();
+function f_TC_pcu_ver_siXX(octetstring si, RSL_IE_SysinfoType rsl_si_type) runs on test_CT {
+ var PCUIF_Message msg;
+ timer T := 3.0;
+
+ f_init_with_pcuif();
/* Set SI13 via RSL */
- f_rsl_bcch_fill_raw(RSL_SYSTEM_INFO_13, si13);
+ f_rsl_bcch_fill_raw(rsl_si_type, si);
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_DATA_IND(0, 0, 0, ?, PCU_IF_SAPI_BCCH))) -> value sd {
- if (substr(sd.data.u.data_ind.data, 0, lengthof(si13)) == si13) {
+ [] as_pcuif_msg(msg, tr_PCUIF_DATA_IND(0, 0, 0, sapi := PCU_IF_SAPI_BCCH)) {
+ if (substr(msg.u.data_ind.data, 0, lengthof(si)) == si) {
setverdict(pass);
} else {
repeat;
@@ -4480,11 +5516,29 @@ testcase TC_pcu_ver_si13() runs on test_CT {
}
[] PCU.receive { repeat; }
[] T.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SI13");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SI");
}
}
}
+/* Test the PCU->BTS Version and BTS->PCU SI1 handshake */
+testcase TC_pcu_ver_si1() runs on test_CT {
+ const octetstring si1 := '550111132A252B27CC29AA11BB33CC'O;
+ f_TC_pcu_ver_siXX(si1, RSL_SYSTEM_INFO_1);
+}
+
+/* Test the PCU->BTS Version and BTS->PCU SI3 handshake */
+testcase TC_pcu_ver_si3() runs on test_CT {
+ const octetstring si3 := '49012223242526272929AABBCC'O;
+ f_TC_pcu_ver_siXX(si3, RSL_SYSTEM_INFO_3);
+}
+
+/* Test the PCU->BTS Version and BTS->PCU SI13 handshake */
+testcase TC_pcu_ver_si13() runs on test_CT {
+ const octetstring si13 := '01010203040506070909'O;
+ f_TC_pcu_ver_siXX(si13, RSL_SYSTEM_INFO_13);
+}
+
private const octetstring c_PCU_DATA := '000102030405060708090a0b0c0d0e0f10111213141516'O;
/* helper function to send a PCU DATA.req */
@@ -4501,15 +5555,14 @@ friend function f_pcu_wait_rts_and_data_req(uint8_t bts_nr, uint8_t trx_nr, uint
PCUIF_Sapi sapi, octetstring data)
runs on test_CT
{
- var PCUIF_send_data sd;
-
+ var PCUIF_Message msg;
timer T := 3.0;
+
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
- tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi))) -> value sd {
- f_pcu_data_req(bts_nr, trx_nr, ts_nr, sd.data.u.rts_req.block_nr,
- sd.data.u.rts_req.fn, sapi, data);
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(bts_nr, trx_nr, ts_nr, sapi)) {
+ f_pcu_data_req(bts_nr, trx_nr, ts_nr, msg.u.rts_req.block_nr,
+ msg.u.rts_req.fn, sapi, data);
}
[] PCU.receive { repeat; }
[] T.timeout {
@@ -4520,60 +5573,53 @@ runs on test_CT
/* Send DATA.req on invalid BTS */
testcase TC_pcu_data_req_wrong_bts() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
f_TC_pcu_act_req(0, 0, 7, true);
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(23, 0, 7, PCU_IF_SAPI_PDTCH, data, false, false);
}
/* Send DATA.req on invalid TRX */
testcase TC_pcu_data_req_wrong_trx() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
f_TC_pcu_act_req(0, 0, 7, true);
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(0, 100, 7, PCU_IF_SAPI_PDTCH, data, false, false);
}
/* Send DATA.req on invalid timeslot */
testcase TC_pcu_data_req_wrong_ts() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
f_TC_pcu_act_req(0, 0, 7, true);
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(0, 0, 70, PCU_IF_SAPI_PDTCH, data, false, false);
}
/* Send DATA.req on timeslot that hasn't been activated */
testcase TC_pcu_data_req_ts_inactive() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ /* intentionally not calling f_TC_pcu_act_req() */
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PDTCH, data, false, false);
}
@@ -4582,8 +5628,9 @@ private function f_pcu_to_l1(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
boolean wait_rts := true)
runs on test_CT {
timer T := 5.0;
- var L1ctlDlMessage rx_dl;
+ var L1ctlMessage rx_dl;
+ L1CTL.clear;
PCU.clear;
if (wait_rts) {
f_pcu_wait_rts_and_data_req(bts_nr, trx_nr, ts_nr, sapi, data);
@@ -4593,11 +5640,11 @@ runs on test_CT {
T.start;
alt {
- [expect_data] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PDCH(ts_nr), ?, data)) {
- /* FIXME: why is fn of DATA_IND different to fn of RTS / DATA_REQ above? */
+ [expect_data] L1CTL.receive(tr_L1CTL_GPRS_DL_BLOCK_IND(tn := ts_nr, data := data)) {
+ /* FIXME: why is fn of DL BLOCK.ind different to fn of RTS / DATA_REQ above? */
setverdict(pass);
}
- [not expect_data] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PDCH(ts_nr), ?, data)) -> value rx_dl {
+ [not expect_data] L1CTL.receive(tr_L1CTL_GPRS_DL_BLOCK_IND(tn := ts_nr, data := data)) -> value rx_dl {
setverdict(fail, "Received unexpected ", rx_dl);
}
[] L1CTL.receive {
@@ -4612,55 +5659,40 @@ runs on test_CT {
}
}
-private function f_disable_dynamic_ts() runs on test_CT
-{
- f_init_vty_bsc();
- /* I'm not quite sure why we need this with osmo-bts-virtual. Somehow it deosn't seem to
- * support dynamic timeslots? But it uses the same scheduler as osmo-bts-trx ?!? */
- f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 3"}, "phys_chan_config TCH/F");
- f_vty_config2(BSCVTY, {"network", "bts 0", "trx 0", "timeslot 4"}, "phys_chan_config TCH/F");
- f_init_pcu_test();
-}
-
-private function f_virtphy_common() runs on test_CT {
- f_disable_dynamic_ts();
+private function f_TC_pcu_init() runs on test_CT {
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
}
testcase TC_pcu_data_req_pdtch() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
f_TC_pcu_act_req(0, 0, 7, true);
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PDTCH, data); //c_PCU_DATA);
}
-/* FIXME: PTTCH has nothing to do with TBFs */
testcase TC_pcu_data_req_ptcch() runs on test_CT {
- var TfiUsfArr tua := f_TfiUsfArrInit();
var octetstring data := '0000'O & f_rnd_octstring(21);
- f_virtphy_common();
+ f_TC_pcu_init();
f_TC_pcu_act_req(0, 0, 7, true);
- f_TfiUsfArrSet(tua, 7, 0);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
- f_sleep(1.0);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
f_pcu_to_l1(0, 0, 7, PCU_IF_SAPI_PTCCH, data);
}
private function f_TC_pcu_ptcch_ul(uint16_t ra)
runs on test_CT {
var template PCUIF_Message pcu_rach_ind;
- var PCUIF_send_data sd;
+ var PCUIF_Message msg;
var GsmFrameNumber fn;
timer T;
@@ -4675,8 +5707,8 @@ runs on test_CT {
/* Expect a RACH.ind on the PCU interface (timeout is one multi-frame) */
T.start(52.0 * 4.615 / 1000.0);
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, pcu_rach_ind)) -> value sd {
- log("Rx an Access Burst on the PCU interface: ", sd.data);
+ [] as_pcuif_msg(msg, pcu_rach_ind) {
+ log("Rx an Access Burst on the PCU interface: ", msg);
setverdict(pass);
T.stop;
}
@@ -4689,22 +5721,20 @@ runs on test_CT {
}
testcase TC_pcu_ptcch() runs on test_CT {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var octetstring data;
timer T;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
/* Activate PDCH channel on TS7 */
f_TC_pcu_act_req(0, 0, 7, true);
- /* Tune trxcon to that PDCH channel */
- var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_PDCH(7), ts_RSL_ChanMode_SIGN));
- if (mp_freq_hop_enabled and mp_transceiver_num > 1)
- { f_resolve_fh_params(pars); }
- f_l1ctl_est_dchan(L1CTL, pars);
+ /* Tune the L1 to that PDCH channel */
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_DL_TBF_CFG_REQ(0, '00000001'B));
/* Verify PTCCH/U: send several access bursts, make sure they're received */
for (var integer i := 0; i < 16; i := i + 1) {
@@ -4723,25 +5753,13 @@ testcase TC_pcu_ptcch() runs on test_CT {
* let's give it more time in case if we miss the beginning. */
T.start(2.0 * 2.0 * 52.0 * 4.615 / 1000.0);
alt {
- /* PDCH is considered as traffic in trxcon => expect TRAFFIC.ind */
- [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(chan_nr := t_RslChanNr_PDCH(7),
- link_id := tr_RslLinkID_OSMO_PTCCH(?),
- frame := data)) -> value dl {
- log("Rx PTCCH/D data (traffic) block on L1CTL: ", dl);
- setverdict(pass);
- T.stop;
- }
- /* Other PHYs (e.g. virt_phy) may consider PDCH as data => expect DATA.ind */
- [] L1CTL.receive(tr_L1CTL_DATA_IND(chan_nr := t_RslChanNr_PDCH(7),
- link_id := tr_RslLinkID_OSMO_PTCCH(?),
- l2_data := data)) -> value dl {
- log("Rx PTCCH/D data block on L1CTL: ", dl);
+ [] L1CTL.receive(tr_L1CTL_GPRS_DL_BLOCK_IND(fn := ?, tn := 7, data := data)) {
setverdict(pass);
T.stop;
}
[] L1CTL.receive { repeat; }
[] T.timeout {
- setverdict(fail, "Timeout waiting for DATA.ind on L1CTL");
+ setverdict(fail, "Timeout waiting DL BLOCK.ind with PTCCH/D");
}
}
}
@@ -4749,12 +5767,13 @@ testcase TC_pcu_ptcch() runs on test_CT {
/* Send AGCH from PCU; check it appears on Um side */
testcase TC_pcu_data_req_agch() runs on test_CT {
timer T := 3.0;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
f_TC_pcu_act_req(0, 0, 7, true);
- f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_AGCH, c_PCU_DATA);
+ f_PCUIF_tx_mac_block_agch(PCU, g_pcu_conn_id, c_PCU_DATA, confirm := false,
+ wait_for_cnf := false, msg_id := 'ffffffff'O);
T.start;
alt {
@@ -4768,16 +5787,22 @@ testcase TC_pcu_data_req_agch() runs on test_CT {
}
}
-/* Send AGCH from PCU; check it appears on Um side */
+/* Send PCH from PCU; check it appears on Um side */
testcase TC_pcu_data_req_pch() runs on test_CT {
timer T := 3.0;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
f_TC_pcu_act_req(0, 0, 7, true);
- /* three characters prefix: last 3 digits of IMSI as ASCII */
- f_pcu_data_req(0, 0, 7, 0, 0, PCU_IF_SAPI_PCH, '313233'O & c_PCU_DATA);
+
+ var PCUIF_pch pch := {
+ msg_id := '01020304'O,
+ imsi := "00101000000000123",
+ data := c_PCU_DATA,
+ confirm := false
+ };
+ f_pcu_data_req(0, 0, 0, 0, 0, PCU_IF_SAPI_PCH_2, enc_PCUIF_pch(pch));
T.start;
alt {
@@ -4793,13 +5818,15 @@ testcase TC_pcu_data_req_pch() runs on test_CT {
/* Send IMM.ASS from PCU for PCH; check it appears on Um side */
testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
- var octetstring imm_ass := f_rnd_octstring(23);
- f_init_pcu_test();
+ var octetstring req_ref := f_rnd_octstring(3);
+ var octetstring tlli := f_rnd_octstring(4);
+ var octetstring imm_ass := '2d063f300fc364'O & req_ref & '0000dc'O & tlli & '00232b2b2b2b'O;
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
- /* append 3 last imsi digits so BTS can compute pagng group */
- var uint32_t fn := f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
+ /* The BTS will use the last three IMSI digits to compute paging group. */
+ f_PCUIF_tx_imm_ass_pch(PCU, g_pcu_conn_id, imm_ass, '123459987'H);
timer T := 0.5;
T.start;
@@ -4810,6 +5837,30 @@ testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
}
[] L1CTL.receive { repeat; }
[] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated PCH block on Um");
+ }
+ }
+}
+
+/* Send IMM.ASS from PCU for AGCH; check it appears on Um side */
+testcase TC_pcu_data_req_imm_ass_agch() runs on test_CT {
+ var octetstring req_ref := f_rnd_octstring(3);
+ var octetstring tlli := f_rnd_octstring(4);
+ var octetstring imm_ass := '2d063f300fc364'O & req_ref & '0000dc'O & tlli & '00232b2b2b2b'O;
+ f_init_with_pcuif();
+ f_init_l1ctl();
+ f_l1_tune(L1CTL);
+
+ f_PCUIF_tx_mac_block_agch(PCU, g_pcu_conn_id, imm_ass);
+
+ timer T := 0.5;
+ T.start;
+ alt {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, imm_ass)) {
+ setverdict(pass);
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU-originated AGCH block on Um");
}
}
@@ -4817,12 +5868,13 @@ testcase TC_pcu_data_req_imm_ass_pch() runs on test_CT {
/* Send RACH from Um side, expect it to show up on PCU socket */
testcase TC_pcu_rach_content() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
var GsmFrameNumber fn_last := 0;
for (var integer i := 0; i < 1000; i := i+1) {
+ var PCUIF_Message msg;
var OCT1 ra := f_rnd_ra_ps();
var GsmFrameNumber fn := f_L1CTL_RACH(L1CTL, oct2int(ra));
if (fn == fn_last) {
@@ -4833,10 +5885,10 @@ testcase TC_pcu_rach_content() runs on test_CT {
timer T := 2.0;
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND(0, 0, 0, oct2int(ra), 0, ?, fn))) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RACH_IND(0, 0, 0, oct2int(ra), 0, ?, fn)) {
T.stop;
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RACH_IND) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RACH IND");
}
[] PCU.receive { repeat; }
@@ -4855,10 +5907,10 @@ testcase TC_pcu_ext_rach_content() runs on test_CT {
var GsmFrameNumber fn_last := 0;
var L1ctlRachSynchSeq synch_seq;
var PCUIF_BurstType pcu_bt;
- var GsmFrameNumber fn;
+ var GsmFrameNumber fn
var BIT11 ra11;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
@@ -4888,13 +5940,14 @@ testcase TC_pcu_ext_rach_content() runs on test_CT {
burst_type := pcu_bt,
fn := fn);
+ var PCUIF_Message msg;
timer T := 2.0;
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, pcu_rach_ind)) {
+ [] as_pcuif_msg(msg, pcu_rach_ind) {
T.stop;
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RACH_IND)) {
+ [] as_pcuif_msg(msg, tr_PCUIF_RACH_IND) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected RACH IND");
}
[] PCU.receive { repeat; }
@@ -4906,25 +5959,22 @@ testcase TC_pcu_ext_rach_content() runs on test_CT {
setverdict(pass);
}
-private function f_TC_pcu_data_ind_lqual_cb(int16_t lqual_cb_exp, int16_t thresh)
+private function f_TC_pcu_data_ind_lqual_cb(int16_t lqual_cb_exp)
runs on test_CT {
- var template PCUIF_send_data sdt;
- var PCUIF_send_data sd;
- var int16_t lqual_cb;
+ var PCUIF_Message msg;
timer T := 1.0;
- /* PCUIF_DATA.ind is encapsulated into a supplementary record */
- sdt := t_SD_PCUIF_MSGT(g_pcu_conn_id, PCU_IF_MSG_DATA_IND);
+ L1CTL.clear;
+ PCU.clear;
- /* Send a random PDTCH frame over Um */
- L1CTL.send(ts_L1CTL_TRAFFIC_REQ(ts_RslChanNr_PDCH(7), ts_RslLinkID_DCCH(0),
- '0000'O & f_rnd_octstring(21)));
+ /* Send a random Uplink block over the Um */
+ var octetstring data := '0000'O & f_rnd_octstring(21);
+ f_TC_pcu_tx_ul_block_req(data, tn := 7);
T.start;
alt {
- /* If expected link quality is above the threshold */
- [lqual_cb_exp >= thresh] PCU.receive(sdt) -> value sd {
- lqual_cb := sd.data.u.data_ind.lqual_cb;
+ [] as_pcuif_msg(msg, tr_PCUIF_DATA_IND(data := data)) {
+ var integer lqual_cb := msg.u.data_ind.lqual_cb;
log("Rx PCUIF_DATA.ind (lqual_cb=", lqual_cb, ")");
/* Make sure the actual link quality matches the expected value */
@@ -4935,18 +5985,9 @@ runs on test_CT {
setverdict(pass);
}
}
- /* If expected link quality is below the threshold */
- [lqual_cb_exp < thresh] PCU.receive(sdt) -> value sd {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- log2str("Rx unexpected PCUIF_DATA.ind: ", sd.data));
- }
/* Ignore PCUIF_RTS.req and PCUIF_TIME.ind */
[] PCU.receive { repeat; }
- [lqual_cb_exp < thresh] T.timeout {
- log("Rx nothing, as expected");
- setverdict(pass);
- }
- [lqual_cb_exp >= thresh] T.timeout {
+ [] T.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
"Timeout waiting for PCUIF_DATA.ind");
}
@@ -4955,7 +5996,7 @@ runs on test_CT {
/* Verify C/I (Carrier-to-Interference ratio) processing of PDTCH frames */
testcase TC_pcu_data_ind_lqual_cb() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
PCU.clear;
f_init_l1ctl();
@@ -4965,31 +6006,29 @@ testcase TC_pcu_data_ind_lqual_cb() runs on test_CT {
f_TC_pcu_act_req(0, 0, 7, true);
/* Tune trxcon to that PDCH channel on TS7 */
- var ConnHdlrPars pars := valueof(t_Pars(ts_RslChanNr_PDCH(7), ts_RSL_ChanMode_SIGN));
- if (mp_freq_hop_enabled and mp_transceiver_num > 1)
- { f_resolve_fh_params(pars); }
- f_l1ctl_est_dchan(L1CTL, pars);
+ f_TC_pcu_l1ctl_est_pdch(7);
+ L1CTL.send(ts_L1CTL_GPRS_UL_TBF_CFG_REQ(0, '00000001'B));
/* C/I in centiBels, test range: -256 .. +1280, step 128 */
for (var int16_t i := -256; i <= 1280; i := i + 128) {
var TrxcMessage ret;
- ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
- valueof(ts_TRXC_FAKE_CI(i)));
+ ret := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id, ts_TRXC_FAKE_CI(i));
- /* FIXME: OsmoBTS may have different threshold (see MIN_QUAL_NORM) */
- f_TC_pcu_data_ind_lqual_cb(i, thresh := 0);
+ log("Testing C/I=", i, " cB");
+ f_TC_pcu_data_ind_lqual_cb(i);
}
}
/* Send PAGING via RSL, expect it to shw up on PCU socket */
testcase TC_pcu_paging_from_rsl() runs on test_CT {
- f_init_pcu_test();
+ f_init_with_pcuif();
for (var integer i := 0; i < 100; i := i+1) {
var MobileIdentityLV mi_lv;
var octetstring mi_lv_enc;
var MobileIdentityV mi;
+ var PCUIF_Message msg;
timer T := 3.0;
if (i < 50) {
@@ -5007,9 +6046,9 @@ testcase TC_pcu_paging_from_rsl() runs on test_CT {
RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_PAGING_CMD(mi, i mod 4)));
T.start;
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ(0, mi_lv_enc))) {
+ [] as_pcuif_msg(msg, tr_PCUIF_PAG_REQ(0, mi_lv_enc)) {
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_PAG_REQ)) {
+ [] as_pcuif_msg(msg, tr_PCUIF_PAG_REQ) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected PAGING REQ");
}
[] PCU.receive { repeat; }
@@ -5023,28 +6062,28 @@ testcase TC_pcu_paging_from_rsl() runs on test_CT {
/* test for periodic TIME_IND; check number of FN expired and number of TIME_IND within frames */
testcase TC_pcu_time_ind() runs on test_CT {
- var PCUIF_send_data pcu_sd;
var integer num_time_ind := 0;
var integer first_fn, last_fn;
var float test_duration := 5.0;
+ var PCUIF_Message msg;
timer T;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 7, true);
PCU.clear;
T.start(test_duration);
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TIME_IND(0, ?))) -> value pcu_sd {
+ [] as_pcuif_msg(msg, tr_PCUIF_TIME_IND(0, ?)) {
num_time_ind := num_time_ind + 1;
if (not isbound(first_fn)) {
- first_fn := pcu_sd.data.u.time_ind.fn;
+ first_fn := msg.u.time_ind.fn;
}
- last_fn := pcu_sd.data.u.time_ind.fn;
+ last_fn := msg.u.time_ind.fn;
repeat;
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TIME_IND(?, ?))) -> value pcu_sd {
- setverdict(fail, "Received unexpected PCUIF_TIME_IND: ", pcu_sd.data);
+ [] as_pcuif_msg(msg, tr_PCUIF_TIME_IND(?, ?)) {
+ setverdict(fail, "Received unexpected PCUIF_TIME_IND: ", msg);
repeat;
}
[] PCU.receive {
@@ -5076,39 +6115,37 @@ testcase TC_pcu_time_ind() runs on test_CT {
/* test for periodic RTS_REQ; check number of FN expired and number of RTS_IND per SAPI */
testcase TC_pcu_rts_req() runs on test_CT {
- var PCUIF_send_data pcu_sd;
var integer first_fn, last_fn;
var integer num_rts_pdtch := 0;
var integer num_rts_ptcch := 0;
var float test_duration := 5.0;
+ var PCUIF_Message msg;
timer T;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 7, true);
PCU.clear;
T.start(test_duration);
alt {
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PDTCH, ?, ?)))
- -> value pcu_sd {
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PDTCH, ?, ?)) {
num_rts_pdtch := num_rts_pdtch + 1;
if (not isbound(first_fn)) {
- first_fn := pcu_sd.data.u.rts_req.fn;
+ first_fn := msg.u.rts_req.fn;
}
- last_fn := pcu_sd.data.u.rts_req.fn;
+ last_fn := msg.u.rts_req.fn;
repeat;
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PTCCH, ?, ?)))
- -> value pcu_sd {
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ(0, 0, 7, PCU_IF_SAPI_PTCCH, ?, ?)) {
num_rts_ptcch := num_rts_ptcch + 1;
if (not isbound(first_fn)) {
- first_fn := pcu_sd.data.u.rts_req.fn;
+ first_fn := msg.u.rts_req.fn;
}
- last_fn := pcu_sd.data.u.rts_req.fn;
+ last_fn := msg.u.rts_req.fn;
repeat;
}
- [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_RTS_REQ)) -> value pcu_sd {
- setverdict(fail, "Received unexpected PCUIF_RTS_REQ: ", pcu_sd.data);
+ [] as_pcuif_msg(msg, tr_PCUIF_RTS_REQ) {
+ setverdict(fail, "Received unexpected PCUIF_RTS_REQ: ", msg);
repeat;
}
[] PCU.receive {
@@ -5155,12 +6192,12 @@ testcase TC_pcu_oml_alert() runs on test_CT {
var float test_duration := 5.0;
timer T;
- f_init_pcu_test();
+ f_init_with_pcuif();
f_TC_pcu_act_req(0, 0, 7, true);
/* re-connect CTRL port from BTS to BSC */
f_ipa_ctrl_stop();
- f_ipa_ctrl_start(mp_bsc_ctrl_ip, mp_bsc_ctrl_port);
+ f_ipa_ctrl_start_client(mp_bsc_ctrl_ip, mp_bsc_ctrl_port);
/* Send that OML Alert */
PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_OML_ALERT, testcasename())));
@@ -5220,7 +6257,7 @@ testcase TC_pcu_rr_suspend() runs on test_CT {
var ConnHdlrPars pars;
var ConnHdlr vc_conn;
- f_init();
+ f_init_with_pcuif();
pars := valueof(t_Pars(t_RslChanNr_SDCCH4(0,3), ts_RSL_ChanMode_SIGN));
vc_conn := f_start_handler(refers(f_TC_rr_suspend_req), pars, true);
@@ -5229,32 +6266,46 @@ testcase TC_pcu_rr_suspend() runs on test_CT {
/* Ensure that PCUIF socket can accept only a single connection */
testcase TC_pcu_socket_connect_multi() runs on test_CT {
+ var boolean connected := false;
+ var UD_connect_result cr;
+ var integer cid;
timer T := 5.0;
+ var template UD_Result tr_ok := { result_code := SUCCESS, err := omit };
+ var template UD_Result tr_err := { result_code := ERROR, err := ? };
+
/* this (among other things) establishes the first connection to the PCUIF socket */
- f_init();
+ f_init_with_pcuif();
- /* try to establish a second connection, expect it to fail */
+ /* try to establish a second connection */
PCU.send(UD_connect:{mp_pcu_socket, -1});
T.start;
alt {
- [] PCU.receive(UD_connect_result:{id := ?, result := { result_code := ERROR, err := ? }}) {
- setverdict(pass);
+ /* the IUT will first accept() the new connection, and close() it immediately */
+ [not connected] PCU.receive(UD_connect_result:{ id := ?, result := tr_ok }) -> value cr {
+ log("BTS has accept()ed connection");
+ connected := true;
+ cid := cr.id;
+ repeat;
}
- [] PCU.receive(UD_connect_result:?) {
- setverdict(fail, "Unexpected unix domain connect result");
+ [connected] PCU.receive(UD_connect_result:{ id := cid, result := tr_err }) {
+ log("BTS has close()d connection");
+ setverdict(pass);
}
+ /* ignore other messages related to the first connection */
+ [] PCU.receive { repeat; }
[] T.timeout {
- setverdict(pass);
+ setverdict(fail, "Timeout waiting for connection result");
}
}
+
Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
/* Ensure that PCUIF socket can disconnect + reconnect */
testcase TC_pcu_socket_reconnect() runs on test_CT {
/* this (among other things) establishes the first connection to the PCUIF socket */
- f_init();
+ f_init_with_pcuif();
f_sleep(1.0);
@@ -5274,7 +6325,7 @@ testcase TC_pcu_socket_reconnect() runs on test_CT {
/* Ensure that GPRS capability is not advertised before PCU socket conncet */
private function f_get_si(L1CTL_PT pt, RrMessageType si_type)
runs on test_CT return SystemInformation {
- var L1ctlDlMessage l1_dl;
+ var L1ctlMessage l1_dl;
var SystemInformation si;
var integer rc;
timer T := 5.0;
@@ -5315,13 +6366,7 @@ runs on test_CT return boolean {
/* Make sure that GPRS Indicator is absent when the PCU is not connected */
private function f_TC_pcu_socket_noconnect(RrMessageType si_type)
runs on test_CT {
- /* don't call f_init() as this would connect PCU socket */
- f_init_rsl(testcasename());
-
- /* Send both System Information Type 3 and 4 (with GPRS Indicator) */
- f_rsl_bcch_fill(RSL_SYSTEM_INFO_3, ts_SI3_default);
- f_rsl_bcch_fill(RSL_SYSTEM_INFO_4, ts_SI4_default);
-
+ f_init();
f_init_l1ctl();
f_l1_tune(L1CTL);
f_sleep(2.0);
@@ -5348,7 +6393,7 @@ testcase TC_pcu_socket_noconnect_nosi4gprs() runs on test_CT {
private function f_TC_pcu_socket_connect(RrMessageType si_type)
runs on test_CT {
/* this (among other things) establishes the first connection to the PCUIF socket */
- f_init();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
@@ -5376,7 +6421,7 @@ testcase TC_pcu_socket_connect_si4gprs() runs on test_CT {
private function f_TC_pcu_socket_disconnect(RrMessageType si_type)
runs on test_CT {
/* this (among other things) establishes the first connection to the PCUIF socket */
- f_init();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL);
@@ -5413,7 +6458,16 @@ testcase TC_pcu_socket_disconnect_nosi4gprs() runs on test_CT {
testcase TC_pcu_socket_verify_info_ind() runs on test_CT {
var SystemInformation si3 := valueof(ts_SI3_default);
- f_init();
+ f_init_with_pcuif();
+
+ /* actually give the BTS some time to fully come up and to send a PCU INFO IND with the correct
+ * information */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] as_pcu_info_ind(PCU, g_pcu_conn_id, g_pcu_last_info) { repeat; }
+ [] T.timeout {}
+ }
/* Verify cell_id */
var uint16_t cell_id_si3 := si3.payload.si3.cell_id;
@@ -5434,6 +6488,192 @@ testcase TC_pcu_socket_verify_info_ind() runs on test_CT {
setverdict(pass);
}
+/* Verify hopping parameters in the INFO.ind message (version >= 10) */
+testcase TC_pcu_info_ind_fh_params() runs on test_CT {
+ var PCUIF_info_ind info_ind;
+ var FreqHopPars fhp;
+
+ f_init_with_pcuif();
+
+ info_ind := g_pcu_last_info.u.info_ind;
+
+ for (var integer i := 0; i < mp_transceiver_num; i := i + 1) {
+ for (var integer tn := 0; tn < 8; tn := tn + 1) {
+ if (info_ind.trx[i].pdch_mask[tn] != '1'B) {
+ /* Skip inactive timeslots */
+ continue;
+ }
+
+ if (mp_freq_hop_enabled and mp_transceiver_num > 1)
+ { f_resolve_fh_params(fhp, tn, trx_nr := i); }
+ else
+ { fhp.enabled := false; }
+
+ var template PCUIF_InfoTrxTs tr_ts;
+ if (fhp.enabled) {
+ tr_ts := tr_PCUIF_InfoTrxTsH1(
+ hsn := fhp.maio_hsn.hsn,
+ maio := fhp.maio_hsn.maio,
+ ma := f_pad_bit(fhp.ma_map.ma, 64, '0'B),
+ ma_bit_len := mp_transceiver_num);
+ } else {
+ tr_ts := tr_PCUIF_InfoTrxTsH0;
+ }
+
+ var PCUIF_InfoTrxTs ts := info_ind.trx[i].ts[tn];
+ log("Checking timeslot #", tn, " of trx#", i, ": ", ts);
+ if (not match(ts, tr_ts)) {
+ setverdict(fail, "Hopping parameters do not match: ",
+ "received ", ts, " vs expected ", tr_ts);
+ } else {
+ setverdict(pass);
+ }
+ }
+ }
+}
+
+/* Verify IPv4 NSVC address in the INFO.ind message */
+testcase TC_pcu_socket_nsvc_ipv4() runs on test_CT {
+ f_init_vty_bsc();
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 remote ip 127.127.127.127");
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init_with_pcuif();
+
+ var PCUIF_RemoteAddr remote_addr := g_pcu_last_info.u.info_ind.remote_addr;
+ var template PCUIF_RemoteAddr tr_remote_addr := {
+ addr_type := { PCUIF_ADDR_TYPE_IPV4, ? },
+ addr := { f_pad_oct(f_inet_addr("127.127.127.127"), 16, '00'O), ? }
+ };
+
+ if (not match(remote_addr, tr_remote_addr)) {
+ setverdict(fail, "NSVC address ", remote_addr, " does not match ", tr_remote_addr);
+ }
+
+ setverdict(pass);
+}
+
+/* Verify IPv4 NSVC address in the INFO.ind message */
+testcase TC_pcu_socket_nsvc_ipv6() runs on test_CT {
+ f_init_vty_bsc();
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 remote ip fd00::ca:ff:ee");
+
+ f_init_with_pcuif();
+
+ var PCUIF_RemoteAddr remote_addr := g_pcu_last_info.u.info_ind.remote_addr;
+ var template PCUIF_RemoteAddr tr_remote_addr := {
+ addr_type := { PCUIF_ADDR_TYPE_IPV6, ? },
+ addr := { f_inet6_addr("fd00::ca:ff:ee"), ? }
+ };
+
+ if (not match(remote_addr, tr_remote_addr)) {
+ setverdict(fail, "NSVC address ", remote_addr, " does not match ", tr_remote_addr);
+ }
+
+ setverdict(pass);
+}
+
+/* Verify coding of two NSVCs in the INFO.ind message */
+testcase TC_pcu_socket_two_nsvc() runs on test_CT {
+ f_init_vty_bsc();
+
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 nsvci 1234");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 local udp port 1234");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 remote ip 127.127.127.127");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 0 remote udp port 1234");
+
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 1 nsvci 5678");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 1 local udp port 5678");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 1 remote ip fd00::ca:ff:ee");
+ f_vty_config2(BSCVTY, {"network", "bts 0"} , "gprs nsvc 1 remote udp port 5678");
+
+ f_init_with_pcuif();
+
+ var PCUIF_info_ind info_ind := g_pcu_last_info.u.info_ind;
+ var PCUIF_RemoteAddr remote_addr := info_ind.remote_addr;
+ var template PCUIF_RemoteAddr tr_remote_addr := {
+ addr_type := { PCUIF_ADDR_TYPE_IPV4, PCUIF_ADDR_TYPE_IPV6 },
+ addr := {
+ f_pad_oct(f_inet_addr("127.127.127.127"), 16, '00'O),
+ f_inet6_addr("fd00::ca:ff:ee")
+ }
+ };
+
+ if (not match(info_ind.nsvci, { 1234, 5678 }))
+ { setverdict(fail, "NSVCI ", info_ind.nsvci, " does not match { 1234, 5678 }"); }
+ if (not match(remote_addr, tr_remote_addr))
+ { setverdict(fail, "NSVC address ", remote_addr, " does not match ", tr_remote_addr); }
+ if (not match(info_ind.local_port, { 1234, 5678 }))
+ { setverdict(fail, "NSVC lport ", info_ind.local_port, " does not match { 1234, 5678 }"); }
+ if (not match(info_ind.remote_port, { 1234, 5678 }))
+ { setverdict(fail, "NSVC rport ", info_ind.remote_port, " does not match { 1234, 5678 }"); }
+
+ setverdict(pass);
+}
+
+/* Verify periodic interference reports on PDCH */
+testcase TC_pcu_interf_ind() runs on test_CT {
+ var template PCUIF_Message tr_interf_ind;
+ var integer interf_ind_num := 0;
+ var boolean first := true;
+ var PCUIF_Message msg;
+ timer T;
+
+ /* Set the averaging/reporting period to 480ms */
+ f_init_vty_bsc();
+ f_vty_cfg_bts(BSCVTY, 0, { "interference-meas avg-period 1" });
+ f_vty_transceive(BSCVTY, "drop bts connection 0 oml");
+
+ f_init_with_pcuif();
+ f_TC_pcu_act_req(0, 0, 7, true);
+
+ /* We need trxcon for NOPE indications */
+ f_init_l1ctl();
+ f_l1_tune(L1CTL);
+
+ /* Expect -120 .. -90 dBm on TS7 of BTS0/TRX0 */
+ tr_interf_ind := tr_PCUIF_INTERF_IND(
+ bts_nr := 0,
+ trx_nr := 0,
+ fn := ?,
+ interf := { 0, 0, 0, 0, 0, 0, 0, (90..120) }
+ );
+
+ T.start(0.480 * 1.5);
+ alt {
+ /* The first interference report may contain unreliable values, so we ignore it */
+ [first] as_pcuif_msg(msg, tr_PCUIF_INTERF_IND(0, 0)) {
+ /* 4 SACCH periods => 4 reports (plus some guard time) */
+ T.start(0.480 * 4.0 + 0.480 / 2.0);
+ first := false;
+ repeat;
+ }
+ /* Subsequent interference reports shall match our expectations */
+ [not first] as_pcuif_msg(msg, tr_interf_ind) {
+ /* Check TDMA frame number period */
+ if (msg.u.interf_ind.fn mod 104 != 0) {
+ setverdict(fail, "Odd TDMA frame number := ",
+ msg.u.interf_ind.fn);
+ }
+ interf_ind_num := interf_ind_num + 1;
+ if (interf_ind_num < 4)
+ { repeat; }
+ }
+ [not first] as_pcuif_msg(msg, tr_PCUIF_INTERF_IND(0, 0)) {
+ setverdict(fail, "Received unexpected interference report: ", msg);
+ }
+ [] PCU.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for interference reports");
+ }
+ }
+
+ /* Reset the averaging/reporting period back to default */
+ f_vty_cfg_bts(BSCVTY, 0, { "interference-meas avg-period 6" });
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/***********************************************************************
* Osmocom Style Dynamic Timeslot Support
***********************************************************************/
@@ -5444,7 +6684,7 @@ runs on ConnHdlr {
var PCUIF_send_data sd;
[] PCU.receive(t_SD_PCUIF(pcu_conn_id, tr_PCUIF_INFO_IND(bts_nr, ?))) -> value sd {
- var bitstring pdch_mask := sd.data.u.info_ind.trx[trx_nr].pdch_mask;
+ var BIT8 pdch_mask := sd.data.u.info_ind.trx[trx_nr].pdch_mask;
if (substr(pdch_mask, g_chan_nr.tn, 1) != exp) {
repeat;
}
@@ -5631,6 +6871,111 @@ testcase TC_dyn_osmo_pdch_tchh_act() runs on test_CT {
vc_conn.done;
}
+/* try to RSL CHAN ACT the SDCCH8 on an osmocom-style PDCH */
+private function f_TC_dyn_osmo_pdch_sdcch8_act(charstring id) runs on ConnHdlr {
+ var PCUIF_Message first_info;
+ var integer ts_nr := g_chan_nr.tn;
+ var integer trx_nr := 0;
+ var integer bts_nr := 0;
+ var integer pcu_conn_id := -1;
+ var RslChannelNr chan_nr[8] := { valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 0)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 1)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 2)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 3)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 4)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 5)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 6)),
+ valueof(t_RslChanNr_SDCCH8(g_chan_nr.tn, 7)) };
+
+ /* register for the TCH/H channel numbers */
+ for (var integer i := 0; i < lengthof(chan_nr); i := i + 1) {
+ f_rslem_register(0, chan_nr[i]);
+ }
+
+ f_init_pcu(PCU, id, pcu_conn_id, first_info);
+
+ for (var integer i := 0; i < lengthof(chan_nr); i := i + 1) {
+ f_rsl_transceive(ts_RSL_CHAN_ACT(chan_nr[i], g_pars.chan_mode),
+ tr_RSL_CHAN_ACT_ACK(chan_nr[i]), "RSL CHAN ACT [" & int2str(i) & "]");
+ }
+ setverdict(pass);
+}
+testcase TC_dyn_osmo_pdch_sdcch8_act() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+
+ pars := valueof(t_Pars(t_RslChanNr_PDCH(4), ts_RSL_ChanMode_SIGN));
+ vc_conn := f_start_handler(refers(f_TC_dyn_osmo_pdch_sdcch8_act), pars, true);
+ vc_conn.done;
+}
+
+/* Reproduce a race condition described in OS#5245 */
+private function f_rsl_chan_act_deact(charstring id) runs on ConnHdlr {
+ f_rsl_chan_act(g_pars.chan_mode);
+ f_sleep(1.0);
+ f_rsl_chan_deact();
+ setverdict(pass);
+}
+testcase TC_dyn_osmo_pdch_tchh_race_act() runs on test_CT {
+ var ConnHdlrPars pars[2];
+ var ConnHdlr vc_conn[2];
+ var TrxcMessage rsp;
+
+ f_init();
+
+ /* Configure an artificial delay of 200 ms for TRXC RSP messages */
+ rsp := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
+ ts_TRXC_FAKE_TRXC_DELAY(200));
+
+ /* Activate all sub-channels of TCH/H on TS4 immediately in hope that the second
+ * CHANnel ACTIVation message will be handled before the PHY responds to 'SETSLOT' */
+ for (var integer i := 0; i < sizeof(pars); i := i + 1) {
+ /* TS4 is an Osmocom style dynamic timeslot, we want it to be TCH/H */
+ pars[i] := valueof(t_Pars(t_RslChanNr_Lm(4, i), ts_RSL_ChanMode_SIGN));
+ vc_conn[i] := f_start_handler(refers(f_rsl_chan_act_deact),
+ pars[i], l1ctl := false);
+ }
+
+ /* Wait for all components to finish */
+ for (var integer i := 0; i < sizeof(pars); i := i + 1) {
+ vc_conn[i].done;
+ }
+
+ /* Disable the artificial delay for TRXC RSP messages */
+ rsp := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
+ ts_TRXC_FAKE_TRXC_DELAY(0));
+}
+testcase TC_dyn_osmo_pdch_sdcch8_race_act() runs on test_CT {
+ var ConnHdlrPars pars[8];
+ var ConnHdlr vc_conn[8];
+ var TrxcMessage rsp;
+
+ f_init();
+
+ /* Configure an artificial delay of 200 ms for TRXC RSP messages */
+ rsp := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
+ ts_TRXC_FAKE_TRXC_DELAY(200));
+
+ /* Activate all sub-channels of SDCCH/8 on TS4 immediately in hope that subsequent
+ * CHANnel ACTIVation messages will be handled before the PHY responds to 'SETSLOT' */
+ for (var integer i := 0; i < sizeof(pars); i := i + 1) {
+ /* TS4 is an Osmocom style dynamic timeslot, we want it to be SDCCH/8 */
+ pars[i] := valueof(t_Pars(t_RslChanNr_SDCCH8(4, i), ts_RSL_ChanMode_SIGN));
+ vc_conn[i] := f_start_handler(refers(f_rsl_chan_act_deact),
+ pars[i], l1ctl := false);
+ }
+
+ /* Wait for all components to finish */
+ for (var integer i := 0; i < sizeof(pars); i := i + 1) {
+ vc_conn[i].done;
+ }
+
+ /* Disable the artificial delay for TRXC RSP messages */
+ rsp := f_TRXC_transceive(BTS_TRXC, g_bts_trxc_conn_id,
+ ts_TRXC_FAKE_TRXC_DELAY(0));
+}
+
/***********************************************************************
* IPA Style Dynamic Timeslot Support
***********************************************************************/
@@ -5818,7 +7163,7 @@ private function f_tx_lapdm(template (value) LapdmFrame l,
/* TODO: we can use an extension of TTCN-3 for padding, i.e. PADDING('2B'O) */
if (valueof(link_id.c) == SACCH) {
/* Compose dummy L1 header */
- l1h := ts_SacchL1Header(g_pars.l1_pars.ms_power_level, false, g_pars.l1_pars.ms_actual_ta);
+ l1h := ts_SacchL1Header(g_pars.l1_pars.ms_power_level, g_pars.l1_pars.ms_actual_ta);
L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(g_chan_nr, link_id, l1h, f_pad_oct(l2, 21, '2B'O)));
} else {
/* If required, pad L2 frame with constant 0x2b filling */
@@ -5826,19 +7171,23 @@ private function f_tx_lapdm(template (value) LapdmFrame l,
}
}
-private type record RllTestCase {
- uint3_t sapi,
- RslLinkId link_id,
- octetstring l3,
- boolean exp
+friend type record RllTestCase {
+ uint3_t sapi,
+ RslLinkId link_id,
+ octetstring l3,
+ boolean exp,
+ RSL_IE_ActivationType act_type
}
-private type record of RllTestCase RllTestCases;
-private template RllTestCase t_EITC(uint3_t sapi, RslLinkId id,
- octetstring l3, boolean exp) := {
+friend type record of RllTestCase RllTestCases;
+friend template RllTestCase t_EITC(template (present) uint3_t sapi,
+ template (present) RslLinkId id,
+ octetstring l3, boolean exp,
+ RSL_IE_ActivationType act_type := t_RSL_IE_ActType_IA) := {
sapi := sapi,
link_id := id,
l3 := l3,
- exp := exp
+ exp := exp,
+ act_type := act_type
}
/* execute the same callback function with a set of different parameters (tcs) on a
@@ -5873,7 +7222,7 @@ private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
RSL.clear;
/* activate the logical channel */
- f_est_dchan();
+ f_est_dchan(act_type := tc.act_type);
L1CTL.clear;
f_tx_lapdm(ts_LAPDm_SABM(tc.sapi, cr_MO_CMD, true, tc.l3), tc.link_id);
@@ -5910,16 +7259,18 @@ private function f_TC_rll_est_ind(charstring id) runs on ConnHdlr {
testcase TC_rll_est_ind() runs on test_CT {
var RllTestCases tcs := {
/* SAPI0 establishment (contention resolution) */
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
- /* normal SAPI0 establishment */
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), ''O, true)),
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), '01020304'O, true)),
+ /* normal SAPI0 establishment (immediate assignment) */
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), ''O, false)),
+ /* normal SAPI0 establishment (normal assignment) */
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), ''O, true, t_RSL_IE_ActType_ASS)),
/* SAPI 3 doesn't support contention resolution */
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), '01020304'O, false)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), '01020304'O, false)),
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), '01020304'O, false)),
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), '01020304'O, false)),
/* normal SAPI3 establishment on main DCCH */
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), ''O, true)),
/* normal SAPI3 establishment on SACCH */
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), ''O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_est_ind));
}
@@ -5927,7 +7278,7 @@ testcase TC_rll_est_ind() runs on test_CT {
/* test if RLL EST REQ trigeres SABM on Um; UA on Um triggers EST CONF (TS 48.058 3.2) */
private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
var RllTestCase tc := g_pars.spec.rll;
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
timer T := 3.0;
f_l1_tune(L1CTL);
@@ -5941,21 +7292,7 @@ private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
RSL.send(ts_RSL_EST_REQ(g_chan_nr, tc.link_id));
T.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
- var LapdmFrame lapdm;
- var octetstring l2 := dl.payload.data_ind.payload;
- if (dl.dl_info.link_id.c == SACCH) {
- /* remove L1 header */
- l2 := substr(l2, 2, lengthof(l2)-2);
- }
- lapdm.ab := dec_LapdmFrameAB(l2);
- if (match(lapdm, tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O))) {
- setverdict(pass);
- } else {
- repeat;
- }
- }
- [] L1CTL.receive { repeat; }
+ [] as_l1_exp_lapdm(tr_LAPDm_SABM(tc.sapi, cr_MT_CMD, true, ''O));
[] T.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for SABM");
}
@@ -5968,21 +7305,21 @@ private function f_TC_rll_est_req(charstring id) runs on ConnHdlr {
testcase TC_rll_est_req_DCCH_3() runs on test_CT {
var RllTestCases tcs := {
/* normal SAPI3 establishment on main DCCH */
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))//,
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), ''O, true))//,
};
f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
}
testcase TC_rll_est_req_ACCH_3() runs on test_CT {
var RllTestCases tcs := {
/* normal SAPI3 establishment on SACCH */
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), ''O, true))
}
f_rll_testmatrix(tcs, refers(f_TC_rll_est_req));
}
/* altstep to receive a LAPDm frame matching the given template */
-private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
- var L1ctlDlMessage dl;
+friend altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
+ var L1ctlMessage dl;
[] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
var LapdmFrame lapdm;
var octetstring l2 := dl.payload.data_ind.payload;
@@ -5996,6 +7333,8 @@ private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
lapdm.b4 := dec_LapdmFrameB4(l2);
} else if (ischosen(exp.bbis)) {
lapdm.bbis := dec_LapdmFrameBbis(l2);
+ } else if (ischosen(exp.bter)) {
+ lapdm.bter := dec_LapdmFrameBter(l2);
}
log("Rx LAPDm ", lapdm);
if (match(lapdm, exp)) {
@@ -6006,7 +7345,7 @@ private altstep as_l1_exp_lapdm(template LapdmFrame exp) runs on ConnHdlr {
}
[] L1CTL.receive { repeat; }
}
-private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
+friend function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on ConnHdlr {
timer T := t;
T.start;
alt {
@@ -6018,10 +7357,12 @@ private function f_l1_exp_lapdm(template LapdmFrame exp, float t := 3.0) runs on
}
/* establish one Radio Link Layer via SABM -> UA. Use l3 for contention resolution */
-private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
+friend function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) runs on ConnHdlr {
+ timer T := 2.0;
/* send SABM from MS -> BTS */
f_tx_lapdm(ts_LAPDm_SABM(sapi, cr_MO_CMD, true, l3), link_id);
/* expect RLL EST IND on Abis */
+ T.start;
alt {
[l3 != ''O] RSL.receive(tr_RSL_EST_IND(g_chan_nr, link_id, l3));
[l3 == ''O] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id));
@@ -6029,6 +7370,9 @@ private function f_est_rll_mo(uint3_t sapi, RslLinkId link_id, octetstring l3) r
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Failing due to RSL_ERROR_IND");
}
[] RSL.receive { repeat; }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RLL EST IND");
+ }
}
/* expect UA from BTS -> MS */
f_l1_exp_lapdm(tr_LAPDm_UA(sapi, cr_MT_RSP, true, l3));
@@ -6066,26 +7410,26 @@ private function f_TC_rll_rel_ind(charstring id) runs on ConnHdlr {
}
testcase TC_rll_rel_ind_DCCH_0() runs on test_CT {
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true))
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), '01020304'O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
}
testcase TC_rll_rel_ind_ACCH_0() runs on test_CT {
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true))
+ valueof(t_EITC(0, ts_RslLinkID_SACCH(0), ''O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
}
testcase TC_rll_rel_ind_DCCH_3() runs on test_CT {
var RllTestCases tcs := {
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true))
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), ''O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
}
testcase TC_rll_rel_ind_ACCH_3() runs on test_CT {
var RllTestCases tcs := {
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), ''O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_rel_ind));
}
@@ -6108,7 +7452,7 @@ private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
/* ... and expect the DISC on the Um side */
alt {
[] as_l1_exp_lapdm(tr_LAPDm_DISC(tc.sapi, cr_MT_CMD, true)) {
- /* FIXME: send a UA in resposne to the DISC */
+ /* FIXME: send a UA in response to the DISC */
}
}
@@ -6119,10 +7463,10 @@ private function f_TC_rll_rel_req(charstring id) runs on ConnHdlr {
}
testcase TC_rll_rel_req() runs on test_CT {
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), '01020304'O, true)),
- valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), ''O, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), ''O, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), ''O, true))
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), '01020304'O, true)),
+ valueof(t_EITC(0, ts_RslLinkID_SACCH(0), ''O, true)),
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), ''O, true)),
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), ''O, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_rel_req));
}
@@ -6162,16 +7506,16 @@ private function f_TC_rll_ud_req(charstring id) runs on ConnHdlr {
testcase TC_rll_unit_data_req_DCCH() runs on test_CT {
var octetstring l3 := f_rnd_octstring(15);
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), l3, true)),
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), l3, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
}
testcase TC_rll_unit_data_req_ACCH() runs on test_CT {
var octetstring l3 := f_rnd_octstring(19);
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
+ valueof(t_EITC(0, ts_RslLinkID_SACCH(0), l3, true)),
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), l3, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_ud_req));
}
@@ -6204,16 +7548,16 @@ private function f_TC_rll_ud_ind(charstring id) runs on ConnHdlr {
testcase TC_rll_unit_data_ind_DCCH() runs on test_CT {
var octetstring l3 := f_rnd_octstring(20);
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_DCCH(0)), l3, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_DCCH(3)), l3, true))
+ valueof(t_EITC(0, ts_RslLinkID_DCCH(0), l3, true)),
+ valueof(t_EITC(3, ts_RslLinkID_DCCH(3), l3, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
}
testcase TC_rll_unit_data_ind_ACCH() runs on test_CT {
var octetstring l3 := f_rnd_octstring(18);
var RllTestCases tcs := {
- valueof(t_EITC(0, valueof(ts_RslLinkID_SACCH(0)), l3, true)),
- valueof(t_EITC(3, valueof(ts_RslLinkID_SACCH(3)), l3, true))
+ valueof(t_EITC(0, ts_RslLinkID_SACCH(0), l3, true)),
+ valueof(t_EITC(3, ts_RslLinkID_SACCH(3), l3, true))
};
f_rll_testmatrix(tcs, refers(f_TC_rll_ud_ind));
}
@@ -6293,7 +7637,7 @@ private function f_TC_chan_act_encr(charstring id) runs on ConnHdlr {
f_est_dchan(true);
/* now we actually need to transmit some data both ways to check if the encryption works */
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var octetstring l3 := f_rnd_octstring(20);
var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
@@ -6324,6 +7668,11 @@ testcase TC_chan_act_a53() runs on test_CT {
pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
}
+testcase TC_chan_act_a54() runs on test_CT {
+ var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
+ pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_4, f_rnd_octstring(16)));
+ f_testmatrix_each_chan(pars, refers(f_TC_chan_act_encr));
+}
/* Test channel activation with A5/n right from the beginning and RSL MODE MODIFY
which should break the en/decryption on purpose by supplying a new key that is unknown to the MS*/
@@ -6332,7 +7681,7 @@ private function f_TC_rsl_modify_encr(charstring id) runs on ConnHdlr {
f_est_dchan(true);
/* now we actually need to transmit some data both ways to check if the encryption works */
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var octetstring l3 := f_rnd_octstring(20);
var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
@@ -6344,7 +7693,7 @@ private function f_TC_rsl_modify_encr(charstring id) runs on ConnHdlr {
f_unitdata_mo(link_id, l3);
var RSL_Message rsl;
- rsl := valueof(ts_RSL_MODE_MODIFY_REQ(g_chan_nr, valueof(ts_RSL_ChanMode_SIGN(false))));
+ rsl := valueof(ts_RSL_MODE_MODIFY_REQ(g_chan_nr, ts_RSL_ChanMode_SIGN));
/* modify key to break proper encryption */
g_pars.encr.key := f_rnd_octstring(8);
@@ -6391,6 +7740,77 @@ testcase TC_rsl_modify_encr() runs on test_CT {
f_testmatrix_each_chan(pars, refers(f_TC_rsl_modify_encr));
}
+/* Verify RF RESource INDication messages (periodically sent over the RSL) */
+private function f_TC_rsl_rf_resource_ind(template (present) RSL_ResourceInfo info)
+runs on test_CT {
+ const IpaStreamId sid := IPAC_PROTO_RSL_TRX0;
+ var ASP_RSL_Unitdata ud;
+ timer T;
+
+ /* Intave is 6 SACCH periods by default */
+ var float Tval := int2float(6 * 480) / 1000.0 + 0.5;
+
+ T.start(Tval);
+ alt {
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RF_RES_IND(info), sid)) {
+ setverdict(pass);
+ }
+ [] RSL_CCHAN.receive(tr_ASP_RSL_UD(tr_RSL_RF_RES_IND(?), sid)) -> value ud {
+ setverdict(fail, "RF RESource INDication mismatch: ", ud.rsl);
+ }
+ [] RSL_CCHAN.receive { repeat; }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Timeout waiting for RF RESource INDication");
+ }
+ }
+}
+testcase TC_rsl_rf_resource_ind() runs on test_CT {
+ var TrxParsItem trx_pars := mp_trx_pars[0];
+ var RSL_ResourceInfo info := { };
+ var ChannelNrs chans := { };
+
+ f_init(trx_nr := 0);
+
+ f_init_l1ctl();
+ f_l1_tune(L1CTL);
+
+ /* Generate a list of logical channels from module parameters */
+ for (var integer tn := 0; tn < lengthof(trx_pars.ts); tn := tn + 1) {
+ var PchanConfig config := trx_pars.ts[tn].config;
+ select (config) {
+ case (GSM_PCHAN_TCHH_TCHF_PDCH) {
+ /* dyn/osmocom: set to NONE by default */
+ }
+ case (GSM_PCHAN_TCHF_PDCH) {
+ /* dyn/ipaccess: set to TCH/F by default */
+ chans := chans & { valueof(ts_RslChanNr_Bm(tn)) };
+ }
+ case (GSM_PCHAN_PDCH) {
+ chans := chans & { valueof(ts_RslChanNr_PDCH(tn)) };
+ }
+ case else {
+ chans := chans & f_gen_chans_for_ts(tn, config);
+ }
+ }
+ }
+
+ /* Generate a list of RSL ResourceInfo items */
+ for (var integer i := 0; i < lengthof(chans); i := i + 1) {
+ info := info & { valueof(ts_RSL_ResourceInfoItem(chans[i], mp_interf_band)) };
+ }
+
+ /* Align to the first interference report */
+ f_TC_rsl_rf_resource_ind(?);
+
+ /* Test 4 consecutive messages */
+ for (var integer i := 0; i < 4; i := i + 1) {
+ f_TC_rsl_rf_resource_ind(info);
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/* Test unencrypted channel activation followed by explicit ENCR CMD later */
private function f_TC_encr_cmd(charstring id) runs on ConnHdlr {
/* L3 payload doesn't matter, as it is passed transparently */
@@ -6445,6 +7865,11 @@ testcase TC_encr_cmd_a53() runs on test_CT {
pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_3, f_rnd_octstring(8)));
f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
}
+testcase TC_encr_cmd_a54() runs on test_CT {
+ var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
+ pars.encr := valueof(ts_RSL_IE_EncrInfo(RSL_ALG_ID_A5_4, f_rnd_octstring(16)));
+ f_testmatrix_each_chan(pars, refers(f_TC_encr_cmd));
+}
private function f_assert_lapdm(octetstring enc, template LapdmFrame exp_match, charstring name := "") {
var LapdmFrame lf;
@@ -6487,43 +7912,11 @@ testcase TC_lapdm_selftest() runs on test_CT {
/***********************************************************************
* DTX Related (see GSM 05.08, section 8.3)
***********************************************************************/
-
-/* XXX These functions must be kept in sync with g_AllChannels defined on test_CT. */
-private function f_g_chan_is_tchf() runs on ConnHdlr return boolean {
- return (g_chan_nr == valueof(ts_RslChanNr_Bm(1)) or
- g_chan_nr == valueof(ts_RslChanNr_Bm(2)) or
- g_chan_nr == valueof(ts_RslChanNr_Bm(3)) or
- g_chan_nr == valueof(ts_RslChanNr_Bm(4)));
-}
-private function f_g_chan_is_tchh() runs on ConnHdlr return boolean {
- return (g_chan_nr == valueof(ts_RslChanNr_Lm(5,0)) or
- g_chan_nr == valueof(ts_RslChanNr_Lm(5,1)));
-}
-private function f_g_chan_is_sdcch4() runs on ConnHdlr return boolean {
- return (g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,0)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,1)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,2)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH4(0,3)));
-}
-private function f_g_chan_is_sdcch8() runs on ConnHdlr return boolean {
- return (g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,0)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,1)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,2)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,3)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,4)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,5)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,6)) or
- g_chan_nr == valueof(ts_RslChanNr_SDCCH8(6,7)));
-}
-
-private function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
- var L1ctlDlMessage dl;
- var octetstring l2_fill_frame := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
- var octetstring l2_fill_frame_sacch := substr(l2_fill_frame, 0, lengthof(l2_fill_frame) - 2);
+private function f_TC_tch_sign_l2_fill_frame(charstring id) runs on ConnHdlr {
+ var L1ctlMessage dl;
var GsmFrameNumber first_fn;
var boolean is_first_frame := true;
- var integer nfill_frames_sacch := 0;
- var integer nfill_frames_nonsacch := 0;
+ var integer nfill_frames := 0;
var integer expected_fill_frames := 10000; /* initial value causes test failure if not overridden */
/* Frames numbers (mod 104) for which a fill frame is expected on TCHF if DTX is enabled. */
var Integers required_tdma_frames_dtx_tchf := { 52, 53, 54, 55, 56, 57, 58, 59 };
@@ -6541,104 +7934,82 @@ private function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
/* activate TCHF signalling channel */
f_est_dchan(false);
+ /* A template for matching dummy LAPDm func=UA frames */
+ var template L1ctlMessage tr_fill_frame := tr_L1CTL_DATA_IND(
+ chan_nr := g_chan_nr, link_id := tr_RslLinkID_DCCH(?),
+ l2_data := f_pad_oct('030301'O, 23, '2B'O));
+
T.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, ?)) -> value dl {
+ [] L1CTL.receive(tr_fill_frame) -> value dl {
var GsmFrameNumber fn := dl.dl_info.frame_nr;
- var octetstring l2 := dl.payload.data_ind.payload;
if (is_first_frame) {
is_first_frame := false;
first_fn := dl.dl_info.frame_nr;
}
- if (dl.dl_info.link_id.c == SACCH) {
- l2 := substr(l2, 2, lengthof(l2) - 2); /* remove L1 header */
- if (not match(l2_fill_frame_sacch, l2)) {
- repeat;
- }
- } else if (not match(l2_fill_frame, l2)) {
- repeat;
- }
-
- if (dtxd) {
- if (not f_g_chan_is_tchf()) {
- T.stop;
- f_rsl_chan_deact();
- f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received fill frame on non-TCH/F channel; DTX is only allowed on TCH/F!");
- }
+ if (g_pars.chan_mode.dtx_d) {
if (fn > first_fn + frame_dtx_tchf_mod) {
T.stop;
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
- /* With DTX enabled we can expect at least 3 fill frames for every 104 frames.
- * 2 SACCH, 1 TCH/F */
- expected_fill_frames := 3;
+ /* With DTX enabled we can expect at least 3 fill frames for every 104 frames. */
+ expected_fill_frames := 2;
- if (nfill_frames_sacch + nfill_frames_nonsacch < expected_fill_frames) {
- log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
- " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
+ if (nfill_frames < expected_fill_frames) {
+ setverdict(fail, "Not enough fill frames received: ",
+ nfill_frames, " out of ", expected_fill_frames);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
} else {
setverdict(pass);
}
} else {
- if (dl.dl_info.link_id.c == SACCH) {
- nfill_frames_sacch := nfill_frames_sacch + 1;
- repeat;
- }
/* On DTX TCH/F channels, fill frames occur only for specific frame numbers mod 104.
* Furthermore, the L1SAP layer gives us frame numbers for the start of a block so
* we should only see the subset of frames numbers which correspond to a block boundary.
* TCH/F blocks are defined to start at 0,4,8,13,17,21 (modulo 26) */
for (var integer i := 0; i < lengthof(required_tdma_blocks_dtx_tchf); i := i + 1) {
if (fn mod frame_dtx_tchf_mod == required_tdma_blocks_dtx_tchf[i]) {
- nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
+ nfill_frames := nfill_frames + 1;
repeat;
}
}
- log("Received DTX TCH fill frame with bad frame number: ", fn,
- " (mod ", frame_dtx_tchf_mod, ": ", fn mod frame_dtx_tchf_mod, ")",
- " (mod ", block_dtx_tchf_mod, ": ", fn mod block_dtx_tchf_mod, ")");
+ setverdict(fail, "Received DTX TCH fill frame with bad frame number: ", fn,
+ " (mod ", frame_dtx_tchf_mod, ": ", fn mod frame_dtx_tchf_mod, ")",
+ " (mod ", block_dtx_tchf_mod, ": ", fn mod block_dtx_tchf_mod, ")");
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected L2 fill frame received on Um");
}
} else {
- if (dl.dl_info.link_id.c == SACCH) {
- nfill_frames_sacch := nfill_frames_sacch + 1;
- } else {
- nfill_frames_nonsacch := nfill_frames_nonsacch + 1;
- }
+ nfill_frames := nfill_frames + 1;
if (fn > first_fn + frame_dtx_tchf_mod) {
T.stop;
- if (f_g_chan_is_tchf()) {
- /* Without DTX we can expect 25 fill frames for every 104 frames.
- * (24 FACCH + 1 SACCH filling) */
- expected_fill_frames := 25;
- } else if (f_g_chan_is_tchh()) {
- /* We can expect 2 fill frames for every 104 frames. */
- expected_fill_frames := 2;
- } else if (f_g_chan_is_sdcch4() or f_g_chan_is_sdcch8()) {
- /* We can expect 5 fill frames for every 104 frames. */
- expected_fill_frames := 5;
- } else {
- f_rsl_chan_deact();
- f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unknown channel type");
+
+ select (g_chan_nr) {
+ /* TCH/F: we expect 24 fill frames for every 104 frames. */
+ case (t_RslChanNr_Bm(?)) { expected_fill_frames := 24; }
+ /* TCH/H: we expect 2 fill frames for every 104 frames. */
+ case (t_RslChanNr_Lm(?, ?)) { expected_fill_frames := 2; }
+ /* SDCCH: we expect 5 fill frames for every 104 frames. */
+ case (t_RslChanNr_SDCCH4(?, ?)) { expected_fill_frames := 4; }
+ case (t_RslChanNr_SDCCH8(?, ?)) { expected_fill_frames := 4; }
+ case else {
+ /* This shall not happen, just to be sure */
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
}
f_rsl_chan_deact();
f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
- if (nfill_frames_sacch + nfill_frames_nonsacch >= expected_fill_frames) {
+ if (nfill_frames >= expected_fill_frames) {
setverdict(pass);
} else {
- log("received only ", nfill_frames_sacch, "+", nfill_frames_nonsacch,
- " (SACCH+other) out of ", expected_fill_frames, " expected fill frames");
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Not enough fill frames received");
+ setverdict(fail, "Not enough fill frames received: ",
+ nfill_frames, " out of ", expected_fill_frames);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
} else {
repeat;
@@ -6654,29 +8025,21 @@ private function f_test_l2_fill_frames(boolean dtxd) runs on ConnHdlr {
}
}
-private function f_TC_tch_sign_l2_fill_frame(charstring id) runs on ConnHdlr {
- f_test_l2_fill_frames(false);
-}
-
-private function f_TC_tch_sign_l2_fill_frame_dtxd(charstring id) runs on ConnHdlr {
- f_test_l2_fill_frames(true);
-}
-
private function f_tch_sign_l2_fill_frame(boolean dtxd) runs on test_CT {
+ var template RSL_IE_ChannelMode ch_mode;
var ConnHdlr vc_conn;
var ConnHdlrPars pars;
pars.t_guard := 60.0;
f_init();
+ ch_mode := ts_RSL_ChanMode_SIGN(dtxd := dtxd);
for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
- pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN(dtxd)));
+ pars := valueof(t_Pars(g_AllChannels[i], ch_mode));
if (dtxd) {
if (i >= 4) { /* DTX is only allowed on TCH/F */
break;
}
- vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame_dtxd), pars);
- } else {
- vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame), pars);
}
+ vc_conn := f_start_handler(refers(f_TC_tch_sign_l2_fill_frame), pars);
vc_conn.done;
}
}
@@ -6701,6 +8064,1163 @@ testcase TC_chopped_ipa_payload() runs on test_CT {
IPA_Testing.f_run_TC_chopped_ipa_payload(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT);
}
+
+/* Callback function to be called by as_TC_ms_pwr_ctrl().
+ * Return value: Measurement Report to be sent (encoded octetstring). */
+type function f_TC_ms_pwr_ctrl_cb(inout SacchL1Header l1h, integer num_blocks)
+ runs on ConnHdlr return octetstring;
+
+private altstep as_TC_ms_pwr_ctrl(f_TC_ms_pwr_ctrl_cb cb, inout integer num_blocks)
+runs on ConnHdlr {
+ var L1ctlMessage l1_dl;
+ var SacchL1Header l1h;
+ var octetstring l2;
+
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl {
+ /* Parse the L1 SACCH header (MS Power Level & Timing Advance) */
+ l1h := dec_SacchL1Header(substr(l1_dl.payload.data_ind.payload, 0, 2));
+ log("as_TC_ms_pwr_ctrl(): Rx SACCH L1 header: ", l1h);
+
+ /* Pass it to the user specified call-back function */
+ l2 := cb.apply(l1h, num_blocks);
+ /* Send a Measurement Report generated by the call-back */
+ L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(l1_dl.dl_info.chan_nr,
+ l1_dl.dl_info.link_id,
+ l1h, l2));
+
+ /* Shall we keep going? */
+ num_blocks := num_blocks - 1;
+ log("as_TC_ms_pwr_ctrl(): ", num_blocks, " SACCH blocks remaining");
+ if (num_blocks > 0) { repeat; }
+ }
+ [] L1CTL.receive { repeat; }
+}
+
+private function f_TC_ms_pwr_ctrl_cb_def(inout SacchL1Header l1h, integer num_blocks)
+runs on ConnHdlr return octetstring {
+ /* Command the L1 to apply received parameters */
+ f_L1CTL_PARAM(L1CTL, l1h.actual_ta, l1h.ms_power_lvl);
+
+ /* Dummy measurement report (the results are invalid) */
+ return f_pad_oct('010349'O & '0615004001C0'O, 21, '00'O);
+}
+
+private function f_TC_ms_pwr_ctrl_cb_const(inout SacchL1Header l1h, integer num_blocks)
+runs on ConnHdlr return octetstring {
+ if (l1h.ms_power_lvl != g_pars.l1_pars.ms_power_level) {
+ setverdict(fail, "Unexpected MS Power level change: ",
+ g_pars.l1_pars.ms_power_level, " -> ",
+ l1h.ms_power_lvl);
+ }
+
+ return f_TC_ms_pwr_ctrl_cb_def(l1h, num_blocks);
+}
+
+private function f_TC_ms_pwr_ctrl_cb_rssi_pwm(inout SacchL1Header l1h, integer num_blocks)
+runs on ConnHdlr return octetstring {
+ /* UL RSSI oscillation driven by SACCH block number */
+ if (num_blocks rem 2 == 0) {
+ f_trxc_fake_rssi(-100);
+ } else {
+ f_trxc_fake_rssi(-50);
+ }
+
+ /* Make sure that MS power level remains constant */
+ return f_TC_ms_pwr_ctrl_cb_const(l1h, num_blocks);
+}
+
+/* Make sure that MS power level remains constant when 'rx-current' equals 'rx-target' */
+private function f_TC_ms_pwr_ctrl_constant(charstring id)
+runs on ConnHdlr {
+ var integer num_blocks := 8;
+ timer T := int2float(num_blocks);
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* These IEs are needed for autonomous MS power control */
+ var template (value) RSL_IE_List ies := {
+ t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{
+ ms_power := ts_RSL_IE_MS_Power(g_pars.l1_pars.ms_power_level)
+ }),
+ t_RSL_IE(RSL_IE_MS_POWER_PARAM, RSL_IE_Body:{
+ ms_power_params := ts_RSL_IE_MS_Power_Parameters(''O)
+ })
+ };
+
+ /* Ensure that 'rx-current' equals 'rx-target' */
+ f_trxc_fake_rssi(mp_uplink_power_target);
+
+ /* Populate SACCH cache with a Measurement Report */
+ f_send_meas_rep(ts_MeasurementResults);
+
+ /* Establish a dedicated channel */
+ f_est_dchan(more_ies := valueof(ies));
+
+ L1CTL.clear;
+ T.start;
+ alt {
+ [] as_TC_ms_pwr_ctrl(refers(f_TC_ms_pwr_ctrl_cb_const), num_blocks);
+ [] T.timeout {
+ setverdict(fail, "Not all SACCH blocks were processed in time, ",
+ num_blocks, " were not handled");
+ }
+ }
+
+ /* Release the channel */
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+}
+testcase TC_ms_pwr_ctrl_constant() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* Explicitly configure the Uplink power target (in dBm) */
+ f_vty_config(BTSVTY, "bts 0", "uplink-power-target " & int2str(mp_uplink_power_target));
+
+ for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i + 1) {
+ pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
+ log(testcasename(), ": starting on ", pars.chan_nr);
+
+ vc_conn := f_start_handler(refers(f_TC_ms_pwr_ctrl_constant),
+ pars, trxc_comp := true);
+ vc_conn.done;
+ }
+
+ /* No need to reset Uplink power parameters - the IUT restarts anyway */
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* Test Exponentially Weighted Moving Average (EWMA) power filtering */
+private function f_TC_ms_pwr_ctrl_pf_ewma(charstring id)
+runs on ConnHdlr {
+ var integer num_blocks := 16;
+ timer T := int2float(num_blocks);
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* These IEs are needed for autonomous MS power control */
+ var template (value) RSL_IE_List ies := {
+ t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{
+ ms_power := ts_RSL_IE_MS_Power(g_pars.l1_pars.ms_power_level)
+ }),
+ t_RSL_IE(RSL_IE_MS_POWER_PARAM, RSL_IE_Body:{
+ ms_power_params := ts_RSL_IE_MS_Power_Parameters(''O)
+ })
+ };
+
+ /* Ensure that 'rx-current' equals 'rx-target' */
+ f_trxc_fake_rssi(mp_uplink_power_target);
+
+ /* Populate SACCH cache with a Measurement Report */
+ f_send_meas_rep(ts_MeasurementResults);
+
+ /* Establish a dedicated channel */
+ f_est_dchan(more_ies := valueof(ies));
+
+ L1CTL.clear;
+ T.start;
+ alt {
+ [] as_TC_ms_pwr_ctrl(refers(f_TC_ms_pwr_ctrl_cb_rssi_pwm), num_blocks);
+ [] T.timeout {
+ setverdict(fail, "Not all SACCH blocks were processed in time, ",
+ num_blocks, " were not handled");
+ }
+ }
+
+ /* Release the channel */
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+}
+testcase TC_ms_pwr_ctrl_pf_ewma() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* Explicitly configure EWMA filtering with 80% smoothing (alpha = 0.2) */
+ f_vty_config(BTSVTY, "bts 0", "uplink-power-filtering algo ewma beta 80");
+ /* Explicitly configure the Uplink power range (target and delte) */
+ f_vty_config(BTSVTY, "bts 0", "uplink-power-target " & int2str(mp_uplink_power_target)
+ & " hysteresis " & int2str(mp_uplink_power_hysteresis));
+
+ for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i + 1) {
+ pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN));
+ log(testcasename(), ": starting on ", pars.chan_nr);
+
+ vc_conn := f_start_handler(refers(f_TC_ms_pwr_ctrl_pf_ewma),
+ pars, trxc_comp := true);
+ vc_conn.done;
+ }
+
+ /* No need to reset Uplink power parameters - the IUT restarts anyway */
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private function f_TC_speech_no_rtp(charstring id) runs on ConnHdlr {
+ var template L1ctlMessage tr_dummy_frame;
+ var integer dummy_frame_num := 0;
+ var L1ctlMessage l1_dl;
+ timer T := 8.0;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ f_est_dchan();
+
+ /* There may be a few errors right after the channel activation */
+ f_sleep(2.0); /* ... so let's give the L1 some time to stabilize */
+ L1CTL.clear;
+
+ /* Expect empty TRAFFIC.ind with no bit errors and bad CRC. In the absence
+ * of RTP, osmo-bts is transmitting dummy speech frames with inverted CRC3.
+ * This is a beautiful hack inducing a BFI condition in the MS receiver.
+ * See https://osmocom.org/issues/4823#note-13 for more details. */
+ tr_dummy_frame := tr_L1CTL_TRAFFIC_IND(g_chan_nr, tr_RslLinkID_DCCH(0));
+ tr_dummy_frame.dl_info.fire_crc := (1..255); /* != 0 */
+ tr_dummy_frame.dl_info.num_biterr := 0;
+ tr_dummy_frame.payload := omit;
+
+ T.start;
+ alt {
+ [] L1CTL.receive(tr_dummy_frame) -> value l1_dl {
+ dummy_frame_num := dummy_frame_num + 1;
+ log("Rx dummy TRAFFIC.ind (num ", dummy_frame_num, "): ", l1_dl);
+ /* break the loop if we got 5 dummy frames */
+ if (dummy_frame_num < 5)
+ { repeat; }
+ }
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr)) -> value l1_dl {
+ setverdict(fail, "Rx unexpected TRAFFIC.ind: ", l1_dl);
+ }
+ [] as_l1_sacch_loop();
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for TRAFFIC.ind");
+ }
+ }
+
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_speech_no_rtp_tchf() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F, V1 (FR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_speech_no_rtp), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F, V2 (EFR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2)));
+ vc_conn := f_start_handler(refers(f_TC_speech_no_rtp), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_no_rtp), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_speech_no_rtp_tchh() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS5, TCH/H, V1 (HR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_speech_no_rtp), pars);
+ vc_conn.done;
+
+ /* TS5, TCH/H, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_no_rtp), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* Verify handling of Downlink and Uplink speech frames */
+private function f_TC_speech_rtp(charstring id) runs on ConnHdlr {
+ var octetstring payload;
+ var L1ctlMessage l1_dl;
+ var PDU_RTP rtp_pdu;
+ timer Td, Tu;
+
+ log("Testing channel mode ", g_pars.chan_mode);
+
+ f_l1_tune(L1CTL);
+ f_est_dchan();
+
+ select (g_pars.chan_mode) {
+ case (tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1)) /* TCH/FS */
+ { payload := f_pad_oct('D0'O & f_rnd_octstring(6), 33, 'FF'O); }
+ case (tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1)) /* TCH/HS */
+ { payload := f_pad_oct('00'O & f_rnd_octstring(6), 15, '00'O); }
+ case (tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2)) /* TCH/EFS */
+ { payload := f_pad_oct('C0'O & f_rnd_octstring(6), 31, '00'O); }
+ case (tr_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3)) /* TCH/AFS */
+ {
+ var integer amr_ft := get_start_amr_ft();
+ var integer payload_len := f_amrft_payload_len(amr_ft) + 2;
+ payload := enc_RTP_AMR_Hdr(valueof(ts_RTP_AMR_Hdr(amr_ft, amr_ft, '1'B)));
+ payload := f_pad_oct(payload & f_rnd_octstring(6), payload_len, '00'O);
+ }
+ case (tr_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3)) /* TCH/AHS */
+ {
+ var integer amr_ft := get_start_amr_ft();
+ var integer payload_len := f_amrft_payload_len(amr_ft) + 2;
+ payload := enc_RTP_AMR_Hdr(valueof(ts_RTP_AMR_Hdr(amr_ft, amr_ft, '1'B)));
+ payload := f_pad_oct(payload & f_rnd_octstring(6), payload_len, '00'O);
+ }
+ case else {
+ setverdict(fail, "Unhandled RSL channel mode := ", g_pars.chan_mode);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Activate the RTP emulation */
+ var RtpemConfig cfg := c_RtpemDefaultCfg;
+ cfg.tx_payloads[0].fixed_payload := payload;
+ f_rtpem_activate(cfg, RTPEM_MODE_BIDIR);
+
+ /* Give the scheduler some time to fill up the buffers */
+ f_sleep(2.0);
+ L1CTL.clear;
+ RSL.clear;
+
+ /* Make sure that Downlink frames are received at the UE */
+ Td.start(2.0);
+ alt {
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr, frame := payload)) -> value l1_dl {
+ var octetstring data := l1_dl.payload.traffic_ind.data;
+ log("TCH received (len=", lengthof(data), "): ", data);
+ L1CTL.send(ts_L1CTL_TRAFFIC_REQ(g_chan_nr, l1_dl.dl_info.link_id,
+ l1_dl.payload.traffic_ind.data));
+ setverdict(pass);
+ }
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr, frame := ?)) -> value l1_dl {
+ setverdict(fail, "Rx unexpected Downlink speech frame ",
+ "(", l1_dl.payload.traffic_ind.data, ") ",
+ "expected (", payload, ")");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ [] as_l1_sacch_loop();
+ [] L1CTL.receive { repeat; }
+ [] Td.timeout {
+ setverdict(fail, "Timeout waiting for Downlink speech frames");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Make sure that Uplink frames are received at the BTS */
+ RTPEM_DATA.clear;
+ Tu.start(2.0);
+ alt {
+ [] as_l1_tch_loop();
+ [] as_l1_sacch_loop();
+ [] RTPEM_DATA.receive(PDU_RTP:?) -> value rtp_pdu {
+ if (rtp_pdu.data != payload)
+ { repeat; }
+ }
+ [] RTPEM_DATA.receive { repeat; }
+ [] L1CTL.receive { repeat; }
+ [] Tu.timeout {
+ setverdict(fail, "Timeout waiting for Uplink speech frames");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_NONE);
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_speech_rtp_tchf() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F, V1 (FR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_speech_rtp), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F, V2 (EFR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM2)));
+ vc_conn := f_start_handler(refers(f_TC_speech_rtp), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_rtp), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_speech_rtp_tchh() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS5, TCH/H0, V1 (HR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1)));
+ vc_conn := f_start_handler(refers(f_TC_speech_rtp), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/H0, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_rtp), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+
+/* Verify handling of Downlink and Uplink Osmux speech frames */
+private function f_TC_speech_osmux(charstring id) runs on ConnHdlr {
+ var L1ctlMessage l1_dl;
+ var OSMUX_PDU osmux_pdu;
+ var octetstring pl;
+ var octetstring exp_rtp_pl;
+ timer Td, Tu;
+
+ f_l1_tune(L1CTL);
+ f_est_dchan();
+
+ /* Activate the RTP emulation */
+ pl := f_rnd_octstring(6);
+ f_osmuxem_activate(pl);
+
+ /* Give the scheduler some time to fill up the buffers */
+ f_sleep(2.0);
+ L1CTL.clear;
+ RSL.clear;
+
+ /* we transmit using AMR_FT_2 (5.90), see t_TxHandleAMR590 in f_osmuxem_activate() */
+ var integer amr_ft := get_start_amr_ft();
+ var integer amr_pl_len := f_amrft_payload_len(amr_ft);
+ var octetstring hdr := enc_RTP_AMR_Hdr(valueof(ts_RTP_AMR_Hdr(amr_ft, amr_ft, '1'B)));
+ pl := f_osmux_gen_expected_rx_rtp_payload(amr_ft, pl);
+ exp_rtp_pl := hdr & pl;
+
+ /* Make sure that Downlink frames are received at the UE */
+ Td.start(2.0);
+ alt {
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr, frame := exp_rtp_pl)) -> value l1_dl {
+ var octetstring data := l1_dl.payload.traffic_ind.data;
+ log("TCH received (len=", lengthof(data), "): ", data);
+ L1CTL.send(ts_L1CTL_TRAFFIC_REQ(g_chan_nr, l1_dl.dl_info.link_id, data));
+ setverdict(pass);
+ }
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr, frame := ?)) -> value l1_dl {
+ setverdict(fail, "Rx unexpected Downlink speech frame ",
+ "(", l1_dl.payload.traffic_ind.data, ") ",
+ "expected (", exp_rtp_pl, ")");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ [] as_l1_sacch_loop();
+ [] L1CTL.receive { repeat; }
+ [] Td.timeout {
+ setverdict(fail, "Timeout waiting for Downlink speech frames");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Make sure that Uplink frames are received at the BTS */
+ OsmuxEM_DATA.clear;
+ var template (present) OSMUX_PDU osmux_pdu_exp := tr_PDU_Osmux_AMR(cid := g_pars.loc_osmux_cid,
+ amr_ft := amr_ft,
+ amr_cmr := amr_ft);
+ Tu.start(2.0);
+ alt {
+ [] as_l1_tch_loop();
+ [] as_l1_sacch_loop();
+ [] OsmuxEM_DATA.receive(osmux_pdu_exp) -> value osmux_pdu {
+ var boolean matched := false;
+ for (var integer i := 0; i < osmux_pdu.osmux_amr.header.ctr + 1; i := i + 1) {
+ var octetstring rx_pl;
+ rx_pl := f_osmux_amr_get_nth_amr_payload(osmux_pdu.osmux_amr, i);
+ log("got ", rx_pl, " vs exp ", pl);
+ if (rx_pl == pl) {
+ matched := true;
+ break;
+ }
+ }
+ if (not matched) {
+ repeat;
+ }
+ }
+ [] OsmuxEM_DATA.receive { repeat; }
+ [] Tu.timeout {
+ setverdict(fail, "Timeout waiting for Uplink speech frames");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_osmuxem_mode(OsmuxEM_CTRL, OSMUXEM_MODE_NONE);
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_speech_osmux_tchf() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS5, TCH/H0, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1), ts_RSL_ChanMode(RSL_CHRT_TCH_F, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_osmux), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_speech_osmux_tchh() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS5, TCH/H0, V3 (AMR codec) */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0), ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3)));
+ pars.mr_conf := valueof(ts_RSL_MultirateCfg);
+ vc_conn := f_start_handler(refers(f_TC_speech_osmux), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* CSD channel tests */
+private function f_TC_data_rtp_loopback(charstring id) runs on ConnHdlr {
+ var octetstring udata := ''O;
+ var integer payload_len;
+ var L1ctlMessage l1_dl;
+ timer Td;
+
+ log("Testing channel mode ", g_pars.chan_mode);
+
+ select (g_pars.chan_mode) {
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, (RSL_CMOD_CSD_T_14k4, RSL_CMOD_CSD_NT_14k5)))
+ { payload_len := 290; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, (RSL_CMOD_CSD_T_9k6, RSL_CMOD_CSD_NT_12k0)))
+ { payload_len := 4 * 60; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, (RSL_CMOD_CSD_T_4k8, RSL_CMOD_CSD_NT_6k0)))
+ { payload_len := 2 * 60; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, (RSL_CMOD_CSD_T_4k8, RSL_CMOD_CSD_NT_6k0)))
+ { payload_len := 4 * 60; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, (RSL_CMOD_CSD_T_2k4, RSL_CMOD_CSD_T_1k2,
+ RSL_CMOD_CSD_T_600, RSL_CMOD_CSD_T_1200_75)))
+ { payload_len := 2 * 36; }
+ case (tr_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, (RSL_CMOD_CSD_T_2k4, RSL_CMOD_CSD_T_1k2,
+ RSL_CMOD_CSD_T_600, RSL_CMOD_CSD_T_1200_75)))
+ { payload_len := 4 * 36; }
+ case else {
+ setverdict(fail, "Unhandled RSL channel mode := ", g_pars.chan_mode);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Generate a pseudo-random payload */
+ for (var integer i := 0; i < payload_len; i := i + 1) {
+ udata := udata & int2oct(i mod 2, 1);
+ }
+
+ /* Activate the RTP emulation */
+ f_rtpem_activate(mode := RTPEM_MODE_LOOPBACK, rtp_pt := 120);
+
+ /* Tune to the dedicated channel */
+ f_l1_tune(L1CTL);
+ f_est_dchan();
+
+ /* Send a pseudo-random data frame on the Uplink */
+ log("Sending Uplink TCH (len=", lengthof(udata), "): ", udata);
+ L1CTL.send(ts_L1CTL_TRAFFIC_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), udata));
+
+ /* Expect this frame to show up on the Downlink */
+ Td.start(4.0);
+ alt {
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr, frame := udata)) {
+ log("TCH received (len=", lengthof(udata), "): ", udata);
+ setverdict(pass);
+ Td.stop;
+ }
+ [] L1CTL.receive(tr_L1CTL_TRAFFIC_IND(g_chan_nr)) -> value l1_dl {
+ var octetstring ddata := l1_dl.payload.traffic_ind.data;
+ log("TCH received (len=", lengthof(ddata), "): ", ddata);
+ repeat;
+ }
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr)) -> value l1_dl {
+ var octetstring ddata := l1_dl.payload.data_ind.payload;
+ log("FACCH received: ", ddata);
+ repeat;
+ }
+ [] as_l1_sacch_loop();
+ [] L1CTL.receive { repeat; }
+ [] Td.timeout {
+ setverdict(fail, "Timeout waiting for matching Downlink data frame");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* TODO: send and expect FACCH */
+
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_NONE);
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+testcase TC_data_rtp_tchf144() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F14.4 (14k5 radio interface rate), transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_T_14k4)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F14.4 (14k5 radio interface rate), non-transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_NT_14k5)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_data_rtp_tchf96() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F9.6 (12k radio interface rate), transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_T_9k6)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F9.6 (12k radio interface rate), non-transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_NT_12k0)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_data_rtp_tchf48() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F4.8 (6k radio interface rate), transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_T_4k8)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/F4.8 (6k radio interface rate), non-transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_NT_6k0)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_data_rtp_tchh48() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/H4.8 (6k radio interface rate), transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, RSL_CMOD_CSD_T_4k8)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ /* TS1, TCH/H4.8 (6k radio interface rate), non-transparent service */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, RSL_CMOD_CSD_NT_6k0)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_data_rtp_tchf24() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/F2.4 (3k6 radio interface rate), transparent services only */
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_T_2k4)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ pars := valueof(t_Pars(ts_RslChanNr_Bm(1),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_F, RSL_CMOD_CSD_T_1k2)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+testcase TC_data_rtp_tchh24() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* TS1, TCH/H2.4 (3k6 radio interface rate), transparent services only */
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, RSL_CMOD_CSD_T_2k4)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ pars := valueof(t_Pars(ts_RslChanNr_Lm(5, 0),
+ ts_RSL_ChanMode_DATA(RSL_CHRT_TCH_H, RSL_CMOD_CSD_T_1k2)));
+ vc_conn := f_start_handler(refers(f_TC_data_rtp_loopback), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+
+private function f_TC_early_immediate_assignment(charstring id) runs on ConnHdlr {
+ var GsmFrameNumber fn;
+ var ChannelDescription ch_desc;
+ var integer ra := 23;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* Send RACH request and wait for ChanReq */
+ fn := f_rach_req_wait_chan_rqd(ra);
+
+ /* The BSC already sends the Immediate Assignment, before the channel is active.
+ * (Also before the Channel Activation, even. I tried to write this test so that we first send the Chan Act and then the IMM
+ * ASS, but osmo-bts-trx responds so fast that the Chan Activ ACK comes back even before titan dispatches the
+ * IMM ASS. So move the IMM ASS even before the Chan Activ.) */
+ if (g_pars.fhp.enabled) {
+ ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.fhp.maio_hsn, g_pars.tsc));
+ } else {
+ var GsmArfcn arfcn := mp_trx_pars[g_pars.trx_nr].arfcn;
+ ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, arfcn, g_pars.tsc));
+ }
+ var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, g_pars.fhp.ma_map));
+ RSL.send(ts_ASP_RSL_UD(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)))); /* force sending to TRX0 */
+
+ /* Do not expect the Immediate Assignment to show up on MS side yet. Even give it one second before the BSC
+ * requests Chan Activ, to make sure the RR IMM ASS is held back. */
+ var L1ctlMessage dl;
+ var GsmRrMessage rr;
+
+ var template GsmRrMessage rr_imm_ass := tr_IMM_ASS(ra, fn);
+ rr_imm_ass.payload.imm_ass.ded_or_tbf := ?;
+ rr_imm_ass.payload.imm_ass.pkt_chan_desc := *;
+ rr_imm_ass.payload.imm_ass.chan_desc := *;
+
+ timer T := 1.0;
+ T.start;
+ alt {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
+ rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
+ if (match(rr, rr_imm_ass)) {
+ setverdict(fail, "Expected IMM ASS to be delayed until Chan Act ACK, but it was passed to the MS immediately");
+ mtc.stop;
+ } else {
+ repeat;
+ }
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout;
+ }
+ RSL.send(ts_RSL_CHAN_ACT(g_chan_nr, g_pars.chan_mode, t_RSL_IE_ActType_IA));
+ RSL.receive(tr_RSL_CHAN_ACT_ACK(g_chan_nr));
+
+ /* Now expect the IMM ASS on Um */
+ f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
+ setverdict(pass);
+
+ /* Release the channel */
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+}
+
+testcase TC_early_immediate_assignment() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ /* verify early Immediate Assignment on C0 (the BCCH carrier): TCH/F on TS1 */
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN, trx_nr := 0));
+ vc_conn := f_start_handler(refers(f_TC_early_immediate_assignment), pars);
+ vc_conn.done;
+
+ /* verify early Immediate Assignment on C1: TCH/F on TS0 */
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_early_immediate_assignment), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private function f_TC_est_dchan(charstring id) runs on ConnHdlr {
+ var integer ra := oct2int(f_rnd_ra_cs());
+ var ChannelDescription ch_desc;
+
+ /* Tune the MS to BCCH */
+ f_l1_tune(L1CTL);
+
+ /* Send RACH request and wait for ChanReq */
+ var GsmFrameNumber fn := f_rach_req_wait_chan_rqd(ra);
+
+ /* Activate channel on the BTS side */
+ f_rsl_chan_act(g_pars.chan_mode);
+
+ /* Craft channel description (with or without frequency hopping parameters) */
+ if (g_pars.fhp.enabled) {
+ ch_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.fhp.maio_hsn, g_pars.tsc));
+ } else {
+ ch_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, mp_trx_pars[0].arfcn, g_pars.tsc));
+ }
+
+ /* Send IMM.ASS via CCHAN */
+ var GsmRrMessage rr_msg := valueof(ts_IMM_ASS(ra, fn, 0, ch_desc, g_pars.fhp.ma_map));
+ RSL.send(ts_RSL_IMM_ASSIGN(enc_GsmRrMessage(rr_msg)));
+
+ /* Receive IMM.ASS on the MS side */
+ var ImmediateAssignment imm_ass := f_L1CTL_WAIT_IMM_ASS(L1CTL, ra, fn);
+
+ /* Match the Channel Description IE in received IMM.ASS */
+ if (not match(imm_ass.chan_desc, ch_desc)) {
+ setverdict(fail, "Channel Description IE does not match");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Tune the MS to a dedicated channel indicated in the IMM.ASS */
+ f_L1CTL_DM_EST_REQ_IA(L1CTL, imm_ass, g_pars.fhp.ma);
+
+ /* Expect SACCH frames on Downlink */
+ L1CTL.clear;
+ f_exp_sacch(true);
+
+ /* We're done, deactivate and release */
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rsl_chan_deact();
+}
+testcase TC_est_dchan() runs on test_CT {
+ var ConnHdlr vc_conn;
+ var ConnHdlrPars pars;
+
+ f_init();
+
+ for (var integer i := 0; i < sizeof(g_AllChannels); i := i + 1) {
+ pars := valueof(t_Pars(g_AllChannels[i], ts_RSL_ChanMode_SIGN));
+ vc_conn := f_start_handler(refers(f_TC_est_dchan), pars);
+ vc_conn.done;
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private type record TopTestCase {
+ RSL_IE_BS_Power bs_power,
+ RSL_IE_OSMO_TopAcchCap top_cap,
+ record of TopTestStep steps
+};
+private type record TopTestStep {
+ MeasurementResults meas_res optional,
+ GsmRxLev overpower_sacch,
+ GsmRxLev overpower_facch
+};
+
+private function f_rxlev_match(template (present) RslLinkId link_id,
+ template (present) GsmRxLev rxlev)
+runs on ConnHdlr {
+ var L1ctlMessage dl := f_L1CTL_rx_data(L1CTL, g_chan_nr, link_id);
+ if (not match(dl.dl_info.rx_level, rxlev)) {
+ setverdict(fail, "RxLev(", link_id, ") := ", dl.dl_info.rx_level,
+ " does not match expected RxLev := ", rxlev);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+}
+
+private function f_TC_acch_overpower(charstring id) runs on ConnHdlr {
+ var TopTestCase tc := g_pars.spec.top;
+ var GsmRxLev rxlev_dcch;
+ var L1ctlMessage dl;
+
+ /* Wait for Pau ramping to complete */
+ f_sleep(6.0);
+
+ f_l1_tune(L1CTL);
+ L1CTL.clear;
+ RSL.clear;
+
+ /* Measure RxLev(BCCH), calculate RxLev(DCCH) */
+ dl := f_L1CTL_rx_data(L1CTL, t_RslChanNr_BCCH(0));
+ rxlev_dcch := dl.dl_info.rx_level - (tc.bs_power.power_level * 2);
+
+ log("RxLev(BCCH) := ", dl.dl_info.rx_level);
+ log("Expected RxLev(DCCH) := ", rxlev_dcch);
+
+ /* Additional IEs for the CHANnel ACTIVation message */
+ var template (value) RSL_IE_List ies := {
+ /* Employ BS power control in static mode */
+ t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{
+ bs_power := tc.bs_power
+ }),
+ /* Indicate the given Temporary Overpower capability */
+ t_RSL_IE(RSL_IE_OSMO_TOP_ACCH_CAP, RSL_IE_Body:{
+ top_acch_cap := tc.top_cap
+ })
+ };
+
+ /* Establish a dedicated channel */
+ f_est_dchan(more_ies := valueof(ies));
+
+ /* Give it some time to stabilize */
+ f_sleep(0.480 * 2.0);
+ L1CTL.clear;
+ RSL.clear;
+
+ for (var integer i := 0; i < lengthof(tc.steps); i := i + 1) {
+ var TopTestStep step := tc.steps[i];
+ var GsmRxLev rxlev_facch := rxlev_dcch + step.overpower_facch;
+ var GsmRxLev rxlev_sacch := rxlev_dcch + step.overpower_sacch;
+
+ log("Executing step[", i, "] := ", step);
+
+ /* Send RR Measurement Report (if present) */
+ if (ispresent(step.meas_res)) {
+ f_transceive_meas_rep(step.meas_res);
+ f_sleep(0.480 * 2.0);
+ L1CTL.clear;
+ }
+
+ /* Check RxLev on both FACCH and SACCH */
+ f_rxlev_match(tr_RslLinkID_DCCH(?), rxlev_facch);
+ f_rxlev_match(tr_RslLinkID_SACCH(?), rxlev_sacch);
+
+ setverdict(pass);
+ }
+
+ f_rsl_chan_deact();
+ f_L1CTL_DM_REL_REQ(L1CTL, g_chan_nr);
+ f_rslem_unregister(g_pars.trx_nr, g_chan_nr);
+}
+testcase TC_acch_overpower_rxqual_thresh() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Verify lower and upper RxQual thresholds */
+ var template (value) TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(4), /* 4dB */
+ steps := {
+ /* Channel established, no overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Worst possible RxQual value, overpower of 4dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Worst possible RxQual value, disabling overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Lower threshold not reached, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 1),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* Lower threshold not reached, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 2),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* Lower threshold reached, overpower of 4dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 4),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Upper threshold not reached, keeping overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 3),
+ overpower_sacch := 4, overpower_facch := 4 },
+ /* Upper threshold reached, disabling overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 2),
+ overpower_sacch := 0, overpower_facch := 0 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1,
+ t_guard := 30.0));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_rxqual_thresh_dtx() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Verify handling of FULL and SUB values */
+ var template (value) TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(4), /* 4dB */
+ steps := {
+ /* Channel established, no overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* Invalid measurement results, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 7,
+ rxq_s := 7,
+ valid := false),
+ overpower_sacch := 0, overpower_facch := 0 },
+
+ /* DTXu was in use, no overpower */
+ { meas_res := ts_MeasurementResults(rxq_f := 7,
+ rxq_s := 0,
+ dtx_used := true),
+ overpower_sacch := 0, overpower_facch := 0 },
+ /* DTXu was in use, overpower of 4 dB */
+ { meas_res := ts_MeasurementResults(rxq_f := 0,
+ rxq_s := 7,
+ dtx_used := true),
+ overpower_sacch := 4, overpower_facch := 4 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_always_on_facch() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower is always on, SACCH disabled */
+ var template (value) TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0, /* always on */
+ sacch_enable := false),
+ steps := {
+ /* Channel established, FACCH overpower */
+ { meas_res := omit,
+ overpower_sacch := 0, overpower_facch := 4 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 0, overpower_facch := 4 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 0, overpower_facch := 4 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_always_on_sacch() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower is always on, FACCH disabled */
+ var template (value) TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(4), /* 4 x 2dB = 8dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0, /* always on */
+ facch_enable := false),
+ steps := {
+ /* Channel established, SACCH overpower */
+ { meas_res := omit,
+ overpower_sacch := 4, overpower_facch := 0 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 4, overpower_facch := 0 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 4, overpower_facch := 0 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+testcase TC_acch_overpower_limit() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ /* Overpower higher than current power reduction level (2dB) */
+ var template (value) TopTestCase top := {
+ bs_power := ts_RSL_IE_BS_Power(1), /* 1 x 2dB = 2dB */
+ top_cap := ts_RSL_IE_OSMO_TopAcchCap(overpower := 4, /* 4dB */
+ rxqual := 0 /* always on */),
+ steps := {
+ /* Channel established, ACCH overpower of 2dB */
+ { meas_res := omit,
+ overpower_sacch := 2, overpower_facch := 2 },
+ /* MS indicates good RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 0),
+ overpower_sacch := 2, overpower_facch := 2 },
+ /* MS indicates bad RxQual, no difference */
+ { meas_res := ts_MeasurementResults(rxq_f := 7),
+ overpower_sacch := 2, overpower_facch := 2 }
+ }
+ };
+
+ pars := valueof(t_Pars(t_RslChanNr_Bm(0), ts_RSL_ChanMode_SIGN,
+ spec := { top := top }, trx_nr := 1));
+ vc_conn := f_start_handler(refers(f_TC_acch_overpower), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
/* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */
/* protocol error as per 44.006 */
/* link layer failure (repetition of I-frame N200 times without ACK */
@@ -6719,10 +9239,8 @@ testcase TC_chopped_ipa_payload() runs on test_CT {
** multirate
* check DEACTIVATE SACCH
** unsupported algorithm
-* handover detection
* BS Power Control
* Physical Context
-* RF resource ind
* error handling
** IE duplicated?
* PCU interface
@@ -6732,6 +9250,7 @@ testcase TC_chopped_ipa_payload() runs on test_CT {
*/
control {
+ execute( TC_est_dchan() );
execute( TC_chan_act_stress() );
execute( TC_chan_act_react() );
execute( TC_chan_deact_not_active() );
@@ -6749,16 +9268,24 @@ control {
execute( TC_rach_count() );
execute( TC_rach_max_ta() );
execute( TC_ho_rach() );
+ execute( TC_ho_physical_info() );
execute( TC_rach_load_idle_thresh0() );
execute( TC_rach_load_idle_below_thresh() );
execute( TC_rach_load_count() );
+ execute( TC_meas_res_speech_tchf() );
+ execute( TC_meas_res_speech_tchf_facch() );
+ execute( TC_meas_res_speech_tchh() );
+ execute( TC_meas_res_speech_tchh_facch() );
+ execute( TC_meas_res_speech_tchh_toa256() );
execute( TC_meas_res_sign_tchf() );
execute( TC_meas_res_sign_tchh() );
execute( TC_meas_res_sign_sdcch4() );
execute( TC_meas_res_sign_sdcch8() );
execute( TC_meas_res_sign_tchh_toa256() );
+ execute( TC_meas_res_speech_tchf_sapi3() );
+ execute( TC_meas_res_speech_tchh_sapi3() );
execute( TC_tx_power_start_ramp_up_bcch() );
- execute( TC_tx_power_start_ramp_down_bcch() );
+ execute( TC_tx_power_down_bcch() );
execute( TC_tx_power_ramp_adm_state_change() );
execute( TC_rsl_bs_pwr_static_ass() );
execute( TC_rsl_bs_pwr_static_power_control() );
@@ -6772,6 +9299,7 @@ control {
execute( TC_rsl_chan_initial_ms_pwr() );
execute( TC_rsl_chan_initial_ta() );
execute( TC_rsl_modify_encr() );
+ execute( TC_rsl_rf_resource_ind() );
execute( TC_conn_fail_crit() );
execute( TC_paging_imsi_80percent() );
execute( TC_paging_tmsi_80percent() );
@@ -6793,14 +9321,18 @@ control {
execute( TC_ipa_crcx_mdcx_dlcx_not_active() );
execute( TC_ipa_crcx_mdcx_mdcx_dlcx_not_active() );
execute( TC_ipa_crcx_sdcch_not_active() );
+ execute( TC_ipa_crcx_ack_addr() );
if (mp_pcu_socket != "") {
+ execute( TC_paging_imsi_200percent_with_ps() );
execute( TC_pcu_act_req() );
execute( TC_pcu_act_req_wrong_ts() );
execute( TC_pcu_act_req_wrong_bts() );
execute( TC_pcu_act_req_wrong_trx() );
execute( TC_pcu_deact_req() );
execute( TC_pcu_deact_req_wrong_ts() );
+ execute( TC_pcu_ver_si1() );
+ execute( TC_pcu_ver_si3() );
execute( TC_pcu_ver_si13() );
if (mp_l1_supports_gprs) {
execute( TC_pcu_data_req_pdtch() );
@@ -6814,6 +9346,7 @@ control {
execute( TC_pcu_data_req_agch() );
execute( TC_pcu_data_req_pch() );
execute( TC_pcu_data_req_imm_ass_pch() );
+ execute( TC_pcu_data_req_imm_ass_agch() );
execute( TC_pcu_rach_content() );
execute( TC_pcu_ext_rach_content() );
execute( TC_pcu_data_ind_lqual_cb() );
@@ -6835,7 +9368,11 @@ control {
execute( TC_dyn_osmo_pdch_double_act() );
execute( TC_dyn_ipa_pdch_act_deact() );
execute( TC_dyn_ipa_pdch_act_tchf_act_nack() );
-
+ execute( TC_pcu_info_ind_fh_params() );
+ execute( TC_pcu_socket_nsvc_ipv4() );
+ execute( TC_pcu_socket_nsvc_ipv6() );
+ execute( TC_pcu_socket_two_nsvc() );
+ execute( TC_pcu_interf_ind() );
} else {
log("PCU socket path not available, skipping PCU tests");
}
@@ -6843,6 +9380,9 @@ control {
execute( TC_dyn_osmo_pdch_unsol_deact() );
execute( TC_dyn_osmo_pdch_tchf_act() );
execute( TC_dyn_osmo_pdch_tchh_act() );
+ execute( TC_dyn_osmo_pdch_sdcch8_act() );
+ execute( TC_dyn_osmo_pdch_tchh_race_act() );
+ execute( TC_dyn_osmo_pdch_sdcch8_race_act() );
execute( TC_dyn_ipa_pdch_tchf_act() );
execute( TC_dyn_ipa_pdch_tchf_act_pdch_act_nack() );
@@ -6862,9 +9402,11 @@ control {
execute( TC_chan_act_a51() );
execute( TC_chan_act_a52() );
execute( TC_chan_act_a53() );
+ execute( TC_chan_act_a54() );
execute( TC_encr_cmd_a51() );
execute( TC_encr_cmd_a52() );
execute( TC_encr_cmd_a53() );
+ execute( TC_encr_cmd_a54() );
execute( TC_err_rep_wrong_mdisc() );
execute( TC_err_rep_wrong_msg_type() );
@@ -6877,6 +9419,31 @@ control {
execute( TC_chopped_ipa_ping() );
execute( TC_chopped_ipa_payload() );
+
+ execute( TC_ms_pwr_ctrl_constant() );
+ execute( TC_ms_pwr_ctrl_pf_ewma() );
+
+ execute( TC_speech_no_rtp_tchf() );
+ execute( TC_speech_no_rtp_tchh() );
+ execute( TC_speech_rtp_tchf() );
+ execute( TC_speech_rtp_tchh() );
+ execute( TC_speech_osmux_tchf() );
+ execute( TC_speech_osmux_tchh() );
+
+ execute( TC_data_rtp_tchf144() );
+ execute( TC_data_rtp_tchf96() );
+ execute( TC_data_rtp_tchf48() );
+ execute( TC_data_rtp_tchh48() );
+ execute( TC_data_rtp_tchf24() );
+ execute( TC_data_rtp_tchh24() );
+
+ execute( TC_early_immediate_assignment() );
+
+ execute( TC_acch_overpower_rxqual_thresh() );
+ execute( TC_acch_overpower_rxqual_thresh_dtx() );
+ execute( TC_acch_overpower_always_on_facch() );
+ execute( TC_acch_overpower_always_on_sacch() );
+ execute( TC_acch_overpower_limit() );
}
diff --git a/bts/BTS_Tests_ASCI.ttcn b/bts/BTS_Tests_ASCI.ttcn
new file mode 100644
index 00000000..6814295b
--- /dev/null
+++ b/bts/BTS_Tests_ASCI.ttcn
@@ -0,0 +1,423 @@
+module BTS_Tests_ASCI {
+
+/* ASCI Integration Tests for OsmoBTS
+ *
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ *
+ * Authors: Harald Welte; Andreas Eversberg
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from L1CTL_PortType all;
+import from L1CTL_Types all;
+import from LAPDm_Types all;
+import from IPA_Emulation all;
+import from GSM_RR_Types all;
+import from L3_Templates all;
+
+import from MobileL3_CommonIE_Types all;
+
+import from RSL_Emulation all;
+import from RSL_Types all;
+
+import from BTS_Tests all;
+
+
+
+/* convert from boolean value to BIT1 */
+private function bool2bit1(boolean inp) return BIT1 {
+ if (inp) {
+ return '1'B;
+ } else {
+ return '0'B;
+ }
+}
+
+/* encode a VBS/VGCS call reference into it's OCT5 representation */
+private function f_enc_gcr(integer call_ref, boolean is_group_call, boolean ack_required := false)
+return OCT5
+{
+ var DescriptiveGroupOrBroadcastCallReference_V v := {
+ binaryCodingOfGroupOrBroadcastCallReference := int2bit(call_ref, 27),
+ sF := bool2bit1(is_group_call),
+ aF := bool2bit1(ack_required),
+ callPriority := '000'B,
+ cipheringInformation := '0000'B,
+ spare := '0000'B
+ }
+ return bit2oct(encvalue(v));
+}
+
+/* Send Notification command to start and stop notifying an ASCI call.
+ * When it starts, it is expected that NCH is received by MS. Also it is expected that NCH is received again.
+ * When it stops, it is expected that NCH is not received anymore. */
+testcase TC_vbs_notification() runs on test_CT
+{
+ timer T;
+
+ f_init();
+ f_init_l1ctl();
+ f_l1_tune(L1CTL);
+
+ var OCT5 gcr := f_enc_gcr(hex2int('2342'H), false, false);
+ var OCT3 chan_desc := '234266'O;
+ var octetstring notif_nch := '090620B42230000091A1330B2B2B2B2B2B2B2B2B2B2B2B'O;
+ var integer recv_count := 0;
+
+ log("Sending RSL NOTIF_CMD (start)");
+ RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_NOTIF_CMD_START(gcr, chan_desc)));
+
+ /* NCH must be received twice. */
+ T.start(2.0);
+ alt {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, notif_nch)) {
+ log("Received matching NOTIFICATION/NCH.");
+ recv_count := recv_count + 1;
+ if (recv_count != 2) {
+ repeat;
+ }
+ T.stop;
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for NCH message");
+ }
+ }
+
+ log("Sending RSL NOTIF_CMD (stop)");
+ RSL_CCHAN.send(ts_ASP_RSL_UD(ts_RSL_NOTIF_CMD_STOP(gcr)));
+
+ /* Flush pending messages and be sure that the sending of notifications has stopped. */
+ f_sleep(1.0);
+ L1CTL.clear;
+
+ /* NCH must not be received. */
+ T.start(2.0);
+ alt {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?, notif_nch)) {
+ T.stop;
+ setverdict(fail, "Received unexpected NOTIFICATION/NCH.");
+ }
+ [] L1CTL.receive { repeat; }
+ [] T.timeout {
+ log("Not received NOTIFICATION/NCH. (as expected)");
+ setverdict(pass);
+ }
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* Sub function to clean up MS and BTS. */
+private function f_vgcs_cleanup() runs on ConnHdlr
+{
+ /* Cleanup L1CTL. */
+ f_L1CTL_RESET(L1CTL);
+ f_l1_tune(L1CTL);
+
+ /* Cleanup VGCS Channel. */
+ f_rsl_chan_deact();
+}
+
+/* A VGCS channel is activated. The BSC sends UPLINK FREE message and UPLINK BUSY message.
+ * When the UPLINK FREE message is sent, the MS is expected to receive several UPLINK FREE messages.
+ * Then the UPLINK BUSY message is sent, the MS is expected to receive one UPLINK BUSY message.
+ */
+private function f_TC_vgcs_uplink_free_and_busy(charstring id) runs on ConnHdlr
+{
+ var octetstring uplink_free := '082B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
+ var octetstring uplink_busy := '062A'O;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* Activate channel on the BTS side */
+ log("Activating VGCS channel.");
+ f_rsl_chan_act(g_pars.chan_mode);
+
+ /* enable dedicated mode */
+ f_l1ctl_est_dchan(L1CTL, g_pars);
+
+ /* Send one UPLINK FREE message and expect them to be repeated. */
+ log("Send UPLINK FREE.");
+ RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), uplink_free));
+ for (var integer i := 0; i < 20; i := i + 1) {
+ f_l1_exp_lapdm(tr_LAPDm_Bter_UI(uplink_free));
+ log("Received UPLINK FREE.");
+ }
+
+ /* Send one UPLINK BUSY message and expect it to be received. */
+ log("Send UPLINK BUSY.");
+ RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), uplink_busy));
+ f_l1_exp_lapdm(tr_LAPDm_UI(0, cr_MT_CMD, uplink_busy));
+ log("Received UPLINK BUSY.");
+
+ /* Deactivate and cleanup. */
+ f_vgcs_cleanup();
+}
+testcase TC_vgcs_uplink_free_and_busy() runs on test_CT
+{
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F_GROUP, RSL_CMOD_SP_GSM1);
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ch_mode));
+ vc_conn := f_start_handler(refers(f_TC_vgcs_uplink_free_and_busy), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* Sub function to test talker detect. */
+private function f_vgcs_talker_detect() runs on ConnHdlr
+{
+ var octetstring uplink_free := '082B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
+ var octetstring uplink_access := 'C0'O;
+ var template octetstring uplink_grant := '0609C0*'O;
+ var RSL_Message rm;
+ var GsmFrameNumber fn;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* Activate channel on the BTS side. */
+ log("Activating VGCS channel.");
+ f_rsl_chan_act(g_pars.chan_mode);
+
+ /* Enable dedicated mode. */
+ f_l1ctl_est_dchan(L1CTL, g_pars);
+
+ /* Send one UPLINK FREE message and expect them to be repeated. */
+ log("Send UPLINK FREE.");
+ RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, ts_RslLinkID_DCCH(0), uplink_free));
+ f_l1_exp_lapdm(tr_LAPDm_Bter_UI(uplink_free));
+ log("Received UPLINK FREE.");
+
+ /* Send UPLINK ACCESS on VGCS channel. */
+ log("Send UPLINK ACCESS.");
+ fn := f_L1CTL_RACH(L1CTL, oct2int(uplink_access), chan_nr := g_pars.chan_nr);
+
+ /* Receive UPLINK GRANT by the MS. */
+ f_l1_exp_lapdm(tr_LAPDm_UI(0, cr_MT_CMD, uplink_grant));
+ log("Received VGCS UPLINK GRANT.");
+
+ /* Wait for talker detection. */
+ timer T := 1.0;
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_TALKER_DET(g_pars.chan_nr, ?)) -> value rm {
+ log("RSL Talker Detect has been detected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive(tr_RSL_CHAN_RQD(?, ?, ?, ?)) -> value rm {
+ setverdict(fail, "RSL_CHAN_RQD was not expected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL Talker Detect.");
+ }
+ }
+}
+
+/* A VGCS channel is activated. The BSC sends UPLINK FREE message. The MS sends RACH on VGCS channel.
+ * The MS receives VGCS UPLINK GRAND, but does not respond to it. It is expeced that the BSC receivce RSL CONN FAIL.
+ */
+private function f_TC_vgcs_talker_fail(charstring id) runs on ConnHdlr
+{
+ var RSL_Message rm;
+
+ /* Perform link establishment and talker detection. */
+ f_vgcs_talker_detect();
+
+ /* Leave dedicated channel, to force link timeout. */
+ f_L1CTL_RESET(L1CTL);
+ f_l1_tune(L1CTL);
+
+ /* Wait for link timeout. */
+ timer T := 40.0;
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_CONN_FAIL_IND(g_pars.chan_nr, ?)) -> value rm {
+ log("RSL Conn Fail Ind has been detected as expected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL Conn Fail Ind.");
+ }
+ }
+
+ /* Deactivate and cleanup. */
+ f_vgcs_cleanup();
+}
+testcase TC_vgcs_talker_fail() runs on test_CT
+{
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F_GROUP, RSL_CMOD_SP_GSM1);
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ch_mode));
+ pars.t_guard := 60.0;
+ vc_conn := f_start_handler(refers(f_TC_vgcs_talker_fail), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+/* A VGCS channel is activated. The BSC sends UPLINK FREE message. The MS sends RACH on VGCS channel.
+ * The MS receives VGCS UPLINK GRAND and establishes layer 2. Then the BSC forces to releases the uplink.
+ */
+private function f_TC_vgcs_talker_est_rel(charstring id) runs on ConnHdlr
+{
+ var octetstring uplink_free := '082B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
+ var octetstring l3 := '01020304'O;
+ template RslLinkId link_id := ts_RslLinkID_DCCH(0);
+ var RSL_Message rm;
+
+ /* Perform link establishment and talker detection. */
+ f_vgcs_talker_detect();
+
+ /* Establish layer 2. It also detects, if RSL Est Ind is received. */
+ f_est_rll_mo(0, valueof(link_id), l3);
+
+ /* Release link by BSC. */
+ RSL.send(ts_RSL_REL_REQ(g_chan_nr, link_id, RSL_REL_MODE_LOCAL));
+
+ log("Send UPLINK FREE.");
+ RSL.send(ts_RSL_UNITDATA_REQ(g_chan_nr, link_id, uplink_free));
+ f_l1_exp_lapdm(tr_LAPDm_Bter_UI(uplink_free));
+ log("Received UPLINK FREE.");
+
+ /* Deactivate and cleanup. */
+ f_vgcs_cleanup();
+}
+testcase TC_vgcs_talker_est_rel() runs on test_CT
+{
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F_GROUP, RSL_CMOD_SP_GSM1);
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ch_mode));
+ vc_conn := f_start_handler(refers(f_TC_vgcs_talker_est_rel), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private function f_TC_vgcs_listener_det(charstring id) runs on ConnHdlr
+{
+ var octetstring uplink_access := '25'O;
+ var RSL_Message rm;
+ var GsmFrameNumber fn;
+
+ f_l1_tune(L1CTL);
+ RSL.clear;
+
+ /* Activate channel on the BTS side. */
+ log("Activating VGCS channel.");
+ f_rsl_chan_act(g_pars.chan_mode);
+
+ /* Enable dedicated mode. */
+ f_l1ctl_est_dchan(L1CTL, g_pars);
+
+ /* Send UPLINK ACCESS on VGCS channel. */
+ log("Send UPLINK ACCESS.");
+ fn := f_L1CTL_RACH(L1CTL, oct2int(uplink_access), chan_nr := g_pars.chan_nr);
+
+ /* Wait for listener detection. */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_LISTENER_DET(g_pars.chan_nr, ?)) -> value rm {
+ log("RSL Talker Listener has been detected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive(tr_RSL_CHAN_RQD(?, ?, ?, ?)) -> value rm {
+ setverdict(fail, "RSL_CHAN_RQD was not expected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL Listener Detect.");
+ }
+ }
+
+ /* Send UPLINK ACCESS on VGCS channel. */
+ log("Send second UPLINK ACCESS.");
+ fn := f_L1CTL_RACH(L1CTL, oct2int(uplink_access), chan_nr := g_pars.chan_nr);
+
+ /* Wait for listener detection. */
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_LISTENER_DET(g_pars.chan_nr, ?)) {
+ setverdict(fail, "RSL Listener Detect has been detected, but not expected!");
+ T.stop;
+ }
+ [] RSL.receive(tr_RSL_CHAN_RQD(?, ?, ?, ?)) -> value rm {
+ setverdict(fail, "RSL_CHAN_RQD was not expected: ", rm);
+ T.stop;
+ }
+ [] RSL.receive { repeat; }
+ [] T.timeout {
+ log("Timeout waiting for RSL Listener Detect, as expected.");
+ }
+ }
+
+ /* Deactivate and cleanup. */
+ f_vgcs_cleanup();
+}
+testcase TC_vgcs_listener_det() runs on test_CT
+{
+ var template RSL_IE_ChannelMode ch_mode;
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+
+ f_init();
+
+ ch_mode := ts_RSL_ChanMode(RSL_CHRT_TCH_F_GROUP, RSL_CMOD_SP_GSM1);
+ pars := valueof(t_Pars(t_RslChanNr_Bm(1), ch_mode));
+ vc_conn := f_start_handler(refers(f_TC_vgcs_listener_det), pars);
+ vc_conn.done;
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+control {
+ execute( TC_vbs_notification() );
+ execute( TC_vgcs_uplink_free_and_busy() );
+ execute( TC_vgcs_talker_fail() );
+ execute( TC_vgcs_talker_est_rel() );
+ execute( TC_vgcs_listener_det() );
+
+}
+
+}
diff --git a/bts/BTS_Tests_LAPDm.ttcn b/bts/BTS_Tests_LAPDm.ttcn
index 9981bbc9..7dda8b88 100644
--- a/bts/BTS_Tests_LAPDm.ttcn
+++ b/bts/BTS_Tests_LAPDm.ttcn
@@ -41,26 +41,24 @@ function f_lapdm_exit() runs on lapdm_test_CT {
unmap(lapdm_component:L1CTL, system:L1CTL);
}
-/* master function establishing a dedicated radio channel (takes care of RACH/IMM.ASS handling) */
-function f_establish_dcch() runs on lapdm_test_CT {
- var BCCH_tune_req tune_req := { arfcn := { false, mp_trx0_arfcn }, combined_ccch := true };
- var DCCH_establish_req est_req := { ra := 23 };
-
- LAPDM.send(tune_req);
- LAPDM.send(est_req);
- LAPDM.receive(DCCH_establish_res:?);
-}
-
/* master function switching to a dedicated radio channel */
function f_switch_dcch() runs on ConnHdlr {
- var BCCH_tune_req tune_req := { arfcn := { false, mp_trx0_arfcn }, combined_ccch := true };
- var DCCH_switch_req sw_req := { ma := g_pars.ma };
+ var TrxParsItem trx_pars := mp_trx_pars[g_pars.trx_nr];
+ var GsmBandArfcn arfcn := valueof(ts_GsmBandArfcn(trx_pars.arfcn));
+ var BCCH_tune_req tune_req := { arfcn := arfcn, combined_ccch := true };
+ var DCCH_switch_req sw_req;
/* Craft channel description (with or without frequency hopping parameters) */
- if (ispresent(g_pars.maio_hsn)) {
- sw_req.chan_desc := valueof(ts_ChanDescH1(g_pars.chan_nr, g_pars.maio_hsn));
+ if (g_pars.fhp.enabled) {
+ sw_req.chan_desc := valueof(ts_ChanDescH1(g_pars.chan_nr,
+ g_pars.fhp.maio_hsn,
+ g_pars.tsc));
+ sw_req.ma := g_pars.fhp.ma;
} else {
- sw_req.chan_desc := valueof(ts_ChanDescH0(g_pars.chan_nr, mp_trx0_arfcn));
+ sw_req.chan_desc := valueof(ts_ChanDescH0(g_pars.chan_nr,
+ trx_pars.arfcn,
+ g_pars.tsc));
+ sw_req.ma := omit;
}
LAPDM.send(tune_req);
@@ -239,7 +237,7 @@ private function fp_common_init() runs on ConnHdlr
/* Obtain frequency hopping parameters for a given timeslot */
if (mp_freq_hop_enabled and mp_transceiver_num > 1) {
- f_resolve_fh_params(g_pars);
+ f_resolve_fh_params(g_pars.fhp, g_pars.chan_nr.tn);
}
/* activate the channel on the BTS side */
@@ -289,7 +287,7 @@ private function f_TC_sabm_retransmit_bts(charstring id) runs on ConnHdlr {
LAPDM.clear;
RSL.send(ts_RSL_EST_REQ(g_chan_nr, ts_RslLinkID_DCCH(sapi)));
- timer T := 8.0;
+ timer T := 20.0;
var integer sabm_received := 0;
T.start;
alt {
@@ -313,6 +311,7 @@ private function f_TC_sabm_retransmit_bts(charstring id) runs on ConnHdlr {
}
testcase TC_sabm_retransmit_bts() runs on test_CT {
var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
+ pars.t_guard := 30.0;
f_testmatrix_each_chan(pars, refers(f_TC_sabm_retransmit_bts));
}
@@ -803,6 +802,11 @@ private function f_TC_nr_seq_error(charstring id) runs on ConnHdlr {
/* SAPI = 0, C = 1, P = 0, M = 0, L = N201, N(S) = 0, N(R) = 1. * */
LAPDM.send(t_PH_DATA(0, false, ts_LAPDm_I(sapi, c_r:=cr_MO_CMD, p:=false,
nr:=1, ns:=0, l3:=l3_mo)));
+ /* LAPD indicates the data and then indicates error with sequence error cause. */
+ RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, l3_mo));
+ RSL.receive(tr_RSL_ERROR_IND(g_chan_nr, link_id, '07'O));
+ /* Release RSL link. */
+ RSL.send(ts_RSL_REL_REQ(g_chan_nr, link_id));
/* The BTS may: a) send a DISC frame within N200×T200; */
/* DISC SAPI = 0, C = 0, P = 1, M = 0, L = 0. */
@@ -1016,12 +1020,11 @@ runs on ConnHdlr {
p:=false, nr:=(dls.v_s) mod 8)));
[] as_ignore_background(not is_sacch);
[] LAPDM.receive(t_PH_DATA(0, is_sacch, ?)) -> value pd {
- setverdict(fail, "received unexpected LAPDm ", pd);
- repeat;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("received unexpected LAPDm ", pd));
}
[] LAPDM.receive(t_PH_DATA(0, ?, ?)) { repeat; }
[offset < lengthof(l3)] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, ?)) {
- setverdict(fail, "received RSL DATA IND before message complete");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "received RSL DATA IND before message complete");
}
}
}
@@ -1033,10 +1036,10 @@ runs on ConnHdlr {
setverdict(pass);
}
[] RSL.receive(tr_RSL_DATA_IND(g_chan_nr, link_id, ?)) {
- setverdict(fail, "Received RSL DATA IND with wrong payload");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received RSL DATA IND with wrong payload");
}
[] T.timeout {
- setverdict(fail, "Timeout waiting for RSL DATA IND of de-segmented message");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for RSL DATA IND of de-segmented message");
}
}
}
@@ -1109,7 +1112,7 @@ private function f_n200_by_chan_nr(RslChannelNr chan_nr, RslLinkId link_id) retu
/* Test if there are exactly N200+1 transmissions of I frames; inspired by 25.2.4.1 */
private function f_TC_t200_n200(charstring id) runs on ConnHdlr {
- var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0));
+ var RslLinkId link_id := valueof(ts_RslLinkID_SACCH(0));
var integer sapi := link_id.sapi;
var boolean is_sacch := false;
if (link_id.c == SACCH) {
@@ -1123,13 +1126,13 @@ private function f_TC_t200_n200(charstring id) runs on ConnHdlr {
fp_common_init();
/* some common altstep for meas res and other background noise */
- d := activate(as_ignore_background(true));
+ d := activate(as_ignore_background(not is_sacch));
RSL.clear;
LAPDM.clear;
f_establish_mo(link_id);
- var octetstring l3_mt := f_rnd_octstring(20);
+ var octetstring l3_mt := f_rnd_octstring(18);
RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
/* first transmission, P = 0 */
LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_I(sapi, c_r:=cr_MT_CMD, p:=false,
@@ -1150,7 +1153,7 @@ private function f_TC_t200_n200(charstring id) runs on ConnHdlr {
/* break */
}
}
- [] LAPDM.receive(t_PH_DATA(0, false, tr_LAPDm_I(sapi, ?, ?, ?, ?, ?))) {
+ [] LAPDM.receive(t_PH_DATA(0, is_sacch, tr_LAPDm_I(sapi, ?, ?, ?, ?, ?))) {
setverdict(fail, "Received unexpected I frame");
}
[not is_sacch] as_lapdm_acch();
@@ -1338,6 +1341,135 @@ testcase TC_sabm_incorrect_c() runs on test_CT {
f_testmatrix_each_chan(pars, refers(f_TC_sabm_incorrect_c));
}
+/* Test procedure for normal reestablishment, as per:
+ * OS#4819
+ * 3GPP TS 44.006 8.4.1.2 "Normal establishment procedure"
+ * 3GPP TS 44.006 8.4.2.1 "General requirements"
+ * 3GPP TS 44.006 8.6.3 "Procedures for re-establishment"
+ * */
+private function f_TC_normal_reestablishment(charstring id) runs on ConnHdlr {
+ var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0))
+ var octetstring l3_mo := f_rnd_octstring(c_TS0406_MAX_L3_OCTETS);
+ var default d;
+ timer T := 3.0;
+ var boolean use_sacch := false;
+ var boolean received_estind := false;
+ var boolean received_ua := false;
+
+ fp_common_init();
+
+ /* some common altstep for meas res and other background noise */
+ d := activate(as_ignore_background(true));
+ RSL.clear;
+ LAPDM.clear;
+
+ f_establish_mo(link_id);
+
+ deactivate(d);
+
+ var LapdmDlState dls := valueof(t_init_LapdmDlState);
+ f_lapdm_transceive_mo(dls, link_id, l3_mo);
+
+ LAPDM.send(t_PH_DATA(link_id.sapi, use_sacch, ts_LAPDm_SABM(link_id.sapi, c_r:=cr_MO_CMD, p:=true, l3:=''O)));
+ T.start
+ alt {
+ [] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_UA(link_id.sapi, cr_MT_RSP, f:=true, l3:=''O))) {
+ received_ua := true;
+ if (not received_estind) {
+ repeat;
+ }
+ }
+ [] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id)) {
+ received_estind := true;
+ if (not received_ua) {
+ repeat;
+ }
+ }
+ [] RSL.receive { repeat; }
+ [] LAPDM.receive { repeat; }
+ [] T.timeout { setverdict(fail, "Timeout waiting for UA"); }
+ }
+
+ /* Test we can still send data afterwards */
+ l3_mo := f_rnd_octstring(c_TS0406_MAX_L3_OCTETS);
+ dls := valueof(t_init_LapdmDlState);
+ f_lapdm_transceive_mo(dls, link_id, l3_mo);
+
+
+ fp_common_fini();
+}
+testcase TC_normal_reestablishment() runs on test_CT {
+ var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
+ f_testmatrix_each_chan(pars, refers(f_TC_normal_reestablishment));
+}
+
+/* Test procedure for normal reestablishment in state LAPD_STATE_TIMER_RECOV (after T200, waiting for Ack), as per:
+ * OS#4819
+ * 3GPP TS 44.006 8.4.1.2 "Normal establishment procedure"
+ * 3GPP TS 44.006 8.4.2.1 "General requirements"
+ * 3GPP TS 44.006 8.6.3 "Procedures for re-establishment"
+ * */
+private function f_TC_normal_reestablishment_state_unacked(charstring id) runs on ConnHdlr {
+ var RslLinkId link_id := valueof(ts_RslLinkID_DCCH(0))
+ var octetstring l3_mo := f_rnd_octstring(c_TS0406_MAX_L3_OCTETS);
+ var octetstring l3_mt := f_rnd_octstring(20);
+ var LapdmDlState dls;
+ var default d;
+ timer T := 3.0;
+ var boolean use_sacch := false;
+ var boolean received_estind := false;
+ var boolean received_ua := false;
+
+ fp_common_init();
+
+ /* some common altstep for meas res and other background noise */
+ d := activate(as_ignore_background(true));
+ RSL.clear;
+ LAPDM.clear;
+
+ f_establish_mo(link_id);
+ RSL.send(ts_RSL_DATA_REQ(g_chan_nr, link_id, l3_mt));
+ /* first transmission, P = 0 */
+ LAPDM.receive(t_PH_DATA(0, use_sacch, tr_LAPDm_I(link_id.sapi, c_r:=cr_MT_CMD, p:=false,
+ nr:=0, ns:=0, l3:=l3_mt)));
+ /* re-transmission, P = 1 */
+ LAPDM.receive(t_PH_DATA(0, use_sacch, tr_LAPDm_I(link_id.sapi, c_r:=cr_MT_CMD, p:=true,
+ nr:=0, ns:=0, l3:=l3_mt)));
+ deactivate(d);
+
+ /* We received one retrans, so peer is in LAPD_STATE_TIMER_RECOV state. Now send SABM: */
+ LAPDM.send(t_PH_DATA(link_id.sapi, use_sacch, ts_LAPDm_SABM(link_id.sapi, c_r:=cr_MO_CMD, p:=true, l3:=''O)));
+ T.start
+ alt {
+ [] LAPDM.receive(t_PH_DATA(?, use_sacch, tr_LAPDm_UA(link_id.sapi, cr_MT_RSP, f:=true, l3:=''O))) {
+ received_ua := true;
+ if (not received_estind) {
+ repeat;
+ }
+ }
+ [] RSL.receive(tr_RSL_EST_IND_NOL3(g_chan_nr, link_id)) {
+ received_estind := true;
+ if (not received_ua) {
+ repeat;
+ }
+ }
+ [] RSL.receive { repeat; }
+ [] LAPDM.receive { repeat; }
+ [] T.timeout { setverdict(fail, "Timeout waiting for UA"); }
+ }
+
+ /* Test we can still send data afterwards */
+ l3_mo := f_rnd_octstring(c_TS0406_MAX_L3_OCTETS);
+ dls := valueof(t_init_LapdmDlState);
+ f_lapdm_transceive_mo(dls, link_id, l3_mo);
+
+ fp_common_fini();
+}
+testcase TC_normal_reestablishment_state_unacked() runs on test_CT {
+ var ConnHdlrPars pars := valueof(t_Pars(t_RslChanNr_Bm(1), ts_RSL_ChanMode_SIGN));
+ f_testmatrix_each_chan(pars, refers(f_TC_normal_reestablishment_state_unacked));
+}
+
control {
execute(TC_sabm_ua_dcch_sapi0());
execute(TC_sabm_ua_dcch_sapi0_nopayload());
@@ -1360,6 +1492,8 @@ control {
execute(TC_rr_response_frame_loss());
execute(TC_incorrect_cr());
execute(TC_sabm_incorrect_c());
+ execute(TC_normal_reestablishment());
+ execute(TC_normal_reestablishment_state_unacked());
}
}
diff --git a/bts/BTS_Tests_OML.ttcn b/bts/BTS_Tests_OML.ttcn
index 4835e66e..980643a1 100644
--- a/bts/BTS_Tests_OML.ttcn
+++ b/bts/BTS_Tests_OML.ttcn
@@ -16,6 +16,13 @@ import from Osmocom_Types all;
import from AbisOML_Types all;
import from IPA_Emulation all;
import from IPA_Types all;
+import from Misc_Helpers all;
+
+import from PCUIF_Types all;
+import from PCUIF_CodecPort all;
+import from PCUIF_CodecPort all;
+
+import from BTS_Tests all;
const integer NUM_TRX := 8;
@@ -43,6 +50,8 @@ modulepar {
uint8_t mp_air_timer := 100;
uint8_t mp_ny1 := 10;
uint8_t mp_bsic := 63;
+
+ charstring mp_pcu_socket := PCU_SOCK_DEFAULT;
};
/* BSC side OML component */
@@ -53,6 +62,17 @@ type component BSC_OML_CT {
port IPA_OML_PT OML;
var uint8_t g_bts_nr := 0;
+ /* Port for Abis/Osmo/PCU */
+ port IPA_OSMO_PCU_PT IPA_OSMO_PCU;
+ /* PCU Interface of BTS */
+ port PCUIF_CODEC_PT PCU;
+ var integer g_pcu_conn_id;
+ /* Last PCU INFO IND we received */
+ var PCUIF_Message g_pcu_last_info;
+
+ /* As rxed by Get Attributes Response NM_ATT_MANUF_ID IE, see f_oml_getattr() */
+ var bitstring g_bts_features;
+
/* global test case guard timer */
timer T_oml_guard := 60.0;
};
@@ -66,6 +86,7 @@ private altstep as_Tguard() runs on BSC_OML_CT {
private altstep as_SwAct() runs on BSC_OML_CT {
var OML_PDU rx;
+ [] OML.receive(tr_OML_SwActivatedRep(?, ?));
[] OML.receive(tr_OML_SwActReq(?, ?, ?, ?)) -> value rx {
var OML_FOM_ObjectClass obj_class := rx.u.fom.hdr.obj_class;
var OML_FOM_ObjectInstance obj_inst := rx.u.fom.hdr.obj_inst;
@@ -94,9 +115,10 @@ private altstep as_IPA_evt() runs on BSC_OML_CT {
}
function f_init_oml(charstring id) runs on BSC_OML_CT {
- vc_IPA_OML := IPA_Emulation_CT.create(id & "-OML-IPA");
+ vc_IPA_OML := IPA_Emulation_CT.create(id & "-OML-IPA") alive;
map(vc_IPA_OML:IPA_PORT, system:IPA_CODEC_PT);
connect(vc_IPA_OML:IPA_OML_PORT, self:OML);
+ connect(vc_IPA_OML:IPA_OSMO_PCU_PORT, self:IPA_OSMO_PCU);
vc_IPA_OML.start(IPA_Emulation.main_server(mp_oml_ip, mp_oml_port));
T_oml_guard.start;
@@ -109,15 +131,63 @@ function f_init_oml(charstring id) runs on BSC_OML_CT {
activate(as_IPA_evt());
}
+private function f_init_pcu(PCUIF_CODEC_PT pt, charstring id,
+ out integer pcu_conn_id, out PCUIF_Message pcu_last_info) {
+ timer T := 2.0;
+ var PCUIF_send_data sd;
+
+ if (mp_pcu_socket == "") {
+ pcu_conn_id := -1;
+ return;
+ }
+ map(self:PCU, system:PCU);
+ pcu_conn_id := f_pcuif_connect(pt, mp_pcu_socket);
+
+ T.start;
+ alt {
+ [] as_pcu_info_ind(pt, pcu_conn_id, pcu_last_info);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for PCU INFO_IND");
+ }
+ }
+ pt.send(t_SD_PCUIF(pcu_conn_id, ts_PCUIF_TXT_IND(0, PCU_VERSION, testcasename())));
+}
+
+private function f_shutdown_helper() runs on BSC_OML_CT
+{
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
+}
/* Perform an "OPSTART" procedure with the speciifed MO" */
private function f_oml_opstart(template (value) OML_FOM_ObjectClass obj_class,
template (value) OML_FOM_ObjectInstance obj_inst,
- boolean exp_fail := false)
+ boolean exp_fail := false,
+ template OML_FOM_OperationalState exp_stchg := ?)
runs on BSC_OML_CT {
+ var boolean check_stchg := not istemplatekind(exp_stchg, "?");
+ var boolean ack_received := false;
+ var boolean stchg_received := not check_stchg;
+
OML.send(ts_OML_Opstart(obj_class, obj_inst));
+
alt {
+ [check_stchg] OML.receive(tr_OML_StateChgEvtRep(obj_class, obj_inst,
+ exp_stchg, NM_AVSTATE_OK)) {
+ stchg_received := true;
+ if (not ack_received) {
+ repeat;
+ }
+ setverdict(pass);
+ }
+ [check_stchg] OML.receive(tr_OML_StateChgEvtRep(obj_class, obj_inst,
+ ?, NM_AVSTATE_OK)) {
+ setverdict(fail, "Unexpected State Change for ", obj_class, " ", obj_inst);
+ }
[not exp_fail] OML.receive(tr_OML_OpstartACK(obj_class, obj_inst)) {
+ ack_received := true;
+ if (not stchg_received) {
+ repeat;
+ }
setverdict(pass);
}
[not exp_fail] OML.receive(tr_OML_OpstartNACK(obj_class, obj_inst)) {
@@ -207,7 +277,7 @@ runs on BSC_OML_CT {
}
/* Perform a "SET BTS ATTRIBUTES" procedure with the BTS */
-private function f_oml_bts_attr()
+private function f_oml_bts_setattr()
runs on BSC_OML_CT {
var OML_FOM_ObjectInstance obj_inst := valueof(ts_OML_ObjectInstance(g_bts_nr, 255, 255));
var template (value) OML_FOM_IE_List ies := {
@@ -265,12 +335,15 @@ private function f_oml_send_exp_no_resp(template (value) OML_PDU tx, charstring
}
}
-private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg) runs on BSC_OML_CT
+private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg)
+ runs on BSC_OML_CT return OML_PDU
{
+ var OML_PDU rx;
timer T := 5.0;
+
T.start;
alt {
- [] OML.receive(exp_rx) {
+ [] OML.receive(exp_rx) -> value rx {
setverdict(pass);
}
[] OML.receive { repeat; }
@@ -278,6 +351,7 @@ private function f_oml_exp_rx(template OML_PDU exp_rx, charstring err_msg) runs
setverdict(fail, "Timeout waiting for ", err_msg);
}
}
+ return rx;
}
/* Send an OML message and expect a failure event report in response */
@@ -326,7 +400,23 @@ private function f_oml_send_exp_nack(template (value) OML_PDU tx, template OML_F
}
+private function f_oml_getattr(template OML_PDU exp_rx := tr_OML_GetAttributesResponse(NM_OC_BTS, ?, ?)) runs on BSC_OML_CT
+{
+ var OML_FOM_ObjectInstance obj_inst := valueof(ts_OML_ObjectInstance(g_bts_nr, 255, 255));
+ var OML_FOM_IE_Type attr_li[2] := { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG };
+ var octetstring req_attr := ''O;
+ for (var integer i := 0; i < lengthof(attr_li); i := i + 1) {
+ req_attr := req_attr & int2oct(enum2int(attr_li[i]), 1);
+ }
+ var OML_PDU cmd := valueof(ts_OML_GetAttributes(NM_OC_BTS, obj_inst, req_attr));
+ OML.send(cmd);
+ var OML_PDU rx := f_oml_exp_rx(exp_rx, "BTS GetAttributes Response");
+
+ var OML_FOM_IE_Body ie_ari := f_OML_FOM_get_ie(rx.u.fom, NM_ATT_GET_ARI);
+ var OML_FOM_IE_Body manuf_id := f_OML_FOM_IE_List_get_ie(ie_ari.ari.ies, NM_ATT_MANUF_ID);
+ g_bts_features := oct2bit(manuf_id.other.payload);
+}
@@ -347,6 +437,7 @@ testcase TC_oml_selftest() runs on BSC_OML_CT {
testcase TC_oml_nothing() runs on BSC_OML_CT {
f_init_oml(testcasename());
f_sleep(100.0);
+ f_shutdown_helper();
}
/* test behavior for unsupported message discriminator */
@@ -363,6 +454,7 @@ testcase TC_wrong_mdisc() runs on BSC_OML_CT {
};
f_oml_send_exp_fail_rep(mmi_pdu, "Unexpected response to MMI message");
+ f_shutdown_helper();
}
/* send a message of unknown/unsupported type */
@@ -371,6 +463,7 @@ testcase TC_wrong_msgtype() runs on BSC_OML_CT {
var OML_PDU tx := valueof(ts_OML_MsgType(NM_MT_ESTABLISH_TEI, NM_OC_BTS,
ts_OML_ObjectInstance(0, 255, 255), omit));
f_oml_send_exp_fail_rep(tx, "ESTABLISH_TEI");
+ f_shutdown_helper();
}
/* send message shorter than OML header length indicates */
@@ -384,6 +477,7 @@ testcase TC_short_length() runs on BSC_OML_CT {
ts_OML_ObjectInstance(0, 255, 255),
?, ?, ?);
f_oml_exp_rx(exp_fail, "Failure Event Report");
+ f_shutdown_helper();
}
/* send message longer than OML header length indicates */
@@ -396,6 +490,7 @@ testcase TC_long_length() runs on BSC_OML_CT {
tr_OML_ChangeAdmStateACK(NM_OC_BTS, ts_OML_ObjectInstance(0, 255, 255),
NM_STATE_LOCKED);
f_oml_exp_rx(exp, "Change ADM State ACK");
+ f_shutdown_helper();
}
/* test behavior for unsupported placement (!= ONLY) */
@@ -415,6 +510,7 @@ testcase TC_wrong_placement() runs on BSC_OML_CT {
pdu.placement := ABIS_OM_PLACEMENT_LAST;
f_oml_send_exp_fail_rep(pdu, "Unexpected response to PLACEMENT_LAST");
+ f_shutdown_helper();
}
/* test behavior for sequence != 0 (invalid if mdisc == ONLY) */
@@ -429,6 +525,7 @@ testcase TC_wrong_seq() runs on BSC_OML_CT {
pdu.sequence := 23;
f_oml_send_exp_fail_rep(pdu, "Unexpected response to sequence != 0");
+ f_shutdown_helper();
}
/* test behavior for unsupported obj_class */
@@ -442,6 +539,7 @@ testcase TC_wrong_obj_class() runs on BSC_OML_CT {
/* NM_NACK_OBJCLASS_INVAL */
f_oml_send_exp_nack(pdu, NM_NACK_OBJCLASS_NOTSUPP);
+ f_shutdown_helper();
}
/* test behavior for wrong BTS number in object instance */
@@ -453,6 +551,7 @@ testcase TC_wrong_bts_nr() runs on BSC_OML_CT {
var OML_PDU pdu := valueof(ts_OML_ChangeAdmState(obj_class, obj_inst, NM_STATE_LOCKED));
f_oml_send_exp_nack(pdu, NM_NACK_BTSNR_UNKN);
+ f_shutdown_helper();
}
/* test behavior for wrong TRX number in object instance */
@@ -464,6 +563,7 @@ testcase TC_wrong_trx_nr() runs on BSC_OML_CT {
var OML_PDU pdu := valueof(ts_OML_ChangeAdmState(obj_class, obj_inst, NM_STATE_LOCKED));
f_oml_send_exp_nack(pdu, NM_NACK_TRXNR_UNKN);
+ f_shutdown_helper();
}
/* test behavior for wrong TS number in object instance */
@@ -475,6 +575,7 @@ testcase TC_wrong_ts_nr() runs on BSC_OML_CT {
var OML_PDU pdu := valueof(ts_OML_ChangeAdmState(obj_class, obj_inst, NM_STATE_LOCKED));
f_oml_send_exp_nack(pdu, NM_NACK_OBJINST_UNKN);
+ f_shutdown_helper();
}
/* RADIO CARRIER: Test OPSTART with SET BTS ATTRIBUTES; expect ACK */
@@ -486,6 +587,7 @@ testcase TC_radio_carrier_opstart() runs on BSC_OML_CT {
f_oml_radio_attr(0);
f_oml_opstart(obj_class, obj_inst);
+ f_shutdown_helper();
}
/* RADIO CARRIER: Test OPSTART without SET BTS ATTRIBUTES; expect NACK */
@@ -497,6 +599,7 @@ testcase TC_radio_carrier_opstart_noattr() runs on BSC_OML_CT {
/* we are *not* setting any attributes here */
f_oml_opstart(obj_class, obj_inst, exp_fail := true);
+ f_shutdown_helper();
}
@@ -507,8 +610,16 @@ testcase TC_bts_opstart() runs on BSC_OML_CT {
var OML_FOM_ObjectClass obj_class := NM_OC_BTS;
var OML_FOM_ObjectInstance obj_inst := valueof(ts_OML_ObjectInstance(g_bts_nr, 255, 255));
- f_oml_bts_attr();
- f_oml_opstart(obj_class, obj_inst);
+ alt {
+ [] OML.receive(tr_OML_SwActivatedRep(NM_OC_BTS, ts_OML_ObjectInstance(g_bts_nr, 255, 255))) {
+ setverdict(pass);
+ }
+ [] OML.receive { repeat; }
+ }
+
+ f_oml_bts_setattr();
+ f_oml_opstart(obj_class, obj_inst, false, NM_OPSTATE_ENABLED);
+ f_shutdown_helper();
}
@@ -521,6 +632,7 @@ testcase TC_bts_opstart_noattr() runs on BSC_OML_CT {
/* we are *not* setting any attributes here */
f_oml_opstart(obj_class, obj_inst, exp_fail := true);
+ f_shutdown_helper();
}
/* CHANNEL: Test OPSTART after SET CHANNEL ATTRIBUTES; expect ACK */
@@ -532,6 +644,7 @@ testcase TC_ts_opstart() runs on BSC_OML_CT {
f_oml_ts_attr(trx_nr := 0, ts_nr := 1);
f_oml_opstart(obj_class, obj_inst);
+ f_shutdown_helper();
}
@@ -544,6 +657,7 @@ testcase TC_ts_opstart_noattr() runs on BSC_OML_CT {
/* we are *not* setting any attributes here */
f_oml_opstart(obj_class, obj_inst, exp_fail := true);
+ f_shutdown_helper();
}
/* Ensure the initial Event State Change Reports after OML connect match our expectation */
@@ -558,6 +672,127 @@ testcase TC_initial_state_reports() runs on BSC_OML_CT {
[] OML.receive(tr_OML_StateChgEvtRep(NM_OC_BTS, ts_OML_ObjectInstance(0, 255, 255),
NM_OPSTATE_DISABLED, NM_AVSTATE_DEPENDENCY));
}
+ f_shutdown_helper();
+}
+
+/* Make sure that the IUT sends RSL Connect NACK when configuring unexistent TRX NR */
+testcase TC_ipa_rsl_connect_nack() runs on BSC_OML_CT {
+ timer T := 2.0;
+ /* Unconfigured TRX: */
+ template (value) OML_FOM_ObjectInstance obj_inst := ts_OML_ObjectInstance(0, 200, 255);
+
+ f_init_oml(testcasename());
+
+ OML.send(ts_OML_IPA_RslConnect(obj_inst, 0, 65535));
+
+ T.start;
+ alt {
+ [] OML.receive(tr_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT_NACK)) {
+ setverdict(pass);
+ }
+ [] OML.receive(tr_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT_ACK)) {
+ setverdict(fail, "RSL Connect ACK is not expected");
+ }
+ [] OML.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RSL Connect NACK");
+ }
+ }
+ f_shutdown_helper();
+}
+
+/* Make sure that the IUT forwards Container PCUIF messages between BSC and PCU */
+testcase TC_ipa_osmo_pcu_anr_fwd() runs on BSC_OML_CT {
+ var PCUIF_send_data pcu_sd_msg;
+ var PCUIF_Message msg_rx;
+ timer T := 2.0;
+
+ f_init_oml(testcasename());
+ f_init_pcu(PCU, testcasename(), g_pcu_conn_id, g_pcu_last_info);
+ f_oml_getattr();
+
+ log("BTS Features:", g_bts_features);
+ if (lengthof(g_bts_features) < 21 or g_bts_features[20] != '1'B) {
+ setverdict(fail, "Feature ABIS_OSMO_PCU not supported!");
+ }
+
+ IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP));
+ IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP));
+ IPA_OSMO_PCU.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK));
+
+ /* Sent via A-bis/IPA, received via the PCUIF */
+ var PCUIF_neigh_addr_req naddr_req := {
+ local_lac := f_rnd_int(c_UINT16_MAX),
+ local_ci := f_rnd_int(c_UINT16_MAX),
+ tgt_arfcn := f_rnd_int(c_UINT16_MAX),
+ tgt_bsic := f_rnd_int(63)
+ };
+ template (value) PCUIF_container ts_payloadReq := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_REQ,
+ spare := '00'O,
+ len := 0, /* overwritten */
+ u := { neigh_addr_req := naddr_req }
+ };
+ template (present) PCUIF_container tr_payloadReq := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_REQ,
+ spare := ?,
+ len := ?,
+ u := { neigh_addr_req := naddr_req }
+ };
+
+ IPA_OSMO_PCU.send(ts_PCUIF_CONTAINER(0, ts_payloadReq))
+ T.start;
+ alt {
+ [] PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_CONTAINER(0, tr_payloadReq))) {
+ setverdict(pass);
+ }
+ [] PCU.receive(PCUIF_send_data:?) -> value pcu_sd_msg {
+ setverdict(fail, "Unexpected message received: ", pcu_sd_msg.data, " vs exp: ",
+ t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_CONTAINER(0, tr_payloadReq)));
+ }
+ [] T.timeout { setverdict(fail, "Timeout waiting for ANR request on PCU inteface");}
+ }
+ T.stop;
+
+ /* Sent via the PCUIF, received via A-bis/IPA */
+ var PCUIF_neigh_addr_cnf naddr_cnf := {
+ orig_req := naddr_req,
+ error_code := 0,
+ mcc := 262,
+ mnc := 42,
+ mnc_3_digits := 0,
+ lac := f_rnd_int(c_UINT16_MAX),
+ rac := f_rnd_int(255),
+ cell_identity := f_rnd_int(c_UINT16_MAX)
+ };
+
+ template (value) PCUIF_container ts_payloadRsp := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_CNF,
+ spare := '00'O,
+ len := 0, /* overwritten */
+ u := { neigh_addr_cnf := naddr_cnf }
+ };
+ template (present) PCUIF_container tr_payloadRsp := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_CNF,
+ spare := ?,
+ len := ?,
+ u := { neigh_addr_cnf := naddr_cnf }
+ };
+
+ /* Send back the response: */
+ PCU.send(t_SD_PCUIF(g_pcu_conn_id, ts_PCUIF_CONTAINER(0, ts_payloadRsp)))
+ T.start;
+ alt {
+ [] IPA_OSMO_PCU.receive(tr_PCUIF_CONTAINER(0, tr_payloadRsp)) {
+ setverdict(pass);
+ }
+ [] IPA_OSMO_PCU.receive(PCUIF_Message:?) -> value msg_rx {
+ setverdict(fail, "Unexpected message received: ", msg_rx, " vs exp: ",
+ tr_PCUIF_CONTAINER(0, tr_payloadRsp));
+ }
+ [] T.timeout { setverdict(fail, "Timeout waiting for ANR request on BSC inteface"); }
+ }
+ f_shutdown_helper();
}
@@ -577,6 +812,11 @@ control {
execute( TC_ts_opstart() );
execute( TC_ts_opstart_noattr() );
execute( TC_initial_state_reports() );
+
+ execute( TC_ipa_osmo_pcu_anr_fwd() );
+
+ /* This one makes osmo-bts <= 1.6.0 crash, keep it at the end: */
+ execute( TC_ipa_rsl_connect_nack() );
}
/* BTS:
diff --git a/bts/BTS_Tests_SMSCB.ttcn b/bts/BTS_Tests_SMSCB.ttcn
index 92e80940..3cd1919c 100644
--- a/bts/BTS_Tests_SMSCB.ttcn
+++ b/bts/BTS_Tests_SMSCB.ttcn
@@ -56,6 +56,8 @@ t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def :=
type record CbchTestPars {
/* Should we execute on SDCCH4 or SDCCH8? */
RslChannelNr chan_nr,
+ /* Frequency Hopping parameters */
+ FreqHopPars fhp,
/* Parameters for BASIC CBCH */
CbchTestParsChan basic,
/* Parameters for EXTENDED CBCH */
@@ -235,6 +237,12 @@ private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
mtc.stop;
}
+ /* Obtain frequency hopping parameters for a given timeslot */
+ if (mp_freq_hop_enabled and mp_transceiver_num > 1)
+ { f_resolve_fh_params(pars.fhp, pars.chan_nr.tn); }
+ else
+ { pars.fhp.enabled := false; }
+
f_cbch_compute_exp_blocks(pars);
f_init_vty_bsc();
@@ -249,10 +257,16 @@ private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
} else {
f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED);
- /* TODO: also handle frequency hopping parameters */
- L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr,
- 7 /* TODO: mp_tsc */,
- mp_trx0_arfcn));
+
+ if (pars.fhp.enabled) {
+ L1CTL.send(ts_L1CTL_DM_EST_REQ_H1(pars.chan_nr, mp_tsc_def,
+ pars.fhp.maio_hsn.hsn,
+ pars.fhp.maio_hsn.maio,
+ pars.fhp.ma));
+ } else {
+ L1CTL.send(ts_L1CTL_DM_EST_REQ_H0(pars.chan_nr, mp_tsc_def,
+ mp_trx_pars[0].arfcn));
+ }
}
/* send SMSCB[s] via RSL */
@@ -351,7 +365,7 @@ private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
/* shared function doing the heavy lifting for most CBCH tests */
private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var integer msg_count;
timer T;
@@ -404,7 +418,7 @@ private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
}
private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
timer T := 5.0;
f_smscb_setup(pars);
@@ -683,8 +697,7 @@ testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
basic := valueof(t_CbchPC(msgs_1m_3b_default)),
extended := omit
};
- var template RslChannelNr t_chan_nr := t_RslChanNr_CBCH4(0);
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
timer T := 5.0;
f_TC_smscb_default_only(pars);
@@ -698,7 +711,7 @@ testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
T.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH4(0))) -> value dl {
log("CBCH: ", dl);
var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
/* detect the proper CBCH messages; check frame number */
@@ -905,12 +918,11 @@ const octetstring c_etws := c_etws_seg0 & c_etws_seg1 & c_etws_seg2 & c_etws_seg
/* Ensure only Paging Type 1 with segmented ETWS Primary Notification are sent after RSL_OSMO_ETWS_CMD */
testcase TC_etws_p1ro() runs on test_CT {
- var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
/* decoding the actual entire P1 rest octets by manually generated code is
* too much effort; instead simply do a binary compare to this constant */
const bitstring c_P1RO_hdr := '00101011101'B;
var integer seg_received[4] := { 0, 0, 0, 0 };
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
timer T := 10.0;
f_init();
@@ -923,7 +935,7 @@ testcase TC_etws_p1ro() runs on test_CT {
L1CTL.clear;
T.start;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
select (l3) {
case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) {
@@ -993,17 +1005,18 @@ testcase TC_etws_p1ro() runs on test_CT {
setverdict(fail, "Segment ", i, " not received often enough");
}
}
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
/* Ensure only Paging Type 1 without ETWS Primary Notification are sent after disabling them */
testcase TC_etws_p1ro_end() runs on test_CT {
- var template RslChannelNr t_chan_nr := ts_RslChanNr_PCH_AGCH(0);
/* we expect four blocks of 14 bytes, let's fill them with content easily
* distinguishable */
/* decoding the actual entire P1 rest octets by manually generated code is
* too much effort; instead simply do a binary compare to this constant */
const bitstring c_P1RO_hdr := '00101011101'B;
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
timer T := 10.0;
f_init();
@@ -1019,7 +1032,7 @@ testcase TC_etws_p1ro_end() runs on test_CT {
T.start;
L1CTL.clear;
alt {
- [] L1CTL.receive(tr_L1CTL_DATA_IND(t_chan_nr)) -> value dl {
+ [] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
var GsmRrMessage l3 := dec_GsmRrMessage(dl.payload.data_ind.payload);
select (l3) {
case (tr_PAG_REQ1(tr_MI_LV(t_MI_NoIdentity()))) { repeat; }
@@ -1034,13 +1047,15 @@ testcase TC_etws_p1ro_end() runs on test_CT {
setverdict(pass);
}
}
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
/* Ensure ETWS Primary Notification is passed from RSL to PCU interface */
testcase TC_etws_pcu() runs on test_CT {
timer T := 10.0;
- f_init();
+ f_init_with_pcuif();
f_init_l1ctl();
f_l1_tune(L1CTL, ccch_mode := CCCH_MODE_COMBINED_CBCH);
@@ -1059,6 +1074,8 @@ testcase TC_etws_pcu() runs on test_CT {
setverdict(fail, "PCU socket timeout receiving APP INFO (ETWS)");
}
}
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
}
@@ -1084,7 +1101,6 @@ control {
execute( TC_cbc_sdcch4_load_idle() );
execute( TC_cbc_sdcch4_load_overload() );
- if (false) { /* FIXME: SDCCH/8 support broken, needs trxcon + L1CTL work */
execute( TC_sms_cb_cmd_sdcch8_1block() );
execute( TC_sms_cb_cmd_sdcch8_2block() );
execute( TC_sms_cb_cmd_sdcch8_3block() );
@@ -1095,7 +1111,6 @@ control {
execute( TC_sms_cb_cmd_sdcch8_default_and_normal() );
execute( TC_cbc_sdcch8_load_idle() );
execute( TC_cbc_sdcch8_load_overload() );
- }
execute( TC_etws_p1ro() );
execute( TC_etws_p1ro_end() );
diff --git a/bts/BTS_Tests_VAMOS.ttcn b/bts/BTS_Tests_VAMOS.ttcn
new file mode 100644
index 00000000..3b840525
--- /dev/null
+++ b/bts/BTS_Tests_VAMOS.ttcn
@@ -0,0 +1,334 @@
+module BTS_Tests_VAMOS {
+
+/* Integration Tests for OsmoBTS
+ *
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanitskiy@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
+ *
+ * This module contains VAMOS specific test cases.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from L1CTL_PortType all;
+import from L1CTL_Types all;
+import from LAPDm_Types all;
+import from IPA_Emulation all;
+import from GSM_RR_Types all;
+import from L3_Templates all;
+
+import from RSL_Emulation all;
+import from RSL_Types all;
+
+import from BTS_Tests all;
+
+private type record of ChanNrModeSet ChanNrModeTest;
+private type record of ChanNrMode ChanNrModeSet;
+private type record ChanNrMode {
+ RslChannelNr chan_nr,
+ RSL_IE_ChannelMode chan_mode
+};
+
+/* VFF: V0(TCH/F) & V1(TCH/F), 2 channels total */
+private template (value) ChanNrModeTest
+ChanNrModeTestVFF(uint3_t tn) := {
+ {
+ { ts_RslChanNr_Bm(tn), /* V0(TCH/F), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_F_VAMOS) },
+ { ts_RslChanNr_Osmo_VAMOS_Bm(tn), /* V1(TCH/F), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_F_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Bm(tn), /* V0(TCH/F), FR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_F_VAMOS, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Osmo_VAMOS_Bm(tn), /* V1(TCH/F), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_F_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Bm(tn), /* V0(TCH/F), EFR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_F_VAMOS, RSL_CMOD_SP_GSM2) },
+ { ts_RslChanNr_Osmo_VAMOS_Bm(tn), /* V1(TCH/F), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_F_VAMOS, RSL_CMOD_SP_GSM3) }
+ },
+ {
+ { ts_RslChanNr_Bm(tn), /* V0(TCH/F), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_F_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Bm(tn), /* V1(TCH/F), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_F_VAMOS, RSL_CMOD_SP_GSM3) }
+ }
+};
+
+/* VHH: V0(TCH/H0) & V1(TCH/H0) + V0(TCH/H1) & V1(TCH/H1), 4 channels total */
+private template (value) ChanNrModeTest
+ChanNrModeTestVHH(uint3_t tn) := {
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* V0(TCH/H0), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 0), /* V1(TCH/H0), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* V0(TCH/H0), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), HR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 0), /* V1(TCH/H0), HR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* V0(TCH/H0), HR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 0), /* V1(TCH/H0), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* V0(TCH/H0), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 0), /* V1(TCH/H0), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) }
+ }
+};
+
+/* HVHH: TCH/H0 + V0(TCH/H1) & V1(TCH/H1), 3 channels total (mixed) */
+private template (value) ChanNrModeTest
+ChanNrModeTestHVHH(uint3_t tn) := {
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* TCH/H0, signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_TCH_H) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_OSMO_TCH_H_VAMOS) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* TCH/H0, signalling */
+ ts_RSL_ChanMode_SIGN(RSL_CHRT_TCH_H) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* TCH/H0, HR codec */
+ ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), HR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM1) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) }
+ },
+ {
+ { ts_RslChanNr_Lm(tn, 0), /* TCH/H0, AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_TCH_H, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Lm(tn, 1), /* V0(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) },
+ { ts_RslChanNr_Osmo_VAMOS_Lm(tn, 1), /* V1(TCH/H1), AMR codec */
+ ts_RSL_ChanMode(RSL_CHRT_OSMO_TCH_H_VAMOS, RSL_CMOD_SP_GSM3) }
+ }
+};
+
+private template (value) RSL_IE
+ts_RSL_IE_OsmoTSC := {
+ iei := RSL_IE_OSMO_TRAINING_SEQUENCE,
+ body := {
+ osmo_training_sequence := {
+ len := 0, /* overridden */
+ tsc_set := f_rnd_int(4),
+ tsc := f_rnd_int(8)
+ }
+ }
+}
+
+private function f_TC_vamos_exec_async(in ChanNrModeTest test, void_fn handler)
+runs on test_CT {
+ /* Up to 4 simultenious lchans */
+ var ConnHdlrPars pars[4];
+ var ConnHdlr vc_conn[4];
+
+ f_init();
+
+ for (var integer i := 0; i < lengthof(test); i := i + 1) {
+ /* Start a ConnHdlr component for each logical channel */
+ for (var integer ch := 0; ch < lengthof(test[i]); ch := ch + 1) {
+ pars[ch] := valueof(t_Pars(test[i][ch].chan_nr,
+ test[i][ch].chan_mode));
+ if (ischosen(test[i][ch].chan_mode.u.speech) and test[i][ch].chan_mode.u.speech == RSL_CMOD_SP_GSM3) {
+ pars[ch].mr_conf := valueof(ts_RSL_MultirateCfg);
+ }
+ vc_conn[ch] := f_start_handler(handler, pars[ch], l1ctl := false);
+ }
+
+ /* Wait for all ConnHdlr components to finish */
+ for (var integer ch := 0; ch < lengthof(test[i]); ch := ch + 1) {
+ vc_conn[ch].done;
+ }
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+}
+
+private function f_TC_vamos_chan_act(charstring id)
+runs on ConnHdlr {
+ var RSL_IE tsc_ie := valueof(ts_RSL_IE_OsmoTSC);
+
+ /* CHANnel ACTIVation with Osmocom specific TSC IE */
+ f_rsl_chan_act(g_pars.chan_mode, more_ies := { tsc_ie });
+
+ /* Hold the channel for a while */
+ f_sleep(0.3);
+
+ /* DEACTivate the channel */
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+
+/* VFF: V0(TCH/F) & V1(TCH/F), 2 channels total */
+testcase TC_vamos_chan_act_vff() runs on test_CT { /* TCH/F on TS1 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(1));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act));
+}
+testcase TC_vamos_chan_act_dyn_ipa_vff() runs on test_CT { /* TCH/F+PDCH on TS3 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(3));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act));
+}
+testcase TC_vamos_chan_act_dyn_osmo_vff() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act));
+}
+
+/* VHH: V0(TCH/H0) & V1(TCH/H0) + V0(TCH/H1) & V1(TCH/H1), 4 channels total */
+testcase TC_vamos_chan_act_vhh() runs on test_CT {
+ var ChanNrModeTest test := valueof(ChanNrModeTestVHH(5));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act)); /* TCH/H on TS5 */
+}
+testcase TC_vamos_chan_act_dyn_osmo_vhh() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVHH(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act));
+}
+
+/* HVHH: TCH/H0 + V0(TCH/H1) & V1(TCH/H1), 3 channels total (mixed) */
+testcase TC_vamos_chan_act_hvhh() runs on test_CT {
+ var ChanNrModeTest test := valueof(ChanNrModeTestHVHH(5));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act)); /* TCH/H on TS5 */
+}
+testcase TC_vamos_chan_act_dyn_osmo_hvhh() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestHVHH(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_act));
+}
+
+private function f_TC_vamos_chan_mode_modify(charstring id)
+runs on ConnHdlr {
+ var RSL_IE tsc_ie := valueof(ts_RSL_IE_OsmoTSC);
+
+ /* CHANnel ACTIVation with Osmocom specific IEs */
+ f_rsl_chan_act(g_pars.chan_mode, more_ies := { tsc_ie });
+
+ /* If we're in signalling mode, modify to speech */
+ if (g_pars.chan_mode.spd_ind == RSL_SPDI_SIGN) {
+ g_pars.chan_mode.spd_ind := RSL_SPDI_SPEECH;
+ g_pars.chan_mode.u.speech := RSL_CMOD_SP_GSM1;
+ } else { /* ... or vice versa */
+ g_pars.chan_mode.spd_ind := RSL_SPDI_SIGN;
+ g_pars.chan_mode.u.sign := RSL_CMOD_NO_RESOURCE;
+ }
+
+ var RSL_Message rsl := valueof(ts_RSL_MODE_MODIFY_REQ(g_chan_nr, g_pars.chan_mode));
+ rsl.ies := rsl.ies & { tsc_ie };
+ RSL.send(rsl);
+
+ timer T := 1.0;
+ T.start;
+ alt {
+ [] RSL.receive(tr_RSL_MODE_MODIFY_ACK(g_chan_nr)) { setverdict(pass); }
+ [] RSL.receive(tr_RSL_MODE_MODIFY_NACK(g_chan_nr, ?)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx MODE MODIFY NACK");
+ }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Timeout waiting for MODE MODIFY (N)ACK");
+ }
+ }
+
+ /* DEACTivate the channel */
+ f_rsl_chan_deact();
+ f_rslem_unregister(0, g_chan_nr);
+}
+
+/* VFF: V0(TCH/F) & V1(TCH/F), 2 channels total */
+testcase TC_vamos_chan_mode_modify_vff() runs on test_CT { /* TCH/F on TS1 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(1));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify));
+}
+testcase TC_vamos_chan_mode_modify_dyn_ipa_vff() runs on test_CT { /* TCH/F+PDCH on TS3 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(3));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify));
+}
+testcase TC_vamos_chan_mode_modify_dyn_osmo_vff() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVFF(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify));
+}
+
+/* VHH: V0(TCH/H0) & V1(TCH/H0) + V0(TCH/H1) & V1(TCH/H1), 4 channels total */
+testcase TC_vamos_chan_mode_modify_vhh() runs on test_CT {
+ var ChanNrModeTest test := valueof(ChanNrModeTestVHH(5));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify)); /* TCH/H on TS5 */
+}
+testcase TC_vamos_chan_mode_modify_dyn_osmo_vhh() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestVHH(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify));
+}
+
+/* HVHH: TCH/H0 + V0(TCH/H1) & V1(TCH/H1), 3 channels total (mixed) */
+testcase TC_vamos_chan_mode_modify_hvhh() runs on test_CT {
+ var ChanNrModeTest test := valueof(ChanNrModeTestHVHH(5));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify)); /* TCH/H on TS5 */
+}
+testcase TC_vamos_chan_mode_modify_dyn_osmo_hvhh() runs on test_CT { /* TCH/F+TCH/H+PDCH on TS4 */
+ var ChanNrModeTest test := valueof(ChanNrModeTestHVHH(4));
+ f_TC_vamos_exec_async(test, refers(f_TC_vamos_chan_mode_modify));
+}
+
+control {
+ /* CHANnel ACTIVation tests */
+ execute( TC_vamos_chan_act_vff() );
+ execute( TC_vamos_chan_act_vhh() );
+ execute( TC_vamos_chan_act_hvhh() );
+ execute( TC_vamos_chan_act_dyn_ipa_vff() );
+ execute( TC_vamos_chan_act_dyn_osmo_vff() );
+ execute( TC_vamos_chan_act_dyn_osmo_vhh() );
+ execute( TC_vamos_chan_act_dyn_osmo_hvhh() );
+
+ /* MODE MODIFY tests */
+ execute( TC_vamos_chan_mode_modify_vff() );
+ execute( TC_vamos_chan_mode_modify_vhh() );
+ execute( TC_vamos_chan_mode_modify_hvhh() );
+ execute( TC_vamos_chan_mode_modify_dyn_ipa_vff() );
+ execute( TC_vamos_chan_mode_modify_dyn_osmo_vff() );
+ execute( TC_vamos_chan_mode_modify_dyn_osmo_vhh() );
+ execute( TC_vamos_chan_mode_modify_dyn_osmo_hvhh() );
+}
+
+}
diff --git a/bts/expected-results.xml b/bts/expected-results.xml
index fa86f8a4..a856fca2 100644
--- a/bts/expected-results.xml
+++ b/bts/expected-results.xml
@@ -1,5 +1,6 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='156' failures='18' errors='1' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='220' failures='12' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='BTS_Tests' name='TC_est_dchan' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chan_act_stress' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chan_act_react' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chan_deact_not_active' time='MASKED'/>
@@ -10,47 +11,37 @@
<testcase classname='BTS_Tests' name='TC_sacch_multi' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_sacch_multi_chg' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_sacch_chan_act' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_sacch_chan_act_ho_async' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : Unexpected RSL message received"
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_sacch_chan_act_ho_async testcase
- </failure>
- </testcase>
- <testcase classname='BTS_Tests' name='TC_sacch_chan_act_ho_sync' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : Unexpected RSL message received"
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_sacch_chan_act_ho_sync testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_sacch_chan_act_ho_async' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_sacch_chan_act_ho_sync' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rach_content' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_rach_content_emerg' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rach_count' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rach_max_ta' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_ho_rach' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_rach_load_idle_thresh0' time='MASKED'>
- <failure type='fail-verdict'>Unexpected RACH LOAD IND: { streamId := IPAC_PROTO_RSL_TRX0 (0), rsl := { msg_disc := { msg_group := RSL_MDISC_CCHAN (6), transparent := false }, msg_type := RSL_MT_CCCH_LOAD_IND (18), ies := { { iei := RSL_IE_CHAN_NR (1), body := { chan_nr := { u := { ch0 := RSL_CHAN_NR_RACH (17) }, tn := 0 } } }, { iei := RSL_IE_RACH_LOAD (18), body := { rach_load := { len := 6, slot_count := 0, busy_count := 0, access_count := 0 } } } } } }
+ <testcase classname='BTS_Tests' name='TC_ho_physical_info' time='MASKED'>
+ <failure type='fail-verdict'>Rx unexpected Downlink DCCH (before handover RACH): MASKED
BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_rach_load_idle_thresh0 testcase
+ BTS_Tests.ttcn:MASKED TC_ho_physical_info testcase
</failure>
</testcase>
+ <testcase classname='BTS_Tests' name='TC_rach_load_idle_thresh0' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rach_load_idle_below_thresh' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_rach_load_count' time='MASKED'>
- <failure type='fail-verdict'>Unexpected RACH LOAD IND: { streamId := IPAC_PROTO_RSL_TRX0 (0), rsl := { msg_disc := { msg_group := RSL_MDISC_CCHAN (6), transparent := false }, msg_type := RSL_MT_CCCH_LOAD_IND (18), ies := { { iei := RSL_IE_CHAN_NR (1), body := { chan_nr := { u := { ch0 := RSL_CHAN_NR_RACH (17) }, tn := 0 } } }, { iei := RSL_IE_RACH_LOAD (18), body := { rach_load := { len := 6, slot_count := 0, busy_count := 0, access_count := 0 } } } } } }
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_rach_load_count testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_rach_load_count' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchf' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchf_facch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchh' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchh_facch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchh_toa256' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_meas_res_sign_tchf' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_meas_res_sign_tchh' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : Received unspecific MEAS RES { msg_disc := { msg_group := RSL_MDISC_DCHAN (4), transparent := false }, msg_type := RSL_MT_MEAS_RES (40), ies := { { iei := RSL_IE_CHAN_NR (1), body := { chan_nr := { u := { lm := { tag := '0001'B, sub_chan := 0 } }, tn := 5 } } }, { iei := RSL_IE_MEAS_RES_NR (27), body := { meas_res_nr := 1 } }, { iei := RSL_IE_UPLINK_MEAS (25), body := { uplink_meas := { len := 3, rfu := '0'B, dtx_d := false, rxlev_f_u := 10, reserved1 := '00'B, rxlev_s_u := 10, reserved2 := '00'B, rxq_f_u := 7, rxq_s_u := 7, supp_meas_info := omit } } }, { iei := RSL_IE_BS_POWER (4), body := { bs_power := { reserved := 0, epc := false, fpc := false, power_level := 0 } } }, { iei := RSL_IE_L1_INFO (10), body := { l1_info := { ms_power_lvl := 7, fpc := false, reserved := 0, actual_ta := 0 } } }, { iei := RSL_IE_L3_INFO (11), body := { l3_info := { len := 6, payload := '061539390000'O } } }, { iei := RSL_IE_MS_TIMING_OFFSET (37), body := { ms_timing_offset := 65 } } } }"
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_meas_res_sign_tchh testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_meas_res_sign_tchh' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_meas_res_sign_sdcch4' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_meas_res_sign_sdcch8' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_meas_res_sign_tchh_toa256' time='MASKED'>
- <error type='DTE'></error>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_meas_res_sign_tchh_toa256' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchf_sapi3' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_meas_res_speech_tchh_sapi3' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_tx_power_start_ramp_up_bcch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_tx_power_down_bcch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_tx_power_ramp_adm_state_change' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rsl_bs_pwr_static_ass' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rsl_bs_pwr_static_power_control' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rsl_ms_pwr_ctrl' time='MASKED'/>
@@ -62,12 +53,8 @@
<testcase classname='BTS_Tests' name='TC_rsl_ms_pwr_dyn_max' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rsl_chan_initial_ms_pwr' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rsl_chan_initial_ta' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_rsl_modify_encr' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : BTS shouldn't be able to decrypt after key change"
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_rsl_modify_encr testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_rsl_modify_encr' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_rsl_rf_resource_ind' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_conn_fail_crit' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_paging_imsi_80percent' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_paging_tmsi_80percent' time='MASKED'/>
@@ -89,13 +76,28 @@
<testcase classname='BTS_Tests' name='TC_ipa_crcx_mdcx_dlcx_not_active' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_ipa_crcx_mdcx_mdcx_dlcx_not_active' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_ipa_crcx_sdcch_not_active' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_ipa_crcx_ack_addr' time='MASKED'>
+ <failure type='fail-verdict'>CRCX ACK indicates nonsense addr "0.0.0.0"
+ BTS_Tests.ttcn:MASKED BTS_Tests control part
+ BTS_Tests.ttcn:MASKED TC_ipa_crcx_ack_addr testcase
+ </failure>
+ </testcase>
+ <testcase classname='BTS_Tests' name='TC_paging_imsi_200percent_with_ps' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_act_req' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_act_req_wrong_ts' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_act_req_wrong_bts' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_act_req_wrong_trx' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_deact_req' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_deact_req_wrong_ts' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_ver_si1' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_ver_si3' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_ver_si13' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_pdtch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_ptcch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_wrong_bts' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_wrong_trx' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_wrong_ts' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_data_req_ts_inactive' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_ptcch' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_data_req_agch' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_data_req_pch' time='MASKED'/>
@@ -116,34 +118,27 @@
<testcase classname='BTS_Tests' name='TC_pcu_socket_connect_multi' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_socket_reconnect' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_socket_noconnect_nosi3gprs' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_pcu_socket_noconnect_nosi4gprs' time='MASKED'>
- <failure type='fail-verdict'>SYSTEM_INFORMATION_TYPE_4 (28) indicates GPRS even before PCU socket connected
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_pcu_socket_noconnect_nosi4gprs testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_noconnect_nosi4gprs' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_socket_connect_si3gprs' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_socket_connect_si4gprs' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_pcu_socket_disconnect_nosi3gprs' time='MASKED'/>
- <testcase classname='BTS_Tests' name='TC_pcu_socket_disconnect_nosi4gprs' time='MASKED'>
- <failure type='fail-verdict'>SYSTEM_INFORMATION_TYPE_4 (28) indicates GPRS after PCU socket disconnected
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_pcu_socket_disconnect_nosi4gprs testcase
- </failure>
- </testcase>
- <testcase classname='BTS_Tests' name='TC_pcu_socket_verify_info_ind' time='MASKED'>
- <failure type='fail-verdict'>Expected cell_id '23' and got '0'. This either means, that the BTS is sending the wrong cell_id, or that the BTS sent it too early (OS#4179)
- BTS_Tests.ttcn:MASKED BTS_Tests control part
- BTS_Tests.ttcn:MASKED TC_pcu_socket_verify_info_ind testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_disconnect_nosi4gprs' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_verify_info_ind' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_act_deact' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_double_act' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_ipa_pdch_act_deact' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_ipa_pdch_act_tchf_act_nack' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_info_ind_fh_params' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_nsvc_ipv4' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_nsvc_ipv6' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_socket_two_nsvc' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_pcu_interf_ind' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_unsol_deact' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_tchf_act' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_tchh_act' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_sdcch8_act' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_tchh_race_act' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_dyn_osmo_pdch_sdcch8_race_act' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_ipa_pdch_tchf_act' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_dyn_ipa_pdch_tchf_act_pdch_act_nack' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_rll_est_ind' time='MASKED'/>
@@ -161,22 +156,44 @@
<testcase classname='BTS_Tests' name='TC_chan_act_a51' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chan_act_a52' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chan_act_a53' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_chan_act_a54' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_encr_cmd_a51' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_encr_cmd_a52' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_encr_cmd_a53' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_encr_cmd_a54' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_err_rep_wrong_mdisc' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_err_rep_wrong_msg_type' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_err_rep_wrong_sequence' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_lapdm_selftest' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_tch_sign_l2_fill_frame' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_tch_sign_l2_fill_frame_dtxd' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : Not enough fill frames received"
+ <failure type='fail-verdict'>Received DTX TCH fill frame with bad frame number: MASKED
BTS_Tests.ttcn:MASKED BTS_Tests control part
BTS_Tests.ttcn:MASKED TC_tch_sign_l2_fill_frame_dtxd testcase
</failure>
</testcase>
<testcase classname='BTS_Tests' name='TC_chopped_ipa_ping' time='MASKED'/>
<testcase classname='BTS_Tests' name='TC_chopped_ipa_payload' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_ms_pwr_ctrl_constant' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_ms_pwr_ctrl_pf_ewma' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_no_rtp_tchf' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_no_rtp_tchh' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_rtp_tchf' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_rtp_tchh' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_osmux_tchf' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_speech_osmux_tchh' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchf144' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchf96' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchf48' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchh48' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchf24' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_data_rtp_tchh24' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_early_immediate_assignment' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_acch_overpower_rxqual_thresh' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_acch_overpower_rxqual_thresh_dtx' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_acch_overpower_always_on_facch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_acch_overpower_always_on_sacch' time='MASKED'/>
+ <testcase classname='BTS_Tests' name='TC_acch_overpower_limit' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_cbch_load_idle_no_cbch' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch4_1block' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch4_2block' time='MASKED'/>
@@ -189,6 +206,16 @@
<testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch4_default_then_null' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_cbc_sdcch4_load_idle' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_cbc_sdcch4_load_overload' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_1block' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_2block' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_3block' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_4block' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_multi' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_schedule' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_default_only' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_sms_cb_cmd_sdcch8_default_and_normal' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_cbc_sdcch8_load_idle' time='MASKED'/>
+ <testcase classname='BTS_Tests_SMSCB' name='TC_cbc_sdcch8_load_overload' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_etws_p1ro' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_etws_p1ro_end' time='MASKED'/>
<testcase classname='BTS_Tests_SMSCB' name='TC_etws_pcu' time='MASKED'/>
@@ -229,13 +256,24 @@
<testcase classname='BTS_Tests_LAPDm' name='TC_rec_invalid_frame' time='MASKED'/>
<testcase classname='BTS_Tests_LAPDm' name='TC_segm_concat_dcch' time='MASKED'/>
<testcase classname='BTS_Tests_LAPDm' name='TC_segm_concat_sacch' time='MASKED'/>
- <testcase classname='BTS_Tests_LAPDm' name='TC_t200_n200' time='MASKED'>
- <failure type='fail-verdict'>"BTS_Tests.ttcn:MASKED : Tguard timeout"
- BTS_Tests_LAPDm.ttcn:MASKED BTS_Tests_LAPDm control part
- BTS_Tests_LAPDm.ttcn:MASKED TC_t200_n200 testcase
- </failure>
- </testcase>
+ <testcase classname='BTS_Tests_LAPDm' name='TC_t200_n200' time='MASKED'/>
<testcase classname='BTS_Tests_LAPDm' name='TC_rr_response_frame_loss' time='MASKED'/>
<testcase classname='BTS_Tests_LAPDm' name='TC_incorrect_cr' time='MASKED'/>
<testcase classname='BTS_Tests_LAPDm' name='TC_sabm_incorrect_c' time='MASKED'/>
+ <testcase classname='BTS_Tests_LAPDm' name='TC_normal_reestablishment' time='MASKED'/>
+ <testcase classname='BTS_Tests_LAPDm' name='TC_normal_reestablishment_state_unacked' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_vhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_hvhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_dyn_ipa_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_dyn_osmo_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_dyn_osmo_vhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_act_dyn_osmo_hvhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_vhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_hvhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_dyn_ipa_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_dyn_osmo_vff' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_dyn_osmo_vhh' time='MASKED'/>
+ <testcase classname='BTS_Tests_VAMOS' name='TC_vamos_chan_mode_modify_dyn_osmo_hvhh' time='MASKED'/>
</testsuite>
diff --git a/bts/gen_links.sh b/bts/gen_links.sh
index 7aa8398e..c9eb7860 100755
--- a/bts/gen_links.sh
+++ b/bts/gen_links.sh
@@ -32,15 +32,22 @@ DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
gen_links $DIR $FILES
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
DIR=../library
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_VTY_Functions.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn Osmocom_Types.ttcn RLCMAC_Templates.ttcn RLCMAC_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn RLCMAC_EncDec.cc L1CTL_Types.ttcn L1CTL_PortType.ttcn L1CTL_PortType_CtrlFunct.ttcn L1CTL_PortType_CtrlFunctDef.cc LAPDm_RAW_PT.ttcn LAPDm_Types.ttcn "
-#FILES+="NS_Emulation.ttcn NS_CodecPort.ttcn NS_CodecPort_CtrlFunct.ttcn NS_CodecPort_CtrlFunctDef.cc "
#FILES+="BSSGP_Emulation.ttcn Osmocom_Gb_Types.ttcn "
FILES+="IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp IPA_CodecPort.ttcn RSL_Types.ttcn RSL_Emulation.ttcn AbisOML_Types.ttcn "
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
FILES+="L3_Templates.ttcn L3_Common.ttcn "
FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
FILES+="TRXC_Types.ttcn TRXC_CodecPort.ttcn TRXC_CodecPort_CtrlFunct.ttcn TRXC_CodecPort_CtrlFunctDef.cc "
+FILES+="AMR_Types.ttcn "
+FILES+="RTP_CodecPort.ttcn RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_Emulation.ttcn IuUP_EncDec.cc "
+FILES+="RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc "
+FILES+="OSMUX_CodecPort.ttcn OSMUX_Emulation.ttcn OSMUX_Types.ttcn OSMUX_CodecPort_CtrlFunct.ttcn OSMUX_CodecPort_CtrlFunctDef.cc "
FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn "
FILES+="IPA_Testing.ttcn"
gen_links $DIR $FILES
diff --git a/bts/osmo-bsc.cfg b/bts/osmo-bsc.cfg
index 84a3a3c1..967e2655 100644
--- a/bts/osmo-bsc.cfg
+++ b/bts/osmo-bsc.cfg
@@ -3,22 +3,34 @@
!!
password foo
!
-log gsmtap 127.0.0.10
+log gsmtap 127.0.0.1
logging level set-all debug
+ logging filter all 1
!
log stderr
logging filter all 1
- logging color 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging print extended-timestamp 1
- logging level set-all debug
+ logging color 1
+!
+ logging level set-all notice
+ logging level rll info
+ logging level rsl debug
+ logging level msc debug
+ logging level filter debug
+ logging level pcu debug
+ logging level lctrl info
+ logging level lsccp info
!
stats interval 5
!
line vty
no login
- bind 127.0.0.11
+ bind 127.0.0.1
!
e1_input
e1_line 0 driver ipa
@@ -28,6 +40,8 @@ e1_input
cs7 instance 0
point-code 0.23.3
asp asp-clnt-msc-0 2905 0 m3ua
+ role asp
+ sctp-role client
as as-clnt-msc-0 m3ua
asp asp-clnt-msc-0
routing-key 2 0.23.3
@@ -44,9 +58,9 @@ network
handover1 power budget interval 6
handover1 power budget hysteresis 3
handover1 maximum distance 9999
- periodic location update 30
+ timer t3212 30
bts 0
- type sysmobts
+ type osmo-bts
band DCS1800
cell_identity 0
location_area_code 1
@@ -66,7 +80,7 @@ network
early-classmark-sending forbidden
early-classmark-sending-3g allowed
ip.access unit_id 1234 0
- ip.access rsl-ip 127.0.0.10
+ ip.access rsl-ip 127.0.0.2
oml ip.access stream_id 255 line 0
neighbor-list mode manual-si5
neighbor-list add arfcn 100
@@ -75,7 +89,6 @@ network
si5 neighbor-list add arfcn 20
codec-support fr
gprs mode gprs
- gprs 11bit_rach_support_for_egprs 0
gprs routing area 0
gprs network-control-order nc0
gprs cell bvci 1234
@@ -133,18 +146,98 @@ network
timeslot 7
phys_chan_config PDCH
hopping enabled 0
+ trx 1
+ rf_locked 0
+ arfcn 873
+ nominal power 50
+ max_power_red 20
+ rsl e1 tei 1
+ timeslot 0
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config SDCCH8
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config TCH/F_TCH/H_PDCH
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config TCH/F_PDCH
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config SDCCH8
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ trx 2
+ rf_locked 0
+ arfcn 875
+ nominal power 50
+ max_power_red 20
+ rsl e1 tei 2
+ timeslot 0
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config SDCCH8
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config SDCCH8
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config PDCH
+ hopping enabled 0
+ trx 3
+ rf_locked 0
+ arfcn 877
+ nominal power 50
+ max_power_red 20
+ rsl e1 tei 3
+ timeslot 0
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 1
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 2
+ phys_chan_config TCH/H
+ hopping enabled 0
+ timeslot 3
+ phys_chan_config SDCCH8
+ hopping enabled 0
+ timeslot 4
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 5
+ phys_chan_config TCH/F
+ hopping enabled 0
+ timeslot 6
+ phys_chan_config PDCH
+ hopping enabled 0
+ timeslot 7
+ phys_chan_config SDCCH8
+ hopping enabled 0
msc 0
- core-location-area-code 666
- core-cell-identity 333
- ip.access rtp-base 4000
- timeout-ping 12
- timeout-pong 14
- no timeout-ping advanced
- no bsc-welcome-text
- no bsc-msc-lost-text
- no bsc-grace-text
codec-list fr1 fr2 fr3
- type normal
allow-emergency allow
amr-config 12_2k forbidden
amr-config 10_2k forbidden
@@ -156,4 +249,3 @@ msc 0
amr-config 4_75k forbidden
bsc
mid-call-timeout 0
- no missing-msc-text
diff --git a/bts/osmo-bts.cfg b/bts/osmo-bts.cfg
index c2cd0bd8..e80f51b0 100644
--- a/bts/osmo-bts.cfg
+++ b/bts/osmo-bts.cfg
@@ -2,32 +2,51 @@
! OsmoBTS (0.4.0.446-e0fb) configuration saved from vty
!!
!
-log gsmtap 127.0.0.10
+log gsmtap 127.0.0.1
logging level set-all debug
+ logging filter all 1
!
log stderr
logging filter all 1
- logging color 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging print extended-timestamp 1
- logging level set-all debug
+ logging color 1
+!
+ logging level set-all notice
+ logging level rsl info
+ logging level meas info
+ logging level pag info
+ logging level l1c info
+ logging level dsp info
+ logging level pcu info
+ logging level trx info
+ logging level osmux info
+ logging level lmib info
+ logging level lmux info
!
line vty
no login
- bind 127.0.0.20
+ bind 127.0.0.1
!
e1_input
e1_line 0 driver ipa
e1_line 0 port 0
no e1_line 0 keepalive
phy 0
- osmotrx ip local 127.0.0.20
- osmotrx ip remote 127.0.0.21
- osmotrx fn-advance 20
- osmotrx rts-advance 5
+ osmotrx ip local 127.0.0.1
+ osmotrx ip remote 127.0.0.1
instance 0
osmotrx rx-gain 10
+ instance 1
+ osmotrx rx-gain 10
+ instance 2
+ osmotrx rx-gain 10
+ instance 3
+ osmotrx rx-gain 10
bts 0
band DCS1800
ipa unit-id 1234 0
@@ -35,22 +54,37 @@ bts 0
rtp jitter-buffer 100
paging queue-size 200
paging lifetime 0
- uplink-power-target -75
- gsmtap-sapi rach
- gsmtap-sapi agch
- gsmtap-sapi bcch
- gsmtap-sapi pch
- gsmtap-sapi sdcch
- gsmtap-sapi sacch
+ gsmtap-remote-host 127.0.0.1
+ gsmtap-sapi enable-all
+ no gsmtap-sapi pdtch
+ no gsmtap-sapi ptcch
min-qual-rach 50
min-qual-norm -5
!settsc
pcu-socket /tmp/pcu_sock
+ osmux
+ use on
+ local-ip 127.0.0.11
+ local-port 1984
trx 0
power-ramp max-initial 0 mdBm
power-ramp step-size 8000 mdB
power-ramp step-interval 1
- ms-power-control dsp
phy 0 instance 0
+ trx 1
+ power-ramp max-initial 0 mdBm
+ power-ramp step-size 8000 mdB
+ power-ramp step-interval 1
+ phy 0 instance 1
+ trx 2
+ power-ramp max-initial 0 mdBm
+ power-ramp step-size 8000 mdB
+ power-ramp step-interval 1
+ phy 0 instance 2
+ trx 3
+ power-ramp max-initial 0 mdBm
+ power-ramp step-size 8000 mdB
+ power-ramp step-interval 1
+ phy 0 instance 3
ctrl
- bind 127.0.0.20
+ bind 127.0.0.1
diff --git a/bts/regen_makefile.sh b/bts/regen_makefile.sh
index 9f1bf1da..054b7501 100755
--- a/bts/regen_makefile.sh
+++ b/bts/regen_makefile.sh
@@ -1,7 +1,32 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc UD_PT.cc RLCMAC_EncDec.cc Native_FunctionDefs.cc TRXC_CodecPort_CtrlFunctDef.cc L1CTL_PortType_CtrlFunctDef.cc TELNETasp_PT.cc"
+NAME=BTS_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSL -DIPA_EMULATION_OML -DIPA_EMULATION_CTRL"
+FILES="
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IuUP_EncDec.cc
+ L1CTL_PortType_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ OSMUX_CodecPort_CtrlFunctDef.cc
+ RLCMAC_EncDec.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ TRXC_CodecPort_CtrlFunctDef.cc
+ UD_PT.cc
+"
-../regen-makefile.sh BTS_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_OML
+ -DIPA_EMULATION_OSMO_PCU
+ -DIPA_EMULATION_RSL
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/bts/run_fake_trx.sh b/bts/run_fake_trx.sh
new file mode 100755
index 00000000..22099729
--- /dev/null
+++ b/bts/run_fake_trx.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+# Most BTS_Tests require to have fake_trx running.
+# fake trx is part of osmo-trx
+FAKE_TRX_DIR="${FAKE_TRX_DIR:-../../osmo-trx/osmocom-bb/src/target/trx_toolkit}"
+
+if [ -n "$FAKE_TRX_DIR" ] ; then
+ cd "$FAKE_TRX_DIR"
+fi
+
+exec ./fake_trx.py --trx TRX1@127.0.0.1:5700/1 --trx TRX2@127.0.0.1:5700/2 --trx TRX3@127.0.0.1:5700/3
diff --git a/cbc/BSC_ConnectionHandler.ttcn b/cbc/BSC_ConnectionHandler.ttcn
new file mode 100644
index 00000000..5f4fa59c
--- /dev/null
+++ b/cbc/BSC_ConnectionHandler.ttcn
@@ -0,0 +1,206 @@
+/* BSC (CBSP) Connection Handler of CBC test suite in TTCN-3
+ * (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 BSC_ConnectionHandler {
+
+import from Osmocom_Types all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+import from CBSP_Types all;
+import from CBSP_Templates all;
+import from CBSP_Adapter all;
+import from CBSP_CodecPort all;
+
+import from CBS_Message all;
+
+type function void_fn() runs on BSC_ConnHdlr;
+
+/* Coordinate with test_CT: */
+type port BSC_ConnHdlr_Coord_PT message {
+ inout charstring;
+} with { extension "internal" };
+
+/* this component represents a single subscriber connection */
+type component BSC_ConnHdlr extends CBSP_Adapter_CT {
+ var BSC_ConnHdlrPars g_pars;
+ port BSC_ConnHdlr_Coord_PT COORD;
+}
+
+type record BSC_ConnHdlrPars {
+ charstring bsc_host,
+ integer bsc_cbsp_port,
+ charstring cbc_host,
+ integer cbc_cbsp_port,
+ boolean tcp_is_client,
+ void_fn start_fn,
+ CBS_Message exp_cbs_msg optional,
+ BSSMAP_FIELD_CellIdentificationList cell_list_success optional,
+ CBSP_FailureListItems tx_fail_list optional
+};
+
+function f_BSC_ConnHdlr_main(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ g_pars := pars;
+ if (g_pars.tcp_is_client) {
+ CBSP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_cbsp_port,
+ g_pars.bsc_host, g_pars.bsc_cbsp_port);
+ } else {
+ CBSP_Adapter.f_bind(g_pars.bsc_host, g_pars.bsc_cbsp_port);
+ CBSP_Adapter.f_wait_client_connect();
+ }
+
+ var BSSMAP_FIELD_CellIdentificationList cell_list := {
+ cIl_allInBSS := ''O
+ };
+ activate(as_cbsp_keepalive_ack(0));
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST));
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_EMERG, CBSP_RI_DATA_LOST));
+ as_cbsp_reset(0);
+ COORD.send(COORD_MSG_CONNECTED);
+
+ g_pars.start_fn.apply();
+}
+
+altstep as_cbsp_reset(integer idx) runs on CBSP_Adapter_CT {
+ var CBSP_RecvFrom rf;
+ [] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_RESET)) -> value rf {
+ var CBSP_IE ie;
+ f_cbsp_find_ie(rf.msg, CBSP_IEI_CELL_LIST, ie);
+ CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx],
+ ts_CBSP_RESET_COMPL(ie.body.cell_list.cell_id)));
+ }
+}
+
+/* receive + acknowledge KEEP-ALIVE */
+altstep as_cbsp_keepalive_ack(integer idx) runs on CBSP_Adapter_CT {
+ [] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_KEEP_ALIVE)) {
+ CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], ts_CBSP_KEEP_ALIVE_COMPL));
+ }
+}
+
+/* receive + ignore RESTART */
+altstep as_cbsp_restart(integer idx) runs on CBSP_Adapter_CT {
+ [] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_RESTART));
+}
+
+function f_cbsp_tx_write_compl(CBS_Message msg, integer idx := 0,
+ template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
+ template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit)
+runs on BSC_ConnHdlr {
+ var template (value) CBSP_PDU tx;
+ var template (value) BSSMAP_FIELD_CellIdentificationList tx_list;
+ if (istemplatekind(tx_cell_list, "omit")) {
+ /* use the "expected list" when confirming the write-replace */
+ tx_list := msg.cell_list;
+ } else {
+ /* use an user-provided different list of cells */
+ tx_list := valueof(tx_cell_list);
+ }
+ if (istemplatekind(tx_compl_list, "omit")) {
+ if (msg_id_is_etws(msg.msg_id)) {
+ tx := ts_CBSP_WRITE_EMERG_COMPL(msg.msg_id, msg.ser_nr, tx_list);
+ } else {
+ tx := ts_CBSP_WRITE_CBS_COMPL(msg.msg_id, msg.ser_nr, tx_list, msg.channel_ind);
+ }
+ } else {
+ if (msg_id_is_etws(msg.msg_id)) {
+ tx := ts_CBSP_REPLACE_EMERG_COMPL(msg.msg_id, msg.ser_nr, msg.old_ser_nr,
+ tx_list);
+ } else {
+ tx := ts_CBSP_REPLACE_CBS_COMPL(msg.msg_id, msg.ser_nr, msg.old_ser_nr,
+ valueof(tx_compl_list), tx_list,
+ msg.channel_ind);
+ }
+ }
+ CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
+}
+
+function f_cbsp_tx_write_fail(CBS_Message msg, integer idx := 0,
+ template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
+ template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit,
+ template (omit) CBSP_FailureListItems tx_fail_list := omit)
+runs on BSC_ConnHdlr {
+ var template (value) CBSP_PDU tx;
+ tx := ts_CBSP_WRITE_CBS_FAIL(msg.msg_id, msg.ser_nr, valueof(tx_fail_list),
+ tx_compl_list, tx_cell_list, msg.channel_ind);
+ CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
+}
+
+/* handle a CBSP-WRITE-REPLACE and respond to it with COMPLETE or FAILURE depending on arguments */
+function f_cbsp_handle_write(CBS_Message msg, integer idx := 0,
+ template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
+ template (omit) CBSP_FailureListItems tx_fail_list := omit,
+ template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit)
+runs on BSC_ConnHdlr {
+ var template CBSP_IEs content_ies := {};
+ var template (present) CBSP_PDU rx_templ;
+ var CBSP_RecvFrom rf;
+ if (msg_id_is_etws(msg.msg_id)) {
+ rx_templ := tr_CBSP_WRITE_EMERG(msg.msg_id, msg.ser_nr, msg.cell_list, 1,
+ hex2int('180'H) + (msg.msg_id - 4352),
+ msg.num_bcast_req, 0)
+ } else {
+ for (var integer i := 0; i < lengthof(msg.content); i := i+1) {
+ //content_ies[i] := tr_CbspMsgContent(msg.content[i].payload, msg.content[i].user_len);
+ content_ies[i] := tr_CbspMsgContent(?, ?);
+ }
+ rx_templ := tr_CBSP_WRITE_CBS(msg.msg_id, msg.ser_nr, msg.cell_list, msg.channel_ind,
+ msg.category, msg.rep_period, msg.num_bcast_req, msg.dcs,
+ content_ies);
+ }
+ alt {
+ [] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], rx_templ)) -> value rf {
+ var template (value) CBSP_PDU tx;
+ if (istemplatekind(tx_fail_list, "omit")) {
+ f_cbsp_tx_write_compl(msg, idx, tx_cell_list, tx_compl_list);
+ } else {
+ f_cbsp_tx_write_fail(msg, idx, tx_cell_list, tx_compl_list, tx_fail_list);
+ }
+ }
+ [] as_cbsp_keepalive_ack(idx) { repeat; }
+ [] CBSP[idx].receive {
+ setverdict(fail, "Received unexpected CBSP in index ", idx);
+ }
+ }
+}
+
+/* handle a CBSP-KILL and respond to it with COMPLETE or FAILURE depending on arguments */
+function f_cbsp_handle_kill(integer idx, uint16_t msg_id, uint16_t ser_nr,
+ template BSSMAP_FIELD_CellIdentificationList exp_list,
+ template (omit) BSSMAP_FIELD_CellIdentificationList tx_list,
+ template (omit) CBSP_FailureListItems tx_fail_list := omit,
+ template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit,
+ template (omit) uint8_t channel_ind := omit)
+runs on BSC_ConnHdlr {
+ var template (present) CBSP_PDU rx_templ;
+ var CBSP_RecvFrom rf;
+
+ rx_templ := tr_CBSP_KILL(msg_id, ser_nr, exp_list, channel_ind);
+ alt {
+ [] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], rx_templ)) -> value rf {
+ var template (value) CBSP_PDU tx;
+ if (istemplatekind(tx_fail_list, "omit")) {
+ tx := ts_CBSP_KILL_COMPL(msg_id, ser_nr, tx_compl_list, tx_list, channel_ind);
+ } else {
+ tx := ts_CBSP_KILL_FAIL(msg_id, ser_nr, valueof(tx_fail_list), tx_compl_list,
+ tx_list, channel_ind);
+ }
+ CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
+ }
+ [] as_cbsp_keepalive_ack(idx) { repeat; }
+ [] CBSP[idx].receive {
+ setverdict(fail, "Received unexpected CBSP in index ", idx);
+ }
+ }
+}
+
+}
diff --git a/cbc/CBC_Tests.cfg b/cbc/CBC_Tests.cfg
new file mode 100644
index 00000000..7c2a3acc
--- /dev/null
+++ b/cbc/CBC_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./CBC_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+CBC_Tests.control
diff --git a/cbc/CBC_Tests.default b/cbc/CBC_Tests.default
new file mode 100644
index 00000000..48fe83de
--- /dev/null
+++ b/cbc/CBC_Tests.default
@@ -0,0 +1,12 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.CBCVTY.PROMPT1 := "OsmoCBC> "
+*.TCP.noDelay := "yes" // turn off nagle
+*.HTTP.use_notification_ASPs := "yes"
+
+[MODULE_PARAMETERS]
+// Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoCBC";
+
+[EXECUTE]
diff --git a/cbc/CBC_Tests.ttcn b/cbc/CBC_Tests.ttcn
new file mode 100644
index 00000000..2f1ad7f3
--- /dev/null
+++ b/cbc/CBC_Tests.ttcn
@@ -0,0 +1,937 @@
+module CBC_Tests {
+
+import from Osmocom_Types all;
+import from Socket_API_Definitions all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+import from CBSP_Types all;
+import from CBSP_Templates all;
+import from CBSP_Adapter all;
+import from CBSP_CodecPort all;
+
+import from SABP_Types all;
+import from SABP_Templates all;
+import from SABP_IEs all;
+import from SABP_PDU_Descriptions all;
+
+import from SBC_AP_IEs all;
+import from SBC_AP_Constants all;
+import from SBC_AP_PDU_Contents all;
+import from SBC_AP_PDU_Descriptions all;
+import from SBC_AP_Types all;
+import from SBC_AP_Templates all;
+import from SBC_AP_CodecPort all;
+import from SBC_AP_Adapter all;
+
+import from HTTP_Adapter all;
+import from HTTPmsg_Types all;
+import from ECBE_Types all;
+
+import from CBS_Message all;
+import from ECBE_Components all;
+import from BSC_ConnectionHandler all;
+import from MME_ConnectionHandler all;
+
+const integer MAX_BSC := 2;
+const integer MAX_MME := 2;
+
+type record BSC_modulepar_cfg {
+ boolean tcp_is_client
+};
+type record of BSC_modulepar_cfg BSC_modulepar_cfgs;
+
+type record MME_modulepar_cfg {
+ boolean sctp_is_client
+};
+type record of MME_modulepar_cfg MME_modulepar_cfgs;
+
+modulepar {
+ charstring mp_local_host := "127.0.0.2";
+ charstring mp_cbc_host := "127.0.0.1";
+ integer mp_cbc_cbsp_port := 48049;
+ integer mp_cbc_sbcap_port := c_SBC_AP_PORT;
+ integer mp_cbc_ecbe_port := 12345;
+ integer mp_local_cbsp_port := 15000;
+ integer mp_local_sbcap_port := 16000;
+ /* Must match osmo-cbc.cfg: */
+ BSC_modulepar_cfgs mp_bsc_cfg := {
+ { tcp_is_client := true },
+ { tcp_is_client := false }
+ };
+ MME_modulepar_cfgs mp_mme_cfg := {
+ { sctp_is_client := true },
+ { sctp_is_client := false }
+ };
+};
+
+type component test_CT extends CBSP_Adapter_CT, http_CT {
+ timer g_Tguard := 60.0;
+ var integer g_num_bsc;
+ var integer g_num_mme;
+ var BSC_ConnHdlr g_vc_conn_BSC[MAX_BSC];
+ var MME_ConnHdlr g_vc_conn_MME[MAX_MME];
+ var BSC_ConnHdlrPars g_pars_BSC[MAX_BSC];
+ var MME_ConnHdlrPars g_pars_MME[MAX_MME];
+ port BSC_ConnHdlr_Coord_PT COORD_BSC[MAX_BSC];
+ port MME_ConnHdlr_Coord_PT COORD_MME[MAX_BSC];
+};
+
+private function f_shutdown_helper() runs on test_CT {
+ /* Wait for all BSC cons to terminate */
+ for (var integer i := 0; i < g_num_bsc; i := i + 1) {
+ g_vc_conn_BSC[i].done;
+ }
+ /* Wait for all MME cons to terminate */
+ for (var integer i := 0; i < g_num_mme; i := i + 1) {
+ g_vc_conn_MME[i].done;
+ }
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+/* altstep for the global guard timer */
+private altstep as_Tguard() runs on test_CT {
+ [] g_Tguard.timeout {
+ setverdict(fail, "Tguard timeout");
+ all component.stop;
+ mtc.stop;
+ }
+}
+
+/*
+ * BSC Conn Handler:
+ */
+private function f_BSC_ConnHdlr_start_fn_void() runs on BSC_ConnHdlr {
+ log("Default start_fn() function called!");
+}
+private function f_init_pars_bsc(charstring bsc_host, integer bsc_cbsp_port,
+ charstring cbc_host, integer cbc_cbsp_port,
+ boolean tcp_is_client)
+ runs on test_CT return BSC_ConnHdlrPars {
+ var BSC_ConnHdlrPars pars := {
+ bsc_host := bsc_host,
+ bsc_cbsp_port := bsc_cbsp_port,
+ cbc_host := cbc_host,
+ cbc_cbsp_port := cbc_cbsp_port,
+ tcp_is_client := tcp_is_client,
+ start_fn := refers(f_BSC_ConnHdlr_start_fn_void),
+ exp_cbs_msg := omit,
+ cell_list_success := omit,
+ tx_fail_list := omit
+ };
+ return pars;
+}
+
+private function f_init_bsc(integer idx, charstring id) runs on test_CT return BSC_ConnHdlr {
+ var BSC_ConnHdlr vc_conn;
+ id := id & "-BSC" & int2str(idx);
+ vc_conn := BSC_ConnHdlr.create(id) alive;
+ g_pars_BSC[idx] := f_init_pars_bsc(mp_local_host, mp_local_cbsp_port + idx,
+ mp_cbc_host, mp_cbc_cbsp_port,
+ mp_bsc_cfg[idx].tcp_is_client);
+ connect(self:COORD_BSC[idx], vc_conn:COORD);
+ return vc_conn;
+}
+
+private function f_start_bsc(integer idx, charstring id, BSC_ConnHdlrPars pars)
+ runs on test_CT {
+ id := id & "-BSC" & int2str(idx);
+ g_vc_conn_BSC[idx] := f_init_bsc(idx, id);
+ g_vc_conn_BSC[idx].start(f_BSC_ConnHdlr_main(id, pars));
+}
+
+/*
+ * MME Conn Handler:
+ */
+private function f_MME_ConnHdlr_start_fn_void() runs on MME_ConnHdlr {
+ log("Default start_fn() function called!");
+}
+private function f_init_pars_mme(charstring mme_host, integer mme_sbcap_port,
+ charstring cbc_host, integer cbc_sbcap_port,
+ boolean sctp_is_client)
+ runs on test_CT return MME_ConnHdlrPars {
+ var MME_ConnHdlrPars pars := {
+ mme_host := mme_host,
+ mme_sbcap_port := mme_sbcap_port,
+ cbc_host := cbc_host,
+ cbc_sbcap_port := cbc_sbcap_port,
+ sctp_is_client := sctp_is_client,
+ start_fn := refers(f_MME_ConnHdlr_start_fn_void),
+ exp_cbs_msg := omit,
+ write_replace_warning_req_cause := SBC_AP_Cause_message_accepted,
+ write_replace_warning_ind_cause := omit,
+ write_repl_unknown_TAIs := omit,
+ bcast_cell_id_list := omit
+ };
+ return pars;
+}
+
+private function f_init_mme(integer idx, charstring id) runs on test_CT return MME_ConnHdlr {
+ var MME_ConnHdlr vc_conn;
+ id := id & "-MME" & int2str(idx);
+ vc_conn := MME_ConnHdlr.create(id) alive;
+ g_pars_MME[idx] := f_init_pars_mme(mp_local_host, mp_local_sbcap_port + idx,
+ mp_cbc_host, mp_cbc_sbcap_port,
+ mp_mme_cfg[idx].sctp_is_client);
+ connect(self:COORD_MME[idx], vc_conn:COORD);
+ return vc_conn;
+}
+
+private function f_start_mme(integer idx, charstring id, MME_ConnHdlrPars pars)
+ runs on test_CT {
+ id := id & "-MME" & int2str(idx);
+ g_vc_conn_MME[idx] := f_init_mme(idx, id);
+ g_vc_conn_MME[idx].start(f_MME_ConnHdlr_main(id, pars));
+}
+
+private function f_init(integer num_bsc := 0, integer num_mme := 0) runs on test_CT {
+ f_http_init(mp_cbc_host, mp_cbc_ecbe_port);
+
+ g_num_bsc := num_bsc;
+ for (var integer i := 0; i < g_num_bsc; i := i + 1) {
+ g_vc_conn_BSC[i] := f_init_bsc(i, testcasename());
+ }
+
+ g_num_mme := num_mme;
+ for (var integer i := 0; i < g_num_mme; i := i + 1) {
+ g_vc_conn_MME[i] := f_init_mme(i, testcasename());
+ }
+}
+
+function f_start(float t_guard := 60.0) runs on test_CT {
+ /* Start guard timer and activate it as default */
+ g_Tguard.start(t_guard);
+ activate(as_Tguard());
+
+ for (var integer i := 0; i < g_num_bsc; i := i + 1) {
+ f_start_bsc(i, testcasename(), g_pars_BSC[i]);
+ }
+ for (var integer i := 0; i < g_num_mme; i := i + 1) {
+ f_start_mme(i, testcasename(), g_pars_MME[i]);
+ }
+
+ /* Now wait for conns to be ready: */
+ for (var integer i := 0; i < g_num_bsc; i := i + 1) {
+ COORD_BSC[i].receive(COORD_MSG_CONNECTED);
+ }
+ for (var integer i := 0; i < g_num_mme; i := i + 1) {
+ COORD_MME[i].receive(COORD_MSG_CONNECTED);
+ }
+}
+
+/* test whether or not we receive a valid KEEP-ALIVE from the CBC */
+private function f_bsc_TC_rx_keepalive() runs on BSC_ConnHdlr {
+ var CBSP_PDU rx;
+ var CBSP_IE ie;
+ rx := f_cbsp_exp(tr_CBSP_KEEP_ALIVE(?));
+ f_cbsp_find_ie(rx, CBSP_IEI_KEEP_ALIVE_REP_PERIOD, ie);
+}
+testcase TC_rx_keepalive() runs on test_CT {
+
+ f_init(num_bsc := 1);
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_rx_keepalive);
+ f_start();
+ f_shutdown_helper();
+}
+
+/* test whether CBC terminates connection if KEEP-ALIVE is not answered by BSC */
+private function f_bsc_TC_rx_keepalive_timeout() runs on BSC_ConnHdlr {
+ var CBSP_PDU rx;
+ var CBSP_IE ie;
+ var integer ka_rep_per_s;
+
+ rx := f_cbsp_exp(tr_CBSP_KEEP_ALIVE(?));
+ f_cbsp_find_ie(rx, CBSP_IEI_KEEP_ALIVE_REP_PERIOD, ie);
+
+ /* sleep for longer than the keep-alive period */
+ ka_rep_per_s := f_cbsp_period2s(ie.body.keep_alive_rep_period);
+ f_sleep(int2float(ka_rep_per_s + 5));
+
+ /* expect the CBSP connection to be closed */
+ CBSP[0].receive(PortEvent:{connClosed:=?})
+}
+testcase TC_rx_keepalive_timeout() runs on test_CT {
+ f_init(num_bsc := 1);
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_rx_keepalive_timeout);
+ f_start(t_guard := 100.0);
+ f_shutdown_helper();
+}
+
+private const BSSMAP_FIELD_CellIdentificationList cil_BSS := {
+ cIl_allInBSS := ''O
+};
+private function f_bsc_TC_write_replace() runs on BSC_ConnHdlr {
+ f_cbsp_handle_write(g_pars.exp_cbs_msg);
+ f_sleep(100.0);
+}
+testcase TC_write_replace() runs on test_CT {
+ var CBS_Message msg := {
+ msg_id := 42,
+ ser_nr := 16752,
+ old_ser_nr := omit,
+ cell_list := cil_BSS,
+ channel_ind := 0,
+ category := CBSP_CATEG_NORMAL,
+ rep_period := 5,
+ num_bcast_req := 3,
+ dcs := 1,
+ content := {
+ { '00'O, 1 }
+ }
+ };
+
+ f_init(num_bsc := 1);
+ g_pars_BSC[0].exp_cbs_msg := msg;
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_write_replace);
+ f_start();
+ f_shutdown_helper();
+}
+
+testcase TC_selftest() runs on test_CT {
+ const octetstring c_load_q := '0700000d0400080000f110012345671200'O;
+ const octetstring c_load_q_compl := '0800000f0a000a0000f1100123456700001200'O;
+ const octetstring c_reset := '1000000b0400080000f11001234567'O;
+ const octetstring c_reset_compl := '1100000b0400080000f11001234567'O;
+ const octetstring c_msg_sts_q := '0a0000130e022b0200000400080000f110012345671200'O;
+ const octetstring c_msg_sts_q_fail := '0c0000140e022b0200000900090000f11001234567021200'O;
+ const octetstring c_kill := '040000110e00000200000400080000f11001234567'O;
+ const octetstring c_kill_fail := '060000120e00000200000900090000f1100123456702'O;
+ const octetstring c_write_repl := '010000c70e022b0300300400080000f110012345671200050006000407000613020c400107f4f29c9e769f5de337b90c921d1b8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d100'O;
+ const octetstring c_write_repl_compl := '020000130e022b0300300400080000f110012345671200'O;
+ const octetstring c_write_repl_fail := '030000140e022b0300300900090000f110012345670d1200'O;
+ const octetstring c_msg_s_q := '0a0000130e022b0200900400080000f110012345671200'O;
+ const octetstring c_msg_s_q_compl := '0b0000160e022b02009008000b0000f110012345670008001200'O;
+ const octetstring c_kill_compl := '050000160e022b02008008000b0000f110012345670006001200'O;
+
+ log(dec_CBSP_PDU(c_load_q));
+ log(dec_CBSP_PDU(c_load_q_compl));
+ log(dec_CBSP_PDU(c_reset));
+ log(dec_CBSP_PDU(c_reset_compl));
+ log(dec_CBSP_PDU(c_msg_sts_q));
+ log(dec_CBSP_PDU(c_msg_sts_q_fail));
+ log(dec_CBSP_PDU(c_kill));
+ log(dec_CBSP_PDU(c_kill_fail));
+ log(dec_CBSP_PDU(c_write_repl));
+ log(dec_CBSP_PDU(c_write_repl_compl));
+ log(dec_CBSP_PDU(c_write_repl_fail));
+ log(dec_CBSP_PDU(c_msg_s_q));
+ log(dec_CBSP_PDU(c_msg_s_q_compl));
+ log(dec_CBSP_PDU(c_kill_compl));
+}
+
+testcase TC_selftest_sabp() runs on test_CT {
+ const octetstring c_write := '00000080930000080006000211120007000240c0000f0010000113f0030282ec0613f0030282ec070001400100000d0002012a000900020000000400010100000056029f01b4d90d064297d9ec37e8fe96b3c9a0303bdd68341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d168341a8d46a3d10012'O;
+
+ log(dec_SABP_PDU(c_write));
+ log(enc_SABP_PDU(dec_SABP_PDU(c_write)));
+
+ var template (value) Service_Areas_List sa_list := {
+ ts_SabpSai('62F224'O, '0023'O, '0042'O)
+ };
+ var template (value) SABP_PDU tx;
+
+ tx := ts_SABP_Write(int2bit(1, 16), int2bit(1, 16), sa_list, 23, 42, '00000000'B, '01011010'B);
+ log("Write: ", enc_SABP_PDU(valueof(tx)))
+
+ var Service_Areas_List sa_list2 := { valueof(ts_SabpSai('62F224'O, '1000'O, '0042'O)) };
+ for (var integer i := 0; i < 2500; i := i+1) {
+ sa_list2 := sa_list2 & {valueof(ts_SabpSai('62F224'O, '2000'O, int2oct(i,2))) };
+ }
+ tx := ts_SABP_Write(int2bit(2, 16), int2bit(2, 16), sa_list2, 23, 42, '00000000'B, '01011010'B);
+ log("Write: ", enc_SABP_PDU(valueof(tx)))
+
+ tx := ts_SABP_Restart(sa_list);
+ log("Restart: ", enc_SABP_PDU(valueof(tx)));
+}
+
+private function f_bsc_create_and_delete() runs on BSC_ConnHdlr {
+ f_cbsp_handle_write(g_pars.exp_cbs_msg, 0, g_pars.cell_list_success);
+ f_cbsp_handle_kill(0, g_pars.exp_cbs_msg.msg_id, g_pars.exp_cbs_msg.ser_nr,
+ exp_list:=g_pars.cell_list_success, tx_list:=g_pars.cell_list_success,
+ tx_fail_list:=omit, tx_compl_list:=omit,
+ channel_ind:=g_pars.exp_cbs_msg.channel_ind);
+}
+
+private function f_mme_create_and_delete() runs on MME_ConnHdlr {
+ f_sbcap_handle_write_replace_warn_req(g_pars.exp_cbs_msg, 0);
+ if (ispresent(g_pars.write_replace_warning_ind_cause) and
+ ispresent(g_pars.bcast_cell_id_list)) {
+ f_sbcap_tx_write_replace_warn_ind(0, g_pars.exp_cbs_msg,
+ g_pars.write_replace_warning_ind_cause,
+ g_pars.bcast_cell_id_list)
+ }
+ f_sbcap_handle_stop_warn_req(0, g_pars.exp_cbs_msg);
+}
+
+function f_create_and_delete(CBS_Message msg)
+runs on test_CT {
+ var EcbeCbcMessage ecbe := f_cbs2ecbe(msg, "TTCN-3");
+ f_ecbe_tx_post_cbs(ecbe);
+ f_ecbe_rx_resp(201);
+
+ f_sleep(2.0);
+
+ f_ecbe_tx_delete_cbs(msg.msg_id);
+ f_ecbe_rx_resp(200);
+}
+
+private template (value) CBS_Message t_CBSmsg(uint16_t msg_id, uint16_t ser_nr) := {
+ msg_id := msg_id,
+ ser_nr := ser_nr,
+ old_ser_nr := omit,
+ cell_list := cil_BSS,
+ channel_ind := 0,
+ category := CBSP_CATEG_NORMAL,
+ rep_period := 5,
+ num_bcast_req := 3,
+ dcs := 1,
+ content := {
+ { '00'O, 1 }
+ }
+};
+
+/* specify a variety of different Cell Identifier formats to extend test coverage */
+testcase TC_ecbe_create_delete_cgi() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(43, 16752);
+
+ cell_list_success := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 43)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+testcase TC_ecbe_create_delete_lac_ci() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(44, 16752);
+ cell_list_success := ts_BSSMAP_CIL_LAC_CI({
+ ts_BSSMAP_CI_LAC_CI(10001, 50001),
+ ts_BSSMAP_CI_LAC_CI(10002, 50002),
+ ts_BSSMAP_CI_LAC_CI(10003, 50003)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+testcase TC_ecbe_create_delete_lac() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(45, 16752);
+ cell_list_success := ts_BSSMAP_CIL_LAC({
+ ts_BSSMAP_CI_LAC(10001),
+ ts_BSSMAP_CI_LAC(10002),
+ ts_BSSMAP_CI_LAC(10003)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+testcase TC_ecbe_create_delete_ci() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(46, 16752);
+ cell_list_success := ts_BSSMAP_CIL_CI({
+ ts_BSSMAP_CI_CI(50001),
+ ts_BSSMAP_CI_CI(50002),
+ ts_BSSMAP_CI_CI(50003)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+testcase TC_ecbe_create_delete_lai() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(47, 16752);
+ cell_list_success := ts_BSSMAP_CIL_LAI({
+ ts_BSSMAP_CI_LAI('901'H, '70'H, 25),
+ ts_BSSMAP_CI_LAI('901'H, '70'H, 26),
+ ts_BSSMAP_CI_LAI('901'H, '70'H, 27)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create and delete message with MME available. MME reports
+ * Write-Replace-Warning-Indication and Stop-Warning-Indication to CBC
+ */
+testcase TC_ecbe_create_delete_mme_indication() runs on test_CT {
+ var template (value) CellId_Broadcast_List bcast_cell_id_li;
+ var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
+
+ f_init(num_bsc := 0, num_mme := 1);
+
+ bcast_cell_id_li := {
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234)),
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 5678))
+ };
+ g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create and delete message with MME available. MME reports
+ * Write-Replace-Response with Unknown TAI IE.
+ */
+testcase TC_ecbe_create_delete_mme_unknown_tai() runs on test_CT {
+ var template (value) List_of_TAIs write_repl_unknown_TAIs;
+ var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
+
+ f_init(num_bsc := 0, num_mme := 1);
+
+ write_repl_unknown_TAIs := {{ts_SBCAP_TAI(f_enc_mcc_mnc('901'H, '70'H), 1234)}};
+ g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].write_repl_unknown_TAIs := valueof(write_repl_unknown_TAIs);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create and delete message with both BSC and MME available */
+testcase TC_ecbe_create_delete_bsc_and_mme() runs on test_CT {
+ f_init(num_bsc := 1, num_mme := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CellId_Broadcast_List bcast_cell_id_li;
+ var template (value) CBS_Message msg := t_CBSmsg(43, 16752);
+
+ cell_list_success := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 43)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+
+ bcast_cell_id_li := {
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234))
+ };
+ g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create and delete message with BSC acting as TCP server */
+testcase TC_ecbe_create_delete_bsc_server() runs on test_CT {
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(46, 16752);
+
+ /* The 2nd BSC is the one configured as server, but we only want to test
+ * that one, so initialize both but copy over config of the 2nd one to
+ * the first one, to start only one BSC: */
+ f_init(num_bsc := 2);
+ g_num_bsc := 1;
+ g_pars_BSC[0] := g_pars_BSC[1];
+
+ cell_list_success := ts_BSSMAP_CIL_CI({
+ ts_BSSMAP_CI_CI(50001),
+ ts_BSSMAP_CI_CI(50002),
+ ts_BSSMAP_CI_CI(50003)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create and delete message with MME acting as SCTP server */
+testcase TC_ecbe_create_delete_mme_server() runs on test_CT {
+ var template (value) CellId_Broadcast_List bcast_cell_id_li;
+ var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
+
+ /* The 2nd MME is the one configured as server, but we only want to test
+ * that one, so initialize both but copy over config of the 2nd one to
+ * the first one, to start only one MME: */
+ f_init(num_bsc := 0, num_mme := 2);
+ g_num_mme := 1;
+ g_pars_MME[0] := g_pars_MME[1];
+
+ bcast_cell_id_li := {
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234)),
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 5678))
+ };
+ g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Create 2 concurrent messages against an MME, then delete them */
+private function f_mme_TC_concurrent_cbs_msg_mme() runs on MME_ConnHdlr {
+ var CBS_Message msg[2];
+ msg[0] := g_pars.exp_cbs_msg;
+ msg[1] := msg[0];
+ msg[1].msg_id := msg[0].msg_id + 1;
+
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ f_sbcap_handle_write_replace_warn_req(msg[i], 0);
+ if (ispresent(g_pars.write_replace_warning_ind_cause) and
+ ispresent(g_pars.bcast_cell_id_list)) {
+ f_sbcap_tx_write_replace_warn_ind(0, msg[i],
+ g_pars.write_replace_warning_ind_cause,
+ g_pars.bcast_cell_id_list)
+ }
+ }
+ /* Now handle Stop: */
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ f_sbcap_handle_stop_warn_req(0, msg[i]);
+ }
+}
+testcase TC_concurrent_cbs_msg_mme() runs on test_CT {
+ var template (value) CellId_Broadcast_List bcast_cell_id_li;
+ var CBS_Message msg[2];
+ var EcbeCbcMessage ecbe;
+
+ msg[0] := valueof(t_CBSmsg(49, 16752));
+ msg[1] := msg[0];
+ msg[1].msg_id := msg[0].msg_id + 1;
+
+ f_init(num_bsc := 0, num_mme := 1);
+
+ bcast_cell_id_li := {
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234))
+ };
+ g_pars_MME[0].start_fn := refers(f_mme_TC_concurrent_cbs_msg_mme);
+ g_pars_MME[0].exp_cbs_msg := msg[0];
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
+ f_start();
+
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ ecbe := f_cbs2ecbe(msg[i], "TTCN-3");
+ f_ecbe_tx_post_cbs(ecbe);
+ f_ecbe_rx_resp(201);
+ }
+
+ f_sleep(2.0);
+
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ f_ecbe_tx_delete_cbs(msg[i].msg_id);
+ f_ecbe_rx_resp(200);
+ }
+
+ f_shutdown_helper();
+}
+
+/* Test ETWS message over CBSP. TS 23.041 9.4.1.2.2 */
+testcase TC_ecbe_create_delete_etws_bsc() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(4352 /* Earthquake */, 16752);
+ msg.channel_ind := omit;
+
+ cell_list_success := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Test ETWS message over SBc-AP. TS 23.041 9.4.1.2.2 */
+testcase TC_ecbe_create_delete_etws_mme() runs on test_CT {
+ f_init(num_mme := 1);
+ var template (value) CBS_Message msg := t_CBSmsg(4352 /* Earthquake */, 16753);
+ msg.channel_ind := omit;
+
+ g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+/* Test BSC answering WRITE-REPLACE REQUEST with WRITE-REPLACE FAILURE */
+private function f_bsc_TC_create_nack_bsc() runs on BSC_ConnHdlr {
+ f_cbsp_handle_write(g_pars.exp_cbs_msg, 0, g_pars.cell_list_success, g_pars.tx_fail_list);
+}
+testcase TC_create_nack_bsc() runs on test_CT {
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBSP_FailureListItems tx_fail_list;
+ var CBS_Message msg;
+ var EcbeCbcMessage ecbe;
+
+ msg := valueof(t_CBSmsg(49, 16752));
+
+ f_init(num_bsc := 1, num_mme := 0);
+
+ cell_list_success := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42)
+ });
+ tx_fail_list := {
+ CBSP_FailureListItem_CGI(ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 48), CBSP_CAUSE_CELL_ID_NOT_VALID),
+ CBSP_FailureListItem_LAC_CI(ts_BSSMAP_CI_LAC_CI(10001, 50001), CBSP_CAUSE_LAI_OR_LAC_NPT_VALID)
+ };
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_create_nack_bsc);
+ g_pars_BSC[0].exp_cbs_msg := msg;
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ g_pars_BSC[0].tx_fail_list := valueof(tx_fail_list);
+ f_start();
+
+ ecbe := f_cbs2ecbe(msg, "TTCN-3");
+ f_ecbe_tx_post_cbs(ecbe);
+ f_ecbe_rx_resp(201);
+
+ f_shutdown_helper();
+}
+
+/* Test MME answering Write-Replace Warning Request with Write-Replace Warning Response cause != accepted */
+private function f_mme_TC_create_nack_mme() runs on MME_ConnHdlr {
+ f_sbcap_handle_write_replace_warn_req(g_pars.exp_cbs_msg, 0);
+}
+testcase TC_create_nack_mme() runs on test_CT {
+ var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
+
+ f_init(num_bsc := 0, num_mme := 1);
+
+ g_pars_MME[0].start_fn := refers(f_mme_TC_create_nack_mme);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_req_cause := SBcAP_Cause_unspecifed_error;
+ f_start();
+ f_create_and_delete(valueof(msg));
+ f_shutdown_helper();
+}
+
+
+/* Test cell in BSC going unavailable for broadcasting and going available again */
+private function f_bsc_TC_cell_failure_restart_idle_bsc() runs on BSC_ConnHdlr {
+ var template (value) CBSP_FailureListItems fail_list := {
+ CBSP_FailureListItem_CGI(ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42), CBSP_CAUSE_CB_NOT_OPERATIONAL),
+ CBSP_FailureListItem_CGI(ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42), CBSP_CAUSE_CB_NOT_OPERATIONAL)
+ };
+ f_cbsp_send(ts_CBSP_FAILURE(fail_list, CBSP_BC_MSGT_CBS));
+ f_cbsp_send(ts_CBSP_FAILURE(fail_list, CBSP_BC_MSGT_EMERG));
+
+ f_sleep(1.0);
+
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list;
+ cell_list := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42),
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 24, 42)
+ });
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST));
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_EMERG, CBSP_RI_DATA_LOST));
+}
+testcase TC_cell_failure_restart_idle_bsc() runs on test_CT {
+ f_init(num_bsc := 1, num_mme := 0);
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_cell_failure_restart_idle_bsc);
+ f_start();
+ f_shutdown_helper();
+}
+
+/* Test cell in MME going unavailable for broadcasting and going available again */
+private function f_mme_TC_cell_failure_restart_idle_mme() runs on MME_ConnHdlr {
+ var template (value) Global_ENB_ID enb_id := ts_Global_ENB_ID_MACRO(f_enc_mcc_mnc('901'H, '70'H), 90);
+ var template (value) Failed_Cell_List fail_list := {
+ ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234),
+ ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 5678)
+ };
+ f_SBC_AP_send(ts_SBCAP_PWS_FAILURE(fail_list, enb_id));
+
+ f_sleep(1.0);
+
+ var template (value) Restarted_Cell_List cell_list;
+ cell_list := {
+ ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234),
+ ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 5678)
+ };
+ f_SBC_AP_send(ts_SBCAP_PWS_RESTART(cell_list, enb_id));
+}
+testcase TC_cell_failure_restart_idle_mme() runs on test_CT {
+ f_init(num_bsc := 0, num_mme := 1);
+ g_pars_MME[0].start_fn := refers(f_mme_TC_cell_failure_restart_idle_mme);
+ f_start();
+ f_shutdown_helper();
+}
+
+/* Test cell actively broadcasting a message in BSC going unavailable for
+ broadcasting and going available again. The CBC should reload the announced
+ cell with the active messages. See 3GPP TS 48.049 7.8 */
+private function f_bsc_TC_cell_failure_restart_active_bsc() runs on BSC_ConnHdlr {
+ var template (value) CBSP_FailureListItems fail_list := {
+ CBSP_FailureListItem_CGI(g_pars.cell_list_success.cIl_CGI[0], CBSP_CAUSE_CB_NOT_OPERATIONAL)
+ };
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list := ts_BSSMAP_CIL_CGI({
+ g_pars.cell_list_success.cIl_CGI[0]
+ });
+
+ /* Guide cell into active broadcast msg state: */
+ f_cbsp_handle_write(g_pars.exp_cbs_msg, 0, g_pars.cell_list_success);
+
+ /* BSC reports the cell is down */
+ f_cbsp_send(ts_CBSP_FAILURE(fail_list, CBSP_BC_MSGT_CBS));
+ f_cbsp_send(ts_CBSP_FAILURE(fail_list, CBSP_BC_MSGT_EMERG));
+ f_sleep(1.0);
+
+ /* BSC reports the cell is up again */
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST));
+ f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_EMERG, CBSP_RI_DATA_LOST));
+
+/* TODO: OS#5641
+ * The BSC informs the CBC by sending the RESTART message (see figure 7.8.2.1)
+ * containing the Cell List IE identifying the cell(s) being in CBS message
+ * operational state or in emergency message operational state and the Recovery
+ * Indication IE, indicating whether the broadcast information data is lost or
+ * not in the BSC.
+ * The RESTART message is sent once per broadcast message type
+ * as indicated by the Broadcast Message Type IE.
+ */
+ f_bsc_create_and_delete();
+}
+testcase TC_cell_failure_restart_active_bsc() runs on test_CT {
+ f_init(num_bsc := 1);
+ var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
+ var template (value) CBS_Message msg := t_CBSmsg(43, 16752);
+
+ cell_list_success := ts_BSSMAP_CIL_CGI({
+ ts_BSSMAP_CI_CGI('901'H, '70'H, 23, 42)
+ });
+ g_pars_BSC[0].start_fn := refers(f_bsc_TC_cell_failure_restart_active_bsc);
+ g_pars_BSC[0].exp_cbs_msg := valueof(msg);
+ g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
+ f_start();
+
+ var EcbeCbcMessage ecbe := f_cbs2ecbe(valueof(msg), "TTCN-3");
+ f_ecbe_tx_post_cbs(ecbe);
+ f_ecbe_rx_resp(201);
+
+ f_shutdown_helper();
+}
+
+/* Test cell actively broadcasting a message in MME going unavailable for
+ broadcasting and going available again. The CBC should reload the announced
+ cell with the active messages. See 3GPP TS 29.168 4.3.3E.2 */
+private function f_mme_TC_cell_failure_restart_active_mme() runs on MME_ConnHdlr {
+ var template (value) Global_ENB_ID enb_id := ts_Global_ENB_ID_MACRO(f_enc_mcc_mnc('901'H, '70'H), 90);
+ var template (value) Failed_Cell_List fail_list := {
+ g_pars.bcast_cell_id_list[0].eCGI
+ }
+ var template (value) Restarted_Cell_List cell_list := {
+ g_pars.bcast_cell_id_list[0].eCGI
+ };
+ /* Guide cell into active broadcast msg state: */
+ f_sbcap_handle_write_replace_warn_req(g_pars.exp_cbs_msg, 0);
+ if (ispresent(g_pars.write_replace_warning_ind_cause) and
+ ispresent(g_pars.bcast_cell_id_list)) {
+ f_sbcap_tx_write_replace_warn_ind(0, g_pars.exp_cbs_msg,
+ g_pars.write_replace_warning_ind_cause,
+ g_pars.bcast_cell_id_list)
+ }
+
+ /* MME reports the cell is down */
+ f_SBC_AP_send(ts_SBCAP_PWS_FAILURE(fail_list, enb_id));
+
+ f_sleep(1.0);
+
+ /* MME reports the cell is up again */
+ f_SBC_AP_send(ts_SBCAP_PWS_RESTART(cell_list, enb_id));
+
+/* TODO: OS#5641
+ * The CBC shall reload the warning message data (with the same Message
+ * Identifier and Serial Number) to the (H)eNB by initiating Write Replace
+ * Warning procedure(s) as specified in clause 4.3.3.2 with the following
+ * additions:
+ * - the CBC should set the Warning Area List IE in the Write-Replace
+ * Warning Request message to the identities of the cell(s) received in the
+ * Restarted-Cell-List which are relevant to the warning message data being
+ * reloaded;
+ * - the CBC shall copy the Global eNB ID into the Write-Replace
+ * Warning Request message; and
+ * - the CBC may update the Number of Broadcast Requested, if necessary.
+ */
+ f_mme_create_and_delete();
+}
+testcase TC_cell_failure_restart_active_mme() runs on test_CT {
+ var template (value) CellId_Broadcast_List bcast_cell_id_li;
+ var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
+
+ f_init(num_bsc := 0, num_mme := 1);
+
+ bcast_cell_id_li := {
+ ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234))
+ };
+ g_pars_MME[0].start_fn := refers(f_mme_TC_cell_failure_restart_active_mme);
+ g_pars_MME[0].exp_cbs_msg := valueof(msg);
+ g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
+ g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
+ f_start();
+
+ var EcbeCbcMessage ecbe := f_cbs2ecbe(valueof(msg), "TTCN-3");
+ f_ecbe_tx_post_cbs(ecbe);
+ f_ecbe_rx_resp(201);
+
+ f_shutdown_helper();
+}
+
+control {
+ execute( TC_rx_keepalive() );
+ execute( TC_rx_keepalive_timeout() );
+ execute( TC_ecbe_create_delete_cgi() );
+ execute( TC_ecbe_create_delete_lac_ci() );
+ execute( TC_ecbe_create_delete_lac() );
+ execute( TC_ecbe_create_delete_ci() );
+ execute( TC_ecbe_create_delete_lai() );
+ execute( TC_ecbe_create_delete_mme_indication() );
+ execute( TC_ecbe_create_delete_mme_unknown_tai() );
+ execute( TC_ecbe_create_delete_bsc_and_mme() );
+ execute( TC_ecbe_create_delete_bsc_server() );
+ execute( TC_ecbe_create_delete_mme_server() );
+ execute( TC_concurrent_cbs_msg_mme() );
+
+ execute( TC_ecbe_create_delete_etws_bsc() );
+ execute( TC_ecbe_create_delete_etws_mme() );
+
+ execute( TC_create_nack_bsc() );
+ execute( TC_create_nack_mme() );
+
+ execute( TC_cell_failure_restart_idle_bsc() );
+ execute( TC_cell_failure_restart_idle_mme() );
+
+ execute( TC_cell_failure_restart_active_bsc() );
+ execute( TC_cell_failure_restart_active_mme() );
+}
+
+}
diff --git a/cbc/CBS_Message.ttcn b/cbc/CBS_Message.ttcn
new file mode 100644
index 00000000..faaa4032
--- /dev/null
+++ b/cbc/CBS_Message.ttcn
@@ -0,0 +1,50 @@
+/* ECBE (REST) interface client of osmo-cbc test suite in TTCN-3
+ * (C) 2022 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 CBS_Message {
+
+import from Osmocom_Types all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+
+import from CBSP_Types all;
+
+/* Messages used for coordination between handlers and test_CT: */
+const charstring COORD_MSG_CONNECTED := "COORD_MSG_CONNECTED";
+
+
+type record CBS_Message {
+ uint16_t msg_id,
+ uint16_t ser_nr,
+ uint16_t old_ser_nr optional,
+ BSSMAP_FIELD_CellIdentificationList cell_list,
+ uint8_t channel_ind optional,
+ CBSP_Category category,
+ uint16_t rep_period,
+ uint16_t num_bcast_req,
+ uint8_t dcs,
+ CBS_MessageContents content
+};
+type record CBS_MessageContent {
+ octetstring payload,
+ uint8_t user_len
+};
+type record of CBS_MessageContent CBS_MessageContents;
+
+function msg_id_is_etws(uint16_t msg_id) return boolean
+{
+ if (msg_id >= 4352 and msg_id <= 4359) {
+ return true;
+ }
+ return false;
+}
+
+}
diff --git a/cbc/ECBE_Components.ttcn b/cbc/ECBE_Components.ttcn
new file mode 100644
index 00000000..996b17d8
--- /dev/null
+++ b/cbc/ECBE_Components.ttcn
@@ -0,0 +1,139 @@
+/* ECBE (REST) interface client of osmo-cbc test suite in TTCN-3
+ * (C) 2022 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 ECBE_Components {
+
+import from Osmocom_Types all;
+
+import from HTTP_Adapter all;
+import from HTTPmsg_Types all;
+import from ECBE_Types all;
+
+import from CBSP_Types all;
+
+import from CBS_Message all;
+
+private function f_cbs2ecbe_category(CBSP_Category cat_in) return EcbeCategory
+{
+ select (cat_in) {
+ case (CBSP_CATEG_HIGH_PRIO) { return high_priority; }
+ case (CBSP_CATEG_BACKGROUND) { return background; }
+ case (CBSP_CATEG_NORMAL) { return normal; }
+ case else { mtc.stop }
+ }
+}
+
+private function f_cbs2ecbe_page(CBS_MessageContent inp) return EcbePage
+{
+ return hex2str(oct2hex(inp.payload));
+}
+
+private function f_cbs2ecbe_etws(CBS_Message inp, charstring cbe_name) return EcbeCbcMessage
+{
+ var EcbeWarningTypeDecoded warn_type;
+ int2enum(inp.msg_id - 4352, warn_type);
+
+ var EcbeCbcMessage ret := {
+ cbe_name := cbe_name,
+ category := f_cbs2ecbe_category(inp.category),
+ repetition_period := inp.rep_period,
+ num_of_bcast := inp.num_bcast_req,
+ scope := { scope_plmn := {} },
+ smscb_message := {
+ serial_nr := {
+ serial_nr_encoded := inp.ser_nr
+ },
+ message_id := inp.msg_id,
+ payload := {
+ payload_etws := {
+ warning_type := {
+ warning_type_decoded := warn_type
+ },
+ emergency_user_alert := true,
+ popup_on_display := true,
+ warning_sec_info := omit
+ }
+ }
+ }
+ };
+ return ret;
+}
+
+/* convert from CBS_Message to EcbeCbcMessage */
+function f_cbs2ecbe(CBS_Message inp, charstring cbe_name) return EcbeCbcMessage
+{
+ if (msg_id_is_etws(inp.msg_id)) {
+ return f_cbs2ecbe_etws(inp, cbe_name);
+ }
+
+ var EcbeCbcMessage ret := {
+ cbe_name := cbe_name,
+ category := f_cbs2ecbe_category(inp.category),
+ repetition_period := inp.rep_period,
+ num_of_bcast := inp.num_bcast_req,
+ scope := { scope_plmn := {} },
+ smscb_message := {
+ serial_nr := {
+ serial_nr_encoded := inp.ser_nr
+ },
+ message_id := inp.msg_id,
+ payload := {
+ payload_encoded := {
+ dcs := inp.dcs,
+ pages := { } /* appended below */
+ }
+ }
+ }
+ };
+ for (var integer i := 0; i < lengthof(inp.content); i := i+1) {
+ ret.smscb_message.payload.payload_encoded.pages :=
+ ret.smscb_message.payload.payload_encoded.pages & { f_cbs2ecbe_page(inp.content[i]) };
+ }
+ return ret;
+}
+
+/*********************************************************************************
+ * ECBE (REST) interface
+ *********************************************************************************/
+
+function f_ecbe_tx_post_cbs(EcbeCbcMessage cbc)
+runs on http_CT {
+ var charstring body := oct2char(enc_EcbeCbcMessage(cbc));
+ log("TX POST CBS: ", body);
+ var HTTPMessage http_resp;
+ f_http_tx_request(url := "/api/ecbe/v1/message", method := "POST", body := body);
+}
+
+function f_ecbe_rx_resp(template integer exp_sts := (200..299))
+runs on http_CT return HTTPResponse {
+ var HTTPMessage http_resp := f_http_rx_response(tr_HTTP_Resp(exp_sts), tout := 20.0);
+ return http_resp.response;
+}
+
+/* run a HTTP POST to add a new CBC message */
+function f_ecbe_post_cbs(EcbeCbcMessage cbc, template integer exp_sts := 201)
+runs on http_CT return HTTPResponse {
+ f_ecbe_tx_post_cbs(cbc);
+ return f_ecbe_rx_resp(exp_sts)
+}
+
+function f_ecbe_tx_delete_cbs(integer msg_id)
+runs on http_CT {
+ f_http_tx_request("/api/ecbe/v1/message/" & int2str(msg_id), method := "DELETE");
+}
+
+/* run a HTTP GET on specified URL expecting json in RSRES format as response */
+function f_ecbe_delete_cbs(integer msg_id, template integer exp_sts := 200)
+runs on http_CT return HTTPResponse {
+ f_ecbe_tx_delete_cbs(msg_id);
+ return f_ecbe_rx_resp(exp_sts);
+}
+
+}
diff --git a/cbc/ECBE_Types.ttcn b/cbc/ECBE_Types.ttcn
new file mode 100644
index 00000000..7c66fb96
--- /dev/null
+++ b/cbc/ECBE_Types.ttcn
@@ -0,0 +1,147 @@
+module ECBE_Types {
+
+/* Type definitions for the ECBE (External Cell Broadcast Entity) protocol of OsmoCBC */
+/* (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ */
+
+/***********************************************************************
+ * smscb.schema.json
+ ***********************************************************************/
+
+type charstring EcbeLanguageCode length(2);
+
+type integer EcbeMessageId (0..65535);
+
+type enumerated EcbeGeographicScope {
+ cell_wide_immediate,
+ plmn_wide,
+ lac_sac_tac_wide,
+ cell_wide
+};
+
+type integer EcbeMessageCode (0..1023);
+
+type integer EcbeUpdateNumber (0..15);
+
+type integer EcbeSerialNrEncoded (0..65535);
+
+type record EcbeSerialNrDecoded {
+ EcbeGeographicScope geo_scope,
+ EcbeMessageCode msg_code,
+ EcbeUpdateNumber update_nr
+};
+
+type union EcbeSerialNr {
+ EcbeSerialNrEncoded serial_nr_encoded,
+ EcbeSerialNrDecoded serial_nr_decoded
+};
+
+type integer EcbeDcsEncoded (0..255);
+
+type enumerated EcbeCharacterSet {
+ gsm,
+ eight_bit,
+ ucs2
+};
+
+type integer EcbeDcsClass (0..3);
+
+type record EcbePayloadDecoded {
+ EcbeCharacterSet character_set optional,
+ EcbeLanguageCode Language optional,
+ EcbeDcsClass dcs_class optional,
+ charstring data_utf8
+};
+
+type charstring EcbePage;
+type record of EcbePage EcbePages;
+
+type record EcbePayloadEncoded {
+ EcbeDcsEncoded dcs,
+ EcbePages pages
+};
+
+type integer EcbeWarningTypeEncoded (0..127);
+
+type enumerated EcbeWarningTypeDecoded {
+ earthquake,
+ tsunami,
+ earthquake_and_tsunami,
+ test,
+ other,
+ rfu
+};
+
+type union EcbeWarningType {
+ EcbeWarningTypeEncoded warning_type_encoded,
+ EcbeWarningTypeDecoded warning_type_decoded
+};
+
+type record EcbePayloadEtws {
+ EcbeWarningType warning_type,
+ boolean emergency_user_alert optional,
+ boolean popup_on_display optional,
+ charstring warning_sec_info optional
+};
+
+type union EcbePayload {
+ EcbePayloadEncoded payload_encoded,
+ EcbePayloadDecoded payload_decoded,
+ EcbePayloadEtws payload_etws
+};
+
+type record EcbeSmscbMessage {
+ EcbeSerialNr serial_nr,
+ EcbeMessageId message_id,
+ EcbePayload payload
+};
+
+external function enc_EcbeSmscbMessage(in EcbeSmscbMessage inp) return octetstring
+ with { extension "prototype(convert) encode(JSON)" }
+external function dec_EcbeSmscbMessage(in octetstring inp) return EcbeSmscbMessage
+ with { extension "prototype(convert) decode(JSON)" }
+
+/***********************************************************************
+ * cbc.schema.json
+ ***********************************************************************/
+
+type enumerated EcbeCategory {
+ normal,
+ high_priority,
+ background
+};
+
+type integer EcbeRepetitionPeriod (1..4095);
+
+type enumerated EcbeChannelIndicator {
+ basic,
+ extended
+};
+
+type integer EcbeWarningPeriodSec (0..3600);
+
+type integer EcbeNumberOfBroadcasts (0..65535);
+
+type record EcbeScopePlmn {
+};
+
+type union EcbeScope {
+ EcbeScopePlmn scope_plmn
+};
+
+type record EcbeCbcMessage {
+ charstring cbe_name optional,
+ EcbeCategory category optional,
+ EcbeRepetitionPeriod repetition_period optional,
+ EcbeNumberOfBroadcasts num_of_bcast optional,
+ EcbeScope scope,
+ EcbeSmscbMessage smscb_message
+};
+
+external function enc_EcbeCbcMessage(in EcbeCbcMessage inp) return octetstring
+ with { extension "prototype(convert) encode(JSON)" }
+external function dec_EcbeCbcMessage(in octetstring inp) return EcbeCbcMessage
+ with { extension "prototype(convert) decode(JSON)" }
+
+} with { encode "JSON" }
diff --git a/cbc/MME_ConnectionHandler.ttcn b/cbc/MME_ConnectionHandler.ttcn
new file mode 100644
index 00000000..4ab30c64
--- /dev/null
+++ b/cbc/MME_ConnectionHandler.ttcn
@@ -0,0 +1,146 @@
+/* MME (SBc-AP) Connection Handler of CBC test suite in TTCN-3
+ * (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 MME_ConnectionHandler {
+
+import from SBC_AP_IEs all;
+import from SBC_AP_Constants all;
+import from SBC_AP_PDU_Contents all;
+import from SBC_AP_PDU_Descriptions all;
+import from SBC_AP_Types all;
+import from SBC_AP_Templates all;
+import from SBC_AP_CodecPort all;
+import from SBC_AP_Adapter all;
+
+import from CBS_Message all;
+
+type function void_fn() runs on MME_ConnHdlr;
+
+/* Coordinate with test_CT: */
+type port MME_ConnHdlr_Coord_PT message {
+ inout charstring;
+} with { extension "internal" };
+
+/* this component represents a single subscriber connection */
+type component MME_ConnHdlr extends SBC_AP_Adapter_CT {
+ var MME_ConnHdlrPars g_pars;
+ port MME_ConnHdlr_Coord_PT COORD;
+}
+
+type record MME_ConnHdlrPars {
+ charstring mme_host,
+ integer mme_sbcap_port,
+ charstring cbc_host,
+ integer cbc_sbcap_port,
+ boolean sctp_is_client,
+ void_fn start_fn,
+ CBS_Message exp_cbs_msg optional,
+ SBC_AP_Cause write_replace_warning_req_cause,
+ SBC_AP_Cause write_replace_warning_ind_cause optional,
+ List_of_TAIs write_repl_unknown_TAIs optional,
+ CellId_Broadcast_List bcast_cell_id_list optional
+};
+
+function f_MME_ConnHdlr_main(charstring id, MME_ConnHdlrPars pars) runs on MME_ConnHdlr {
+ g_pars := pars;
+ if (g_pars.sctp_is_client) {
+ SBC_AP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_sbcap_port,
+ g_pars.mme_host, g_pars.mme_sbcap_port);
+ } else {
+ SBC_AP_Adapter.f_bind(g_pars.mme_host, g_pars.mme_sbcap_port);
+ SBC_AP_Adapter.f_wait_client_connect();
+ }
+ COORD.send(COORD_MSG_CONNECTED);
+ g_pars.start_fn.apply();
+}
+
+function f_sbcap_tx_write_replace_warn_resp(CBS_Message msg, integer idx := 0)
+runs on MME_ConnHdlr {
+ var template (value) SBC_AP_PDU tx;
+ if (ispresent(g_pars.write_repl_unknown_TAIs)) {
+ tx := ts_SBCAP_WRITE_WARNING_RESP_UNKNOWN_TAI(
+ int2bit(msg.msg_id, 16),
+ int2bit(msg.ser_nr, 16),
+ g_pars.write_replace_warning_req_cause,
+ g_pars.write_repl_unknown_TAIs);
+ } else {
+ tx := ts_SBCAP_WRITE_WARNING_RESP(int2bit(msg.msg_id, 16),
+ int2bit(msg.ser_nr, 16),
+ g_pars.write_replace_warning_req_cause);
+ }
+ f_SBC_AP_send(tx, idx);
+}
+
+function f_sbcap_tx_write_replace_warn_ind(integer idx := 0, CBS_Message msg,
+ SBC_AP_Cause cause,
+ template (value) CellId_Broadcast_List bcast_cell_id_li)
+runs on MME_ConnHdlr {
+ var template (value) SBC_AP_PDU tx;
+ tx := ts_SBCAP_WRITE_WARNING_IND(int2bit(msg.msg_id, 16),
+ int2bit(msg.ser_nr, 16),
+ cause, bcast_cell_id_li);
+ f_SBC_AP_send(tx, idx);
+}
+
+function f_sbcap_tx_stop_warn_resp(integer idx := 0, CBS_Message msg)
+runs on MME_ConnHdlr {
+ var template (value) SBC_AP_PDU tx;
+ tx := ts_SBCAP_STOP_WARNING_RESP(int2bit(msg.msg_id, 16),
+ int2bit(msg.ser_nr, 16));
+ f_SBC_AP_send(tx, idx);
+}
+
+/* handle a SBc-AP Write-Replace Request and respond to it with Response or FAILURE depending on arguments */
+function f_sbcap_handle_write_replace_warn_req(CBS_Message msg, integer idx := 0)
+runs on MME_ConnHdlr {
+ var template (present) SBC_AP_PDU rx_templ;
+ var SBC_AP_RecvFrom rf;
+ if (msg_id_is_etws(msg.msg_id)) {
+ rx_templ := tr_SBCAP_WRITE_WARNING_REQ_ETWS(
+ int2bit(msg.msg_id, 16), int2bit(msg.ser_nr, 16),
+ msg.rep_period, msg.num_bcast_req, hex2oct('018'H & int2hex(msg.msg_id - 4352, 1)));
+ } else {
+ rx_templ := tr_SBCAP_WRITE_WARNING_REQ_CBS(
+ int2bit(msg.msg_id, 16), int2bit(msg.ser_nr, 16),
+ msg.rep_period, msg.num_bcast_req);
+ }
+ alt {
+ [] SBC_AP[idx].receive(tr_SBC_AP_Recv(g_SBC_AP_conn_id[idx], rx_templ)) -> value rf {
+ log ("received expected req:", rf);
+ f_sbcap_tx_write_replace_warn_resp(msg, idx);
+ }
+ [] SBC_AP[idx].receive {
+ setverdict(fail, "Received unexpected SBc-AP in index ", idx);
+ }
+ }
+}
+
+/* handle a SBc-AP Stop-Warning-Request and respond to it with Response or FAILURE depending on arguments */
+function f_sbcap_handle_stop_warn_req(integer idx := 0, CBS_Message msg)
+runs on MME_ConnHdlr {
+ var template (present) SBC_AP_PDU rx_templ;
+ var SBC_AP_RecvFrom rf;
+
+ rx_templ := tr_SBCAP_STOP_WARNING(int2bit(msg.msg_id, 16),
+ int2bit(msg.ser_nr, 16));
+ alt {
+ [] SBC_AP[idx].receive(tr_SBC_AP_Recv(g_SBC_AP_conn_id[idx], rx_templ)) -> value rf {
+ log ("received expected req:", rf);
+ f_sbcap_tx_stop_warn_resp(idx, msg);
+ }
+ [] SBC_AP[idx].receive {
+ setverdict(fail, "Received unexpected SBc-AP in index ", idx);
+ }
+ }
+}
+
+}
diff --git a/cbc/expected-results.xml b/cbc/expected-results.xml
new file mode 100644
index 00000000..72acd7c0
--- /dev/null
+++ b/cbc/expected-results.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<testsuite name='CBC_Tests' tests='0' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='CBC_Tests' name='TC_rx_keepalive' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_rx_keepalive_timeout' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_cgi' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_lac_ci' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_lac' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_ci' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_lai' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_mme_indication' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_mme_unknown_tai' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_bsc_and_mme' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_bsc_server' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_mme_server' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_concurrent_cbs_msg_mme' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_etws_bsc' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_ecbe_create_delete_etws_mme' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_create_nack_bsc' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_create_nack_mme' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_cell_failure_restart_idle_bsc' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_cell_failure_restart_idle_mme' time='MASKED'/>
+ <testcase classname='CBC_Tests' name='TC_cell_failure_restart_active_bsc' time='MASKED'>
+ <failure type='fail-verdict'>Tguard timeout
+ CBC_Tests.ttcn:MASKED TC_cell_failure_restart_active_bsc testcase
+ </failure>
+ </testcase>
+ <testcase classname='CBC_Tests' name='TC_cell_failure_restart_active_mme' time='MASKED'>
+ <failure type='fail-verdict'>Tguard timeout
+ CBC_Tests.ttcn:MASKED TC_cell_failure_restart_active_mme testcase
+ </failure>
+ </testcase>
+</testsuite>
diff --git a/cbc/gen_links.sh b/cbc/gen_links.sh
new file mode 100755
index 00000000..3bb9e77b
--- /dev/null
+++ b/cbc/gen_links.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit 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.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.BSSMAP/src
+FILES="BSSAP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library/sabp
+FILES="SABP_CommonDataTypes.asn SABP_Constants.asn SABP_Containers.asn SABP_IEs.asn SABP_PDU_Contents.asn SABP_PDU_Descriptions.asn SABP_Types.ttcn SABP_EncDec.cc SABP_Templates.ttcn "
+FILES+="SABP_CodecPort.ttcn SABP_CodecPort_CtrlFunct.ttcn SABP_CodecPort_CtrlFunctDef.cc SABP_Adapter.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library/sbcap
+FILES="SBC_AP_CommonDataTypes.asn SBC_AP_Constants.asn SBC_AP_Containers.asn SBC_AP_IEs.asn SBC_AP_PDU_Contents.asn SBC_AP_PDU_Descriptions.asn "
+FILES+="SBC_AP_Types.ttcn SBC_AP_EncDec.cc SBC_AP_Templates.ttcn SBC_AP_CodecPort.ttcn SBC_AP_CodecPort_CtrlFunct.ttcn SBC_AP_CodecPort_CtrlFunctDef.cc SBC_AP_Adapter.ttcn "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Abstract_Socket/src
+FILES="Abstract_Socket.cc Abstract_Socket.hh "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.HTTPmsg/src
+FILES="HTTPmsg_MessageLen.ttcn HTTPmsg_MessageLen_Function.cc HTTPmsg_PT.cc HTTPmsg_PT.hh HTTPmsg_PortType.ttcn HTTPmsg_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.JSON_v07_2006/src
+FILES="JSON_EncDec.cc JSON_Types.ttcn "
+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 "
+FILES+="HTTP_Adapter.ttcn "
+FILES+="BSSMAP_Templates.ttcn "
+FILES+="CBSP_Types.ttcn CBSP_Templates.ttcn "
+FILES+="CBSP_CodecPort.ttcn CBSP_CodecPort_CtrlFunct.ttcn CBSP_CodecPort_CtrlFunctdef.cc CBSP_Adapter.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/cbc/regen_makefile.sh b/cbc/regen_makefile.sh
new file mode 100755
index 00000000..96900b3c
--- /dev/null
+++ b/cbc/regen_makefile.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+NAME=CBC_Tests
+
+FILES="
+ *.asn
+ *.ttcn
+ Abstract_Socket.cc
+ CBSP_CodecPort_CtrlFunctdef.cc
+ HTTPmsg_MessageLen_Function.cc
+ HTTPmsg_PT.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ JSON_EncDec.cc
+ Native_FunctionDefs.cc
+ SABP_CodecPort_CtrlFunctDef.cc
+ SABP_EncDec.cc
+ SBC_AP_CodecPort_CtrlFunctDef.cc
+ SBC_AP_EncDec.cc
+ SCTPasp_PT.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile
diff --git a/ccid/CCID_Tests.ttcn b/ccid/CCID_Tests.ttcn
index f7423cdf..e650f375 100644
--- a/ccid/CCID_Tests.ttcn
+++ b/ccid/CCID_Tests.ttcn
@@ -29,13 +29,6 @@ type component Test_CT {
var Slot_CT vc_SLOT[NR_SLOTS];
};
-/* per-slot test component; manages one slot */
-type component Slot_CT {
- var uint8_t g_slot_nr;
- port CCID_SLOT_PT CCID;
- timer g_Tguard := 120.0;
-};
-
/* maximum number of slots we are supporting in the test suite */
private const integer NR_SLOTS := 16;
@@ -96,25 +89,6 @@ private template (value) CCID_ProtocolData ts_ProtoDataT0(ISO7816_Fi fi, ISO7816
type function void_fn() runs on Slot_CT;
-/* altstep running on the per-slot test component */
-private altstep as_Tguard() runs on Slot_CT {
- [] g_Tguard.timeout {
- Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
- }
-}
-
-private altstep as_ccid_any() runs on Slot_CT {
- var CCID_PDU pdu;
- [] CCID.receive(CCID_PDU:?) -> value pdu {
- setverdict(fail, "Received unexpected CCID ", pdu);
- self.stop;
- }
- [] CCID.receive {
- setverdict(fail, "Received unexpected non-CCID");
- self.stop;
- }
-}
-
/* first function inside Slot_CT; wait for CCID_EVENT_UP + call testcase-specific function */
private function f_handler_init(void_fn fn, integer slot_nr) runs on Slot_CT {
g_slot_nr := slot_nr;
@@ -163,119 +137,6 @@ private function f_init() runs on Test_CT {
}
-/* transceive a CCID command (send 'tx' on OUT; expect 'rx' on IN) */
-private function f_ccid_xceive(template (value) CCID_PDU tx, template (present) CCID_PDU exp_rx)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- tx.hdr.bSlot := g_slot_nr;
- exp_rx.hdr.bSlot := g_slot_nr;
-
- CCID.send(tx);
- alt {
- [] CCID.receive(exp_rx) -> value pdu {
- return pdu;
- }
- [] as_ccid_any();
- }
- return pdu;
-}
-
-private template (present) CCID_Header_IN tr_inact :=
- tr_CCID_HeaderIN_OK(icc_status := (CCID_ICC_STATUS_PRES_INACT, CCID_ICC_STATUS_NO_ICC));
-
-private template (present) CCID_Header_IN tr_act :=
- tr_CCID_HeaderIN_OK(icc_status := CCID_ICC_STATUS_PRES_ACT);
-
-/* Send IccPowerOn on OUT; expect DataBlock in retunr */
-private function f_ccid_power_on(CCID_PowerSelect psel := CCID_PWRSEL_AUTO,
- template (present) CCID_Header_IN hdr_in := tr_act)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_IccPowerOn(g_slot_nr, psel),
- tr_CCID_DataBlock(g_slot_nr, hdr_in := hdr_in) );
- return pdu;
-}
-
-/* Send IccPowerOn on OUT; expect SlotStatus in return */
-private function f_ccid_power_off(template (present) CCID_Header_IN hdr_in := tr_inact)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_IccPowerOff(g_slot_nr),
- tr_CCID_SlotStatus(slot := g_slot_nr, hdr_in := hdr_in) );
- return pdu;
-}
-
-/* Send IccClockCommand on OUT; expect SlotStatus in return */
-private function f_ccid_clock_cmd(CCID_ClockCommand cmd,
- template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_ClockCommand(g_slot_nr, cmd),
- tr_CCID_SlotStatus(slot := g_slot_nr, hdr_in := hdr_in));
- return pdu;
-}
-
-/* Send XfrBlock on OUT; expect DataBlock in return */
-private function f_ccid_xfr(octetstring tx, template octetstring rx) runs on Slot_CT return octetstring {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_XfrBlock(g_slot_nr, tx, 0),
- tr_CCID_DataBlock(g_slot_nr, ?, ?, rx) );
- return pdu.u.DataBlock.abData;
-}
-
-/* Send SetParameters on OUT; expect Parameters on IN */
-private function f_ccid_set_par(template (value) CCID_ProtocolData par,
- template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_SetParameters(g_slot_nr, par),
- tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
- return pdu;
-}
-
-/* Send GetParameters on OUT; expect Parameters on IN */
-private function f_ccid_get_par(template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_GetParameters(g_slot_nr),
- tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
- return pdu;
-}
-
-/* Send ResetParameters on OUT; expect Parameters on IN */
-private function f_ccid_reset_par(template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- /* [at least] Omnikey seems to have failed to follow the CCID spec here :/ */
- if (mp_quirk_resetpar_returns_slotsts) {
- pdu := f_ccid_xceive(ts_CCID_ResetParameters(g_slot_nr),
- tr_CCID_SlotStatus(g_slot_nr, hdr_in := hdr_in));
- } else {
- pdu := f_ccid_xceive(ts_CCID_ResetParameters(g_slot_nr),
- tr_CCID_Parameters(g_slot_nr, hdr_in := hdr_in));
- }
- return pdu;
-}
-
-/* Send Escape on OUT; expect Escape on IN */
-private function f_ccid_escape(template (value) octetstring data,
- template (present) CCID_Header_IN hdr_in := tr_CCID_HeaderIN_OK)
-runs on Slot_CT return CCID_PDU {
- var CCID_PDU pdu;
-
- pdu := f_ccid_xceive(ts_CCID_Escape(g_slot_nr, data),
- tr_CCID_EscapeIN(g_slot_nr, hdr_in := hdr_in));
- return pdu;
-}
-
/***********************************************************************
* Test behavior regarding valid situations
diff --git a/ccid/gen_links.sh b/ccid/gen_links.sh
index e53954b6..593f6248 100755
--- a/ccid/gen_links.sh
+++ b/ccid/gen_links.sh
@@ -4,9 +4,9 @@ BASEDIR=../deps
. ../gen_links.sh.inc
-#DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
-#FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
-#gen_links $DIR $FILES
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCConversion_Functions.ttcn TCCConversion.cc"
+gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.USB/src
FILES="USB_PT.cc USB_PT.hh USB_PortType.ttcn USB_PortTypes.ttcn USB_Templates.ttcn USB_Types.ttcn USB_Component.ttcn "
diff --git a/ccid/regen_makefile.sh b/ccid/regen_makefile.sh
index 215d9c69..c91ac12f 100755
--- a/ccid/regen_makefile.sh
+++ b/ccid/regen_makefile.sh
@@ -1,8 +1,18 @@
#!/bin/sh
-FILES="*.ttcn USB_PT.cc Native_FunctionDefs.cc "
+NAME=CCID_Tests
-../regen-makefile.sh CCID_Tests.ttcn $FILES
+FILES="
+ *.ttcn
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ USB_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
#sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lusb/' Makefile
sed -i -e '/^LINUX_LIBS/ s/$/ `pkg-config --libs libusb-1.0`/' Makefile
diff --git a/deps/Makefile b/deps/Makefile
index b808dcc4..11ff460b 100644
--- a/deps/Makefile
+++ b/deps/Makefile
@@ -13,24 +13,42 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ECLIPSEGITHUB:=https://github.com/eclipse
-ECLIPSEGIT2:=https://git.eclipse.org/r/titan
+ECLIPSEGITLAB:=https://gitlab.eclipse.org/eclipse/titan
OSMOGITHUB:=https://github.com/osmocom
-OSMOGIT:=git://git.osmocom.org
+OSMOGERRIT:=https://gerrit.osmocom.org
+OSMOGITEA:=https://gitea.osmocom.org/ttcn3
-ECLIPSEGITHUB_REPOS= titan.Libraries.TCCUsefulFunctions \
+ECLIPSEGITLAB_REPOS= titan.Libraries.TCCUsefulFunctions \
+ titan.ProtocolEmulations.M3UA \
+ titan.ProtocolModules.BSSAPP_v7.3.0 \
+ titan.ProtocolModules.DIAMETER_ProtocolModule_Generator \
titan.ProtocolModules.DNS \
+ titan.ProtocolModules.GRE \
+ titan.ProtocolModules.GTP_v13.5.0 \
+ titan.ProtocolModules.GTPv2_v13.7.0 \
titan.ProtocolModules.ICMP \
titan.ProtocolModules.ICMPv6 \
titan.ProtocolModules.IP \
+ titan.ProtocolModules.ISUP_Q.762 \
titan.ProtocolModules.JSON_v07_2006 \
titan.ProtocolModules.L2TP \
+ titan.ProtocolModules.LLC_v7.1.0 \
titan.ProtocolModules.M3UA \
+ titan.ProtocolModules.MobileL3_v13.4.0 \
titan.ProtocolModules.SMPP \
titan.ProtocolModules.TCP \
titan.ProtocolModules.UDP \
titan.ProtocolModules.RTP \
- titan.ProtocolModules.DIAMETER_ProtocolModule_Generator \
+ titan.ProtocolModules.M2PA \
+ titan.ProtocolModules.ROSE \
+ titan.ProtocolModules.SCTP \
+ titan.ProtocolModules.SDP \
+ titan.ProtocolModules.SUA \
+ titan.ProtocolModules.NAS_EPS_15.2.0.1 \
+ 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 \
@@ -39,53 +57,42 @@ ECLIPSEGITHUB_REPOS= titan.Libraries.TCCUsefulFunctions \
titan.TestPorts.PCAPasp \
titan.TestPorts.PIPEasp \
titan.TestPorts.SIPmsg \
+ titan.TestPorts.TELNETasp \
titan.TestPorts.TCPasp \
+ titan.TestPorts.UDPasp \
titan.TestPorts.UNIX_DOMAIN_SOCKETasp
-ECLIPSEGIT2_REPOS= titan.ProtocolModules.GRE \
- titan.ProtocolModules.M2PA \
- titan.ProtocolModules.ROSE \
- titan.ProtocolModules.SCTP \
- titan.ProtocolModules.SUA \
- titan.ProtocolModules.SDP \
- titan.ProtocolModules.BSSAPP_v7.3.0 \
- titan.ProtocolModules.BSSGP_v13.0.0 \
- titan.ProtocolModules.GTP_v13.5.0 \
- titan.ProtocolModules.GTPv2_v13.7.0 \
- titan.ProtocolModules.ISUP_Q.762 \
- titan.ProtocolModules.LLC_v7.1.0 \
- titan.ProtocolModules.MobileL3_v13.4.0 \
- titan.ProtocolModules.NAS_EPS_15.2.0.1 \
- titan.ProtocolModules.NS_v7.3.0 \
- titan.ProtocolModules.SGsAP_13.2.0 \
- titan.ProtocolModules.SNDCP_v7.0.0
-
OSMOGITHUB_REPOS= titan.TestPorts.SCTPasp \
titan.TestPorts.MTP3asp \
- titan.TestPorts.UDPasp \
- titan.TestPorts.TELNETasp \
- titan.ProtocolEmulations.M3UA \
- titan.ProtocolEmulations.SCCP
+ titan.ProtocolEmulations.SCCP \
+ titan.ProtocolModules.BSSGP_v13.0.0
+
+OSMOGERRIT_REPOS= osmo-uecups
-OSMOGIT_REPOS= titan.ProtocolModules.MAP \
- titan.ProtocolModules.BSSMAP \
+OSMOGITEA_REPOS= titan.ProtocolModules.BSSMAP \
+ titan.ProtocolModules.MAP \
titan.TestPorts.USB \
- osmo-uecups
+ titan.TestPorts.AF_PACKET
-ALL_REPOS=$(ECLIPSEGITHUB_REPOS) $(ECLIPSEGIT2_REPOS) $(OSMOGITHUB_REPOS) $(OSMOGIT_REPOS)
+ALL_REPOS= $(ECLIPSEGITLAB_REPOS) \
+ $(OSMOGITHUB_REPOS) \
+ $(OSMOGERRIT_REPOS) \
+ $(OSMOGITEA_REPOS) \
+ $(FORKEDGITLAB_REPOS)
# Tag names from 'git-describe --tags'; if not available, a commit hash may be used instead.
-# In order to keep local changes in the repository of a dependency, set its commit to the
-# name of a local branch here (e.g. 'master').
+# Do not put references to branches here, except for local testing: this breaks the caching
+# logic of docker containers, which only invalidate their cached ttcn3 dependencies if this
+# file changed.
titan.Libraries.TCCUsefulFunctions_commit= R.35.B-6-gb3687da
titan.ProtocolEmulations.M3UA_commit= f086e78d74defa044d864f17adaad9433fedc961
-titan.ProtocolEmulations.SCCP_commit= R.7.A-9-g9e70fba
+titan.ProtocolEmulations.SCCP_commit= f8a44f2cdef44d0c3adf787ab3184c293a9a58be
titan.ProtocolModules.BSSAPP_v7.3.0_commit= R.2.A-4-g20cfaf8
-titan.ProtocolModules.BSSGP_v13.0.0_commit= R.2.A-6-gc447f28
-titan.ProtocolModules.BSSMAP_commit= master
+titan.ProtocolModules.BSSGP_v13.0.0_commit= e97d92a8b66bec399babea52f593771b76cb175a
+titan.ProtocolModules.BSSMAP_commit= 4acb6ab5f058477f0b90c2da182d52054e3614b0
titan.ProtocolModules.DNS_commit= R.7.B
titan.ProtocolModules.GRE_commit= R.2.A-5-g654c446
-titan.ProtocolModules.GTP_v13.5.0_commit= R.2.A-5-ge120ace
+titan.ProtocolModules.GTP_v13.5.0_commit= 6b769f985eb91bf5a4332f29faa4a043b23ce62e
titan.ProtocolModules.GTPv2_v13.7.0_commit= R.2.A-5-g85cb124
titan.ProtocolModules.ICMP_commit= e49d9fb9f7de637b4bf4803dc6b6e911a8661640
titan.ProtocolModules.ICMPv6_commit= 46f4d9b6e1e3c794294a92588401a81e4881dd27
@@ -97,7 +104,7 @@ titan.ProtocolModules.LLC_v7.1.0_commit= 09817f113255d7fb56f1d45d3dd629a093d9248
titan.ProtocolModules.MAP_commit= R.2.A-1-g79c6a3d
titan.ProtocolModules.M2PA_commit= R.2.A-5-ga75b589
titan.ProtocolModules.M3UA_commit= c496d298876fed55c2b730278b7ee77982555563
-titan.ProtocolModules.MobileL3_v13.4.0_commit= badbad680df216b3211260d56b14734eeb2c9028
+titan.ProtocolModules.MobileL3_v13.4.0_commit= b6602eb357673f097ea1a1d22edd568ecd239da1
titan.ProtocolModules.NAS_EPS_15.2.0.1_commit= R.1.A-2-g2ba853c
titan.ProtocolModules.NS_v7.3.0_commit= R.2.A-6-gf73f195
titan.ProtocolModules.RTP_commit= R.5.A-4-g83ee83a
@@ -111,22 +118,24 @@ titan.ProtocolModules.SNDCP_v7.0.0_commit= R.2.A-5-gd0f0ce6
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.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
titan.TestPorts.HTTPmsg_commit= R.9.B-4-g9a0dfde
-titan.TestPorts.IPL4asp_commit= R.30.E
+titan.TestPorts.IPL4asp_commit= R.30.E-7-g029bccb
titan.TestPorts.LANL2asp_commit= R.8.C-3-gb07c265
titan.TestPorts.MTP3asp_commit= 1cecdad6f3641a5f19b3833703bff6e5005eff11
titan.TestPorts.PCAPasp_commit= R.8.A-3-g9ad320f
titan.TestPorts.PIPEasp_commit= R.7.D-3-g8b01154
-titan.TestPorts.SCTPasp_commit= R.11.A-2-g2faa9cf
+titan.TestPorts.SCTPasp_commit= R.11.A-8-g2e911c3
titan.TestPorts.SIPmsg_commit= R.15.A-1-ge4f9dd0
titan.TestPorts.TCPasp_commit= R.9.A-5-g2c91bc6
-titan.TestPorts.TELNETasp_commit= R.9.A-5-g7a07a97
-titan.TestPorts.UDPasp_commit= c20d77a34f288dd70dd4aaa30e520778876e9336
-titan.TestPorts.UNIX_DOMAIN_SOCKETasp_commit= R.2.A-8-g7ec4fe0
-titan.TestPorts.USB_commit= master
-osmo-uecups_commit= master
+titan.TestPorts.TELNETasp_commit= 873fe539642542cd9a901c208f1ec11c6d2f5387
+titan.TestPorts.UDPasp_commit= 54176e95850654e5e8b0ffa2f1b5f35c412b949c
+titan.TestPorts.UNIX_DOMAIN_SOCKETasp_commit= R.2.A-13-gd34ab71
+titan.TestPorts.USB_commit= a9470fdc99c82fbf988f4508c3161118c9106e28
+osmo-uecups_commit= 8362efef7c6fa341eb947a75786878e0685767b7
all: $(foreach dir,$(ALL_REPOS),$(dir)/update)
clean: $(foreach dir,$(ALL_REPOS),$(dir)/clean)
@@ -149,7 +158,15 @@ ifneq ($$($(1)_ORIGIN),$(2)/$(1))
cd $(1) && git remote set-url origin $(2)/$(1) && git fetch
endif
ifneq ($$($(1)_HEAD),$($(1)_commit))
- cd $(1) && git fetch && git checkout -q -f "$($(1)_commit)"
+ cd $(1) && \
+ git fetch && \
+ if git rev-parse "origin/$($(1)_commit)" 2>/dev/null; then \
+ set -x && \
+ git checkout -q -f "origin/$($(1)_commit)"; \
+ else \
+ set -x && \
+ git checkout -q -f "$($(1)_commit)"; \
+ fi
endif
endif
@@ -170,14 +187,17 @@ else
endif
endef
-$(foreach dir,$(ECLIPSEGITHUB_REPOS), \
- $(eval $(call GIT_template,$(dir),$(ECLIPSEGITHUB))))
-
-$(foreach dir,$(ECLIPSEGIT2_REPOS), \
- $(eval $(call GIT_template,$(dir),$(ECLIPSEGIT2))))
+$(foreach dir,$(ECLIPSEGITLAB_REPOS), \
+ $(eval $(call GIT_template,$(dir),$(ECLIPSEGITLAB))))
$(foreach dir,$(OSMOGITHUB_REPOS), \
$(eval $(call GIT_template,$(dir),$(OSMOGITHUB))))
-$(foreach dir,$(OSMOGIT_REPOS), \
- $(eval $(call GIT_template,$(dir),$(OSMOGIT))))
+$(foreach dir,$(OSMOGERRIT_REPOS), \
+ $(eval $(call GIT_template,$(dir),$(OSMOGERRIT))))
+
+$(foreach dir,$(OSMOGITEA_REPOS), \
+ $(eval $(call GIT_template,$(dir),$(OSMOGITEA))))
+
+$(foreach dir,$(FORKEDGITLAB_REPOS), \
+ $(eval $(call GIT_template,$(dir),$(FORKEDGITLAB))))
diff --git a/dia2gsup/DIA2GSUP_Tests.cfg b/dia2gsup/DIA2GSUP_Tests.cfg
new file mode 100644
index 00000000..0c166fe8
--- /dev/null
+++ b/dia2gsup/DIA2GSUP_Tests.cfg
@@ -0,0 +1,19 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./DIA2GSUP_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+DIA2GSUP_Tests.control
diff --git a/dia2gsup/DIA2GSUP_Tests.default b/dia2gsup/DIA2GSUP_Tests.default
new file mode 100644
index 00000000..95b42e94
--- /dev/null
+++ b/dia2gsup/DIA2GSUP_Tests.default
@@ -0,0 +1,8 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING; // | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[EXECUTE]
diff --git a/dia2gsup/DIA2GSUP_Tests.ttcn b/dia2gsup/DIA2GSUP_Tests.ttcn
new file mode 100644
index 00000000..6d1828f4
--- /dev/null
+++ b/dia2gsup/DIA2GSUP_Tests.ttcn
@@ -0,0 +1,362 @@
+module DIA2GSUP_Tests {
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from L3_Common all;
+
+import from IPA_Emulation all;
+import from GSUP_Types all;
+import from GSUP_Templates all;
+import from GSUP_Emulation all;
+
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+import from DIAMETER_Emulation all;
+
+type component MTC_CT {
+ var DIAMETER_Emulation_CT vc_DIAMETER;
+ port DIAMETER_PT DIAMETER_UNIT;
+ port DIAMETEREM_PROC_PT DIAMETER_PROC;
+
+ var GSUP_Emulation_CT vc_GSUP;
+ var IPA_Emulation_CT vc_GSUP_IPA;
+ port IPA_CTRL_PT GSUP_IPA_EVENT;
+
+ timer g_Tguard;
+};
+
+type component D2G_ConnHdlr extends DIAMETER_ConnHdlr, GSUP_ConnHdlr {
+ var D2G_ConnHdlrPars g_pars;
+};
+
+type record D2G_ConnHdlrPars {
+ hexstring imsi,
+ AuthVector vec optional
+};
+
+private function f_init_pars(integer imsi_suffix := 1)
+runs on MTC_CT return D2G_ConnHdlrPars {
+ var D2G_ConnHdlrPars pars := {
+ imsi := f_gen_imsi(imsi_suffix),
+ vec := f_gen_auth_vec_3g()
+ };
+ return pars;
+}
+
+
+modulepar {
+ /* our emulated GSUP HLR */
+ charstring mp_hlr_ip := "127.0.0.1";
+ integer mp_hlr_port := 4222;
+
+ /* our emulated MME */
+ charstring mp_s6_local_ip := "127.0.0.100";
+ integer mp_s6_local_port := 3868;
+
+ /* IUT behaving as HSS */
+ charstring mp_hss_ip := "127.0.0.4";
+ integer mp_hss_port := 3868;
+
+ charstring mp_diam_realm := "localdomain";
+}
+
+private altstep as_Tguard() runs on MTC_CT {
+ [] g_Tguard.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
+ }
+}
+
+private function f_init_gsup(charstring id) runs on MTC_CT {
+ id := id & "-GSUP";
+ var GsupOps ops := {
+ create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
+ };
+
+ vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
+ vc_GSUP := GSUP_Emulation_CT.create(id);
+
+ map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
+ connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
+ /* we use this hack to get events like ASP_IPA_EVENT_UP */
+ connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
+
+ vc_GSUP.start(GSUP_Emulation.main(ops, id));
+ vc_GSUP_IPA.start(IPA_Emulation.main_server(mp_hlr_ip, mp_hlr_port));
+
+ /* wait for incoming connection to GSUP port before proceeding */
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] GSUP_IPA_EVENT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
+ [] T.timeout {
+ setverdict(fail, "No connection to GSUP Port");
+ mtc.stop;
+ }
+ }
+}
+
+private type function void_fn(charstring id) runs on D2G_ConnHdlr;
+
+private function f_init_handler(void_fn fn, charstring id, D2G_ConnHdlrPars pars) runs on D2G_ConnHdlr {
+ g_pars := pars;
+
+ /* tell GSUP dispatcher to send this IMSI to us */
+ f_create_gsup_expect(hex2str(g_pars.imsi));
+
+ fn.apply(id);
+}
+
+private function f_start_handler(void_fn fn, D2G_ConnHdlrPars pars)
+runs on MTC_CT return D2G_ConnHdlr {
+ var D2G_ConnHdlr vc_conn;
+ var charstring id := testcasename();
+
+ vc_conn := D2G_ConnHdlr.create(id);
+
+ connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
+ connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
+
+ connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
+ connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);
+
+ DIAMETER_UNIT.receive(DiameterCapabilityExchgInd:?);
+
+ vc_conn.start(f_init_handler(fn, id, pars));
+ return vc_conn;
+}
+
+private function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
+runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
+ DIAMETER_UNIT.send(msg);
+ return omit;
+}
+
+private function f_init_diameter(charstring id) runs on MTC_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 := {
+ remote_ip := mp_hss_ip,
+ remote_sctp_port := mp_hss_port,
+ local_ip := mp_s6_local_ip,
+ local_sctp_port := mp_s6_local_port,
+ origin_host := "hss." & mp_diam_realm,
+ origin_realm := mp_diam_realm,
+ auth_app_id := omit,
+ vendor_app_id := c_DIAMETER_3GPP_S6_AID
+ };
+ vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
+ map(vc_DIAMETER:DIAMETER, system:DIAMETER_CODEC_PT);
+ connect(vc_DIAMETER:DIAMETER_UNIT, self:DIAMETER_UNIT);
+ connect(vc_DIAMETER:DIAMETER_PROC, self:DIAMETER_PROC);
+ vc_DIAMETER.start(DIAMETER_Emulation.main(ops, pars, id));
+}
+
+private function f_init(float t_guard := 40.0) runs on MTC_CT {
+
+ g_Tguard.start(t_guard);
+ activate(as_Tguard());
+
+ /* Sleep to allow the remote to forget the connection (see diameter connect timer). */
+ f_sleep(1.0);
+ f_init_gsup(testcasename());
+ f_init_diameter(testcasename());
+}
+
+
+private function f_DIA_AI_success() runs on D2G_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var octetstring sess_id := char2oct("foobar");
+ var OCT3 vplmn := '00F110'O;
+
+ /* Unlike AIR, AIA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_diameter_expect_eteid(ete_id);
+
+ /* Send AIR to translator; expect it to show up on GSUP side */
+ DIAMETER.send(ts_DIA_AIR(g_pars.imsi, vplmn, sess_id, hbh_id := hbh_id, ete_id := ete_id));
+ GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
+
+ /* Send a positive response back to the translator; expect AIA */
+ var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
+ g_pars.vec.sres,
+ g_pars.vec.kc,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.res));
+ GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+
+ alt {
+ /* Unlike AIR, AIA contains no IMSI, hence it is received in DIAMETER_UNIT: */
+ [] DIAMETER.receive(tr_DIA_AIA) {
+ setverdict(pass);
+ }
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia));
+ }
+ }
+}
+
+private function f_TC_authinfo_normal(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_success();
+}
+
+testcase TC_authinfo_normal() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_normal), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_DIA_AI_gsup_error(integer gsup_cause, template (present) GenericAVP err_avp) runs on D2G_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var octetstring sess_id := char2oct("foobar");
+ var OCT3 vplmn := '00F110'O;
+
+ /* Unlike AIR, AIA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_diameter_expect_eteid(ete_id);
+
+ /* Send AIR to translator; expect it to show up on GSUP side */
+ DIAMETER.send(ts_DIA_AIR(g_pars.imsi, vplmn, sess_id, hbh_id := hbh_id, ete_id := ete_id));
+ GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
+
+ /* Send an error response back to the translator; expect AIA */
+ GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, gsup_cause));
+
+ alt {
+ /* Unlike AIR, AIA contains no IMSI, hence it is received in DIAMETER_UNIT: */
+ [] DIAMETER.receive(tr_DIA_AIA_ERR(err_avp)) {
+ setverdict(pass);
+ }
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia));
+ }
+ }
+}
+
+private function f_TC_authinfo_gsup_err_imsi_unknown(charstring id) runs on D2G_ConnHdlr {
+ var DIAMETER_ExperimentalResultcode res_code := DIAMETER_ERROR_USER_UNKNOWN;
+ f_DIA_AI_gsup_error(2, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(res_code), 4)));
+}
+testcase TC_authinfo_gsup_err_imsi_unknown() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_imsi_unknown), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_illegal_ms(charstring id) runs on D2G_ConnHdlr {
+ var DIAMETER_ExperimentalResultcode res_code := DIAMETER_ERROR_USER_UNKNOWN;
+ f_DIA_AI_gsup_error(3, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(res_code), 4)));
+}
+testcase TC_authinfo_gsup_err_illegal_ms() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_illegal_ms), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_plmn_not_allowed(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_gsup_error(11, tr_AVP_ResultCode(DIAMETER_UNABLE_TO_COMPLY));
+}
+testcase TC_authinfo_gsup_err_plmn_not_allowed() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_plmn_not_allowed), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_romaning_not_allowed(charstring id) runs on D2G_ConnHdlr {
+ var DIAMETER_ExperimentalResultcode res_code := DIAMETER_ERROR_ROAMING_NOT_ALLOWED;
+ f_DIA_AI_gsup_error(12, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(res_code), 4)));
+}
+testcase TC_authinfo_gsup_err_romaning_not_allowed() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_romaning_not_allowed), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_net_fail(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_gsup_error(17, tr_AVP_ResultCode(DIAMETER_UNABLE_TO_COMPLY));
+}
+testcase TC_authinfo_gsup_err_net_fail() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_net_fail), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_congestion(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_gsup_error(22, tr_AVP_ResultCode(DIAMETER_UNABLE_TO_COMPLY));
+}
+testcase TC_authinfo_gsup_err_congestion() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_congestion), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_auth_unacceptable(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_gsup_error(23, tr_AVP_ResultCode(DIAMETER_UNABLE_TO_COMPLY));
+}
+testcase TC_authinfo_gsup_err_auth_unacceptable() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_auth_unacceptable), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_gsup_err_proto_unspec(charstring id) runs on D2G_ConnHdlr {
+ f_DIA_AI_gsup_error(23, tr_AVP_ResultCode(DIAMETER_UNABLE_TO_COMPLY));
+}
+testcase TC_authinfo_gsup_err_proto_unspec() runs on MTC_CT {
+ var D2G_ConnHdlrPars pars := f_init_pars();
+ var D2G_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_gsup_err_proto_unspec), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+control {
+ execute ( TC_authinfo_normal() );
+ execute ( TC_authinfo_gsup_err_imsi_unknown() );
+ execute ( TC_authinfo_gsup_err_illegal_ms() );
+ execute ( TC_authinfo_gsup_err_plmn_not_allowed() );
+ execute ( TC_authinfo_gsup_err_romaning_not_allowed() );
+ execute ( TC_authinfo_gsup_err_net_fail() );
+ execute ( TC_authinfo_gsup_err_congestion() );
+ execute ( TC_authinfo_gsup_err_auth_unacceptable() );
+ execute ( TC_authinfo_gsup_err_proto_unspec() );
+}
+
+}
diff --git a/dia2gsup/gen_links.sh b/dia2gsup/gen_links.sh
new file mode 100755
index 00000000..d6537817
--- /dev/null
+++ b/dia2gsup/gen_links.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit 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.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src
+FILES="DIAMETER_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+#FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn "
+#FILES+="SS_DataTypes.asn SS_Errors.asn SS_Operations.asn SS_PDU_Defs.asn SS_Protocol.asn SS_Types.ttcn SS_EncDec.cc"
+FILES="MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn "
+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 "
+FILES+="Osmocom_CTRL_Types.ttcn "
+FILES+="L3_Common.ttcn "
+FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn "
+FILES+="DIAMETER_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn "
+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 "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/dia2gsup/regen_makefile.sh b/dia2gsup/regen_makefile.sh
new file mode 100755
index 00000000..22d8e06c
--- /dev/null
+++ b/dia2gsup/regen_makefile.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+NAME=DIA2GSUP_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ DIAMETER_EncDec.cc
+ DIAMETER_CodecPort_CtrlFunctDef.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_GSUP
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh DIA2GSUP_Tests.ttcn $FILES
diff --git a/doc/bsc_tests_aoip.dot b/doc/bsc_tests_aoip.dot
new file mode 100644
index 00000000..1457bdff
--- /dev/null
+++ b/doc/bsc_tests_aoip.dot
@@ -0,0 +1,81 @@
+digraph G {
+ rankdir = LR;
+ label = "MSC_Tests component hierarchy";
+
+ "MSC_ConnHdlr" [
+ shape = "record"
+ label = "<f0> MSC_ConnHdlr | <BSSAP> BSSAP | <BSSAP_PROC> BSSAP_PROC | <RSL> RSL | <RSL_PROC> RSL_PROC | <MGCP> MGCP | <MGCP_PROC> MGCP_PROC | <MGCP_MULTI> MGCP_MULTI | <BSSAP_LE> BSSAP_LE | <BSSAP_LE_PROC> BSSAP_LE_PROC | <STATSD_PROC> STATSD_PROC | <RAN> RAN | <BSCVTY> BSCVTY | <COORD> COORD | <MGCP_MSC_CLIENT> MGCP_MSC_CLIENT"
+ ];
+
+ "RAN_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RAN_Emulation_CT | <MGCP> MGCP | <CTRL> CTRL | <CTRL_CLIENT> CTRL_CLIENT | <CLIENT> CLIENT | <PROC> PROC | <BSSAP> BSSAP | <RANAP> RANAP"
+ ];
+ "RAN_Emulation_CT":BSSAP -> "SCCP_CT":SCCP_SP_PORT
+ "MSC_ConnHdlr":BSSAP -> "RAN_Emulation_CT":CLIENT
+ "MSC_ConnHdlr":BSSAP_PROC -> "RAN_Emulation_CT":PROC
+ "MSC_ConnHdlr":IPA_CTRL -> "IPA_Emulation_CT":IPA_CTRL_PORT
+
+ "RSL_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RSL_Emulation_CT | <CLIENT_PT> CLIENT_PT | <RSL_PROC> RSL_PROC | <CCHAN_PT> CCHAN_PT | <IPA_PT> IPA_PT"
+ ]
+ "RSL_Emulation_CT":IPA_PT -> "IPA_Emulation_CT":IPA_RSL_PORT
+ "MSC_ConnHdlr":RSL -> "RSL_Emulation_CT":CLIENT_PT
+ "MSC_ConnHdlr":RSL_PROC -> "RSL_Emulation_CT":RSL_PROC
+
+ "BSSAP_LE_Emulation_CT" [
+ shape = "record"
+ label = "<f0> BSSAP_LE_Emulation_CT | <CLIENT> CLIENT | <PROC> PROC | <BSSAP_LE> BSSAP_LE"
+ ]
+ "BSSAP_LE_Emulation_CT":BSSAP_LE -> "SCCP_CT":SCCP_SP_PORT
+ "MSC_ConnHdlr":BSSAP_LE -> "BSSAP_LE_Emulation_CT":CLIENT
+ "MSC_ConnHdlr":BSSAP_LE_PROC -> "BSSAP_LE_Emulation_CT":PROC
+
+ "SCCP_CT" [
+ shape = "record"
+ label = "<f0> SCCP_CT | <MTP3_SCCP_PORT> MTP3_SCCP_PORT | <SCCP_SP_PORT> SCCP_SP_PORT"
+ ];
+ "SCCP_CT":MTP3_SCCP_PORT -> "M3UA_CT":MTP3_SP_PORT
+
+ "M3UA_CT" [
+
+ shape = "record"
+ label = "<f0> M3UA_CT | <STCP_PORT> SCTP_PORT | <MTP3_SP_PORT> MTP3_SP_PORT"
+ ];
+ "M3UA_CT":SCTP_PORT -> "system":SCTP
+
+
+ "StatsD_Checker_CT" [
+ shape = "record"
+ label = "<f0> StatsD_Checker_CT | <STATSD_PROC> STATSD_PROC | <STATS> STATS | <STATSVTY> STATSVTY"
+ ]
+ "StatsD_Checker_CT":STATS -> "system":IPL4 [label="STATSD_CODEC_PT"]
+ "StatsD_Checker_CT":STATSVTY -> "system":TELNET
+ "MSC_ConnHdlr":STATSD_PROC -> "StatsD_Checker_CT":STATSD_PROC
+
+
+ "MGCP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> MGCP_Emulation_CT | <MGCP_CLIENT> MGCP_CLIENT | <MGCP_PROC> MGCP_PROC | <MGCP_CLIENT_MULTI> MGCP_CLIENT_MULTI | <MGCP> MGCP"
+ ]
+ "MGCP_Emulation_CT":MGCP -> "system":IPL4 [label="MGCP_CODEC_PT"]
+ "MGCP_Emulation_CT":MGCP -> "IPA_Emulation_CT":IPA_MGCP_PORT
+ "MSC_ConnHdlr":MGCP -> "MGCP_Emulation_CT":MGCP_CLIENT
+ "MSC_ConnHdlr":MGCP_PROC -> "MGCP_Emulation_CT":MGCP_PROC
+ "MSC_ConnHdlr":MGCP_MULTI -> "MGCP_Emulation_CT":MGCP_CLIENT_MULTI
+ "MSC_ConnHdlr":BSCVTY -> "system":TELNET
+
+
+ "IPA_Emulation_CT" [
+ shape = "record"
+ label = "<f0> IPA_Emulation_CT | <MTP3_SP_PORT> MTP3_SP_PORT | <IPA_MGCP_PORT> IPA_MGCP_PORT | <IPA_RSL_PORT> IPA_RSL_PORT | <IPA_OML_PORT> IPA_OML_PORT | <IPA_CTRL_PORT> IPA_CTRL_PORT | <IPA_GSUP_PORT> IPA_GSUP_PORT | <IPA_RSPRO_PORT> IPA_RSPRO_PORT | <IPA_OSMO_PCU_PORT> IPA_OSMO_PCU_PORT | <IPA_SP_PORT> IPA_SP_PORT | <IPA_PORT> IPA_PORT"
+ ];
+ "IPA_Emulation_CT":IPA_PORT -> "system":IPL4 [label="IPA_CODEC_PT"]
+
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <SCTP> SCTP | <IPL4> IPL4 | <UD> UD | <TELNET> TELNET"
+ ];
+}
diff --git a/doc/bts_tests.dot b/doc/bts_tests.dot
new file mode 100644
index 00000000..3fd94719
--- /dev/null
+++ b/doc/bts_tests.dot
@@ -0,0 +1,49 @@
+digraph G {
+ rankdir = LR;
+ label = "BTS_Tests component hierarchy";
+
+ "ConnHdlr" [
+ shape = "record"
+ label = "<f0> ConnHdlr | <RSL> RSL | <RSL_PROC> RSL_PROC | <LAPDM> LAPDM | <L1CTL> L1CTL | <BTS_TRXC> BTS_TRXC | <BSCVTY> BSCVTY | <PCU> PCU | <RTPEM_DATA> RTPEM_DATA | <RTPEM_CTRL> RTPEM_CTRL"
+ ];
+ "ConnHdlr":L1CTL -> "system":UD [label="L1CTL_PT:UD_PT"]
+ "ConnHdlr":BTS_TRXC -> "system":IPL4 [label="TRXC_CODEC_PT"]
+ "ConnHdlr":BSCVTY -> "system":TELNET
+ "ConnHdlr":PCU -> "system":UD [label="PCUIF_CODEC_PT"]
+
+ "RSL_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RSL_Emulation_CT | <CLIENT_PT> CLIENT_PT | <RSL_PROC> RSL_PROC | <CCHAN_PT> CCHAN_PT | <IPA_PT> IPA_PT"
+ ]
+ "RSL_Emulation_CT":IPA_PT -> "IPA_Emulation_CT":IPA_RSL_PORT
+ "ConnHdlr":RSL -> "RSL_Emulation_CT":CLIENT_PT
+ "ConnHdlr":RSL_PROC -> "RSL_Emulation_CT":RSL_PROC
+
+ "LAPDm_CT" [
+ shape = "record"
+ label = "<f0> LAPDM_CT | <LAPDM_SP> LAPDM_SP | <L1CTL> L1CTL"
+ ]
+ "LAPDm_CT":L1CTL -> "system":UD [label="L1CTL_PT:UD_PT"]
+ "ConnHdlr":LAPDM -> "LAPDm_CT":LAPDM_SP
+
+ "RTP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RTP_Emulation_CT | <DATA> DATA | <CTRL> CTRL | <RTP> RTP | <RTCP> RTCP"
+ ]
+ "RTP_Emulation_CT":RTP -> "system":IPL4 [label="RTP_CODEC_PT"]
+ "RTP_Emulation_CT":RTCP -> "system":IPL4 [label="RTP_CODEC_PT"]
+ "ConnHdlr":RTPEM_DATA -> "RTP_Emulation_CT":DATA
+ "ConnHdlr":RTPEM_CTRL -> "RTP_Emulation_CT":CTRL
+
+ "IPA_Emulation_CT" [
+ shape = "record"
+ label = "<f0> IPA_Emulation_CT | <MTP3_SP_PORT> MTP3_SP_PORT | <IPA_MGCP_PORT> IPA_MGCP_PORT | <IPA_RSL_PORT> IPA_RSL_PORT | <IPA_OML_PORT> IPA_OML_PORT | <IPA_CTRL_PORT> IPA_CTRL_PORT | <IPA_GSUP_PORT> IPA_GSUP_PORT | <IPA_RSPRO_PORT> IPA_RSPRO_PORT | <IPA_OSMO_PCU_PORT> IPA_OSMO_PCU_PORT | <IPA_SP_PORT> IPA_SP_PORT | <IPA_PORT> IPA_PORT"
+ ];
+ "IPA_Emulation_CT":IPA_PORT -> "system":IPL4 [label="IPA_CODEC_PT"]
+
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <IPL4> IPL4 | <UD> UD | <TELNET> TELNET"
+ ];
+}
diff --git a/doc/gb_stack_fr.dot b/doc/gb_stack_fr.dot
new file mode 100644
index 00000000..f69a264a
--- /dev/null
+++ b/doc/gb_stack_fr.dot
@@ -0,0 +1,48 @@
+digraph G {
+ rankdir = LR;
+ label = "Gb protocol stack with NS over FR";
+
+ "BSSGP_BVC_CT" [
+ shape = "record"
+ label = "<f0> BSSGP_BVC_CT | <BSSGP_SP> BSSGP_SP | <BSSGP_SP_SIG> BSSGP_SP_SIG | <BSSGP_PROC> BSSGP_PROC | <GLOBAL> GLOBAL | <MGMT> MGMT | <BVC> BVC"
+ ]
+
+ "BSSGP_CT" [
+ shape = "record"
+ label = "<f0> BSSGP_CT | <PROC> PROC | <GLOBAL> GLOBAL | <RIM> RIM | <MGMT> MGMT | <BVC> BVC | <BSCP> BSCP"
+ ]
+
+ "NS_CT" [
+ shape = "record"
+ label = "<f0> NS_CT | <NS_SP> NS_SP | <NSVC> NSVC | <NS_CTRL> NS_CTRL | <NSIP_PROC> NSIP_PROC"
+ ]
+
+ "NSVC_CT" [
+ shape = "record"
+ label = "<f0> NSVC_CT | <NS_SP> NS_SP | <NSCP> NSCP"
+ ]
+
+ "NS_Provider_FR_CT" [
+ shape = "record"
+ label = "<f0> NS_PRovider_FR_CT | <NSE> NSE | <FR> FR | <FR_PROC> FR_PROC"
+ ]
+
+ "FR_Emulation_CT" [
+ shape = "record"
+ label = "<f0> FR_Emulation_CT | <CLIENT> CLIENT | <PROC> PROC | <FR> FR"
+ ]
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <FR> FR"
+ ]
+
+ "BSSGP_BVC_CT":BVC -> "BSSGP_CT":BVC
+ "BSSGP_CT":BSCP -> "NS_CT":NS_SP
+
+ "NS_CT":NSVC -> "NSVC_CT":NS_SP
+ "NSVC_CT":NSCP -> "NS_Provider_FR_CT":NSE
+ "NS_Provider_FR_CT":FR -> "FR_Emulation_CT":CLIENT
+ "NS_Provider_FR_CT":FR_PROC -> "FR_Emulation_CT":PROC
+ "FR_Emulation_CT":FR -> "system":FR
+}
diff --git a/doc/gb_stack_ip.dot b/doc/gb_stack_ip.dot
new file mode 100644
index 00000000..0c54c789
--- /dev/null
+++ b/doc/gb_stack_ip.dot
@@ -0,0 +1,43 @@
+digraph G {
+ rankdir = LR;
+ label = "Gb protocol stack with NS over IP";
+
+ "BSSGP_BVC_CT" [
+ shape = "record"
+ label = "<f0> BSSGP_BVC_CT | <BSSGP_SP> BSSGP_SP | <BSSGP_SP_SIG> BSSGP_SP_SIG | <BSSGP_PROC> BSSGP_PROC | <GLOBAL> GLOBAL | <MGMT> MGMT | <BVC> BVC"
+ ]
+
+ "BSSGP_CT" [
+ shape = "record"
+ label = "<f0> BSSGP_CT | <PROC> PROC | <GLOBAL> GLOBAL | <RIM> RIM | <MGMT> MGMT | <BVC> BVC | <BSCP> BSCP"
+ ]
+
+ "NS_CT" [
+ shape = "record"
+ label = "<f0> NS_CT | <NS_SP> NS_SP | <NSVC> NSVC | <NS_CTRL> NS_CTRL | <NSIP_PROC> NSIP_PROC"
+ ]
+
+ "NSVC_CT" [
+ shape = "record"
+ label = "<f0> NSVC_CT | <NS_SP> NS_SP | <NSCP> NSCP"
+ ]
+
+ "NS_Provider_IPL4_CT" [
+ shape = "record"
+ label = "<f0> NS_Provider_IPL4_CT | <NSE> NSE | <NSVC> NSVC | <IPL4> IPL4 | <PROC> PROC"
+ ]
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <IPL4> IPL4"
+ ]
+
+ "BSSGP_BVC_CT":BVC -> "BSSGP_CT":BVC
+ "BSSGP_CT":BSCP -> "NS_CT":NS_SP
+
+ "NS_CT":NSVC -> "NSVC_CT":NS_SP
+ "NS_CT":NSIP_PROC -> "NS_Provider_IPL4_CT":PROC
+ "NSVC_CT":NSCP -> "NS_Provider_IPL4_CT":NSVC
+ "NS_Provider_IPL4_CT":IPL4 -> "system":IPL4
+
+}
diff --git a/doc/msc_tests_aoip.dot b/doc/msc_tests_aoip.dot
new file mode 100644
index 00000000..c7998448
--- /dev/null
+++ b/doc/msc_tests_aoip.dot
@@ -0,0 +1,89 @@
+digraph G {
+ rankdir = LR;
+ label = "MSC_Tests component hierarchy";
+
+ "BSC_ConnHdlr" [
+ shape = "record"
+ label = "<f0> BSC_ConnHdlr | <BSSAP> BSSAP | <BSSAP_PROC> BSSAP_PROC | <MNCC> MNCC | <MNCC_PROC> MNCC_PROC | <GSUP> GSUP | <GSUP_PROC> GSUP_PROC | <MGCP> MGCP | <MGCP_PROC> MGCP_PROC | <MGCP_MULTI> MGCP_MULTI | <SMPP> SMPP | <SMPP_PROC> SMPP_PROC | <IPA_CTRL> IPA_CTRL | <SGsAP> SGsAP | <SGsAP_PROC> SGsAP_PROC"
+ ];
+
+ "RAN_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RAN_Emulation_CT | <MGCP> MGCP | <CTRL> CTRL | <CTRL_CLIENT> CTRL_CLIENT | <CLIENT> CLIENT | <PROC> PROC | <BSSAP> BSSAP | <RANAP> RANAP"
+ ];
+ "RAN_Emulation_CT":BSSAP -> "SCCP_CT":SCCP_SP_PORT
+ "BSC_ConnHdlr":BSSAP -> "RAN_Emulation_CT":CLIENT
+ "BSC_ConnHdlr":BSSAP_PROC -> "RAN_Emulation_CT":PROC
+ "BSC_ConnHdlr":IPA_CTRL -> "IPA_Emulation_CT":IPA_CTRL_PORT
+
+
+ "SCCP_CT" [
+ shape = "record"
+ label = "<f0> SCCP_CT | <MTP3_SCCP_PORT> MTP3_SCCP_PORT | <SCCP_SP_PORT> SCCP_SP_PORT"
+ ];
+ "SCCP_CT":MTP3_SCCP_PORT -> "M3UA_CT":MTP3_SP_PORT
+
+ "M3UA_CT" [
+
+ shape = "record"
+ label = "<f0> M3UA_CT | <STCP_PORT> SCTP_PORT | <MTP3_SP_PORT> MTP3_SP_PORT"
+ ];
+ "M3UA_CT":SCTP_PORT -> "system":SCTP
+
+
+ "MNCC_Emulation_CT" [
+ shape = "record"
+ label = "<f0> MNCC_Emulation_CT | <MNCC_CLIENT> MNCC_CLIENT | <MNCC_PROC> MNCC_PROC | <MNCC> MNCC"
+ ]
+ "MNCC_Emulation_CT":MNCC -> "system":UD [label="MNCC_CODEC_PT"]
+ "BSC_ConnHdlr":MNCC -> "MNCC_Emulation_CT":MNCC_CLIENT
+ "BSC_ConnHdlr":MNCC_PROC -> "MNCC_Emulation_CT":MNCC_PROC
+
+
+ "GSUP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> GSUP_Emulation_CT | <GSUP_CLIENT> GSUP_CLIENT | <GSUP_PROC> GSUP_PROC | <GSUP> GSUP"
+ ]
+ "GSUP_Emulation_CT":GSUP -> "IPA_Emulation_CT":IPA_GSUP_PORT
+ "BSC_ConnHdlr":GSUP -> "GSUP_Emulation_CT":GSUP_CLIENT
+ "BSC_ConnHdlr":GSUP_PROC -> "GSUP_Emulation_CT":GSUP_PROC
+
+
+ "MGCP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> MGCP_Emulation_CT | <MGCP_CLIENT> MGCP_CLIENT | <MGCP_PROC> MGCP_PROC | <MGCP_CLIENT_MULTI> MGCP_CLIENT_MULTI | <MGCP> MGCP"
+ ]
+ "MGCP_Emulation_CT":MGCP -> "system":IPL4 [label="MGCP_CODEC_PT"]
+ "MGCP_Emulation_CT":MGCP -> "IPA_Emulation_CT":IPA_MGCP_PORT
+ "BSC_ConnHdlr":MGCP -> "MGCP_Emulation_CT":MGCP_CLIENT
+ "BSC_ConnHdlr":MGCP_PROC -> "MGCP_Emulation_CT":MGCP_PROC
+ "BSC_ConnHdlr":MGCP_MULTI -> "MGCP_Emulation_CT":MGCP_CLIENT_MULTI
+
+ "SMPP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> SMPP_Emulation_CT | <SMPP_CLIENT> SMPP_CLIENT | <SMPP_PROC> SMPP_PROC | <SMPP_PORT> SMPP_PORT"
+ ]
+ "SMPP_Emulation_CT":SMPP_PORT -> "system":IPL4 [label="SMPP_CODEC_PT"]
+ "BSC_ConnHdlr":SMPP -> "SMPP_Emulation_CT":SMPP_CLIENT
+ "BSC_ConnHdlr":SMPP_PROC -> "SMPP_Emulation_CT":SMPP_PROC
+
+ "SGsAP_Emulation_CT" [
+ shape = "record"
+ label = "<f0> SGsAP_Emulation_CT | <SGsAP_CLIENT> SGsAP_CLIENT | <SGsAP_PROC> SGsAP_PROC | <SGsAP_UNIT> SGsAP_UNIT | <SGsAP> SGsAP"
+ ]
+ "SGsAP_Emulation_CT":SGsAP -> "system":IPL4 [label="SGsAP_CODEC_PT"]
+ "BSC_ConnHdlr":SGsAP -> "SGsAP_Emulation_CT":SGsAP_CLIENT
+ "BSC_ConnHdlr":SGsAP_PROC -> "SGsAP_Emulation_CT":SGsAP_PROC
+
+ "IPA_Emulation_CT" [
+ shape = "record"
+ label = "<f0> IPA_Emulation_CT | <MTP3_SP_PORT> MTP3_SP_PORT | <IPA_MGCP_PORT> IPA_MGCP_PORT | <IPA_RSL_PORT> IPA_RSL_PORT | <IPA_OML_PORT> IPA_OML_PORT | <IPA_CTRL_PORT> IPA_CTRL_PORT | <IPA_GSUP_PORT> IPA_GSUP_PORT | <IPA_RSPRO_PORT> IPA_RSPRO_PORT | <IPA_OSMO_PCU_PORT> IPA_OSMO_PCU_PORT | <IPA_SP_PORT> IPA_SP_PORT | <IPA_PORT> IPA_PORT"
+ ];
+ "IPA_Emulation_CT":IPA_PORT -> "system":IPL4 [label="IPA_CODEC_PT"]
+
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <SCTP> SCTP | <IPL4> IPL4 | <UD> UD"
+ ];
+}
diff --git a/doc/ran_emulation_aoip.dot b/doc/ran_emulation_aoip.dot
new file mode 100644
index 00000000..83745558
--- /dev/null
+++ b/doc/ran_emulation_aoip.dot
@@ -0,0 +1,39 @@
+digraph G {
+ rankdir = LR;
+ label = "RAN_Emulation when used with AoIP as in MSC_Tests";
+
+ "RAN_ConnHdlr" [
+ shape = "record"
+ label = "<f0> RAN_ConnHdlr | <BSSAP> BSSAP | <BSSAP_PROC> BSSAP_PROC"
+ ];
+
+ "RAN_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RAN_Emulation_CT | <MGCP> MGCP | <CTRL> CTRL | <CTRL_CLIENT> CTRL_CLIENT | <CLIENT> CLIENT | <PROC> PROC | <BSSAP> BSSAP | <RANAP> RANAP"
+ ];
+
+ "SCCP_CT" [
+ shape = "record"
+ label = "<f0> SCCP_CT | <MTP3_SCCP_PORT> MTP3_SCCP_PORT | <SCCP_SP_PORT> SCCP_SP_PORT"
+ ];
+
+ "M3UA_CT" [
+
+ shape = "record"
+ label = "<f0> M3UA_CT | <STCP_PORT> SCTP_PORT | <MTP3_SP_PORT> MTP3_SP_PORT"
+ ];
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <SCTP> SCTP"
+ ];
+
+ "RAN_ConnHdlr":BSSAP -> "RAN_Emulation_CT":CLIENT
+ "RAN_ConnHdlr":BSSAP_PROC -> "RAN_Emulation_CT":PROC
+
+ "RAN_Emulation_CT":BSSAP -> "SCCP_CT":SCCP_SP_PORT
+ "RAN_Emulation_CT":RANAP -> "SCCP_CT":SCCP_SP_PORT
+
+ "SCCP_CT":MTP3_SCCP_PORT -> "M3UA_CT":MTP3_SP_PORT
+ "M3UA_CT":SCTP_PORT -> "system":SCTP
+}
diff --git a/doc/ran_emulation_sccplite.dot b/doc/ran_emulation_sccplite.dot
new file mode 100644
index 00000000..7ab7feb8
--- /dev/null
+++ b/doc/ran_emulation_sccplite.dot
@@ -0,0 +1,39 @@
+digraph G {
+ rankdir = LR;
+ label = "RAN_Emulation when used with SCCPLite";
+
+ "RAN_ConnHdlr" [
+ shape = "record"
+ label = "<f0> RAN_ConnHdlr | <BSSAP> BSSAP | <BSSAP_PROC> BSSAP_PROC"
+ ];
+
+ "RAN_Emulation_CT" [
+ shape = "record"
+ label = "<f0> RAN_Emulation_CT | <MGCP> MGCP | <CTRL> CTRL | <CTRL_CLIENT> CTRL_CLIENT | <CLIENT> CLIENT | <PROC> PROC | <BSSAP> BSSAP | <RANAP> RANAP"
+ ];
+
+ "SCCP_CT" [
+ shape = "record"
+ label = "<f0> SCCP_CT | <MTP3_SCCP_PORT> MTP3_SCCP_PORT | <SCCP_SP_PORT> SCCP_SP_PORT"
+ ];
+
+ "IPA_Emulation_CT" [
+ shape = "record"
+ label = "<f0> IPA_Emulation_CT | <MTP3_SP_PORT> MTP3_SP_PORT | <IPA_MGCP_PORT> IPA_MGCP_PORT | <IPA_RSL_PORT> IPA_RSL_PORT | <IPA_OML_PORT> IPA_OML_PORT | <IPA_CTRL_PORT> IPA_CTRL_PORT | <IPA_GSUP_PORT> IPA_GSUP_PORT | <IPA_RSPRO_PORT> IPA_RSPRO_PORT | <IPA_OSMO_PCU_PORT> IPA_OSMO_PCU_PORT | <IPA_SP_PORT> IPA_SP_PORT | <IPA_PORT> IPA_PORT"
+ ];
+
+ "system" [
+ shape = "record"
+ label = "<f0> system | <IPA_CODEC_PORT> IPA_CODEC_PORT"
+ ];
+
+ "RAN_ConnHdlr":BSSAP -> "RAN_Emulation_CT":CLIENT
+ "RAN_ConnHdlr":BSSAP_PROC -> "RAN_Emulation_CT":PROC
+
+ "RAN_Emulation_CT":BSSAP -> "SCCP_CT":SCCP_SP_PORT
+ "RAN_Emulation_CT":MGCP -> "IPA_Emulation_CT":IPA_MGCP_PORT
+ "RAN_Emulation_CT":CTRL -> "IPA_Emulation_CT":IPA_CTRL_PORT
+
+ "SCCP_CT":MTP3_SCCP_PORT -> "IPA_Emulation_CT":MTP3_SP_PORT
+ "IPA_Emulation_CT":IPA_PORT -> "system":IPA_CODEC_PORT
+}
diff --git a/epdg/EPDG_Tests.cfg b/epdg/EPDG_Tests.cfg
new file mode 100644
index 00000000..c1642937
--- /dev/null
+++ b/epdg/EPDG_Tests.cfg
@@ -0,0 +1,19 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./EPDG_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+EPDG_Tests.control
diff --git a/epdg/EPDG_Tests.default b/epdg/EPDG_Tests.default
new file mode 100644
index 00000000..95b42e94
--- /dev/null
+++ b/epdg/EPDG_Tests.default
@@ -0,0 +1,8 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING; // | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[EXECUTE]
diff --git a/epdg/EPDG_Tests.ttcn b/epdg/EPDG_Tests.ttcn
new file mode 100644
index 00000000..f963994e
--- /dev/null
+++ b/epdg/EPDG_Tests.ttcn
@@ -0,0 +1,1349 @@
+module EPDG_Tests {
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Native_Functions all;
+import from Osmocom_Types all;
+import from L3_Common all;
+import from DNS_Helpers all;
+import from IP_Types all;
+import from ICMP_Types all;
+import from ICMP_Templates all;
+
+import from IPA_Emulation all;
+import from PCO_Types all;
+import from GSUP_Types all;
+import from GSUP_Templates all;
+import from GSUP_Emulation all;
+
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_rfc4004_Templates all;
+import from DIAMETER_ts29_229_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+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_Templates all;
+
+import from GTPv2_Types all;
+import from GTPv2_Templates all;
+import from GTPv2_Emulation all;
+
+modulepar {
+ /* our emulated GSUP strongswan (CEAI iface) */
+ charstring mp_gsup_local_ip := "127.0.0.100";
+ integer mp_gsup_local_port := 0;
+ charstring mp_gsup_remote_ip := "127.0.0.1";
+ integer mp_gsup_remote_port := 4222;
+
+ /* our emulated HSS */
+ charstring mp_swx_local_ip := "127.0.0.100";
+ integer mp_swx_local_port := 3868;
+
+ /* our emulated PGW (Diameter S6b) */
+ charstring mp_s6b_local_ip := "127.0.0.100";
+ integer mp_s6b_local_port := 3869;
+ charstring mp_s6b_remote_ip := "127.0.0.1";
+ integer mp_s6b_remote_port := 3869;
+ /* 3GPP TS 23.003 clause 19: "nai.epc.mnc<MNC>.mcc<MCC>.3gppnetwork.org" */
+ charstring mp_s6b_nai_realm := "nai.epc.mnc001.mcc01.3gppnetwork.org";
+
+ /* our emulated PGW (GTPv2C S2b) */
+ charstring mp_s2b_local_ip := "127.0.0.100";
+ integer mp_s2b_local_port := GTP2C_PORT;
+ charstring mp_s2b_remote_ip := "127.0.0.1";
+ integer mp_s2b_remote_port := GTP2C_PORT;
+ charstring mp_s2b_dns_ipv4 := "1.2.3.4";
+ charstring mp_s2b_dns_ipv6 := "::1";
+ charstring mp_s2b_pcscf_ipv4 := "5.6.7.8";
+ charstring mp_s2b_pcscf_ipv6 := "::2";
+ /* our emulated PGW /* GTP1U */
+ charstring mp_upf_gtpu_local_ip := "127.0.0.100";
+
+ charstring mp_diam_realm := "localdomain";
+ integer mp_diam_watchdog_initial_wait_sec := 6*3;
+}
+
+type port Coord_PT message
+{
+ inout charstring;
+} with { extension "internal" };
+private const charstring COORD_CMD_READY := "COORD_CMD_READY";
+private const charstring COORD_CMD_START := "COORD_CMD_START";
+private const charstring COORD_CMD_ATTACHED := "COORD_CMD_ATTACHED";
+private const charstring COORD_CMD_STOP := "COORD_CMD_STOP";
+
+type component MTC_CT {
+ var DIAMETER_Emulation_CT vc_SWx;
+ port DIAMETER_PT SWx_UNIT;
+ port DIAMETEREM_PROC_PT SWx_PROC;
+
+ var DIAMETER_Emulation_CT vc_S6b;
+ port DIAMETER_PT S6b_UNIT;
+ port DIAMETEREM_PROC_PT S6b_PROC;
+
+ var GSUP_Emulation_CT vc_GSUP;
+ var IPA_Emulation_CT vc_GSUP_IPA;
+ port IPA_CTRL_PT GSUP_IPA_EVENT;
+
+ var GTPv2_Emulation_CT vc_GTP2;
+ port GTP2EM_PT TEID0;
+
+ port Coord_PT COORD;
+
+ timer g_Tguard;
+};
+
+private altstep as_Tguard() runs on MTC_CT {
+ [] g_Tguard.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout");
+ }
+}
+
+type component DIAMETER_ConnHdlr_CT extends DIAMETER_ConnHdlr {
+ port DIAMETER_Conn_PT DIAMETER_CLIENT;
+ port DIAMETEREM_PROC_PT DIAMETER_PROC_CLIENT;
+}
+
+function f_diam_connhldr_ct_main(hexstring imsi) runs on DIAMETER_ConnHdlr_CT {
+ var DIAMETER_ConnHdlr vc_conn_unused;
+ var PDU_DIAMETER msg;
+ var UINT32 ete_id;
+
+ f_diameter_expect_imsi(imsi);
+
+ while (true) {
+ alt {
+ [] DIAMETER_CLIENT.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER.send(msg);
+ }
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER_CLIENT.send(msg);
+ }
+ [] DIAMETER_PROC_CLIENT.getcall(DIAMETEREM_register_eteid:{?,?}) -> param(ete_id, vc_conn_unused) {
+ DIAMETER_PROC.call(DIAMETEREM_register_eteid:{ete_id, self}) {
+ [] DIAMETER_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+ DIAMETER_PROC_CLIENT.reply(DIAMETEREM_register_eteid:{ete_id, vc_conn_unused});
+ }
+ }
+ }
+}
+
+type component EPDG_ConnHdlr extends DIAMETER_ConnHdlr, GSUP_ConnHdlr, GTP2_ConnHdlr {
+ var EPDG_ConnHdlrPars g_pars;
+
+ port DIAMETER_Conn_PT SWx;
+ port DIAMETEREM_PROC_PT SWx_PROC;
+ port DIAMETER_Conn_PT S6b;
+ port DIAMETEREM_PROC_PT S6b_PROC;
+ port Coord_PT COORD;
+};
+type record of EPDG_ConnHdlr EPDG_ConnHdlrList;
+
+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,
+ /* GTP-U address of the peer (ePDG) */
+ charstring gtpu_addr_remote optional
+};
+
+type record EPDG_ConnHdlrPars {
+ hexstring imsi,
+ charstring apn,
+ charstring ue_ip,
+
+ /* TEI (Control) local side */
+ OCT4 teic_local,
+ /* TEI (Control) remote side */
+ OCT4 teic_remote optional,
+
+ BearerConfig bearer optional,
+
+ AuthVector vec optional
+};
+
+private function f_epdg_connhldr_SWx_expect_eteid(UINT32 ete_id) runs on EPDG_ConnHdlr {
+ SWx_PROC.call(DIAMETEREM_register_eteid:{ete_id, null}) {
+ [] SWx_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+}
+private function f_epdg_connhldr_S6b_expect_eteid(UINT32 ete_id) runs on EPDG_ConnHdlr {
+ S6b_PROC.call(DIAMETEREM_register_eteid:{ete_id, null}) {
+ [] S6b_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+}
+
+private function f_gen_addr_in_pool(integer idx := 0) return charstring
+{
+ /* Skip first 2 addresses reserved for TUN */
+ var integer internal_idx := idx + 2;
+ var integer suffix := internal_idx rem (256*256);
+ var integer C := suffix / 256;
+ var integer D := suffix rem 256;
+ return "192.168." & int2str(C) & "." & int2str(D);
+}
+
+private function f_init_pars(integer idx := 0)
+runs on MTC_CT return EPDG_ConnHdlrPars {
+ var EPDG_ConnHdlrPars pars := {
+ imsi := f_rnd_imsi('26242'H),
+ apn := "internet",
+ ue_ip := f_gen_addr_in_pool(idx),
+ teic_local := '00000000'O,
+ teic_remote := omit,
+ bearer := {
+ ebi := omit,
+ teid_local := omit,
+ teid_remote := omit,
+ gtpu_addr_remote := omit
+ },
+ vec := f_gen_auth_vec_3g()
+ };
+ return pars;
+}
+
+private function f_init_gsup(charstring id) runs on MTC_CT {
+ id := id & "-GSUP";
+ var GsupOps ops := {
+ create_cb := refers(GSUP_Emulation.ExpectedCreateCallback)
+ };
+
+ vc_GSUP_IPA := IPA_Emulation_CT.create(id & "-IPA");
+ vc_GSUP := GSUP_Emulation_CT.create(id);
+
+ map(vc_GSUP_IPA:IPA_PORT, system:IPA_CODEC_PT);
+ connect(vc_GSUP:GSUP, vc_GSUP_IPA:IPA_GSUP_PORT);
+ /* we use this hack to get events like ASP_IPA_EVENT_UP */
+ connect(vc_GSUP_IPA:IPA_CTRL_PORT, self:GSUP_IPA_EVENT);
+
+ vc_GSUP.start(GSUP_Emulation.main(ops, id));
+ vc_GSUP_IPA.start(IPA_Emulation.main_client(mp_gsup_remote_ip, mp_gsup_remote_port,
+ mp_gsup_local_ip, mp_gsup_local_port));
+
+ /* wait for incoming connection to GSUP port before proceeding */
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] GSUP_IPA_EVENT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "No connection to GSUP Port");
+ }
+ }
+}
+
+private function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
+runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
+ DIAMETER_UNIT.send(msg);
+ return omit;
+}
+
+private function f_init_diameter(charstring id) runs on MTC_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;
+
+ /* SWx setup: */
+ pars := {
+ remote_ip := "",
+ remote_sctp_port := -1, /* server mode */
+ local_ip := mp_swx_local_ip,
+ local_sctp_port := mp_swx_local_port,
+ origin_host := "hss." & mp_diam_realm,
+ origin_realm := mp_diam_realm,
+ auth_app_id := omit,
+ vendor_app_id := c_DIAMETER_3GPP_SWx_AID
+ };
+ vc_SWx := DIAMETER_Emulation_CT.create(id);
+ map(vc_SWx:DIAMETER, system:DIAMETER_CODEC_PT);
+ connect(vc_SWx:DIAMETER_UNIT, self:SWx_UNIT);
+ connect(vc_SWx:DIAMETER_PROC, self:SWx_PROC);
+ vc_SWx.start(DIAMETER_Emulation.main(ops, pars, id));
+
+ /* S6b setup: */
+ pars := {
+ remote_ip := mp_s6b_remote_ip,
+ remote_sctp_port := mp_s6b_remote_port, /* client mode */
+ local_ip := mp_s6b_local_ip,
+ local_sctp_port := mp_s6b_local_port,
+ origin_host := "pgw." & 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(SWx_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#L49
+ */
+ f_sleep(int2float(mp_diam_watchdog_initial_wait_sec));
+}
+
+private function f_init_gtp(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,
+ 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));
+}
+
+private function f_init(float t_guard := 40.0) runs on MTC_CT {
+
+ g_Tguard.start(t_guard);
+ activate(as_Tguard());
+
+ f_init_gsup(testcasename());
+ f_init_diameter(testcasename());
+ f_init_gtp(testcasename());
+}
+
+private type function void_fn(charstring id) runs on EPDG_ConnHdlr;
+
+private function f_init_handler(void_fn fn, charstring id, EPDG_ConnHdlrPars pars) runs on EPDG_ConnHdlr {
+ g_pars := pars;
+
+ /* tell GSUP dispatcher to send this IMSI to us */
+ f_create_gsup_expect(hex2str(g_pars.imsi));
+
+ /* tell GTPv2 dispatcher to send this IMSI to us */
+ f_gtp2_register_imsi(g_pars.imsi);
+
+ fn.apply(id);
+}
+
+private function f_start_handler(void_fn fn, EPDG_ConnHdlrPars pars)
+runs on MTC_CT return EPDG_ConnHdlr {
+ var EPDG_ConnHdlr vc_conn;
+ var charstring id := testcasename();
+ var DIAMETER_ConnHdlr_CT vc_conn_swx, vc_conn_s6b;
+
+ vc_conn := EPDG_ConnHdlr.create(id);
+
+ /* GSUP */
+ connect(vc_conn:GSUP, vc_GSUP:GSUP_CLIENT);
+ connect(vc_conn:GSUP_PROC, vc_GSUP:GSUP_PROC);
+
+ /* GTP2 */
+ connect(vc_conn:GTP2, vc_GTP2:CLIENT);
+ connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC);
+
+ /* SWx */
+ vc_conn_swx := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_swx:DIAMETER, vc_SWx:DIAMETER_CLIENT);
+ connect(vc_conn_swx:DIAMETER_PROC, vc_SWx:DIAMETER_PROC);
+ connect(vc_conn:SWx, vc_conn_swx:DIAMETER_CLIENT);
+ connect(vc_conn:SWx_PROC, vc_conn_swx:DIAMETER_PROC_CLIENT);
+ vc_conn_swx.start(f_diam_connhldr_ct_main(pars.imsi));
+
+ /* S6b */
+ vc_conn_s6b := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_s6b:DIAMETER, vc_S6b:DIAMETER_CLIENT);
+ connect(vc_conn_s6b:DIAMETER_PROC, vc_S6b:DIAMETER_PROC);
+ connect(vc_conn:S6b, vc_conn_s6b:DIAMETER_CLIENT);
+ connect(vc_conn:S6b_PROC, vc_conn_s6b:DIAMETER_PROC_CLIENT);
+ vc_conn_s6b.start(f_diam_connhldr_ct_main(pars.imsi));
+
+ /* COORD */
+ connect(vc_conn:COORD, self:COORD);
+
+ vc_conn.start(f_init_handler(fn, id, pars));
+ return vc_conn;
+}
+
+private function f_nai() runs on EPDG_ConnHdlr return charstring {
+ return hex2str(g_pars.imsi) & "@" & mp_s6b_nai_realm;
+}
+
+private function f_DIA_SWx_tx_MAA_success(PDU_DIAMETER rx_mar) runs on EPDG_ConnHdlr {
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ var template (value) GenericAVP sip_auth_data_item;
+
+ avp := f_DIAMETER_get_avp(rx_mar, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+ sip_auth_data_item := ts_AVP_3GPP_SIPAuthDataItem(0,
+ g_pars.vec.rand,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.auts);
+ /* Send MAA to translator; expect it to show up on GSUP side */
+ SWx.send(ts_DIA_SWx_MAA(g_pars.imsi, sip_auth_data_item,
+ sess_id := sess_id,
+ hbh_id := rx_mar.hop_by_hop_id,
+ ete_id := rx_mar.end_to_end_id));
+}
+
+private function f_DIA_SWx_tx_MAA_error(PDU_DIAMETER rx_mar, template (value) GenericAVP result) runs on EPDG_ConnHdlr {
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ var template (value) GenericAVP sip_auth_data_item;
+
+ avp := f_DIAMETER_get_avp(rx_mar, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+ sip_auth_data_item := ts_AVP_3GPP_SIPAuthDataItem(0,
+ g_pars.vec.rand,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.auts);
+ SWx.send(ts_DIA_SWx_MAA_result(g_pars.imsi, result,
+ sess_id := sess_id,
+ hbh_id := rx_mar.hop_by_hop_id,
+ ete_id := rx_mar.end_to_end_id));
+}
+
+/* Diameter SWx MAR + MAA. */
+private altstep as_DIA_SWx_MA_success(boolean exp_req_resync := false) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ [] SWx.receive(tr_DIA_SWx_MAR(g_pars.imsi)) -> value rx_dia {
+ if (exp_req_resync) {
+ var octetstring rand_autn_concatenated := g_pars.vec.rand & g_pars.vec.auts;
+ var AVP avp_grp;
+ var GenericAVP sip_auth_avp;
+
+ avp_grp := f_DIAMETER_get_avp_or_fail(rx_dia, c_AVP_Code_CxDx_3GPP_SIP_Auth_Data_Item);
+ sip_auth_avp.avp := f_AVP_Grouped_get_avp_or_fail(avp_grp.avp_data.avp_CxDx_3GPP_SIP_Auth_Data_Item,
+ c_AVP_Code_CxDx_3GPP_SIP_Authorization);
+
+ if (not match(sip_auth_avp, tr_AVP_3GPP_SIPAuthorization(rand_autn_concatenated))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected Diameter AVP SIP-Authorization: ", sip_auth_avp,
+ " vs exp ", tr_AVP_3GPP_SIPAuthorization(rand_autn_concatenated)));
+ }
+ }
+ f_DIA_SWx_tx_MAA_success(rx_dia);
+ setverdict(pass);
+ }
+ [] SWx.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia));
+ }
+}
+
+/* Diameter SWx SAR + SAA. */
+private altstep as_DIA_SWx_SA_success(template (present) CxDx_3GPP_Server_Assignment_Type server_ass_type := ?) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ [] SWx.receive(tr_DIA_SWx_SAR(g_pars.imsi)) -> value rx_dia {
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+ /* Send SAA to translator; expect it to show up on GSUP side */
+ SWx.send(ts_DIA_SWx_SAA(g_pars.imsi,
+ IPv4,
+ g_pars.apn,
+ sess_id := sess_id,
+ hbh_id := rx_dia.hop_by_hop_id,
+ ete_id := rx_dia.end_to_end_id));
+ setverdict(pass);
+ }
+ [] SWx.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia));
+ }
+}
+
+/* Send PPR as HSS to AAA server, expect back PPA */
+private function f_DIA_SWx_PP(template (present) GenericAVP exp_result_tmpl := tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ boolean exp_aaa_proc := true) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var octetstring reason_info := char2oct("test");
+
+ /* Unlike PPR, PPA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so PPA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_epdg_connhldr_SWx_expect_eteid(ete_id);
+
+ SWx.send(ts_DIA_SWx_PPR(g_pars.imsi,
+ IPv4,
+ g_pars.apn,
+ hbh_id := hbh_id,
+ ete_id := ete_id));
+
+ if (exp_aaa_proc) {
+ /* TODO: in successful case, we want to validate how this procedure extends to other interfaces:
+ * """ 3GPP TS 29.273 8.1.2.3.3:
+ * After a successful user profile download, the 3GPP AAA Server shall
+ * initiate re-authentication procedure as described
+ * in clause 7.2.2.4 if the subscriber has previously been authenticated
+ * and authorized to untrusted non-3GPP access.
+ * """
+ */
+ /* TS 29.273 9.1.2.5.1:
+ * "The Service Authorization Information Update procedure is performed in two steps":
+ * step 1: */
+ as_DIA_S6b_RA_success();
+ /* step 2 */
+ /* Since PGW Address didn't change, expect no SAR+SAA triggered as a consequence to AAR+AAA. */
+ f_S6b_AA_success(exp_swx_sa_proc := false);
+ }
+
+ alt {
+ [] SWx.receive(tr_DIA_SWx_PPA(exp_result_tmpl, hbh_id := hbh_id, ete_id := ete_id)) -> value rx_dia {}
+ [] SWx.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter SWx msg rx: ", rx_dia));
+ }
+ }
+}
+
+/* Send RTR as HSS to AAA server, expect back RTA */
+private function f_DIA_SWx_RT(template (value) CxDx_3GPP_Reason_Code reason_code,
+ template (present) GenericAVP exp_result_tmpl := tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ boolean exp_aaa_proc := true) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var octetstring reason_info := char2oct("test");
+ var CxDx_3GPP_Reason_Code reason_code_permanent_termination := PERMANENT_TERMINATION;
+
+ /* Unlike STR, STA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_epdg_connhldr_SWx_expect_eteid(ete_id);
+
+ SWx.send(ts_DIA_SWx_RTR(g_pars.imsi, reason_code, reason_info,
+ hbh_id := hbh_id,
+ ete_id := ete_id));
+
+ if (match(reason_code_permanent_termination, reason_code) and exp_aaa_proc) {
+ /* Expect Abort-Session procedure (ASR + ASA) in the S6b interface: */
+ as_DIA_S6b_AS_success();
+ /* Here AAA-Server starts an ASR + ASA procedure towards ePDG, which forwards it to strongswan: */
+ as_GSUP_rx_CL_REQ(OSMO_GSUP_CANCEL_TYPE_WITHDRAW);
+ f_GSUP_tx_CL_RES();
+ /* No need to so STR+STA, since the session was already aborted above during ASR+ASA: */
+ as_GTP2C_DeleteSession_success(do_s6b_st_proc := false);
+ }
+
+ alt {
+ [] SWx.receive(tr_DIA_SWx_RTA(exp_result_tmpl, hbh_id := hbh_id, ete_id := ete_id)) -> value rx_dia {}
+ [] SWx.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter SWx msg rx: ", rx_dia));
+ }
+ }
+}
+
+
+/* Send AAR as PGW to AAA server, expect back AAA */
+private function f_S6b_AA_success(boolean exp_swx_sa_proc := true) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var template (value) MIPv4_NONE_MIP_Home_Agent_Address pgw_addr;
+
+ pgw_addr := ts_AVP_Home_Agent_Address(IP, f_inet_addr(mp_s2b_local_ip));
+
+ /* Unlike AAR, AAA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_epdg_connhldr_S6b_expect_eteid(ete_id);
+
+ S6b.send(ts_DIA_S6b_AAR(f_nai(),
+ int2oct(DIA_TS29_373_MIP6_Feature_Vector_GTPv2_SUPPORTED, 8),
+ g_pars.apn,
+ pgw_addr,
+ hbh_id := hbh_id, ete_id := ete_id));
+
+ if (exp_swx_sa_proc) {
+ /* AAR in S6b in AAA-Server triggers Service-Assignment Request/Answer towards HSS: */
+ as_DIA_SWx_SA_success();
+ }
+
+ alt {
+ [] S6b.receive(tr_DIA_S6b_AAA) -> value rx_dia {}
+ [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter S6b msg rx: ", rx_dia));
+ }
+ }
+}
+
+/* Send STR as PGW to AAA server, expect back STA */
+private function f_S6b_ST_success() runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+
+ /* Unlike STR, STA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_epdg_connhldr_S6b_expect_eteid(ete_id);
+
+ S6b.send(ts_DIA_S6b_STR(g_pars.imsi, DIAMETER_LOGOUT,
+ hbh_id := hbh_id, ete_id := ete_id));
+ alt {
+ [] S6b.receive(tr_DIA_S6b_STA(DIAMETER_SUCCESS)) -> value rx_dia {}
+ [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter S6b msg rx: ", rx_dia));
+ }
+ }
+}
+
+/* Diameter S6b RAR + RAA, TS 29.273 9.1.2.5. */
+private altstep as_DIA_S6b_RA_success() runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ [] S6b.receive(tr_DIA_S6b_RAR(f_nai())) -> value rx_dia {
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+ S6b.send(ts_DIA_S6b_RAA(DIAMETER_SUCCESS,
+ sess_id := sess_id,
+ hbh_id := rx_dia.hop_by_hop_id,
+ ete_id := rx_dia.end_to_end_id));
+ setverdict(pass);
+ }
+ [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter S6b msg rx: ", rx_dia));
+ }
+}
+
+/* Diameter S6b ASR + ASA, TS 29.273 9.1.2.3.4. */
+private altstep as_DIA_S6b_AS_success() runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ [] S6b.receive(tr_DIA_S6b_ASR(f_nai())) -> value rx_dia {
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+ S6b.send(ts_DIA_S6b_ASA(DIAMETER_SUCCESS,
+ sess_id := sess_id,
+ hbh_id := rx_dia.hop_by_hop_id,
+ ete_id := rx_dia.end_to_end_id));
+ setverdict(pass);
+ }
+ [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter S6b msg rx: ", rx_dia));
+ }
+}
+
+private function f_exp_tr_GTP2C_APCO_in_CreateSessionReq()
+ runs on EPDG_ConnHdlr return template (present) APCO {
+ var template ProtocolIDs_and_ContainerIDs protos, protosV4, protosV6, protosV46;
+ protosV4 := {tr_GTP2C_PCO_P_DNS_IPv4(''O), tr_GTP2C_PCO_P_PCSCF_IPv4(''O)};
+ protosV6 := {tr_GTP2C_PCO_P_DNS_IPv6(''O), tr_GTP2C_PCO_P_PCSCF_IPv6(''O)};
+ protosV46 := {tr_GTP2C_PCO_P_DNS_IPv4(''O), tr_GTP2C_PCO_P_PCSCF_IPv4(''O),
+ tr_GTP2C_PCO_P_DNS_IPv6(''O), tr_GTP2C_PCO_P_PCSCF_IPv6(''O)}
+ /* TODO: pick proto based on req_type v4, v6 or v4v6 */
+ protos := protosV4;
+ return tr_GTP2C_APCO('0000'B, protos);
+}
+
+private function f_GTPv2C_gen_APCO_response(APCO apco_req) runs on EPDG_ConnHdlr return template (value) APCO {
+ var ProtocolIDs_and_ContainerIDs proto_list_resp := {};
+
+ for (var integer i := 0; i < lengthof(apco_req.protocolIDs_and_ContainerIDs); i := i + 1) {
+ var ProtocolID_or_ContainerID proto_req := apco_req.protocolIDs_and_ContainerIDs[i];
+ select (proto_req.protocolID_or_ContainerID) {
+ case (PCO_P_to_OCT2(PCO_P_DNS_IPv4_ADDR)) {
+ proto_list_resp := proto_list_resp & { valueof(ts_GTP2C_PCO_P_DNS_IPv4(f_inet_addr(mp_s2b_dns_ipv4))) };
+ }
+ case (PCO_P_to_OCT2(PCO_P_DNS_IPv6_ADDR)) {
+ proto_list_resp := proto_list_resp & { valueof(ts_GTP2C_PCO_P_DNS_IPv6(f_inet_addr(mp_s2b_dns_ipv6))) };
+ }
+ case (PCO_P_to_OCT2(PCO_P_PCSCF_IPv4_ADDR)) {
+ proto_list_resp := proto_list_resp & { valueof(ts_GTP2C_PCO_P_PCSCF_IPv4(f_inet_addr(mp_s2b_pcscf_ipv4))) };
+ }
+ case (PCO_P_to_OCT2(PCO_P_PCSCF_ADDR)) {
+ proto_list_resp := proto_list_resp & { valueof(ts_GTP2C_PCO_P_PCSCF_IPv6(f_inet_addr(mp_s2b_pcscf_ipv6))) };
+ }
+ case else {
+ log("Ignoring unknown PCO Protocol ID: ", proto_req);
+ }
+ }
+ }
+
+ return ts_GTP2C_APCO(apco_req.instance, proto_list_resp);
+}
+
+private function f_EPDG_ConnHdlr_parse_CreateSessionReq(PDU_GTPCv2 rx_msg) runs on EPDG_ConnHdlr {
+ var BearerContextIEs rx_bctx_ies;
+ var FullyQualifiedTEID rx_fteid_gtpu;
+
+ /* Parse TEIC and Bearer EBI and TEID and store it in g_pars */
+ g_pars.teic_remote := rx_msg.gtpcv2_pdu.createSessionRequest.fullyQualifiedTEID[0].tEID_GRE_Key;
+ rx_bctx_ies := rx_msg.gtpcv2_pdu.createSessionRequest.bearerContextGrouped[0].bearerContextIEs;
+ g_pars.bearer.ebi := rx_bctx_ies.ePS_Bearer_ID.ePS_Bearer_ID_Value;
+
+ rx_fteid_gtpu := rx_bctx_ies.fullyQualifiedTEID[0];
+ g_pars.bearer.teid_remote := rx_fteid_gtpu.tEID_GRE_Key;
+ if (rx_fteid_gtpu.v4_Flag == '1'B) {
+ g_pars.bearer.gtpu_addr_remote := f_inet_ntoa(rx_fteid_gtpu.iPv4_Address);
+ }
+ /*if (rx_fteid_gtpu.v6_Flag == '1'B) {
+ g_gtpu6_remote := rx_fteid_gtpu.iPv6_Address;
+ }*/
+
+ /* allocate + register TEID-C on local side */
+ g_pars.teic_local := f_gtp2_allocate_teid();
+ g_pars.bearer.teid_local := g_pars.teic_local;
+}
+
+/* ePDG Creates session at the PGW. PGW sends Diameter s6b AAR + AAA. */
+private altstep as_GTP2C_CreateSession_success() runs on EPDG_ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_CreateSessionReq(g_pars.imsi, apco := f_exp_tr_GTP2C_APCO_in_CreateSessionReq())) -> value rx_msg {
+ f_EPDG_ConnHdlr_parse_CreateSessionReq(rx_msg);
+
+ /* Upon rx of CreateSession, emulate PGW asking the AAA server. */
+ f_S6b_AA_success();
+
+ fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S2b_PGW_GTPC, g_pars.teic_local, 1,
+ f_inet_addr(mp_s2b_local_ip), omit);
+ fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_PGW_GTPU, g_pars.bearer.teid_local, 4,
+ f_inet_addr(mp_s2b_local_ip), omit);
+ paa := ts_GTP2C_PdnAddrAlloc_v4(f_inet_addr(g_pars.ue_ip));
+ bctx_ies := ts_GTP2C_BcContextIE(ebi := g_pars.bearer.ebi,
+ teid_list := { fteid_u_ie },
+ qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0),
+ charging_id := ts_GTP2C_ChargingID(g_pars.teic_local));
+ GTP2.send(ts_GTP2C_CreateSessionResp(g_pars.teic_remote, rx_msg.sequenceNumber,
+ Request_accepted,
+ { fteid_c_ie }, paa,
+ { ts_GTP2C_BcGrouped(bctx_ies) },
+ f_GTPv2C_gen_APCO_response(rx_msg.gtpcv2_pdu.createSessionRequest.aPCO) ));
+ setverdict(pass);
+ }
+ [] GTP2.receive(PDU_GTPCv2:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP2C msg rx: ", rx_msg));
+ }
+}
+
+/* ePDG Creates session at the PGW. PGW sends Diameter s6b AAR + AAA. */
+private altstep as_GTP2C_CreateSession_error(GTP2C_Cause resp_cause, boolean do_s6b_aar := false) runs on EPDG_ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_CreateSessionReq(g_pars.imsi, apco := f_exp_tr_GTP2C_APCO_in_CreateSessionReq())) -> value rx_msg {
+ f_EPDG_ConnHdlr_parse_CreateSessionReq(rx_msg);
+
+ /* Upon rx of CreateSession, emulate PGW asking the AAA server. */
+ if (do_s6b_aar) {
+ f_S6b_AA_success();
+ }
+
+ fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S2b_PGW_GTPC, g_pars.teic_local, 1,
+ f_inet_addr(mp_s2b_local_ip), omit);
+ fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_PGW_GTPU, g_pars.bearer.teid_local, 4,
+ f_inet_addr(mp_s2b_local_ip), omit);
+ GTP2.send(ts_GTP2C_CreateSessionResp(g_pars.teic_remote, rx_msg.sequenceNumber,
+ resp_cause));
+ setverdict(pass);
+ }
+ [] GTP2.receive(PDU_GTPCv2:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP2C msg rx: ", rx_msg));
+ }
+}
+
+/* ePDG Deletes session at the PGW. PGW sends Diameter s6b AAR + AAA. */
+private altstep as_GTP2C_DeleteSession_success(boolean do_s6b_st_proc := true) runs on EPDG_ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var BearerContextIEs rx_bctx_ies;
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_DeleteSessionReq(g_pars.teic_local)) -> value rx_msg {
+ if (do_s6b_st_proc) {
+ /* Upon rx of DeleteSession, emulate PGW requesting the AAA server for Sesssion Termination. */
+ f_S6b_ST_success();
+ }
+
+ GTP2.send(ts_GTP2C_DeleteSessionResp(g_pars.teic_remote,
+ rx_msg.sequenceNumber,
+ Request_accepted));
+ setverdict(pass);
+ }
+ [] GTP2.receive(PDU_GTPCv2:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP2C msg rx: ", rx_msg));
+ }
+}
+
+/* Expect CreateBearerResponse */
+private altstep as_GTP2C_CreateBearer_success() runs on EPDG_ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+
+ [] GTP2.receive(tr_GTP2C_CreateBearerResp(g_pars.teic_local)) -> value rx_msg {
+ setverdict(pass);
+ }
+ [] GTP2.receive(PDU_GTPCv2:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP2C msg rx: ", rx_msg));
+ }
+}
+private function f_GTP2C_CreateBearer_success(uint4_t dedicated_bearer_id := 6) runs on EPDG_ConnHdlr {
+
+ var template (value) FullyQualifiedTEID fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S2bU_ePDG_GTPU, g_pars.bearer.teid_local, dedicated_bearer_id,
+ f_inet_addr(mp_s2b_local_ip), omit);
+ var template (value) FullyQualifiedTEID_List teid_list := { fteid_u_ie };
+
+ var template (value) FullyQualifiedPDN_ConnectionSetID pgw_fq_csid := ts_GTP2C_FQCSID_IPv4(f_inet_addr(mp_s2b_local_ip), int2oct(dedicated_bearer_id, 2));
+ var template (value) FullyQualifiedPDN_ConnectionSetID_List csid_list := { pgw_fq_csid };
+
+ var template (value) BearerContextGrouped_List bcg_list := {
+ ts_GTP2C_BcGrouped({
+ ePS_Bearer_ID := ts_GTP2C_EpsBearerId(dedicated_bearer_id),
+ cause := omit,
+ ePS_Bearer_TFT := omit,
+ fullyQualifiedTEID := teid_list,
+ bearerLevel_QoS := ts_GTP2C_BearerQos('09'O, 0,0,0,0),
+ chargingID := ts_GTP2C_ChargingID(f_rnd_octstring(4)),
+ bearerFlags := omit,
+ transactionIdentifier := omit,
+ protocolConfigOptions := omit,
+ rAN_NASCause := omit,
+ additionalProtocolConfigOptions := omit,
+ extendedProtocolConfigOptions := omit
+ })
+ };
+ GTP2.send(ts_GTP2C_CreateBearerReq(g_pars.teic_remote, omit, g_pars.bearer.ebi,
+ dedicated_bearer_id, bcg_list, csid_list));
+ as_GTP2C_CreateBearer_success();
+}
+
+/* Expect DeleteBearerResponse */
+private altstep as_GTP2C_DeleteBearer_success() runs on EPDG_ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var template (value) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+
+ [] GTP2.receive(tr_GTP2C_DeleteBearerResp(g_pars.teic_local)) -> value rx_msg {
+ setverdict(pass);
+ }
+ [] GTP2.receive(PDU_GTPCv2:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP2C msg rx: ", rx_msg));
+ }
+}
+private function f_GTP2C_DeleteBearer_success() runs on EPDG_ConnHdlr {
+ var integer proc_trans_id := 3;
+ GTP2.send(ts_GTP2C_DeleteBearerReq(g_pars.teic_remote, proc_trans_id, g_pars.bearer.ebi, Access_changed_from_Non_3GPP_to_3GPP));
+ as_GSUP_CancelLocation_success();
+ as_GTP2C_DeleteBearer_success();
+}
+
+private template (value) Gtp1uPeer ts_GtpPeerU(octetstring ip) := {
+ connId := 1,
+ remName := f_inet_ntoa(ip),
+ remPort := GTP1U_PORT
+}
+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, 0 /*seq*/, 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));
+}
+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 {
+ /*TODO: verify gtpu txseq:
+ if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
+ setverdict(fail);
+ stop;
+ }
+ */
+ var octetstring gpdu := rx_msg.gtpu.gtpu_IEs.g_PDU_IEs.data;
+ var IPv4_packet ip4 := f_IPv4_dec(gpdu);
+ if (ip4.header.ver != 4) {
+ repeat;
+ }
+ var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload);
+ if (not match(icmp4, expected)) {
+ repeat;
+ }
+ }
+ [] GTP2.receive(Gtp1uUnitdata:?) -> value rx_msg {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GTP msg rx: ", rx_msg));
+ }
+}
+
+/************
+ * GSUP CEAI
+ ************/
+
+private function f_GSUP_tx_SAI_REQ(boolean req_resync := false) runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ var template (value) GSUP_IEs pdp_info;
+ pdp_info := { ts_GSUP_IE_PDP_CONTEXT_ID('00'O),
+ ts_GSUP_IE_PDP_ADDRESS(ts_EuaIPv4Dyn),
+ ts_GSUP_IE_APN(f_enc_dns_hostname(g_pars.apn)) };
+ if (req_resync) {
+ GSUP.send(ts_GSUP_SAI_REQ_PDP_INFO_UMTS_AKA_RESYNC(
+ g_pars.imsi, pdp_info,
+ g_pars.vec.auts, g_pars.vec.rand));
+ } else {
+ GSUP.send(ts_GSUP_SAI_REQ_PDP_INFO(g_pars.imsi, pdp_info));
+ }
+}
+
+private altstep as_GSUP_rx_SAI_RES() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ var template (present) GSUP_IE auth_tuple_ie := tr_GSUP_IE_AuthTuple3G(
+ g_pars.vec.rand,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.rand & g_pars.vec.auts);
+
+ [] GSUP.receive(tr_GSUP_SAI_RES(g_pars.imsi, auth_tuple_ie)) -> value rx_gsup {
+ }
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+}
+
+private altstep as_GSUP_rx_SAI_ERR(template (present) integer cause := ?) runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+
+ [] GSUP.receive(tr_GSUP_SAI_ERR(g_pars.imsi, cause)) -> value rx_gsup {
+ }
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+}
+
+private altstep as_GSUP_rx_CL_REQ(template GSUP_CancelType ctype := omit) runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+
+ [] GSUP.receive(tr_GSUP_CL_REQ(g_pars.imsi, dom := *, ctype := ctype)) -> value rx_gsup {
+ }
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+}
+
+private function f_GSUP_tx_CL_RES() runs on EPDG_ConnHdlr {
+ GSUP.send(ts_GSUP_CL_RES(g_pars.imsi));
+}
+
+/* GSUP AuthInfo Req + Resp, triggers SWx MAR + MAA. */
+private function f_GSUP_AI_success(boolean req_resync := false) runs on EPDG_ConnHdlr {
+ f_GSUP_tx_SAI_REQ(req_resync);
+ as_DIA_SWx_MA_success(req_resync);
+ as_GSUP_rx_SAI_RES();
+ setverdict(pass);
+}
+
+/* GSUP LU Req + Resp, triggers SWx SAR + SAA (Server Assignment). */
+private function f_GSUP_LU_success() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ var template octetstring destination_name := *;
+ GSUP.send(ts_GSUP_UL_REQ(g_pars.imsi));
+ as_DIA_SWx_SA_success(REGISTRATION);
+ /* Expect a positive response back to the translator */
+ alt {
+ [] GSUP.receive(tr_GSUP_UL_RES(g_pars.imsi, destination_name));
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+ }
+ setverdict(pass);
+}
+
+/* GSUP TunnelEPDG Tunnel Req + Resp, triggers S2b CreateSession Req + Response. */
+private function f_GSUP_EPDGTunnel_success() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ var template (value) PCO_DATA pco := PCO_Types.ts_PCO({ ts_PCO_P_DNS_IPv4, ts_PCO_P_PCSCF_IPv4 });
+ GSUP.send(ts_GSUP_EPDGTunnel_REQ(g_pars.imsi, pco));
+ as_GTP2C_CreateSession_success();
+ /* Expect a positive response back to the translator; */
+ var template (present) GSUP_IEs exp_pdp_info := {
+ tr_GSUP_IE_PDP_CONTEXT_ID(?),
+ tr_GSUP_IE_PDP_ADDRESS(tr_GSUP_PDP_Address_IPv4(f_inet_addr(g_pars.ue_ip))),
+ tr_GSUP_IE_APN(f_enc_dns_hostname(g_pars.apn)),
+ tr_GSUP_IE_PDP_QOS(?),
+ tr_GSUP_IE_Charging_Characteristics(?)
+ };
+ var template (present) PCO_DATA exp_pco := PCO_Types.tr_PCO({
+ tr_PCO_P_DNS_IPv4(f_inet_addr(mp_s2b_dns_ipv4)),
+ tr_PCO_P_PCSCF_IPv4(f_inet_addr(mp_s2b_pcscf_ipv4))
+ });
+ /* TODO: check for v6 and v4v6 types ^ */
+ alt {
+ [] GSUP.receive(tr_GSUP_EPDGTunnel_RES(g_pars.imsi, exp_pdp_info));
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+ }
+ setverdict(pass);
+}
+
+/* GSUP TunnelEPDG Tunnel Req + Resp, triggers S2b CreateSession Req + Response (rejected). */
+private function f_GSUP_EPDGTunnel_error() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ var template (value) PCO_DATA pco := PCO_Types.ts_PCO({ ts_PCO_P_DNS_IPv4, ts_PCO_P_PCSCF_IPv4 });
+ GSUP.send(ts_GSUP_EPDGTunnel_REQ(g_pars.imsi, pco));
+ as_GTP2C_CreateSession_error(APN_access_denied__no_subscription);
+ alt {
+ [] GSUP.receive(tr_GSUP_EPDGTunnel_ERR(g_pars.imsi));
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+ }
+ setverdict(pass);
+}
+
+/* GSUP Purge MS Req + Resp, triggers S2b DeleteSession Req + Response. */
+private function f_GSUP_PurgeMS_success() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+ GSUP.send(ts_GSUP_PURGE_MS_REQ(g_pars.imsi, OSMO_GSUP_CN_DOMAIN_PS));
+ as_GTP2C_DeleteSession_success();
+ /* ePDG internally sends STR to its AAA-Server. Since all sessions
+ become inactive, AAA-Server sends SAR(USER_DEREGISTRATION) to HSS: */
+
+ /* Expect a positive response back to the translator; */
+ as_DIA_SWx_SA_success(USER_DEREGISTRATION);
+ alt {
+ [] GSUP.receive(tr_GSUP_PURGE_MS_RES(g_pars.imsi));
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+ }
+ setverdict(pass);
+}
+
+/* Expect CancelLocationReq */
+private altstep as_GSUP_CancelLocation_success() runs on EPDG_ConnHdlr {
+ var GSUP_PDU rx_gsup;
+
+ [] GSUP.receive(tr_GSUP_CL_REQ(g_pars.imsi)) -> value rx_gsup {
+ GSUP.send(ts_GSUP_CL_RES(g_pars.imsi));
+ }
+ [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup));
+ }
+}
+
+private function f_initial_attach() runs on EPDG_ConnHdlr {
+ f_GSUP_AI_success();
+ f_GSUP_LU_success();
+ f_GSUP_EPDGTunnel_success();
+}
+
+private function f_TC_authinfo_normal(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ f_GSUP_PurgeMS_success();
+}
+testcase TC_authinfo_normal() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_normal), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_authinfo_MAA_unknown_user(charstring id) runs on EPDG_ConnHdlr {
+ var PDU_DIAMETER rx_dia;
+ var DIAMETER_ExperimentalResultcode exp_result_code := DIAMETER_ERROR_USER_UNKNOWN;
+ f_GSUP_tx_SAI_REQ();
+
+ SWx.receive(tr_DIA_SWx_MAR(g_pars.imsi)) -> value rx_dia;
+ f_DIA_SWx_tx_MAA_error(rx_dia,
+ ts_AVP_ExperimentalResult(vendor_id_3GPP,
+ int2oct(enum2int(exp_result_code), 4)));
+ /* cause 2 = IMSI_UNKNOWN */
+ as_GSUP_rx_SAI_ERR(2);
+}
+testcase TC_authinfo_MAA_unknown_user() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_MAA_unknown_user), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* Emulate UE doing MAR+MAA, then repeating and continuing. */
+private function f_TC_authinfo_twice(charstring id) runs on EPDG_ConnHdlr {
+ f_GSUP_AI_success();
+ f_initial_attach();
+}
+testcase TC_authinfo_twice() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_twice), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* Emulate UE doing MAR+MAA, then UE requesting again due to resync needed */
+private function f_TC_authinfo_fail_resync(charstring id) runs on EPDG_ConnHdlr {
+ f_GSUP_AI_success(false);
+ f_GSUP_AI_success(true);
+ f_GSUP_LU_success();
+ f_GSUP_EPDGTunnel_success();
+ f_GSUP_PurgeMS_success();
+}
+testcase TC_authinfo_fail_resync() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_authinfo_fail_resync), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_ho_lte_to_wifi(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ /* Whenever UE comes from 3GPP, PGW may activate a dedicated S2b bearer
+ * and notify ePDG with a Create Bearer Request */
+ f_GTP2C_CreateBearer_success();
+ f_GSUP_PurgeMS_success();
+}
+testcase TC_ho_lte_to_wifi() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_ho_lte_to_wifi), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_ho_wifi_to_lte(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ /* Whenever UE goes back to 3GPP, PGW will notify ePDG with a Delete Bearer Request
+ * cause="Access changed from non-3gpp to 3gpp" */
+ f_GTP2C_DeleteBearer_success();
+}
+testcase TC_ho_wifi_to_lte() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_ho_wifi_to_lte), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_s2b_CreateSession_rejected(charstring id) runs on EPDG_ConnHdlr {
+ f_GSUP_AI_success();
+ f_GSUP_LU_success();
+ f_GSUP_EPDGTunnel_error();
+}
+testcase TC_s2b_CreateSession_rejected() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_s2b_CreateSession_rejected), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/* 3GPP TS 29.273 Network Initiated De-Registration by HSS, Administrative */
+private function f_TC_hss_initiated_deregister_new_server_assigned(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ /* Procedure should be performed properly: */
+ f_DIA_SWx_RT(NEW_SERVER_ASSIGNED, tr_AVP_ResultCode(DIAMETER_SUCCESS));
+ /* Subscriber was already removed, it should fail if requested again: */
+ var DIAMETER_ts29_229_ExperimentalResultcode erc := DIAMETER_ERROR_USER_UNKNOWN;
+ f_DIA_SWx_RT(NEW_SERVER_ASSIGNED, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(erc), 4)));
+}
+testcase TC_hss_initiated_deregister_new_server_assigned() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_hss_initiated_deregister_new_server_assigned), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_hss_initiated_deregister_permanent_termination(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ /* Procedure should be performed properly: */
+ f_DIA_SWx_RT(PERMANENT_TERMINATION, tr_AVP_ResultCode(DIAMETER_SUCCESS));
+ /* Subscriber was already removed, it should fail if requested again: */
+ var DIAMETER_ts29_229_ExperimentalResultcode erc := DIAMETER_ERROR_USER_UNKNOWN;
+ f_DIA_SWx_RT(PERMANENT_TERMINATION, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(erc), 4)),
+ exp_aaa_proc := false);
+}
+testcase TC_hss_initiated_deregister_permanent_termination() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_hss_initiated_deregister_permanent_termination), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/*
+ * 3GPP TS 29.273 8.1.2.3 HSS Initiated Update of User Profile
+ * 3GPP TS 29.273 8.2.2.2 HSS Initiated Update of User Profile Procedure
+ */
+private function f_TC_hss_initiated_update_user_profile(charstring id) runs on EPDG_ConnHdlr {
+ f_initial_attach();
+ /* Procedure should be performed properly: */
+ f_DIA_SWx_PP(tr_AVP_ResultCode(DIAMETER_SUCCESS));
+}
+testcase TC_hss_initiated_update_user_profile() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_hss_initiated_update_user_profile), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+/*
+ * Same as TC_hss_initiated_update_user_profile_unknown, but without registering
+ * subscriber first, so expect DIAMETER_ERROR_USER_UNKNOWN in answer.
+ */
+private function f_TC_hss_initiated_update_user_profile_unknown(charstring id) runs on EPDG_ConnHdlr {
+ var DIAMETER_ts29_229_ExperimentalResultcode erc := DIAMETER_ERROR_USER_UNKNOWN;
+ f_DIA_SWx_PP(tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(erc), 4)),
+ exp_aaa_proc := false);
+}
+testcase TC_hss_initiated_update_user_profile_unknown() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_hss_initiated_update_user_profile_unknown), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+private function f_TC_concurrent_ues(charstring id) runs on EPDG_ConnHdlr {
+ COORD.send(COORD_CMD_READY);
+ COORD.receive(COORD_CMD_START);
+ f_initial_attach();
+ COORD.send(COORD_CMD_ATTACHED);
+ COORD.receive(COORD_CMD_STOP);
+ f_GSUP_PurgeMS_success();
+}
+private function f_TC_concurrent_ues_MTC(integer num_ues) runs on MTC_CT {
+ var EPDG_ConnHdlrList vc_conn_list := {};
+ var EPDG_ConnHdlr vc_conn;
+ f_init(t_guard := 100.0);
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ var EPDG_ConnHdlrPars pars := f_init_pars(i);
+ vc_conn := f_start_handler(refers(f_TC_concurrent_ues), pars);
+ vc_conn_list := vc_conn_list & { vc_conn };
+ }
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ COORD.receive(COORD_CMD_READY) from vc_conn_list[i];
+ }
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ COORD.send(COORD_CMD_START) to vc_conn_list[i];
+ f_sleep(0.1);
+ }
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ COORD.receive(COORD_CMD_ATTACHED) from vc_conn_list[i];
+ }
+
+ log("All attached!");
+ f_sleep(1.0);
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ COORD.send(COORD_CMD_STOP) to vc_conn_list[i];
+ }
+
+ for (var integer i := 0; i < num_ues; i := i + 1) {
+ vc_conn_list[i].done;
+ }
+
+ setverdict(pass);
+}
+testcase TC_concurrent_ues2() runs on MTC_CT {
+ f_TC_concurrent_ues_MTC(2)
+}
+testcase TC_concurrent_ues100() runs on MTC_CT {
+ f_TC_concurrent_ues_MTC(100)
+}
+
+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_echo_ping_pong(seq_nr := 0);
+ /* Send one again, to validate it works several times: */
+ f_GTP1U_echo_ping_pong(seq_nr := 1);
+ f_GSUP_PurgeMS_success();
+}
+testcase TC_upf_echo_req() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_upf_echo_req), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+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);
+ 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));
+ f_GSUP_PurgeMS_success();
+}
+testcase TC_mt_ipv4_echo_req() runs on MTC_CT {
+ var EPDG_ConnHdlrPars pars := f_init_pars();
+ var EPDG_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_mt_ipv4_echo_req), pars);
+ vc_conn.done;
+ setverdict(pass);
+}
+
+control {
+ execute ( TC_authinfo_normal() );
+ execute ( TC_authinfo_MAA_unknown_user() );
+ execute ( TC_authinfo_twice() );
+ execute ( TC_authinfo_fail_resync() );
+ execute ( TC_ho_lte_to_wifi() );
+ execute ( TC_ho_wifi_to_lte() );
+ execute ( TC_s2b_CreateSession_rejected() );
+ execute ( TC_hss_initiated_deregister_new_server_assigned() );
+ execute ( TC_hss_initiated_deregister_permanent_termination() );
+ execute ( TC_hss_initiated_update_user_profile() );
+ execute ( TC_hss_initiated_update_user_profile_unknown() );
+ execute ( TC_concurrent_ues2() );
+ execute ( TC_concurrent_ues100() );
+ execute ( TC_upf_echo_req() );
+ execute ( TC_mt_ipv4_echo_req() );
+}
+
+}
diff --git a/epdg/expected-results.xml b/epdg/expected-results.xml
new file mode 100644
index 00000000..83155cd6
--- /dev/null
+++ b/epdg/expected-results.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<testsuite name='EPDG_Tests' tests='11' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='EPDG_Tests' name='TC_authinfo_normal' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_authinfo_MAA_unknown_user' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_authinfo_twice' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_authinfo_fail_resync' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_ho_lte_to_wifi' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_ho_wifi_to_lte' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_s2b_CreateSession_rejected' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_hss_initiated_deregister_new_server_assigned' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_hss_initiated_deregister_permanent_termination' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_hss_initiated_update_user_profile' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_hss_initiated_update_user_profile_unknown' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_concurrent_ues2' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_concurrent_ues100' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_upf_echo_req' time='MASKED'/>
+ <testcase classname='EPDG_Tests' name='TC_mt_ipv4_echo_req' time='MASKED'/>
+</testsuite>
diff --git a/epdg/gen_links.sh b/epdg/gen_links.sh
new file mode 100755
index 00000000..55e449f0
--- /dev/null
+++ b/epdg/gen_links.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit 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.IP/src
+FILES="IP_EncDec.cc IP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.ICMP/src
+FILES="ICMP_EncDec.cc ICMP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src
+FILES="DIAMETER_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_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.GTP_v13.5.0/src
+FILES="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=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="Osmocom_CTRL_Types.ttcn "
+FILES+="L3_Common.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_229_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn DIAMETER_ts29_273_Templates.ttcn "
+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+="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 "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/epdg/regen_makefile.sh b/epdg/regen_makefile.sh
new file mode 100755
index 00000000..9aa83b4c
--- /dev/null
+++ b/epdg/regen_makefile.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+NAME=EPDG_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ IP_EncDec.cc
+ ICMP_EncDec.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ DIAMETER_EncDec.cc
+ DIAMETER_CodecPort_CtrlFunctDef.cc
+ UECUPS_CodecPort_CtrlFunctDef.cc
+ GTPU_EncDec.cc
+ GTPv1U_CodecPort_CtrlFunctDef.cc
+ GTPv2_CodecPort_CtrlFunctDef.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_GSUP
+"
+
+../regen-makefile.sh EPDG_Tests.ttcn $FILES
diff --git a/fr-net/FRNET_Tests.cfg b/fr-net/FRNET_Tests.cfg
new file mode 100644
index 00000000..555b260e
--- /dev/null
+++ b/fr-net/FRNET_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# We cannot include Common.cfg, as this includes the LoggerPlugins configuration
+# for junit-xml generation. However, we don't want to generate any junit-xml,
+# as FRNET_Tests really is not a test suite, but just a stub against which FR_Tests
+# can execute
+# testsuite specific configuration, not expected to change
+"./FRNET_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+FRNET_Tests.control
diff --git a/fr-net/FRNET_Tests.default b/fr-net/FRNET_Tests.default
new file mode 100644
index 00000000..9ec4a0c5
--- /dev/null
+++ b/fr-net/FRNET_Tests.default
@@ -0,0 +1,22 @@
+[ORDERED_INCLUDE]
+# We cannot include Common.cfg, as this includes the LoggerPlugins configuration
+# for junit-xml generation. However, we don't want to generate any junit-xml,
+# as FRNET_Tests really is not a test suite, but just a stub against which FR_Tests
+# can execute
+
+[LOGGING]
+LogFile := "%e-%c-%h-%r.%s"
+AppendFile := Yes;
+SourceInfoFormat := Single;
+LogSourceInfo := Yes;
+FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+ConsoleMask := ERROR | WARNING | TESTCASE | USER | VERDICTOP;
+
+[MODULE_PARAMETERS]
+
+[TESTPORT_PARAMETERS]
+*.FR.sleep_on_enobufs := "2000" # 2ms
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
diff --git a/fr-net/FRNET_Tests.ttcn b/fr-net/FRNET_Tests.ttcn
new file mode 100644
index 00000000..0a6af591
--- /dev/null
+++ b/fr-net/FRNET_Tests.ttcn
@@ -0,0 +1,142 @@
+module FRNET_Tests {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+
+import from NS_Emulation all;
+import from BSSGP_Emulation all;
+import from LLC_Types all;
+import from LLC_Templates all;
+
+modulepar {
+ integer mp_num_bvc := 10;
+ NSConfigurations mp_nsconfig := {
+ {
+ nsei := 123,
+ role_sgsn := true,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlcnet1",
+ dlci := 21
+ }
+ },
+ nsvci := 101
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlcnet2",
+ dlci := 22
+ }
+ },
+ nsvci := 102
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlcnet3",
+ dlci := 23
+ }
+ },
+ nsvci := 103
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlcnet4",
+ dlci := 24
+ }
+ },
+ nsvci := 104
+ }
+ }
+ }
+ };
+}
+
+type record GbInstance {
+ NS_CT vc_NS,
+ BSSGP_CT vc_BSSGP,
+ BssgpConfig cfg
+};
+
+type record of GbInstance GbInstances;
+type record of NSConfiguration NSConfigurations;
+type record of BssgpCellId BssgpCellIds;
+
+type component test_CT {
+ var GbInstances g_gb;
+};
+
+
+private function CreateCallback(BssgpBvci bvci, BssgpCellId cell_id, OCT4 tlli, BssgpDecoded dec) runs on BSSGP_BVC_CT {
+ if (ischosen(dec.bssgp.pDU_BSSGP_UL_UNITDATA)) {
+ var PDU_LLC llc_rx := dec_PDU_LLC(dec.bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU)
+ select (llc_rx) {
+ case (tr_LLC_UI(sapi := '0010'B)) {
+ //log("BVCI=", bvci, ", CellId=", cell_id, ", TLLI=", tlli, ", BSSGP=", dec);
+ /* mirror back as DL-UNITDATA */
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, dec.bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU), bvci, oct2int(tlli)));
+ }
+ case else {
+ /* simply ignore any inbound traffic for now */
+ }
+ }
+ }
+}
+
+private function f_init_gb(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
+ var charstring id_idx := id & int2str(offset);
+ gb.vc_NS := NS_CT.create(id_idx & "-NSemu") alive;
+ gb.vc_BSSGP := BSSGP_CT.create(id_idx & "-BSSGPemu") alive;
+ connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
+ gb.vc_NS.start(NSStart(mp_nsconfig[offset], id_idx));
+ gb.vc_BSSGP.start(BssgpStart(gb.cfg, testcasename()));
+}
+
+function f_gen_bvc(integer base, integer idx) return BssgpBvcConfig {
+ var BssgpBvcConfig bvc := {
+ bvci := base + 100 + idx,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := '262F42'H,
+ lac := base + 300 + idx
+ },
+ rac := 1
+ },
+ cell_id := base + 600 + idx
+ },
+ depth := BSSGP_DECODE_DEPTH_LLC,
+ create_cb := refers(CreateCallback)
+ };
+ return bvc;
+}
+
+testcase TC_foo() runs on test_CT {
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig); i := i+1) {
+ g_gb[i].cfg := {
+ nsei := mp_nsconfig[i].nsei,
+ sgsn_role := true,
+ bvc := { }
+ };
+ /* create 'mp_num_bvc' number of BVCs */
+ for (var integer j := 0; j < mp_num_bvc; j := j+1) {
+ g_gb[i].cfg.bvc := g_gb[i].cfg.bvc & { f_gen_bvc(i * 1000, j) };
+ }
+ f_init_gb(g_gb[i], "gb", i);
+ }
+
+ while (true) {
+ f_sleep(100.0);
+ }
+}
+
+control {
+ execute( TC_foo() );
+}
+
+
+}
diff --git a/fr-net/gen_links.sh b/fr-net/gen_links.sh
new file mode 100755
index 00000000..413676c3
--- /dev/null
+++ b/fr-net/gen_links.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+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.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.LLC_v7.1.0/src
+FILES="LLC_EncDec.cc LLC_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SNDCP_v7.0.0/src
+FILES="SNDCP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.AF_PACKET/src
+FILES="AF_PACKET_PT.cc AF_PACKET_PT.hh AF_PACKET_PortType.ttcn AF_PACKET_PortTypes.ttcn "
+FILES+="FrameRelay_Types.ttcn FrameRelay_CodecPort.ttcn FrameRelay_Emulation.ttcn Q931_Types.ttcn Q933_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn Osmocom_Types.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Provider_FR.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
+FILES+="LLC_Templates.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/fr-net/regen_makefile.sh b/fr-net/regen_makefile.sh
new file mode 100755
index 00000000..89eccd33
--- /dev/null
+++ b/fr-net/regen_makefile.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+NAME=FRNET_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ AF_PACKET_PT.cc
+ BSSGP_EncDec.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DNS_EMULATION_FR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/fr/FR_Tests.cfg b/fr/FR_Tests.cfg
new file mode 100644
index 00000000..9a97c3a5
--- /dev/null
+++ b/fr/FR_Tests.cfg
@@ -0,0 +1,16 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./FR_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+FR_Tests.control
diff --git a/fr/FR_Tests.default b/fr/FR_Tests.default
new file mode 100644
index 00000000..14c32b1f
--- /dev/null
+++ b/fr/FR_Tests.default
@@ -0,0 +1,16 @@
+[DEFINE]
+TCPDUMP_START := $TTCN3_HACKS_PATH"/ttcn3-dumpcap-start.sh"
+TCPDUMP_STOP := $TTCN3_HACKS_PATH"/ttcn3-dumpcap-stop.sh"
+
+[LOGGING]
+#*.FileMask := LOG_ALL
+ConsoleMask := ERROR | WARNING | TESTCASE | USER
+
+[MODULE_PARAMETERS]
+
+[TESTPORT_PARAMETERS]
+*.FR.sleep_on_enobufs := "2000"
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
diff --git a/fr/FR_Tests.ttcn b/fr/FR_Tests.ttcn
new file mode 100644
index 00000000..65029c1b
--- /dev/null
+++ b/fr/FR_Tests.ttcn
@@ -0,0 +1,320 @@
+module FR_Tests {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+
+import from NS_Emulation all;
+import from BSSGP_Emulation all;
+import from LLC_Types all;
+import from LLC_Templates all;
+
+modulepar {
+ /* NS transport layer MTU (NS header and anything after it) */
+ integer mp_ns_mtu := 1500;
+ /* number of BVCs to bring up in one Gb instance */
+ integer mp_num_bvc := 10;
+ /* number of UEs to start in each PTP BVC */
+ integer mp_num_ue_in_bvc := 10;
+ /* NS configurations; one per NSE; each with any number of NSVC */
+ NSConfigurations mp_nsconfig := {
+ {
+ nsei := 123,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlc1",
+ dlci := 21
+ }
+ },
+ nsvci := 101
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc2",
+ dlci := 22
+ }
+ },
+ nsvci := 102
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc3",
+ dlci := 23
+ }
+ },
+ nsvci := 103
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc4",
+ dlci := 24
+ }
+ },
+ nsvci := 104
+ }
+ }
+ }
+ };
+}
+
+/* 4 bytes NS-UNITDATA,
+ * >= 12 Bytes DL-UNITDATA or 18 bytes BSSGP UL-UNITDATA
+ * 3 bytes LLC UI header
+ * 3 bytes LLC FCS
+ * <= 3 bytes optional padding
+ * --> at least 31 bytes required
+ */
+const integer c_LLC_BSSGP_NS_overhead := 40;
+
+type record GbInstance {
+ NS_CT vc_NS,
+ BSSGP_CT vc_BSSGP,
+ BssgpConfig cfg
+};
+
+type record of GbInstance GbInstances;
+type record of NSConfiguration NSConfigurations;
+type record of BssgpCellId BssgpCellIds;
+
+
+type component test_CT {
+ var GbInstances g_gb;
+ port BSSGP_CT_PROC_PT BSSGP_PROC[16];
+};
+
+/* initialize one Gb interface */
+private function f_init_gb(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
+ var charstring id_idx := id & int2str(offset);
+ gb.vc_NS := NS_CT.create(id_idx & "-NSemu") alive;
+ gb.vc_BSSGP := BSSGP_CT.create(id_idx & "-BSSGPemu") alive;
+ connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
+ gb.vc_NS.start(NSStart(mp_nsconfig[offset], id_idx));
+ connect(self:BSSGP_PROC[offset], gb.vc_BSSGP:PROC);
+ gb.vc_BSSGP.start(BssgpStart(gb.cfg, testcasename()));
+}
+
+/* generate a BVC dynamically, using distinct number ranges for BVCI, CID, LAC, ... */
+private function f_gen_bvc(integer base, integer idx) return BssgpBvcConfig {
+ var BssgpBvcConfig bvc := {
+ bvci := base + 100 + idx,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := '262F42'H,
+ lac := base + 300 + idx
+ },
+ rac := 1
+ },
+ cell_id := base + 600 + idx
+ },
+ depth := BSSGP_DECODE_DEPTH_LLC,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ };
+ return bvc;
+}
+
+/***********************************************************************
+ * UE simulation component
+ ***********************************************************************/
+
+type component UE_CT extends BSSGP_Client_CT {
+ var UE_Pars g_pars;
+ timer g_Tguard;
+ var LLC_Entities llc;
+}
+type record of UE_CT ro_ue;
+
+type record UE_Pars {
+ hexstring imsi,
+ OCT4 tlli,
+ float tguard,
+ BssgpBvci bvci,
+ BssgpCellId cell_id
+};
+
+type function void_fn(charstring id) runs on UE_CT;
+
+private altstep as_ue_tguard() runs on UE_CT {
+[] g_Tguard.timeout {
+ setverdict(fail, "Tguard timeout after ", g_pars.tguard);
+ self.stop;
+ }
+}
+
+/* first function executed in UE_CT; creates LLC context, registers with BSSGP, starts Tguard */
+function f_handler_init(void_fn fn, charstring id, UE_Pars pars) runs on UE_CT {
+ g_pars := pars;
+ llc := f_llc_create(false);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli);
+ g_Tguard.start(g_pars.tguard);
+ activate(as_ue_tguard());
+
+ log(id, " Waiting for BVC-UNBLOCK");
+ timer T := 15.0;
+ T.start;
+ alt {
+ [] BSSGP[0].receive(BssgpStatusIndication:{*,?,BVC_S_UNBLOCKED}) { }
+ [] BSSGP[0].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, id, " Timeout waiting for BVC-UNBLOCK");
+ self.stop;
+ }
+ }
+
+ log (id, " Entering main loop");
+ fn.apply(id);
+ log (id, "Leaving main loop");
+ f_bssgp_client_unregister(g_pars.imsi);
+}
+
+/* start a single UE component; connect it to BSSGP */
+function f_start_ue(void_fn fn, charstring id, BssgpBvcConfig bvc, integer imsi_suffix, BSSGP_BVC_CT bvc_comp, float t_guard := 40.0)
+runs on test_CT return UE_CT
+{
+ var UE_CT ue_comp;
+ var UE_Pars ue_pars := {
+ imsi := f_gen_imsi(imsi_suffix),
+ tlli := f_gprs_tlli_random(),
+ tguard := t_guard,
+ bvci := bvc.bvci,
+ cell_id := bvc.cell_id
+ };
+
+ ue_comp := UE_CT.create(id);
+ connect(ue_comp:BSSGP[0], bvc_comp:BSSGP_SP);
+ connect(ue_comp:BSSGP_SIG[0], bvc_comp:BSSGP_SP_SIG);
+ connect(ue_comp:BSSGP_PROC[0], bvc_comp:BSSGP_PROC);
+ ue_comp.start(f_handler_init(fn, id, ue_pars));
+
+ return ue_comp;
+}
+
+
+/* main test case body function; start Gb instances, start UE_CTs on top; wait for termination */
+private function f_tc_body(void_fn ue_fn, integer ue_per_bvc := mp_num_ue_in_bvc,
+ float delay_between_ue := 0.005, float ue_tguard := 40.0) runs on test_CT {
+ var ro_ue ues := {};
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig); i := i+1) {
+ g_gb[i].cfg := {
+ nsei := mp_nsconfig[i].nsei,
+ sgsn_role := false,
+ bvc := { }
+ };
+ /* create 'mp_num_bvc' number of BVCs */
+ for (var integer j := 0; j < mp_num_bvc; j := j+1) {
+ g_gb[i].cfg.bvc := g_gb[i].cfg.bvc & { f_gen_bvc(i * 1000, j) };
+ }
+ log("Initializing Gb interface ", i, ": NSEI=", g_gb[i].cfg.nsei);
+ f_init_gb(g_gb[i], "gb", i);
+ }
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig); i := i+1) {
+ for (var integer j := 0; j < mp_num_bvc; j := j+1) {
+ var BSSGP_BVC_CT bvc_comp := f_bssgp_get_bvci_ct(g_gb[i].cfg.bvc[j].bvci, BSSGP_PROC[i]);
+ for (var integer k := 0; k < ue_per_bvc; k := k+1) {
+ var charstring id := "gb" & int2str(i) & "-bvc" & int2str(g_gb[i].cfg.bvc[j].bvci) & "-UEsim" & int2str(k);
+ var UE_CT ue;
+ ue := f_start_ue(ue_fn, id, g_gb[i].cfg.bvc[j], i*10000+j*100+k, bvc_comp,
+ue_tguard);
+ ues := ues & { ue };
+ /* a bit of staggering to ensure the timers above don't run all at the same time */
+ f_sleep(delay_between_ue);
+ /* FIXME: as the BSSGP emulation is already running, we must not
+ * take too long to start the UE components. If we do, the
+ * BVC_S_UNBLOCKED notification will arrive before the components
+ * all are running, meaning we never get that one :( */
+ }
+ }
+ }
+
+ /* wait for all UE components to terminate */
+ for (var integer i := 0; i < lengthof(ues); i := i + 1) {
+ ues[i].done;
+ }
+ setverdict(pass);
+}
+
+private function f_ul_ud(charstring id) runs on UE_CT
+{
+ for (var integer num_pkts := 0; num_pkts < 50; num_pkts := num_pkts + 1) {
+ var integer ran_index := 0;
+ //BSSGP[ran_index].send(ts_BSSGP_UL_UD(g_pars.tlli, g_pars.bssgp_cell_id[ran_index], llc_enc));
+ BSSGP[ran_index].send(ts_LLC_UI(f_rnd_octstring(512), '0000'B, '1'B, 0))
+ f_sleep(0.5);
+ /* 512 bytes + 32 bytes HDR every 0.5s (1088/s) means about 8704/s per UE */
+ /* at 100 UE that ends up about 870 kBps */
+ }
+}
+/* Generate uplink-unitdata traffic */
+testcase TC_ul_ud() runs on test_CT
+{
+ f_tc_body(refers(f_ul_ud));
+}
+
+
+/* test bring-up of all BVCs */
+private function f_pass(charstring id) runs on UE_CT
+{
+ setverdict(pass);
+}
+testcase TC_bvc_bringup() runs on test_CT
+{
+ f_tc_body(refers(f_pass), ue_per_bvc := 1, ue_tguard := 20.0);
+}
+
+
+private function f_ul2dl_ud(charstring id) runs on UE_CT
+{
+ var integer max_llc_payload_len := mp_ns_mtu - c_LLC_BSSGP_NS_overhead;
+
+ for (var integer num_pkts := 0; num_pkts < 50; num_pkts := num_pkts + 1) {
+ var integer ran_index := 0;
+ var template (value) PDU_LLC llc_tx;
+ var template (present) PDU_LLC llc_rx_exp;
+ var octetstring llc_payload := f_rnd_octstring_rnd_len(max_llc_payload_len);
+ var PDU_LLC llc_rx;
+ timer T := 5.0;
+
+ /* SAPI '0010'B is looped back by FRNET_Tests.ttcn */
+ llc_tx := ts_LLC_UI(llc_payload, '0010'B, '1'B, 0);
+ llc_rx_exp := llc_tx;
+ llc_rx_exp.pDU_LLC_UI.fCS := ?;
+
+ //BSSGP[ran_index].send(ts_BSSGP_UL_UD(g_pars.tlli, g_pars.cell_id, llc_enc));
+ BSSGP[ran_index].send(llc_tx);
+ T.start;
+ alt {
+ [] BSSGP[ran_index].receive(llc_rx_exp) -> value llc_rx { }
+ [] BSSGP[ran_index].receive(PDU_LLC:?) -> value llc_rx {
+ setverdict(fail, "Unexpected LLC: ", llc_rx);
+ break;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ", llc_rx_exp);
+ break;
+ }
+ }
+ //f_sleep(0.1);
+ /* 512 bytes + 32 bytes HDR every 0.5s (1088/s) means about 8704/s per UE */
+ /* at 100 UE that ends up about 870 kBps */
+ }
+}
+/* Generate uplink-unitdata traffic */
+testcase TC_ul2dl_ud() runs on test_CT
+{
+ f_tc_body(refers(f_ul2dl_ud), ue_tguard := 100.0);
+}
+
+
+control {
+ execute( TC_bvc_bringup() );
+ execute( TC_ul_ud() );
+ execute( TC_ul2dl_ud() );
+}
+
+}
diff --git a/fr/gen_links.sh b/fr/gen_links.sh
new file mode 100755
index 00000000..413676c3
--- /dev/null
+++ b/fr/gen_links.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+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.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.LLC_v7.1.0/src
+FILES="LLC_EncDec.cc LLC_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SNDCP_v7.0.0/src
+FILES="SNDCP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.AF_PACKET/src
+FILES="AF_PACKET_PT.cc AF_PACKET_PT.hh AF_PACKET_PortType.ttcn AF_PACKET_PortTypes.ttcn "
+FILES+="FrameRelay_Types.ttcn FrameRelay_CodecPort.ttcn FrameRelay_Emulation.ttcn Q931_Types.ttcn Q933_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn Osmocom_Types.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Provider_FR.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
+FILES+="LLC_Templates.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/fr/regen_makefile.sh b/fr/regen_makefile.sh
new file mode 100755
index 00000000..1b37cb68
--- /dev/null
+++ b/fr/regen_makefile.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+NAME=FR_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ AF_PACKET_PT.cc
+ AF_PACKET_PT.hh
+ BSSGP_EncDec.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DNS_EMULATION_FR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/gbproxy/GBProxy_Tests.cfg b/gbproxy/GBProxy_Tests.cfg
new file mode 100644
index 00000000..d610e407
--- /dev/null
+++ b/gbproxy/GBProxy_Tests.cfg
@@ -0,0 +1,27 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./GBProxy_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+*.GBPVTY.CTRL_HOSTNAME := "127.0.0.1"
+
+[MODULE_PARAMETERS]
+GBProxy_Tests.mp_nsconfig_sgsn := {
+ {
+ handle_sns := true
+ }, {
+ handle_sns := true
+ }
+
+}
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+GBProxy_Tests.control
diff --git a/gbproxy/GBProxy_Tests.default b/gbproxy/GBProxy_Tests.default
new file mode 100644
index 00000000..b0f28f58
--- /dev/null
+++ b/gbproxy/GBProxy_Tests.default
@@ -0,0 +1,32 @@
+[DEFINE]
+TCPDUMP_START := $TTCN3_HACKS_PATH"/ttcn3-dumpcap-start.sh"
+TCPDUMP_STOP := $TTCN3_HACKS_PATH"/ttcn3-dumpcap-stop.sh"
+
+[LOGGING]
+FileMask := LOG_ALL | TTCN_MATCHING;
+
+"IPA-CTRL-IPA".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+"GBProxy-GSUP-IPA".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+"GBProxy-Gb0-NS".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+"GBProxy-Gb0-BSSGP".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+"GBProxy-GSUP".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+
+[TESTPORT_PARAMETERS]
+*.GBPVTY.CTRL_MODE := "client"
+*.GBPVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.GBPVTY.CTRL_PORTNUM := "4246"
+*.GBPVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.GBPVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.GBPVTY.CTRL_READMODE := "buffered"
+*.GBPVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.GBPVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.GBPVTY.PROMPT1 := "OsmoGbProxy> "
+*.FR.sleep_on_enobufs := "2000" # 2ms
+
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoGbProxy";
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
diff --git a/gbproxy/GBProxy_Tests.fr.cfg b/gbproxy/GBProxy_Tests.fr.cfg
new file mode 100644
index 00000000..65c3f52d
--- /dev/null
+++ b/gbproxy/GBProxy_Tests.fr.cfg
@@ -0,0 +1,119 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./GBProxy_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+*.GBPVTY.CTRL_HOSTNAME := "127.0.0.1"
+
+[MODULE_PARAMETERS]
+GBProxy_Tests.mp_enable_bss_load_sharing := true;
+
+GBProxy_Tests.mp_nsconfig_sgsn := {
+ {
+ handle_sns := true
+ }, {
+ handle_sns := true
+ }
+}
+
+GBProxy_Tests.mp_nsconfig_pcu := {
+ {
+ nsei := 2001,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlc1",
+ dlci := 16
+ }
+ },
+ nsvci := 1
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc2",
+ dlci := 17
+ }
+ },
+ nsvci := 2
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc3",
+ dlci := 18
+ }
+ },
+ nsvci := 3
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc4",
+ dlci := 19
+ }
+ },
+ nsvci := 4
+ }
+ }
+ },
+ {
+ nsei := 2002,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlc5",
+ dlci := 20
+ }
+ },
+ nsvci := 5
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc6",
+ dlci := 21
+ }
+ },
+ nsvci := 6
+ }
+ }
+ },
+ {
+ nsei := 2003,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlc7",
+ dlci := 22
+ }
+ },
+ nsvci := 7
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc8",
+ dlci := 23
+ }
+ },
+ nsvci := 8
+ }
+ }
+ }
+}
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+GBProxy_Tests.control
diff --git a/gbproxy/GBProxy_Tests.ttcn b/gbproxy/GBProxy_Tests.ttcn
new file mode 100644
index 00000000..7a6572a3
--- /dev/null
+++ b/gbproxy/GBProxy_Tests.ttcn
@@ -0,0 +1,3805 @@
+module GBProxy_Tests {
+
+/* Osmocom GBProxy test suite in TTCN-3
+ * (C) 2020-2021 Harald Welte <laforge@osmocom.org>
+ * (C) 2020 sysmocom - s.f.m.c. GmbH
+ * All rights reserved.
+ *
+ * Author: Daniel Willmann <dwillmann@sysmocom.de>
+
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+import from GSM_Types all;
+import from Native_Functions all;
+import from NS_Types all;
+import from NS_Emulation all;
+import from BSSGP_Types all;
+import from BSSGP_Emulation all;
+import from SCCPasp_Types all;
+import from Osmocom_Gb_Types all;
+
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_GMM_SM_Types all;
+import from MobileL3_Types all;
+import from L3_Templates all;
+import from L3_Common all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+import from Osmocom_CTRL_Adapter all;
+
+import from LLC_Types all;
+import from LLC_Templates all;
+
+/* mcc_mnc is 24.008 10.5.5.15 encoded. 262 42 */
+const BcdMccMnc c_mcc_mnc := '262F42'H;
+
+/* 48.016 section 6.1.4.2: The default maximum information field size of 1600 octets shall be supported on the Gb interface */
+const integer max_fr_info_size := 1600;
+
+modulepar {
+ charstring mp_gbproxy_ip := "127.0.0.1";
+ integer mp_gbproxy_ctrl_port := 4263;
+ /* NRI bit-length. 0 for no pooling */
+ integer mp_nri_bitlength := 5;
+ roro_integer mp_sgsn_nri := {
+ { 3 }, /* list of NRIs of first SGSN */
+ { 4 } /* list of NRIs of second SGSN */
+ };
+ boolean mp_enable_bss_load_sharing := false;
+ /* SGSN NS configuration */
+ NSConfigurations mp_nsconfig_sgsn := {
+ {
+ nsei := 101,
+ role_sgsn := true,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 7777,
+ local_ip := "127.0.0.10",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 0,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 101
+ }, {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 7770,
+ local_ip := "127.0.0.10",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 0
+ }
+ },
+ nsvci := 201
+ }
+
+ }
+ }, {
+ nsei := 102,
+ role_sgsn := true,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 8888,
+ local_ip := "127.0.0.11",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 0,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 102
+ }, {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 8880,
+ local_ip := "127.0.0.11",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 0
+ }
+ },
+ nsvci := 202
+ }
+ }
+ }
+ };
+ /* BSS NSEI start at 2000 + x
+ * NSVCI start from value of NSEI + 100
+ * UDP port is NSVCI * 10 */
+ NSConfigurations mp_nsconfig_pcu := {
+ {
+ nsei := 2001,
+ role_sgsn := false,
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21010,
+ local_ip := "127.0.1.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.2",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 2101
+ }
+ }
+ },
+ {
+ nsei := 2002,
+ role_sgsn := false,
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21020,
+ local_ip := "127.0.2.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.2",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 2102
+ }
+ }
+ },
+ {
+ nsei := 2003,
+ role_sgsn := false,
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21030,
+ local_ip := "127.0.3.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.2",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 2103
+ }
+ }
+ }
+ };
+ /* BVCI are NSEI*10 + x
+ * The first NSE only has one BVC, the second one 2 and so on
+ * The Cell ID is BVCI + 10000
+ * LAC/RAC are configured in such a way that:
+ * LAC 13135 is present once in NSE(2001), twice in NSE(2002) and once in NSE(2003)
+ * LAC 13300 is present twice in NSE(2003)
+ * RAI 13135-1 is present in NSE(2002) and NSE(2003)
+ * RAI 13300-0 is present twice in NSE(2003)
+ */
+ BssgpConfigs mp_gbconfigs := {
+ {
+ nsei := 2001,
+ sgsn_role := false,
+ bvc := {
+ {
+ bvci := 20011,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13135
+ },
+ rac := 0
+ },
+ cell_id := 30011
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
+ }, {
+ nsei := 2002,
+ sgsn_role := false,
+ bvc := {
+ {
+ bvci := 20021,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13135
+ },
+ rac := 1
+ },
+ cell_id := 30021
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ },
+ {
+ bvci := 20022,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13135
+ },
+ rac := 2
+ },
+ cell_id := 30022
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
+ }, {
+ nsei := 2003,
+ sgsn_role := false,
+ bvc := {
+ {
+ bvci := 20031,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13135
+ },
+ rac := 1
+ },
+ cell_id := 30031
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ },
+ {
+ bvci := 20032,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13300
+ },
+ rac := 0
+ },
+ cell_id := 30032
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ },
+ {
+ bvci := 20033,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 13300
+ },
+ rac := 0
+ },
+ cell_id := 30033
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
+ }
+ }
+};
+
+type record GbInstance {
+ NS_CT vc_NS,
+ BSSGP_CT vc_BSSGP,
+ BSSGP_BVC_CTs vc_BSSGP_BVC,
+ BssgpConfig cfg
+};
+type record of BSSGP_BVC_CT BSSGP_BVC_CTs
+
+const integer NUM_PCU := 3;
+type record of GbInstance GbInstances;
+type record of BssgpConfig BssgpConfigs;
+type record of NSConfiguration NSConfigurations;
+type record of BssgpCellId BssgpCellIds;
+
+/* you cannot simply change this to any larger number of SGSNs and expect all test
+ * cases to work. This would have overly complicated the code. Check below for
+ * tests that use interleave on SGSN_MGMT.receive() for each SGSN NSEI for example */
+const integer NUM_SGSN := 2;
+
+type component test_CT extends CTRL_Adapter_CT {
+ var GbInstances g_pcu;
+ var GbInstances g_sgsn;
+
+ port NS_CTRL_PT NS_CTRL;
+
+ port BSSGP_CT_PROC_PT PROC;
+
+ port BSSGP_BVC_MGMT_PT SGSN_MGMT;
+ port BSSGP_BVC_MGMT_PT PCU_MGMT;
+
+ port TELNETasp_PT GBPVTY;
+
+ var boolean g_initialized := false;
+ var boolean g_use_echo := false;
+
+ var ro_integer g_roi := {};
+ var roro_integer g_roroi := {};
+ timer g_Tguard;
+};
+
+type component BSSGP_ConnHdlr {
+ /* array of per-BVC ports on the PCU side */
+ port BSSGP_PT PCU_PTP[NUM_PCU];
+ port BSSGP_PT PCU_SIG[NUM_PCU];
+ port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
+ /* component reference to the component to which we're currently connected */
+ var BSSGP_BVC_CT pcu_ct[NUM_PCU];
+ /* BSSGP BVC configuration of the component to which we're currently connected */
+ var BssgpBvcConfig pcu_bvc_cfg[NUM_PCU];
+
+ /* array of per-BVC ports on the SGSN side */
+ port BSSGP_PT SGSN_PTP[NUM_SGSN];
+ port BSSGP_PT SGSN_SIG[NUM_SGSN];
+ port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
+ /* component reference to the component to which we're currently connected */
+ var BSSGP_BVC_CT sgsn_ct[NUM_PCU];
+
+ var BSSGP_ConnHdlrPars g_pars;
+ timer g_Tguard;
+ var LLC_Entities llc;
+
+ var ro_integer g_roi := {};
+}
+
+type record SGSN_ConnHdlrNetworkPars {
+ boolean expect_ptmsi,
+ boolean expect_auth,
+ boolean expect_ciph
+};
+
+type record BSSGP_ConnHdlrPars {
+ /* IMEI of the simulated ME */
+ hexstring imei,
+ /* IMSI of the simulated MS */
+ hexstring imsi,
+ /* MSISDN of the simulated MS (probably unused) */
+ hexstring msisdn,
+ /* P-TMSI allocated to the simulated MS */
+ OCT4 p_tmsi optional,
+ OCT3 p_tmsi_sig optional,
+ /* TLLI of the simulated MS */
+ OCT4 tlli,
+ OCT4 tlli_old optional,
+ RoutingAreaIdentificationV ra optional,
+ GbInstances pcu,
+ GbInstances sgsn,
+ /* The SGSN index to be used within the test */
+ integer sgsn_idx,
+ float t_guard
+};
+
+private function get_bvc_idx_for_bvci(GbInstance gbi, BssgpBvci bvci) return integer
+{
+ var integer i;
+
+ for (i := 0; i < lengthof(gbi.cfg.bvc); i := i + 1) {
+ if (gbi.cfg.bvc[i].bvci == bvci) {
+ return i;
+ }
+ }
+ setverdict(fail, "Could not find BVC Index for BVCI ", bvci);
+ return -1;
+}
+
+private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
+ /* mcc_mnc is encoded as of 24.008 10.5.5.15 */
+ var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
+
+ var RoutingAreaIdentificationV ret := {
+ mccDigit1 := mcc_mnc[0],
+ mccDigit2 := mcc_mnc[1],
+ mccDigit3 := mcc_mnc[2],
+ mncDigit3 := mcc_mnc[3],
+ mncDigit1 := mcc_mnc[4],
+ mncDigit2 := mcc_mnc[5],
+ lac := int2oct(cell_id.ra_id.lai.lac, 16),
+ rac := int2oct(cell_id.ra_id.rac, 8)
+ }
+ return ret;
+};
+
+private function f_fix_create_cb(inout BssgpConfig cfg)
+{
+ for (var integer i := 0; i < lengthof(cfg.bvc); i := i + 1) {
+ if (not isbound(cfg.bvc[i].create_cb)) {
+ cfg.bvc[i].create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
+}
+
+private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
+ var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
+ var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
+ gb.vc_NS := NS_CT.create(ns_id) alive;
+ gb.vc_BSSGP := BSSGP_CT.create(bssgp_id) alive;
+ /* connect lower end of BSSGP emulation with NS upper port */
+ connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
+
+ gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
+ gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
+
+ for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
+ /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
+ connect(self:PROC, gb.vc_BSSGP:PROC);
+ gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
+ disconnect(self:PROC, gb.vc_BSSGP:PROC);
+ /* connect all of the per-BVC MGMT ports to our PCU_MGMT port (1:N) */
+ connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
+ }
+ /* connect all of the BSSGP/NSE global MGMT port to our PCU_MGMT port (1:N) */
+ connect(self:PCU_MGMT, gb.vc_BSSGP:MGMT);
+}
+
+private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
+ var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
+ var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
+ gb.vc_NS := NS_CT.create(ns_id) alive;
+ gb.vc_BSSGP := BSSGP_CT.create(bssgp_id) alive;
+ /* connect lower end of BSSGP emulation with NS upper port */
+ connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
+
+ gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
+ gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
+
+ for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
+ /* obtain the component reference of the BSSGP_BVC_CT for each PTP BVC */
+ connect(self:PROC, gb.vc_BSSGP:PROC);
+ gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
+ disconnect(self:PROC, gb.vc_BSSGP:PROC);
+ /* connect all of the per-BVC MGMT ports to our SGSN_MGMT port (1:N) */
+ connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
+ }
+ /* connect all of the BSSGP/NSE global MGMT port to our SGSN_MGMT port (1:N) */
+ connect(self:SGSN_MGMT, gb.vc_BSSGP:MGMT);
+}
+
+
+private function f_destroy_gb(inout GbInstance gb) runs on test_CT {
+ gb.vc_NS.stop;
+ gb.vc_BSSGP.stop;
+
+ for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
+ gb.vc_BSSGP_BVC[i].stop;
+ }
+}
+
+private function f_init_vty() runs on test_CT {
+ map(self:GBPVTY, system:GBPVTY);
+ f_vty_set_prompts(GBPVTY);
+ f_vty_transceive(GBPVTY, "enable");
+}
+
+/* count the number of unblocked BVCI for each SGSN NSE */
+private altstep as_count_unblocked4nse(integer sgsn_idx, inout roro_integer bvci_unblocked)
+runs on test_CT {
+ var BssgpStatusIndication bsi;
+ [] SGSN_MGMT.receive(BssgpStatusIndication:{g_sgsn[sgsn_idx].cfg.nsei, ?, BVC_S_UNBLOCKED}) -> value bsi {
+ bvci_unblocked[sgsn_idx] := bvci_unblocked[sgsn_idx] & { bsi.bvci };
+ /* 'repeat' until sufficient number of BVC-rest has been received on all SGSNs */
+ for (var integer i := 0; i < lengthof(bvci_unblocked); i := i+1) {
+ if (lengthof(bvci_unblocked[i]) < lengthof(g_sgsn[i].cfg.bvc)) {
+ repeat;
+ }
+ }
+ }
+}
+
+private template (value) charstring ts_pcu_bvc_fsm_id(uint16_t nsei, uint16_t bvci) :=
+ "NSE" & f_int2str(nsei, 5) & "-BVC" & f_int2str(bvci, 5);
+
+function f_bvc_fsm_ensure_state(uint16_t nsei, uint16_t bvci, template (present) charstring exp)
+runs on CTRL_Adapter_CT {
+ f_ctrl_get_exp_inst_state(IPA_CTRL, "BSSGP-BVC", ts_pcu_bvc_fsm_id(nsei, bvci), exp);
+}
+
+function f_init(float t_guard := 30.0) runs on test_CT {
+ var roro_integer bvci_unblocked;
+ var BssgpStatusIndication bsi;
+ var integer i;
+
+ if (g_initialized == true) {
+ return;
+ }
+ g_initialized := true;
+
+ g_Tguard.start(t_guard);
+ activate(as_gTguard(g_Tguard));
+
+ f_ipa_ctrl_start_client(mp_gbproxy_ip, mp_gbproxy_ctrl_port);
+
+ var BssgpBvcConfigs bvcs := { };
+ for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
+ g_pcu[i].cfg := mp_gbconfigs[i];
+ /* make sure all have a proper crate_cb, which cannot be specified in config file */
+ f_fix_create_cb(g_pcu[i].cfg);
+ /* concatenate all the PCU-side BVCs for the SGSN side */
+ bvcs := bvcs & g_pcu[i].cfg.bvc;
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ g_sgsn[i].cfg := {
+ nsei := mp_nsconfig_sgsn[i].nsei,
+ sgsn_role := true,
+ bvc := bvcs
+ }
+ }
+
+ f_init_vty();
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_sgsn[i].cfg.nsei) & " force-unconfigured");
+ }
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_pcu[i].cfg.nsei) & " force-unconfigured");
+ f_vty_transceive(GBPVTY, "delete-gbproxy-peer " & int2str(g_pcu[i].cfg.nsei) & " only-bvc");
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
+ }
+ f_sleep(4.0);
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ bvci_unblocked[i] := {};
+ }
+
+ /* wait until all BVC are unblocked on both sides */
+ timer T := 15.0;
+ T.start;
+ alt {
+ /* TODO: We need to add more lines if NUM_SGSN increases. Activating default altsteps
+ * unfortunately doesn't work as we want to access the local variable bvci_unblocked. */
+ [] as_count_unblocked4nse(0, bvci_unblocked);
+ [lengthof(g_sgsn) > 1] as_count_unblocked4nse(1, bvci_unblocked);
+ [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
+ repeat;
+ }
+ [] SGSN_MGMT.receive(BssgpResetIndication:?) {
+ repeat;
+ }
+ [] SGSN_MGMT.receive {
+ f_shutdown(__FILE__, __LINE__, fail, "Received unexpected message on SGSN_MGMT");
+ }
+
+ [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
+ repeat;
+ }
+ [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
+ repeat;
+ }
+ [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
+ repeat;
+ }
+ [] PCU_MGMT.receive {
+ f_shutdown(__FILE__, __LINE__, fail, "Received unexpected message on PCU_MGMT");
+ }
+
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for unblock of all BVCs on SGSN side; ",
+ "unblocked so far: ", bvci_unblocked);
+ /* don't stop here but print below analysis */
+ }
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ /* iterate over list and check all BVCI */
+ for (var integer j := 0; j < lengthof(g_sgsn[i].cfg.bvc); j := j+1) {
+ var BssgpBvci bvci := g_sgsn[i].cfg.bvc[j].bvci;
+ if (not ro_integer_contains(bvci_unblocked[i], bvci)) {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("SGSN ", i, " BVCI=", bvci, " was not unblocked during start-up"));
+ }
+ }
+ }
+
+ /* Wait to ensure the gbproxy processed the RESET_ACK messages from the SGSN.
+ * Otherwise the state might still be WAIT_RESET_ACK */
+ f_sleep(0.2);
+
+ /* verify all SGSN-side BVC FSM in IUT are UNBLOCKED */
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_bvc_fsm_ensure_state(mp_nsconfig_sgsn[i].nsei, 0, "UNBLOCKED");
+ /* iterate over list and check all BVCI */
+ for (var integer j := 0; j < lengthof(g_sgsn[i].cfg.bvc); j := j+1) {
+ var BssgpBvci bvci := g_sgsn[i].cfg.bvc[j].bvci;
+ f_bvc_fsm_ensure_state(mp_nsconfig_sgsn[i].nsei, bvci, "UNBLOCKED");
+ }
+ }
+ /* verify all PCU-side BVC FSM in IUT are UNBLOCKED */
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_bvc_fsm_ensure_state(mp_nsconfig_pcu[i].nsei, 0, "UNBLOCKED");
+ /* iterate over list and check all BVCI */
+ for (var integer j := 0; j < lengthof(g_pcu[i].cfg.bvc); j := j+1) {
+ var BssgpBvci bvci := g_pcu[i].cfg.bvc[j].bvci;
+ f_bvc_fsm_ensure_state(mp_nsconfig_pcu[i].nsei, bvci, "UNBLOCKED");
+ }
+ }
+
+ /* re-start guard timer after all BVCs are up, so it only counts the actual test case */
+ g_Tguard.start(t_guard);
+}
+
+function f_cleanup() runs on test_CT {
+ var integer i;
+
+ /* To avoid a dynamic test case error we need to prevent messages arriving on unconnected
+ * ports. Waiting here ensures that any messages "in flight" will be delivered to the port
+ * before the component is shutdown and disconnected. */
+ f_sleep(0.2);
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_destroy_gb(g_sgsn[i]);
+ }
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_destroy_gb(g_pcu[i]);
+ }
+
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
+}
+
+type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
+
+/* helper function to create, connect and start a BSSGP_ConnHdlr component */
+function f_start_handler(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
+ integer sgsn_idx := 0, integer nri_idx := 0, boolean have_ptmsi := true)
+runs on test_CT return BSSGP_ConnHdlr {
+ var BSSGP_ConnHdlr vc_conn;
+ var integer nri := mp_sgsn_nri[sgsn_idx][nri_idx];
+ var OCT4 p_tmsi := f_gen_tmsi(imsi_suffix, nri_v := nri, nri_bitlen := mp_nri_bitlength);
+
+ var BSSGP_ConnHdlrPars pars := {
+ imei := f_gen_imei(imsi_suffix),
+ imsi := f_gen_imsi(imsi_suffix),
+ msisdn := f_gen_msisdn(imsi_suffix),
+ p_tmsi := p_tmsi,
+ p_tmsi_sig := omit,
+ tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL),
+ tlli_old := omit,
+ ra := omit,
+ pcu := g_pcu,
+ sgsn := g_sgsn,
+ sgsn_idx := sgsn_idx,
+ t_guard := t_guard
+ };
+ if (not have_ptmsi) {
+ pars.p_tmsi := omit;
+ }
+
+ vc_conn := BSSGP_ConnHdlr.create(id) alive;
+
+ log("Starting ", id, " for SGSN[", sgsn_idx, "], NRI=", nri, ", P-TMSI=", pars.p_tmsi,
+ ", TLLI=", pars.tlli, ", IMSI=", pars.imsi, " on component=", vc_conn);
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+function f_start_handlers(void_fn fn, charstring id, integer imsi_suffix, float t_guard := 30.0,
+ boolean have_ptmsi := true)
+runs on test_CT
+{
+ var integer sgsn_idx, nri_idx;
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx:=nri_idx+1) {
+ var integer extd_imsi_suffix := 1000*sgsn_idx + 100*nri_idx;
+ var BSSGP_ConnHdlr vc_conn;
+ vc_conn := f_start_handler(fn, id, extd_imsi_suffix, t_guard, sgsn_idx, nri_idx,
+ have_ptmsi);
+ /* Idea: we could also run them in parallel ? */
+ vc_conn.done;
+ }
+ }
+}
+
+/* Connect the PCU-side per-BVC ports (PCU/PCU_SIG/PCU_PROC) array slot 'port_idx' to specified per-BVC component */
+private function f_connect_to_pcu_bvc(integer port_idx, integer nse_idx, integer bvc_idx)
+runs on BSSGP_ConnHdlr {
+ var BSSGP_BVC_CT bvc_ct := g_pars.pcu[nse_idx].vc_BSSGP_BVC[bvc_idx]
+ if (PCU_PTP[port_idx].checkstate("Connected")) {
+ /* unregister + disconnect from old BVC */
+ f_client_unregister(g_pars.imsi, PCU_PROC[port_idx]);
+ disconnect(self:PCU_PTP[port_idx], pcu_ct[port_idx]:BSSGP_SP);
+ disconnect(self:PCU_SIG[port_idx], pcu_ct[port_idx]:BSSGP_SP_SIG);
+ disconnect(self:PCU_PROC[port_idx], pcu_ct[port_idx]:BSSGP_PROC);
+ }
+ /* connect to new BVC and register us */
+ connect(self:PCU_PTP[port_idx], bvc_ct:BSSGP_SP);
+ connect(self:PCU_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
+ connect(self:PCU_PROC[port_idx], bvc_ct:BSSGP_PROC);
+ f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[port_idx]);
+ pcu_ct[port_idx] := bvc_ct;
+ pcu_bvc_cfg[port_idx] := g_pars.pcu[nse_idx].cfg.bvc[bvc_idx];
+}
+
+/* Connect the SGSN-side per-BVC ports (SGSN/SGSN_SIG/SGSN_PROC) array slot 'port_idx' to specified per-BVC component */
+private function f_connect_to_sgsn_bvc(integer port_idx, BSSGP_BVC_CT bvc_ct) runs on BSSGP_ConnHdlr {
+ if (SGSN_PTP[port_idx].checkstate("Connected")) {
+ /* unregister + disconnect from old BVC */
+ f_client_unregister(g_pars.imsi, SGSN_PROC[port_idx]);
+ disconnect(self:SGSN_PTP[port_idx], sgsn_ct[port_idx]:BSSGP_SP);
+ disconnect(self:SGSN_SIG[port_idx], sgsn_ct[port_idx]:BSSGP_SP_SIG);
+ disconnect(self:SGSN_PROC[port_idx], sgsn_ct[port_idx]:BSSGP_PROC);
+ }
+ /* connect to new BVC and register us */
+ connect(self:SGSN_PTP[port_idx], bvc_ct:BSSGP_SP);
+ connect(self:SGSN_SIG[port_idx], bvc_ct:BSSGP_SP_SIG);
+ connect(self:SGSN_PROC[port_idx], bvc_ct:BSSGP_PROC);
+ f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[port_idx]);
+ sgsn_ct[port_idx] := bvc_ct;
+}
+
+private altstep as_gTguard(timer Tguard) {
+ [] Tguard.timeout {
+ f_shutdown(__FILE__, __LINE__, fail, "Tguard timeout");
+ }
+}
+
+/* first function called in every ConnHdlr */
+private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
+runs on BSSGP_ConnHdlr {
+ var integer i;
+ /* do some common stuff like setting up g_pars */
+ g_pars := pars;
+
+ llc := f_llc_create(false);
+
+ /* default connections on PCU side: First BVC of each NSE/PCU */
+ for (i := 0; i < lengthof(g_pars.pcu); i := i+1) {
+ f_connect_to_pcu_bvc(port_idx := i, nse_idx := i, bvc_idx := 0);
+ }
+
+ /* default connections on SGSN side: First BVC of each NSE/SGSN */
+ for (i := 0; i < lengthof(g_pars.sgsn); i := i+1) {
+ f_connect_to_sgsn_bvc(i, g_pars.sgsn[i].vc_BSSGP_BVC[0]);
+ }
+
+ g_Tguard.start(pars.t_guard);
+ activate(as_gTguard(g_Tguard));
+
+ /* call the user-supplied test case function */
+ fn.apply(id);
+
+ for (i := 0; i < NUM_SGSN; i := i+1) {
+ if (SGSN_PROC[i].checkstate("Connected")) {
+ f_client_unregister(g_pars.imsi, SGSN_PROC[i])
+ }
+ }
+
+ for (i := 0; i < NUM_PCU; i := i+1) {
+ if (PCU_PROC[i].checkstate("Connected")) {
+ f_client_unregister(g_pars.imsi, PCU_PROC[i])
+ }
+ }
+}
+
+private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
+runs on BSSGP_ConnHdlr {
+ PT.call(BSSGP_register_client:{imsi, tlli}) {
+ [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
+ }
+}
+
+private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
+runs on BSSGP_ConnHdlr {
+ PT.call(BSSGP_unregister_client:{imsi}) {
+ [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
+ }
+}
+
+/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
+friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
+ var integer sgsn_idx := g_pars.sgsn_idx;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ if (use_sig) {
+ PCU_SIG[pcu_idx].send(tx);
+ } else {
+ PCU_PTP[pcu_idx].send(tx);
+ }
+
+ T.start;
+ alt {
+ [use_sig] SGSN_SIG[sgsn_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [not use_sig] SGSN_PTP[sgsn_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] SGSN_PTP[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Unexpected BSSGP on SGSN[", sgsn_idx, "] side: ", rx));
+ }
+ [] SGSN_SIG[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Unexpected SIG BSSGP on SGSN[", sgsn_idx, "] side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on SGSN[", sgsn_idx, "] side: ", exp_rx));
+ }
+ }
+}
+
+/* Send 'tx' from PCU; expect 'exp_rx' on _any_ SGSN */
+friend function f_pcu2any_sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer pcu_idx := 0, boolean use_sig := false)
+runs on BSSGP_ConnHdlr return integer {
+ var integer rx_idx := -1;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ if (use_sig) {
+ PCU_SIG[pcu_idx].send(tx);
+ } else {
+ PCU_PTP[pcu_idx].send(tx);
+ }
+
+ T.start;
+ alt {
+ [use_sig] any from SGSN_SIG.receive(exp_rx) -> @index value rx_idx {
+ setverdict(pass);
+ }
+ [not use_sig] any from SGSN_PTP.receive(exp_rx) -> @index value rx_idx {
+ setverdict(pass);
+ }
+ [] any from SGSN_PTP.receive(PDU_BSSGP:?) -> value rx @index value rx_idx {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Unexpected BSSGP on SGSN[", rx_idx, "] side: ", rx));
+ }
+ [] any from SGSN_SIG.receive(PDU_BSSGP:?) -> value rx @index value rx_idx {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Unexpected SIG BSSGP on SGSN[", rx_idx, "] side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on SGSN side: ", exp_rx));
+ }
+ }
+ return rx_idx;
+}
+
+/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
+friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer pcu_idx := 0, boolean use_sig := false) runs on BSSGP_ConnHdlr {
+ var integer sgsn_idx := g_pars.sgsn_idx;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ if (use_sig) {
+ SGSN_SIG[sgsn_idx].send(tx);
+ } else {
+ SGSN_PTP[sgsn_idx].send(tx);
+ }
+
+ T.start;
+ alt {
+ [use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [not use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] PCU_PTP[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on PCU side: ", rx));
+ }
+ [] PCU_SIG[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected SIG BSSGP on PCU side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on PCU side: ", exp_rx));
+ }
+ }
+}
+
+/***********************************************************************
+ * GlobaLTest_CT: Using the per-NSE GLOBAL ports on PCU + SGSN side
+ ***********************************************************************/
+
+type component GlobalTest_CT extends test_CT {
+ port BSSGP_PT G_PCU[NUM_PCU];
+ var integer g_pcu_idx[NUM_PCU]; /* BVC index currently connected to G_PCU */
+ port BSSGP_PT G_SGSN[NUM_SGSN];
+ var integer g_sgsn_idx[NUM_SGSN]; /* BVC index currently connected to G_SGSN */
+ port BSSGP_PT RIM_PCU[NUM_PCU];
+ port BSSGP_PT RIM_SGSN[NUM_SGSN];
+};
+
+/* connect the signaling BVC of each NSE to the G_PCU / G_SGSN ports */
+private function f_global_init() runs on GlobalTest_CT {
+ var integer i;
+ for (i := 0; i < lengthof(g_sgsn); i := i+1) {
+ connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP:GLOBAL);
+ connect(self:RIM_SGSN[i], g_sgsn[i].vc_BSSGP:RIM);
+ }
+ for (i := 0; i < lengthof(g_pcu); i := i+1) {
+ connect(self:G_PCU[i], g_pcu[i].vc_BSSGP:GLOBAL);
+ connect(self:RIM_PCU[i], g_pcu[i].vc_BSSGP:RIM);
+ }
+}
+
+/* connect the first PTP BVC of each NSE to the G_PCU / G_SGSN ports */
+private function f_global_init_ptp() runs on GlobalTest_CT {
+ var integer i;
+ for (i := 0; i < lengthof(g_sgsn); i := i+1) {
+ log("Connecting G_SGSN[", i, "] to BVCI=", g_sgsn[i].cfg.bvc[0].bvci);
+ connect(self:G_SGSN[i], g_sgsn[i].vc_BSSGP_BVC[0]:GLOBAL);
+ g_sgsn_idx[i] := 0;
+ }
+ for (i := 0; i < lengthof(g_pcu); i := i+1) {
+ log("Connecting G_PCU[", i, "] to BVCI=", g_pcu[i].cfg.bvc[0].bvci);
+ connect(self:G_PCU[i], g_pcu[i].vc_BSSGP_BVC[0]:GLOBAL);
+ g_pcu_idx[i] := 0;
+ }
+}
+
+/* (re)connect G_SGSN[sgsn_idx] to a specific PTP BVCI */
+private function f_global_ptp_connect_sgsn_bvci(integer sgsn_idx, BssgpBvci bvci) runs on GlobalTest_CT
+{
+ var integer sgsn_bvc_idx := get_bvc_idx_for_bvci(g_sgsn[sgsn_idx], bvci);
+ var integer old_sgsn_bvc_idx := g_sgsn_idx[sgsn_idx];
+ disconnect(self:G_SGSN[sgsn_idx], g_sgsn[sgsn_idx].vc_BSSGP_BVC[old_sgsn_bvc_idx]:GLOBAL);
+ connect(self:G_SGSN[sgsn_idx], g_sgsn[sgsn_idx].vc_BSSGP_BVC[sgsn_bvc_idx]:GLOBAL);
+ g_sgsn_idx[sgsn_idx] := sgsn_bvc_idx;
+}
+
+/* (re)connect G_PCU[pcu_idx] to a specific PTP BVCI */
+private function f_global_ptp_connect_pcu_bvci(integer pcu_idx, BssgpBvci bvci) runs on GlobalTest_CT
+{
+ var integer pcu_bvc_idx := get_bvc_idx_for_bvci(g_pcu[pcu_idx], bvci);
+ var integer old_pcu_bvc_idx := g_pcu_idx[pcu_idx];
+ disconnect(self:G_PCU[pcu_idx], g_pcu[pcu_idx].vc_BSSGP_BVC[old_pcu_bvc_idx]:GLOBAL);
+ connect(self:G_PCU[pcu_idx], g_pcu[pcu_idx].vc_BSSGP_BVC[pcu_bvc_idx]:GLOBAL);
+ g_pcu_idx[pcu_idx] := pcu_bvc_idx;
+}
+
+/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
+friend function f_global_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer pcu_idx := 0, integer sgsn_idx := 0) runs on GlobalTest_CT {
+ var integer rx_idx;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ G_PCU[pcu_idx].send(tx);
+ T.start;
+ alt {
+ [] G_SGSN[sgsn_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] any from G_SGSN.receive(exp_rx) -> @index value rx_idx {
+ setverdict(fail, "BSSGP arrived on wrong SGSN[", rx_idx, "] instead of SGSN[", sgsn_idx, "]");
+ }
+ [] G_SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on SGSN side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Timeout waiting for BSSGP on SGSN side: ", exp_rx));
+ }
+ }
+}
+
+/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
+friend function f_global_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer sgsn_idx := 0, integer pcu_idx := 0) runs on GlobalTest_CT {
+ var integer rx_idx;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ G_SGSN[sgsn_idx].send(tx);
+ T.start;
+ alt {
+ [] G_PCU[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] any from G_PCU.receive(exp_rx) -> @index value rx_idx {
+ setverdict(fail, "BSSGP arrived on wrong PCU[", rx_idx, "] instead of PCU[", pcu_idx, "]");
+ }
+ [] G_PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on PCU side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Timeout waiting for BSSGP on PCU side: ", exp_rx));
+ }
+ }
+}
+
+
+/* TODO:
+ * Detach without Attach
+ * SM procedures without attach / RAU
+ * ATTACH / RAU
+ ** with / without authentication
+ ** with / without P-TMSI allocation
+ * re-transmissions of LLC frames
+ * PDP Context activation
+ ** with different GGSN config in SGSN VTY
+ ** with different PDP context type (v4/v6/v46)
+ ** timeout from GGSN
+ ** multiple / secondary PDP context
+ */
+
+private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
+ f_sleep(5.0);
+ setverdict(pass);
+}
+
+testcase TC_BVC_bringup() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_BVC_bringup), testcasename(), 51);
+ f_cleanup();
+}
+
+testcase TC_BVC_bringup_conflicting() runs on test_CT {
+ var float t_guard := 15.0;
+ var BssgpStatusIndication bsi;
+ var integer i;
+
+
+ g_Tguard.start(t_guard);
+ activate(as_gTguard(g_Tguard));
+
+ f_ipa_ctrl_start_client(mp_gbproxy_ip, mp_gbproxy_ctrl_port);
+
+ var BssgpBvcConfigs bvcs := { };
+ for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
+ g_pcu[i].cfg := mp_gbconfigs[i];
+ g_pcu[i].cfg.bvc[0].bvci := 23;
+ /* make sure all have a proper create_cb, which cannot be specified in config file */
+ f_fix_create_cb(g_pcu[i].cfg);
+ /* concatenate all the PCU-side BVCs for the SGSN side */
+ bvcs := bvcs & g_pcu[i].cfg.bvc;
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ g_sgsn[i].cfg := {
+ nsei := mp_nsconfig_sgsn[i].nsei,
+ sgsn_role := true,
+ bvc := bvcs
+ }
+ }
+
+ f_init_vty();
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_sgsn[i].cfg.nsei) & " force-unconfigured");
+ }
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_vty_transceive(GBPVTY, "nsvc nsei " & int2str(g_pcu[i].cfg.nsei) & " force-unconfigured");
+ f_vty_transceive(GBPVTY, "delete-gbproxy-peer " & int2str(g_pcu[i].cfg.nsei) & " only-bvc");
+ }
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
+ }
+ f_sleep(4.0);
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
+ }
+
+ /* wait until all BVC are unblocked on both sides */
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
+ repeat;
+ }
+ [] SGSN_MGMT.receive(BssgpResetIndication:?) {
+ repeat;
+ }
+ [] SGSN_MGMT.receive {
+ f_shutdown(__FILE__, __LINE__, fail, "Received unexpected message on SGSN_MGMT");
+ }
+ [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
+ repeat;
+ }
+ [] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
+ repeat;
+ }
+ [] PCU_MGMT.receive(BssgpResetIndication:{0}) {
+ repeat;
+ }
+ [] PCU_MGMT.receive {
+ f_shutdown(__FILE__, __LINE__, fail, "Received unexpected message on PCU_MGMT");
+ }
+ [] T.timeout {
+ }
+ }
+
+ /* Wait to ensure the gbproxy processed the RESET_ACK messages from the SGSN.
+ * Otherwise the state might still be WAIT_RESET_ACK */
+ f_sleep(0.2);
+
+ /* Verify BVCs, but ignore conflicting BVCI 23 */
+ /* verify SGSN-side BVC FSM in IUT are UNBLOCKED */
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ f_bvc_fsm_ensure_state(mp_nsconfig_sgsn[i].nsei, 0, "UNBLOCKED");
+ /* iterate over list and check all BVCI */
+ for (var integer j := 0; j < lengthof(g_sgsn[i].cfg.bvc); j := j+1) {
+ var BssgpBvci bvci := g_sgsn[i].cfg.bvc[j].bvci;
+ if (bvci == 23) {
+ continue;
+ }
+ f_bvc_fsm_ensure_state(mp_nsconfig_sgsn[i].nsei, bvci, "UNBLOCKED");
+ }
+ }
+ /* verify PCU-side BVC FSM in IUT are UNBLOCKED */
+ for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ f_bvc_fsm_ensure_state(mp_nsconfig_pcu[i].nsei, 0, "UNBLOCKED");
+ /* iterate over list and check all BVCI */
+ for (var integer j := 0; j < lengthof(g_pcu[i].cfg.bvc); j := j+1) {
+ var BssgpBvci bvci := g_pcu[i].cfg.bvc[j].bvci;
+ if (bvci == 23) {
+ continue;
+ }
+ f_bvc_fsm_ensure_state(mp_nsconfig_pcu[i].nsei, bvci, "UNBLOCKED");
+ }
+ }
+
+ /* re-start guard timer after all BVCs are up, so it only counts the actual test case */
+ g_Tguard.start(t_guard);
+ f_start_handlers(refers(f_TC_BVC_bringup), testcasename(), 51);
+ f_cleanup();
+}
+
+friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
+ var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
+ timer T := 5.0;
+ var PDU_BSSGP rx_pdu;
+ PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
+ T.start;
+ alt {
+ [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
+ return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
+ }
+ [] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli));
+ }
+ }
+ return '00'O;
+}
+
+friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
+ var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
+ timer T := 5.0;
+ PCU_SIG[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, bvcc.cell_id.ra_id, susp_ref));
+ T.start;
+ alt {
+ [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
+ [] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli));
+ }
+ }
+}
+
+
+/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
+private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
+ var integer ran_idx := 0;
+ var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
+ var integer i;
+
+ for (i := 0; i < max_fr_info_size-4; i := i+4) {
+ var octetstring payload := f_rnd_octstring(i);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
+
+ log("UL-UNITDATA(payload_size=", i);
+ f_pcu2sgsn(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+
+testcase TC_ul_unitdata() runs on test_CT
+{
+ f_init(60.0);
+ f_start_handlers(refers(f_TC_ul_unitdata), testcasename(), 1);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+
+/* send uplink-unitdata of a variety of different sizes; expect it to show up on the only connected SGSN */
+private function f_TC_ul_unitdata_pool_failure(charstring id) runs on BSSGP_ConnHdlr {
+ var integer ran_idx := 0;
+ var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
+ var integer i;
+
+ /* All data should arrive at the one SGSN that is still up */
+ g_pars.sgsn_idx := 0;
+
+ for (i := 0; i < max_fr_info_size-4; i := i+4) {
+ var octetstring payload := f_rnd_octstring(i);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
+
+ log("UL-UNITDATA(payload_size=", i);
+ f_pcu2sgsn(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+
+private function f_disable_ns_pcu(integer pcu_idx) runs on test_CT
+{
+ var integer i;
+
+ connect(self:NS_CTRL, g_pcu[pcu_idx].vc_NS:NS_CTRL);
+ for (i := 0; i < lengthof(mp_nsconfig_pcu[pcu_idx].nsvc); i := i + 1) {
+ var uint16_t nsvci := mp_nsconfig_pcu[pcu_idx].nsvc[i].nsvci;
+ var NsDisableVcRequest tx_disar;
+ tx_disar.nsvci := nsvci;
+ log(tx_disar);
+ NS_CTRL.send(tx_disar);
+ }
+ disconnect(self:NS_CTRL, g_pcu[pcu_idx].vc_NS:NS_CTRL);
+}
+
+testcase TC_ul_unitdata_pool_failure() runs on test_CT
+{
+ var integer i;
+ var integer j;
+
+ f_init(60.0);
+
+ for (i := 1; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ connect(self:NS_CTRL, g_sgsn[i].vc_NS:NS_CTRL);
+ for (j := 0; j < lengthof(mp_nsconfig_sgsn[i].nsvc); j := j+1) {
+ var uint16_t nsvci := mp_nsconfig_sgsn[i].nsvc[j].nsvci;
+ var NsDisableVcRequest tx_disar;
+ tx_disar.nsvci := nsvci;
+ NS_CTRL.send(tx_disar);
+ }
+ disconnect(self:NS_CTRL, g_sgsn[i].vc_NS:NS_CTRL);
+ }
+ /* Wait until gbproxy notices that the NSVCs are down */
+ f_sleep(15.0);
+
+ f_start_handlers(refers(f_TC_ul_unitdata_pool_failure), testcasename(), 1);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
+private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+
+ for (i := 0; i < max_fr_info_size-4; i := i+4) {
+ var octetstring payload := f_rnd_octstring(i);
+ var template (value) PDU_BSSGP pdu_tx :=
+ ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx :=
+ tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
+
+ log("DL-UNITDATA(payload_size=", i, ")");
+ f_sgsn2pcu(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+
+testcase TC_dl_unitdata() runs on test_CT
+{
+ f_init(60.0);
+ f_start_handlers(refers(f_TC_dl_unitdata), testcasename(), 2);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+
+ for (i := 0; i < 10; i := i+1) {
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
+
+ f_sgsn2pcu(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+testcase TC_ra_capability() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_ra_capability), testcasename(), 3);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+ var OCT1 tag;
+ for (i := 0; i < 10; i := i+1) {
+ tag := int2oct(23 + i, 1);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
+
+ f_pcu2sgsn(pdu_tx, pdu_rx);
+
+ pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
+
+ f_sgsn2pcu(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+testcase TC_ra_capability_upd() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_ra_capability_upd), testcasename(), 4);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+private function f_TC_radio_status(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+ var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
+ for (i := 0; i < 10; i := i+1) {
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(g_pars.tlli, cause);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(g_pars.tlli, cause)
+
+ f_pcu2sgsn(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+testcase TC_radio_status() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_radio_status), testcasename(), 5);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+private function f_TC_radio_status_tmsi(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+ var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
+ for (i := 0; i < 10; i := i+1) {
+ var integer tmsi_int := oct2int(g_pars.p_tmsi);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(omit, cause, tmsi_int);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(omit, cause, tmsi_int);
+ f_pcu2sgsn(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+testcase TC_radio_status_tmsi() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_radio_status_tmsi), testcasename(), 5);
+ f_cleanup();
+}
+
+private function f_TC_radio_status_imsi(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+ var BssgpRadioCause cause := BSSGP_RADIO_CAUSE_CONTACT_LOST;
+ for (i := 0; i < 10; i := i+1) {
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RADIO_STATUS(omit, cause, imsi := g_pars.imsi);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RADIO_STATUS(omit, cause, imsi := g_pars.imsi);
+ f_pcu2any_sgsn(pdu_tx, pdu_rx);
+ }
+ setverdict(pass);
+}
+testcase TC_radio_status_imsi() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_radio_status_imsi), testcasename(), 5);
+ f_cleanup();
+}
+
+
+
+private function f_suspend_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
+ integer suffix)
+runs on GlobalTest_CT
+{
+ var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
+ var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
+ nri_bitlen := mp_nri_bitlength);
+ var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
+ f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
+
+ pdu_tx := ts_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_SUSPEND_ACK(tlli, ra_id, int2oct(suffix, 1));
+ f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
+
+ pdu_tx := ts_BSSGP_SUSPEND(tlli, ra_id);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_SUSPEND(tlli, ra_id);
+ f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
+
+ /* These messages are simple passed through so just also test sending NACK */
+ pdu_tx := ts_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_SUSPEND_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
+ f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
+}
+
+private function f_TC_suspend(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
+runs on GlobalTest_CT {
+ var integer i;
+
+ for (i := 0; i < 10; i := i+1) {
+ f_suspend_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
+ }
+ setverdict(pass);
+}
+testcase TC_suspend() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+ f_init();
+ f_global_init();
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
+ f_TC_suspend(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
+ }
+ }
+ f_cleanup();
+}
+
+private function f_resume_one(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx,
+ integer suffix)
+runs on GlobalTest_CT
+{
+ var RoutingAreaIdentification ra_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id.ra_id;
+ var OCT4 p_tmsi := f_gen_tmsi(suffix, nri_v := mp_sgsn_nri[sgsn_idx][nri_idx],
+ nri_bitlen := mp_nri_bitlength);
+ var OCT4 tlli := f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
+ f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
+
+ pdu_tx := ts_BSSGP_RESUME_ACK(tlli, ra_id);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_RESUME_ACK(tlli, ra_id);
+ f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
+
+ pdu_tx := ts_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_RESUME(tlli, ra_id, int2oct(suffix, 1));
+ f_global_pcu2sgsn(pdu_tx, pdu_rx, pcu_idx, sgsn_idx);
+
+ /* These messages are simple passed through so just also test sending NACK */
+ pdu_tx := ts_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_RESUME_NACK(tlli, ra_id, BSSGP_CAUSE_UNKNOWN_MS);
+ f_global_sgsn2pcu(pdu_tx, pdu_rx, sgsn_idx, pcu_idx);
+}
+
+private function f_TC_resume(integer sgsn_idx, integer nri_idx, integer pcu_idx, integer bvc_idx)
+runs on GlobalTest_CT {
+ var integer i;
+
+ for (i := 0; i < 10; i := i+1) {
+ f_resume_one(sgsn_idx, nri_idx, pcu_idx, bvc_idx, suffix := i);
+ }
+ setverdict(pass);
+}
+testcase TC_resume() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+ f_init();
+ f_global_init();
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx+1) {
+ f_TC_resume(sgsn_idx, nri_idx, pcu_idx:=0, bvc_idx:=0);
+ }
+ }
+ f_cleanup();
+}
+
+/* test the load-sharing between multiple NS-VC on the BSS side */
+private function f_TC_dl_ud_unidir(charstring id) runs on BSSGP_ConnHdlr {
+ var integer i;
+
+ for (i := 0; i < 10; i := i+1) {
+ var octetstring payload := f_rnd_octstring(i);
+ var template (value) PDU_BSSGP pdu_tx :=
+ ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
+ SGSN_PTP[g_pars.sgsn_idx].send(pdu_tx);
+ }
+ setverdict(pass);
+}
+
+private function f_TC_load_sharing_dl(integer sgsn_idx) runs on test_CT_NS
+{
+ const integer num_ue := 10;
+ var BSSGP_ConnHdlr vc_conn[num_ue];
+ /* all BVC are now fully brought up. We disconnect BSSGP from NS on the BSS
+ * side so we get the raw NsUnitdataIndication and hence observe different
+ * NSVCI */
+ disconnect(g_pcu[0].vc_NS:NS_SP, g_pcu[0].vc_BSSGP:BSCP);
+ connect(g_pcu[0].vc_NS:NS_SP, self:NS);
+
+ /* there may still be some NS-VCs coming up? After all, the BVC-RESET succeeds after the first
+ * of the NS-VC is ALIVE/UNBLOCKED */
+ f_sleep(3.0);
+
+ /* start parallel components generating DL-UNITDATA from the SGSN side */
+ for (var integer i:= 0; i < num_ue; i := i+1) {
+ vc_conn[i] := f_start_handler(refers(f_TC_dl_ud_unidir), testcasename(),
+ 5+i, 30.0, sgsn_idx);
+ }
+
+ /* now start counting all the messages that were queued before */
+ /* TODO: We have a hard-coded assumption of 4 NS-VC in one NSE/NS-VCG here! */
+ var ro_integer rx_count := { 0, 0, 0, 0 };
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] as_NsUdiCount(0, rx_count);
+ [] as_NsUdiCount(1, rx_count);
+ [] as_NsUdiCount(2, rx_count);
+ [] as_NsUdiCount(3, rx_count);
+ [] NS.receive(NsUnitdataIndication:{0,?,?,*,*}) { repeat; } /* signaling BVC */
+ [] NS.receive(NsStatusIndication:?) { repeat; }
+ [] NS.receive {
+ f_shutdown(__FILE__, __LINE__, fail, "Rx unexpected NS");
+ }
+ [] T.timeout {
+ }
+ }
+ for (var integer i := 0; i < lengthof(rx_count); i := i+1) {
+ log("Rx on NSVCI ", mp_nsconfig_pcu[0].nsvc[i].nsvci, ": ", rx_count[i]);
+ if (rx_count[i] == 0) {
+ setverdict(fail, "Data not shared over all NSVC");
+ }
+ }
+}
+
+testcase TC_load_sharing_dl() runs on test_CT_NS
+{
+ var integer sgsn_idx, nri_idx;
+ f_init();
+ for (sgsn_idx:=0; sgsn_idx < NUM_SGSN; sgsn_idx:=sgsn_idx+1) {
+ f_TC_load_sharing_dl(sgsn_idx);
+ }
+ setverdict(pass);
+}
+private altstep as_NsUdiCount(integer nsvc_idx, inout ro_integer roi) runs on test_CT_NS {
+ var NsUnitdataIndication udi;
+ var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[0];
+ [] NS.receive(NsUnitdataIndication:{bvcc.bvci, g_pcu[0].cfg.nsei, mp_nsconfig_pcu[0].nsvc[nsvc_idx].nsvci, *, *}) -> value udi {
+ roi[nsvc_idx] := roi[nsvc_idx] + 1;
+ repeat;
+ }
+}
+type component test_CT_NS extends test_CT {
+ port NS_PT NS;
+};
+
+
+/***********************************************************************
+ * PAGING PS procedure
+ ***********************************************************************/
+
+private function f_send_paging_ps(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false)
+runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
+ var template (value) PDU_BSSGP pdu_tx;
+ var template (present) PDU_BSSGP pdu_rx;
+ /* we always specify '0' as BVCI in the templates below, as we override it with
+ * 'p4' later anyway */
+ pdu_rx := tr_BSSGP_PS_PAGING(0);
+ pdu_rx.pDU_BSSGP_PAGING_PS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
+ if (ispresent(g_pars.p_tmsi)) {
+ pdu_tx := ts_BSSGP_PS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
+ pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
+ } else {
+ pdu_tx := ts_BSSGP_PS_PAGING_IMSI(0, g_pars.imsi);
+ pdu_rx.pDU_BSSGP_PAGING_PS.pTMSI := omit;
+ }
+ pdu_tx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
+ pdu_rx.pDU_BSSGP_PAGING_PS.paging_Field4 := p4;
+ if (use_sig == false) {
+ SGSN_PTP[sgsn_idx].send(pdu_tx);
+ } else {
+ SGSN_SIG[sgsn_idx].send(pdu_tx);
+ }
+ return pdu_rx;
+}
+
+/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
+ * specified PCU index */
+private function f_send_paging_ps_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false,integer pcu_idx := 0)
+runs on BSSGP_ConnHdlr {
+ var template (present) PDU_BSSGP exp_rx;
+ var boolean test_done := false;
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
+ /* Expect paging to propagate to the one BSS addressed by the BVCI only */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ test_done := true;
+ repeat;
+ }
+ [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
+ setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
+ }
+ [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ test_done := true;
+ repeat;
+ }
+ [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
+ }
+ [] any from PCU_PTP.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_SIG.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging than expected received PTP BVC");
+ }
+ [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging than expected on SIGNALING BVC");
+ }
+ [not test_done] T.timeout {
+ setverdict(fail, "Timeout waiting for paging");
+ }
+ [test_done] T.timeout;
+ }
+}
+
+/* send a PS-PAGING but don't expect it to show up on any PTP or SIG BVC */
+private function f_send_paging_ps_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false)
+runs on BSSGP_ConnHdlr {
+ var template (present) PDU_BSSGP exp_rx;
+ exp_rx := f_send_paging_ps(p4, sgsn_idx, use_sig);
+ /* Expect paging to propagate to no BSS */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] any from PCU_PTP.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_SIG.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging received on PTP BVC");
+ }
+ [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging received on SIGNALING BVC");
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+}
+
+private function f_TC_paging_ps_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4BssArea, g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_bss() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_bss), testcasename(), 9);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for Location Area */
+private function f_TC_paging_ps_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
+{
+ var template (present) PDU_BSSGP exp_rx;
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_lac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_lac), testcasename(), 10);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for unknown Location Area */
+private function f_TC_paging_ps_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var GSM_Types.LocationAreaIdentification unknown_la := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ };
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4LAC(unknown_la), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_lac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_lac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for Routeing Area */
+private function f_TC_paging_ps_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_rac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_rac), testcasename(), 11);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for unknown Routeing Area */
+private function f_TC_paging_ps_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var RoutingAreaIdentification unknown_ra := {
+ lai := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ },
+ rac := 254
+ };
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4RAC(unknown_ra), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_rac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_rac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for BVCI (one cell) */
+private function f_TC_paging_ps_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* this should be the normal case for MS in READY MM state after a lower layer failure */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12);
+ f_cleanup();
+}
+
+
+/* PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
+testcase TC_paging_ps_ptp_bvci_imsi() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_bvci), testcasename(), 12, have_ptmsi:=false);
+ f_cleanup();
+}
+
+/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) */
+testcase TC_paging_ps_reject_ptp_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16);
+ f_cleanup();
+}
+
+/* Rejected PS-PAGING on PTP-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
+private function f_TC_paging_ps_reject_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* first send the PS-PAGING from SGSN -> PCU */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, false, 0);
+ /* then simulate the PS-PAGING-REJECT from the PCU */
+ f_send_paging_ps_rej(use_sig:=false);
+}
+testcase TC_paging_ps_reject_ptp_bvci_imsi() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_reject_ptp_bvci), testcasename(), 16, have_ptmsi:=false);
+ f_cleanup();
+}
+
+/* PS-PAGING on PTP-BVC for unknown BVCI */
+private function f_TC_paging_ps_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
+ f_send_paging_ps_exp_one_bss(ts_BssgpP4Bvci(33333), g_pars.sgsn_idx, false, 0);
+}
+testcase TC_paging_ps_ptp_bvci_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_ptp_bvci_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* DUMMY PAGING PS on PTP BVC */
+private function f_TC_dummy_paging_ps_ptp(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
+ tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := false);
+ f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
+ tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := false)
+}
+testcase TC_dummy_paging_ps_ptp() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_dummy_paging_ps_ptp), testcasename(), 11);
+ f_cleanup();
+}
+
+/* altstep for expecting BSSGP PDU on signaling BVC of given pcu_idx + storing in 'roi' */
+private altstep as_paging_sig_pcu(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
+runs on BSSGP_ConnHdlr {
+[] PCU_SIG[pcu_idx].receive(exp_rx) {
+ if (ro_integer_contains(roi, pcu_idx)) {
+ setverdict(fail, "Received multiple paging on same SIG BVC");
+ }
+ roi := roi & { pcu_idx };
+ repeat;
+ }
+[] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
+ }
+[] PCU_SIG[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging than expected received SIGNALING BVC");
+ }
+[] PCU_PTP[pcu_idx].receive(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}) {
+ setverdict(fail, "Different Paging than expected received PTP BVC");
+ }
+}
+
+type record of default ro_default;
+
+/* send PS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
+private function f_send_paging_ps_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
+{
+ var template (present) PDU_BSSGP exp_rx;
+ exp_rx := f_send_paging_ps(p4, sgsn_idx, true);
+
+ /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
+ defaults := defaults & { d };
+ }
+ f_sleep(2.0);
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+ log("Paging received on PCU ", g_roi);
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ var boolean rx_on_i := ro_integer_contains(g_roi, i);
+ var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
+ if (exp_on_i and not rx_on_i) {
+ setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
+ }
+ if (not exp_on_i and rx_on_i) {
+ setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
+ }
+ }
+ setverdict(pass);
+}
+
+/* Send PAGING-PS-REJECT on SIG BVC, expect it to arrive on the "right" SGSN */
+private function f_send_paging_ps_rej(boolean use_sig := true, integer pcu_idx := 0) runs on BSSGP_ConnHdlr
+{
+ var template (value) PDU_BSSGP pdu_tx;
+ var template (present) PDU_BSSGP exp_rx;
+ var PDU_BSSGP pdu_rx;
+ timer T := 5.0;
+ var template (omit) GsmTmsi tmsi_int := omit;
+
+ if (ispresent(g_pars.p_tmsi)) {
+ tmsi_int := oct2int(g_pars.p_tmsi);
+ }
+
+ pdu_tx := ts_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
+ exp_rx := tr_BSSGP_PAGING_PS_REJ(g_pars.imsi, 23, 42, tmsi_int);
+
+ if (use_sig) {
+ PCU_SIG[pcu_idx].send(pdu_tx);
+ } else {
+ PCU_PTP[pcu_idx].send(pdu_tx);
+ }
+ T.start;
+ alt {
+ [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
+ setverdict(pass);
+ }
+ [use_sig] SGSN_SIG[g_pars.sgsn_idx].receive {
+ setverdict(fail, "Unexpected PDU on SGSN");
+ }
+ [use_sig] any from SGSN_SIG.receive(exp_rx) -> value pdu_rx {
+ setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
+ }
+ [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive(exp_rx) -> value pdu_rx {
+ setverdict(pass);
+ }
+ [not use_sig] SGSN_PTP[g_pars.sgsn_idx].receive {
+ setverdict(fail, "Unexpected PDU on SGSN");
+ }
+ [not use_sig] any from SGSN_PTP.receive(exp_rx) -> value pdu_rx {
+ setverdict(fail, "PAGING-PS-REJECT arrived on wrong SGSN");
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for PAGING-PS-REJECT");
+ }
+ }
+}
+
+/* PS-PAGING on SIG-BVC for BSS Area */
+private function f_TC_paging_ps_sig_bss(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* we expect the paging to arrive on all three NSE */
+ f_send_paging_ps_exp_multi(ts_BssgpP4BssArea, g_pars.sgsn_idx, {0, 1, 2});
+}
+testcase TC_paging_ps_sig_bss() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_bss), testcasename(), 13);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for Location Area */
+private function f_TC_paging_ps_sig_lac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* The first LAC (13135) is shared by all three NSEs */
+ f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), g_pars.sgsn_idx, {0, 1, 2});
+ /* Reset state */
+ g_roi := {};
+ /* Make LAC (13300) available on pcu index 2 */
+ f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
+ f_send_paging_ps_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[2].cell_id.ra_id.lai), g_pars.sgsn_idx, {2});
+}
+testcase TC_paging_ps_sig_lac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_lac), testcasename(), 14);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for unknown Location Area */
+private function f_TC_paging_ps_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var GSM_Types.LocationAreaIdentification unknown_la := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ };
+ f_send_paging_ps_exp_no_bss(ts_BssgpP4LAC(unknown_la), g_pars.sgsn_idx, true);
+}
+testcase TC_paging_ps_sig_lac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_lac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for Routeing Area */
+private function f_TC_paging_ps_sig_rac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* Only PCU index 0 has a matching BVC with the RA ID */
+ f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), g_pars.sgsn_idx, {0});
+ g_roi := {};
+ /* PCU index 1 and 2 have a matching BVC with the RA ID */
+ f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), g_pars.sgsn_idx, {1, 2});
+ g_roi := {};
+ /* PCU index 2 has two matching BVCs with the RA ID */
+ f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
+ f_send_paging_ps_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), g_pars.sgsn_idx, {2});
+}
+testcase TC_paging_ps_sig_rac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_rac), testcasename(), 15);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for unknown Routeing Area */
+private function f_TC_paging_ps_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var RoutingAreaIdentification unknown_ra := {
+ lai := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ },
+ rac := 254
+ };
+ f_send_paging_ps_exp_no_bss(ts_BssgpP4RAC(unknown_ra), g_pars.sgsn_idx, true);
+}
+testcase TC_paging_ps_sig_rac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_rac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for BVCI (one cell) */
+private function f_TC_paging_ps_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, {0});
+}
+testcase TC_paging_ps_sig_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
+testcase TC_paging_ps_sig_bvci_imsi() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_bvci), testcasename(), 16, have_ptmsi:=false);
+ f_cleanup();
+}
+
+/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) */
+private function f_TC_paging_ps_reject_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* first send the PS-PAGING from SGSN -> PCU */
+ f_send_paging_ps_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), g_pars.sgsn_idx, {0});
+ /* then simulate the PS-PAGING-REJECT from the PCU */
+ f_send_paging_ps_rej(use_sig:=true);
+
+}
+testcase TC_paging_ps_reject_sig_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16);
+ f_cleanup();
+}
+
+/* Rejected PS-PAGING on SIG-BVC for BVCI (one cell) using IMSI only (no P-TMSI allocated) */
+testcase TC_paging_ps_reject_sig_bvci_imsi() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_reject_sig_bvci), testcasename(), 16, have_ptmsi:=false);
+ f_cleanup();
+}
+
+/* PS-PAGING on SIG-BVC for unknown BVCI */
+private function f_TC_paging_ps_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_send_paging_ps_exp_no_bss(ts_BssgpP4Bvci(33333), g_pars.sgsn_idx, true);
+}
+testcase TC_paging_ps_sig_bvci_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_ps_sig_bvci_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* DUMMY PAGING PS on SIG BVC */
+private function f_TC_dummy_paging_ps_sig(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_sgsn2pcu(ts_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit),
+ tr_BSSGP_DUMMY_PAGING_PS(g_pars.imsi, omit), use_sig := true);
+ f_pcu2sgsn(ts_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5),
+ tr_BSSGP_DUMMY_PAGING_PS_RESP(g_pars.imsi, 1, 5), use_sig := true)
+}
+testcase TC_dummy_paging_ps_sig() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_dummy_paging_ps_sig), testcasename(), 11);
+ f_cleanup();
+}
+
+
+
+/***********************************************************************
+ * PAGING CS procedure
+ ***********************************************************************/
+
+private function f_send_paging_cs(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false)
+runs on BSSGP_ConnHdlr return template (present) PDU_BSSGP {
+ var template (value) PDU_BSSGP pdu_tx;
+ var template (present) PDU_BSSGP pdu_rx;
+ /* we always specify '0' as BVCI in the templates below, as we override it with
+ * 'p4' later anyway */
+ pdu_rx := tr_BSSGP_CS_PAGING(0);
+ pdu_rx.pDU_BSSGP_PAGING_CS.iMSI := tr_BSSGP_IMSI(g_pars.imsi);
+ if (ispresent(g_pars.p_tmsi)) {
+ pdu_tx := ts_BSSGP_CS_PAGING_PTMSI(0, g_pars.imsi, oct2int(g_pars.p_tmsi));
+ pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := tr_BSSGP_TMSI(oct2int(g_pars.p_tmsi));
+ } else {
+ pdu_tx := ts_BSSGP_CS_PAGING_IMSI(0, g_pars.imsi);
+ pdu_rx.pDU_BSSGP_PAGING_CS.tMSI := omit;
+ }
+ pdu_tx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
+ pdu_rx.pDU_BSSGP_PAGING_CS.paging_Field4 := p4;
+ if (use_sig == false) {
+ SGSN_PTP[sgsn_idx].send(pdu_tx);
+ } else {
+ SGSN_SIG[sgsn_idx].send(pdu_tx);
+ }
+ return pdu_rx;
+}
+
+/* send paging defined by 'p4' on given SGSN-side index (ptp or signaling) and expect one paging to arrive on
+ * specified PCU index */
+private function f_send_paging_cs_exp_one_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false,integer pcu_idx := 0)
+runs on BSSGP_ConnHdlr {
+ var template (present) PDU_BSSGP exp_rx;
+ var boolean test_done := false;
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
+ /* Expect paging to propagate to the one BSS addressed by the BVCI only */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [not use_sig and not test_done] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ test_done := true;
+ repeat;
+ }
+ [not use_sig] PCU_SIG[pcu_idx].receive(exp_rx) {
+ setverdict(fail, "Received paging on SIGNALING BVC, expected PTP BVC");
+ }
+ [use_sig and not test_done] PCU_SIG[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ test_done := true;
+ repeat;
+ }
+ [use_sig] PCU_PTP[pcu_idx].receive(exp_rx) {
+ setverdict(fail, "Received paging on PTP BVC, expected SIGNALING BVC");
+ }
+ [] any from PCU_PTP.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_SIG.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
+ setverdict(fail, "Different Paging than expected received PTP BVC");
+ }
+ [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
+ setverdict(fail, "Different Paging than expected on SIGNALING BVC");
+ }
+ [not test_done] T.timeout {
+ setverdict(fail, "Timeout while waiting for paging")
+ }
+ [test_done] T.timeout;
+ }
+}
+
+/* send a CS-PAGING but don't expect it to show up on any PTP or SIG BVC */
+private function f_send_paging_cs_exp_no_bss(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ boolean use_sig := false)
+runs on BSSGP_ConnHdlr {
+ var template (present) PDU_BSSGP exp_rx;
+ exp_rx := f_send_paging_cs(p4, sgsn_idx, use_sig);
+ /* Expect paging to propagate to no BSS */
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] any from PCU_PTP.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_SIG.receive(exp_rx) {
+ setverdict(fail, "Paging received on unexpected BVC");
+ }
+ [] any from PCU_PTP.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
+ setverdict(fail, "Different Paging received on PTP BVC");
+ }
+ [] any from PCU_SIG.receive(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}) {
+ setverdict(fail, "Different Paging received on SIGNALING BVC");
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+}
+
+private function f_TC_paging_cs_ptp_bss(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4BssArea, 0, false, 0);
+}
+testcase TC_paging_cs_ptp_bss() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_bss), testcasename(), 17);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for Location Area */
+private function f_TC_paging_cs_ptp_lac(charstring id) runs on BSSGP_ConnHdlr
+{
+ var template (present) PDU_BSSGP exp_rx;
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_lac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_lac), testcasename(), 18);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for unknown Location Area */
+private function f_TC_paging_cs_ptp_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var GSM_Types.LocationAreaIdentification unknown_la := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ };
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown LAC */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4LAC(unknown_la), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_lac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_lac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for Routeing Area */
+private function f_TC_paging_cs_ptp_rac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* doesn't really make sense: Sending to a single BVCI means the message ends up
+ * at that BVC (cell) only, and paging all over the BSS area is not possible */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_rac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_rac), testcasename(), 19);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for unknown Routeing Area */
+private function f_TC_paging_cs_ptp_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var RoutingAreaIdentification unknown_ra := {
+ lai := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ },
+ rac := 254
+ };
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown RAC */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4RAC(unknown_ra), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_rac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_rac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for BVCI (one cell) */
+private function f_TC_paging_cs_ptp_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* this should be the normal case for MS in READY MM state after a lower layer failure */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_bvci), testcasename(), 20);
+ f_cleanup();
+}
+
+/* CS-PAGING on PTP-BVC for unknown BVCI */
+private function f_TC_paging_cs_ptp_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* as it's sent on the PTP BVC, we expect it to pass even for unknown BVCI */
+ f_send_paging_cs_exp_one_bss(ts_BssgpP4Bvci(33333), 0, false, 0);
+}
+testcase TC_paging_cs_ptp_bvci_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_ptp_bvci_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* send CS-PAGING on SIG BVC, expect it to arrive on given list of PCU indexes */
+private function f_send_paging_cs_exp_multi(template (value) Paging_Field4 p4, integer sgsn_idx := 0,
+ ro_integer exp_on_pcu_idx) runs on BSSGP_ConnHdlr
+{
+ var template (present) PDU_BSSGP exp_rx;
+ exp_rx := f_send_paging_cs(p4, 0, true);
+
+ /* FIXME: make sure the relevant BVCs/BSS are connected to the ports! */
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ var default d := activate(as_paging_sig_pcu(i, exp_rx, g_roi));
+ defaults := defaults & { d };
+ }
+ f_sleep(2.0);
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+ log("Paging received on PCU ", g_roi);
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
+ var boolean rx_on_i := ro_integer_contains(g_roi, i);
+ var boolean exp_on_i := ro_integer_contains(exp_on_pcu_idx, i);
+ if (exp_on_i and not rx_on_i) {
+ setverdict(fail, "PS-PAGING not received on ", mp_nsconfig_pcu[i].nsei);
+ }
+ if (not exp_on_i and rx_on_i) {
+ setverdict(fail, "PS-PAGING not expected but received on ", mp_nsconfig_pcu[i].nsei);
+ }
+ }
+ setverdict(pass);
+}
+
+/* CS-PAGING on SIG-BVC for BSS Area */
+private function f_TC_paging_cs_sig_bss(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* we expect the paging to arrive on all three NSE */
+ f_send_paging_cs_exp_multi(ts_BssgpP4BssArea, 0, {0, 1, 2});
+}
+testcase TC_paging_cs_sig_bss() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_bss), testcasename(), 13);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for Location Area */
+private function f_TC_paging_cs_sig_lac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* The first LAC (13135) is shared by all three NSEs */
+ f_send_paging_cs_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[0].cell_id.ra_id.lai), 0, {0, 1, 2});
+ /* Reset state */
+ g_roi := {};
+ /* Make LAC (13300) available on pcu index 2 */
+ f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
+ f_send_paging_cs_exp_multi(ts_BssgpP4LAC(pcu_bvc_cfg[2].cell_id.ra_id.lai), 0, {2});
+}
+testcase TC_paging_cs_sig_lac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_lac), testcasename(), 14);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for unknown Location Area */
+private function f_TC_paging_cs_sig_lac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var GSM_Types.LocationAreaIdentification unknown_la := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ };
+ f_send_paging_cs_exp_no_bss(ts_BssgpP4LAC(unknown_la), 0, true);
+}
+testcase TC_paging_cs_sig_lac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_lac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for Routeing Area */
+private function f_TC_paging_cs_sig_rac(charstring id) runs on BSSGP_ConnHdlr
+{
+ /* Only PCU index 0 has a matching BVC with the RA ID */
+ f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[0].cell_id.ra_id), 0, {0});
+ g_roi := {};
+ /* PCU index 1 and 2 have a matching BVC with the RA ID */
+ f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {1, 2});
+ g_roi := {};
+ /* PCU index 2 has two matching BVCs with the RA ID */
+ f_connect_to_pcu_bvc(port_idx := 2, nse_idx := 2, bvc_idx := 1);
+ f_send_paging_cs_exp_multi(ts_BssgpP4RAC(pcu_bvc_cfg[2].cell_id.ra_id), 0, {2});
+}
+testcase TC_paging_cs_sig_rac() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_rac), testcasename(), 15);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for unknown Routeing Area */
+private function f_TC_paging_cs_sig_rac_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ var RoutingAreaIdentification unknown_ra := {
+ lai := {
+ mcc_mnc := '567F99'H,
+ lac := 33333
+ },
+ rac := 254
+ };
+ f_send_paging_cs_exp_no_bss(ts_BssgpP4RAC(unknown_ra), 0, true);
+}
+testcase TC_paging_cs_sig_rac_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_rac_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for BVCI (one cell) */
+private function f_TC_paging_cs_sig_bvci(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_send_paging_cs_exp_multi(ts_BssgpP4Bvci(pcu_bvc_cfg[0].bvci), 0, {0});
+}
+testcase TC_paging_cs_sig_bvci() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_bvci), testcasename(), 16);
+ f_cleanup();
+}
+
+/* CS-PAGING on SIG-BVC for unknown BVCI */
+private function f_TC_paging_cs_sig_bvci_unknown(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_send_paging_cs_exp_no_bss(ts_BssgpP4Bvci(33333), 0, true);
+}
+testcase TC_paging_cs_sig_bvci_unknown() runs on test_CT {
+ f_init();
+ f_start_handlers(refers(f_TC_paging_cs_sig_bvci_unknown), testcasename(), 11);
+ f_cleanup();
+}
+
+/***********************************************************************
+ * FLUSH-LL procedure
+ ***********************************************************************/
+
+private function f_TC_flush_ll_bvci_new(charstring id) runs on BSSGP_ConnHdlr {
+ var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
+ var integer i;
+ for (i := 0; i < 10; i := i+1) {
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_FLUSH_LL(g_pars.tlli, bvci, bvci_new := bvci);
+
+ f_sgsn2pcu(pdu_tx, pdu_rx, use_sig := true);
+
+ pdu_tx := ts_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(1, 1), 23, bvci_new := bvci);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(1, 1), 23, bvci_new := bvci);
+
+ f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
+ }
+ setverdict(pass);
+}
+
+testcase TC_flush_ll_bvci_new() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_flush_ll_bvci_new), testcasename(), 6);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+private function f_TC_flush_ll_no_bvci_new(charstring id) runs on BSSGP_ConnHdlr {
+ var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
+ var integer i;
+ for (i := 0; i < 10; i := i+1) {
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_FLUSH_LL(g_pars.tlli, bvci);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_FLUSH_LL(g_pars.tlli, bvci);
+
+ f_sgsn2pcu(pdu_tx, pdu_rx, use_sig := true);
+
+ pdu_tx := ts_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ pdu_rx := tr_BSSGP_FLUSH_LL_ACK(g_pars.tlli, int2oct(0, 1), 23);
+
+ f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
+ }
+ setverdict(pass);
+}
+
+testcase TC_flush_ll_no_bvci_new() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_flush_ll_no_bvci_new), testcasename(), 6);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+/***********************************************************************
+ * SGSN-INVOKE-TRACE procedure
+ ***********************************************************************/
+
+private altstep as_bssgp_g_pcu_count(integer pcu_idx, template (present) PDU_BSSGP exp_rx, inout ro_integer roi)
+runs on GlobalTest_CT {
+[] G_PCU[pcu_idx].receive(exp_rx) from g_pcu[pcu_idx].vc_BSSGP {
+ if (ro_integer_contains(roi, pcu_idx)) {
+ setverdict(fail, "Received multiple on same SIG BVC");
+ }
+ roi := roi & { pcu_idx };
+ repeat;
+ }
+}
+/* send a INVOKE-TRACE from SGSN and expect to receive a copy on each NSE */
+testcase TC_trace() runs on GlobalTest_CT
+{
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_global_init();
+
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
+ var template (present) PDU_BSSGP exp_rx := ts_BSSGP_INVOKE_TRACE('23'O, '4321'O);
+
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
+ }
+ G_SGSN[0].send(pdu_tx);
+ f_sleep(2.0);
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ if (not ro_integer_contains(g_roi, i)) {
+ setverdict(fail, "Failed to receive TRACE on PCU index ", i);
+ }
+ }
+ setverdict(pass);
+
+ f_cleanup();
+}
+
+/***********************************************************************
+ * LLC-DISCARDED procedure
+ ***********************************************************************/
+
+private function f_TC_llc_discarded(charstring id) runs on BSSGP_ConnHdlr {
+ var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
+
+ var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_LLC_DISCARDED(g_pars.tlli, 23, bvci, 2342);
+
+ f_pcu2sgsn(pdu_tx, pdu_rx, use_sig := true);
+
+ setverdict(pass);
+}
+/* Send a LLC-DISCARDED from BSS side and expect it to show up on SGSN (SIG BVC) */
+testcase TC_llc_discarded() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_llc_discarded), testcasename(), 6);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+/***********************************************************************
+ * OVERLOAD procedure
+ ***********************************************************************/
+
+/* Send an OVERLOAD from SGSN side and expect it to show up on each PCU (SIG BVC) */
+testcase TC_overload() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+
+ var template (value) PDU_BSSGP pdu_tx := ts_OVERLOAD('1'B);
+ var template (present) PDU_BSSGP exp_rx := tr_OVERLOAD('1'B);
+
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ activate(as_bssgp_g_pcu_count(i, exp_rx, g_roi));
+ }
+ G_SGSN[0].send(pdu_tx);
+ f_sleep(2.0);
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ if (not ro_integer_contains(g_roi, i)) {
+ setverdict(fail, "Failed to receive OVERLOAD on PCU index ", i);
+ }
+ }
+ setverdict(pass);
+
+ f_cleanup();
+}
+
+/***********************************************************************
+ * BVC-BLOCK / BVC-UNBLOCK procedure
+ ***********************************************************************/
+
+private function f_block_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
+{
+ var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
+ var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
+ var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
+
+ SGSN_MGMT.clear;
+ PCU_MGMT.clear;
+
+ /* block the PTP BVC from the PCU side */
+ PCU_MGMT.send(BssgpBlockRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to bvc_ct;
+ /* expect state on both PCU and SGSN side to change */
+ interleave {
+ [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from bvc_ct;
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(mp_nsconfig_sgsn[0].nsei, bvc_cfg.bvci, BVC_S_BLOCKED));
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(mp_nsconfig_sgsn[1].nsei, bvc_cfg.bvci, BVC_S_BLOCKED));
+ /* Doesn't auto-scale with NUM_SGSN */
+ }
+ setverdict(pass);
+}
+testcase TC_bvc_block_ptp() runs on test_CT
+{
+ f_init();
+ f_sleep(1.0);
+ f_block_ptp_bvc_from_pcu(0, 0);
+ f_cleanup();
+}
+
+private function f_unblock_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
+{
+ var BSSGP_BVC_CT bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
+ var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
+ var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
+
+ SGSN_MGMT.clear;
+ PCU_MGMT.clear;
+
+ /* block the PTP BVC from the PCU side */
+ PCU_MGMT.send(BssgpUnblockRequest:{}) to bvc_ct;
+ /* expect state on both PCU and SGSN side to change */
+ interleave {
+ [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_UNBLOCKED)) from bvc_ct;
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(mp_nsconfig_sgsn[0].nsei, bvc_cfg.bvci, BVC_S_UNBLOCKED));
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(mp_nsconfig_sgsn[1].nsei, bvc_cfg.bvci, BVC_S_UNBLOCKED));
+ /* Doesn't auto-scale with NUM_SGSN */
+ }
+ setverdict(pass);
+}
+testcase TC_bvc_unblock_ptp() runs on test_CT
+{
+ f_init();
+ f_sleep(1.0);
+ f_block_ptp_bvc_from_pcu(0, 0);
+ f_sleep(1.0);
+ f_unblock_ptp_bvc_from_pcu(0, 0);
+ f_cleanup();
+}
+
+/***********************************************************************
+ * BVC-RESET procedure
+ ***********************************************************************/
+private altstep as_count_bvc_reset(integer sgsn_idx, BssgpBvci bvci, inout roro_integer roroi)
+runs on test_CT {
+ var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(sgsn_idx, bvci);
+ [] SGSN_MGMT.receive(BssgpResetIndication:{bvci}) from sgsn_bvc_ct {
+ roroi[sgsn_idx] := roroi[sgsn_idx] & { bvci };
+ repeat;
+ }
+}
+private altstep as_ignore_status(BSSGP_BVC_MGMT_PT pt) {
+[] pt.receive(BssgpStatusIndication:?) { repeat; }
+}
+private function f_get_sgsn_bvc_ct(integer sgsn_idx, BssgpBvci bvci) runs on test_CT return BSSGP_BVC_CT {
+ for (var integer i := 0; i < lengthof(g_sgsn[sgsn_idx].cfg.bvc); i := i+1) {
+ if (g_sgsn[sgsn_idx].cfg.bvc[i].bvci == bvci) {
+ return g_sgsn[sgsn_idx].vc_BSSGP_BVC[i];
+ }
+ }
+ return null;
+}
+private function f_reset_ptp_bvc_from_pcu(integer pcu_idx, integer bvc_idx) runs on test_CT
+{
+ var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
+ var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
+ var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
+ var ro_default defaults;
+ var integer i;
+
+ SGSN_MGMT.clear;
+ PCU_MGMT.clear;
+
+ for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ g_roroi[i] := {};
+ }
+
+ /* block the PTP BVC from the PCU side */
+ PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to pcu_bvc_ct;
+
+ /* expect state on both PCU and SGSN side to change */
+ defaults := { activate(as_ignore_status(SGSN_MGMT)) };
+
+ /* Activate altsteps: One for each SGSN */
+ for (i := 0; i < lengthof(g_sgsn); i := i+1) {
+ var default d := activate(as_count_bvc_reset(i, bvc_cfg.bvci, g_roroi));
+ defaults := defaults & { d };
+ }
+
+ timer T := 3.0;
+ T.start;
+ alt {
+ [] PCU_MGMT.receive(tr_BssgpStsInd(nsei_pcu, bvc_cfg.bvci, BVC_S_BLOCKED)) from pcu_bvc_ct {
+ g_roi := g_roi & { bvc_cfg.bvci };
+ repeat;
+ }
+ [] T.timeout;
+ }
+
+ for (i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ /* Check if BVC-RESET was received at all SGSNs */
+ for (i := 0; i < lengthof(g_sgsn); i := i+1) {
+ if (not ro_integer_contains(g_roroi[i], bvc_cfg.bvci)) {
+ setverdict(fail, "Missing SGSN[", i, "] BVC-BLOCK of BVCI=", bvc_cfg.bvci);
+ }
+ }
+
+ setverdict(pass);
+ f_cleanup();
+}
+/* Send a BVC-RESET for a PTP BVC from the BSS side: expect it to propagate */
+testcase TC_bvc_reset_ptp_from_bss() runs on test_CT
+{
+ f_init();
+ f_sleep(3.0);
+ f_reset_ptp_bvc_from_pcu(0, 0);
+ f_cleanup();
+}
+
+private altstep as_count_bvc_sts(integer sgsn_idx, BssgpBvci bvci,
+ template (present) BvcState exp_bvc_state, inout roro_integer roroi)
+runs on test_CT {
+ var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(sgsn_idx, bvci);
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvci, exp_bvc_state)) from sgsn_bvc_ct {
+ roroi[sgsn_idx] := roroi[sgsn_idx] & { bvci };
+ repeat;
+ }
+}
+
+private altstep as_count_bvc_block(integer sgsn_idx, BssgpBvci bvci, inout roro_integer roroi)
+runs on test_CT {
+ [] as_count_bvc_sts(sgsn_idx, bvci, BVC_S_BLOCKED, roroi);
+}
+
+private altstep as_count_bvc_unblock(integer sgsn_idx, BssgpBvci bvci, inout roro_integer roroi)
+runs on test_CT {
+ [] as_count_bvc_sts(sgsn_idx, bvci, BVC_S_UNBLOCKED, roroi);
+}
+
+/* reset the signaling BVC from one BSS; expect no signaling BVC reset on SGSN; but BVC-BLOCK for PTP */
+testcase TC_bvc_reset_sig_from_bss() runs on test_CT {
+
+ f_init();
+ f_sleep(3.0);
+
+ for (var integer i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
+ g_roroi[i] := {};
+ }
+
+ /* Start BVC-RESET procedure for BVCI=0 */
+ PCU_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_pcu[0].vc_BSSGP;
+
+ /* Activate altsteps: One for each PTP BVC and SGSN within that PCUs NSE */
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
+ var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
+ for (var integer j := 0; j < lengthof(g_sgsn); j := j+1) {
+ var default d := activate(as_count_bvc_block(j, bvcc.bvci, g_roroi));
+ defaults := defaults & { d };
+ }
+ }
+
+ timer T := 3.0;
+ T.start;
+ alt {
+ [] SGSN_MGMT.receive(BssgpResetIndication:{0}) {
+ setverdict(fail, "BSS-side Reset of BVCI=0 should not propagate");
+ }
+ [] T.timeout;
+ }
+
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ /* check if BVC-block was received on all expected BVC/SGSN */
+ for (var integer i := 0; i < lengthof(g_pcu[0].cfg.bvc); i := i+1) {
+ var BssgpBvcConfig bvcc := g_pcu[0].cfg.bvc[i];
+ for (var integer j := 0; j < lengthof(g_sgsn); j := j+1) {
+ if (not ro_integer_contains(g_roroi[j], bvcc.bvci)) {
+ setverdict(fail, "Missing SGSN[", j, "] BVC-BLOCK of BVCI=", bvcc.bvci);
+ }
+ }
+ }
+
+ /* check if BVC-block was not received on any unexpected BVC is not required as
+ * such a message would basically run into 'no matching clause' */
+ setverdict(pass);
+ f_cleanup();
+}
+
+private function f_reset_ptp_bvc_from_sgsn(integer pcu_idx, integer bvc_idx) runs on test_CT
+{
+ var BSSGP_BVC_CT pcu_bvc_ct := g_pcu[pcu_idx].vc_BSSGP_BVC[bvc_idx];
+ var BssgpBvcConfig bvc_cfg := g_pcu[pcu_idx].cfg.bvc[bvc_idx];
+ var Nsei nsei_pcu := g_pcu[pcu_idx].cfg.nsei;
+ var BSSGP_BVC_CT sgsn_bvc_ct := f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
+ var default d;
+
+ SGSN_MGMT.clear;
+ PCU_MGMT.clear;
+
+ /* block the PTP BVC from the PCU side */
+ SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to sgsn_bvc_ct;
+ /* expect state on both PCU and SGSN side to change */
+ d := activate(as_ignore_status(PCU_MGMT));
+ interleave {
+ [] SGSN_MGMT.receive(tr_BssgpStsInd(?, bvc_cfg.bvci, BVC_S_BLOCKED)) from sgsn_bvc_ct;
+ [] PCU_MGMT.receive(BssgpResetIndication:{bvc_cfg.bvci}) from pcu_bvc_ct;
+ }
+ deactivate(d);
+ setverdict(pass);
+}
+
+/* Send a BVC-RESET for a PTP BVC from the SGSN side: expect it to propagate */
+testcase TC_bvc_reset_ptp_from_sgsn() runs on test_CT
+{
+ f_init();
+ f_sleep(3.0);
+ f_reset_ptp_bvc_from_sgsn(0, 0);
+ f_cleanup();
+}
+
+/* Send a BVC-RESET for a blocked PTP BVC from the SGSN side: expect NS-STATUS with cause BVCI unknown */
+testcase TC_bvc_reset_blocked_ptp_from_sgsn() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_sleep(3.0);
+ /* Make sure NS for BVC is down and try again */
+ f_disable_ns_pcu(0);
+ f_sleep(10.0);
+
+ var BssgpBvcConfig bvc_cfg := g_pcu[0].cfg.bvc[0];
+ SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to f_get_sgsn_bvc_ct(0, bvc_cfg.bvci);
+
+ /* Check for NS-STATUS with BVCI unknown, ignore other messages */
+ var template (present) PDU_BSSGP exp_rx :=
+ tr_BSSGP_STATUS(bvc_cfg.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, ?);
+
+ alt {
+ [] G_SGSN[0].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] SGSN_MGMT.receive(BssgpStatusIndication:{*, bvc_cfg.bvci, BVC_S_UNBLOCKED}) {
+ setverdict(fail, "BVC unblocked that should be gone on BSS side");
+ }
+ [] SGSN_MGMT.receive {
+ repeat;
+ }
+ [] G_SGSN[0].receive {
+ repeat;
+ }
+ }
+
+ f_cleanup();
+}
+
+private altstep as_ignore_mgmt(BSSGP_BVC_MGMT_PT pt) {
+ [] pt.receive {repeat; }
+}
+
+private altstep as_count_bvc0_block(integer pcu_idx, Nsei nsei, inout ro_integer roi)
+runs on test_CT {
+ var BSSGP_CT pcu_ct := g_pcu[pcu_idx].vc_BSSGP;
+ [] PCU_MGMT.receive(BssgpResetIndication:{0}) from pcu_ct {
+ roi := roi & { nsei };
+ repeat;
+ }
+}
+
+/* reset the signaling BVC from the SGSN; expect all signaling BVC on all BSS to be reset */
+testcase TC_bvc_reset_sig_from_sgsn() runs on test_CT {
+
+ f_init();
+ f_sleep(3.0);
+
+ SGSN_MGMT.clear;
+ PCU_MGMT.clear;
+
+ /* Start BVC-RESET procedure for BVCI=0 */
+ SGSN_MGMT.send(BssgpResetRequest:{cause:=BSSGP_CAUSE_OM_INTERVENTION}) to g_sgsn[0].vc_BSSGP;
+
+ /* Defaults match in reverse activation order, this one is a catch-all for Status indications
+ * and reset indications sent from other components (like the ptp_bvcs). If we don't drain
+ * the port and a different message sits at the front we wait forever and fail the test.
+ */
+ var ro_default defaults := { activate(as_ignore_mgmt(PCU_MGMT)) };
+
+ /* Activate altsteps: One for each PCU NSE */
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ var NSConfiguration nscfg := mp_nsconfig_pcu[i];
+ var default d := activate(as_count_bvc0_block(i, nscfg.nsei, g_roi));
+ defaults := defaults & { d };
+ }
+
+ f_sleep(3.0);
+
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ /* check if BVC-block was received on all expected BVC */
+ for (var integer i := 0; i < lengthof(g_pcu); i := i+1) {
+ var NSConfiguration nscfg := mp_nsconfig_pcu[i];
+ if (not ro_integer_contains(g_roi, nscfg.nsei)) {
+ setverdict(fail, "Missing PCU-side BVC-RESET of BVCI=0 on PCU index ", i);
+ }
+ }
+
+ /* check if BVC-block was not received on any unexpected BVC is not required as
+ * such a message would basically run into 'no matching clause' */
+
+ f_cleanup();
+}
+
+/***********************************************************************
+ * FLOW-CONTROL-BVC procedure
+ ***********************************************************************/
+
+private altstep as_g_count_sgsn(integer sgsn_idx, inout ro_integer roi,
+ template PDU_BSSGP exp_rx, template (omit) PDU_BSSGP tx_reply)
+runs on GlobalTest_CT {
+ [] G_SGSN[sgsn_idx].receive(exp_rx) {
+ roi := roi & { sgsn_idx };
+ if (ispresent(tx_reply)) {
+ G_SGSN[sgsn_idx].send(tx_reply);
+ }
+ repeat;
+ }
+}
+/* Send FC-BVC from simulated PCU; expect each SGSN to receive it; expect PCU to receive ACK */
+testcase TC_fc_bvc() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init_ptp();
+
+ var template (value) PDU_BSSGP pdu_tx := ts_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP pdu_rx := tr_BVC_FC_BVC(10240, 2000, 1024, 1000, '01'O);
+ var template (value) PDU_BSSGP ack_tx :=
+ ts_BVC_FC_BVC_ACK(pdu_tx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value);
+
+ /* Send a FC-BVC from BSS to gbproxy, expect an ACK in response */
+ G_PCU[0].send(pdu_tx);
+
+ /* Activate altsteps: One for each SGSN-side PTP BVC port */
+ var ro_default defaults := {};
+ for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
+ var default d := activate(as_g_count_sgsn(i, g_roi, pdu_rx, ack_tx));
+ defaults := defaults & { d };
+ }
+
+ f_sleep(3.0);
+
+ for (var integer i := 0; i < lengthof(defaults); i := i+1) {
+ deactivate(defaults[i]);
+ }
+
+ /* check if BVC-block was received on all expected BVC */
+ for (var integer i := 0; i < lengthof(g_sgsn); i := i+1) {
+ if (not ro_integer_contains(g_roi, i)) {
+ setverdict(fail, "Missing BVC-FLOW-CONTROL on SGSN index ", i);
+ }
+ }
+
+ /* Expect ACK on PCU side */
+ G_PCU[0].receive(ack_tx);
+
+ setverdict(pass);
+
+ f_cleanup();
+}
+
+/***********************************************************************
+ * FLOW-CONTROL-MS procedure
+ ***********************************************************************/
+
+private function f_TC_fc_ms(charstring id) runs on BSSGP_ConnHdlr {
+ var BssgpBvci bvci := g_pars.pcu[0].cfg.bvc[0].bvci;
+
+ var template (value) PDU_BSSGP fc_tx := ts_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
+ /* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
+ var template (present) PDU_BSSGP fc_rx := tr_BVC_FC_MS(g_pars.tlli, 100, 200, '12'O);
+ var template (value) PDU_BSSGP ack_tx := ts_BVC_FC_MS_ACK(g_pars.tlli, '12'O);
+
+ f_pcu2sgsn(fc_tx, fc_rx, use_sig := false);
+ f_sgsn2pcu(ack_tx, ack_tx, use_sig := false);
+
+ setverdict(pass);
+}
+/* Send a FLOW-CONTROL-MS from BSS side and expect it to show up on SGSN (PTP BVC) */
+testcase TC_fc_ms() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_fc_ms), testcasename(), 21);
+ /* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
+ f_cleanup();
+}
+
+/***********************************************************************
+ * MS-REGISTRATION ENQUIRY procedure
+ ***********************************************************************/
+
+private function f_TC_ms_reg_enq(charstring id) runs on BSSGP_ConnHdlr
+{
+ f_pcu2any_sgsn(ts_BSSGP_MS_REG_ENQ(g_pars.imsi), tr_BSSGP_MS_REG_ENQ(g_pars.imsi), use_sig := true);
+ f_sgsn2pcu(ts_BSSGP_MS_REW_ENQ_RESP(g_pars.imsi, omit), tr_BSSGP_MS_REW_ENQ_RESP(g_pars.imsi, omit), use_sig := true);
+}
+testcase TC_ms_reg_enq() runs on test_CT
+{
+ f_init();
+ f_start_handlers(refers(f_TC_ms_reg_enq), testcasename(), 22);
+ f_cleanup();
+}
+
+/***********************************************************************
+ * RIM (RAN Information Management)
+ ***********************************************************************/
+
+/* Our tests here are rather synthetic, as they don't reflect normal message flows
+ as they would be observed in a live network. However, for testing gbproxy, this shouldn't
+ matter as gbproxy is not concerned with anything but the source / destination routing
+ information */
+
+/* gbproxy must route all unknown RIM Routing Info (Cell Id) to the SGSN. We just define
+ one here of which we know it is not used among the [simulated] PCUs */
+const BssgpCellId cell_id_sgsn := {
+ ra_id := {
+ lai := {
+ mcc_mnc := c_mcc_mnc,
+ lac := 65534
+ },
+ rac := 0
+ },
+ cell_id := 65533
+};
+
+/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on any of our SGSN (RIM can be routed anywhere) */
+friend function f_rim_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer pcu_idx := 0) runs on GlobalTest_CT {
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ RIM_PCU[pcu_idx].send(tx);
+ T.start;
+ alt {
+ [] any from RIM_SGSN.receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] any from RIM_SGSN.receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on SGSN side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on SGSN side: ", exp_rx));
+ }
+ }
+}
+
+/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
+friend function f_rim_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer sgsn_idx := 0, integer pcu_idx := 0) runs on GlobalTest_CT {
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ RIM_SGSN[sgsn_idx].send(tx);
+ T.start;
+ alt {
+ [] RIM_PCU[pcu_idx].receive(exp_rx) {
+ setverdict(pass);
+ }
+ [] RIM_PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on PCU side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on PCU side: ", exp_rx));
+ }
+ }
+}
+
+/* Send 'tx' on PTP-BVCI from SRC-PCU; expect 'rx' on DST-PCU */
+friend function f_rim_pcu2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
+ integer src_pcu_idx, integer dst_pcu_idx) runs on GlobalTest_CT {
+ var integer rx_idx;
+ var PDU_BSSGP rx;
+ timer T := 2.0;
+
+ RIM_PCU[src_pcu_idx].send(tx);
+ T.start;
+ alt {
+ [] RIM_PCU[dst_pcu_idx].receive(exp_rx) -> value rx{
+ setverdict(pass);
+ }
+ [] any from RIM_PCU.receive(exp_rx) -> @index value rx_idx {
+ setverdict(fail, "Received RIM on wrong PCU[", rx_idx ,"], expected on PCU[", dst_pcu_idx, "]");
+ }
+ [] any from RIM_SGSN.receive(exp_rx) {
+ setverdict(fail, "Received RIM on SGSN but expected it on other PCU");
+ }
+ [] any from RIM_SGSN.receive(PDU_BSSGP:?) -> value rx {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected BSSGP on SGSN side: ", rx));
+ }
+ [] T.timeout {
+ f_shutdown(__FILE__, __LINE__, fail,
+ log2str("Timeout waiting for BSSGP on SGSN side: ", exp_rx));
+ }
+ }
+}
+
+
+type function rim_fn(integer sgsn_idx, integer pcu_idx, integer bvc_idx) runs on GlobalTest_CT;
+
+/* helper function for the RIM test cases: Execute 'fn' for each BVC on each PCU for
+ each SGSN */
+private function f_rim_iterator(rim_fn fn) runs on GlobalTest_CT
+{
+ var integer sgsn_idx, pcu_idx, bvc_idx;
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx+1) {
+ for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx+1) {
+ for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx+1) {
+ log("Testing RIM SGSN[", sgsn_idx, "] <-> PCU[", pcu_idx, "][", bvc_idx, "]");
+ fn.apply(sgsn_idx, pcu_idx, bvc_idx);
+ }
+ }
+ }
+}
+
+/* RAN-INFORMATION-REQUEST */
+private function f_TC_rim_info_req(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) RAN_Information_Request_RIM_Container cont_tx;
+ var template RAN_Information_Request_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_cid(cell_id_sgsn);
+
+ cont_tx := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+ cont_rx := tr_RAN_Information_Request_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+
+ f_rim_pcu2sgsn(ts_RAN_INFORMATION_REQUEST(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_RAN_INFORMATION_REQUEST(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+
+ f_rim_sgsn2pcu(ts_RAN_INFORMATION_REQUEST(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_RAN_INFORMATION_REQUEST(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+}
+testcase TC_rim_info_req() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_info_req));
+ f_cleanup();
+}
+
+/* RAN-INFORMATION */
+private function f_TC_rim_info(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) RAN_Information_RIM_Container cont_tx;
+ var template RAN_Information_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_cid(cell_id_sgsn);
+
+ cont_tx := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+
+ cont_rx := tr_RAN_Information_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+
+ f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+
+ f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+}
+testcase TC_rim_info() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_info));
+ f_cleanup();
+}
+
+/* RAN-INFORMATION-ACK */
+private function f_TC_rim_info_ack(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) RAN_Information_Ack_RIM_Container cont_tx;
+ var template RAN_Information_Ack_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_cid(cell_id_sgsn);
+
+ cont_tx := ts_RAN_Information_Ack_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0));
+
+ cont_rx := tr_RAN_Information_Ack_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0));
+
+ f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_ACK(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+
+ f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_ACK(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_ACK(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+}
+testcase TC_rim_info_ack() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_info_ack));
+ f_cleanup();
+}
+
+/* RAN-INFORMATION-ERROR */
+private function f_TC_rim_info_error(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) RAN_Information_Error_RIM_Container cont_tx;
+ var template RAN_Information_Error_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_cid(cell_id_sgsn);
+
+ cont_tx := ts_RAN_Information_Error_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_BSSGP_CAUSE(BSSGP_CAUSE_EQUIMENT_FAILURE),
+ omit, valueof(ts_BVC_UNBLOCK(23)));
+
+ cont_rx := tr_RAN_Information_Error_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_BSSGP_CAUSE(BSSGP_CAUSE_EQUIMENT_FAILURE),
+ omit, enc_PDU_BSSGP(valueof(tr_BVC_UNBLOCK(23))));
+
+ f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+
+ f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_ERROR(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+}
+testcase TC_rim_info_error() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_info_error));
+ f_cleanup();
+}
+
+//////////////////
+/* RAN-INFORMATION-APPLICATION-ERROR */
+private function f_TC_rim_info_app_error(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) Application_Error_Container app_cont_tx;
+ var template Application_Error_Container app_cont_rx;
+ var template (value) RAN_Information_Application_Error_RIM_Container cont_tx;
+ var template RAN_Information_Application_Error_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_cid(cell_id_sgsn);
+
+ app_cont_tx := tsu_Application_Error_Container_NACC(cell_id, 23,
+ tsu_Application_Container_IE_NACC_req(cell_id));
+
+ app_cont_rx := rsu_Application_Error_Container_NACC(cell_id, 23,
+ rsu_Application_Container_IE_NACC_req(cell_id));
+
+ cont_tx := ts_RAN_Information_Application_Error_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP),
+ omit, app_cont_tx);
+ cont_rx := tr_RAN_Information_Application_Error_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP),
+ omit, app_cont_rx);
+
+ f_rim_pcu2sgsn(ts_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+
+ f_rim_sgsn2pcu(ts_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+}
+testcase TC_rim_info_app_error() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_info_app_error));
+ f_cleanup();
+}
+
+/* RAN-INFORMATION routing directly between PCUs, without SGSN involvement */
+private function f_TC_rim_info_pcu2pcu(integer src_pcu_idx, integer src_bvc_idx,
+ integer dst_pcu_idx, integer dst_bvc_idx)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id_src := g_pcu[src_pcu_idx].cfg.bvc[src_bvc_idx].cell_id;
+ var BssgpCellId cell_id_dst := g_pcu[dst_pcu_idx].cfg.bvc[dst_bvc_idx].cell_id;
+ var template (value) RIM_Routing_Information ri_pcu_src_tx;
+ var template (value) RIM_Routing_Information ri_pcu_dst_tx;
+ var template RIM_Routing_Information ri_pcu_src_rx;
+ var template RIM_Routing_Information ri_pcu_dst_rx;
+ var template (value) RAN_Information_RIM_Container cont_tx;
+ var template RAN_Information_RIM_Container cont_rx;
+
+ log("Testing RIM PCU2PCU from PCU[", src_pcu_idx, "][", src_bvc_idx, "] to PCU[",
+ dst_pcu_idx, "][", dst_bvc_idx, "]");
+
+ ri_pcu_src_tx := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
+ t_RIM_Routing_Address_cid(cell_id_src));
+ ri_pcu_dst_tx := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
+ t_RIM_Routing_Address_cid(cell_id_dst));
+ ri_pcu_src_rx := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
+ t_RIM_Routing_Address_cid(cell_id_src));
+ ri_pcu_dst_rx := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID,
+ t_RIM_Routing_Address_cid(cell_id_dst));
+
+ cont_tx := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+ cont_rx := tr_RAN_Information_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+
+ f_rim_pcu2pcu(ts_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu_dst_tx, src := ri_pcu_src_tx, cont := cont_tx),
+ tr_PDU_BSSGP_RAN_INFORMATION(dst := ri_pcu_dst_rx, src := ri_pcu_src_rx, cont := cont_rx),
+ src_pcu_idx, dst_pcu_idx);
+}
+testcase TC_rim_info_pcu2pcu() runs on GlobalTest_CT
+{
+ var integer src_pcu_idx, dst_pcu_idx;
+ var integer src_bvc_idx, dst_bvc_idx;
+ f_init();
+ f_global_init();
+
+ for (src_pcu_idx := 0; src_pcu_idx < lengthof(g_pcu); src_pcu_idx := src_pcu_idx + 1) {
+ for (src_bvc_idx := 0; src_bvc_idx < lengthof(g_pcu[src_pcu_idx].cfg.bvc); src_bvc_idx := src_bvc_idx + 1) {
+ for (dst_pcu_idx := 0; dst_pcu_idx < lengthof(g_pcu); dst_pcu_idx := dst_pcu_idx + 1) {
+ if (dst_pcu_idx == src_pcu_idx) {
+ continue;
+ }
+
+ for (dst_bvc_idx := 0; dst_bvc_idx < lengthof(g_pcu[dst_pcu_idx].cfg.bvc);
+dst_bvc_idx := dst_bvc_idx + 1) {
+ f_TC_rim_info_pcu2pcu(src_pcu_idx, src_bvc_idx, dst_pcu_idx, dst_bvc_idx);
+ }
+ }
+ }
+ }
+
+ f_cleanup();
+}
+
+
+/* Test RIM REQ sent from an MME->SGSN->GBPROXY->PCU and back (eNACC) */
+private function f_TC_rim_from_eutran(integer sgsn_idx, integer pcu_idx, integer bvc_idx := 0)
+runs on GlobalTest_CT
+{
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var template (value) RAN_Information_Request_RIM_Container cont_tx;
+ var template RAN_Information_Request_RIM_Container cont_rx;
+ var template RIM_Routing_Address ra_pcu;
+ var template RIM_Routing_Address ra_sgsn;
+
+ ra_pcu := t_RIM_Routing_Address_cid(cell_id);
+ ra_sgsn := t_RIM_Routing_Address_enbid(cell_id_sgsn, tac := 3, gnbid := '12345678123456'O);
+
+ cont_tx := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(0),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+ cont_rx := tr_RAN_Information_Request_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(0),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_STOP));
+
+ f_rim_sgsn2pcu(ts_RAN_INFORMATION_REQUEST(dst := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := ts_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, ra_sgsn),
+ cont := cont_tx),
+ tr_RAN_INFORMATION_REQUEST(dst := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ src := tr_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, ra_sgsn),
+ cont := cont_rx),
+ sgsn_idx, pcu_idx);
+
+
+ f_rim_pcu2sgsn(ts_RAN_INFORMATION_REQUEST(dst := ts_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, ra_sgsn),
+ src := ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_tx),
+ tr_RAN_INFORMATION_REQUEST(dst := tr_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, ra_sgsn),
+ src := tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, ra_pcu),
+ cont := cont_rx),
+ pcu_idx);
+}
+testcase TC_rim_from_eutran() runs on GlobalTest_CT
+{
+ f_init();
+ f_global_init();
+ f_rim_iterator(refers(f_TC_rim_from_eutran));
+ f_cleanup();
+}
+
+/***********************************************************************
+ * STATUS handling
+ ***********************************************************************/
+
+/* BSSGP STATUS PDU must be routed based on inner "PDU In Error" message */
+
+/* generate a TMSI with NRI matching sgsn_idx + nri_idx */
+private function f_gen_tmsi_for_sgsn_nri(integer sgsn_idx, integer nri_idx) runs on test_CT return OCT4
+{
+ var integer nri := mp_sgsn_nri[sgsn_idx][nri_idx];
+ return f_gen_tmsi(0, nri_v := nri, nri_bitlen := mp_nri_bitlength);
+}
+
+/* generate a TLLI with NRI matching sgsn_idx + nri_idx */
+private function f_gen_tlli_for_sgsn_nri(integer sgsn_idx, integer nri_idx) runs on test_CT return OCT4
+{
+ var OCT4 p_tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
+ return f_gprs_tlli_from_tmsi(p_tmsi, TLLI_LOCAL);
+}
+
+/* STATUS in uplink direction; expect routing by its NRI */
+private function f_TC_status_ul(integer pcu_idx, integer sgsn_idx, PDU_BSSGP inner)
+runs on GlobalTest_CT
+{
+ var template (value) PDU_BSSGP tx := ts_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE, inner);
+ var template (present) PDU_BSSGP exp_rx :=
+ tr_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE,
+ tx.pDU_BSSGP_STATUS.pDU_in_Error.erroneous_BSSGP_PDU);
+
+ f_global_pcu2sgsn(tx, exp_rx, pcu_idx, sgsn_idx);
+}
+
+/* STATUS in uplink direction; expect routing by its NRI */
+private function f_TC_status_dl(integer sgsn_idx, integer pcu_idx, PDU_BSSGP inner)
+runs on GlobalTest_CT
+{
+ var template (value) PDU_BSSGP tx := ts_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE, inner);
+ var template (present) PDU_BSSGP exp_rx :=
+ tr_BSSGP_STATUS(omit, BSSGP_CAUSE_EQUIMENT_FAILURE,
+ tx.pDU_BSSGP_STATUS.pDU_in_Error.erroneous_BSSGP_PDU);
+
+ f_global_sgsn2pcu(tx, exp_rx, sgsn_idx, pcu_idx);
+}
+
+/* STATUS in uplink direction on SIG-BVC containing a TLLI; expect routing by its NRI */
+testcase TC_status_sig_ul_tlli() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+
+ f_init();
+ f_global_init();
+
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
+ /* some downlink PDU occurring on SIG-BVC with a TLLI */
+ var OCT4 tlli := f_gen_tlli_for_sgsn_nri(sgsn_idx, nri_idx);
+ var PDU_BSSGP inner := valueof(ts_BSSGP_FLUSH_LL(tlli, 2342));
+
+ f_TC_status_ul(0, sgsn_idx, inner);
+ }
+ }
+
+ f_cleanup();
+}
+
+/* STATUS in uplink direction on SIG-BVC containing a TMSI; expect routing by its NRI */
+testcase TC_status_sig_ul_tmsi() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+
+ f_init();
+ f_global_init();
+
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
+ /* some downlink PDU occurring on SIG-BVC with a TMSI */
+ const hexstring imsi := '001010123456789'H
+ var OCT4 tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
+ var BssgpBvci bvci := g_pcu[0].cfg.bvc[0].bvci;
+ var PDU_BSSGP inner := valueof(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
+ f_TC_status_ul(0, sgsn_idx, inner);
+ }
+ }
+
+ f_cleanup();
+}
+
+
+/* STATUS in uplink direction on PTP-BVC containing a TLLI; expect routing by its NRI */
+testcase TC_status_ptp_ul_tlli() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+
+ f_init();
+ f_global_init_ptp();
+
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
+ /* some downlink PDU occurring on PTP-BVC with a TLLI */
+ var OCT4 tlli := f_gen_tlli_for_sgsn_nri(sgsn_idx, nri_idx);
+ var PDU_BSSGP inner := valueof(ts_BSSGP_DL_UD(tlli, '2342'O));
+
+ f_TC_status_ul(0, sgsn_idx, inner);
+ }
+ }
+
+ f_cleanup();
+}
+
+/* STATUS in uplink direction on PTP-BVC containing a TMSI; expect routing by its NRI */
+testcase TC_status_ptp_ul_tmsi() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, nri_idx;
+
+ f_init();
+ f_global_init_ptp();
+
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ for (nri_idx := 0; nri_idx < lengthof(mp_sgsn_nri[sgsn_idx]); nri_idx := nri_idx + 1) {
+ /* some downlink PDU occurring on PTP-BVC with a TMSI */
+ const hexstring imsi := '001010123456789'H
+ var OCT4 tmsi := f_gen_tmsi_for_sgsn_nri(sgsn_idx, nri_idx);
+ var BssgpBvci bvci := g_pcu[0].cfg.bvc[0].bvci;
+ var PDU_BSSGP inner := valueof(ts_BSSGP_CS_PAGING_PTMSI(bvci, imsi, oct2int(tmsi)));
+ f_TC_status_ul(0, sgsn_idx, inner);
+ }
+ }
+
+ f_cleanup();
+}
+
+/* STATUS in downlink direction in SIG-BVC containing a BVCI; expect routing by it */
+testcase TC_status_sig_dl_bvci() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, pcu_idx, bvc_idx;
+
+ f_init();
+ f_global_init();
+
+ /* test each BVC in each PCU from each SGSN */
+ for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx + 1) {
+ for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx + 1) {
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ /* some uplink PDU occurring on SIG-BVC containing a BVCI */
+ var BssgpBvci bvci := g_pcu[pcu_idx].cfg.bvc[bvc_idx].bvci;
+ var PDU_BSSGP inner := valueof(ts_BSSGP_LLC_DISCARDED('12345678'O, 1, bvci, 23));
+ f_TC_status_dl(sgsn_idx, pcu_idx, inner);
+ }
+ }
+ }
+
+ f_cleanup();
+}
+
+/* STATUS in downlink direction in PTP-BVC; expect routing by BVCI */
+testcase TC_status_ptp_dl_bvci() runs on GlobalTest_CT
+{
+ var integer sgsn_idx, pcu_idx, bvc_idx;
+
+ f_init();
+ f_global_init_ptp();
+
+ /* test each BVC in each PCU from each SGSN */
+ for (pcu_idx := 0; pcu_idx < lengthof(g_pcu); pcu_idx := pcu_idx + 1) {
+ for (bvc_idx := 0; bvc_idx < lengthof(g_pcu[pcu_idx].cfg.bvc); bvc_idx := bvc_idx + 1) {
+ var BssgpBvci bvci := g_pcu[pcu_idx].cfg.bvc[bvc_idx].bvci;
+ f_global_ptp_connect_pcu_bvci(pcu_idx, bvci);
+ for (sgsn_idx := 0; sgsn_idx < NUM_SGSN; sgsn_idx := sgsn_idx + 1) {
+ f_global_ptp_connect_sgsn_bvci(sgsn_idx, bvci);
+
+ /* some uplink PDU occurring on PTP-BVC */
+ var BssgpCellId cell_id := g_pcu[pcu_idx].cfg.bvc[bvc_idx].cell_id;
+ var PDU_BSSGP inner := valueof(ts_BSSGP_UL_UD('12345678'O, cell_id, '4223'O));
+ f_TC_status_dl(sgsn_idx, pcu_idx, inner);
+ }
+ }
+ }
+
+ f_cleanup();
+}
+
+/* TODO: test case for DL-STATUS(SUSPEND/RESUME) containing RA-ID; expect routing by RA-ID */
+/* TODO: test case for UL-STATUS(PAGING-by-IMSI) after sending an actual PAGIN-by-IMSI in DL first */
+
+control {
+ execute( TC_BVC_bringup() );
+ execute( TC_BVC_bringup_conflicting() );
+
+ execute( TC_ul_unitdata() );
+ execute( TC_ul_unitdata_pool_failure() );
+ execute( TC_dl_unitdata() );
+ execute( TC_ra_capability() );
+ execute( TC_ra_capability_upd() );
+ execute( TC_radio_status() );
+ execute( TC_radio_status_tmsi() );
+ execute( TC_radio_status_imsi() );
+ execute( TC_suspend() );
+ execute( TC_resume() );
+ execute( TC_trace() );
+ execute( TC_llc_discarded() );
+ execute( TC_overload() );
+ execute( TC_bvc_block_ptp() );
+ execute( TC_bvc_unblock_ptp() );
+ execute( TC_bvc_reset_ptp_from_bss() );
+ execute( TC_bvc_reset_sig_from_bss() );
+ execute( TC_bvc_reset_ptp_from_sgsn() );
+ execute( TC_bvc_reset_blocked_ptp_from_sgsn() );
+ execute( TC_bvc_reset_sig_from_sgsn() );
+ if (mp_enable_bss_load_sharing) {
+ /* don't enable this by default, as we don't yet have any automatic test setup for FR with 4 NS-VC */
+ execute( TC_load_sharing_dl() );
+ }
+
+ /* PAGING-PS over PTP BVC */
+ execute( TC_paging_ps_ptp_bss() );
+ execute( TC_paging_ps_ptp_lac() );
+ execute( TC_paging_ps_ptp_lac_unknown() );
+ execute( TC_paging_ps_ptp_rac() );
+ execute( TC_paging_ps_ptp_rac_unknown() );
+ execute( TC_paging_ps_ptp_bvci() );
+ execute( TC_paging_ps_ptp_bvci_imsi() );
+ execute( TC_paging_ps_ptp_bvci_unknown() );
+ execute( TC_paging_ps_reject_ptp_bvci() );
+ execute( TC_paging_ps_reject_ptp_bvci_imsi() );
+ execute( TC_dummy_paging_ps_ptp() );
+
+ /* PAGING-PS over SIG BVC */
+ execute( TC_paging_ps_sig_bss() );
+ execute( TC_paging_ps_sig_lac() );
+ execute( TC_paging_ps_sig_lac_unknown() );
+ execute( TC_paging_ps_sig_rac() );
+ execute( TC_paging_ps_sig_rac_unknown() );
+ execute( TC_paging_ps_sig_bvci() );
+ execute( TC_paging_ps_sig_bvci_imsi() );
+ execute( TC_paging_ps_sig_bvci_unknown() );
+ execute( TC_paging_ps_reject_sig_bvci() );
+ execute( TC_paging_ps_reject_sig_bvci_imsi() );
+ execute( TC_dummy_paging_ps_sig() );
+
+ /* PAGING-CS over PTP BVC */
+ execute( TC_paging_cs_ptp_bss() );
+ execute( TC_paging_cs_ptp_lac() );
+ execute( TC_paging_cs_ptp_lac_unknown() );
+ execute( TC_paging_cs_ptp_rac() );
+ execute( TC_paging_cs_ptp_rac_unknown() );
+ execute( TC_paging_cs_ptp_bvci() );
+ execute( TC_paging_cs_ptp_bvci_unknown() );
+
+ /* PAGING-CS over SIG BVC */
+ execute( TC_paging_cs_sig_bss() );
+ execute( TC_paging_cs_sig_lac() );
+ execute( TC_paging_cs_sig_lac_unknown() );
+ execute( TC_paging_cs_sig_rac() );
+ execute( TC_paging_cs_sig_rac_unknown() );
+ execute( TC_paging_cs_sig_bvci() );
+ execute( TC_paging_cs_sig_bvci_unknown() );
+
+ /* RAN Information Management */
+ execute( TC_rim_info_req() );
+ execute( TC_rim_info() );
+ execute( TC_rim_info_ack() );
+ execute( TC_rim_info_error() );
+ execute( TC_rim_info_app_error() );
+ execute( TC_rim_info_pcu2pcu() );
+ execute( TC_rim_from_eutran() );
+
+
+ execute( TC_flush_ll_bvci_new() );
+
+ execute( TC_flush_ll_no_bvci_new() );
+
+ execute( TC_fc_bvc() );
+ execute( TC_fc_ms() );
+ execute( TC_ms_reg_enq() );
+
+ /* Uplink STATUS */
+ execute( TC_status_sig_ul_tlli() );
+ execute( TC_status_sig_ul_tmsi() );
+ execute( TC_status_ptp_ul_tlli() );
+ execute( TC_status_ptp_ul_tmsi() );
+
+ /* Downlink STATUS */
+ execute( TC_status_sig_dl_bvci() );
+ execute( TC_status_ptp_dl_bvci() );
+}
+
+
+}
diff --git a/gbproxy/README.md b/gbproxy/README.md
new file mode 100644
index 00000000..a86aad38
--- /dev/null
+++ b/gbproxy/README.md
@@ -0,0 +1,18 @@
+# GBProxy_Tests.ttcn
+
+* external interfaces
+ * Gb (emulates PCU side NS/BSSGP)
+ * Gb (emulates SGSN side NS/BSSGP)
+ * VTY
+
+{% dot gbproxy_tests.svg
+digraph G {
+ rankdir=LR;
+ GBP [label="IUT\nosmo-gbproxy",shape="box"];
+ ATS [label="ATS\nGBProxy_Tests.ttcn"];
+
+ ATS -> GBP [label="Gb (from SGSN)"];
+ GBP -> ATS [label="Gb (from PCU)"];
+ ATS -> SGSN [label="VTY"];
+}
+%}
diff --git a/gbproxy/expected-results.xml b/gbproxy/expected-results.xml
new file mode 100644
index 00000000..5b9f8b1e
--- /dev/null
+++ b/gbproxy/expected-results.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='76' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='GBProxy_Tests' name='TC_BVC_bringup' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_BVC_bringup_conflicting' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_ul_unitdata' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_ul_unitdata_pool_failure' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_dl_unitdata' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_ra_capability' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_ra_capability_upd' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_radio_status' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_radio_status_tmsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_radio_status_imsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_suspend' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_resume' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_trace' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_llc_discarded' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_overload' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_block_ptp' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_unblock_ptp' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_reset_ptp_from_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_reset_sig_from_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_reset_ptp_from_sgsn' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_reset_blocked_ptp_from_sgsn' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_bvc_reset_sig_from_sgsn' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_lac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_lac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_rac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_rac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_bvci_imsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_ptp_bvci_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_reject_ptp_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_reject_ptp_bvci_imsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_dummy_paging_ps_ptp' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_lac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_lac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_rac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_rac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_bvci_imsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_sig_bvci_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_reject_sig_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_ps_reject_sig_bvci_imsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_dummy_paging_ps_sig' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_lac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_lac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_rac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_rac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_ptp_bvci_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_bss' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_lac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_lac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_rac' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_rac_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_paging_cs_sig_bvci_unknown' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info_req' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info_ack' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info_error' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info_app_error' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_info_pcu2pcu' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_rim_from_eutran' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_flush_ll_bvci_new' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_flush_ll_no_bvci_new' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_fc_bvc' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_fc_ms' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_ms_reg_enq' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_sig_ul_tlli' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_sig_ul_tmsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_ptp_ul_tlli' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_ptp_ul_tmsi' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_sig_dl_bvci' time='MASKED'/>
+ <testcase classname='GBProxy_Tests' name='TC_status_ptp_dl_bvci' time='MASKED'/>
+</testsuite>
diff --git a/gbproxy/gen_links.sh b/gbproxy/gen_links.sh
new file mode 100755
index 00000000..c7756ec3
--- /dev/null
+++ b/gbproxy/gen_links.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+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.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+# for Osmocom_VTY
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.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.LLC_v7.1.0/src
+FILES="LLC_EncDec.cc LLC_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SNDCP_v7.0.0/src
+FILES="SNDCP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_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
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.ProtocolModules.M3UA/src
+FILES="M3UA_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA Emulation
+DIR=$BASEDIR/titan.TestPorts.MTP3asp/src
+FILES="MTP3asp_PortType.ttcn MTP3asp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.ProtocolEmulations.M3UA/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolEmulations.SCCP/src
+FILES="SCCP_Emulation.ttcn SCCP_EncDec.cc SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.AF_PACKET/src
+FILES="AF_PACKET_PT.cc AF_PACKET_PT.hh AF_PACKET_PortType.ttcn AF_PACKET_PortTypes.ttcn "
+FILES+="FrameRelay_Types.ttcn FrameRelay_CodecPort.ttcn FrameRelay_Emulation.ttcn Q931_Types.ttcn Q933_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Provider_FR.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
+FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
+FILES+="Osmocom_VTY_Functions.ttcn "
+FILES+="LLC_Templates.ttcn L3_Templates.ttcn L3_Common.ttcn "
+# IPA_Emulation + dependencies
+FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTP_Emulation.ttcn
+GTPv1C_Templates.ttcn IPCP_Types.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/gbproxy/osmo-gbproxy.cfg b/gbproxy/osmo-gbproxy.cfg
new file mode 100644
index 00000000..d2695670
--- /dev/null
+++ b/gbproxy/osmo-gbproxy.cfg
@@ -0,0 +1,47 @@
+!
+! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging print category-hex 0
+ logging timestamp 1
+ logging print file 1
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+ logging level gprs debug
+line vty
+ no login
+!
+gbproxy
+ nri bitlen 5
+sgsn nsei 101
+ name first
+ nri add 3
+sgsn nsei 102
+ name second
+ nri add 4
+ns
+ bind udp sgsn-side
+ listen 127.0.0.1 23000
+ accept-ipaccess
+ nse 101
+ ip-sns-bind sgsn-side
+ ip-sns-remote 127.0.0.10 7777
+ nse 102
+ ip-sns-bind sgsn-side
+ ip-sns-remote 127.0.0.11 8888
+ bind udp bss-side
+ listen 127.0.0.2 23000
+ accept-dynamic-ip-sns
+ ip-sns-default bind bss-side
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 5
+ timer tns-alive 2
+ timer tns-alive-retries 3
diff --git a/gbproxy/osmo-gbproxy.fr.cfg b/gbproxy/osmo-gbproxy.fr.cfg
new file mode 100644
index 00000000..b7eb5385
--- /dev/null
+++ b/gbproxy/osmo-gbproxy.fr.cfg
@@ -0,0 +1,60 @@
+!
+! Osmocom Gb Proxy (0.9.0.404-6463) configuration saved from vty
+!!
+!
+log stderr
+ logging level lns debug
+line vty
+ no login
+!
+ns
+ bind udp local
+ listen 127.0.0.1 23000
+ bind fr hdlcnet1
+ fr hdlcnet1 frnet
+ bind fr hdlcnet2
+ fr hdlcnet2 frnet
+ bind fr hdlcnet3
+ fr hdlcnet3 frnet
+ bind fr hdlcnet4
+ fr hdlcnet4 frnet
+ bind fr hdlcnet5
+ fr hdlcnet5 frnet
+ bind fr hdlcnet6
+ fr hdlcnet6 frnet
+ bind fr hdlcnet7
+ fr hdlcnet7 frnet
+ bind fr hdlcnet8
+ fr hdlcnet8 frnet
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 30
+ timer tns-alive 3
+ timer tns-alive-retries 10
+ nse 101
+ ip-sns-bind local
+ ip-sns-remote 127.0.0.10 7777
+ nse 102
+ ip-sns-bind local
+ ip-sns-remote 127.0.0.11 8888
+ nse 2001
+ nsvc fr hdlcnet1 dlci 16 nsvci 1
+ nsvc fr hdlcnet2 dlci 17 nsvci 2
+ nsvc fr hdlcnet3 dlci 18 nsvci 3
+ nsvc fr hdlcnet4 dlci 19 nsvci 4
+ nse 2002
+ nsvc fr hdlcnet5 dlci 20 nsvci 5
+ nsvc fr hdlcnet6 dlci 21 nsvci 6
+ nse 2003
+ nsvc fr hdlcnet7 dlci 22 nsvci 7
+ nsvc fr hdlcnet8 dlci 23 nsvci 8
+gbproxy
+ nri bitlen 5
+sgsn nsei 101
+ name first
+ nri add 3
+sgsn nsei 102
+ name second
+ nri add 4
diff --git a/gbproxy/regen_makefile.sh b/gbproxy/regen_makefile.sh
new file mode 100755
index 00000000..cd17d5c4
--- /dev/null
+++ b/gbproxy/regen_makefile.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+NAME=GBProxy_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ AF_PACKET_PT.cc
+ AF_PACKET_PT.hh
+ BSSGP_EncDec.cc
+ GTPC_EncDec.cc
+ GTPU_EncDec.cc
+ GTPv1C_CodecPort_CtrlFunctDef.cc
+ GTPv1U_CodecPort_CtrlFunctDef.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ SCCP_EncDec.cc
+ SCTPasp_PT.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DBSSGP_EM_L3
+ -DIPA_EMULATION_CTRL
+ -DNS_EMULATION_FR
+ -DUSE_MTP3_DISTRIBUTOR
+"
+
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -i 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lsctp/' Makefile
diff --git a/gen_links.sh.inc b/gen_links.sh.inc
index 539b3983..c21bcd60 100644
--- a/gen_links.sh.inc
+++ b/gen_links.sh.inc
@@ -36,6 +36,8 @@ gen_links() {
}
ignore_pp_results() {
+ # Avoid using the pattern itself if no file is found in globbing below:
+ shopt -s nullglob
for pp in *.ttcnpp; do
ttcn_file="$(echo $pp | sed 's/pp$//')"
echo "$ttcn_file" >> .gitignore
diff --git a/ggsn_tests/GGSN_Tests.cfg b/ggsn_tests/GGSN_Tests.cfg
index e849ed45..b542108c 100644
--- a/ggsn_tests/GGSN_Tests.cfg
+++ b/ggsn_tests/GGSN_Tests.cfg
@@ -13,6 +13,10 @@
[TESTPORT_PARAMETERS]
[MODULE_PARAMETERS]
+# local T3-RESPONSE timeout, seconds:
+GGSN_Tests.mp_t3_response := 1;
+# local N3-REQUESTS counter:
+GGSN_Tests.mp_n3_requests := 2;
[EXECUTE]
GGSN_Tests.control
diff --git a/ggsn_tests/GGSN_Tests.default b/ggsn_tests/GGSN_Tests.default
index 4d52e242..9832ba12 100644
--- a/ggsn_tests/GGSN_Tests.default
+++ b/ggsn_tests/GGSN_Tests.default
@@ -21,5 +21,6 @@ GGSN_Tests.m_ggsn_ip4_dns2 := "8.8.8.8"
GGSN_Tests.m_ggsn_ip6_dns1 := "2001:4860:4860::8888"
GGSN_Tests.m_ggsn_ip6_dns2 := "2001:4860:4860::8844"
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoGGSN";
+GTPv1C_CodecPort.mp_pl_SystemUnderTest := GGSN;
[EXECUTE]
diff --git a/ggsn_tests/GGSN_Tests.ttcn b/ggsn_tests/GGSN_Tests.ttcn
index be0e565f..23a99248 100644
--- a/ggsn_tests/GGSN_Tests.ttcn
+++ b/ggsn_tests/GGSN_Tests.ttcn
@@ -11,29 +11,56 @@ module GGSN_Tests {
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+ import from TCCEncoding_Functions all;
import from General_Types all;
import from Osmocom_Types all;
import from Misc_Helpers all;
import from IPL4asp_PortType all;
import from IPL4asp_Types all;
- import from GTP_CodecPort all;
- import from GTP_CodecPort_CtrlFunct all;
- import from GTP_Templates all;
+ import from GTPv1C_CodecPort all;
+ import from GTPv1U_CodecPort all;
+ import from GTPv1C_CodecPort_CtrlFunct all;
+ import from GTPv1U_CodecPort_CtrlFunct all;
import from GTPC_Types all;
import from GTPU_Types all;
+ import from GTPv1C_Templates all;
+ import from GTPv1U_Templates all;
import from IPCP_Types all;
import from PAP_Types all;
import from IP_Types all;
import from ICMP_Types all;
import from ICMPv6_Types all;
+ import from ICMP_Templates all;
+ import from ICMPv6_Templates all;
import from Native_Functions all;
import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType 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_ts32_299_Templates all;
+ import from DIAMETER_Emulation all;
+
const integer GTP0_PORT := 3386;
const integer GTP1C_PORT := 2123;
const integer GTP1U_PORT := 2152;
+ const integer PCRF_PORT := 3868;
+ const integer OCS_PORT := 3869;
+
+ type enumerated GGSN_Impl {
+ GGSN_IMPL_OSMOCOM,
+ GGSN_IMPL_OPEN5GS
+ };
+
+ type enumerated GGSN_Conf {
+ GGSN_CONF_ALL,
+ GGSN_CONF_V4_ONLY,
+ GGSN_CONF_V6_ONLY,
+ GGSN_CONF_V4V6_ONLY
+ };
modulepar {
/* Default IP addresses. May be overridden by GGSN_Tests configuration files. */
@@ -65,6 +92,11 @@ module GGSN_Tests {
* The tests expect to be able to send ping packets between any two simulated MS within the same
* address range. This requires IP forwarding to be enabled on the corresponding tun interfaces.
*/
+ integer mp_t3_response := 5; /* local T3-RESPONSE timeout, seconds */
+ integer mp_n3_requests := 3; /* local N3-REQUESTS counter */
+
+ GGSN_Impl m_ggsn_impl := GGSN_IMPL_OSMOCOM;
+ GGSN_Conf m_ggsn_conf := GGSN_CONF_ALL;
}
type set PdpContext {
@@ -83,7 +115,12 @@ module GGSN_Tests {
/* TEI (Data) remote side */
OCT4 teid_remote,
/* TEI (Control) remote side */
- OCT4 teic_remote
+ OCT4 teic_remote,
+ OCT1 ratType optional,
+ UserLocationInformation uli optional,
+ OCT2 charging_char optional,
+ OCT8 imeisv optional,
+ MS_TimeZone ms_tz optional
}
type component GT_CT {
@@ -97,8 +134,8 @@ module GGSN_Tests {
var OCT4 g_sgsn_ip_c;
var OCT4 g_sgsn_ip_u;
/* FIXME: parse remName from config file */
- var GtpPeer g_peer_c := { connId := 0, remName := m_ggsn_ip_gtpc, remPort := GTP1C_PORT };
- var GtpPeer g_peer_u := { connId := 0, remName := m_ggsn_ip_gtpu, remPort := GTP1U_PORT };
+ var Gtp1cPeer g_peer_c := { connId := 0, remName := m_ggsn_ip_gtpc, remPort := GTP1C_PORT };
+ var Gtp1uPeer g_peer_u := { connId := 0, remName := m_ggsn_ip_gtpu, remPort := GTP1U_PORT };
timer T_default := 3.0;
/* next to-be-sent GTP-C sequence number */
@@ -108,7 +145,23 @@ module GGSN_Tests {
port TELNETasp_PT GGSNVTY;
var boolean use_gtpu_txseq := false;
- var boolean g_use_echo := false;
+ var integer g_use_echo_intval := 0; /* 0 = disabled */
+
+ /* Emulated PCRF, used with m_ggsn_impl = GGSN_IMPL_OPEN5GS */
+ var DIAMETER_conn_parameters g_gx_pars;
+ var DIAMETER_Emulation_CT vc_Gx;
+ port DIAMETER_PT Gx_UNIT;
+ port DIAMETEREM_PROC_PT Gx_PROC;
+
+ /* Emulated OCS, used with m_ggsn_impl = GGSN_IMPL_OPEN5GS */
+ var DIAMETER_conn_parameters g_gy_pars;
+ var DIAMETER_Emulation_CT vc_Gy;
+ port DIAMETER_PT Gy_UNIT;
+ port DIAMETEREM_PROC_PT Gy_PROC;
+ var integer g_gy_validity_time := 0; /* In seconds. 0 => disabled, !0 => grant over CC-Time period */
+ var integer g_gy_volume_quota := 0; /* In octets. 0 => disabled, !0 => request IUT to revalidate after N octets */
+ var integer g_gy_volume_threshold := 0; /* In octets. Request IUT to revalidate at N octets before reaching g_gy_volume_quota */
+ var PDU_DIAMETER g_rx_gy; /* Store last received Gy message */
}
private function f_init_vty() runs on GT_CT {
@@ -161,17 +214,74 @@ module GGSN_Tests {
return true;
}
- private function f_vty_enable_echo_interval(boolean enable) runs on GT_CT {
+ private function f_vty_enable_echo_interval(integer intval_sec) runs on GT_CT {
f_vty_enter_config(GGSNVTY);
f_vty_transceive(GGSNVTY, "ggsn ggsn0");
- if (enable) {
- f_vty_transceive(GGSNVTY, "echo-interval 5");
+ if (intval_sec > 0) {
+ f_vty_transceive(GGSNVTY, "echo-interval " & int2str(intval_sec));
} else {
f_vty_transceive(GGSNVTY, "no echo-interval");
}
f_vty_transceive(GGSNVTY, "end");
}
+ private function DiameterForwardUnitdataCallback(PDU_DIAMETER msg)
+ runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
+ DIAMETER_UNIT.send(msg);
+ return omit;
+ }
+
+ private function f_init_diameter(charstring id) runs on GT_CT {
+ var DIAMETEROps ops := {
+ create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(DiameterForwardUnitdataCallback),
+ raw := true /* handler mode (single component for all IMSI)) */
+ };
+
+ /* Gx setup: */
+ g_gx_pars := {
+ remote_ip := m_ggsn_ip_gtpc,
+ remote_sctp_port := -1,
+ local_ip := m_bind_ip_gtpc,
+ local_sctp_port := PCRF_PORT,
+ origin_host := "pcrf.localdomain",
+ origin_realm := "localdomain",
+ 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, g_gx_pars, id));
+
+ /* Gy setup: */
+ g_gy_pars := {
+ remote_ip := m_ggsn_ip_gtpc,
+ remote_sctp_port := -1,
+ local_ip := m_bind_ip_gtpc,
+ local_sctp_port := OCS_PORT,
+ origin_host := "ocs.localdomain",
+ origin_realm := "localdomain",
+ 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, g_gy_pars, id));
+
+ f_diameter_wait_capability(Gx_UNIT);
+ f_diameter_wait_capability(Gy_UNIT);
+ /* Give some time for our emulation to get out of SUSPECT list of SUT (3 watchdong ping-pongs):
+ * RFC6733 sec 5.1
+ * RFC3539 sec 3.4.1 [5]
+ * https://github.com/freeDiameter/freeDiameter/blob/master/libfdcore/p_psm.c#L49
+ */
+ f_sleep(1.0);
+ }
+
function f_init() runs on GT_CT {
if (g_initialized == true) {
return;
@@ -183,39 +293,56 @@ module GGSN_Tests {
var Result res;
map(self:GTPC, system:GTPC);
- res := GTP_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, m_bind_ip_gtpc, GTP1C_PORT, {udp:={}});
+ res := GTPv1C_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, m_bind_ip_gtpc, GTP1C_PORT, {udp:={}});
log("GTP1C ConnectionID: ", res.connId);
g_peer_c.connId := res.connId;
map(self:GTPU, system:GTPU);
- res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, m_bind_ip_gtpu, GTP1U_PORT, {udp:={}});
+ res := GTPv1U_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, m_bind_ip_gtpu, GTP1U_PORT, {udp:={}});
g_peer_u.connId:= res.connId;
g_restart_ctr := f_rnd_octstring(1);
g_c_seq_nr := f_rnd_int(65535);
g_d_seq_nr := f_rnd_int(65535);
- f_init_vty();
- f_vty_set_gpdu_txseq(use_gtpu_txseq);
- f_vty_enable_echo_interval(g_use_echo);
+ if (m_ggsn_impl == GGSN_IMPL_OSMOCOM) {
+ f_init_vty();
+ f_vty_set_gpdu_txseq(use_gtpu_txseq);
+ f_vty_enable_echo_interval(g_use_echo_intval);
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(GGSNVTY, testcasename() & "() start");
+ } else if (m_ggsn_impl == GGSN_IMPL_OPEN5GS) {
+ f_init_diameter(testcasename());
+ }
+ }
+
+ function f_shutdown_helper() runs on GT_CT {
+ /* Sleep (T3-RESPONSE * N3-REQUESTS) seconds.
+ * This ensures all retransmit queues are cleared before jumping
+ * into next tests, hence avoding situation where a test resuses
+ * a seqnum still in the GGSN's resp queue (dup req detector).
+ * See OS#5485 avout decreasing time. We could also add a new
+ * VTY command that calls gtp_clear_queues() */
+ f_sleep(int2float(mp_t3_response * mp_n3_requests));
+ setverdict(pass);
}
/* Altstep implementing responses to any incoming echo requests */
- altstep pingpong() runs on GT_CT {
+ private altstep pingpong() runs on GT_CT {
var Gtp1cUnitdata ud;
var Gtp1uUnitdata udu;
- [g_use_echo] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
+ [g_use_echo_intval > 0] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
repeat;
};
- [not g_use_echo] GTPC.receive(tr_GTPC_PING(?)) {
+ [g_use_echo_intval == 0] GTPC.receive(tr_GTPC_PING(?)) {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
"GTP Echo Req rceived but not enabled in VTY");
};
[] T_default.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
- "pinpong T_default timeout");
+ "pingpong T_default timeout");
};
}
@@ -234,98 +361,383 @@ module GGSN_Tests {
return int2oct(f_rnd_int(4294967296), 4);
}
+ /* return random IMEI(SV) */
+ function f_rnd_imeisv() return OCT8 {
+ return hex2oct(f_rnd_hexstring(16, 10));
+ }
+
/* define an (internal) representation of a PDP context */
- template PdpContext t_DefinePDP(hexstring imsi, octetstring msisdn, octetstring apn,
- EndUserAddress eua) := {
+ template PdpContext t_DefinePDP(hexstring imsi, charstring msisdn, octetstring apn,
+ EndUserAddress eua, OCT1 ratType := '02'O /* GERAN */) := {
imsi := imsi,
- msisdn := msisdn,
+ msisdn := '11'O & f_enc_TBCD(msisdn), /* encoded as TS 29.060 7.7.33, TS 29.002 */
nsapi := f_rnd_nsapi(),
apn := apn,
pco_req := omit,
eua := eua,
teid := f_rnd_tei(),
- teic := f_rnd_tei()
+ teic := f_rnd_tei(),
+ ratType := ratType,
+ uli := {
+ type_gtpc := '98'O,
+ lengthf := 0 /* filled in by encoder */,
+ geographicLocationType := '00'O /* CGI */,
+ geographicLocation := {
+ geographicLocationCGI := ts_GeographicLocationCGI('262'H, '42F'H, '0001'O, '0002'O)
+ }
+ },
+ charging_char := '0000'O,
+ imeisv := f_rnd_imeisv(),
+ ms_tz := f_ts_MS_TimeZone('03'O, '01'B)
}
/* send GTP-C for a given context and increment sequence number */
function f_send_gtpc(in template Gtp1cUnitdata data) runs on GT_CT {
GTPC.send(data);
- g_c_seq_nr := g_c_seq_nr + 1;
+ g_c_seq_nr := (g_c_seq_nr + 1) mod 65536;
}
/* send GTP-U for a given context and increment sequence number */
function f_send_gtpu(inout PdpContext ctx, in octetstring data) runs on GT_CT {
if (use_gtpu_txseq) {
GTPU.send(ts_GTP1U_GPDU(g_peer_u, g_d_seq_nr, ctx.teid_remote, data));
- g_d_seq_nr := g_d_seq_nr + 1;
+ g_d_seq_nr := (g_d_seq_nr + 1) mod 65536;
} else {
GTPU.send(ts_GTP1U_GPDU(g_peer_u, omit, ctx.teid_remote, data));
}
}
- function f_handle_create_req(inout PdpContext ctx, in Gtp1cUnitdata ud, in OCT1 exp_cause := '80'O) runs on GT_CT {
+ function f_handle_create_req(inout PdpContext ctx, in Gtp1cUnitdata ud, in template OCT1 exp_cause := '80'O) runs on GT_CT {
var CreatePDPContextResponse cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
- if (exp_cause == '80'O and exp_cause == cpr.cause.causevalue) {
+
+ if (not match(cpr.cause.causevalue, exp_cause)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "CreatePDPContextResp: cause expectancies didn't match");
+ }
+
+ if (cpr.cause.causevalue == '80'O) { /* Accepted */
/* Check if EUA type corresponds to requested type */
if (match(ctx.eua, t_EuaIPv4(?)) and
not match(cpr.endUserAddress, tr_EuaIPv4(?))){
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "EUAv4 expectancies didn't match");
}
if (match(ctx.eua, t_EuaIPv6(?)) and
not match(cpr.endUserAddress, tr_EuaIPv6(?))) {
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "EUAv6 expectancies didn't match");
}
if (match(ctx.eua, t_EuaIPv4v6(?, ?)) and
not match(cpr.endUserAddress, tr_EuaIPv4v6(?, ?))) {
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "EUAv4v6 expectancies didn't match");
}
- /* Check if PCO response corresponds to request */
- if (ispresent(ctx.pco_req)) {
- if (match(ctx.pco_req, ts_PCO_IPv4_DNS_CONT) and
- not match(cpr.protConfigOptions, tr_PCO_IPv4_DNS_CONT_resp(?))) {
- log("IPv4 DNS Container requested, but missing");
- setverdict(fail);
- }
- if (match(ctx.pco_req, ts_PCO_IPv6_DNS) and
- not match(cpr.protConfigOptions, tr_PCO_IPv6_DNS_resp(?))) {
- log("IPv6 DNS Container requested, but missing");
- setverdict(fail);
- }
+ } else if (cpr.cause.causevalue == '81'O) { /* Cause: New PDP type due to network preference */
+ /* ETSI TS 129 060 7.3.2 Create PDP Context Response. OS#5449 */
+ /* This should only happen if EUA requested type is v4v6: */
+ if (not ischosen(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Cause not expected when requesting a non v4v6 EUA");
}
- ctx.teid_remote := cpr.teidDataI.teidDataI;
- ctx.teic_remote := cpr.teidControlPlane.teidControlPlane;
- ctx.eua := cpr.endUserAddress;
- ctx.pco_neg := cpr.protConfigOptions;
- setverdict(pass);
- } else if (exp_cause != '80'O and exp_cause == cpr.cause.causevalue) {
+ if (not match(cpr.endUserAddress, (tr_EuaIPv4(?), tr_EuaIPv6(?)))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Cause not expected when requesting+receiving EUAv4v6");
+ }
+ } else {
if (ispresent(cpr.endUserAddress)) {
- log("EUA received on createPDPContextResponse cause=" & oct2str(cpr.cause.causevalue));
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "EUA received on createPDPContextResponse cause=" & oct2str(cpr.cause.causevalue));
}
setverdict(pass);
+ return;
+ }
+
+ /* Check if PCO response corresponds to request */
+ if (ispresent(ctx.pco_req)) {
+ if (match(ctx.pco_req, ts_PCO_IPv4_DNS_CONT) and
+ not match(cpr.protConfigOptions, tr_PCO_IPv4_DNS_CONT_resp(?))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "IPv4 DNS Container requested, but missing");
+ }
+ if (match(ctx.pco_req, ts_PCO_IPv6_DNS) and
+ not match(cpr.protConfigOptions, tr_PCO_IPv6_DNS_resp(?))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "IPv6 DNS Container requested, but missing");
+ }
+ }
+ ctx.teid_remote := cpr.teidDataI.teidDataI;
+ ctx.teic_remote := cpr.teidControlPlane.teidControlPlane;
+ ctx.eua := cpr.endUserAddress;
+ ctx.pco_neg := cpr.protConfigOptions;
+ setverdict(pass);
+ }
+
+ function f_handle_update_req(inout PdpContext ctx, in Gtp1cUnitdata ud, in OCT1 exp_cause := '80'O) runs on GT_CT {
+ var UpdatePDPContextResponseGGSN upr := ud.gtpc.gtpc_pdu.updatePDPContextResponse.updatePDPContextResponseGGSN;
+ if (exp_cause == '80'O and exp_cause == upr.cause.causevalue) {
+ ctx.teid_remote := upr.teidDataI.teidDataI;
+ ctx.teic_remote := upr.teidControlPlane.teidControlPlane;
+ if (ispresent(upr.protConfigOptions)) {
+ ctx.pco_neg := upr.protConfigOptions;
+ }
+ setverdict(pass);
+ } else if (exp_cause != '80'O and exp_cause == upr.cause.causevalue) {
+ setverdict(pass);
} else {
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "UpdatePDPContextResp: cause expectancies didn't match");
+ }
+ }
+
+ private altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on GT_CT {
+ var PDU_DIAMETER rx_dia;
+ [] Gx_UNIT.receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia {
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ var AVP_Unsigned32 req_num;
+
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_DCC_NONE_CC_Request_Number);
+ req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
+
+ Gx_UNIT.send(ts_DIA_Gx_CCA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
+ req_type, req_num));
+ }
+ [] Gx_UNIT.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
+ }
+ }
+
+ private function f_tr_DIA_Gy_CCR(template (omit) PdpContext ctx, DCC_NONE_CC_Request_Type req_type)
+ runs on GT_CT return template (present) PDU_DIAMETER
+ {
+ var template (present) PDU_DIAMETER tpl;
+ var charstring smf_origin_host := "smf.localdomain";
+ var template (present) octetstring imsi := ?;
+ var template (present) octetstring msisdn := ?;
+ var template (present) octetstring imeisv := ?;
+ var template (present) octetstring rat_type := ?;
+ var template (present) OCT4 charging_char := ?;
+ var template (present) OCT1 nsapi := ?;
+ if (not istemplatekind(ctx, "omit")) {
+ var PdpContext ctx_val := valueof(ctx);
+ imsi := char2oct(f_dec_TBCD(imsi_hex2oct(ctx_val.imsi)));
+ msisdn := char2oct(f_dec_TBCD(substr(ctx_val.msisdn, 1, lengthof(ctx_val.msisdn) -1)));
+ imeisv := char2oct(f_dec_TBCD(ctx_val.imeisv));
+ rat_type := ctx_val.ratType;
+ charging_char := char2oct(oct2str(ctx_val.charging_char));
+ nsapi := char2oct(hex2str(bit2hex(ctx_val.nsapi)));
+ }
+ select (req_type) {
+ case (INITIAL_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(g_gy_pars.origin_realm),
+ tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_MultipleServicesIndicator,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ tr_AVP_Requested_Service_Unit,
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ tr_AVP_3GPP_PDPType((IPv4,IPv6,IPv4v6)),
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ tr_AVP_3GPP_MS_TimeZone,
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type),
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })
+ ))
+ ))
+ ));
+ }
+ case (UPDATE_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(g_gy_pars.origin_realm),
+ tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_DestinationHost(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ tr_AVP_Requested_Service_Unit,
+ tr_AVP_Used_Service_Unit,
+ /* tr_AVP_3GPP_Reporting_Reason, can be sometimes inside UsedServiceUnit */
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ /* tr_AVP_3GPP_PDPType, Only in INIT */
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ tr_AVP_3GPP_MS_TimeZone,
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type),
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })
+ ))
+ ))
+ ));
+ }
+ case (TERMINATION_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(g_gy_pars.origin_realm),
+ tr_AVP_DestinationRealm(g_gy_pars.origin_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_DestinationHost(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_TerminationCause(?),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ /* tr_AVP_Requested_Service_Unit, Only in INIT and UPDATE */
+ tr_AVP_Used_Service_Unit,
+ tr_AVP_3GPP_Reporting_Reason(FINAL),
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ /* tr_AVP_3GPP_PDPType, Only in INIT */
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_bind_ip_gtpc))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(m_ggsn_ip_gtpc))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ tr_AVP_3GPP_MS_TimeZone,
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type),
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })
+ ))
+ ))
+ ));
+ }
+ }
+ return tpl;
+ }
+
+ private altstep as_DIA_Gy_CCR(template (omit) PdpContext ctx, DCC_NONE_CC_Request_Type req_type) runs on GT_CT {
+ [] Gy_UNIT.receive(f_tr_DIA_Gy_CCR(ctx, req_type := req_type)) -> value g_rx_gy {
+ var template (value) PDU_DIAMETER tx_dia;
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ var AVP_Unsigned32 req_num;
+
+ avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+
+ avp := f_DIAMETER_get_avp(g_rx_gy, c_AVP_Code_DCC_NONE_CC_Request_Number);
+ req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
+ if (g_gy_validity_time > 0) {
+ if (g_gy_volume_quota > 0) {
+ tx_dia := ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(
+ g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id,
+ sess_id, req_type, req_num,
+ g_gy_validity_time,
+ g_gy_volume_quota, g_gy_volume_threshold);
+ } else {
+ tx_dia := ts_DIA_Gy_CCA_ValidityTime(
+ g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id,
+ sess_id, req_type, req_num,
+ g_gy_validity_time);
+ }
+ } else {
+ tx_dia := ts_DIA_Gy_CCA(g_rx_gy.hop_by_hop_id, g_rx_gy.end_to_end_id, sess_id,
+ DIAMETER_SUCCESS, req_type, req_num);
+ }
+ Gy_UNIT.send(tx_dia);
+ }
+ [] Gy_UNIT.receive(PDU_DIAMETER:?) -> value g_rx_gy {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER Gy", g_rx_gy));
}
}
/* send a PDP context activation */
- function f_pdp_ctx_act(inout PdpContext ctx, OCT1 exp_cause := '80'O) runs on GT_CT {
+ function f_pdp_ctx_act(inout PdpContext ctx, template OCT1 exp_cause := '80'O) runs on GT_CT return CreatePDPContextResponse {
var Gtp1cUnitdata ud;
+ var CreatePDPContextResponse cpr;
var default d;
log("sending CreatePDP");
f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx.imsi, g_restart_ctr,
ctx.teid, ctx.teic, ctx.nsapi, ctx.eua, ctx.apn,
- g_sgsn_ip_c, g_sgsn_ip_u, ctx.msisdn, ctx.pco_req));
+ g_sgsn_ip_c, g_sgsn_ip_u, ctx.msisdn, ctx.pco_req, ctx.ratType,
+ ctx.uli, ctx.charging_char, ctx.imeisv, ctx.ms_tz));
T_default.start;
d := activate(pingpong());
+ if (Gx_PROC.checkstate("Connected")) {
+ as_DIA_Gx_CCR(INITIAL_REQUEST);
+ }
+ if (Gy_PROC.checkstate("Connected")) {
+ as_DIA_Gy_CCR(ctx, INITIAL_REQUEST);
+ }
alt {
[] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ctx.teic)) -> value ud {
f_handle_create_req(ctx, ud, exp_cause);
+ cpr := ud.gtpc.gtpc_pdu.createPDPContextResponse;
}
}
deactivate(d);
T_default.stop;
+ return cpr;
}
function f_pdp_ctx_exp_del_req(PdpContext ctx, template (omit) OCT1 expect_cause := omit, boolean expect_teardown := false) runs on GT_CT {
@@ -343,13 +755,16 @@ module GGSN_Tests {
ud.gtpc.gtpc_pdu.deletePDPContextRequest.cause.causevalue == valueof(expect_cause)) {
setverdict(pass);
} else {
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "DeletePDPContextReq: cause expectancies didn't match");
}
if (expect_teardown == ispresent(ud.gtpc.gtpc_pdu.deletePDPContextRequest.tearDownIndicator)) {
setverdict(pass);
} else {
setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "DeletePDPContextReq: tearDownIndicator expectancies didn't match");
}
}
}
@@ -357,7 +772,7 @@ module GGSN_Tests {
T_default.stop;
}
- function f_pdp_ctx_del(PdpContext ctx, template BIT1 teardown_ind, OCT1 expect_causevalue := '80'O) runs on GT_CT {
+ function f_pdp_ctx_del(PdpContext ctx, template BIT1 teardown_ind, OCT1 expect_causevalue := '80'O, boolean expect_diameter := true) runs on GT_CT {
var Gtp1cUnitdata ud;
var default d;
var OCT4 expect_teid;
@@ -373,335 +788,87 @@ module GGSN_Tests {
f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, ctx.teic_remote, ctx.nsapi, teardown_ind));
T_default.start;
d := activate(pingpong());
+ if (Gx_PROC.checkstate("Connected") and expect_diameter) {
+ as_DIA_Gx_CCR(TERMINATION_REQUEST);
+ }
+ if (Gy_PROC.checkstate("Connected") and expect_diameter) {
+ as_DIA_Gy_CCR(ctx, TERMINATION_REQUEST);
+ }
alt {
[] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, expect_teid)) -> value ud {
if (ud.gtpc.gtpc_pdu.deletePDPContextResponse.cause.causevalue == expect_causevalue) {
setverdict(pass);
} else {
- setverdict(fail);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "DeletePDPContextResp: cause expectancies didn't match");
}
}
}
deactivate(d);
T_default.stop;
}
- /* IPv6 router solicitation fe80::2 -> ff02::2 from 02:88:b5:1f:25:59 */
- const octetstring c_router_solicit := '6000000000103afffe800000000000000000000000000002ff02000000000000000000000000000285009f2b0000000001010288b51f2559'O;
- /* IPv6 neighbor solicitation fe80::2 -> ff02::1:ff00:2 from 02:88:b5:1f:25:59 */
- const octetstring c_neigh_solicit:= '6000000000203afffe800000000000000000000000000002ff0200000000000000000001ff00000287009f9600000000fe80000000000000000000000000000201010288b51f2559'O;
-
- /* template for sending an ICMPv4 echo request */
- template PDU_ICMP ts_ICMPv4_ERQ := {
- echo := {
- type_field := 8,
- code := 0,
- checksum := '0000'O,
- identifier := '0345'O,
- sequence_number := '0001'O,
- data := ''O
- }
- }
-
- /* template for receiving/matching an ICMPv4 echo request */
- template PDU_ICMP tr_ICMPv4_ERQ := {
- echo := {
- type_field := 8,
- code := 0,
- checksum := ?,
- identifier := ?,
- sequence_number := ?,
- data := ?
- }
- }
-
- /* template for receiving/matching an ICMPv4 echo reply */
- template PDU_ICMP tr_ICMPv4_ERP(template octetstring data := *) := {
- echo_reply := {
- type_field := 0,
- code := 0,
- checksum := ?,
- identifier := ?,
- sequence_number := ?,
- data := data
- }
- }
-
- /* template for receiving/matching an ICMPv6 Destination Unreachable */
- template PDU_ICMP tr_ICMPv4_DU := {
- destination_unreachable := {
- type_field := 1,
- code := ?,
- checksum := ?,
- unused := ?,
- original_ip_msg := ?
- }
- }
-
- /* template to construct IPv4_packet from input arguments, ready for use in f_IPv4_enc() */
- template IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, LIN2_BO_LAST tlen, octetstring payload) := {
- header := {
- ver := 4,
- hlen := 5,
- tos := 0,
- tlen := tlen,
- id := 35902,
- res := '0'B,
- dfrag := '1'B,
- mfrag := '0'B,
- foffset := 0,
- ttl := 64,
- proto := proto,
- cksum := 0,
- srcaddr := srcaddr,
- dstaddr := dstaddr
- },
- ext_headers := omit,
- payload := payload
- }
-
- /* template to generate a 'Prefix Information' ICMPv6 option */
- template OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
- prefixInformation := {
- typeField := 3,
- lengthIndicator := 8,
- prefixLength := prefix_len,
- reserved1 := '000000'B,
- a_Bit := '0'B,
- l_Bit := '0'B,
- validLifetime := oct2int('FFFFFFFF'O),
- preferredLifetime := oct2int('FFFFFFFF'O),
- reserved2 := '00000000'O,
- prefix := prefix
- }
- }
-
- /* template for sending an ICMPv6 echo request */
- template PDU_ICMPv6 ts_ICMPv6_ERQ := {
- echoRequest := {
- typeField := 128,
- code := 0,
- checksum := '0000'O,
- identifier := 0,
- sequenceNr := 0,
- data := ''O
- }
- }
-
- /* template for sending an ICMPv6 router solicitation */
- template PDU_ICMPv6 ts_ICMPv6_RS := {
- routerSolicitation := {
- typeField := 133,
- code := 0,
- checksum := '0000'O,
- reserved := '00000000'O,
- /* TODO: do we need 'Source link-layer address' ? */
- options := omit
- }
- }
-
- /* template for sending an ICMPv6 router advertisement */
- template PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
- routerAdvertisement := {
- typeField := 134,
- code := 0,
- checksum := '0000'O,
- curHopLimit := ?,
- reserved := '000000'B,
- o_Bit := '0'B,
- m_Bit := '0'B,
- routerLifetime := oct2int('FFFF'O),
- reachableTime := oct2int('FFFFFFFF'O),
- retransTimer := oct2int('FFFFFFFF'O),
- options := {
- ts_ICMP6_OptPrefix(prefix, prefix_len)
- }
- }
- }
- /* template for sending an ICMPv6 neighbor solicitation */
- template PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
- neighborSolicitation := {
- typeField := 135,
- code := 0,
- checksum := '0000'O,
- reserved := '00000000'O,
- targetAddress := target_addr,
- /* TODO: do we need 'Source link-layer address' ? */
- options := omit
- }
- }
-
- /* derive ICMPv6 link-local address from lower 64bit of link_id */
- /* template for receiving/matching an ICMPv6 'Prefix Information' option */
- template OptionField tr_ICMP6_OptPrefix(template OCT16 prefix, template INT1 prefix_len) := {
- prefixInformation := {
- typeField := 3,
- lengthIndicator := 4,
- prefixLength := prefix_len,
- reserved1 := ?,
- a_Bit := ?,
- l_Bit := ?,
- validLifetime := ?,
- preferredLifetime := ?,
- reserved2 := ?,
- prefix := prefix
- }
- }
-
- /* template for receiving/matching an ICMPv6 router advertisement */
- template PDU_ICMPv6 tr_ICMPv6_RA(template OCT16 prefix, template INT1 prefix_len) := {
- routerAdvertisement := {
- typeField := 134,
- code := 0,
- checksum := ?,
- curHopLimit := ?,
- reserved := ?,
- o_Bit := '0'B,
- m_Bit := '0'B,
- routerLifetime := ?,
- reachableTime := ?,
- retransTimer := ?,
- options := {
- tr_ICMP6_OptPrefix(prefix, prefix_len)
- }
- }
- }
+ /* send a Update PdP Context Request, expect Response */
+ function f_pdp_ctx_update(inout PdpContext ctx, OCT1 exp_cause := '80'O, template (omit) OCT4 new_teid := omit, template (omit) OCT4 new_teic := omit) runs on GT_CT {
+ var Gtp1cUnitdata ud;
+ var default d;
- /* template for receiving/matching an ICMPv6 Destination Unreachable */
- template PDU_ICMPv6 tr_ICMPv6_DU := {
- destinationUnreachable := {
- typeField := 1,
- code := ?,
- checksum := ?,
- unused := ?,
- originalIpMsg := ?
+ if (not istemplatekind(new_teid, "omit")) {
+ ctx.teid := valueof(new_teid);
}
- }
-
- /* template for receiving/matching an ICMPv6 echo request */
- template PDU_ICMPv6 tr_ICMPv6_ERQ := {
- echoRequest := {
- typeField := 128,
- code := 0,
- checksum := ?,
- identifier := ?,
- sequenceNr := ?,
- data := ?
+ if (not istemplatekind(new_teic, "omit")) {
+ ctx.teic := valueof(new_teic);
}
- }
- /* template for receiving/matching an ICMPv6 echo reply */
- template PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := {
- echoReply := {
- typeField := 129,
- code := 0,
- checksum := ?,
- identifier := ?,
- sequenceNr := ?,
- data := data
+ log("sending UpdatePDP");
+ f_send_gtpc(ts_GTPC_UpdatePDP(g_peer_c, ctx.teic_remote, g_c_seq_nr, ctx.imsi, g_restart_ctr,
+ ctx.teid, ctx.teic, ctx.nsapi, g_sgsn_ip_c, g_sgsn_ip_u,
+ ctx.pco_req, ctx.ratType, ctx.uli));
+ T_default.start;
+ d := activate(pingpong());
+ alt {
+ [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, updatePDPContextResponse, ctx.teic)) -> value ud {
+ f_handle_update_req(ctx, ud, exp_cause);
+ }
}
+ deactivate(d);
+ T_default.stop;
}
- /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
- template IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
- header := {
- ver := 6,
- trclass := 0,
- flabel := 0,
- plen := 0,
- nexthead := nexthead,
- hlim := hlim,
- srcaddr := srcaddr,
- dstaddr := dstaddr
- },
- ext_headers := omit,
- payload := payload
- }
-
- function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
- return 'FE80000000000000'O & substr(link_id, 8, 8);
- }
-
- function f_ipv6_global(in OCT16 link_id) return OCT16 {
- return substr(link_id, 0, 8) & '1234123412341234'O;
- }
-
- /* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */
- function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 {
- var integer i;
- var octetstring res := substr(addr, 0, prefix);
- for (i := prefix; i < lengthof(addr); i := i + 1) {
- var octetstring a := addr[i] xor4b '11'O;
- res := res & a;
+ /* Get link-id from PDP Context EUA */
+ function f_ctx_get_ipv6_interface_id(in PdpContext ctx) return OCT16 {
+ var OCT16 interface_id;
+ if (ischosen(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6)) {
+ interface_id := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address;
+ } else if (ischosen(ctx.eua.endUserAddress.endUserAddressIPv6)) {
+ interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unexpected request to submit icmpv6 rs in IPv4 PDP context");
}
- return res;
- }
-
- /* Compute solicited-node multicast address as per RFC4291 2.7.1 */
- function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
- return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
- }
-
- /* generate and encode ICMPv6 router solicitation */
- function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
- const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
- var OCT16 saddr := f_ipv6_link_local(link_id);
-
- var octetstring tmp;
- tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
- var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));
-
- return f_IPv6_enc(ip6);
+ return interface_id;
}
/* create ICMPv6 router solicitation deriving link-id from PDP Context EUA */
function f_icmpv6_rs_for_pdp(in PdpContext ctx) return octetstring {
- var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
+ var OCT16 interface_id := f_ctx_get_ipv6_interface_id(ctx);
return f_gen_icmpv6_router_solicitation(interface_id);
}
- /* generate and encode ICMPv6 neighbor solicitation */
- function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
- var octetstring tmp;
- tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
- var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
- return f_IPv6_enc(ip6);
- }
-
/* generate and encode ICMPv6 neighbor solicitation for PDP Context */
function f_gen_icmpv6_neigh_solicit_for_pdp(in PdpContext ctx) return octetstring {
- var OCT16 interface_id := ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address;
+ var OCT16 interface_id := f_ctx_get_ipv6_interface_id(ctx);
var OCT16 link_local := f_ipv6_link_local(interface_id);
var OCT16 daddr := f_ipv6_sol_node_mcast(link_local);
return f_gen_icmpv6_neigh_solicit(link_local, daddr, link_local);
}
- /* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */
- function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr) return octetstring {
- var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ));
- var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp));
- var octetstring data := f_IPv4_enc(ip4);
- var OCT2 cksum := f_IPv4_checksum(data);
- data[10] := cksum[0];
- data[11] := cksum[1];
- return data;
- }
-
- /* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */
- function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring {
- var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr);
- var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
- var octetstring data := f_IPv6_enc(ip6);
- return data;
- }
-
/* Wait for ICMPv4 from GTP */
function f_wait_icmp4(PdpContext ctx, template PDU_ICMP expected) runs on GT_CT {
var Gtp1uUnitdata ud;
T_default.start;
alt {
- [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
+ [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ctx.teid)) -> value ud {
if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
setverdict(fail);
stop;
@@ -716,6 +883,9 @@ module GGSN_Tests {
repeat;
}
}
+ [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
+ setverdict(fail, "Received wrong local TEID");
+ }
[] GTPU.receive { setverdict(fail); }
[] T_default.timeout { setverdict(fail); }
}
@@ -739,8 +909,8 @@ module GGSN_Tests {
alt {
[] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value ud {
if (f_verify_gtpu_txseq(ud.gtpu, use_gtpu_txseq) == false) {
- setverdict(fail);
- stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received GTPU with wrong txseq while waiting for ICMPv6: ", expected));
}
var octetstring gpdu := ud.gtpu.gtpu_IEs.g_PDU_IEs.data;
var IPv6_packet ip6 := f_IPv6_dec(gpdu);
@@ -758,8 +928,14 @@ module GGSN_Tests {
}
}
[] GTPU.receive(tr_GTPU_GPDU(?, ?)) { repeat; }
- [] GTPU.receive { setverdict(fail); }
- [] T_default.timeout { setverdict(fail); }
+ [] GTPU.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected GTPU while waiting for ICMPv6: ", expected));
+ }
+ [] T_default.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Timeout waiting for ICMPv6: ", expected));
+ }
}
T_default.stop;
}
@@ -835,16 +1011,17 @@ module GGSN_Tests {
testcase TC_pdp6_act_deact() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
f_pdp_ctx_act(ctx);
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test IPv6 context activation for dynamic IPv6 EUA wirh request of IPv6 DNS in PCO */
testcase TC_pdp6_act_deact_pcodns() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
f_pdp_ctx_act(ctx);
@@ -861,32 +1038,32 @@ module GGSN_Tests {
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement */
testcase TC_pdp6_act_deact_icmp6() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
f_pdp_ctx_act(ctx);
f_PCO_ensure_no_duplicates(ctx.pco_neg);
- //f_send_gtpu(ctx, c_router_solicit);
- //f_send_gtpu(ctx, c_neigh_solicit);
f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
f_wait_rtr_adv(ctx);
f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv6 EUA with IPv6 DNS in PCO and router solicitation/advertisement.
Test we can send ICMPv6 ping over GTPU to DNS server. */
testcase TC_pdp6_act_deact_gtpu_access() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
f_pdp_ctx_act(ctx);
@@ -899,37 +1076,87 @@ module GGSN_Tests {
/* Check if we can use valid link-local src addr. */
var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_ll, dns1_addr));
+ if (m_ggsn_impl == GGSN_IMPL_OSMOCOM) {
+ f_wait_icmp6_echo_reply(ctx);
+ } else {
+ f_wait_gtpu_fail(ctx);
+ }
+
+ /* Check if we can use valid global src addr, should work */
+ var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
+ f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_glob, dns1_addr));
f_wait_icmp6_echo_reply(ctx);
- /* Check that attempting RA with another ll src addr won't work, packet dropped: */
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Check that attempting RA with another ll src addr won't work, packet dropped: */
+ testcase TC_pdp6_act_deact_gtpu_access_wrong_ll_saddr() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
+ f_pdp_ctx_act(ctx);
+
+ f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
+ f_wait_rtr_adv(ctx);
+ f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
+
+ var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8);
f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong));
f_wait_gtpu_fail(ctx);
- /* Check if we can use valid global src addr, should work */
- var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
- f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_glob, dns1_addr));
- f_wait_icmp6_echo_reply(ctx);
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
- /* Assert that packets with wrong global src addr are dropped by GGSN */
+ /* Assert that packets with wrong global src addr are dropped by GGSN */
+ testcase TC_pdp6_act_deact_gtpu_access_wrong_global_saddr() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
+ f_pdp_ctx_act(ctx);
+
+ f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
+ f_wait_rtr_adv(ctx);
+ f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
+
+ var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
+ var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv6.ipv6_address);
var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob);
f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr));
f_wait_gtpu_fail(ctx);
- /* Send an IPv4 ICMP ECHO REQUEST to APN6, should fail (packet dropped) */
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Send an IPv4 ICMP ECHO REQUEST to APN6, should fail (packet dropped */
+ testcase TC_pdp6_act_deact_gtpu_access_ipv4_apn6() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
+ f_pdp_ctx_act(ctx);
+
+ f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
+ f_wait_rtr_adv(ctx);
+ f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
+
var OCT4 saddr_v4 := f_inet_addr("192.168.10.2");
var OCT4 daddr_v4 := f_inet_addr("8.8.8.8");
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_v4, daddr_v4));
f_wait_gtpu_fail(ctx);
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Validate if different clients (pdp ctx) can reach one another through GGSN. */
testcase TC_pdp6_clients_interact() runs on GT_CT {
f_init();
- var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
- var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
+ var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet6, valueof(t_EuaIPv6Dyn)));
f_pdp_ctx_act(ctxA);
f_send_gtpu(ctxA, f_icmpv6_rs_for_pdp(ctxA));
f_wait_rtr_adv(ctxA);
@@ -955,14 +1182,16 @@ module GGSN_Tests {
f_pdp_ctx_del(ctxA, '1'B);
f_pdp_ctx_del(ctxB, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4 EUA without DNS request */
testcase TC_pdp4_act_deact() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
f_pdp_ctx_act(ctx);
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP */
@@ -970,8 +1199,9 @@ module GGSN_Tests {
f_init();
var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
- ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP);
+ var uint8_t ipcp_req_id := oct2int(f_rnd_octstring(1));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP(ipcp_req_id));
f_pdp_ctx_act(ctx);
f_PCO_ensure_no_duplicates(ctx.pco_neg);
/* verify IPCP is at all contained */
@@ -980,14 +1210,19 @@ module GGSN_Tests {
}
/* verify IPCP contains both primary and secondary DNS */
var IpcpPacket ipcp := dec_IpcpPacket(f_PCO_extract_proto(ctx.pco_neg, '8021'O));
- if (not match(ipcp, tr_IPCP_Ack_DNS(0, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
- if (not match(ipcp, tr_IPCP_Ack_DNS(0))) {
- setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
+ if (not match(ipcp, tr_IPCP_Ack_DNS(ipcp_req_id, ggsn_ip4_dns1, ggsn_ip4_dns2))) {
+ if (not match(ipcp, tr_IPCP_Ack_DNS(ipcp_req_id))) {
+ if (not match(ipcp, tr_IPCP_Ack_DNS(?))) {
+ setverdict(fail, "Primary/Secondary DNS PCO IPCP option not found");
+ } else {
+ setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected identifier");
+ }
} else {
setverdict(fail, "Primary/Secondary DNS PCO IPCP option found but not matching expected values");
}
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in IPCP + PAP authentication (broken) */
@@ -995,7 +1230,7 @@ module GGSN_Tests {
f_init();
var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
ctx.pco_req := valueof(ts_PCO_PAP_IPv4_DNS);
f_pdp_ctx_act(ctx);
f_PCO_ensure_no_duplicates(ctx.pco_neg);
@@ -1021,12 +1256,13 @@ module GGSN_Tests {
setverdict(fail, "PAP isn't an AuthenticateAck: ", pap);
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4 EUA with IPv4 DNS in PCO */
testcase TC_pdp4_act_deact_pcodns() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
f_pdp_ctx_act(ctx);
@@ -1043,13 +1279,14 @@ module GGSN_Tests {
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4 EUA.
Test we can send ICMPv6 ping over GTPU to DNS server. */
testcase TC_pdp4_act_deact_gtpu_access() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
f_pdp_ctx_act(ctx);
@@ -1061,23 +1298,49 @@ module GGSN_Tests {
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
f_wait_icmp4_echo_reply(ctx);
- /* Assert that packets with wrong global src addr are dropped by GGSN */
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Assert that packets with wrong global src addr are dropped by GGSN */
+ testcase TC_pdp4_act_deact_gtpu_access_wrong_saddr() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ f_PCO_ensure_no_duplicates(ctx.pco_neg);
+ var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
+ var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O);
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr));
f_wait_gtpu_fail(ctx);
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Send an IPv6 RA to APN4, should fail (packet dropped) */
+ testcase TC_pdp4_act_deact_gtpu_access_ipv6_apn4() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
/* Send an IPv6 RA to APN4, should fail (packet dropped) */
var OCT16 saddr_v6 := f_inet6_addr("fde4:8dba:82e1:2000:1:2:3:4");
f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_v6));
f_wait_gtpu_fail(ctx);
+
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Helper function for tests below. */
function f_pdp4_clients_interact() runs on GT_CT {
f_init();
- var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
- var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
f_pdp_ctx_act(ctxA);
f_pdp_ctx_act(ctxB);
var OCT4 addrA := ctxA.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
@@ -1093,12 +1356,14 @@ module GGSN_Tests {
testcase TC_pdp4_clients_interact_with_txseq() runs on GT_CT {
use_gtpu_txseq := true;
f_pdp4_clients_interact();
+ f_shutdown_helper();
}
/* Validate if different clients (pdp ctx) can reach one another through GGSN (without Tx sequence number). */
testcase TC_pdp4_clients_interact_without_txseq() runs on GT_CT {
use_gtpu_txseq := false;
f_pdp4_clients_interact();
+ f_shutdown_helper();
}
testcase TC_echo_req_resp() runs on GT_CT {
@@ -1111,6 +1376,20 @@ module GGSN_Tests {
[] T_default.timeout { setverdict(fail); }
}
T_default.stop;
+ f_shutdown_helper();
+ }
+
+ testcase TC_echo_req_resp_gtpu() runs on GT_CT {
+ f_init();
+ GTPU.send(ts_GTPU_PING(g_peer_u, g_d_seq_nr));
+ T_default.start;
+ alt {
+ [] GTPU.receive(tr_GTPU_PONG(g_peer_u)) { setverdict(pass); };
+ [] GTPU.receive { repeat; };
+ [] T_default.timeout { setverdict(fail); }
+ }
+ T_default.stop;
+ f_shutdown_helper();
}
/* Test if the parser can cope with PCO that only contain either a
@@ -1122,7 +1401,7 @@ module GGSN_Tests {
* see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
var octetstring pco_neg_dns;
@@ -1147,6 +1426,7 @@ module GGSN_Tests {
f_pdp_ctx_del(ctx, '1'B);
/* PCO with secondary DNS only */
+ ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_SEC_DNS_IPCP);
f_pdp_ctx_act(ctx);
pco_neg_dns := f_PCO_extract_proto(ctx.pco_neg, '8021'O, 1);
@@ -1155,6 +1435,7 @@ module GGSN_Tests {
setverdict(fail, "Secondary DNS IPv4 PCO option not found");
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test if the parser can cope with PCO that contains primary and secondary DNS in a separate IPCP container.
@@ -1167,7 +1448,7 @@ module GGSN_Tests {
* see also: Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
var octetstring pco_neg_dns;
@@ -1191,14 +1472,60 @@ module GGSN_Tests {
setverdict(fail, "Secondary DNS IPv4 PCO option not found");
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Validate that SUT updates remote TEIC when requested through UpdatePDPContextRequest */
+ testcase TC_pdp4_act_update_teic() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ /* UpdatePDPContestRequest changing the local TEIC */
+ var OCT4 new_teic := ctx.teic;
+ new_teic[3] := new_teic[3] xor4b '11'O;
+ f_pdp_ctx_update(ctx, new_teic := new_teic);
+
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Validate that SUT updates remote TEID when requested through UpdatePDPContextRequest */
+ testcase TC_pdp4_act_update_teid() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ f_PCO_ensure_no_duplicates(ctx.pco_neg);
+ var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
+ var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
+
+ /* Data is sent (back) to the local TEID established during CreatePDPContext */
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+
+ /* UpdatePDPContestRequest changing the local TEID */
+ var OCT4 new_teid := ctx.teid;
+ new_teid[3] := new_teid[3] xor4b '11'O;
+ f_pdp_ctx_update(ctx, new_teid := new_teid);
+
+ /* Check if we can send data after updating the PDP context. Answer should be sent to the new TEID */
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test IPv4v6 context activation for dynamic IPv4v6 EUA without DNS request */
testcase TC_pdp46_act_deact() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
f_pdp_ctx_act(ctx);
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4v6 EUA with IPv4 DNS in IPCP */
@@ -1206,7 +1533,7 @@ module GGSN_Tests {
f_init();
var OCT4 ggsn_ip4_dns1 := f_inet_addr(m_ggsn_ip4_dns1);
var OCT4 ggsn_ip4_dns2 := f_inet_addr(m_ggsn_ip4_dns2);
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_DNS_IPCP);
f_pdp_ctx_act(ctx);
f_PCO_ensure_no_duplicates(ctx.pco_neg);
@@ -1225,12 +1552,13 @@ module GGSN_Tests {
}
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4v6 EUA with IPv6 DNS in PCO and router solicitation/advertisement */
testcase TC_pdp46_act_deact_icmp6() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
f_pdp_ctx_act(ctx);
@@ -1239,13 +1567,14 @@ module GGSN_Tests {
f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp46(ctx));
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test IPv4v6 context activation for dynamic IPv4v6 EUA with request of IPv4 DNS in PCO */
testcase TC_pdp46_act_deact_pcodns4() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
f_pdp_ctx_act(ctx);
@@ -1262,13 +1591,14 @@ module GGSN_Tests {
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test IPv4v6 context activation for dynamic IPv4v6 EUA with request of IPv6 DNS in PCO */
testcase TC_pdp46_act_deact_pcodns6() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
f_pdp_ctx_act(ctx);
@@ -1285,13 +1615,14 @@ module GGSN_Tests {
}
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Test PDP context activation for dynamic IPv4v6 EUA.
Test we can send ICMPv6 ping over GTPU to DNS server. */
testcase TC_pdp46_act_deact_gtpu_access() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
f_pdp_ctx_act(ctx);
@@ -1302,23 +1633,69 @@ module GGSN_Tests {
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
f_wait_icmp4_echo_reply(ctx);
- /* Assert that packets with wrong global src addr are dropped by GGSN */
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Assert that packets with wrong ipv4 src addr are dropped by GGSN on APN IPv4v6 */
+ testcase TC_pdp46_act_deact_gtpu_access_wrong_saddr_ipv4() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
+ var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv4_address;
var OCT4 saddr_wrong := substr(saddr, 0, 3) & (saddr[3] xor4b '11'O);
f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr_wrong, dns1_addr));
f_wait_gtpu_fail(ctx);
- /* Send an IPv6 RA to APN4, should fail (packet dropped) */
- var OCT16 saddr_v6 := f_inet6_addr("fde4:8dba:82e1:2000:1:2:3:4");
- f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_v6));
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Check that attempting RA with another ll src addr won't work, packet dropped: */
+ testcase TC_pdp46_act_deact_gtpu_access_wrong_ll_saddr_ipv6() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ var OCT16 saddr_ll := f_ipv6_link_local(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
+ var OCT16 saddr_ll_wrong := f_ipv6_mangle(saddr_ll, 8);
+ f_send_gtpu(ctx, f_gen_icmpv6_router_solicitation(saddr_ll_wrong));
f_wait_gtpu_fail(ctx);
+
f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
+ }
+
+ /* Assert that packets with wrong ipv6 global src addr are dropped by GGSN on APN IPv4v6 */
+ testcase TC_pdp46_act_deact_gtpu_access_wrong_global_saddr_ipv6() runs on GT_CT {
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv6_DNS);
+ f_pdp_ctx_act(ctx);
+
+ f_send_gtpu(ctx, f_icmpv6_rs_for_pdp(ctx));
+ f_wait_rtr_adv(ctx);
+ f_send_gtpu(ctx, f_gen_icmpv6_neigh_solicit_for_pdp(ctx));
+
+ var OCT16 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '0003'O);
+ var OCT16 saddr_glob := f_ipv6_global(ctx.eua.endUserAddress.endUserAddressIPv4andIPv6.ipv6_address);
+ var OCT16 saddr_wrong := f_ipv6_mangle(saddr_glob);
+ f_send_gtpu(ctx, f_gen_icmpv6_echo(saddr_wrong, dns1_addr));
+ f_wait_gtpu_fail(ctx);
+
+ f_pdp_ctx_del(ctx, '1'B);
+ f_shutdown_helper();
}
/* Validate if different clients (pdp ctx) can reach one another through GGSN. */
testcase TC_pdp46_clients_interact() runs on GT_CT {
f_init();
- var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
- var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
+ var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInet46, valueof(t_EuaIPv4Dynv6Dyn)));
f_pdp_ctx_act(ctxA);
f_send_gtpu(ctxA, f_icmpv6_rs_for_pdp46(ctxA));
f_wait_rtr_adv(ctxA);
@@ -1344,22 +1721,46 @@ module GGSN_Tests {
f_pdp_ctx_del(ctxA, '1'B);
f_pdp_ctx_del(ctxB, '1'B);
+ f_shutdown_helper();
}
/* Test IPv4v6 context activation for dynamic IPv4v6 EUA on a v4-only APN */
testcase TC_pdp46_act_deact_apn4() runs on GT_CT {
- f_init();
- /* A typical MS first attempts v4v6, and if rejected, then tries v4 and v6 separetly */
- var PdpContext ctx46 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dynv6Dyn)));
- f_pdp_ctx_act(ctx46, 'DC'O); /* Cause: Unknown PDP address or PDP type */
-
- var PdpContext ctx4 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
- f_pdp_ctx_act(ctx4, '80'O); /* Normal accept cause */
-
- var PdpContext ctx6 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv6Dyn)));
- f_pdp_ctx_act(ctx6, 'DC'O); /* Cause: Unknown PDP address or PDP type */
+ const OCT1 cause_accept := '80'O; /* Normal accept cause */
+ const OCT1 cause_new_pdp_type := '81'O; /* Cause: New PDP type due to network preference */
+ const OCT1 cause_unknown_pdp := 'DC'O; /* Cause: Unknown PDP address or PDP type */
+ var CreatePDPContextResponse cpr;
- f_pdp_ctx_del(ctx4, '1'B);
+ f_init();
+ var PdpContext ctx46 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dynv6Dyn)));
+ cpr := f_pdp_ctx_act(ctx46, (cause_unknown_pdp, cause_new_pdp_type));
+
+ if (cpr.cause.causevalue == cause_new_pdp_type) {
+ /* 3GPP TS 23.060 sec 9.2.1: "If the MS requests PDP type IPv4v6,
+ * but the operator preferences dictate the use of a single IP
+ * version only, the PDP type shall be changed to a single address
+ * PDP type (IPv4 or IPv6) and a reason cause shall be returned to
+ * the MS indicating that only the assigned PDP type is allowed. In
+ * this case, the MS shall not request another PDP context for the
+ * other PDP type during the existence of the PDP context." */
+ f_pdp_ctx_del(ctx46, '1'B);
+ } else {
+ /* 3GPP TS 23.060 sec 9.2.1 NOTE 5: If the MS requests PDP type
+ * IPv4v6, and the PDP context is rejected due to "unknown PDP
+ * type", the MS can attempt to establish dual-stack connectivity
+ * by performing two PDP context request procedures to activate an
+ * IPv4 PDP context and an IPv6 PDP context, both to the same APN. A
+ * typical MS first attempts v4v6, and if rejected, then tries v4
+ * and v6 separetly */
+ var PdpContext ctx4 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ f_pdp_ctx_act(ctx4, cause_accept); /* Normal accept cause */
+
+ var PdpContext ctx6 := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv6Dyn)));
+ f_pdp_ctx_act(ctx6, cause_unknown_pdp); /* Cause: Unknown PDP address or PDP type */
+
+ f_pdp_ctx_del(ctx4, '1'B);
+ }
+ f_shutdown_helper();
}
/* Validate if 2nd CtxCreateReq with increased Recovery IE causes ggsn to drop 1st one (while keeping 2nd one). */
@@ -1370,11 +1771,11 @@ module GGSN_Tests {
var boolean ctxB_created := false;
f_init();
- var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
- var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctxA := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctxB := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
f_pdp_ctx_act(ctxA);
- g_restart_ctr := int2oct(oct2int(g_restart_ctr) + 1, 1);
+ g_restart_ctr := int2oct((oct2int(g_restart_ctr) + 1) mod 256, 1);
log("sending 2nd CreatePDP (recovery increased)");
f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctxB.imsi, g_restart_ctr,
@@ -1422,86 +1823,472 @@ module GGSN_Tests {
T_default.stop;
f_pdp_ctx_del(ctxB, '1'B);
+ f_shutdown_helper();
}
- /* Send a duplicate echo req. osmo-ggsn maintains a queue for sent
- responses (60 seconds): If same delete req is sent and duplicate is
- detected, saved duplicate response should be sent back. */
+ /* Send a duplicate echo req. osmo-ggsn maintains a queue for sent responses (T3-RESPONSE * N3-REQUESTS):
+ * If same delete req is sent and duplicate is detected, saved duplicate response should be sent back. */
testcase TC_act_deact_retrans_duplicate() runs on GT_CT {
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
f_pdp_ctx_act(ctx);
f_pdp_ctx_del(ctx, '1'B);
/* leave some time in between to make sure retransmit response queue keeps packets for a while */
- f_sleep(1.0);
+ f_sleep(int2float(mp_t3_response));
/* g_c_seq_nr was increased during f_pdp_ctx_del(), we want a
duplicate. If it was not a duplicate, osmo-ggsn would answer
with a failure since that PDP ctx was already deleted. */
- g_c_seq_nr := g_c_seq_nr - 1;
- f_pdp_ctx_del(ctx, '1'B);
+ if (g_c_seq_nr == 0) {
+ g_c_seq_nr := 65535;
+ } else {
+ g_c_seq_nr := g_c_seq_nr - 1;
+ }
+ f_pdp_ctx_del(ctx, '1'B, expect_diameter := false);
/* Now send a new pdp ctx del (increased seqnum). It should fail with cause "non-existent": */
var OCT1 cause_nonexistent := 'C0'O;
- f_pdp_ctx_del(ctx, '1'B, cause_nonexistent);
+ f_pdp_ctx_del(ctx, '1'B, cause_nonexistent, expect_diameter := false);
+ f_shutdown_helper();
}
/* Activate PDP context + trigger Recovery procedure through EchoResp */
testcase TC_pdp_act_restart_ctr_echo() runs on GT_CT {
var Gtp1cUnitdata ud;
- g_use_echo := true;
+ g_use_echo_intval := 5;
+ timer T_echo;
f_init();
- var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), '1234'O, c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
f_pdp_ctx_act(ctx);
/* Wait to receive echo request and send initial Restart counter */
- GTPC.receive(tr_GTPC_PING(?)) -> value ud {
+ T_echo.start(int2float(g_use_echo_intval) + 1.0);
+ alt {
+ [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
- };
+ }
+ [] T_echo.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Timeout waiting for ping");
+ }
+ }
+ T_echo.stop;
/* Wait to receive second echo request and send incremented Restart
counter. This will fake a restarted SGSN, and pdp ctx allocated
should be released by GGSN */
- g_restart_ctr := int2oct(oct2int(g_restart_ctr) + 1, 1);
- GTPC.receive(tr_GTPC_PING(?)) -> value ud {
+ g_restart_ctr := int2oct((oct2int(g_restart_ctr) + 1) mod 256, 1);
+ T_echo.start(int2float(g_use_echo_intval) + 1.0);
+ alt {
+ [] GTPC.receive(tr_GTPC_PING(?)) -> value ud {
var uint16_t seq := oct2int(ud.gtpc.opt_part.sequenceNumber);
GTPC.send(ts_GTPC_PONG(ud.peer, seq, g_restart_ctr));
- };
+ }
+ [] T_echo.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Timeout waiting for ping");
+ }
+ }
+ T_echo.stop;
f_pdp_ctx_exp_del_req(ctx, omit, true);
- setverdict(pass);
+ f_shutdown_helper();
+ }
+
+ /* Test creation, user plane and deletion of big amount (1000) of concurrent PDP context */
+ testcase TC_lots_of_concurrent_pdp_ctx() runs on GT_CT {
+ var Gtp1cUnitdata udc;
+ var Gtp1uUnitdata udu;
+ const integer num_ctx := 1000;
+ var PdpContext ctx[num_ctx];
+ timer T_next := 0.01;
+ var integer next_req_ctx := 0;
+ var integer rx_resp_ctx := 0;
+ var integer rx_pong := 0;
+ var OCT4 dns1_addr;
+ var OCT4 saddr;
+ var integer teic;
+ var integer idx;
+
+ f_init();
+
+ for (var integer i := 0; i < num_ctx; i := i + 1) {
+ ctx[i] := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234" & int2str(f_rnd_int(4294967296)), c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx[i].teic := int2oct(i+1, 4); /* +1: skip TEIC=0 */
+ ctx[i].teid := int2oct(i+1, 4); /* +1: skip TEID=0 */
+ ctx[i].pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ }
+
+ T_default.start(60.0);
+
+ T_next.start;
+ alt {
+ [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(INITIAL_REQUEST) { repeat; }
+ [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, INITIAL_REQUEST) { repeat; }
+ [] pingpong();
+ [] T_next.timeout {
+ f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx[next_req_ctx].imsi, g_restart_ctr,
+ ctx[next_req_ctx].teid, ctx[next_req_ctx].teic, ctx[next_req_ctx].nsapi,
+ ctx[next_req_ctx].eua, ctx[next_req_ctx].apn, g_sgsn_ip_c, g_sgsn_ip_u,
+ ctx[next_req_ctx].msisdn, ctx[next_req_ctx].pco_req, ctx[next_req_ctx].ratType,
+ ctx[next_req_ctx].uli, ctx[next_req_ctx].charging_char, ctx[next_req_ctx].imeisv,
+ ctx[next_req_ctx].ms_tz));
+ next_req_ctx := next_req_ctx + 1;
+ if (next_req_ctx < num_ctx) {
+ T_next.start;
+ }
+ repeat;
+ }
+ [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ?)) -> value udc {
+ teic := oct2int(udc.gtpc.teid);
+ if (not match(teic, (1 .. num_ctx))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx Unexpected TEIC");
+ }
+ idx := teic - 1;
+ f_handle_create_req(ctx[idx], udc);
+ rx_resp_ctx := rx_resp_ctx + 1;
+
+ dns1_addr := f_PCO_extract_proto(ctx[idx].pco_neg, '000d'O);
+ saddr := ctx[idx].eua.endUserAddress.endUserAddressIPv4.ipv4_address;
+ f_send_gtpu(ctx[idx], f_gen_icmpv4_echo(saddr, dns1_addr));
+ repeat;
+ }
+ [] GTPU.receive(tr_GTPU_GPDU(g_peer_u, ?)) -> value udu {
+ var octetstring gpdu := udu.gtpu.gtpu_IEs.g_PDU_IEs.data;
+ var IPv4_packet ip4 := f_IPv4_dec(gpdu);
+ if (ip4.header.ver != 4) {
+ repeat;
+ }
+ var PDU_ICMP icmp4 := f_dec_PDU_ICMP(ip4.payload);
+ if (not match(icmp4, (tr_ICMPv4_ERP, tr_ICMPv4_DU))) {
+ repeat;
+ }
+ rx_pong := rx_pong + 1;
+ if (rx_pong < num_ctx) {
+ repeat;
+ }
+ setverdict(pass);
+ }
+ [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
+ [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
+ }
+
+ /* Let's close them now: */
+ next_req_ctx := 0;
+ rx_resp_ctx := 0;
+ T_next.start;
+ alt {
+ [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(TERMINATION_REQUEST) { repeat; }
+ [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, TERMINATION_REQUEST) { repeat; }
+ [] pingpong();
+ [] T_next.timeout {
+ f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, ctx[next_req_ctx].teic_remote, ctx[next_req_ctx].nsapi, '1'B));
+ next_req_ctx := next_req_ctx + 1;
+ if (next_req_ctx < num_ctx) {
+ T_next.start;
+ }
+ repeat;
+ }
+ [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ?)) -> value udc {
+ teic := oct2int(udc.gtpc.teid);
+ if (not match(teic, (1 .. num_ctx))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx Unexpected TEIC");
+ }
+ rx_resp_ctx := rx_resp_ctx + 1;
+ if (rx_resp_ctx < num_ctx) {
+ repeat;
+ }
+ setverdict(pass);
+ }
+ [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
+ [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
+ }
+ T_next.stop;
+
+ T_default.stop;
+ f_shutdown_helper();
+ }
+
+ /* Test callocation of PDP contexts until reaching addr pool exhaustion */
+ type record of OCT4 TEIClist;
+ testcase TC_addr_pool_exhaustion() runs on GT_CT {
+ var Gtp1cUnitdata udc;
+ var Gtp1uUnitdata udu;
+ var PdpContext ctx;
+ timer T_next := 0.005;
+ var integer next_req_ctx := 0;
+ var integer rx_resp_ctx := 0;
+ var integer num_ctx;
+ var boolean cont_req := true;
+ var CreatePDPContextResponse cpr;
+ var TEIClist teic_list := {};
+ var integer teic;
+
+ f_init();
+
+ T_default.start(120.0);
+
+ T_next.start;
+ alt {
+ [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(INITIAL_REQUEST) { repeat; }
+ [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, INITIAL_REQUEST) { repeat; }
+ [] pingpong();
+ [] T_next.timeout {
+ if (cont_req) {
+ if (next_req_ctx - rx_resp_ctx < 100) { /* if we have too many in progress, wait a bit to continue */
+ ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234" & int2str(f_rnd_int(4294967296)), c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.nsapi := '0001'B;
+ ctx.teic := int2oct(next_req_ctx+1, 4); /* +1: skip TEIC=0 */
+ ctx.teid := int2oct(next_req_ctx+1, 4); /* +1: skip TEID=0 */
+ f_send_gtpc(ts_GTPC_CreatePDP(g_peer_c, g_c_seq_nr, ctx.imsi, g_restart_ctr,
+ ctx.teid, ctx.teic, ctx.nsapi,
+ ctx.eua, ctx.apn, g_sgsn_ip_c, g_sgsn_ip_u,
+ ctx.msisdn, ctx.pco_req, ctx.ratType,
+ ctx.uli, ctx.charging_char, ctx.imeisv,
+ ctx.ms_tz));
+ next_req_ctx := next_req_ctx + 1;
+ }
+ T_next.start;
+ }
+ repeat;
+ }
+ [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, createPDPContextResponse, ?)) -> value udc {
+ cpr := udc.gtpc.gtpc_pdu.createPDPContextResponse;
+
+ if (cpr.cause.causevalue == '80'O) {
+ teic_list := teic_list & {cpr.teidControlPlane.teidControlPlane};
+ } else {
+ if (cont_req == true) {
+ num_ctx := rx_resp_ctx;
+ log("Successfully created ", num_ctx, " PDP contexts before exhausting the pool");
+ setverdict(pass);
+ }
+ cont_req := false;
+ }
+ rx_resp_ctx := rx_resp_ctx + 1;
+ if (not cont_req and next_req_ctx == rx_resp_ctx) {
+ break;
+ } else {
+ repeat;
+ }
+ }
+ [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
+ [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
+ }
+
+ /* Let's close them now: */
+ next_req_ctx := 0;
+ rx_resp_ctx := 0;
+ T_next.start;
+ alt {
+ [Gx_PROC.checkstate("Connected")] as_DIA_Gx_CCR(TERMINATION_REQUEST) { repeat; }
+ [Gy_PROC.checkstate("Connected")] as_DIA_Gy_CCR(omit, TERMINATION_REQUEST) { repeat; }
+ [] pingpong();
+ [lengthof(teic_list) > 0] T_next.timeout {
+ f_send_gtpc(ts_GTPC_DeletePDP(g_peer_c, g_c_seq_nr, teic_list[next_req_ctx], '0001'B, '1'B));
+ next_req_ctx := next_req_ctx + 1;
+ if (next_req_ctx < num_ctx) {
+ T_next.start;
+ }
+ repeat;
+ }
+ [] GTPC.receive(tr_GTPC_MsgType(g_peer_c, deletePDPContextResponse, ?)) -> value udc {
+ teic := oct2int(udc.gtpc.teid);
+ if (not match(teic, (1 .. num_ctx))) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Rx Unexpected TEIC");
+ }
+ rx_resp_ctx := rx_resp_ctx + 1;
+ if (rx_resp_ctx < num_ctx) {
+ repeat;
+ }
+ setverdict(pass);
+ }
+ [] GTPC.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPC"); }
+ [] GTPU.receive { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Rx Unexpected GTPU"); }
+ }
+ T_next.stop;
+
+ T_default.stop;
+ f_shutdown_helper();
+ }
+
+ /* Test charging over Gy interface. */
+ testcase TC_gy_charging_cc_time() runs on GT_CT {
+ var default d;
+
+ g_gy_validity_time := 3; /* Grant access for 3 seconds, needs to be re-validated afterwards */
+ f_init();
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
+
+ /* Send some UL traffic: */
+ var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+
+ T_default.start(10.0);
+ d := activate(pingpong());
+
+ g_gy_validity_time := 2;
+ /* First update reports octests/pkt on both UL/DL (see icmp ping-pong above) */
+ as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), 28, 28);
+
+ /* Second update: 0 ul/dl pkt/octet should be reported, since nothing was sent */
+ as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (2..3), 0, 0);
+
+ /* Third update: make sure report contains again octets/pkts for both UL/DL: */
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+ as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (2..3), 56, 56);
+
+ /* Let the CCA reach the GGSN */
+ f_sleep(0.5);
+ deactivate(d);
+ T_default.stop;
+
+ /* Send some data and validate it is reported in the TERMINATION_REQUEST
+ * (triggered by PFCP Session Deletion Response): */
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr));
+ f_wait_icmp4_echo_reply(ctx);
+
+ f_pdp_ctx_del(ctx, '1'B);
+ f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 28, 28);
+
+
+ f_shutdown_helper();
+ }
+
+ /* Test Volume-Quota-Thresold AVP triggers request before Validity-Time */
+ testcase TC_gy_charging_volume_quota_threshold() runs on GT_CT {
+ var default d;
+ timer Tout;
+ g_gy_volume_quota := 10000; /* Allow for sending 10000 bytes */
+ g_gy_volume_threshold := 9000; /* Will make a trigger when we send bigger payload below (10000-9000 = 1000 bytes) */
+ g_gy_validity_time := 8; /* Grant access for 8 seconds, needs to be re-validated afterwards */
+ f_init();
+ var float tout_sec := int2float(g_gy_validity_time) / 2.0;
+ var PdpContext ctx := valueof(t_DefinePDP(f_rnd_imsi('26242'H), "1234", c_ApnInternet, valueof(t_EuaIPv4Dyn)));
+ ctx.pco_req := valueof(ts_PCO_IPv4_DNS_CONT);
+ f_pdp_ctx_act(ctx);
+
+ var OCT4 dns1_addr := f_PCO_extract_proto(ctx.pco_neg, '000d'O);
+
+ T_default.start(40.0);
+ d := activate(pingpong());
+
+ /* Send some UL traffic: */
+ var octetstring payload := f_rnd_octstring(1200);
+ var OCT4 saddr := ctx.eua.endUserAddress.endUserAddressIPv4.ipv4_address;
+ f_send_gtpu(ctx, f_gen_icmpv4_echo(saddr, dns1_addr, payload));
+ f_wait_icmp4_echo_reply(ctx);
+
+ /* ICMP Req generates one report: */
+ Tout.start(tout_sec);
+ alt {
+ [] as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ [] Tout.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "TImeout waiting for Gy UPDATE triggered by Volume-Quota-Threshold");
+ }
+ }
+ f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..6), (1200..1400), 0);
+
+ /* ICMP Resp (echo back) generates one report: */
+ as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, THRESHOLD, (0..1), 0, (1200..1400));
+
+ /* Second update: 0 ul/dl pkt/octet should be reported, since nothing was sent */
+ as_DIA_Gy_CCR(ctx, UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (8..9), 0, 0);
+
+ /* Let the CCA reach the GGSN */
+ f_sleep(0.5);
+ deactivate(d);
+ T_default.stop;
+
+ f_pdp_ctx_del(ctx, '1'B);
+ f_validate_gy_cc_report(g_rx_gy, FINAL, (0..2), 0, 0);
+
+
+ f_shutdown_helper();
}
control {
- execute(TC_pdp4_act_deact());
- execute(TC_pdp4_act_deact_ipcp());
- execute(TC_pdp4_act_deact_ipcp_pap_broken());
- execute(TC_pdp4_act_deact_pcodns());
- execute(TC_pdp4_act_deact_gtpu_access());
- execute(TC_pdp4_clients_interact_with_txseq());
- execute(TC_pdp4_clients_interact_without_txseq());
- execute(TC_pdp4_act_deact_with_single_dns());
- execute(TC_pdp4_act_deact_with_separate_dns());
-
- execute(TC_pdp6_act_deact());
- execute(TC_pdp6_act_deact_pcodns());
- execute(TC_pdp6_act_deact_icmp6());
- execute(TC_pdp6_act_deact_gtpu_access());
- execute(TC_pdp6_clients_interact());
-
- execute(TC_pdp46_act_deact());
- execute(TC_pdp46_act_deact_ipcp());
- execute(TC_pdp46_act_deact_icmp6());
- execute(TC_pdp46_act_deact_pcodns4());
- execute(TC_pdp46_act_deact_pcodns6());
- execute(TC_pdp46_act_deact_gtpu_access());
- execute(TC_pdp46_clients_interact());
- execute(TC_pdp46_act_deact_apn4());
+ if (m_ggsn_conf != GGSN_CONF_V6_ONLY) {
+ execute(TC_pdp4_act_deact());
+ execute(TC_pdp4_act_deact_ipcp());
+ execute(TC_pdp4_act_deact_ipcp_pap_broken());
+ execute(TC_pdp4_act_deact_pcodns());
+ execute(TC_pdp4_act_deact_gtpu_access());
+ execute(TC_pdp4_act_deact_gtpu_access_wrong_saddr());
+ execute(TC_pdp4_act_deact_gtpu_access_ipv6_apn4());
+ execute(TC_pdp4_clients_interact_with_txseq());
+ execute(TC_pdp4_clients_interact_without_txseq());
+ execute(TC_pdp4_act_deact_with_single_dns());
+ execute(TC_pdp4_act_deact_with_separate_dns());
+ execute(TC_pdp4_act_update_teic());
+ execute(TC_pdp4_act_update_teid());
+ }
+
+ if (m_ggsn_conf != GGSN_CONF_V4_ONLY) {
+ execute(TC_pdp6_act_deact());
+ execute(TC_pdp6_act_deact_pcodns());
+ execute(TC_pdp6_act_deact_icmp6());
+ execute(TC_pdp6_act_deact_gtpu_access());
+ execute(TC_pdp6_act_deact_gtpu_access_wrong_ll_saddr());
+ execute(TC_pdp6_act_deact_gtpu_access_wrong_global_saddr());
+ execute(TC_pdp6_act_deact_gtpu_access_ipv4_apn6());
+ execute(TC_pdp6_clients_interact());
+ }
+
+ if (m_ggsn_conf != GGSN_CONF_V4_ONLY and m_ggsn_conf != GGSN_CONF_V6_ONLY) {
+ execute(TC_pdp46_act_deact());
+ execute(TC_pdp46_act_deact_ipcp());
+ execute(TC_pdp46_act_deact_icmp6());
+ execute(TC_pdp46_act_deact_pcodns4());
+ execute(TC_pdp46_act_deact_pcodns6());
+ execute(TC_pdp46_act_deact_gtpu_access());
+ execute(TC_pdp46_act_deact_gtpu_access_wrong_saddr_ipv4());
+ execute(TC_pdp46_act_deact_gtpu_access_wrong_ll_saddr_ipv6());
+ execute(TC_pdp46_act_deact_gtpu_access_wrong_global_saddr_ipv6());
+ execute(TC_pdp46_clients_interact());
+ }
+
+ if (m_ggsn_conf == GGSN_CONF_ALL) {
+ execute(TC_pdp46_act_deact_apn4());
+ }
execute(TC_echo_req_resp());
- execute(TC_pdp_act2_recovery());
- execute(TC_act_deact_retrans_duplicate());
+ execute(TC_echo_req_resp_gtpu());
- execute(TC_pdp_act_restart_ctr_echo());
+ if (m_ggsn_conf == GGSN_CONF_V4_ONLY or m_ggsn_conf == GGSN_CONF_ALL) {
+ execute(TC_pdp_act2_recovery());
+ execute(TC_act_deact_retrans_duplicate());
+ }
+
+ if (m_ggsn_conf != GGSN_CONF_V6_ONLY) {
+ execute(TC_pdp_act_restart_ctr_echo());
+
+ execute(TC_lots_of_concurrent_pdp_ctx());
+ /* Keep at the end, crashes older osmo-ggsn versions (OS#5469): */
+ execute(TC_addr_pool_exhaustion());
+ }
+
+ /* open5gs specific tests: */
+ if (m_ggsn_impl == GGSN_IMPL_OPEN5GS) {
+ execute(TC_gy_charging_cc_time());
+ execute(TC_gy_charging_volume_quota_threshold());
+ }
}
}
diff --git a/ggsn_tests/gen_links.sh b/ggsn_tests/gen_links.sh
index 1b54e9dd..c79e4a8c 100755
--- a/ggsn_tests/gen_links.sh
+++ b/ggsn_tests/gen_links.sh
@@ -10,6 +10,7 @@ BASEDIR=../deps
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
@@ -44,9 +45,25 @@ DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.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.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 PAP_Types.ttcn "
-FILES+="GTP_CodecPort.ttcn GTP_CodecPort_CtrlFunct.ttcn GTP_CodecPort_CtrlFunctDef.cc GTP_Templates.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_Templates.ttcn "
+FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn "
+FILES+="DIAMETER_Templates.ttcn DIAMETER_ts29_212_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn DIAMETER_ts32_299_Templates.ttcn "
+FILES+="ICMP_Templates.ttcn ICMPv6_Templates.ttcn "
FILES+="Osmocom_VTY_Functions.ttcn "
gen_links $DIR $FILES
diff --git a/ggsn_tests/osmo-ggsn.cfg b/ggsn_tests/osmo-ggsn.cfg
new file mode 100644
index 00000000..28284e7a
--- /dev/null
+++ b/ggsn_tests/osmo-ggsn.cfg
@@ -0,0 +1,83 @@
+!
+! OpenGGSN (0.94.1-adac) configuration saved from vty
+!!
+!
+log gsmtap 127.0.0.1
+ logging level set-all debug
+ logging filter all 1
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging print extended-timestamp 1
+ logging level ip info
+ logging level tun info
+ logging level ggsn info
+ logging level sgsn notice
+ logging level icmp6 debug
+ logging level lglobal notice
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp info
+ logging level lstats notice
+ logging level lgsup notice
+ logging level loap notice
+ logging level lss7 notice
+ logging level lsccp notice
+ logging level lsua notice
+ logging level lm3ua notice
+ logging level lmgcp notice
+ logging level lgtp debug
+!
+stats interval 5
+!
+line vty
+ no login
+ bind 0.0.0.0
+!
+ggsn ggsn0
+ gtp state-dir /tmp
+ gtp bind-ip 127.0.0.2
+ timer gtp T3 1
+ timer gtp T1003 2
+ timer gtp X3 2
+ apn internet
+ gtpu-mode tun
+ tun-device tun4
+ type-support v4
+ ip prefix dynamic 176.16.16.0/20
+ ip dns 0 172.18.3.201
+ ip dns 1 8.8.8.8
+ ip ifconfig 176.16.16.0/20
+ no shutdown
+ apn inet6
+ gtpu-mode tun
+ tun-device tun6
+ type-support v6
+ ipv6 prefix dynamic 2001:780:44:2000:0:0:0:0/56
+ ipv6 dns 0 fd02:db8:3::201
+ ipv6 dns 1 2001:4860:4860::8844
+ ipv6 ifconfig 2001:780:44:2000:0:0:0:0/56
+ no shutdown
+ apn inet46
+ gtpu-mode tun
+ tun-device tun46
+ type-support v4v6
+ ip prefix dynamic 176.16.32.0/20
+ ip dns 0 172.18.3.201
+ ip dns 1 8.8.8.8
+ ip ifconfig 176.16.32.0/20
+ ipv6 prefix dynamic 2001:780:44:2100:0:0:0:0/56
+ ipv6 dns 0 fd02:db8:3::201
+ ipv6 dns 1 2001:4860:4860::8844
+ ipv6 ifconfig 2001:780:44:2100:0:0:0:0/56
+ no shutdown
+ default-apn internet
+ no shutdown ggsn
diff --git a/ggsn_tests/regen_makefile.sh b/ggsn_tests/regen_makefile.sh
index 6db1a3dd..ce8e15a6 100755
--- a/ggsn_tests/regen_makefile.sh
+++ b/ggsn_tests/regen_makefile.sh
@@ -1,5 +1,30 @@
#!/bin/sh
-FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc ICMP_EncDec.cc TELNETasp_PT.cc"
+NAME=GGSN_Tests
-../regen-makefile.sh GGSN_Tests.ttcn $FILES
+FILES="
+ *.ttcn
+ BSSGP_EncDec.cc
+ DIAMETER_CodecPort_CtrlFunctDef.cc
+ DIAMETER_EncDec.cc
+ GTPC_EncDec.cc
+ GTPU_EncDec.cc
+ GTPv1C_CodecPort_CtrlFunctDef.cc
+ GTPv1U_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
+ TELNETasp_PT.cc
+ UDP_EncDec.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/hlr/HLR_EUSE.ttcn b/hlr/HLR_EUSE.ttcn
index 17e4776f..170bcd22 100644
--- a/hlr/HLR_EUSE.ttcn
+++ b/hlr/HLR_EUSE.ttcn
@@ -19,6 +19,7 @@
module HLR_EUSE {
import from GSUP_Types all;
+import from GSUP_Templates all;
import from IPA_Emulation all;
import from General_Types all;
diff --git a/hlr/HLR_Tests.cfg b/hlr/HLR_Tests.cfg
index 1ab6e873..7416362d 100644
--- a/hlr/HLR_Tests.cfg
+++ b/hlr/HLR_Tests.cfg
@@ -12,7 +12,6 @@
[MODULE_PARAMETERS]
-HLR_Tests.mp_hlr_supports_dgsm := true
[MAIN_CONTROLLER]
diff --git a/hlr/HLR_Tests.ttcn b/hlr/HLR_Tests.ttcn
index 36e28b8a..46b98c29 100644
--- a/hlr/HLR_Tests.ttcn
+++ b/hlr/HLR_Tests.ttcn
@@ -15,6 +15,7 @@ module HLR_Tests {
import from GSUP_Types all;
+import from GSUP_Templates all;
import from GSUP_Emulation all;
import from IPA_Emulation all;
@@ -70,9 +71,6 @@ modulepar {
/* emulated GSUP server (second HLR) */
charstring mp_hlr_ts_ip := "127.0.0.99";
integer mp_hlr_ts_port := 4222;
-
- /* drop after osmo-hlr release > 1.2.0 */
- boolean mp_hlr_supports_dgsm := true;
};
type record HlrSubscrAud2G {
@@ -154,9 +152,8 @@ function f_init_vty() runs on test_CT {
map(self:VTY, system:VTY);
f_vty_set_prompts(VTY);
f_vty_transceive(VTY, "enable");
- if (mp_hlr_supports_dgsm) {
- f_vty_config(VTY, "mslookup", "no mdns bind");
- }
+ f_vty_config(VTY, "mslookup", "no mdns bind");
+ f_vty_config(VTY, "hlr", "reject-cause not-found imsi-unknown");
}
private altstep as_Tguard() runs on test_CT {
@@ -245,7 +242,7 @@ function f_init(boolean legacy := true, boolean gsup_server := false) runs on te
f_init_gsup_server("HLR_Test");
}
- f_ipa_ctrl_start(mp_hlr_ip, mp_hlr_ctrl_port);
+ f_ipa_ctrl_start_client(mp_hlr_ip, mp_hlr_ctrl_port);
}
/*! Start HLR_ConnHdlr from testCT in a separate thread.
@@ -540,12 +537,15 @@ runs on HLR_ConnHdlr return GSUP_PDU {
return ret;
}
+/* return_isd -> return the Insert Subscriber Data instead of the Update Location Result */
function f_perform_UL(hexstring imsi, template hexstring msisdn,
template (omit) integer exp_err_cause := omit,
GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS,
template (omit) octetstring source_name := omit)
-runs on HLR_ConnHdlr return GSUP_PDU {
- var GSUP_PDU ret;
+runs on HLR_ConnHdlr return GSUP_PDUs {
+ var GSUP_PDU pdu;
+ var GSUP_PDU isd;
+ var GSUP_PDUs ret;
timer T := 3.0;
var boolean exp_fail := false;
var boolean isd_done := false;
@@ -556,31 +556,31 @@ runs on HLR_ConnHdlr return GSUP_PDU {
GSUP.send(valueof(ts_GSUP_UL_REQ(imsi, dom, source_name := source_name)));
T.start;
alt {
- [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause, destination_name := source_name)) -> value ret {
+ [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, exp_err_cause, destination_name := source_name)) -> value pdu {
setverdict(pass);
}
- [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value ret {
+ [exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
setverdict(fail, "Unexpected UL ERROR Cause");
mtc.stop;
}
- [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value ret {
+ [exp_fail] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value pdu {
setverdict(fail, "Unexpected UL.res for unknown IMSI");
mtc.stop;
}
- [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi, destination_name := source_name)) -> value ret {
+ [exp_fail] GSUP.receive(tr_GSUP_ISD_REQ(imsi, destination_name := source_name)) -> value pdu {
setverdict(fail, "Unexpected ISD.req in error case");
mtc.stop;
}
- [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value ret {
+ [not exp_fail] GSUP.receive(tr_GSUP_UL_ERR(imsi, ?, destination_name := source_name)) -> value pdu {
setverdict(fail, "Unexpected UL ERROR");
mtc.stop;
}
- [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn, destination_name := source_name)) -> value ret {
+ [not exp_fail and not isd_done] GSUP.receive(tr_GSUP_ISD_REQ(imsi, msisdn, destination_name := source_name)) -> value isd {
GSUP.send(ts_GSUP_ISD_RES(imsi, source_name := source_name));
isd_done := true;
repeat;
}
- [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value ret {
+ [not exp_fail and isd_done] GSUP.receive(tr_GSUP_UL_RES(imsi, destination_name := source_name)) -> value pdu {
setverdict(pass);
}
[] GSUP.receive { repeat; }
@@ -589,6 +589,12 @@ runs on HLR_ConnHdlr return GSUP_PDU {
mtc.stop;
}
}
+
+ ret := { pdu };
+ if (isd_done) {
+ ret := ret & { isd };
+ }
+
return ret;
}
@@ -983,6 +989,7 @@ testcase TC_gsup_ul_unknown_imsi() runs on test_CT {
vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi), pars);
vc_conn.done;
}
+
testcase TC_gsup_ul_unknown_imsi_via_proxy() runs on test_CT {
var hexstring imsi := f_rnd_imsi('26242'H);
var HLR_ConnHdlrPars pars := valueof(t_Pars_via_proxy(imsi));
@@ -993,15 +1000,35 @@ testcase TC_gsup_ul_unknown_imsi_via_proxy() runs on test_CT {
vc_conn.done;
}
+/* Test if the HLR can be configured to a different error code if the subscriber can't be found.
+ * E.g. on event networks the HLR should return Roaming Not Allowed to unknown subscribers instead
+ * of Subscriber Unknown in HLR.
+ */
+private function f_TC_ul_unknown_imsi_roaming_not_allowed() runs on HLR_ConnHdlr {
+ f_vty_config(VTY, "hlr", "reject-cause not-found roaming-not-allowed");
+ f_perform_UL(g_pars.sub.imsi, ?, 13, source_name := g_pars.source_name);
+ setverdict(pass);
+}
+testcase TC_gsup_ul_unknown_imsi_roaming_not_allowed() runs on test_CT {
+ var hexstring imsi := f_rnd_imsi('26242'H);
+ var HLR_ConnHdlrPars pars := valueof(t_Pars(imsi));
+ var HLR_ConnHdlr vc_conn;
+
+ f_init(false);
+ vc_conn := f_start_handler(refers(f_TC_ul_unknown_imsi_roaming_not_allowed), pars);
+ vc_conn.done;
+}
+
/* test UL for a number of different subscriber cases (algo, 2g/3g, ...) */
private function f_TC_gsup_ul() runs on HLR_ConnHdlr {
- var GSUP_PDU res;
+ var GSUP_PDUs res;
res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn, source_name := g_pars.source_name);
setverdict(pass);
}
+
testcase TC_gsup_ul() runs on test_CT {
var HlrSubscriberList sl;
- var GSUP_PDU res;
+ var GSUP_PDUs res;
f_init(false);
sl := f_gen_subs();
@@ -1020,6 +1047,72 @@ testcase TC_gsup_ul_via_proxy() runs on test_CT {
setverdict(pass);
}
+private function f_TC_gsup_ul_subscriber_data() runs on HLR_ConnHdlr {
+ var GSUP_PDUs pdus;
+ var GSUP_PDU isd;
+ log("GSUP ul subscriber_data", isd);
+ pdus := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn, source_name := g_pars.source_name);
+ isd := pdus[1];
+
+ template GSUP_IEs tr_pdp_info_internet := {
+ tr_GSUP_IE_PDP_CONTEXT_ID('01'O),
+ tr_GSUP_IE_APN(str2apn("internet"))
+ }
+ template GSUP_IEs tr_pdp_info_wildcard := {
+ tr_GSUP_IE_PDP_CONTEXT_ID('02'O),
+ tr_GSUP_IE_APN(str2apn("*"))
+ }
+
+ /* Search for PDP info 'internet', '*' */
+ var boolean found := false;
+ var GSUP_IeValue ievalue;
+ var GSUP_IEs pdp_info;
+ found := f_gsup_find_nested_ie_multiple(isd.ies, OSMO_GSUP_PDP_INFO_IE, 0, ievalue);
+ if (not found) {
+ setverdict(fail, "Multiple APNs: Coulnd't find first PDP Info IE in: ", isd);
+ return;
+ }
+ pdp_info := ievalue.pdp_info;
+ if (not match(pdp_info, tr_pdp_info_internet)) {
+ setverdict(fail, "Multiple APNs: first PDP Info doesn't match: ", pdp_info, "on Template: ", tr_pdp_info_internet);
+ return;
+ }
+
+ /* wildcard '*' */
+ found := f_gsup_find_nested_ie_multiple(isd.ies, OSMO_GSUP_PDP_INFO_IE, 1, ievalue);
+ if (not found) {
+ setverdict(fail, "Multiple APNs: Coulnd't find second PDP Info IE in: ", isd);
+ return;
+ }
+ pdp_info := ievalue.pdp_info;
+ if (not match(pdp_info, tr_pdp_info_wildcard)) {
+ setverdict(fail, "Multiple APNs: second PDP Info doesn't match: ", pdp_info, "on Template: ", tr_pdp_info_wildcard);
+ return;
+ }
+
+ setverdict(pass);
+}
+
+testcase TC_gsup_ul_subscriber_data() runs on test_CT {
+ /* Do a GSUP Update Location Request to get a Insert Subscriber Data Request (ISD).
+ * Check for multiple APN in the ISD:
+ * SGSN -> HLR: Update Location Request
+ * SGSN <- HLR: Insert Subscriber Data Request (Check the TLV)
+ * SGSN -> HLR: Insert Subscriber Data Result
+ * SGSN <- HLR: Update Location Result
+ */
+ var HlrSubscriberList sl;
+
+ f_init(false);
+ f_vty_config2(VTY, {"hlr", "ps"} , "no pdp-profiles default");
+ f_vty_config2(VTY, {"hlr", "ps", "pdp-profiles default", "profile 1"}, "apn internet");
+ f_vty_config2(VTY, {"hlr", "ps", "pdp-profiles default", "profile 2"}, "apn *");
+ sl := f_gen_subs();
+ f_start_handler_per_sub(refers(f_TC_gsup_ul_subscriber_data), sl);
+
+ setverdict(pass);
+}
+
/* Test only the VTY commands */
testcase TC_vty() runs on test_CT {
var HlrSubscriber sub;
@@ -1051,7 +1144,7 @@ testcase TC_vty() runs on test_CT {
/* VTY changes to MSISDN should result in ISD to current VLR */
private function f_TC_vty_msisdn_isd() runs on HLR_ConnHdlr {
var hexstring new_msisdn;
- var GSUP_PDU res;
+ var GSUP_PDUs res;
timer T := 5.0;
/* Create Subscriber */
@@ -1096,9 +1189,10 @@ testcase TC_vty_msisdn_isd() runs on test_CT {
/* Test PURGE MS for CS services */
private function f_TC_gsup_purge_cs() runs on HLR_ConnHdlr {
- var GSUP_PDU res;
+ var GSUP_PDUs res;
+ var GSUP_PDU pdu;
res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
- res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
+ pdu := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_CS);
}
testcase TC_gsup_purge_cs() runs on test_CT {
var HlrSubscriberList sl;
@@ -1113,9 +1207,10 @@ testcase TC_gsup_purge_cs() runs on test_CT {
/* Test PURGE MS for PS services */
private function f_TC_gsup_purge_ps() runs on HLR_ConnHdlr {
- var GSUP_PDU res;
+ var GSUP_PDUs res;
+ var GSUP_PDU pdu;
res := f_perform_UL(g_pars.sub.imsi, g_pars.sub.msisdn);
- res := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
+ pdu := f_perform_PURGE(g_pars.sub.imsi, OSMO_GSUP_CN_DOMAIN_PS);
}
testcase TC_gsup_purge_ps() runs on test_CT {
var HlrSubscriberList sl;
@@ -1545,7 +1640,7 @@ testcase TC_gsup_check_imei_unknown_imsi() runs on test_CT {
/* Test create-subscriber-on-demand during Check IMEI (OsmoMSC would be set to "check-imei-rqd early") */
private function f_TC_subscr_create_on_demand_check_imei_early() runs on HLR_ConnHdlr {
- var GSUP_PDU res; /* save various return values to prevent ttcn3 compiler warnings */
+ var GSUP_PDUs res; /* save various return values to prevent ttcn3 compiler warnings */
var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
/* Random MSISDN and CS+PS NAM (LU must pass) */
@@ -1618,7 +1713,7 @@ testcase TC_subscr_create_on_demand_check_imei_early() runs on test_CT {
/* Test create-subscriber-on-demand during LU (Location Update) */
private function f_TC_subscr_create_on_demand_ul() runs on HLR_ConnHdlr {
- var GSUP_PDU res;
+ var GSUP_PDUs res;
var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
/* Random MSISDN and CS+PS NAM (LU must pass) */
@@ -1685,13 +1780,14 @@ testcase TC_subscr_create_on_demand_ul() runs on test_CT {
/* Test create-subscriber-on-demand during SAI (SendAuthInfo) */
private function f_TC_subscr_create_on_demand_sai() runs on HLR_ConnHdlr {
- var GSUP_PDU res;
+ var GSUP_PDUs res;
+ var GSUP_PDU pdu;
var charstring imsi_pattern := "*IMSI: " & hex2str(g_pars.sub.imsi) & "*";
/* HLR creates the subscriber on demand. Then the IMSI is known, but there is no auth data, so the HLR returns
* the "slightly inaccurate cause 'IMSI Unknown' via GSUP". The MS is able to do a LU afterwards. */
f_vty_config(VTY, "hlr", "subscriber-create-on-demand 3 cs+ps");
- res := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
+ pdu := f_perform_SAI(g_pars.sub.imsi, 2 /* IMSI Unknown */ );
/* Verify that it was created before the LU */
f_vty_subscr_show(VTY, g_pars.sub, pattern imsi_pattern);
@@ -1922,6 +2018,65 @@ testcase TC_MSLookup_mDNS_service_other_proxy() runs on test_CT {
}
}
+
+/* strchr similar to C's/posix strchr but returns the position of the first matching.
+ * if the char c isn't found it returns -1.
+ */
+function strchr(in charstring s, in charstring c) return integer {
+ for (var integer i := 0; i < lengthof(s); i := i+1) {
+ if (s[i] == c) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* str2apn returns octetstring
+ * internet -> '08'O & char2oct("internet")
+ * internet.foo -> '08'O & char2oct("internet") & '03'O & char2oct("foo")
+ * internet.-> '08'O & char2oct("internet")
+ */
+function str2apn(in charstring apn) return octetstring {
+ var octetstring result := ''O;
+ var charstring remain := apn;
+ var integer pos := strchr(remain, ".");
+
+ while (pos != -1) {
+ /* ends on a dot. e.g. "internet.", we must ignore the ending dot and this is then the last element */
+ if (pos == 0) {
+ /* it's not allowed to start with a dot. */
+ return ''O;
+ }
+
+ if (pos + 1 == lengthof(remain)) {
+ /* remove the dot */
+ remain := substr(remain, 0, pos)
+ break;
+ }
+
+ result := result & int2oct(pos, 1) & char2oct(substr(remain, 0, pos));
+ remain := substr(remain, pos + 1, lengthof(remain) - pos - 1);
+ pos := strchr(remain, ".");
+ }
+ /* last element */
+ var integer len := lengthof(remain);
+ result := result & int2oct(len, 1) & char2oct(remain);
+ return result;
+}
+
+private function test_assert(boolean term) {
+ if (term == false) {
+ setverdict(fail, "Values mismatch");
+ }
+}
+
+private function test_str2apn() {
+ test_assert(str2apn("internet") == '08'O & char2oct("internet"));
+ test_assert(str2apn("internet.") == '08'O & char2oct("internet"));
+ test_assert(str2apn("internet.foo") == '08'O & char2oct("internet") & '03'O & char2oct("foo"));
+ test_assert(str2apn(".internet.foo") == ''O);
+}
+
/* TODO:
* UL with ISD error
* UL with ISD timeout
@@ -1943,9 +2098,11 @@ control {
execute( TC_gsup_sai_eps() );
execute( TC_gsup_ul_unknown_imsi() );
execute( TC_gsup_ul_unknown_imsi_via_proxy() );
+ execute( TC_gsup_ul_unknown_imsi_roaming_not_allowed() );
execute( TC_gsup_sai_err_unknown_imsi() );
execute( TC_gsup_ul() );
execute( TC_gsup_ul_via_proxy() );
+ execute( TC_gsup_ul_subscriber_data() );
execute( TC_vty() );
execute( TC_vty_msisdn_isd() );
execute( TC_gsup_purge_cs() );
@@ -1973,13 +2130,11 @@ control {
execute( TC_subscr_create_on_demand_ul() );
execute( TC_subscr_create_on_demand_sai() );
- if (mp_hlr_supports_dgsm) {
- execute( TC_MSLookup_mDNS_service_other_home() );
- execute( TC_MSLookup_GSUP_proxy() );
- execute( TC_MSLookup_mDNS_service_GSUP_HLR_home() );
- execute( TC_MSLookup_mDNS_service_GSUP_HLR_proxy() );
- execute( TC_MSLookup_mDNS_service_other_proxy() );
- }
+ execute( TC_MSLookup_mDNS_service_other_home() );
+ execute( TC_MSLookup_GSUP_proxy() );
+ execute( TC_MSLookup_mDNS_service_GSUP_HLR_home() );
+ execute( TC_MSLookup_mDNS_service_GSUP_HLR_proxy() );
+ execute( TC_MSLookup_mDNS_service_other_proxy() );
};
};
diff --git a/hlr/expected-results.xml b/hlr/expected-results.xml
index 7f1c2779..0ed97987 100644
--- a/hlr/expected-results.xml
+++ b/hlr/expected-results.xml
@@ -1,14 +1,16 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='31' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='38' failures='3' errors='2' skipped='0' inconc='0' time='MASKED'>
<testcase classname='HLR_Tests' name='TC_gsup_sai_err_invalid_imsi' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_sai' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_sai_num_auth_vectors' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_sai_eps' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_ul_unknown_imsi' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_ul_unknown_imsi_via_proxy' time='MASKED'/>
+ <testcase classname='HLR_Tests' name='TC_gsup_ul_unknown_imsi_roaming_not_allowed' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_sai_err_unknown_imsi' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_ul' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_ul_via_proxy' time='MASKED'/>
+ <testcase classname='HLR_Tests' name='TC_gsup_ul_subscriber_data' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_vty' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_vty_msisdn_isd' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_gsup_purge_cs' time='MASKED'/>
@@ -31,4 +33,34 @@
<testcase classname='HLR_Tests' name='TC_subscr_create_on_demand_check_imei_early' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_subscr_create_on_demand_ul' time='MASKED'/>
<testcase classname='HLR_Tests' name='TC_subscr_create_on_demand_sai' time='MASKED'/>
+ <testcase classname='HLR_Tests' name='TC_MSLookup_mDNS_service_other_home' time='MASKED'>
+ <failure type='fail-verdict'>OsmoHLR did not answer to mDNS query
+ HLR_Tests.ttcn:MASKED HLR_Tests control part
+ HLR_Tests.ttcn:MASKED TC_MSLookup_mDNS_service_other_home testcase
+ </failure>
+ </testcase>
+ <testcase classname='HLR_Tests' name='TC_MSLookup_GSUP_proxy' time='MASKED'>
+ <failure type='fail-verdict'>Timeout
+ HLR_Tests.ttcn:MASKED HLR_Tests control part
+ HLR_Tests.ttcn:MASKED TC_MSLookup_GSUP_proxy testcase
+ </failure>
+ </testcase>
+ <testcase classname='HLR_Tests' name='TC_MSLookup_mDNS_service_GSUP_HLR_home' time='MASKED'>
+ <failure type='fail-verdict'>OsmoHLR did not answer to mDNS query
+ HLR_Tests.ttcn:MASKED HLR_Tests control part
+ HLR_Tests.ttcn:MASKED TC_MSLookup_mDNS_service_GSUP_HLR_home testcase
+ </failure>
+ </testcase>
+ <testcase classname='HLR_Tests' name='TC_MSLookup_mDNS_service_GSUP_HLR_proxy' time='MASKED'>
+ <failure type='fail-verdict'>Timeout
+ HLR_Tests.ttcn:MASKED HLR_Tests control part
+ HLR_Tests.ttcn:MASKED TC_MSLookup_mDNS_service_GSUP_HLR_proxy testcase
+ </failure>
+ </testcase>
+ <testcase classname='HLR_Tests' name='TC_MSLookup_mDNS_service_other_proxy' time='MASKED'>
+ <failure type='fail-verdict'>Timeout
+ HLR_Tests.ttcn:MASKED HLR_Tests control part
+ HLR_Tests.ttcn:MASKED TC_MSLookup_mDNS_service_other_proxy testcase
+ </failure>
+ </testcase>
</testsuite>
diff --git a/hlr/gen_links.sh b/hlr/gen_links.sh
index c77920dd..588fe084 100755
--- a/hlr/gen_links.sh
+++ b/hlr/gen_links.sh
@@ -44,7 +44,8 @@ FILES="UDPasp_PT.cc UDPasp_PT.hh UDPasp_PortType.ttcn UDPasp_Types.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp GSUP_Types.ttcn GSUP_Emulation.ttcn "
+FILES="Native_Functions.ttcn Native_FunctionDefs.cc Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn 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+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
FILES+="Osmocom_VTY_Functions.ttcn "
FILES+="SS_Templates.ttcn USSD_Helpers.ttcn "
diff --git a/hlr/regen_makefile.sh b/hlr/regen_makefile.sh
index 14b05daa..c5faddef 100755
--- a/hlr/regen_makefile.sh
+++ b/hlr/regen_makefile.sh
@@ -1,9 +1,28 @@
#!/bin/sh
-MAIN="HLR_Tests.ttcn"
+NAME=HLR_Tests
-FILES="*.ttcn *.ttcnpp DNS_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc TELNETasp_PT.cc TCCEncoding.cc UDPasp_PT.cc SS_EncDec.cc MAP_EncDec.cc *.asn"
+FILES="
+ *.asn
+ *.ttcn
+ *.ttcnpp
+ DNS_EncDec.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ MAP_EncDec.cc
+ SS_EncDec.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ UDPasp_PT.cc
+"
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_GSUP -DIPA_EMULATION_CTRL"
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_GSUP
+ -DIPA_EMULATION_CTRL
+"
-../regen-makefile.sh $MAIN $FILES
+../regen-makefile.sh -e $NAME $FILES
diff --git a/hnbgw/HNBGW_Tests.cfg b/hnbgw/HNBGW_Tests.cfg
new file mode 100644
index 00000000..8cf00481
--- /dev/null
+++ b/hnbgw/HNBGW_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./HNBGW_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+HNBGW_Tests.control
diff --git a/hnbgw/HNBGW_Tests.default b/hnbgw/HNBGW_Tests.default
new file mode 100644
index 00000000..51bcdac3
--- /dev/null
+++ b/hnbgw/HNBGW_Tests.default
@@ -0,0 +1,28 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.HNBGWVTY.CTRL_MODE := "client"
+*.HNBGWVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.HNBGWVTY.CTRL_PORTNUM := "4261"
+*.HNBGWVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.HNBGWVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.HNBGWVTY.CTRL_READMODE := "buffered"
+*.HNBGWVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.HNBGWVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.HNBGWVTY.PROMPT1 := "OsmoHNBGW> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4261"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoHNBGW> "
+*.LLSK.socket_type := "SEQPACKET"
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoHNBGW";
+
+[EXECUTE]
diff --git a/hnbgw/HNBGW_Tests.ttcn b/hnbgw/HNBGW_Tests.ttcn
new file mode 100644
index 00000000..3369e373
--- /dev/null
+++ b/hnbgw/HNBGW_Tests.ttcn
@@ -0,0 +1,2933 @@
+module HNBGW_Tests {
+
+/* Integration Tests for OsmoHNBGW
+ * (C) 2021 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
+ *
+ * This test suite tests OsmoHNBGW while emulating the hNodeB as well as MSC, SGSN, MGW
+ * See README for more details.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from GSM_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from HNBAP_Templates all;
+import from HNBAP_IEs all;
+import from HNBAP_PDU_Descriptions all;
+
+import from RUA_IEs all;
+import from RUA_Templates all;
+import from RUA_Emulation all;
+
+import from Iuh_Emulation all;
+
+import from RANAP_Types all;
+import from RANAP_PDU_Descriptions all;
+import from RANAP_PDU_Contents all;
+import from RANAP_IEs all;
+import from RANAP_Templates all;
+import from RANAP_CodecPort all;
+
+import from RAN_Adapter all;
+import from RAN_Emulation all;
+
+import from MGCP_Emulation all;
+import from MGCP_Types all;
+import from MGCP_Templates all;
+import from MGCP_CodecPort all;
+import from SDP_Types all;
+import from SDP_Templates all;
+
+import from PFCP_Types all;
+import from PFCP_Emulation all;
+import from PFCP_Templates all;
+import from PFCP_CodecPort all;
+
+import from TCCConversion_Functions all;
+import from MobileL3_Types all;
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_GMM_SM_Types all;
+import from L3_Templates all;
+import from L3_Common all;
+
+import from SCCPasp_Types all;
+
+const integer NUM_MSC := 4;
+const integer NUM_SGSN := 4;
+
+const integer FIRST_MSC_IDX := 0;
+const integer FIRST_SGSN_IDX := NUM_MSC;
+
+modulepar {
+ /* IP address at which the HNodeB can be reached */
+ charstring mp_hnodeb_ip := "127.0.0.1";
+ integer mp_hnodeb_port := -1;
+
+ /* IP address at which the test binds */
+ charstring mp_hnbgw_ip := "127.0.0.1";
+ integer mp_hnbgw_iuh_port := 29169;
+ integer mp_hnbgw_ctrl_port := 4262;
+
+ /* Our emulated StatsD server: */
+ charstring mp_local_statsd_ip := "127.0.0.1";
+ integer mp_local_statsd_port := 8125;
+
+ charstring mp_mgw_ip := "127.0.0.1";
+ integer mp_mgw_port := 2427;
+
+ RAN_Configurations mp_cn_cfg := {
+ /* MSCs (NUM_MSC entries) */
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23905, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 188, /* 0.23.4 first MSC emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 0.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 1
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23907, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 2, /* 0.0.2 second MSC emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 0.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 3
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23909, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 3, /* 0.0.3 third MSC emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 0.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 5
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23911, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 4, /* 0.0.4 fourth MSC emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 0.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 7
+ },
+
+ /* SGSNs (NUM_SGSN entries) */
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { /* local */ 23906, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
+ own_pc := 185, /* 0.23.1 first SGSN emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 2
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { /* local */ 23908, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
+ own_pc := 10, /* 0.1.2 second SGSN emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 4
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { /* local */ 23910, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
+ own_pc := 11, /* 0.1.3 third SGSN emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 6
+ },
+ {
+ transport := RANAP_TRANSPORT_IuCS,
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { /* local */ 23912, "127.0.0.1", /* remote */ 2905, "127.0.0.1" },
+ own_pc := 12, /* 0.1.4 fourth SGSN emulation */
+ own_ssn := 142,
+ peer_pc := 189, /* 2237, 1.23.5 osmo-hnbgw */
+ peer_ssn := 142,
+ sio := '83'O,
+ rctx := 8
+ }
+ };
+
+ boolean mp_enable_pfcp_tests := false;
+
+ /* IP address at which we listen for PFCP to emulate a UPF in ttcn3 */
+ charstring mp_pfcp_ip_local := "127.0.0.1";
+
+ /* IP address from which the SUT (osmo-hnbgw) sends PFCP requests, and to which the ttcn3 UPF emulation sends
+ * PFCP responses. */
+ charstring mp_pfcp_ip_remote := "127.0.0.2";
+
+ boolean mp_validate_talloc_asn1 := true;
+
+ /* The X31 timer configured at osmo-hnbgw (seconds). This provided an idea on
+ * minimum time the test must wait to consider this timer triggered */
+ integer mp_hnbgw_timer_x31 := 5;
+}
+
+function MSC_UnitdataCallback(RANAP_PDU ranap) runs on RAN_Emulation_CT return template RANAP_PDU {
+ // TODO: Actually implement unitdata handling
+ return omit;
+}
+
+const RanOps MSC_RanOps := {
+ ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
+ ranap_unitdata_cb := refers(MSC_UnitdataCallback),
+ ps_domain := false,
+ decode_dtap := false,
+ role_ms := false,
+ protocol := RAN_PROTOCOL_RANAP,
+ transport := RANAP_TRANSPORT_IuCS,
+ use_osmux := false,
+ bssap_reset_retries := 1,
+ sccp_addr_local := omit,
+ sccp_addr_peer := omit
+}
+
+type record MgwResponse {
+ integer resp,
+ HostName mgw_rtp_ip,
+ /* if set, used after first received MDCX: */
+ HostName mgw_rtp_ip_mdcx optional,
+ PortNumber mgw_rtp_port,
+ MgcpConnectionId mgcp_connection_id
+}
+type record MgcpParameters {
+ integer got_crcx_count,
+ integer got_dlcx_count,
+ MgcpCallId mgcp_call_id optional,
+ MgcpEndpoint mgcp_ep,
+ MgwResponse mgw_conn_ran,
+ MgwResponse mgw_conn_cn,
+ uint7_t rtp_payload_type,
+ charstring rtp_sdp_format,
+ HostName hnb_rtp_ip,
+ PortNumber hnb_rtp_port,
+ HostName cn_rtp_ip,
+ PortNumber cn_rtp_port,
+ boolean use_osmux,
+ integer got_osmux_count
+}
+
+template (value) MgcpParameters t_MgcpParams := {
+ got_crcx_count := 0,
+ got_dlcx_count := 0,
+ mgcp_call_id := omit,
+ mgcp_ep := "rtpbridge/1@mgw",
+ mgw_conn_ran := {
+ resp := 1,
+ mgw_rtp_ip := "127.1.2.1",
+ mgw_rtp_ip_mdcx := omit,
+ mgw_rtp_port := 10000,
+ mgcp_connection_id := '11111'H
+ },
+ mgw_conn_cn := {
+ resp := 1,
+ mgw_rtp_ip := "127.1.2.2",
+ mgw_rtp_ip_mdcx := omit,
+ mgw_rtp_port := 20000,
+ mgcp_connection_id := '22222'H
+ },
+ rtp_payload_type := 112,
+ rtp_sdp_format := "VND.3GPP.IUFP",
+ hnb_rtp_ip := "127.1.1.1",
+ hnb_rtp_port := 10001,
+ cn_rtp_ip := "127.1.3.1",
+ cn_rtp_port := 20001,
+ use_osmux := false,
+ got_osmux_count := 0
+}
+
+type record TestHdlrParams {
+ integer hnb_idx,
+ /* cn_idx indicates which CN link from g_cn[] to connect to the test component.
+ * See also f_cn_idx(). */
+ integer cn_idx,
+ hexstring imsi,
+ boolean ps_domain,
+ MgcpParameters mgcp_pars optional,
+ HnbConfig hnb optional,
+ boolean expect_separate_sccp_cr,
+ integer tx_sccp_cr_data_len,
+ charstring pfcp_local_addr,
+ octetstring nas_pdu optional,
+ /* local and remote SCCP addresses, used in TC_mscpool_paging_* */
+ SCCP_PAR_Address sccp_addr_msc optional,
+ SCCP_PAR_Address sccp_addr_hnbgw optional,
+ /* RAB release cause */
+ RANAP_IEs.Cause rab_rel_cause
+}
+
+/* We extend:
+ * RUA_ConnHdlr (for the Iuh side, emulating the HNB)
+ * RAN_ConnHdlr (for the Iu side, emulating the MSC)
+ * MGCP_ConnHdlr (for the MGCP side, emulating the MGW)
+ * StatsD_ConnHdlr (for the statsd interface, verifying counters)
+ */
+type component ConnHdlr extends RAN_ConnHdlr, MGCP_ConnHdlr, RUA_ConnHdlr, PFCP_ConnHdlr, StatsD_ConnHdlr {
+ var integer g_sccp_conn_id;
+ var TestHdlrParams g_pars;
+ timer g_Tguard;
+
+ port TELNETasp_PT HNBGWVTY;
+}
+
+
+const MGCPOps MSC_MGCPOps := {
+ create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
+}
+
+function f_create_ranap_exp(octetstring l3_enc) runs on ConnHdlr {
+ BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
+ [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
+ }
+}
+
+
+const integer NUM_HNB := 2;
+
+type record HnbConfig {
+ LocationAreaIdentification lai,
+ integer sac
+}
+
+type component test_CT extends CTRL_Adapter_CT, StatsD_Checker_CT {
+ var boolean g_initialized := false;
+
+ /********************* Iu side */
+ var RAN_Adapter g_cn[NUM_MSC + NUM_SGSN];
+
+ /********************* Iuh side */
+ var HnbConfig g_hnb_cfg[NUM_HNB];
+ var Iuh_Emulation_CT vc_Iuh[NUM_HNB];
+ var RUA_Emulation_CT vc_RUA[NUM_HNB];
+ port HNBAP_PT HNBAP[NUM_HNB];
+ /* Number of HNBs to be used/started by the test */
+ var integer g_num_hnbs := NUM_HNB;
+
+ var MGCP_Emulation_CT vc_MGCP;
+ port TELNETasp_PT HNBGWVTY;
+ var StatsD_Checker_CT vc_STATSD;
+ /* global test case guard timer (actual timeout value is set in f_init()) */
+ timer T_guard := 30.0;
+
+ /* The cnlink type 'msc' or 'sgsn', to be used in CTRL commands to obtain counters */
+ var charstring g_ctr_cn_node_name;
+ /* Counter state */
+ var CounterNameValsList g_ctr_cn;
+}
+
+/* global altstep for global guard timer; */
+altstep as_Tguard() runs on test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+ if (HNBGWVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:HNBGWVTY, system:HNBGWVTY);
+ f_vty_set_prompts(HNBGWVTY);
+ f_vty_transceive(HNBGWVTY, "enable");
+}
+
+function f_init_mgcp(charstring id) runs on test_CT {
+ id := id & "-MGCP";
+ var MGCPOps ops := {
+ create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
+ }
+ var MGCP_conn_parameters pars := {
+ callagent_ip := mp_hnbgw_ip,
+ callagent_udp_port := -1,
+ mgw_ip := mp_mgw_ip,
+ mgw_udp_port := mp_mgw_port,
+ multi_conn_mode := false
+ }
+
+ vc_MGCP := MGCP_Emulation_CT.create(id);
+ map(vc_MGCP:MGCP, system:MGCP_CODEC_PT);
+ vc_MGCP.start(MGCP_Emulation.main(ops, pars, id));
+}
+
+function f_init_pfcp(charstring id) runs on ConnHdlr {
+ id := id & "-PFCP";
+
+ var PFCP_Emulation_Cfg pfcp_cfg := {
+ pfcp_bind_ip := mp_pfcp_ip_local,
+ pfcp_bind_port := PFCP_PORT,
+ pfcp_remote_ip := mp_pfcp_ip_remote,
+ pfcp_remote_port := PFCP_PORT,
+ role := UPF
+ };
+
+ vc_PFCP := PFCP_Emulation_CT.create(id) alive;
+ connect(self:PFCP, vc_PFCP:CLIENT);
+ connect(self:PFCP_PROC, vc_PFCP:CLIENT_PROC);
+ vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
+}
+
+function f_init_hnodeb(charstring id, integer hnb_idx, RuaOps rua_ops) runs on test_CT {
+ id := id & "-Iuh" & int2str(hnb_idx);
+
+ /* Iuh lower layer (RUA/HNBAP demux) */
+ var Iuh_conn_parameters iuh_pars;
+ iuh_pars.remote_ip := mp_hnbgw_ip;
+ iuh_pars.remote_sctp_port := mp_hnbgw_iuh_port;
+ iuh_pars.local_ip := mp_hnodeb_ip;
+ iuh_pars.local_sctp_port := mp_hnodeb_port + hnb_idx;
+ vc_Iuh[hnb_idx] := Iuh_Emulation_CT.create(id);
+ connect(self:HNBAP[hnb_idx], vc_Iuh[hnb_idx]:HNBAP);
+
+ vc_RUA[hnb_idx] := RUA_Emulation_CT.create(id & "-RUA");
+ connect(vc_RUA[hnb_idx]:RUA, vc_Iuh[hnb_idx]:RUA);
+
+ /* Start Iuh side components */
+ vc_Iuh[hnb_idx].start(Iuh_Emulation.main(iuh_pars, id));
+ vc_RUA[hnb_idx].start(RUA_Emulation.main(rua_ops, id & "-RUA"));
+}
+
+private type record of boolean BooleanList;
+
+private function f_vty_cnlink_allow_attach(TELNETasp_PT pt, boolean ps_domain, BooleanList allow_attach_list)
+{
+ var charstring config := f_vty_transceive_ret(pt, "show running-config");
+
+ var charstring msc_sgsn;
+ if (ps_domain) {
+ msc_sgsn := "sgsn";
+ } else {
+ msc_sgsn := "msc";
+ }
+
+ f_vty_enter_config(pt);
+ for (var integer cn_nr := 0; cn_nr < sizeof(allow_attach_list); cn_nr := cn_nr+1) {
+ if (f_strstr(config, "\n" & msc_sgsn & " " & int2str(cn_nr) & "\n") < 0) {
+ /* There is no 'msc N' for this cn_nr in the running config, so don't create an empty cn by
+ * stepping into that config node. */
+ log(msc_sgsn, cn_nr, " is not configured, skipping");
+ continue;
+ }
+ f_vty_transceive(pt, msc_sgsn & " " & int2str(cn_nr));
+
+ if (allow_attach_list[cn_nr]) {
+ /* strict := false: ignore if osmo-hnbgw does not support this config option (latest build) */
+ f_vty_transceive(pt, "allow-attach", strict := false);
+ } else {
+ f_vty_transceive(pt, "no allow-attach", strict := false);
+ }
+ f_vty_transceive(pt, "exit");
+ }
+ f_vty_transceive(pt, "exit");
+}
+
+/* Start RAN adapter for CN link N.
+ * e.g. link for 'msc 0' = (ps_domain := false, cn_nr := 0)
+ * link for 'sgsn 3' = (ps_domain := true, cn_nr := 3)
+ */
+private function f_cn_nr_init(boolean ps_domain, integer cn_nr) runs on test_CT {
+ var RanOps ranops := MSC_RanOps;
+ ranops.ps_domain := ps_domain;
+ var integer cn_idx := f_cn_idx(ps_domain, cn_nr);
+ var charstring msc_sgsn := "msc";
+ if (ps_domain) {
+ msc_sgsn := "sgsn";
+ }
+ f_ran_adapter_init(g_cn[cn_idx], mp_cn_cfg[cn_idx], "HNBGW_Test." & msc_sgsn & int2str(cn_nr), ranops);
+ f_ran_adapter_start(g_cn[cn_idx]);
+}
+
+private function f_cn_idx_disconnect(integer cn_idx) runs on test_CT {
+ f_ran_adapter_cleanup(g_cn[cn_idx]);
+}
+
+/* global initialization function */
+function f_init(charstring id := "HNBGW", float guard_timeout := 30.0, integer nr_msc := 1, integer nr_sgsn := 1,
+ boolean start_hnb := true) runs on test_CT {
+
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
+ f_init_statsd("VirtHNBGW", vc_STATSD, mp_local_statsd_ip, mp_local_statsd_port);
+
+ /* RUA/RANAP emulation on top of lower-layer Iuh */
+ var RuaOps rua_ops := {
+ create_cb := refers(IuhRanapCreateCallback),
+ unitdata_cb := refers(IuhRanapUnitdataCallback)
+ };
+ for (var integer i := 0; i < g_num_hnbs; i := i+1) {
+ g_hnb_cfg[i] := {
+ lai := {
+ mcc_mnc := '00F110'H,
+ lac := 2342 + i
+ },
+ sac := 55
+ };
+ f_init_hnodeb(testcasename(), i, rua_ops);
+ }
+
+ f_init_vty("VirtHNBGW");
+ f_ipa_ctrl_start_client(mp_hnbgw_ip, mp_hnbgw_ctrl_port);
+
+ /* MSC emulation */
+
+ /* Make sure each MSC's internal state is "DISCONNECTED" at first */
+ for (var integer i := 0; i < NUM_MSC; i := i + 1) {
+ f_vty_transceive(HNBGWVTY, "msc " & int2str(i) & " ranap reset", strict := false);
+ }
+
+ var BooleanList allow_attach := { false, false, false, false };
+ for (var integer i := 0; i < nr_msc; i := i + 1) {
+ var integer cn_idx := FIRST_MSC_IDX + i;
+ allow_attach[i] := true;
+ f_cn_nr_init(ps_domain := false, cn_nr := i);
+ }
+ /* start the test with exactly all enabled MSCs allowed to attach */
+ f_vty_cnlink_allow_attach(HNBGWVTY, false, allow_attach);
+
+ /* SGSN emulation */
+
+ /* Make sure each SGSN's internal state is "DISCONNECTED" at first */
+ for (var integer i := 0; i < NUM_SGSN; i := i + 1) {
+ f_vty_transceive(HNBGWVTY, "sgsn " & int2str(i) & " ranap reset", strict := false);
+ }
+
+ allow_attach := { false, false, false, false };
+ for (var integer i := 0; i < nr_sgsn; i := i + 1) {
+ var integer cn_idx := FIRST_SGSN_IDX + i;
+ allow_attach[i] := true;
+ f_cn_nr_init(ps_domain := true, cn_nr := i);
+ }
+ f_vty_cnlink_allow_attach(HNBGWVTY, true, allow_attach);
+
+ f_init_mgcp(id);
+
+ if (start_hnb) {
+ f_start_hnbs();
+ }
+
+ /* Sometimes, the RUA InitialUE-Message from a test happens too quickly, before the RANAP RESET from
+ * RAN_Emulation is through, after above f_cn_nr_init(). In the pcap it seems to be a matter of 50 ms. Give some
+ * grace. */
+ f_sleep(1.0);
+}
+
+friend function f_shutdown_helper() runs on test_CT {
+ if (mp_validate_talloc_asn1) {
+ f_verify_talloc_bytes(HNBGWVTY, {"asn1_context"}, 1);
+ }
+
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+/* helper function to start all of the simulated hNodeBs */
+function f_start_hnbs() runs on test_CT {
+ for (var integer i:= 0; i < g_num_hnbs; i := i+1) {
+ f_hnbap_hnb_register(i, i);
+ }
+}
+
+/***********************************************************************
+ * code running in test_CT, preparing start of per-UE ConnHdlr
+ ***********************************************************************/
+
+/* inbound RUA connection establishment on Iuh side */
+function IuhRanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
+runs on RUA_Emulation_CT return RUA_ConnHdlr {
+ log("CreateCallback");
+ return null;
+}
+
+/* inbound RUA connectionless data on Iuh side */
+function IuhRanapUnitdataCallback(RANAP_PDU ranap)
+runs on RUA_Emulation_CT return template RANAP_PDU {
+ log("UnitdataCallback");
+ return omit;
+}
+
+private function f_start_handler_create(TestHdlrParams pars) runs on test_CT return ConnHdlr {
+ var ConnHdlr vc_conn;
+ var charstring id := testcasename() & int2str(pars.hnb_idx);
+
+ vc_conn := ConnHdlr.create(id);
+
+ /* Iuh RUA part */
+ connect(vc_conn:RUA, vc_RUA[pars.hnb_idx]:CLIENT);
+
+ /* MSC or SGSN */
+ connect(vc_conn:BSSAP, g_cn[pars.cn_idx].vc_RAN:CLIENT);
+ connect(vc_conn:BSSAP_PROC, g_cn[pars.cn_idx].vc_RAN:PROC);
+
+ /* MGCP part */
+ connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
+ connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
+
+ connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);
+
+ return vc_conn;
+}
+
+private function f_start_handler_run(ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT {
+ var charstring id := testcasename(); // & int2str(pars.ran_idx);
+ /* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
+ * a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
+ pars.hnb := g_hnb_cfg[pars.hnb_idx];
+ vc_conn.start(derefers(fn)(id, pars));
+}
+
+function f_start_handler_with_pars(void_fn fn, template (value) TestHdlrParams pars)
+runs on test_CT return ConnHdlr {
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_create(valueof(pars));
+ f_start_handler_run(vc_conn, fn, valueof(pars));
+ return vc_conn;
+}
+
+/***********************************************************************
+ * code running inside per-UE ConnHdlr
+ ***********************************************************************/
+
+type function void_fn(charstring id, TestHdlrParams pars) runs on ConnHdlr;
+
+function f_init_handler(TestHdlrParams pars, float t_guard := 20.0) runs on ConnHdlr {
+ /* make parameters available via component variable */
+ g_pars := pars;
+
+ f_init_pfcp(testcasename());
+
+ /* start guard timer and activate it as default */
+ g_Tguard.start(t_guard);
+ activate(as_Tguard_ConnHdlr());
+
+ map(self:HNBGWVTY, system:HNBGWVTY);
+ f_vty_set_prompts(HNBGWVTY);
+ f_vty_transceive(HNBGWVTY, "enable");
+
+ /* TODO: CTRL? */
+
+ f_sleep(1.0);
+}
+
+/* global altstep for global guard timer; */
+private altstep as_Tguard_ConnHdlr() runs on ConnHdlr {
+ [] g_Tguard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+private function f_bssap_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
+{
+ var RANAP_PDU rx;
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(exp_rx) -> value rx {
+ setverdict(pass);
+ }
+ [] BSSAP.receive(RANAP_PDU:?) {
+ setverdict(fail, "Got an unexpected RANAP message on BSSAP port, was waiting for ", exp_rx);
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for RANAP on BSSAP port: ", exp_rx);
+ mtc.stop;
+ }
+ }
+ T.stop;
+ return rx;
+}
+
+/* send RANAP on Iuh and expect it to show up on Iu */
+function f_iuh2iu(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
+runs on ConnHdlr return RANAP_PDU {
+ var RANAP_PDU rx;
+ timer T := 5.0;
+
+ if (istemplatekind(exp_rx, "omit")) {
+ exp_rx := tx;
+ }
+
+ RUA.send(tx);
+
+ return f_bssap_expect(exp_rx);
+}
+
+/* send RANAP on Iu and expect it to show up on Iuh */
+function f_iu2iuh(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
+runs on ConnHdlr return RANAP_PDU {
+ if (istemplatekind(exp_rx, "omit")) {
+ exp_rx := tx;
+ }
+
+ BSSAP.send(tx);
+
+ return f_rua_expect(exp_rx)
+}
+
+/* expect to receive a specific RUA message on Iuh */
+private function f_rua_expect(template (present) RANAP_PDU exp_rx) runs on ConnHdlr return RANAP_PDU
+{
+ var RANAP_PDU rx;
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] RUA.receive(exp_rx) -> value rx {
+ setverdict(pass);
+ }
+ [] RUA.receive(RANAP_PDU:?) {
+ setverdict(fail, "Got an unexpected RUA message, was waiting for ", exp_rx);
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for Iuh ", exp_rx);
+ mtc.stop;
+ }
+ }
+ T.stop;
+ return rx;
+}
+
+/* send RANAP on Iuh and expect it to show up on Iu */
+function f_iuh2iu_connect(template (present) RANAP_PDU tx, template RANAP_PDU exp_rx := omit)
+runs on ConnHdlr return RANAP_PDU {
+ var RANAP_PDU rx;
+ timer T := 5.0;
+
+ if (istemplatekind(exp_rx, "omit")) {
+ exp_rx := tx;
+ }
+
+ /* create an expect on the Iu side for the random NAS portion */
+ if (g_pars.expect_separate_sccp_cr) {
+ f_ran_register_sccp_cr_without_payload();
+ } else {
+ var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx));
+ f_ran_register_exp(valueof(nas));
+ }
+
+ /* send it via Iuh (creating a RUA connection) */
+ RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
+
+ if (g_pars.expect_separate_sccp_cr) {
+ /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */
+ BSSAP.receive(tr_RANAP_Conn_Req());
+ }
+
+ /* expect to receive it on the Iu side */
+ return f_bssap_expect(exp_rx);
+}
+
+/* 3GPP TS 48.006 9.2 Connection release:
+ *
+ * The MSC sends a SCCP released message. This message shall not contain
+ * any user data field.
+ *
+ * So what we expect normally is:
+ *
+ * HNBGW MSC
+ * RUA --id-Disconnect-------> | ---Data-Form-1(!)---> | Iu-ReleaseComplete
+ * | <--Released---------- | (no data)
+ *
+ * This function tests osmo-hnbgw behavior if the CN fails to send a RLSD:
+ * after some timeout, osmo-hnbgw should send a RLSD to the CN.
+ */
+function f_iuh2iu_disconnect(template (present) RANAP_PDU tx, RUA_IEs.Cause cause,
+ template RANAP_PDU exp_rx := omit)
+runs on ConnHdlr return RANAP_PDU {
+ var RANAP_PDU rx
+ timer T := int2float(mp_hnbgw_timer_x31) + 1.0;
+
+ if (istemplatekind(exp_rx, "omit")) {
+ exp_rx := tx;
+ }
+
+ /* send it via Iuh (creating a RUA connection) */
+ RUA.send(RUA_Disc_Req:{tx, cause});
+
+ /* expect to receive it on the Iu side */
+ rx := f_bssap_expect(exp_rx);
+
+ /* expect disconnect on the Iu side */
+ T.start;
+ alt {
+ [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
+ setverdict(pass);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for Iu disconnect");
+ return rx;
+ }
+
+ }
+ return rx;
+}
+
+private function f_build_initial_ue_with_nas(TestHdlrParams pars, octetstring nas)
+ return RANAP_PDU {
+ var RANAP_IEs.LAI lai := {
+ pLMNidentity := hex2oct(pars.hnb.lai.mcc_mnc),
+ lAC := int2oct(pars.hnb.lai.lac, 2),
+ iE_Extensions := omit
+ };
+ var RANAP_IEs.SAI sai := {
+ pLMNidentity := lai.pLMNidentity,
+ lAC := lai.lAC,
+ sAC := int2oct(pars.hnb.sac, 2),
+ iE_Extensions := omit
+ }
+ var IuSignallingConnectionIdentifier sigc_id := int2bit(f_rnd_int(1000), 24);
+ var GlobalRNC_ID grnc_id := {
+ pLMNidentity := lai.pLMNidentity,
+ rNC_ID := 2342
+ }
+ var template RANAP_PDU ret;
+ if (pars.ps_domain) {
+ var RANAP_IEs.RAC rac := '00'O;
+ ret := ts_RANAP_initialUE_PS(lai, rac, sai, nas, sigc_id, grnc_id);
+ } else {
+ ret := ts_RANAP_initialUE_CS(lai, sai, nas, sigc_id, grnc_id);
+ }
+ return valueof(ret);
+}
+
+/* build a RANAP InitialUE based on the TestHdlrParams */
+friend function f_build_initial_ue(TestHdlrParams pars) return RANAP_PDU {
+
+ var octetstring nas;
+
+ if (pars.tx_sccp_cr_data_len == 0) {
+ nas := f_rnd_octstring(10);
+ } else {
+ /* The test asks for an exact number of Optional Data bytes. */
+
+ /* First see what size the RANAP part of the payload data is,
+ * to adjust the NAS PDU size to the size requested by the test (pars.tx_sccp_cr_data_len). */
+ var RANAP_PDU initial_ue := f_build_initial_ue_with_nas(pars, '00'O);
+
+ var octetstring ranap_plus_one_byte_nas := enc_RANAP_PDU(initial_ue);
+ var integer ranap_length := lengthof(ranap_plus_one_byte_nas) - 1;
+
+ log("ranap_plus_one_byte_nas = ", lengthof(ranap_plus_one_byte_nas), " bytes, ", initial_ue, " = ",
+ ranap_plus_one_byte_nas);
+ log("ranap_length = ", ranap_length);
+
+ /* SCCP CR has a payload length limit of 130 bytes. To trigger this limit, the RANAP + NAS PDU has to be
+ * > 130 bytes. It doesn't need to be 131 bytes in the NAS PDU alone, but let's just make it definitely
+ * large enough. To test for this limit, pars.tx_sccp_cr_data_len asks for a specific amount of data len. */
+ nas := f_rnd_octstring(pars.tx_sccp_cr_data_len - ranap_length);
+ }
+
+ var RANAP_PDU ret := f_build_initial_ue_with_nas(pars, nas);
+
+ if (pars.tx_sccp_cr_data_len != 0) {
+ for (var integer attempts := 0; attempts < 2; attempts := attempts + 1) {
+ var octetstring check_len := enc_RANAP_PDU(ret);
+ log("final RANAP PDU length = ", lengthof(check_len));
+ if (lengthof(check_len) == pars.tx_sccp_cr_data_len) {
+ return ret;
+ }
+ nas := f_rnd_octstring(lengthof(nas) + (pars.tx_sccp_cr_data_len - lengthof(check_len)));
+ log("that was off, changed NAS length to ", lengthof(nas), " and trying again");
+ ret := f_build_initial_ue_with_nas(pars, nas);
+ }
+ setverdict(fail, "Ended up with wrong Optional Data length");
+ mtc.stop;
+ }
+ return ret;
+}
+
+/* build a RANAP RAB AssignmentResponse based on the TestHdlrParams */
+friend function f_build_rab_ass_resp(TestHdlrParams pars) return RANAP_PDU {
+ var template RAB_SetupOrModifiedList rab_sml;
+
+ rab_sml := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA("192.168.1.23"), t_RAB_binding_port(1234));
+
+ return valueof(ts_RANAP_RabAssResp(rab_sml));
+}
+
+
+/***********************************************************************
+ * HNBAP Testing
+ ***********************************************************************/
+
+
+function f_hnbap_hnb_register(integer hnb_idx := 0, integer cell_id := 0, boolean expect_reject := false) runs on test_CT
+{
+ timer T := 2.0;
+
+ HNBAP[hnb_idx].send(ts_HNBAP_HNBRegisterRequest(char2oct("TTCN3-HNB-" & int2str(hnb_idx)),
+ hex2oct(g_hnb_cfg[hnb_idx].lai.mcc_mnc),
+ int2bit(1 + cell_id, 28),
+ int2oct(g_hnb_cfg[hnb_idx].lai.lac, 2),
+ int2oct(0, 1),
+ int2oct(g_hnb_cfg[hnb_idx].sac, 2)));
+
+ T.start;
+ alt {
+ [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterAccept(?)) {
+ if (expect_reject) {
+ setverdict(fail, "Rx HNB Register Accept while expecting reject");
+ } else {
+ setverdict(pass);
+ }
+ }
+ [] HNBAP[hnb_idx].receive(tr_HNBAP_HNBRegisterReject(?)) {
+ if (expect_reject) {
+ setverdict(pass);
+ } else {
+ setverdict(fail, "Rx HNB Register Reject while expecting accept");
+ }
+ }
+ [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
+ repeat;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for HNB Register response");
+ }
+ }
+}
+
+function f_hnbap_ue_register(integer hnb_idx := 0, template (present) UE_Identity ue_id, boolean expect_reject := false) runs on test_CT
+{
+ timer T := 2.0;
+
+ HNBAP[hnb_idx].send(ts_HNBAP_UERegisterRequest(ue_id));
+
+ T.start;
+ alt {
+ [] HNBAP[hnb_idx].receive(tr_HNBAP_UERegisterAccept(ue_id)) {
+ if (expect_reject) {
+ setverdict(fail, "Rx UE Register Accept while expecting reject");
+ } else {
+ setverdict(pass);
+ }
+ }
+ [] HNBAP[hnb_idx].receive(tr_HNBAP_UERegisterReject(ue_id, ?)) {
+ if (expect_reject) {
+ setverdict(pass);
+ } else {
+ setverdict(fail, "Rx UE Register Reject while expecting accept");
+ }
+ }
+ [] HNBAP[hnb_idx].receive(IUHEM_Event:?) {
+ repeat;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for UE Register response");
+ }
+ }
+}
+
+
+testcase TC_hnb_register() runs on test_CT {
+ g_num_hnbs := 1;
+ f_init(start_hnb := false);
+ f_hnbap_hnb_register(0);
+ f_shutdown_helper();
+}
+
+/* Try to register the same HNB from 2 different concurrent connections. Second
+ * one should be rejected. */
+testcase TC_hnb_register_duplicate() runs on test_CT {
+ g_num_hnbs := 2;
+ f_init(start_hnb := false);
+
+ /* Make HNB REQ look as if it came from the same HnodeB (LAI+SAC),
+ * but from different IP address (underlaying link): */
+ g_hnb_cfg[1] := g_hnb_cfg[0];
+ f_hnbap_hnb_register(0);
+ f_hnbap_hnb_register(1, 0, expect_reject := true);
+
+ f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
+
+ f_shutdown_helper();
+}
+
+/* Try to register the same HNB in the same connection already established, aka
+ * duplicate HNB Register Request. It should be accepted and new configuration
+ * applied. TS 25.469 8.2.4 */
+testcase TC_hnb_register_duplicate_reuse_sctp_assoc() runs on test_CT {
+ g_num_hnbs := 1;
+ f_init(start_hnb := false);
+ f_hnbap_hnb_register(0);
+ f_hnbap_hnb_register(0);
+ f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
+ f_shutdown_helper();
+}
+
+/* Drop HNBAP conn (HNBAP DEREG) and reconnect it (HNBAP REG) using same SCTP association.
+ * Related: OS#5676, SYS#6113 */
+testcase TC_hnb_reregister_reuse_sctp_assoc() runs on test_CT {
+ g_num_hnbs := 1;
+ f_init(start_hnb := false);
+ f_hnbap_hnb_register(0);
+ HNBAP[0].send(ts_HNBAP_HNBDe_Register(ts_HnbapCause(unspecified)));
+ f_hnbap_hnb_register(0);
+ f_verify_talloc_count(HNBGWVTY, {"struct hnb_context"}, expect_count := 1);
+ f_shutdown_helper();
+}
+
+/* regular UE registration */
+testcase TC_ue_register() runs on test_CT {
+ var UE_Identity ue_id := { iMSI := imsi_hex2oct(f_gen_imsi(1)) };
+ g_num_hnbs := 1;
+ f_init(start_hnb := true);
+ f_hnbap_ue_register(0, ue_id);
+ f_shutdown_helper();
+}
+
+/* regular UE registration (UE Identity: TMSI+LAI) */
+testcase TC_ue_register_tmsi_lai() runs on test_CT {
+ var UE_Identity ue_id := { tMSILAI := { tMSI := oct2bit(f_gen_tmsi(0)),
+ lAI := { pLMNID := '00F110'O, lAC := '2342'O }
+ }
+ };
+ g_num_hnbs := 1;
+ f_init(start_hnb := true);
+ f_hnbap_ue_register(0, ue_id);
+ f_shutdown_helper();
+}
+
+
+/* UE registration from unregistered HNB */
+testcase TC_ue_register_before_hnb_register() runs on test_CT {
+ var UE_Identity ue_id := { iMSI := imsi_hex2oct(f_gen_imsi(1)) };
+ g_num_hnbs := 1;
+ f_init(start_hnb := false);
+ f_hnbap_ue_register(0, ue_id, expect_reject := true);
+ f_shutdown_helper();
+}
+
+/***********************************************************************
+ * RUA / RANAP Testing
+ ***********************************************************************/
+
+/* Translate from {msc,sgsn}x{0..n} to the proper index to use in g_cn[].
+ * g_cn[] stores CN links, MSCs and SGSNs in the same array.
+ * For example, for 'sgsn 23', use g_cn[ f_cn_idx(ps_domain := true, cn_nr := 23) ].
+ *
+ * Note the naming:
+ * cn_nr is the number used in the cfg file, as in 'msc 0'.
+ * cn_idx is the array index in g_cn[].
+ */
+private function f_cn_idx(boolean ps_domain, integer cn_nr := 0) return integer
+{
+ if (ps_domain) {
+ return FIRST_SGSN_IDX + cn_nr;
+ }
+ return FIRST_MSC_IDX + cn_nr;
+}
+
+private template (value) TestHdlrParams
+t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0,
+ boolean expect_separate_sccp_cr := false, integer tx_sccp_cr_data_len := 0,
+ integer cn_nr := 0, template (value) RANAP_IEs.Cause rab_rel_cause := ts_RanapCause_nas_normal) := {
+ hnb_idx := hnb_idx,
+ cn_idx := f_cn_idx(ps_domain, cn_nr),
+ imsi := f_gen_imsi(imsi_suffix),
+ ps_domain := ps_domain,
+ mgcp_pars := t_MgcpParams,
+ hnb := omit, /* filled in later */
+ expect_separate_sccp_cr := expect_separate_sccp_cr,
+ tx_sccp_cr_data_len := tx_sccp_cr_data_len,
+ pfcp_local_addr := mp_pfcp_ip_local,
+ nas_pdu := omit,
+ sccp_addr_msc := omit,
+ sccp_addr_hnbgw := omit,
+ rab_rel_cause := rab_rel_cause
+}
+
+/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */
+friend function f_tc_initial_ue(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ var RANAP_PDU tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+}
+testcase TC_ranap_cs_initial_ue() runs on test_CT {
+ var ConnHdlr vc_conn;
+
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+testcase TC_ranap_ps_initial_ue() runs on test_CT {
+ var ConnHdlr vc_conn;
+
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+private function f_vty_set_sccp_max_optional_data(TELNETasp_PT pt, integer val := -1)
+{
+ var charstring valstr;
+ if (val < 0) {
+ valstr := "standard";
+ } else {
+ valstr := int2str(val);
+ }
+ f_vty_enter_config(pt);
+ f_vty_transceive(pt, "cs7 instance 0");
+ f_vty_transceive(pt, "sccp max-optional-data " & valstr);
+ f_vty_transceive(pt, "end");
+}
+
+testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT {
+ var ConnHdlr vc_conn;
+
+ g_num_hnbs := 1;
+ f_init();
+
+ f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, expect_separate_sccp_cr := true));
+ vc_conn.done;
+
+ /* reset */
+ f_vty_set_sccp_max_optional_data(HNBGWVTY);
+
+ f_shutdown_helper();
+}
+testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT {
+ var ConnHdlr vc_conn;
+
+ g_num_hnbs := 1;
+ f_init();
+
+ f_vty_set_sccp_max_optional_data(HNBGWVTY, 0);
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, expect_separate_sccp_cr := true));
+ vc_conn.done;
+
+ /* reset */
+ f_vty_set_sccp_max_optional_data(HNBGWVTY);
+
+ f_shutdown_helper();
+}
+
+type record Testdata_CR_Limit {
+ integer data_len,
+ integer max_optional_data,
+ boolean expect_separate_sccp_cr
+};
+type record of Testdata_CR_Limit Testdata_CR_Limits;
+
+testcase TC_sccp_cr_limit() runs on test_CT {
+ g_num_hnbs := 1;
+ f_init();
+
+ const Testdata_CR_Limits tests := {
+ { data_len := 130, max_optional_data := -1, expect_separate_sccp_cr := false },
+ { data_len := 131, max_optional_data := -1, expect_separate_sccp_cr := true },
+
+ { data_len := 100, max_optional_data := 100, expect_separate_sccp_cr := false },
+ { data_len := 101, max_optional_data := 100, expect_separate_sccp_cr := true },
+
+ { data_len := 200, max_optional_data := 200, expect_separate_sccp_cr := false },
+ { data_len := 201, max_optional_data := 200, expect_separate_sccp_cr := true }
+ };
+
+ var integer csps;
+ for (csps := 0; csps < 2; csps := csps + 1) {
+ var boolean ps_domain := (csps > 0);
+
+ var integer i;
+ for (i := 0; i < lengthof(tests); i := i + 1) {
+ var Testdata_CR_Limit t := tests[i];
+ f_logp(HNBGWVTY,
+ "TEST PART TC_sccp_cr_limit ps_domain=" & f_bool2str(ps_domain)
+ & " data_len=" & int2str(t.data_len)
+ & " max_optional_data=" & int2str(t.max_optional_data)
+ & " expect_separate_sccp_cr=" & f_bool2str(t.expect_separate_sccp_cr)
+ );
+
+ f_vty_set_sccp_max_optional_data(HNBGWVTY, t.max_optional_data);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue),
+ t_pars(100 + i,
+ ps_domain := ps_domain,
+ expect_separate_sccp_cr := t.expect_separate_sccp_cr,
+ tx_sccp_cr_data_len := t.data_len));
+ vc_conn.done;
+ }
+ }
+
+ /* reset */
+ f_vty_set_sccp_max_optional_data(HNBGWVTY);
+
+ f_shutdown_helper();
+}
+
+/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
+ * Return true when an OK reply was sent, false otherwise.
+ * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */
+function f_handle_crcx(inout MgcpParameters pars, MgcpCommand mgcp_cmd) return template MgcpResponse {
+ var MgwResponse conn := pars.mgw_conn_ran;
+ if (pars.got_crcx_count > 0) {
+ conn := pars.mgw_conn_cn;
+ }
+ pars.got_crcx_count := pars.got_crcx_count + 1;
+
+ var MgcpMessage mgcp_msg := {
+ command := mgcp_cmd
+ }
+ var template MgcpResponse mgcp_resp;
+ var MgcpOsmuxCID osmux_cid;
+ var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
+ if (ispresent(pars.mgcp_call_id)) {
+ if (pars.mgcp_call_id != call_id) {
+ setverdict(fail, "CRCX contained unexpected call id. Expected:", pars.mgcp_call_id, " got:", call_id);
+ mtc.stop;
+ }
+ } else {
+ pars.mgcp_call_id := call_id;
+ }
+
+ /* When the endpoint contains a wildcard we keep the endpoint
+ * identifier we have set up in pars. Otherwise we use the
+ * endpoint name that the call agent has supplied */
+ if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
+ pars.mgcp_ep := mgcp_cmd.line.ep;
+ }
+
+ if (conn.resp == -1) {
+ /* Reply with rror */
+ var MgcpResponse mgcp_rsp := {
+ line := {
+ code := "542",
+ trans_id := mgcp_cmd.line.trans_id,
+ string := "FORCED_FAIL"
+ },
+ sdp := omit
+
+ }
+ var MgcpParameter mgcp_rsp_param := {
+ code := "Z",
+ val := pars.mgcp_ep
+ };
+ mgcp_rsp.params[0] := mgcp_rsp_param;
+ return mgcp_rsp;
+ }
+
+ if (conn.resp == 0) {
+ /* Do not reply at all */
+ return omit;
+ }
+
+ if (conn.resp != 1) {
+ setverdict(fail, "Unexpected value for pars.mgw_conn_*.resp, expect -1, 0 or 1");
+ mtc.stop;
+ }
+
+ var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
+ hex2str(pars.mgcp_call_id), "42",
+ conn.mgw_rtp_port,
+ { int2str(pars.rtp_payload_type) },
+ { valueof(ts_SDP_rtpmap(pars.rtp_payload_type,
+ pars.rtp_sdp_format)),
+ valueof(ts_SDP_ptime(20)) }));
+
+ if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
+ if (not pars.use_osmux) {
+ setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
+ mtc.stop;
+ }
+ pars.got_osmux_count := pars.got_osmux_count + 1;
+ /* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
+ osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
+ log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
+ if (osmux_cid != -1) {
+ setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
+ mtc.stop;
+ }
+
+ osmux_cid := 0;
+ mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
+ } else {
+ mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
+ }
+
+ f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(pars.mgcp_ep));
+
+ return mgcp_resp;
+}
+
+friend function f_create_rab(inout MgcpParameters pars) runs on ConnHdlr {
+ f_rab_ass_req(pars);
+ f_rab_ass_resp(pars);
+}
+
+friend function f_rab_ass_req(inout MgcpParameters pars) runs on ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ var template RAB_SetupOrModifyList rab_sml;
+ timer T := 5.0;
+
+ /* Send RAB Assignment Request */
+ rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.cn_rtp_ip), t_RAB_binding_port(pars.cn_rtp_port));
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ BSSAP.send(tx);
+ T.start;
+
+ /* Handle MGCP CRCX */
+ alt {
+ [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+ log("CRCX1", mgcp_cmd);
+ var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
+ MGCP.send(valueof(mgcp_rsp));
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for MGCP");
+ }
+ }
+ T.stop;
+
+ /* Expect RAB Assignment Request with IP/port from CRCX ACK via Iuh */
+ rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_ran.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_ran.mgw_rtp_port));
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+
+ f_rua_expect(tx);
+}
+
+friend function f_rab_ass_resp(inout MgcpParameters pars) runs on ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ var template RAB_SetupOrModifiedList rab_smdl;
+
+ /* Send back RAB Assignment Response via Iuh */
+ rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.hnb_rtp_ip), t_RAB_binding_port(pars.hnb_rtp_port));
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+ RUA.send(tx);
+
+ interleave {
+ /* Expect MDCX with IP/port from RAB Assignment Response */
+ [] MGCP.receive(tr_MDCX(tr_SDP(pars.hnb_rtp_ip, pars.hnb_rtp_port))) -> value mgcp_cmd {
+ var HostName mgw_rtp_ip;
+ var boolean exp_rua_rab_reass := false;
+ log("MDCX1", mgcp_cmd);
+ if (ispresent(pars.mgw_conn_ran.mgw_rtp_ip_mdcx)) {
+ mgw_rtp_ip := pars.mgw_conn_ran.mgw_rtp_ip_mdcx;
+ if (pars.mgw_conn_ran.mgw_rtp_ip != pars.mgw_conn_ran.mgw_rtp_ip_mdcx) {
+ exp_rua_rab_reass := true;
+ }
+ } else {
+ mgw_rtp_ip := pars.mgw_conn_ran.mgw_rtp_ip;
+ }
+
+ /* Verify SDP of MDCX */
+ var SDP_Message sdp := valueof(ts_SDP(mgw_rtp_ip, mgw_rtp_ip, hex2str(pars.mgcp_call_id), "42", pars.mgw_conn_ran.mgw_rtp_port,
+ { int2str(pars.rtp_payload_type) }, { valueof(ts_SDP_rtpmap(pars.rtp_payload_type, pars.rtp_sdp_format)), valueof(ts_SDP_ptime(20)) } ));
+ var template MgcpResponse mgcp_rsp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, pars.mgw_conn_ran.mgcp_connection_id, sdp);
+ MGCP.send(valueof(mgcp_rsp));
+
+ /* If IP address changed, we expect HNBGW to Modify the RAB through RAB-Ass-Req: */
+ if (exp_rua_rab_reass) {
+ var template RAB_SetupOrModifyList rab_sml;
+ /* Expect RAB Assignment Request with IP/port from MDCX ACK via Iuh */
+ rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_ran.mgw_rtp_ip_mdcx), t_RAB_binding_port(pars.mgw_conn_ran.mgw_rtp_port));
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+
+ f_rua_expect(tx);
+ /* Send back RAB Assignment Response via Iuh */
+ rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.hnb_rtp_ip), t_RAB_binding_port(pars.hnb_rtp_port));
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+ RUA.send(tx);
+ /* This shouldn't trigger any MGCP, since nothing changed on the HNB IP side. Continue below. */
+ }
+ }
+ /* Handle CRCX for second leg of endpoint, answer with IP/port */
+ [] MGCP.receive(tr_CRCX(pars.mgcp_ep, tr_SDP(pars.cn_rtp_ip, pars.cn_rtp_port))) -> value mgcp_cmd {
+ log("CRCX2", mgcp_cmd);
+ /* Verify SDP of CRCX */
+ var template MgcpResponse mgcp_rsp := f_handle_crcx(pars, mgcp_cmd);
+ MGCP.send(valueof(mgcp_rsp));
+ }
+ }
+
+ /* Expect RAB Assignment Response with IP/port from second CRCX ACK */
+ rab_smdl := ts_RAB_SMdL(t_RAB_id(23), f_ts_RAB_TLA(pars.mgw_conn_cn.mgw_rtp_ip), t_RAB_binding_port(pars.mgw_conn_cn.mgw_rtp_port));
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+
+ f_bssap_expect(tx);
+}
+
+private altstep as_mgcp_dlcx(inout TestHdlrParams pars) runs on ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+
+ [] MGCP.receive(tr_DLCX(pars.mgcp_pars.mgcp_ep)) -> value mgcp_cmd {
+ log("DLCX", mgcp_cmd);
+ MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
+ pars.mgcp_pars.got_dlcx_count := pars.mgcp_pars.got_dlcx_count + 1;
+ if (pars.mgcp_pars.got_dlcx_count != pars.mgcp_pars.got_crcx_count) {
+ repeat;
+ }
+ setverdict(pass);
+ }
+}
+
+friend function f_tc_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ const charstring hnb0_ctr_prefix := "TTCN3.hnb.001-01-L2342-R0-S55-C1.";
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ timer T := 5.0;
+
+ f_init_handler(pars);
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+
+ f_statsd_reset();
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ /* Expect stats to be 0 */
+ var StatsDExpects expect := {
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.req", mtype := "c", min := 0, max := 0},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.cnf", mtype := "c", min := 0, max := 0},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.fail", mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ f_create_rab(pars.mgcp_pars);
+
+ expect := {
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.req", mtype := "c", min := 1, max := 1},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.cnf", mtype := "c", min := 1, max := 1},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.fail", mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ /* Send Iu Release */
+ tx := valueof(ts_RANAP_IuReleaseCommand(pars.rab_rel_cause));
+ f_iu2iuh(tx);
+
+ T.start;
+ alt {
+ [] as_mgcp_dlcx(pars) {}
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for DLCX");
+ }
+ }
+
+ tx := valueof(ts_RANAP_IuReleaseComplete());
+ f_iuh2iu(tx);
+}
+
+testcase TC_rab_assignment() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), t_pars(3));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+friend function f_tc_rab_assign_fail(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ const charstring hnb0_ctr_prefix := "TTCN3.hnb.001-01-L2342-R0-S55-C1.";
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ timer T := 5.0;
+
+ f_init_handler(pars);
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+
+ f_statsd_reset();
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ /* Expect stats to be 0 */
+ var StatsDExpects expect := {
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.req", mtype := "c", min := 0, max := 0},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.cnf", mtype := "c", min := 0, max := 0},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.fail", mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ f_rab_ass_req(pars.mgcp_pars);
+
+ /* Send RAB failed list in response */
+ tx := valueof(ts_RANAP_RabAssResp(rab_fl := ts_RAB_FL(t_RAB_id(23), pars.rab_rel_cause)));
+ f_iuh2iu(tx);
+
+ expect := {
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.req", mtype := "c", min := 1, max := 1},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.cnf", mtype := "c", min := 0, max := 0},
+ {name := hnb0_ctr_prefix & "ranap.cs.rab_act.fail", mtype := "c", min := 1, max := 1}
+ };
+ f_statsd_expect(expect);
+
+
+ T.start;
+ alt {
+ [] as_mgcp_dlcx(pars) {}
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for DLCX");
+ }
+ }
+}
+
+testcase TC_rab_assign_fail() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_fail), t_pars(4, rab_rel_cause := ts_RanapCause_radio_conn_lost));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+friend function f_tc_rab_release(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ const charstring hnb0_ctr_prefix := "TTCN3.hnb.001-01-L2342-R0-S55-C1.";
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ timer T := 15.0;
+
+ f_init_handler(pars);
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+
+ f_statsd_reset();
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ f_create_rab(pars.mgcp_pars);
+
+ var charstring ctr_name;
+ if (pars.rab_rel_cause == valueof(ts_RanapCause_nas_normal)) {
+ ctr_name := "ranap.cs.rab_rel.req.normal";
+ } else {
+ ctr_name := "ranap.cs.rab_rel.req.abnormal";
+ }
+
+ /* Expect stats to be 0 */
+ var StatsDExpects expect := {
+ {name := hnb0_ctr_prefix & ctr_name, mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ /* Send RAB Release */
+ tx := valueof(ts_RANAP_RabAssReq(rab_rl := ts_RAB_RL(t_RAB_id(23), pars.rab_rel_cause)));
+ BSSAP.send(tx);
+
+ expect := {
+ {name := hnb0_ctr_prefix & ctr_name, mtype := "c", min := 1, max := 1}
+ };
+ f_statsd_expect(expect);
+
+ T.start;
+
+ alt {
+ [] as_mgcp_dlcx(pars) {}
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for DLCX");
+ }
+ }
+ T.stop;
+
+ f_rua_expect(tx);
+}
+
+/* RAB release with Cause NAS/Normal (successful/orderly release) */
+testcase TC_rab_release() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release), t_pars(5));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+/* RAB release with Cause abnormal */
+testcase TC_rab_release_abnormal() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_release),
+ t_pars(8, rab_rel_cause := ts_RanapCause_radio_conn_lost));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+friend function f_tc_rab_assign_mgcp_to(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ var template RAB_SetupOrModifyList rab_sml;
+ timer T := 15.0;
+
+ T.start;
+ f_init_handler(pars);
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+
+ /* Send RAB Assignment Request */
+ rab_sml := ts_RAB_SML(t_RAB_id(23), f_ts_RAB_TLA(pars.mgcp_pars.cn_rtp_ip), t_RAB_binding_port(pars.mgcp_pars.cn_rtp_port));
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ BSSAP.send(tx);
+
+ /* Ignore MGCP CRCX */
+ alt {
+ [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+ log("Ignoreing CRCX1", mgcp_cmd);
+ repeat;
+ }
+ [] BSSAP.receive(tr_RANAP_IuReleaseRequest(?)) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for IuRelease");
+ }
+ }
+
+ /* Send Iu Release */
+ tx := valueof(ts_RANAP_IuReleaseCommand(pars.rab_rel_cause));
+ f_iu2iuh(tx);
+
+ tx := valueof(ts_RANAP_IuReleaseComplete());
+ f_iuh2iu(tx);
+}
+
+testcase TC_rab_assign_mgcp_to() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assign_mgcp_to), t_pars(6));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+/* Test case where IuUP IP address announced by HNB and updated through MDCX
+ * makes MGW select a new local IuUP address. HNBGW is expected to update the HNB
+ * through RAB-Modify-Req. */
+testcase TC_rab_assign_mgw_iuup_addr_chg() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+ var template (value) TestHdlrParams pars := t_pars(3);
+ /* Emulate change of local IuUP IP address after rx MDCX: */
+ pars.mgcp_pars.mgw_conn_ran.mgw_rtp_ip_mdcx := "127.3.2.1";
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_rab_assignment), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+/* Create an Iuh connection; send InitialUE; transceive data both directions */
+friend function f_tc_ranap_bidir(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+
+ /* HNB -> MSC: InitialUE */
+ f_iuh2iu_connect(f_build_initial_ue(g_pars));
+
+ /* MSC <- HNB: DirectTransfer */
+ f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+ /* MSC -> HNB: DirectTransfer */
+ f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+
+ /* HNB <- MSC: CommonID */
+ f_iu2iuh(ts_RANAP_CommonId(hex2oct(pars.imsi)));
+}
+testcase TC_ranap_cs_bidir() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(3));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+testcase TC_ranap_ps_bidir() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_bidir), t_pars(4, true));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+
+private function f_tc_ranap_mo_disconnect(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+
+ /* HNB -> MSC: InitialUE */
+ f_iuh2iu_connect(f_build_initial_ue(g_pars));
+
+ /* MSC <- HNB: DirectTransfer */
+ f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+ /* MSC -> HNB: DirectTransfer */
+ f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+
+ /* MSC <- HNB: RUA disconnect */
+ f_iuh2iu_disconnect(ts_RANAP_IuReleaseComplete, RUA_IEs.Cause:{misc:=processing_overload});
+}
+testcase TC_ranap_cs_mo_disconnect() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(5));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+testcase TC_ranap_ps_mo_disconnect() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ranap_mo_disconnect), t_pars(6));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+type record FTeid {
+ HostName addr,
+ OCT4 teid
+}
+
+type record FTeids {
+ FTeid local,
+ FTeid 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 GtpParameters {
+ FTeids core,
+ FTeids access
+}
+
+/* HNB UPF CN
+ * access.remote <---> access.local | core.local <---> core.remote
+ * 127.0.0.4 127.0.0.3 127.0.0.2 127.0.0.1
+ * 0x44004400 0x30303030 0x22002200 0x10101010
+ */
+template GtpParameters t_GtpParameters := {
+ core := {
+ local := {
+ addr := "127.0.0.2",
+ teid := '22002200'O
+ },
+ remote := {
+ addr := "127.0.0.1",
+ teid := '10101010'O
+ }
+ },
+ access := {
+ local := {
+ addr := "127.0.0.3",
+ teid := '30303030'O
+ },
+ remote := {
+ addr := "127.0.0.4",
+ teid := '44004400'O
+ }
+ }
+}
+
+private function f_pfcp_expect(template (present) PDU_PFCP exp_rx, float wait_time := 5.0) runs on ConnHdlr 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;
+}
+
+friend function f_tc_ps_rab_assignment_with_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ var RANAP_PDU tx;
+ var RANAP_PDU rx;
+
+ f_init_handler(pars);
+
+ f_pfcp_register();
+
+ var PDU_PFCP m;
+ var Node_ID upf_node_id := valueof(ts_PFCP_Node_ID_fqdn("\07osmocom\03org"));
+
+ m := f_pfcp_expect(tr_PFCP_Assoc_Setup_Req(), wait_time := 15.0);
+ PFCP.send(ts_PFCP_Assoc_Setup_Resp(m.sequence_number, upf_node_id,
+ ts_PFCP_Cause(REQUEST_ACCEPTED), 1234));
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ var GtpParameters gtp_pars := valueof(t_GtpParameters);
+ var template RAB_SetupOrModifyList rab_sml;
+
+ /* Send RAB Assignment Request */
+ rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ BSSAP.send(tx);
+
+ /* Expect PFCP Session Establishment Request. */
+ m := f_pfcp_expect(tr_PFCP_Session_Est_Req());
+ var F_SEID hnbgw_f_seid := m.message_body.pfcp_session_establishment_request.CP_F_SEID;
+ var PFCP_Session_Establishment_Request serq := m.message_body.pfcp_session_establishment_request;
+
+ /* Acting as UPF, invent a new PFCP SEID to send to HNBGW. Respond to the Session Establishment.
+ * The PFCP response must have the same sequence_number as the request. */
+ var F_SEID up_f_seid := valueof(ts_PFCP_F_SEID_ipv4(f_inet_addr("127.0.0.1"), '1111111111111111'O));
+ var template PDU_PFCP r := ts_PFCP_Session_Est_Resp(m.sequence_number, upf_node_id, hnbgw_f_seid.seid);
+ r.message_body.pfcp_session_establishment_response := {
+ offending_ie := omit,
+ UP_F_SEID := up_f_seid,
+ created_PDR_list := {
+ ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[0].grouped_ie.pdr_id,
+ local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.core.local.teid,
+ f_inet_addr(gtp_pars.core.local.addr))),
+ ts_PFCP_Created_PDR(pdr_id := serq.create_PDR_list[1].grouped_ie.pdr_id,
+ local_F_TEID := ts_PFCP_F_TEID_ipv4(gtp_pars.access.local.teid,
+ f_inet_addr(gtp_pars.access.local.addr)))
+ },
+ load_control_information := omit,
+ overload_control_information := omit,
+ node_list := omit,
+ failed_rule_id := omit,
+ created_traffic_endpoint_list := omit
+ };
+ PFCP.send(r);
+
+ /* Expect on Iuh: RAB Assignment Request with IP/port from PFCP Session Est Resp */
+ rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.local.addr),
+ gtp_pars.access.local.teid);
+ rx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ f_rua_expect(rx);
+
+ /* Send back RAB Assignment Response via Iuh */
+ var template RAB_SetupOrModifiedList rab_smdl;
+ rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
+ gtp_pars.access.remote.teid);
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+ RUA.send(tx);
+
+ m := f_pfcp_expect(tr_PFCP_Session_Mod_Req(up_f_seid.seid));
+ r := ts_PFCP_Session_Mod_Resp(m.sequence_number, hnbgw_f_seid.seid);
+ PFCP.send(r);
+
+ rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.local.addr), gtp_pars.core.local.teid);
+ f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
+
+ f_sleep(2.0);
+ tx := valueof(ts_RANAP_IuReleaseCommand(pars.rab_rel_cause));
+ f_iu2iuh(tx);
+
+ tx := valueof(ts_RANAP_IuReleaseComplete());
+ f_iuh2iu(tx);
+
+ m := f_pfcp_expect(tr_PFCP_Session_Del_Req(up_f_seid.seid));
+ PFCP.send(ts_PFCP_Session_Del_Resp(m.sequence_number, hnbgw_f_seid.seid));
+
+ f_sleep(2.0);
+}
+
+testcase TC_ps_rab_assignment_with_pfcp() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+ f_sleep(1.0);
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_with_pfcp), t_pars(7, ps_domain := true));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+altstep as_disallow_pfcp() runs on ConnHdlr {
+ [] PFCP.receive(PDU_PFCP:?) {
+ setverdict(fail, "Received PFCP message, but no PFCP communication expected");
+ mtc.stop;
+ }
+}
+
+friend function f_tc_ps_rab_assignment_without_pfcp(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ var RANAP_PDU tx;
+ var RANAP_PDU rx;
+ timer T := 5.0;
+
+ f_init_handler(pars);
+
+ f_pfcp_register();
+ activate(as_disallow_pfcp());
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ var GtpParameters gtp_pars := valueof(t_GtpParameters);
+ var template RAB_SetupOrModifyList rab_sml;
+
+ /* Send RAB Assignment Request */
+ rab_sml := ts_RAB_SML_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.core.remote.addr), gtp_pars.core.remote.teid);
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ BSSAP.send(tx);
+
+ /* Expect on Iuh: unmodified RAB Assignment Request */
+ rx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ f_rua_expect(rx);
+
+ /* Send back RAB Assignment Response via Iuh */
+ var template RAB_SetupOrModifiedList rab_smdl;
+ rab_smdl := ts_RAB_SMdL_ps(t_RAB_id(23), f_ts_RAB_TLA(gtp_pars.access.remote.addr),
+ gtp_pars.access.remote.teid);
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+ RUA.send(tx);
+
+ /* Expect on IuPS: unmodified RAB Assignment Response */
+ f_bssap_expect(tr_RANAP_RabAssResp(rab_smdl));
+
+ f_sleep(2.0);
+ tx := valueof(ts_RANAP_IuReleaseCommand(pars.rab_rel_cause));
+ f_iu2iuh(tx);
+
+ tx := valueof(ts_RANAP_IuReleaseComplete());
+ f_iuh2iu(tx);
+
+ f_sleep(2.0);
+}
+
+testcase TC_ps_rab_assignment_without_pfcp() runs on test_CT {
+ var ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ps_rab_assignment_without_pfcp), t_pars(7, ps_domain := true));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+/* Default list of counters for a 'cn' entity to test the cnpool feature. */
+const CounterNameVals counternames_cnpool := {
+ { "cnpool:subscr:new", 0 },
+ { "cnpool:subscr:known", 0 },
+ { "cnpool:subscr:reattach", 0 },
+ { "cnpool:subscr:attach_lost", 0 },
+ { "cnpool:subscr:paged", 0 }
+};
+private function f_ctrs_cn_init(boolean ps_domain, integer cn_count := 0,
+ CounterNameVals counternames := counternames_cnpool) runs on test_CT {
+ if (ps_domain) {
+ g_ctr_cn_node_name := "sgsn";
+ if (cn_count == 0) {
+ cn_count := NUM_SGSN;
+ }
+ } else {
+ g_ctr_cn_node_name := "msc";
+ if (cn_count == 0) {
+ cn_count := NUM_MSC;
+ }
+ }
+ g_ctr_cn := f_counter_name_vals_get_n(IPA_CTRL, g_ctr_cn_node_name, cn_count, counternames);
+ log("initial " & g_ctr_cn_node_name & " rate counters: ", g_ctr_cn);
+}
+
+/* f_ctrs_cn_init();
+ * f_do_thing(on_cn := 0);
+ * f_do_thing(on_cn := 0);
+ * f_do_other(on_cn := 1);
+ * f_ctrs_cn_add(0, "thing", 2);
+ * f_ctrs_cn_add(1, "other");
+ * f_ctrs_cn_verify();
+ */
+private function f_ctrs_cn_verify() runs on test_CT {
+ log("verifying", g_ctr_cn_node_name, " rate counters: ", g_ctr_cn);
+ f_counter_name_vals_expect_n(IPA_CTRL, g_ctr_cn_node_name, g_ctr_cn);
+}
+
+/* convenience: f_ctrs_cn_add() and f_ctrs_cn_verify() in one call.
+ * f_ctrs_cn_init();
+ * f_do_thing(on_cn := 0);
+ * f_do_thing(on_cn := 0);
+ * f_do_thing(on_cn := 0);
+ * f_ctrs_cn_expect(0, "thing", 3);
+ */
+private function f_ctrs_cn_expect(integer cn_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_cn_add(cn_nr, countername, val);
+ f_ctrs_cn_verify();
+}
+
+private function f_ctrs_cn_add(integer cn_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_counter_name_vals_list_add(g_ctr_cn, cn_nr, countername, val);
+}
+
+private function f_perform_compl_l3(octetstring nas, boolean do_clear := true, boolean expect_iu_l3 := true)
+runs on ConnHdlr {
+ timer T := 10.0;
+
+ /* create an expect on the Iu side for the random NAS portion */
+ if (g_pars.expect_separate_sccp_cr) {
+ f_ran_register_sccp_cr_without_payload();
+ } else {
+ f_ran_register_exp(nas);
+ }
+
+ /* send Connect via Iuh (creating a RUA connection) */
+ var RANAP_PDU tx := f_build_initial_ue_with_nas(g_pars, nas);
+ RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
+
+ if (expect_iu_l3) {
+ /* Expect same message to arrive at CN */
+ f_bssap_expect(tx);
+ }
+}
+
+private function f_tc_cnpool_compl_l3(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_perform_compl_l3(g_pars.nas_pdu);
+}
+
+private function f_TC_cnpool_compl_l3(boolean ps_domain, octetstring nas_pdu, integer cn_nr,
+ template (omit) charstring inc_countername := omit) runs on test_CT {
+ var ConnHdlr vc_conn;
+ var template (value) TestHdlrParams pars := t_pars(0, ps_domain := ps_domain, cn_nr := cn_nr);
+ pars.nas_pdu := nas_pdu;
+ log("XXX ", pars);
+ vc_conn := f_start_handler_with_pars(refers(f_tc_cnpool_compl_l3), pars);
+ vc_conn.done;
+
+ if (not istemplatekind(inc_countername, "omit")) {
+ f_ctrs_cn_expect(cn_nr, valueof(inc_countername));
+ }
+}
+
+function f_TC_cnpool_compl_l3_list(boolean ps_domain, ro_octetstring compl3, Osmocom_Types.ro_integer cn_nrs,
+ charstring inc_countername) runs on test_CT {
+ var integer n := lengthof(compl3);
+ if (n < lengthof(cn_nrs)) {
+ n := lengthof(cn_nrs);
+ }
+ for (var integer i := 0; i < n; i := i + 1) {
+ var integer cn_nr := cn_nrs[i mod lengthof(cn_nrs)];
+ f_TC_cnpool_compl_l3(ps_domain, compl3[i mod lengthof(compl3)], cn_nr, inc_countername);
+ }
+}
+
+type enumerated Compl3Type {
+ /* CS */
+ LU,
+ CMSERV,
+ PAGRESP,
+ IMSIDETACH,
+
+ /* PS */
+ ATTACHREQ,
+ RAUREQ,
+ DETREQ
+};
+
+private function f_gen_one_compl_l3(Compl3Type compl3type, template (value) MobileIdentityLV mi,
+ integer ps_nri := -1
+ ) return octetstring
+{
+ /* CS */
+ if (compl3type == LU) {
+ return enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, valueof(mi), '00F110'O)));
+ }
+ if (compl3type == CMSERV) {
+ return enc_PDU_ML3_MS_NW(valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, valueof(mi))));
+ }
+ if (compl3type == PAGRESP) {
+ return enc_PDU_ML3_MS_NW(valueof(ts_PAG_RESP(valueof(mi))));
+ }
+ if (compl3type == IMSIDETACH) {
+ return enc_PDU_ML3_MS_NW(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(valueof(mi))));
+ }
+
+ /* PS */
+ var template (omit) NetworkResourceIdentifierContainerTLV nri := omit;
+ if (ps_nri >= 0) {
+ nri := valueof(ts_GMM_NRI(ps_nri));
+ }
+
+ if (compl3type == ATTACHREQ) {
+ return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_ATTACH_REQ(valueof(mi), f_RAI('001'H, '01'H, '2a2a'O, '17'O),
+ nri := nri)));
+ }
+ if (compl3type == RAUREQ) {
+ return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_RAU_REQ(valueof(mi), GPRS_UPD_T_PERIODIC,
+ f_RAI('001'H, '01'H, '2a2a'O, '17'O),
+ nri := nri)));
+ }
+ if (compl3type == DETREQ) {
+ return enc_PDU_L3_MS_SGSN(valueof(ts_GMM_DET_REQ_MO_mi(c_GMM_DTT_MO_GPRS, power_off := false,
+ p_tmsi := valueof(ts_MI_TLV(mi.mobileIdentityV)))));
+ }
+
+ setverdict(fail, "unknown complete layer 3 type");
+ mtc.stop;
+}
+
+type record of Compl3Type ro_Compl3Type;
+type record of MobileIdentityLV ro_MobileIdentityLV;
+type record of octetstring ro_octetstring;
+
+/* Generate a list of n Complete Layer 3 NAS PDUs,
+ * rotating through the message kinds listed in 'types' and the mobile identities in mis.
+ */
+private function f_gen_compl_l3(ro_Compl3Type types, ro_MobileIdentityLV mis, integer n) return ro_octetstring
+{
+ var ro_octetstring res := {};
+ for (var integer i := 0; i < n; i := i + 1) {
+ var integer ti := i mod lengthof(types);
+ var integer mi := i mod lengthof(mis);
+ res[i] := f_gen_one_compl_l3(types[ti], mis[mi]);
+ }
+ return res;
+}
+
+private function f_gen_mi_imsi(integer n) return MobileIdentityLV
+{
+ return valueof(ts_MI_IMSI_LV(f_gen_imsi(n)));
+}
+
+private function f_gen_mi_imsis(integer n) return ro_MobileIdentityLV
+{
+ var ro_MobileIdentityLV mis := {};
+ for (var integer i := 0; i < n; i := i + 1) {
+ mis[i] := f_gen_mi_imsi(n);
+ }
+ return mis;
+}
+
+function f_vty_set_roundrobin_next(TELNETasp_PT VTY, boolean ps_domain, integer cn_nr)
+{
+ var charstring msc_sgsn;
+ if (ps_domain) {
+ msc_sgsn := "sgsn";
+ } else {
+ msc_sgsn := "msc";
+ }
+ f_vty_transceive(VTY, "cnpool roundrobin next " & msc_sgsn & " " & int2str(cn_nr));
+}
+
+private function f_gen_compl3_by_domain(boolean ps_domain, integer n, template (omit) ro_MobileIdentityLV mis := omit) return ro_octetstring{
+ var ro_Compl3Type types;
+ if (ps_domain) {
+ types := { ATTACHREQ, RAUREQ, DETREQ };
+ } else {
+ types := { LU, CMSERV, PAGRESP, IMSIDETACH };
+ }
+ if (istemplatekind(mis, "omit")) {
+ mis := f_gen_mi_imsis(n);
+ }
+ return f_gen_compl_l3(types, valueof(mis), n);
+}
+
+/* Various Complete Layer 3 by IMSI all end up with the first MSC, because the other MSCs are not connected. */
+testcase TC_mscpool_L3Compl_on_1_cnlink() runs on test_CT {
+ f_TC_cnpool_L3Compl_on_1_cnlink(ps_domain := false);
+}
+testcase TC_sgsnpool_L3Compl_on_1_cnlink() runs on test_CT {
+ f_TC_cnpool_L3Compl_on_1_cnlink(ps_domain := true);
+}
+function f_TC_cnpool_L3Compl_on_1_cnlink(boolean ps_domain) runs on test_CT {
+
+ f_init();
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 4);
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3, {0, 0, 0, 0}, "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* Three Layer 3 Complete by IMSI are round-robin'ed across two connected MSCs */
+testcase TC_mscpool_L3Complete_by_imsi_round_robin() runs on test_CT {
+ f_TC_cnpool_L3Complete_by_imsi_round_robin(ps_domain := false);
+}
+testcase TC_sgsnpool_L3Complete_no_nri_round_robin() runs on test_CT {
+ f_TC_cnpool_L3Complete_by_imsi_round_robin(ps_domain := true);
+}
+function f_TC_cnpool_L3Complete_by_imsi_round_robin(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
+
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3,
+ /* Third Complete Layer 3 wraps back to msc 0 */
+ cn_nrs := {0, 1, 0},
+ inc_countername := "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* Three LU by TMSI are round-robin'ed across two connected MSCs, because they contain a NULL-NRI (0, 1)
+ * (configured in osmo-hnbgw.cfg). */
+testcase TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() runs on test_CT {
+ f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(ps_domain := false, nri_val := 0);
+}
+/* For NRI == 1, one of the MSC also has the NULL-NRI as part of its owned NRIs, but the NULL-NRI setting is stronger
+ * than that. */
+testcase TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() runs on test_CT {
+ f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(ps_domain := false, nri_val := 1);
+}
+function f_TC_cnpool_LU_by_tmsi_null_nri_N_round_robin(boolean ps_domain, integer nri_val) runs on test_CT {
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_MobileIdentityLV mis := { valueof(ts_MI_TMSI_NRI_LV(nri_val)) };
+ var ro_octetstring compl3;
+ if (ps_domain) {
+ compl3 := {
+ f_gen_one_compl_l3(ATTACHREQ, mis[0], nri_val)
+ };
+ } else {
+ compl3 := f_gen_compl_l3({LU}, mis, 1);
+ }
+
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3,
+ /* The third Complete Layer 3 wraps back to msc 0 */
+ {0, 1, 0},
+ "cnpool:subscr:reattach");
+ f_shutdown_helper();
+}
+
+/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI not
+ * assigned to any MSC (configured in osmo-hnbgw.cfg). */
+testcase TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() runs on test_CT {
+ f_TC_cnpool_L3Complete_by_tmsi_unassigned_nri_round_robin(ps_domain := false);
+}
+function f_TC_cnpool_L3Complete_by_tmsi_unassigned_nri_round_robin(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ /* 3 NRIs that are not assigned to any MSC */
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(1000)),
+ valueof(ts_MI_TMSI_NRI_LV(768)),
+ valueof(ts_MI_TMSI_NRI_LV(819))
+ };
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3, { 0, 1, 0 }, "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* Three Layer 3 Complete by TMSI are round-robin'ed across two connected MSCs, because they contain an NRI
+ * assigned to a CN link that is currently not connected (configured in osmo-hnbgw.cfg). */
+testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() runs on test_CT {
+ f_TC_cnpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin(ps_domain := false);
+}
+function f_TC_cnpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ /* 3 NRIs that are assigned to an unconnected MSC */
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(512)),
+ valueof(ts_MI_TMSI_NRI_LV(767)),
+ valueof(ts_MI_TMSI_NRI_LV(750))
+ };
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
+
+ f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0);
+ f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
+ f_ctrs_cn_add(0, "cnpool:subscr:new");
+ f_ctrs_cn_verify();
+
+ f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 1);
+ f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
+ f_ctrs_cn_add(1, "cnpool:subscr:new");
+ f_ctrs_cn_verify();
+
+ f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 0);
+ f_ctrs_cn_add(2, "cnpool:subscr:attach_lost");
+ f_ctrs_cn_add(0, "cnpool:subscr:new");
+ f_ctrs_cn_verify();
+
+ f_shutdown_helper();
+}
+
+/* Three Layer 3 Complete by TMSI with valid NRI for the second MSC are all directed to the second MSC (configured in
+ * osmo-hnbgw.cfg). */
+testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_1() runs on test_CT {
+ f_TC_cnpool_L3Complete_valid_nri_1(ps_domain := false);
+}
+testcase TC_sgsnpool_L3Complete_valid_nri_1() runs on test_CT {
+ f_TC_cnpool_L3Complete_valid_nri_1(ps_domain := true);
+}
+function f_TC_cnpool_L3Complete_valid_nri_1(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* All TMSIs in this test point at the second MSC, set the round robin to point at the first MSC to make sure
+ * this is not using round-robin. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3;
+
+ /* 3 NRIs of the second MSC's range (256-511) */
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(256)),
+ valueof(ts_MI_TMSI_NRI_LV(260)),
+ valueof(ts_MI_TMSI_NRI_LV(511))
+ };
+ if (ps_domain) {
+ compl3 := {
+ f_gen_one_compl_l3(RAUREQ, mis[0], 256),
+ f_gen_one_compl_l3(RAUREQ, mis[1], 260),
+ f_gen_one_compl_l3(RAUREQ, mis[2], 511)
+ };
+ } else {
+ compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
+ }
+
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3, {1, 1, 1}, "cnpool:subscr:known");
+
+ f_shutdown_helper();
+}
+
+/* Layer 3 Complete by TMSI with valid NRI for the third MSC are directed to the third MSC (configured in osmo-hnbgw.cfg),
+ * while a round-robin remains unaffected by that. */
+testcase TC_mscpool_L3Complete_by_tmsi_valid_nri_2() runs on test_CT {
+ f_TC_cnpool_L3Complete_valid_nri_2(ps_domain := false);
+}
+testcase TC_sgsnpool_L3Complete_valid_nri_2() runs on test_CT {
+ f_TC_cnpool_L3Complete_valid_nri_2(ps_domain := true);
+}
+function f_TC_cnpool_L3Complete_valid_nri_2(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 3, nr_sgsn := 3);
+ f_sleep(1.0);
+
+ /* All TMSIs in this test point at the third MSC, set the round robin to point at the second MSC to make sure
+ * this is not using round-robin. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 1);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3;
+
+ /* 2 NRIs of the third MSC's range (512-767) */
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(512)),
+ valueof(ts_MI_TMSI_NRI_LV(678))
+ };
+ if (ps_domain) {
+ compl3 := {
+ f_gen_one_compl_l3(ATTACHREQ, mis[0], 512),
+ f_gen_one_compl_l3(ATTACHREQ, mis[1], 678)
+ };
+ } else {
+ compl3 := f_gen_compl3_by_domain(ps_domain, 2, mis);
+ }
+
+ f_TC_cnpool_compl_l3_list(ps_domain, compl3, {2, 2}, "cnpool:subscr:known");
+
+ /* The above forwardings to third MSC have not affected the round robin, which still points at the second MSC */
+ f_TC_cnpool_compl_l3_list(ps_domain, f_gen_compl3_by_domain(ps_domain, 1), {1}, "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* LU with a TMSI but indicating a different PLMN in its previous LAI: ignore the NRI. */
+testcase TC_mscpool_LU_by_tmsi_from_other_PLMN() runs on test_CT {
+ f_TC_cnpool_nri_from_other_PLMN(ps_domain := false);
+}
+testcase TC_sgsnpool_nri_from_other_PLMN() runs on test_CT {
+ f_TC_cnpool_nri_from_other_PLMN(ps_domain := true);
+}
+function f_TC_cnpool_nri_from_other_PLMN(boolean ps_domain) runs on test_CT {
+
+ f_init(nr_msc := 3, nr_sgsn := 3);
+ f_sleep(1.0);
+
+ /* The TMSIs in this test points at the second MSC, but since it is from a different PLMN, round-robin is used
+ * instead, and hits msc 0. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3;
+
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(260)),
+ valueof(ts_MI_TMSI_NRI_LV(555))
+ };
+ if (ps_domain) {
+ compl3 := {
+ /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-hnbgw.cfg */
+ enc_PDU_L3_MS_SGSN(valueof(ts_GMM_ATTACH_REQ(mis[0], f_RAI('999'H, '99'H, '2a2a'O,
+ '17'O),
+ nri := ts_GMM_NRI(260)
+ ))),
+ /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
+ f_gen_one_compl_l3(ATTACHREQ, mis[1], 555)
+ }
+ } else {
+ compl3 := {
+ /* An NRI of the second MSC's range (256-511), but a PLMN that doesn't match with osmo-hnbgw.cfg */
+ enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, mis[0], '99F999'O))),
+ /* An NRI of the third MSC's range (512-767) and a matching PLMN gets directed by NRI. */
+ enc_PDU_ML3_MS_NW(valueof(ts_LU_REQ(LU_Type_IMSI_Attach, mis[1], '00F110'O)))
+ };
+ }
+
+ /* Foreign NRI: roundrobin */
+ f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
+
+ /* Local NRI: matching msc */
+ f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 2, inc_countername := "cnpool:subscr:known");
+
+ f_shutdown_helper();
+}
+
+/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by IMSI, which would be
+ * round-robined to another MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
+friend function f_tc_mscpool_paging_imsi(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+
+ var hexstring imsi := '001010000000123'H;
+ var RANAP_IEs.CN_DomainIndicator domain_ind;
+ if (pars.ps_domain) {
+ domain_ind := ps_domain;
+ } else {
+ domain_ind := cs_domain;
+ }
+ var template (value) RANAP_PDU paging := ts_RANAP_Paging(domain_ind, imsi_hex2oct(imsi));
+ BSSAP.send(ts_RANAP_UNITDATA_req(pars.sccp_addr_hnbgw, pars.sccp_addr_msc, paging));
+ /* TODO: Expect RUA ConnectionlessTransfer Paging (on all HNB).
+ * We could verify the Paging sent from osmo-hnbgw to RUA with some effort,
+ * but, this test does not care whether the Paging was forwarded to RUA or not, only that osmo-hnbgw *received*
+ * the Paging. In the CN pool decisions, osmo-hnbgw should match up Paging Response to an earlier Paging.
+ */
+
+ f_sleep(1.0);
+
+ /* Despite the round robin pointing at the second MSC ('roundrobin next msc 1'), the earlier Paging for the same IMSI
+ * causes this Paging Response to go to the first MSC ('msc 0'). */
+ f_perform_compl_l3(f_gen_one_compl_l3(PAGRESP, ts_MI_IMSI_LV(imsi)));
+ f_sleep(1.0);
+}
+
+testcase TC_mscpool_paging_imsi() runs on test_CT {
+ f_init(nr_msc := 3);
+ f_sleep(1.0);
+
+ var boolean ps_domain := false;
+
+ /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
+ * second MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ConnHdlr vc_conn1;
+ var template (value) TestHdlrParams pars1 := t_pars(0, ps_domain := ps_domain, cn_nr := 0);
+ pars1.sccp_addr_hnbgw := g_cn[valueof(pars1.cn_idx)].sccp_addr_peer;
+ pars1.sccp_addr_msc := g_cn[valueof(pars1.cn_idx)].sccp_addr_own;
+ vc_conn1 := f_start_handler_with_pars(refers(f_tc_mscpool_paging_imsi), pars1);
+ vc_conn1.done;
+ f_ctrs_cn_expect(0, "cnpool:subscr:paged");
+ f_shutdown_helper();
+}
+
+/* Make sure that whichever MSC paged a subscriber will also get the Paging Response. Page by TMSI with an NRI value
+ * that matches a different MSC, to make sure the Paging->Response relation is stronger than the NRI->MSC mapping. */
+friend function f_tc_mscpool_paging_tmsi(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ f_init_handler(pars);
+
+ var hexstring imsi := '001010000000124'H;
+ var integer nri_v := 300; /* <-- second MSC's NRI */
+ var octetstring tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v);
+
+ var RANAP_IEs.CN_DomainIndicator domain_ind;
+ if (pars.ps_domain) {
+ domain_ind := ps_domain;
+ } else {
+ domain_ind := cs_domain;
+ }
+ var template (value) RANAP_PDU paging := ts_RANAP_Paging_temp_id(domain_ind, imsi_hex2oct(imsi),
+ ts_RANAP_TemporaryUE_ID_TMSI(tmsi));
+ BSSAP.send(ts_RANAP_UNITDATA_req(pars.sccp_addr_hnbgw, pars.sccp_addr_msc, paging));
+ /* TODO: Expect RUA ConnectionlessTransfer Paging (on all HNB).
+ * We could verify the Paging sent from osmo-hnbgw to RUA with some effort,
+ * but, this test does not care whether the Paging was forwarded to RUA or not, only that osmo-hnbgw *received*
+ * the Paging. In the CN pool decisions, osmo-hnbgw should match up Paging Response to an earlier Paging.
+ */
+
+ f_sleep(1.0);
+
+ /* Despite the round robin pointing at the third MSC ('roundrobin next msc 2'), the earlier Paging for the same
+ * TMSI causes this Paging Response to go to the first MSC ('msc 0'). */
+ f_perform_compl_l3(f_gen_one_compl_l3(PAGRESP, ts_MI_TMSI_NRI_LV(nri_v)));
+ f_sleep(1.0);
+}
+testcase TC_mscpool_paging_tmsi() runs on test_CT {
+ f_init(nr_msc := 3);
+ f_sleep(1.0);
+
+ var boolean ps_domain := false;
+
+ /* Testing a Paging on the first MSC to get a Paging Response back to the first MSC. Set round robin to the
+ * third MSC to make sure we're getting the Paging logic, not a coincidental round robin match. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ConnHdlr vc_conn1;
+ var template (value) TestHdlrParams pars1 := t_pars(0, ps_domain := ps_domain, cn_nr := 0);
+ pars1.sccp_addr_hnbgw := g_cn[valueof(pars1.cn_idx)].sccp_addr_peer;
+ pars1.sccp_addr_msc := g_cn[valueof(pars1.cn_idx)].sccp_addr_own;
+ vc_conn1 := f_start_handler_with_pars(refers(f_tc_mscpool_paging_tmsi), pars1);
+ vc_conn1.done;
+ f_ctrs_cn_expect(0, "cnpool:subscr:paged");
+ f_shutdown_helper();
+}
+
+/* For round-robin, skip a CN link that has 'no allow-attach' set. */
+testcase TC_mscpool_no_allow_attach_round_robin() runs on test_CT {
+
+ f_init(nr_msc := 3);
+ f_sleep(1.0);
+
+ var boolean ps_domain := false;
+
+ /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
+ f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, {true, false, true});
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ f_TC_cnpool_compl_l3_list(ps_domain, f_gen_compl3_by_domain(ps_domain, 3),
+ /* msc 1 is skipped */
+ {0, 2, 0},
+ "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* An MSC that has 'no allow-attach' set should still serve subscribers that are already attached according to their
+ * TMSI NRI. */
+testcase TC_mscpool_no_allow_attach_valid_nri() runs on test_CT {
+
+ f_init(nr_msc := 3);
+ f_sleep(1.0);
+
+ var boolean ps_domain := false;
+
+ /* Mark the second MSC as offloading, round-robin should skip this MSC now. */
+ f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, {true, false, true});
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_MobileIdentityLV mis := {
+ valueof(ts_MI_TMSI_NRI_LV(260)),
+ valueof(ts_MI_IMSI_LV('001010000000002'H)),
+ valueof(ts_MI_IMSI_LV('001010000000003'H))
+ };
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3, mis);
+
+ /* Round robin points at msc 0, but the valid NRI directs to msc 1, even though msc 1 has 'no allow-attach'. */
+ f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 1, inc_countername := "cnpool:subscr:known");
+
+ /* Normal round robin skips msc 1, because it has 'no allow-attach' */
+ f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 0, inc_countername := "cnpool:subscr:new");
+ f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 2, inc_countername := "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* When a peer point-code gets an SCCP N-PCSTATE saying it is unreachable, immediately mark the CN link as unusable. */
+testcase TC_mscpool_sccp_n_pcstate_detaches_cnlink() runs on test_CT {
+ f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(ps_domain := false);
+}
+testcase TC_sgsnpool_sccp_n_pcstate_detaches_cnlink() runs on test_CT {
+ f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(ps_domain := true);
+}
+function f_TC_cnpool_sccp_n_pcstate_detaches_cnlink(boolean ps_domain) runs on test_CT
+{
+
+ f_init(nr_msc := 2, nr_sgsn := 2);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
+
+ f_TC_cnpool_compl_l3(ps_domain, compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
+ f_TC_cnpool_compl_l3(ps_domain, compl3[1], cn_nr := 1, inc_countername := "cnpool:subscr:new");
+
+ f_logp(HNBGWVTY, "disconnecting msc0");
+ f_cn_idx_disconnect(f_cn_idx(ps_domain, 0));
+
+ /* Now round-robin would wrap to the first MSC, but since the first MSC is disconnected, it wraps around to the
+ * second. */
+ f_TC_cnpool_compl_l3(ps_domain, compl3[2], cn_nr := 1, inc_countername := "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+/* When a CN link point-code gets an SCCP N-PCSTATE saying it is now reachable, immediately trigger RESET and bring up the
+ * MSC. */
+testcase TC_mscpool_sccp_n_pcstate_attaches_cnlink() runs on test_CT {
+ f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(ps_domain := false);
+}
+testcase TC_sgsnpool_sccp_n_pcstate_attaches_cnlink() runs on test_CT {
+ f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(ps_domain := true);
+}
+function f_TC_cnpool_sccp_n_pcstate_attaches_cnlink(boolean ps_domain) runs on test_CT
+{
+ f_init(nr_msc := 1, nr_sgsn := 1);
+ f_sleep(1.0);
+
+ /* Control which MSC gets chosen next by the round-robin, otherwise
+ * would be randomly affected by which other tests ran before this. */
+ f_vty_set_roundrobin_next(HNBGWVTY, ps_domain, 0);
+
+ var ro_octetstring compl3 := f_gen_compl3_by_domain(ps_domain, 3);
+
+ f_ctrs_cn_init(ps_domain := ps_domain);
+
+ /* There is only one MSC, round robin stays on msc0 */
+ f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[0], cn_nr := 0, inc_countername := "cnpool:subscr:new");
+ f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[1], cn_nr := 0, inc_countername := "cnpool:subscr:new");
+
+ f_logp(HNBGWVTY, "connecting cnlink 1");
+ f_cn_nr_init(ps_domain, 1);
+ f_vty_cnlink_allow_attach(HNBGWVTY, ps_domain, { true, true });
+ f_sleep(1.0);
+
+ /* This time round-robin wraps to the second MSC, because it is now online. */
+ f_TC_cnpool_compl_l3(ps_domain := ps_domain, nas_pdu := compl3[2], cn_nr := 1, inc_countername := "cnpool:subscr:new");
+
+ f_shutdown_helper();
+}
+
+private function f_vty_add_sccp_addr(TELNETasp_PT pt, charstring addr_name, charstring pc, integer cs7_nr := 0)
+{
+ f_vty_enter_config(pt);
+ f_vty_transceive(pt, "cs7 instance 0");
+ f_vty_transceive(pt, "sccp-address " & addr_name);
+ f_vty_transceive(pt, "point-code " & pc);
+ f_vty_transceive(pt, "end");
+}
+
+private function f_vty_set_cnlink_addr(TELNETasp_PT pt, charstring cnlink_and_nr, charstring addr_name)
+{
+ f_vty_enter_config(pt);
+ f_vty_transceive(pt, cnlink_and_nr);
+ f_vty_transceive(pt, "remote-addr " & addr_name);
+ f_vty_transceive(pt, "end");
+}
+
+private function f_vty_apply_sccp(TELNETasp_PT pt)
+{
+ f_vty_enter_config(pt);
+ f_vty_transceive(pt, "apply sccp");
+ f_vty_transceive(pt, "end");
+}
+
+template (present) RUA_Disc_Req tr_RUA_Disc_Req := {
+ ranap := ?,
+ cause := ?
+};
+
+/* With a cnlink up, change the SCCP address, and verify that it restarts upon vty 'apply sccp' */
+private function f_tc_apply_sccp(charstring id, TestHdlrParams pars) runs on ConnHdlr
+{
+ f_init_handler(pars);
+ f_perform_compl_l3(f_gen_compl3_by_domain(pars.ps_domain, 1)[0]);
+
+ f_sleep(1.0);
+ f_logp(HNBGWVTY, "Changing SCCP address, don't apply yet");
+
+ f_vty_add_sccp_addr(HNBGWVTY, "msc-foo", "0.42.4");
+ f_vty_set_cnlink_addr(HNBGWVTY, "msc 0", "msc-foo");
+
+ /* No effect yet, link still open both ways */
+ f_sleep(1.0);
+ f_iuh2iu(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+ f_iu2iuh(ts_RANAP_DirectTransfer(f_rnd_octstring(10)));
+
+ f_logp(HNBGWVTY, "Apply SCCP address changes");
+ f_vty_apply_sccp(HNBGWVTY);
+
+ /* We modified the SCCP configuration, expect disconnect of UE that was active on the aborted link. */
+ RUA.receive(RUA_Disc_Ind:?);
+ BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
+
+ /* Would be nice to test reconnection on the other point-code, too. That would require another cnlink in
+ * osmo-stp.cfg and module parameters... */
+
+ f_sleep(1.0);
+}
+testcase TC_apply_sccp() runs on test_CT
+{
+ f_init();
+ f_sleep(1.0);
+
+ var ConnHdlr vc_conn;
+ var template (value) TestHdlrParams pars := t_pars(0);
+ vc_conn := f_start_handler_with_pars(refers(f_tc_apply_sccp), pars);
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+/* In the field, we encountered a "normal" RAB Assignment that concludes successfully, followed by another RAB
+ * Assignment that has different SDU subflow parameters, and does not contain RTP information. At the time of writing,
+ * it seems that the second RAB Assignment causes a crash. Play through this scenario. */
+friend function f_tc_second_rab_assignment(charstring id, TestHdlrParams pars) runs on ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ var RANAP_PDU tx;
+ timer T := 5.0;
+
+ f_init_handler(pars);
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+
+ tx := f_build_initial_ue(g_pars);
+ f_iuh2iu_connect(tx);
+
+ f_create_rab(pars.mgcp_pars);
+
+ /* Now send a second RAB Assignment with different subflows and omitting transportLayerInformation. (Assuming
+ * the first RAB Assignment's transportLayerInformation remains in use unchanged.) */
+ var template RAB_SetupOrModifyList rab_sml;
+ rab_sml := ts_RAB_SML2(t_RAB_id(23),
+ ts_RabParams,
+ user_plane_info := omit,
+ transport_layer_info := omit);
+ tx := valueof(ts_RANAP_RabAssReq(rab_sml));
+ BSSAP.send(tx);
+ T.start;
+
+ /* Expect this secondary RAB Assignment to go through unchanged. */
+ f_rua_expect(tx);
+
+ /* I'm guessing that the RAB Assignment Response also omits transportLayerInformation, so far not known because
+ * osmo-hnbgw crashed before we could receive the response. */
+
+ /* Send back RAB Assignment Response via Iuh */
+ var template RAB_SetupOrModifiedList rab_smdl;
+ rab_smdl := ts_RAB_SMdL_no_tla(t_RAB_id(23));
+ tx := valueof(ts_RANAP_RabAssResp(rab_smdl));
+ RUA.send(tx);
+ f_bssap_expect(tx);
+
+ /* Send Iu Release */
+ tx := valueof(ts_RANAP_IuReleaseCommand(pars.rab_rel_cause));
+ f_iu2iuh(tx);
+
+ T.start;
+ alt {
+ [] as_mgcp_dlcx(pars) {}
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for DLCX");
+ }
+ }
+
+ tx := valueof(ts_RANAP_IuReleaseComplete());
+ f_iuh2iu(tx);
+}
+
+testcase TC_second_rab_assignment() runs on test_CT {
+ var ConnHdlr vc_conn;
+ g_num_hnbs := 1;
+ f_init();
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_second_rab_assignment), t_pars(3));
+ vc_conn.done;
+
+ f_shutdown_helper();
+}
+
+control {
+ execute(TC_hnb_register());
+ execute(TC_hnb_register_duplicate());
+ execute(TC_hnb_register_duplicate_reuse_sctp_assoc());
+ execute(TC_ue_register());
+ execute(TC_ue_register_tmsi_lai());
+ execute(TC_ue_register_before_hnb_register());
+ execute(TC_ranap_cs_initial_ue());
+ execute(TC_ranap_ps_initial_ue());
+ execute(TC_ranap_cs_initial_ue_empty_cr());
+ execute(TC_ranap_ps_initial_ue_empty_cr());
+ execute(TC_ranap_cs_bidir());
+ execute(TC_ranap_ps_bidir());
+ execute(TC_rab_assignment());
+ execute(TC_rab_release());
+ execute(TC_rab_release_abnormal());
+ execute(TC_rab_assign_fail());
+ execute(TC_rab_assign_mgcp_to());
+ execute(TC_rab_assign_mgw_iuup_addr_chg());
+ execute(TC_ranap_cs_mo_disconnect());
+ execute(TC_ranap_ps_mo_disconnect());
+
+ if (mp_enable_pfcp_tests) {
+ execute(TC_ps_rab_assignment_with_pfcp());
+ } else {
+ execute(TC_ps_rab_assignment_without_pfcp());
+ }
+
+ execute( TC_mscpool_L3Compl_on_1_cnlink() );
+ execute( TC_mscpool_L3Complete_by_imsi_round_robin() );
+ execute( TC_mscpool_LU_by_tmsi_null_nri_0_round_robin() );
+ execute( TC_mscpool_LU_by_tmsi_null_nri_1_round_robin() );
+ execute( TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin() );
+ execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin() );
+ execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_1() );
+ execute( TC_mscpool_L3Complete_by_tmsi_valid_nri_2() );
+ execute( TC_mscpool_LU_by_tmsi_from_other_PLMN() );
+ execute( TC_mscpool_paging_imsi() );
+ execute( TC_mscpool_paging_tmsi() );
+ execute( TC_mscpool_no_allow_attach_round_robin() );
+ execute( TC_mscpool_no_allow_attach_valid_nri() );
+ execute( TC_mscpool_sccp_n_pcstate_detaches_cnlink() );
+ execute( TC_mscpool_sccp_n_pcstate_attaches_cnlink() );
+
+ execute( TC_sgsnpool_L3Compl_on_1_cnlink() );
+ execute( TC_sgsnpool_L3Complete_no_nri_round_robin() );
+ execute( TC_sgsnpool_L3Complete_valid_nri_1() );
+ execute( TC_sgsnpool_L3Complete_valid_nri_2() );
+ execute( TC_sgsnpool_nri_from_other_PLMN() );
+ execute( TC_sgsnpool_sccp_n_pcstate_detaches_cnlink() );
+ execute( TC_sgsnpool_sccp_n_pcstate_attaches_cnlink() );
+
+ /* Run only on nightly since it makes osmo-hnbgw <= 1.5.0 crash: OS#6253 */
+ if (f_osmo_repo_is("nightly")) {
+ execute(TC_second_rab_assignment());
+ }
+
+ /* Run at the end since it makes osmo-hnbgw <= 1.3.0 crash: OS#5676 */
+ execute(TC_hnb_reregister_reuse_sctp_assoc());
+
+ /* Run at the end since it messes with the SCCP config */
+ execute( TC_apply_sccp() );
+}
+
+}
diff --git a/hnbgw/expected-results.xml b/hnbgw/expected-results.xml
new file mode 100644
index 00000000..5f39bc5c
--- /dev/null
+++ b/hnbgw/expected-results.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='42' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='HNBGW_Tests' name='TC_hnb_register' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_hnb_register_duplicate' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_hnb_register_duplicate_reuse_sctp_assoc' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ue_register' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ue_register_tmsi_lai' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ue_register_before_hnb_register' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_release_abnormal' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_cs_initial_ue' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_ps_initial_ue' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_cs_initial_ue_empty_cr' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_ps_initial_ue_empty_cr' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_cs_bidir' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_ps_bidir' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_assignment' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_release' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_release_abnormal' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_assign_fail' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_assign_mgcp_to' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_rab_assign_mgw_iuup_addr_chg' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_cs_mo_disconnect' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ranap_ps_mo_disconnect' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_ps_rab_assignment_without_pfcp' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Compl_on_1_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Complete_by_imsi_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_LU_by_tmsi_null_nri_0_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_LU_by_tmsi_null_nri_1_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Complete_by_tmsi_unassigned_nri_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_msc_not_connected_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_1' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_L3Complete_by_tmsi_valid_nri_2' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_LU_by_tmsi_from_other_PLMN' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_paging_imsi' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_paging_tmsi' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_no_allow_attach_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_no_allow_attach_valid_nri' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_sccp_n_pcstate_detaches_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_mscpool_sccp_n_pcstate_attaches_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_L3Compl_on_1_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_L3Complete_no_nri_round_robin' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_L3Complete_valid_nri_1' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_L3Complete_valid_nri_2' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_nri_from_other_PLMN' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_sccp_n_pcstate_detaches_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_sgsnpool_sccp_n_pcstate_attaches_cnlink' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_second_rab_assignment' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_hnb_reregister_reuse_sctp_assoc' time='MASKED'/>
+ <testcase classname='HNBGW_Tests' name='TC_apply_sccp' time='MASKED'/>
+</testsuite>
diff --git a/hnbgw/gen_links.sh b/hnbgw/gen_links.sh
new file mode 100755
index 00000000..62b3e44d
--- /dev/null
+++ b/hnbgw/gen_links.sh
@@ -0,0 +1,110 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+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 " # GSM 7-bit 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.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
+gen_links $DIR $FILES
+
+# Required by MGCP and IPA
+# Required by PFCP/UDP
+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
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.ProtocolEmulations.M3UA/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.TestPorts.MTP3asp/src
+FILES="MTP3asp_PortType.ttcn MTP3asp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolEmulations.SCCP/src
+FILES="SCCP_Emulation.ttcn SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.BSSMAP/src
+FILES="BSSAP_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.ProtocolModules.M3UA/src
+FILES="M3UA_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.ProtocolEmulations.M3UA/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SDP/src
+FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
+SDP_parser.y lex.SDP_parse_.c"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.PFCP_v15.1.0/src
+FILES="PFCP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library/hnbap
+FILES="HNBAP_CommonDataTypes.asn HNBAP_Constants.asn HNBAP_Containers.asn HNBAP_IEs.asn HNBAP_PDU_Contents.asn HNBAP_PDU_Descriptions.asn "
+FILES+="HNBAP_EncDec.cc HNBAP_Types.ttcn HNBAP_Templates.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library/rua
+FILES="RUA_CommonDataTypes.asn RUA_Constants.asn RUA_Containers.asn RUA_IEs.asn RUA_PDU_Contents.asn RUA_PDU_Descriptions.asn "
+FILES+="RUA_EncDec.cc RUA_Types.ttcn RUA_Templates.ttcn RUA_Emulation.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library/ranap
+FILES="RANAP_CommonDataTypes.asn RANAP_Constants.asn RANAP_Containers.asn RANAP_IEs.asn RANAP_PDU_Contents.asn RANAP_PDU_Descriptions.asn "
+FILES+="RANAP_Types.ttcn RANAP_Templates.ttcn RANAP_CodecPort.ttcn RANAP_EncDec.cc "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Iuh_Types.ttcn Iuh_CodecPort.ttcn Iuh_CodecPort_CtrlFunctDef.cc Iuh_CodecPort_CtrlFunct.ttcn Iuh_Emulation.ttcn DNS_Helpers.ttcn "
+FILES+="SDP_Templates.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc "
+FILES+="RAN_Adapter.ttcnpp RAN_Emulation.ttcnpp BSSAP_CodecPort.ttcn SCCP_Templates.ttcn "
+FILES+="PFCP_CodecPort.ttcn PFCP_CodecPort_CtrlFunct.ttcn PFCP_CodecPort_CtrlFunctDef.cc PFCP_Emulation.ttcn PFCP_Templates.ttcn "
+FILES+="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="L3_Templates.ttcn L3_Common.ttcn "
+
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/hnbgw/osmo-hnbgw-with-pfcp.cfg b/hnbgw/osmo-hnbgw-with-pfcp.cfg
new file mode 100644
index 00000000..ffe5e091
--- /dev/null
+++ b/hnbgw/osmo-hnbgw-with-pfcp.cfg
@@ -0,0 +1,133 @@
+!
+! OsmoHNBGW (1.1.0) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category-hex 0
+ logging print category 1
+ logging print thread-id 0
+ logging print extended-timestamp 1
+ logging print level 1
+ logging print file basename last
+ logging level set-all debug
+ logging level ranap info
+ logging level rua info
+ logging level lss7 error
+ logging level lm3ua error
+ logging level linp error
+ logging level lpfcp info
+ logging level lsua notice
+ logging level lsccp notice
+!
+line vty
+ no login
+!
+cs7 instance 0
+ point-code 0.23.5
+
+ sccp-address msc-naught
+ routing-indicator PC
+ point-code 0.23.4
+
+ sccp-address msc-one
+ routing-indicator PC
+ point-code 0.0.2
+
+ sccp-address msc-two
+ routing-indicator PC
+ point-code 0.0.3
+
+ sccp-address msc-three
+ routing-indicator PC
+ point-code 0.0.4
+
+ sccp-address sgsn-naught
+ routing-indicator PC
+ point-code 0.23.1
+
+ sccp-address sgsn-one
+ routing-indicator PC
+ point-code 0.1.2
+
+ sccp-address sgsn-two
+ routing-indicator PC
+ point-code 0.1.3
+
+ sccp-address sgsn-three
+ routing-indicator PC
+ point-code 0.1.4
+
+hnbgw
+ log-prefix hnb-id
+ iuh
+ local-ip 127.0.0.1
+ local-port 29169
+ hnbap-allow-tmsi 1
+ pfcp
+ remote-addr 127.0.0.1
+ local-addr 127.0.0.2
+ local-port 8805
+ timer pfcp x26 5
+ # reduce default X31 from 15 seconds
+ # https://gerrit.osmocom.org/c/osmo-hnbgw/+/34922
+ timer hnbgw X31 5
+
+msc 0
+ remote-addr msc-naught
+
+msc 1
+ remote-addr msc-one
+
+msc 2
+ remote-addr msc-two
+
+msc 3
+ remote-addr msc-three
+
+sgsn 0
+ remote-addr sgsn-naught
+
+sgsn 1
+ remote-addr sgsn-one
+
+sgsn 2
+ remote-addr sgsn-two
+
+sgsn 3
+ remote-addr sgsn-three
+
+hnbgw
+ iucs
+ nri bitlen 10
+ # a NULL NRI that is outside the NRI ranges used by the MSCs:
+ nri null add 0
+ # a NULL NRI that is also used by an MSC:
+ nri null add 1
+msc 0
+ nri add 1 255
+msc 1
+ nri add 256 511
+msc 2
+ nri add 512 767
+ # range 768-1000 is not assigned to any MSC on purpose
+msc 3
+ nri add 1001 1023
+
+hnbgw
+ iups
+ nri bitlen 10
+ # a NULL NRI that is outside the NRI ranges used by the SGSNs:
+ nri null add 0
+ # a NULL NRI that is also used by an SGSN:
+ nri null add 1
+sgsn 0
+ nri add 1 255
+sgsn 1
+ nri add 256 511
+sgsn 2
+ nri add 512 767
+ # range 768-1000 is not assigned to any SGSN on purpose
+sgsn 3
+ nri add 1001 1023
diff --git a/hnbgw/osmo-hnbgw.cfg b/hnbgw/osmo-hnbgw.cfg
new file mode 100644
index 00000000..2ed6905c
--- /dev/null
+++ b/hnbgw/osmo-hnbgw.cfg
@@ -0,0 +1,147 @@
+!
+! OsmoHNBGW (1.1.0) configuration saved from vty
+!!
+!
+log gsmtap 127.0.0.1
+ logging level set-all debug
+ logging filter all 1
+!
+log stderr
+ logging filter all 1
+ logging color 0
+ logging print category-hex 0
+ logging print category 1
+ logging print level 1
+ logging print thread-id 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging level set-all debug
+!
+line vty
+ no login
+ bind 0.0.0.0
+ctrl
+ bind 0.0.0.0
+!
+
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
+
+cs7 instance 0
+ asp asp-clnt-msc-0 2905 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.2
+ role asp
+ sctp-role client
+ point-code 0.23.5
+ sccp-address msc-naught
+ routing-indicator PC
+ point-code 0.23.4
+
+ sccp-address msc-one
+ routing-indicator PC
+ point-code 0.0.2
+
+ sccp-address msc-two
+ routing-indicator PC
+ point-code 0.0.3
+
+ sccp-address msc-three
+ routing-indicator PC
+ point-code 0.0.4
+
+ sccp-address sgsn-naught
+ routing-indicator PC
+ point-code 0.23.1
+
+ sccp-address sgsn-one
+ routing-indicator PC
+ point-code 0.1.2
+
+ sccp-address sgsn-two
+ routing-indicator PC
+ point-code 0.1.3
+
+ sccp-address sgsn-three
+ routing-indicator PC
+ point-code 0.1.4
+
+hnbgw
+ log-prefix hnb-id
+ iuh
+ local-ip 127.0.0.1
+ local-port 29169
+ hnbap-allow-tmsi 1
+ mgw 0
+ mgw local-ip 127.0.0.1
+ mgw remote-ip 127.0.0.1
+ # don't spam RANAP RESET messages for up to eight CN links across all tests
+ timer hnbgw T4 60
+ # reduce default X31 from 15 seconds
+ # https://gerrit.osmocom.org/c/osmo-hnbgw/+/34922
+ timer hnbgw X31 5
+
+msc 0
+ remote-addr msc-naught
+
+msc 1
+ remote-addr msc-one
+
+msc 2
+ remote-addr msc-two
+
+msc 3
+ remote-addr msc-three
+
+sgsn 0
+ remote-addr sgsn-naught
+
+sgsn 1
+ remote-addr sgsn-one
+
+sgsn 2
+ remote-addr sgsn-two
+
+sgsn 3
+ remote-addr sgsn-three
+
+hnbgw
+ iucs
+ nri bitlen 10
+ # a NULL NRI that is outside the NRI ranges used by the MSCs:
+ nri null add 0
+ # a NULL NRI that is also used by an MSC:
+ nri null add 1
+msc 0
+ nri add 1 255
+msc 1
+ nri add 256 511
+msc 2
+ nri add 512 767
+ # range 768-1000 is not assigned to any MSC on purpose
+msc 3
+ nri add 1001 1023
+
+hnbgw
+ iups
+ nri bitlen 10
+ # a NULL NRI that is outside the NRI ranges used by the SGSNs:
+ nri null add 0
+ # a NULL NRI that is also used by an SGSN:
+ nri null add 1
+sgsn 0
+ nri add 1 255
+sgsn 1
+ nri add 256 511
+sgsn 2
+ nri add 512 767
+ # range 768-1000 is not assigned to any SGSN on purpose
+sgsn 3
+ nri add 1001 1023
diff --git a/hnbgw/osmo-stp.cfg b/hnbgw/osmo-stp.cfg
new file mode 100644
index 00000000..e4b80d43
--- /dev/null
+++ b/hnbgw/osmo-stp.cfg
@@ -0,0 +1,96 @@
+!
+! OsmoSTP (0.8.1) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging print extended-timestamp 1
+ logging level lglobal notice
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp notice
+ logging level lstats notice
+ logging level lgsup notice
+ logging level loap notice
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp notice
+!
+line vty
+ no login
+!
+cs7 instance 0
+ xua rkm routing-key-allocation dynamic-permitted
+ asp virt-msc0-0 23905 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-msc0 m3ua
+ asp virt-msc0-0
+ routing-key 1 0.23.4
+
+ asp virt-msc1-0 23907 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-msc1 m3ua
+ asp virt-msc1-0
+ routing-key 3 0.0.2
+
+ asp virt-msc2-0 23909 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-msc2 m3ua
+ asp virt-msc2-0
+ routing-key 5 0.0.3
+
+ asp virt-sgsn0-0 23906 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-sgsn0 m3ua
+ asp virt-sgsn0-0
+ routing-key 2 0.23.1
+
+ asp virt-sgsn1-0 23908 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-sgsn1 m3ua
+ asp virt-sgsn1-0
+ routing-key 4 0.1.2
+
+ asp virt-sgsn2-0 23910 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-sgsn2 m3ua
+ asp virt-sgsn2-0
+ routing-key 6 0.1.3
+
+ route-table system
+ update route 0.23.4 7.255.7 linkset virt-msc0
+ update route 0.0.2 7.255.7 linkset virt-msc1
+ update route 0.0.3 7.255.7 linkset virt-msc2
+ update route 0.23.1 7.255.7 linkset virt-sgsn0
+ update route 0.1.2 7.255.7 linkset virt-sgsn1
+ update route 0.1.3 7.255.7 linkset virt-sgsn2
+ listen m3ua 2905
+ accept-asp-connections dynamic-permitted
diff --git a/hnbgw/regen_makefile.sh b/hnbgw/regen_makefile.sh
new file mode 100755
index 00000000..13db985b
--- /dev/null
+++ b/hnbgw/regen_makefile.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+NAME=HNBGW_Tests
+
+FILES="
+ *.asn
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IuUP_EncDec.cc
+ Iuh_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SCTPasp_PT.cc
+ SDP_EncDec.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ HNBAP_EncDec.cc
+ RUA_EncDec.cc
+ RANAP_EncDec.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ UD_PT.cc
+ PFCP_CodecPort_CtrlFunctDef.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DRAN_EMULATION_RANAP
+ -DUSE_MTP3_DISTRIBUTOR
+"
+
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp -lfftranscode/' Makefile
diff --git a/hnodeb/HNBGW_ConnectionHandler.ttcn b/hnodeb/HNBGW_ConnectionHandler.ttcn
new file mode 100644
index 00000000..e256963a
--- /dev/null
+++ b/hnodeb/HNBGW_ConnectionHandler.ttcn
@@ -0,0 +1,295 @@
+module HNBGW_ConnectionHandler {
+
+/* HNBGW Connection Handler of HNB_Tests in TTCN-3
+ * (C) 2021 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
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+
+import from SDP_Types all;
+
+import from StatsD_Checker all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+
+import from HNBAP_Templates all;
+
+import from Iuh_Emulation all;
+
+import from RTP_Types all;
+import from RTP_Emulation all;
+
+import from HNBLLIF_CodecPort all;
+import from HNBLLIF_Types all;
+import from HNBLLIF_Templates all;
+
+import from GTP_Emulation all;
+import from GTPv1U_Templates all;
+import from GTPv1U_CodecPort all;
+import from GTPU_Types all;
+
+/* this component represents a single Iuh connection at the HNBGW. */
+type component HNBGW_ConnHdlr extends Iuh_ConnHdlr, GTP_ConnHdlr, StatsD_ConnHdlr {
+ port TELNETasp_PT HNBVTY;
+ /* HNBLLIF Interface of HNodeB */
+ port HNBLLIF_CODEC_PT LLSK;
+ var integer g_llsk_conn_id;
+
+ var RTP_Emulation_CT vc_RTPEM;
+ port RTPEM_CTRL_PT RTPEM_CTRL;
+ port RTPEM_DATA_PT RTPEM_DATA;
+
+ var GTP_Emulation_CT vc_GTP;
+
+
+ var TestHdlrParams g_pars;
+
+ var boolean g_vty_initialized := false;
+}
+
+function f_HNBGW_ConnHdlr_init_vty() runs on HNBGW_ConnHdlr {
+ if (not g_vty_initialized) {
+ map(self:HNBVTY, system:HNBVTY);
+ f_vty_set_prompts(HNBVTY);
+ f_vty_transceive(HNBVTY, "enable");
+ g_vty_initialized := true;
+ }
+}
+
+private function f_HNBGW_ConnHdlr_init_iuh(charstring id) runs on HNBGW_ConnHdlr {
+ var Iuh_Emulation_CT vc_Iuh;
+ vc_Iuh := Iuh_Emulation_CT.create(id & "-HNBGW") alive;
+ connect(self:HNBAP, vc_Iuh:HNBAP);
+ connect(self:RUA, vc_Iuh:RUA);
+
+ var Iuh_conn_parameters iuh_pars;
+ iuh_pars.remote_ip := g_pars.hnodeb_addr;
+ iuh_pars.remote_sctp_port := -1;
+ iuh_pars.local_ip := g_pars.hnbgw_addr;
+ iuh_pars.local_sctp_port := g_pars.hnbgw_port;
+ vc_Iuh.start(Iuh_Emulation.main(iuh_pars, id & "-Iuh"));
+}
+
+private function f_HNBGW_ConnHdlr_init_gtp(charstring id) runs on HNBGW_ConnHdlr {
+ id := id & "-GTP";
+
+ var GtpEmulationCfg gtp_cfg := {
+ gtpc_bind_ip := g_pars.hnbgw_addr,
+ gtpc_bind_port := GTP1C_PORT,
+ gtpu_bind_ip := g_pars.hnbgw_addr,
+ gtpu_bind_port := GTP1U_PORT,
+ sgsn_role := false
+ };
+
+ vc_GTP := GTP_Emulation_CT.create(id) alive;
+ connect(self:GTP, vc_GTP:CLIENT);
+ connect(self:GTP_PROC, vc_GTP:CLIENT_PROC);
+ vc_GTP.start(GTP_Emulation.main(gtp_cfg));
+}
+
+/* initialize all parameters */
+function f_HNBGW_ConnHdlr_init(charstring id, TestHdlrParams pars) runs on HNBGW_ConnHdlr {
+ g_pars := valueof(pars);
+ f_HNBGW_ConnHdlr_init_iuh(id);
+ f_HNBGW_ConnHdlr_init_gtp(id);
+ f_HNBGW_ConnHdlr_init_vty();
+
+ /* Connect to HNB on LLSK and do HELLO ping-pong */
+ f_start_hnbllif(LLSK, id & "-LLSK", g_pars, g_llsk_conn_id);
+}
+
+
+function f_start_hnbllif(HNBLLIF_CODEC_PT pt, charstring id, TestHdlrParams pars,
+ out integer hnbllif_conn_id) {
+ timer T := 2.0;
+ var HNBLLIF_send_data sd;
+ var HNBLLIF_Message last_hello_cnf;
+ if (pars.hnbllif_sk_path == "") {
+ hnbllif_conn_id := -1;
+ return;
+ }
+ hnbllif_conn_id := f_hnbllif_connect(pt, pars.hnbllif_sk_path);
+
+ T.start;
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_CTL, HNBLLIF_Types.mp_hnbllif_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_CTL, HNBLLIF_Types.mp_hnbllif_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=CTL");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_IUH, pars.hnbllif_sapi_iuh_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_IUH, pars.hnbllif_sapi_iuh_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=IUH");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_AUDIO, pars.hnbllif_sapi_audio_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_AUDIO, pars.hnbllif_sapi_audio_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=AUDIO");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_GTP, pars.hnbllif_sapi_gtp_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_GTP, pars.hnbllif_sapi_gtp_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=GTP");
+ }
+ }
+}
+
+type record TestHdlrParams {
+ charstring hnbllif_sk_path, /* "" means don't connect */
+ uint16_t hnbllif_sapi_iuh_version,
+ uint16_t hnbllif_sapi_gtp_version,
+ uint16_t hnbllif_sapi_audio_version,
+ charstring hnbgw_addr,
+ charstring hnodeb_addr,
+ integer hnbgw_port,
+ integer hnbgw_rtp_port,
+ uint16_t rnc_id,
+ charstring hNB_Identity_Info,
+ uint16_t mcc,
+ uint16_t mnc,
+ uint32_t cell_identity,
+ uint16_t lac,
+ uint8_t rac,
+ uint8_t sac
+};
+
+/* Note: Do not use valueof() to get a value of this template, use
+ * f_gen_test_hdlr_pars() instead in order to get a configuration. */
+template (value) TestHdlrParams t_def_TestHdlrPars := {
+ hnbllif_sk_path := HNBLL_SOCK_DEFAULT,
+ hnbllif_sapi_iuh_version := 0,
+ hnbllif_sapi_gtp_version := 0,
+ hnbllif_sapi_audio_version := 1,
+ hnbgw_addr := "127.0.0.1",
+ hnodeb_addr := "127.0.0.1",
+ hnbgw_port := 29169,
+ hnbgw_rtp_port := 9000,
+ rnc_id := 23,
+ hNB_Identity_Info := "OsmoHNodeB",
+ mcc := 1,
+ mnc := 1,
+ cell_identity := 1,
+ lac := 2,
+ rac := 3,
+ sac := 4
+}
+
+template (value) Gtp1uPeer ts_GtpPeerU(charstring ip) := {
+ connId := 1,
+ remName := ip,
+ remPort := GTP1U_PORT
+}
+
+function f_gtpu_send(uint32_t tei, octetstring payload) runs on HNBGW_ConnHdlr {
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(g_pars.hnodeb_addr));
+ GTP.send(ts_GTP1U_GPDU(peer, 0 /*seq*/, int2oct(tei, 4), payload));
+}
+
+/* HNBLLIF socket may at any time receive a new INFO.ind */
+altstep as_hnbllif_hello_cnf(HNBLLIF_CODEC_PT pt, integer hnbllif_conn_id,
+ out HNBLLIF_Message last_hello_cnf,
+ template (present) HNBLLIF_Sapi exp_sapi := ?,
+ template (present) uint16_t exp_version := ?) {
+ var HNBLLIF_send_data sd;
+ [] pt.receive(t_SD_HNBLLIF(hnbllif_conn_id, tr_HNBLLIF_CTL_HELLO_CNF(exp_sapi, exp_version))) -> value sd {
+ last_hello_cnf := sd.data;
+ }
+ [] pt.receive(t_SD_HNBLLIF(hnbllif_conn_id, tr_HNBLLIF_CTL_HELLO_CNF(?))) -> value sd {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Invalid API_VERSION received");
+ }
+}
+
+function f_llsk_rx(template (present) HNBLLIF_Message exp_tmpl) runs on HNBGW_ConnHdlr
+return template (present) HNBLLIF_send_data {
+ return t_SD_HNBLLIF(g_llsk_conn_id, exp_tmpl);
+}
+
+function f_llsk_tx(template (value) HNBLLIF_Message tx_msg) runs on HNBGW_ConnHdlr
+return template (value) HNBLLIF_send_data {
+ return ts_SD_HNBLLIF(g_llsk_conn_id, tx_msg);
+}
+
+function f_enc_mcc_mnc(uint16_t mcc_uint, uint16_t mnc_uint) return OCT3 {
+ var hexstring mnc;
+ var hexstring mcc := int2hex(mcc_uint, 3);
+
+ if (mnc_uint < 100) {
+ mnc := int2hex(mnc_uint, 2);
+ return hex2oct(mcc[1] & mcc[0] & 'F'H & mcc[2] & mnc[1] & mnc[0]);
+ } else {
+ mnc := int2hex(mnc_uint, 3);
+ return hex2oct(mcc[1] & mcc[0] & mnc[2] & mcc[2] & mnc[1] & mnc[0]);
+ }
+}
+
+function f_handle_hnbap_hnb_register_req()
+runs on HNBGW_ConnHdlr {
+ HNBAP.receive(tr_HNBAP_HNBRegisterRequest(char2oct(g_pars.hNB_Identity_Info),
+ f_enc_mcc_mnc(g_pars.mcc, g_pars.mnc),
+ int2bit(g_pars.cell_identity, 28),
+ int2oct(g_pars.lac, 2),
+ int2oct(g_pars.rac, 1),
+ int2oct(g_pars.sac, 2)
+ ));
+ HNBAP.send(ts_HNBAP_HNBRegisterAccept(g_pars.rnc_id));
+}
+
+/* Initialize and start the RTP emulation component for a ConnHdlr */
+function f_HNBGW_rtpem_activate(inout octetstring payload)
+runs on HNBGW_ConnHdlr {
+ /* Initialize, connect and start the emulation component */
+ var RtpemConfig cfg := c_RtpemDefaultCfg;
+ cfg.iuup_mode := true;
+ cfg.iuup_cfg.active_init := false;
+ cfg.tx_payloads[0].payload_type := 96;
+ cfg.rx_payloads[0].payload_type := 96;
+
+ vc_RTPEM := RTP_Emulation_CT.create(testcasename() & "-RTPEM") alive;
+ map(vc_RTPEM:RTP, system:RTP);
+ map(vc_RTPEM:RTCP, system:RTCP);
+ connect(vc_RTPEM:CTRL, self:RTPEM_CTRL);
+ connect(vc_RTPEM:DATA, self:RTPEM_DATA);
+ vc_RTPEM.start(RTP_Emulation.f_main());
+
+ /* Configure the RTP parameters (TCH/FS). TODO: IuUP */
+ var integer payload_len := 33;
+ var octetstring hdr := 'D0'O;
+
+ /* Pad the payload to conform the expected length */
+ payload := f_pad_oct(hdr & payload, payload_len, '00'O);
+ cfg.tx_payloads[0].fixed_payload := payload;
+ f_rtpem_configure(RTPEM_CTRL, cfg);
+
+ /* Bind the RTP emulation to the configured address */
+ f_rtpem_bind(RTPEM_CTRL, g_pars.hnbgw_addr, g_pars.hnbgw_rtp_port);
+
+ /* Set the given RTP emulation mode */
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_RXONLY);
+}
+
+function f_HNBGW_rtpem_connect(HostName remote_host, PortNumber remote_port)
+runs on HNBGW_ConnHdlr {
+ f_rtpem_connect(RTPEM_CTRL, remote_host, remote_port);
+ /* Set the given RTP emulation mode */
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_BIDIR);
+}
+
+}
diff --git a/hnodeb/HNB_Tests.cfg b/hnodeb/HNB_Tests.cfg
new file mode 100644
index 00000000..38d9cc7c
--- /dev/null
+++ b/hnodeb/HNB_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./HNB_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+HNB_Tests.control
diff --git a/hnodeb/HNB_Tests.default b/hnodeb/HNB_Tests.default
new file mode 100644
index 00000000..c385b9a0
--- /dev/null
+++ b/hnodeb/HNB_Tests.default
@@ -0,0 +1,28 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.HNBVTY.CTRL_MODE := "client"
+*.HNBVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.HNBVTY.CTRL_PORTNUM := "4273"
+*.HNBVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.HNBVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.HNBVTY.CTRL_READMODE := "buffered"
+*.HNBVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.HNBVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.HNBVTY.PROMPT1 := "OsmoHNodeB> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4274"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoHNodeB> "
+*.LLSK.socket_type := "SEQPACKET"
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoHNodeB";
+
+[EXECUTE]
diff --git a/hnodeb/HNB_Tests.ttcn b/hnodeb/HNB_Tests.ttcn
new file mode 100644
index 00000000..29f0bbb6
--- /dev/null
+++ b/hnodeb/HNB_Tests.ttcn
@@ -0,0 +1,470 @@
+module HNB_Tests {
+
+/* Integration Tests for OsmoHNodeB
+ * (C) 2021 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
+ *
+ * This test suite tests OsmoHNodB while emulating both multiple UE as
+ * well as the HNBGW. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
+ * level testing.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from HNBAP_Templates all;
+import from RUA_IEs all;
+import from RUA_Templates all;
+
+import from HNBGW_ConnectionHandler all;
+import from Iuh_Emulation all;
+
+import from RTP_Types all;
+import from RTP_Emulation all;
+
+import from HNBLLIF_CodecPort all;
+import from HNBLLIF_Types all;
+import from HNBLLIF_Templates all;
+
+import from GTPU_Types all;
+import from GTPv1U_Templates all;
+import from GTP_Emulation all;
+
+import from IuUP_Types all;
+
+modulepar {
+ /* IP address at which the HNodeB can be reached */
+ charstring mp_hnodeb_ip := "127.0.0.1";
+
+ /* IP address at which the test binds */
+ charstring mp_hnbgw_iuh_ip := "127.0.0.1";
+ integer mp_hnbgw_iuh_port := 29169;
+
+ charstring mp_hnbllif_sk_path := HNBLL_SOCK_DEFAULT;
+}
+
+const hexstring ranap_cm_service_req := '001340400000060003400100000f40060000f11028b6003a40080000f110ffffffff0010400e0d052411035758a605f44e9d4aef004f400300001c0056400500f1100017'H;
+const hexstring ranap_auth_req := '00144032000002001040262505120217dc146aeac56cb5ff6d5fb51f47f19220108ca5a6d0c8110000b9e9272498872764003b400100'H;
+const hexstring ranap_auth_resp := '001440140000010010400d0c0554ccbdd0302104002f3ae4'H;
+const hexstring ranap_paging := '000e401e0000030003400100001740095000010100000000f10040400500b6cf4773'H;
+const hexstring ranap_rab_ass_req := '0000005900000100364052000001003500487824cd80102fa7201a2c0000f44c080a028000514000272028140067400000222814003c40000000503d02000227c03500010a0901a200000000000000000000000000401f4a0000400100'H;
+const hexstring iu_release_compl := '20010003000000'H;
+
+type component test_CT extends CTRL_Adapter_CT {
+ port TELNETasp_PT HNBVTY;
+
+ /* HNBLLIF Interface of HNodeB */
+ port HNBLLIF_CODEC_PT LLSK;
+ var integer g_llsk_conn_id;
+
+ /* global test case guard timer (actual timeout value is set in f_init()) */
+ timer T_guard := 30.0;
+}
+
+/* global altstep for global guard timer; */
+altstep as_Tguard() runs on test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+ if (HNBVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:HNBVTY, system:HNBVTY);
+ f_vty_set_prompts(HNBVTY);
+ f_vty_transceive(HNBVTY, "enable");
+}
+
+private function f_init_hnbllif(TestHdlrParams pars) runs on test_CT {
+ map(self:LLSK, system:LLSK);
+ f_start_hnbllif(LLSK, testcasename(), pars, g_llsk_conn_id);
+}
+
+/* global initialization function */
+function f_init(float guard_timeout := 30.0) runs on test_CT {
+ var integer bssap_idx;
+
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
+ f_init_vty("VirtHNBGW");
+}
+
+friend function f_shutdown_helper() runs on test_CT {
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+private function f_gen_test_hdlr_pars() runs on test_CT return TestHdlrParams {
+
+ var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ pars.hnbllif_sk_path := mp_hnbllif_sk_path;
+ pars.hnodeb_addr := mp_hnodeb_ip;
+ pars.hnbgw_addr := mp_hnbgw_iuh_ip;
+ pars.hnbgw_port := mp_hnbgw_iuh_port;
+ return pars;
+}
+
+type function void_fn(charstring id) runs on HNBGW_ConnHdlr;
+
+/* helper function to create and connect a HNBGW_ConnHdlr component */
+private function f_connect_handler(inout HNBGW_ConnHdlr vc_conn, TestHdlrParams pars) runs on test_CT {
+ if (pars.hnbllif_sk_path != "") {
+ map(vc_conn:LLSK, system:LLSK);
+ }
+}
+
+function f_start_handler_create(TestHdlrParams pars)
+runs on test_CT return HNBGW_ConnHdlr {
+ var charstring id := testcasename();
+ var HNBGW_ConnHdlr vc_conn;
+ vc_conn := HNBGW_ConnHdlr.create(id) alive;
+ f_connect_handler(vc_conn, pars);
+ return vc_conn;
+}
+
+function f_start_handler_run(HNBGW_ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars)
+runs on test_CT return HNBGW_ConnHdlr {
+ var charstring id := testcasename();
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(HNBVTY, id & "() start");
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars_tmpl := omit)
+runs on test_CT return HNBGW_ConnHdlr {
+ var TestHdlrParams pars;
+ if (istemplatekind(pars_tmpl, "omit")) {
+ pars := valueof(f_gen_test_hdlr_pars());
+ } else {
+ pars := valueof(pars_tmpl);
+ }
+ return f_start_handler_run(f_start_handler_create(pars), fn, pars);
+}
+
+/* first function inside ConnHdlr component; sets g_pars + starts function */
+private function f_handler_init(void_fn fn, charstring id, TestHdlrParams pars)
+runs on HNBGW_ConnHdlr {
+ f_HNBGW_ConnHdlr_init(id, pars);
+ HNBAP.receive(IUHEM_Event:{up_down:=IUHEM_EVENT_UP}); /* Wait for HNB to connect to us */
+ fn.apply(id);
+}
+
+private function f_tc_hnb_register_request_accept(charstring id) runs on HNBGW_ConnHdlr {
+ f_handle_hnbap_hnb_register_req();
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+ g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+ f_sleep(1.0);
+}
+testcase TC_hnb_register_request_accept() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_hnb_register_request_accept));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_tc_hnb_register_reject(charstring id) runs on HNBGW_ConnHdlr {
+ HNBAP.receive(tr_HNBAP_HNBRegisterRequest(char2oct(g_pars.hNB_Identity_Info),
+ f_enc_mcc_mnc(g_pars.mcc, g_pars.mnc),
+ int2bit(g_pars.cell_identity, 28),
+ int2oct(g_pars.lac, 2),
+ int2oct(g_pars.rac, 1),
+ int2oct(g_pars.sac, 2)
+ ));
+ HNBAP.send(ts_HNBAP_HNBRegisterReject(ts_HnbapCause(overload)));
+ f_sleep(1.0);
+}
+testcase TC_hnb_register_request_reject() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_hnb_register_reject));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_tc_mo_conn(charstring id) runs on HNBGW_ConnHdlr {
+ const integer context_id := 30;
+ const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */
+ const Establishment_Cause est_cause := normal_call;
+ f_handle_hnbap_hnb_register_req();
+
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+ g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+
+ /* Now an UE attempts CM Service Request: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(context_id, 1, enum2int(est_cause), hex2oct(ranap_cm_service_req))));
+ /* The related RUA Connect + RANAP message is received on Iuh: */
+ RUA.receive(tr_RUA_Connect(ps_domain, context_id_bstr, est_cause, hex2oct(ranap_cm_service_req)));
+
+ /* Now HNBGW answers with RUA-DirectTransfer(RANAP-AuthenticationRequest) */
+ RUA.send(ts_RUA_DirectTransfer(ps_domain, context_id_bstr, hex2oct(ranap_auth_req)));
+
+ /* Now on LLSK first the Conn establishment is confirmed and then we receive data */
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(context_id, 1, 0)));
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_DATA_IND(context_id, 1, hex2oct(ranap_auth_req))));
+
+ /* UE answers with RANAPAuthenticationResponse: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_DATA_REQ(context_id, 1, hex2oct(ranap_auth_resp))));
+ RUA.receive(tr_RUA_DirectTransfer(ps_domain, context_id_bstr, hex2oct(ranap_auth_resp)));
+
+ /* UE sends Iu Release Complete to release the conn */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_RELEASE_REQ(context_id, 1, 0, 0, hex2oct(iu_release_compl))));
+ RUA.receive(tr_RUA_Disconnect(ps_domain, context_id_bstr, ts_RUA_Cause(normal), hex2oct(iu_release_compl)));
+}
+testcase TC_mo_conn() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_mo_conn));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+
+private function f_tc_paging(charstring id) runs on HNBGW_ConnHdlr {
+ const integer context_id := 30;
+ const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */
+ f_handle_hnbap_hnb_register_req();
+
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+ g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+
+ /* HNBGW sends RUA-ConnectionlessTransfer(RANAP-Paging) */
+ RUA.send(ts_RUA_ConnectionlessTransfer(hex2oct(ranap_paging)));
+
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_UNITDATA_IND(hex2oct(ranap_paging))));
+
+ /* Here it would continue with UE-side answers with RUA-Connect(RANAP-PagingResponse) */
+}
+testcase TC_paging() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_paging));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_tc_cs_mo_call(charstring id) runs on HNBGW_ConnHdlr {
+ const integer context_id := 30;
+ const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */
+ const Establishment_Cause est_cause := normal_call;
+ var HNBLLIF_send_data sd;
+ var PDU_RTP rtp_pdu;
+ var octetstring rtp_payload;
+ var HostName hnodeb_rtp_addr;
+ var PortNumber hnodeb_rtp_port;
+ timer Tu;
+ var uint32_t audio_conn_id;
+ var IuUP_FQC fqc := IuUP_FQC_GOOD;
+ var template (omit) HNBLLIF_AUDIO_RFCIs rfcis_tpl := omit;
+
+ if (g_pars.hnbllif_sapi_audio_version >= 1) {
+ var HNBLLIF_AUDIO_RFCIs rfcis;
+ /* generate some unordered RFCI list of 3 elements (the default): */
+ rfcis[0] := 1; rfcis[1] := 2; rfcis[2] := 0;
+ for (var integer i := 3; i < HNBLLIF_MAX_RFCIS; i := i + 1) {
+ rfcis[i] := 0;
+ }
+ rfcis_tpl := rfcis;
+ }
+
+ rtp_payload := f_rnd_octstring(6);
+ f_HNBGW_rtpem_activate(rtp_payload);
+
+ f_handle_hnbap_hnb_register_req();
+
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+ g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+
+ /* Now an UE attempts CM Service Request: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(context_id, 0, enum2int(est_cause), hex2oct(ranap_cm_service_req))));
+ /* The related RUA Connect + RANAP message is received on Iuh: */
+ RUA.receive(tr_RUA_Connect(cs_domain, context_id_bstr, est_cause, hex2oct(ranap_cm_service_req)));
+
+ /* Now HNBGW answers with RUA-DirectTransfer(RANAP-RabASsReq) */
+ RUA.send(ts_RUA_DirectTransfer(cs_domain, context_id_bstr, hex2oct(ranap_rab_ass_req)));
+
+ /* Now on LLSK first the Conn establishment is confirmed and then we receive data */
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(context_id, 0, 0)));
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_DATA_IND(context_id, 0, hex2oct(ranap_rab_ass_req))));
+
+ /* Now LLSK provides the remote TransportLayerAddress from RabAssReq and asks SUT to provide a local address: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_ESTABLISH_REQ(context_id, g_pars.hnbgw_rtp_port, HNBLL_IF_ADDR_TYPE_IPV4,
+ f_HNBLLIF_Addr(HNBLL_IF_ADDR_TYPE_IPV4, g_pars.hnbgw_addr),
+ rfci := rfcis_tpl)));
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_AUDIO_CONN_ESTABLISH_CNF(context_id, ?, 0, ?, HNBLL_IF_ADDR_TYPE_IPV4, ?))) -> value sd;
+
+ audio_conn_id := sd.data.u.audio.u.conn_establish.u.cnf.audio_conn_id;
+ hnodeb_rtp_addr := f_inet_ntoa(sd.data.u.audio.u.conn_establish.u.cnf.local_addr);
+ if (not match(g_pars.hnodeb_addr, hnodeb_rtp_addr)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "hnodeb RTP local address doesn't match expectations");
+ }
+ hnodeb_rtp_port := sd.data.u.audio.u.conn_establish.u.cnf.local_rtp_port;
+ f_HNBGW_rtpem_connect(hnodeb_rtp_addr, hnodeb_rtp_port);
+
+ /* We should eventually receive some RTP/IUUP from the HNBGW once Init phase goes on: */
+ Tu.start(2.0);
+ alt {
+ [] LLSK.receive(f_llsk_rx(tr_HNBLLIF_AUDIO_CONN_DATA_IND(audio_conn_id, ?, enum2int(fqc), ?, rtp_payload)));
+ [] Tu.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for Downlink speech frames");
+ }
+ }
+ Tu.stop;
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_RXONLY);
+
+ /* Make sure that Uplink frames are received at the HNBGW */
+ RTPEM_DATA.clear;
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_DATA_REQ(audio_conn_id, 1, enum2int(fqc), 0, rtp_payload)));
+ Tu.start(2.0);
+ alt {
+ [] RTPEM_DATA.receive(PDU_RTP:?) -> value rtp_pdu {
+ if (rtp_pdu.data != rtp_payload) {
+ log("Unexpected RTP payload received!");
+ repeat;
+ }
+ }
+ [] RTPEM_DATA.receive { repeat; }
+ [] Tu.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for Uplink speech frames");
+ }
+ }
+ Tu.stop;
+
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_NONE);
+ f_sleep(0.5); /* give some time to RTP_Emu to stop sending RTP packets... */
+
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_AUDIO_CONN_RELEASE_REQ(audio_conn_id)));
+
+ /* UE sends Iu Release Complete to release the conn */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_RELEASE_REQ(context_id, 0, 0, 0, hex2oct(iu_release_compl))));
+ RUA.receive(tr_RUA_Disconnect(cs_domain, context_id_bstr, ts_RUA_Cause(normal), hex2oct(iu_release_compl)));
+}
+testcase TC_cs_mo_call() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_cs_mo_call));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+/* Same as TC_cs_mo_call, but using AUDIO SAPI version 0 (no rfci param
+ * in HNBLLIF_AUDIO_conn_establish_req) */
+testcase TC_cs_mo_call_audio_v0() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+ var TestHdlrParams pars;
+
+ f_init();
+ pars := valueof(f_gen_test_hdlr_pars());
+ pars.hnbllif_sapi_audio_version := 0;
+ vc_conn := f_start_handler(refers(f_tc_cs_mo_call), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+private function f_tc_ps_mo_gtp_ping_pong(charstring id) runs on HNBGW_ConnHdlr {
+ const integer context_id := 30;
+ const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */
+ const Establishment_Cause est_cause := normal_call;
+ var uint32_t remote_tei := 8888;
+ var uint32_t local_tei;
+ var octetstring gtp_payload := f_rnd_octstring(40);
+ var HNBLLIF_send_data sd;
+ var uint32_t gtp_conn_id;
+
+ f_gtp_register_teid(int2oct(remote_tei, 4));
+
+ f_handle_hnbap_hnb_register_req();
+
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity,
+ g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id)));
+
+ /* Now an UE attempts CM Service Request: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(context_id, 1, enum2int(est_cause), hex2oct(ranap_cm_service_req))));
+ /* The related RUA Connect + RANAP message is received on Iuh: */
+ RUA.receive(tr_RUA_Connect(ps_domain, context_id_bstr, est_cause, hex2oct(ranap_cm_service_req)));
+
+ /* Now HNBGW answers with RUA-DirectTransfer(RANAP-RabASsReq) */
+ RUA.send(ts_RUA_DirectTransfer(ps_domain, context_id_bstr, hex2oct(ranap_rab_ass_req)));
+
+ /* Now on LLSK first the Conn establishment is confirmed and then we receive data */
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(context_id, 1, 0)));
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_DATA_IND(context_id, 1, hex2oct(ranap_rab_ass_req))));
+
+ /* Now LLSK provides the remote TransportLayerAddress from RabAssReq and asks SUT to provide a local address: */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_GTP_CONN_ESTABLISH_REQ(context_id, remote_tei, HNBLL_IF_ADDR_TYPE_IPV4,
+ f_HNBLLIF_Addr(HNBLL_IF_ADDR_TYPE_IPV4, g_pars.hnbgw_addr))));
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_GTP_CONN_ESTABLISH_CNF(context_id, ?, ?, 0,
+ HNBLL_IF_ADDR_TYPE_IPV4, ?))) -> value sd;
+ gtp_conn_id := sd.data.u.gtp.u.conn_establish.u.cnf.gtp_conn_id;
+ local_tei := sd.data.u.gtp.u.conn_establish.u.cnf.local_tei;
+
+ /* Forward GTP data in both directions */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_GTP_CONN_DATA_REQ(gtp_conn_id, gtp_payload)));
+ GTP.receive(tr_GTPU_GPDU(ts_GtpPeerU(g_pars.hnodeb_addr), int2oct(remote_tei, 4), gtp_payload));
+ f_gtpu_send(local_tei, gtp_payload);
+ LLSK.receive(f_llsk_rx(tr_HNBLLIF_GTP_CONN_DATA_IND(gtp_conn_id, gtp_payload)));
+
+ /* Done, release GTP conn */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_GTP_CONN_RELEASE_REQ(gtp_conn_id)));
+
+ /* UE sends Iu Release Complete to release the conn */
+ LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_RELEASE_REQ(context_id, 1, 0, 0, hex2oct(iu_release_compl))));
+ RUA.receive(tr_RUA_Disconnect(ps_domain, context_id_bstr, ts_RUA_Cause(normal), hex2oct(iu_release_compl)));
+}
+testcase TC_ps_mo_gtp_ping_pong() runs on test_CT {
+ var HNBGW_ConnHdlr vc_conn;
+
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_ps_mo_gtp_ping_pong));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+control {
+ execute( TC_hnb_register_request_accept() );
+ execute( TC_hnb_register_request_reject() );
+ execute( TC_mo_conn() );
+ execute( TC_paging() );
+ execute( TC_cs_mo_call_audio_v0() );
+ execute( TC_cs_mo_call() );
+ execute( TC_ps_mo_gtp_ping_pong() );
+}
+
+}
diff --git a/hnodeb/README.md b/hnodeb/README.md
new file mode 100644
index 00000000..3b3fa9fb
--- /dev/null
+++ b/hnodeb/README.md
@@ -0,0 +1,30 @@
+# HNB_Tests.ttcn
+
+* external interfaces
+ * Iuh side (emulates HNBGW-side)
+ * SCTP/HNBAP
+ * SCTP/RUA/RANAP
+ * RTP side: emulates MGW
+ * GTP-U side: emulates GGSN
+ * UE side
+ * VTY
+ * CTRL
+ * StatsD
+
+{% dot hnb_tests.svg
+digraph G {
+ graph [label="HNB_Tests", labelloc=t, fontsize=30];
+ rankdir=LR;
+ { rank=same; ATS; HNB; };
+ HNB [label="IUT\nosmo-bsc",shape="box"];
+ ATS [label="ATS\nHNB_Tests.ttcn"];
+
+ HNB <- ATS [label="Uu (or some intermediate lower layer)"];
+ HNB -> ATS [label="Iuh"];
+ HNB -> ATS [label="RTP"];
+ HNB -> ATS [label="GTP-U"];
+ HNB <- ATS [label="CTRL"];
+ HNB <- ATS [label="VTY"];
+ HNB -> ATS [label="StatsD"];
+}
+%}
diff --git a/hnodeb/README.txt b/hnodeb/README.txt
new file mode 100644
index 00000000..1cf81ee0
--- /dev/null
+++ b/hnodeb/README.txt
@@ -0,0 +1,32 @@
+Integration Tests for OsmoHnodeB
+--------------------------------
+
+This test suite tests OsmoHNodeB while emulating both multiple UE as
+well as the HNBGW.
+
+The included jenkins.sh script, together with the Dockerfiles from
+http://git.osmocom.org/docker-playground/ can be used to run both the
+osmo-hnodeb-under-test as well as the extenal entities and the tester.
+
+
+Further Test Ideas
+------------------
+
+This is a random list of things about things possible to test.
+Asterisks '*' are TODO, while 'x' means already implemented.
+
+= exhaustion of resources
+
+= paging
+
+= assignment
+
+= hand-over
+
+= erroneous channel release
+
+= misc
+
+= counters
+
+= VTY based/corresponding tests
diff --git a/hnodeb/expected-results.xml b/hnodeb/expected-results.xml
new file mode 100644
index 00000000..f2c456b0
--- /dev/null
+++ b/hnodeb/expected-results.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<testsuite name='HNB_Tests' tests='7' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='HNB_Tests' name='TC_hnb_register_request_accept' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_hnb_register_request_reject' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_mo_conn' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_paging' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_cs_mo_call_audio_v0' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_cs_mo_call' time='MASKED'/>
+ <testcase classname='HNB_Tests' name='TC_ps_mo_gtp_ping_pong' time='MASKED'/>
+</testsuite>
diff --git a/hnodeb/gen_links.sh b/hnodeb/gen_links.sh
new file mode 100755
index 00000000..e4f453e4
--- /dev/null
+++ b/hnodeb/gen_links.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+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 " # GSM 7-bit coding
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+# Required by MGCP and IPA
+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
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SDP/src
+FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
+SDP_parser.y lex.SDP_parse_.c"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.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=../library/hnbap
+FILES="HNBAP_CommonDataTypes.asn HNBAP_Constants.asn HNBAP_Containers.asn HNBAP_IEs.asn HNBAP_PDU_Contents.asn HNBAP_PDU_Descriptions.asn "
+FILES+="HNBAP_EncDec.cc HNBAP_Types.ttcn HNBAP_Templates.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library/rua
+FILES="RUA_CommonDataTypes.asn RUA_Constants.asn RUA_Containers.asn RUA_IEs.asn RUA_PDU_Contents.asn RUA_PDU_Descriptions.asn "
+FILES+="RUA_EncDec.cc RUA_Types.ttcn RUA_Templates.ttcn "
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="HNBLLIF_Types.ttcn HNBLLIF_Templates.ttcn HNBLLIF_CodecPort.ttcn "
+FILES+="Iuh_Types.ttcn Iuh_CodecPort.ttcn Iuh_CodecPort_CtrlFunctDef.cc Iuh_CodecPort_CtrlFunct.ttcn Iuh_Emulation.ttcn DNS_Helpers.ttcn "
+FILES+="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1C_Templates.ttcn "
+FILES+="GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTPv1U_Templates.ttcn "
+FILES+="GTP_Emulation.ttcn IPCP_Types.ttcn GSM_Types.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/hnodeb/osmo-hnodeb.cfg b/hnodeb/osmo-hnodeb.cfg
new file mode 100644
index 00000000..3ccd4b41
--- /dev/null
+++ b/hnodeb/osmo-hnodeb.cfg
@@ -0,0 +1,19 @@
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category-hex 0
+ logging print category 1
+ logging print extended-timestamp 1
+ logging print file basename
+ logging level set-all debug
+line vty
+ no login
+!
+hnodeb
+ cell_identity 1
+ location_area_code 2
+ routing_area_code 3
+ service_area_code 4
+ iuh
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
diff --git a/hnodeb/regen_makefile.sh b/hnodeb/regen_makefile.sh
new file mode 100755
index 00000000..cf5fed3b
--- /dev/null
+++ b/hnodeb/regen_makefile.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+NAME=HNB_Tests
+
+FILES="
+ *.asn
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IuUP_EncDec.cc
+ Iuh_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SCTPasp_PT.cc
+ SDP_EncDec.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ HNBAP_EncDec.cc
+ RUA_EncDec.cc
+ UD_PT.cc
+ GTPC_EncDec.cc
+ GTPU_EncDec.cc
+ GTPv1C_CodecPort_CtrlFunctDef.cc
+ GTPv1U_CodecPort_CtrlFunctDef.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp -lfftranscode/' Makefile
diff --git a/hss/HSS_Tests.cfg b/hss/HSS_Tests.cfg
new file mode 100644
index 00000000..24fe9c4b
--- /dev/null
+++ b/hss/HSS_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./HSS_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+HSS_Tests.control
diff --git a/hss/HSS_Tests.default b/hss/HSS_Tests.default
new file mode 100644
index 00000000..4c0b502e
--- /dev/null
+++ b/hss/HSS_Tests.default
@@ -0,0 +1,7 @@
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[EXECUTE]
diff --git a/hss/HSS_Tests.ttcn b/hss/HSS_Tests.ttcn
new file mode 100644
index 00000000..a5503a71
--- /dev/null
+++ b/hss/HSS_Tests.ttcn
@@ -0,0 +1,275 @@
+module HSS_Tests {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
+
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+import from DIAMETER_Emulation all;
+
+type record of hexstring SubscriberConfigs;
+
+modulepar {
+ charstring mp_hss_hostname := "127.0.0.4";
+ integer mp_hss_port := 3868;
+ charstring mp_diam_local_hostname := "127.0.0.1";
+ integer mp_diam_local_port := 3868;
+ charstring mp_diam_orig_realm := "localdomain";
+ charstring mp_diam_orig_host := "mme.localdomain";
+ charstring mp_diam_dest_realm := "localdomain";
+ charstring mp_diam_dest_host := "hss.localdomain";
+ SubscriberConfigs subscribers := {
+ /* Existing subscriber, ULA returns SERVICE_GRANTED */
+ '001010000000000'H,
+ '001010000000001'H
+ };
+}
+
+/* main component, we typically have one per testcase */
+type component MTC_CT {
+
+ /* emulated MME/SGSN */
+ var DIAMETER_Emulation_CT vc_S6a;
+ port DIAMETER_PT S6a_UNIT;
+ port DIAMETEREM_PROC_PT S6a_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 MTC_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+type component DIAMETER_ConnHdlr_CT extends DIAMETER_ConnHdlr {
+ port DIAMETER_Conn_PT DIAMETER_CLIENT;
+ port DIAMETEREM_PROC_PT DIAMETER_PROC_CLIENT;
+}
+
+function f_diam_connhldr_ct_main(hexstring imsi) runs on DIAMETER_ConnHdlr_CT {
+ var DIAMETER_ConnHdlr vc_conn_unused;
+ var PDU_DIAMETER msg;
+ var UINT32 ete_id;
+
+ f_diameter_expect_imsi(imsi);
+
+ while (true) {
+ alt {
+ [] DIAMETER_CLIENT.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER.send(msg);
+ }
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER_CLIENT.send(msg);
+ }
+ [] DIAMETER_PROC_CLIENT.getcall(DIAMETEREM_register_eteid:{?,?}) -> param(ete_id, vc_conn_unused) {
+ DIAMETER_PROC.call(DIAMETEREM_register_eteid:{ete_id, self}) {
+ [] DIAMETER_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+ DIAMETER_PROC_CLIENT.reply(DIAMETEREM_register_eteid:{ete_id, vc_conn_unused});
+ }
+ }
+ }
+}
+
+/* per-session component; we typically have 1..N per testcase */
+type component Cli_Session_CT {
+ var SessionPars g_pars;
+
+ port DIAMETER_Conn_PT S6a;
+ port DIAMETEREM_PROC_PT S6a_PROC;
+}
+function f_diam_connhldr_expect_eteid(UINT32 ete_id) runs on Cli_Session_CT {
+ S6a_PROC.call(DIAMETEREM_register_eteid:{ete_id, null}) {
+ [] S6a_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+}
+
+/* configuration data for a given Session */
+type record SessionPars {
+ hexstring imsi,
+ uint32_t s6a_next_hbh_id,
+ uint32_t s6a_next_ete_id
+}
+
+template (value) SessionPars
+t_SessionPars(hexstring imsi, uint32_t s6a_next_hbh_id := 1000, uint32_t s6a_next_ete_id := 22220) := {
+ imsi := imsi,
+ s6a_next_hbh_id := s6a_next_hbh_id,
+ s6a_next_ete_id := s6a_next_ete_id
+}
+
+type function void_fn() runs on Cli_Session_CT;
+
+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 MTC_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;
+
+ /* S6a setup: */
+ pars := {
+ remote_ip := mp_hss_hostname,
+ remote_sctp_port := mp_hss_port,
+ local_ip := mp_diam_local_hostname,
+ local_sctp_port := mp_diam_local_port,
+ origin_host := mp_diam_orig_host,
+ origin_realm := mp_diam_orig_realm,
+ auth_app_id := omit,
+ vendor_app_id := c_DIAMETER_3GPP_S6_AID
+ };
+ vc_S6a := DIAMETER_Emulation_CT.create(id);
+ map(vc_S6a:DIAMETER, system:DIAMETER_CODEC_PT);
+ connect(vc_S6a:DIAMETER_UNIT, self:S6a_UNIT);
+ connect(vc_S6a:DIAMETER_PROC, self:S6a_PROC);
+ vc_S6a.start(DIAMETER_Emulation.main(ops, pars, id));
+
+ f_diameter_wait_capability(S6a_UNIT);
+ /* Give some time for our emulation to get out of SUSPECT list of SUT (3 watchdong ping-pongs):
+ * RFC6733 sec 5.1
+ * RFC3539 sec 3.4.1 [5]
+ * https://github.com/freeDiameter/freeDiameter/blob/master/libfdcore/p_psm.c#L49
+ */
+ f_sleep(1.0);
+}
+
+private function f_init(float guard_timeout := 60.0) runs on MTC_CT {
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+ f_init_diameter(testcasename());
+}
+
+function f_start_handler(void_fn fn, template (omit) SessionPars pars_tmpl := omit)
+runs on MTC_CT return Cli_Session_CT {
+ var charstring id := testcasename();
+ var DIAMETER_ConnHdlr_CT vc_conn_s6a;
+ var Cli_Session_CT vc_conn;
+ var SessionPars pars;
+
+ if (isvalue(pars_tmpl)) {
+ pars := valueof(pars_tmpl);
+ } else {
+ /*TODO: set default values */
+ }
+
+ vc_conn := Cli_Session_CT.create(id);
+
+ vc_conn_s6a := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_s6a:DIAMETER, vc_S6a:DIAMETER_CLIENT);
+ connect(vc_conn_s6a:DIAMETER_PROC, vc_S6a:DIAMETER_PROC);
+ connect(vc_conn:S6a, vc_conn_s6a:DIAMETER_CLIENT);
+ connect(vc_conn:S6a_PROC, vc_conn_s6a:DIAMETER_PROC_CLIENT);
+ vc_conn_s6a.start(f_diam_connhldr_ct_main(pars.imsi));
+
+ vc_conn.start(f_handler_init(fn, pars));
+ return vc_conn;
+}
+
+private function f_handler_init(void_fn fn, SessionPars pars)
+runs on Cli_Session_CT {
+ g_pars := valueof(pars);
+ fn.apply();
+}
+
+/* ULR + ULA against HSS */
+private function f_dia_ulr_ula(template (present) AVP_list ula_sub_data) runs on Cli_Session_CT {
+ var octetstring sess_id := char2oct("foobar");
+ var PDU_DIAMETER rx_dia;
+ var UINT32 hbh_id := int2oct(g_pars.s6a_next_hbh_id, 4);
+ var UINT32 ete_id := int2oct(g_pars.s6a_next_ete_id, 4);
+
+ /* Unlike ULR, ULA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_diam_connhldr_expect_eteid(ete_id);
+
+ /* TODO: change this into a ts_DIA_ULR */
+ S6a.send(ts_DIA_ULR(g_pars.imsi, '111F11'O, sess_id,
+ mp_diam_orig_host, mp_diam_orig_realm,
+ mp_diam_dest_realm, hbh_id, ete_id));
+ g_pars.s6a_next_hbh_id := g_pars.s6a_next_hbh_id + 1;
+ g_pars.s6a_next_ete_id := g_pars.s6a_next_ete_id + 1;
+
+ alt {
+ [] S6a.receive(tr_DIA_ULA(ula_sub_data, sess_id, ?, ?, hbh_id, ete_id)) -> value rx_dia {
+ setverdict(pass);
+ }
+ [] S6a.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
+ }
+ }
+}
+
+/* create a session, expect it to succeed */
+private function f_TC_ulr_ula() runs on Cli_Session_CT {
+ var template (present) AVP_list sub_data := superset(
+ tr_AVP_3GPP_SubscriberStatus(SERVICE_GRANTED),
+ tr_AVP_3GPP_SubscrRauTauTmr(?),
+ tr_AVP_3GPP_AMBR(?, ?),
+ tr_AVP_3GPP_ApnConfigProfile(superset(
+ tr_AVP_3GPP_ContextId(?),
+ tr_AVP_3GPP_AllApnConfigsIncl,
+ tr_AVP_3GPP_ApnConfig(?, ?, ?)
+ ))
+ );
+
+ f_dia_ulr_ula(sub_data);
+ setverdict(pass);
+}
+testcase TC_ulr_ula() runs on MTC_CT {
+ var Cli_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars(subscribers[0]));
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_ulr_ula), pars);
+ vc_conn.done;
+}
+
+/* Same as TC_ulr_ula, but done on a subscriber configured with
+Subscriber-Status=1 (OPERATOR_DETERMINED_BARRING) and
+Operator-Determined-Barring=7. */
+private function f_TC_ulr_ula_subscr_op_det_barring_7() runs on Cli_Session_CT {
+ var template (present) AVP_list sub_data := superset(
+ tr_AVP_3GPP_SubscriberStatus(OPERATOR_DETERMINED_BARRING),
+ tr_AVP_3GPP_OperatorDeterminedBarring(7),
+ tr_AVP_3GPP_SubscrRauTauTmr(?),
+ tr_AVP_3GPP_AMBR(?, ?),
+ tr_AVP_3GPP_ApnConfigProfile(superset(
+ tr_AVP_3GPP_ContextId(?),
+ tr_AVP_3GPP_AllApnConfigsIncl,
+ tr_AVP_3GPP_ApnConfig(?, ?, ?)
+ ))
+ );
+
+ f_dia_ulr_ula(sub_data);
+ setverdict(pass);
+}
+testcase TC_ulr_ula_subscr_op_det_barring_7() runs on MTC_CT {
+ var Cli_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars(subscribers[1]));
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_ulr_ula_subscr_op_det_barring_7), pars);
+ vc_conn.done;
+}
+
+
+control {
+ execute( TC_ulr_ula() );
+ execute( TC_ulr_ula_subscr_op_det_barring_7() );
+}
+
+
+}
diff --git a/hss/expected-results.xml b/hss/expected-results.xml
new file mode 100644
index 00000000..f9b5c972
--- /dev/null
+++ b/hss/expected-results.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='1' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='HSS_Tests' name='TC_ulr_ula' time='MASKED'/>
+ <testcase classname='HSS_Tests' name='TC_ulr_ula_subscr_op_det_barring_7' time='MASKED'/>
+</testsuite>
diff --git a/hss/gen_links.sh b/hss/gen_links.sh
new file mode 100755
index 00000000..7160832e
--- /dev/null
+++ b/hss/gen_links.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit 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.DIAMETER_ProtocolModule_Generator/src
+FILES="DIAMETER_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn "
+FILES+="DIAMETER_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/hss/regen_makefile.sh b/hss/regen_makefile.sh
new file mode 100755
index 00000000..23fbd738
--- /dev/null
+++ b/hss/regen_makefile.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+NAME=HSS_Tests
+
+FILES="
+ *.ttcn
+ DIAMETER_CodecPort_CtrlFunctDef.cc
+ DIAMETER_EncDec.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/lapdm/regen_makefile.sh b/lapdm/regen_makefile.sh
index bb02fe8c..f354e873 100755
--- a/lapdm/regen_makefile.sh
+++ b/lapdm/regen_makefile.sh
@@ -1,5 +1,16 @@
#!/bin/sh
-FILES="*.ttcn UD_PT.cc UD_PT.hh RLCMAC_EncDec.cc L1CTL_PortType_CtrlFunctDef.cc"
+NAME=L1CTL_Test
-../regen-makefile.sh L1CTL_Test.ttcn $FILES
+FILES="
+ *.ttcn
+ L1CTL_PortType_CtrlFunctDef.cc
+ RLCMAC_EncDec.cc
+ UD_PT.cc
+ UD_PT.hh
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/library/AMR_Types.ttcn b/library/AMR_Types.ttcn
new file mode 100644
index 00000000..f453234c
--- /dev/null
+++ b/library/AMR_Types.ttcn
@@ -0,0 +1,91 @@
+/*
+ * (C) 2019-2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+module AMR_Types {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+/* AMR voice frame type identifiers
+ * See also 3GPP TS 26.101, Table 1a: Interpretation of Frame Type, Mode
+ * Indication and Mode Request fields */
+type enumerated AMRFT {
+ AMR_FT_0, /* 4.75 */
+ AMR_FT_1, /* 5.15 */
+ AMR_FT_2, /* 5.90 */
+ AMR_FT_3, /* 6.70 */
+ AMR_FT_4, /* 7.40 */
+ AMR_FT_5, /* 7.95 */
+ AMR_FT_6, /* 10.2 */
+ AMR_FT_7, /* 12.2 */
+ AMR_FT_SID /* SID */
+};
+
+/* AMR voice frame length (in bytes, rounded),
+ * See also RFC 3267, chapter 3.6 */
+const integer c_AMRFT_len[9] := {12, 13, 15, 17, 19, 20, 26, 31, 5};
+
+function f_amrft_payload_len(INT4b amr_ft) return integer {
+ return c_AMRFT_len[amr_ft];
+}
+
+const integer c_AMRFT_bits_len[9] := {95, 103, 118, 134, 148, 159, 204, 244, 39};
+
+function f_amrft_payload_bits_len(INT4b amr_ft) return integer {
+ return c_AMRFT_bits_len[amr_ft];
+}
+
+type record RTP_AMR_Hdr {
+ uint4_t cmr,
+ BIT4 padding1,
+ BIT1 f,
+ uint4_t ft,
+ BIT1 q,
+ BIT2 padding2
+} with { variant "FIELDORDER(msb)" };
+
+template (value) RTP_AMR_Hdr ts_RTP_AMR_Hdr(template (value) uint4_t cmr,
+ template (value) uint4_t ft,
+ template (value) BIT1 q := '1'B,
+ template (value) BIT1 f := '0'B) := {
+ cmr := cmr,
+ padding1 := '0000'B,
+ f := f,
+ ft := ft,
+ q := q,
+ padding2 := '00'B
+}
+external function enc_RTP_AMR_Hdr(in RTP_AMR_Hdr amr_hdr) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_RTP_AMR_Hdr(in octetstring stream) return RTP_AMR_Hdr
+ with { extension "prototype(convert) decode(RAW)" };
+
+
+type record RTP_AMR_BWE_Hdr {
+ uint4_t cmr,
+ BIT1 f,
+ uint4_t ft,
+ BIT1 q
+} with { variant "FIELDORDER(msb)" };
+template (value) RTP_AMR_BWE_Hdr ts_RTP_AMR_BWE_Hdr(template (value) uint4_t cmr,
+ template (value) uint4_t ft,
+ template (value) BIT1 q := '1'B,
+ template (value) BIT1 f := '0'B) := {
+ cmr := cmr,
+ f := f,
+ ft := ft,
+ q := q
+}
+external function enc_RTP_AMR_BWE_Hdr(in RTP_AMR_BWE_Hdr amr_hdr) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_RTP_AMR_BWE_Hdr(in octetstring stream) return RTP_AMR_BWE_Hdr
+ with { extension "prototype(convert) decode(RAW)" };
+
+} with { encode "RAW"}
diff --git a/library/AbisOML_Types.ttcn b/library/AbisOML_Types.ttcn
index c4fd81c2..99ad2520 100644
--- a/library/AbisOML_Types.ttcn
+++ b/library/AbisOML_Types.ttcn
@@ -100,7 +100,7 @@ type enumerated OML_FOM_MessageType {
NM_MT_DISC_TERR_TRAF ('2d'H),
NM_MT_DISC_TERR_TRAF_ACK ('2e'H),
NM_MT_DISC_TERR_TRAF_NACK ('2f'H),
- /* Transmission Management Messages */
+ /* Transmission Management Messages */
NM_MT_CONN_MDROP_LINK ('31'H),
NM_MT_CONN_MDROP_LINK_ACK ('32'H),
NM_MT_CONN_MDROP_LINK_NACK ('33'H),
@@ -616,6 +616,15 @@ type record OML_FOM_T200 {
uint8_t sacch_rch_sapi3_10ms
};
+/* Section 9.4.64 */
+type record OML_FOM_ARI {
+ uint16_t len,
+ uint8_t non_reported_attr_len,
+ set of uint8_t non_reported_attr optional,
+ OML_FOM_IE_List ies optional
+} with { variant (len) "LENGTHTO(non_reported_attr_len,non_reported_attr,ies)"
+ variant (non_reported_attr_len) "LENGTHTO(non_reported_attr)" };
+
type union OML_FOM_IE_Body {
OML_FOM_AbisChannel abis_channel,
OML_FOM_AdministrativeState adm_state,
@@ -669,6 +678,8 @@ type union OML_FOM_IE_Body {
uint16_t paging_cfg,
OCT2 freq_ctrl,
+ OML_FOM_ARI ari,
+
OML_IE_L16V other
};
@@ -728,6 +739,8 @@ type record OML_FOM_IE {
paging_cfg, iei = NM_ATT_IPACC_PAGING_CFG;
freq_ctrl, iei = NM_ATT_IPACC_FREQ_CTRL;
+ ari, iei = NM_ATT_GET_ARI;
+
other, OTHERWISE;
)" };
@@ -884,10 +897,12 @@ template (value) OML_PDU ts_OML_StateChgEvtRep(template (value) OML_FOM_ObjectCl
template OML_PDU tr_OML_StateChgEvtRep(template OML_FOM_ObjectClass obj_class,
template OML_FOM_ObjectInstance obj_inst,
template OML_FOM_OperationalState opstate := ?,
- template OML_FOM_AvailabilityStatus avstate := ?) :=
+ template OML_FOM_AvailabilityStatus avstate := ?,
+ template OML_FOM_AdministrativeState admstate := ?) :=
tr_OML_MsgType(NM_MT_STATECHG_EVENT_REP, obj_class, obj_inst, {
tr_OML_IE(NM_ATT_OPER_STATE, OML_FOM_IE_Body:{opstate := opstate}),
- tr_OML_IE(NM_ATT_AVAIL_STATUS, OML_FOM_IE_Body:{avail_status := {len := 1, avail_status := avstate}})
+ tr_OML_IE(NM_ATT_AVAIL_STATUS, OML_FOM_IE_Body:{avail_status := {len := 1, avail_status := avstate}}),
+ tr_OML_IE(NM_ATT_ADM_STATE, OML_FOM_IE_Body:{adm_state := admstate})
});
/* 8.8.2 Failure Event Report */
@@ -1122,6 +1137,20 @@ template OML_PDU tr_OML_GetAttributes(template OML_FOM_ObjectClass obj_class,
tr_OML_IE(NM_ATT_LIST_REQ_ATTR, OML_FOM_IE_Body:{other := tr_OML_IE_L16V(?, req_attr)})
});
+/* 8.11.3 Get Attributes Response */
+template (value) OML_PDU ts_OML_GetAttributesResponse(template (value) OML_FOM_ObjectClass obj_class,
+ template (value) OML_FOM_ObjectInstance obj_inst,
+ template (value) octetstring req_attr) :=
+ ts_OML_MsgType(NM_MT_GET_ATTR_RESP, obj_class, obj_inst, {
+ ts_OML_IE(NM_ATT_GET_ARI, OML_FOM_IE_Body:{other := ts_OML_IE_L16V(0, req_attr)})
+ });
+template OML_PDU tr_OML_GetAttributesResponse(template OML_FOM_ObjectClass obj_class,
+ template OML_FOM_ObjectInstance obj_inst,
+ template OML_FOM_ARI ari := ?) :=
+ tr_OML_MsgType(NM_MT_GET_ATTR_RESP, obj_class, obj_inst, {
+ tr_OML_IE(NM_ATT_GET_ARI, OML_FOM_IE_Body:{ari := ari})
+ });
+
/* convert a request into an ACK */
function f_OML_make_ack(OML_PDU orig) return OML_PDU {
var OML_PDU resp := orig;
@@ -1197,6 +1226,21 @@ function f_OML_make_nack_exp(OML_PDU orig, template OML_FOM_NackCause cause) ret
return resp;
}
+function f_OML_FOM_IE_List_get_ie(OML_FOM_IE_List ie_list, OML_FOM_IE_Type iei) return OML_FOM_IE_Body
+{
+ for (var integer i := 0; i < lengthof(ie_list); i := i + 1) {
+ if (ie_list[i].iei == iei) {
+ return ie_list[i].body;
+ }
+ }
+ var OML_FOM_IE_Body dummy;
+ return dummy; /*TODO: setverdict(fail?) */
+}
+
+function f_OML_FOM_get_ie(OML_FOM fom, OML_FOM_IE_Type iei) return OML_FOM_IE_Body
+{
+ return f_OML_FOM_IE_List_get_ie(fom.ies, iei);
+}
/***********************************************************************
@@ -1205,13 +1249,17 @@ function f_OML_make_nack_exp(OML_PDU orig, template OML_FOM_NackCause cause) ret
-template (value) OML_PDU ts_OML_IPA_RslConnect(uint8_t stream_id, uint16_t port_nr) :=
- ts_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT, NM_OC_BASEB_TRANSC, ts_OML_ObjectInstance(0,0,255), {
+template (value) OML_PDU ts_OML_IPA_RslConnect(template (value) OML_FOM_ObjectInstance obj_inst,
+ template (value) uint8_t stream_id,
+ template (value) uint16_t port_nr) :=
+ ts_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT, NM_OC_BASEB_TRANSC, obj_inst, {
ts_OML_IE(NM_ATT_IPACC_STREAM_ID, OML_FOM_IE_Body:{stream_id := stream_id}),
ts_OML_IE(NM_ATT_IPACC_DST_IP_PORT, OML_FOM_IE_Body:{portnr := port_nr})
});
-template OML_PDU tr_OML_IPA_RslConnect(template uint8_t stream_id, template uint16_t port_nr) :=
- tr_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT, NM_OC_BASEB_TRANSC, tr_OML_ObjectInstance(0,0,255), {
+template OML_PDU tr_OML_IPA_RslConnect(template (present) OML_FOM_ObjectInstance obj_inst,
+ template (present) uint8_t stream_id,
+ template (present) uint16_t port_nr) :=
+ tr_OML_IPA_MsgType(NM_MT_IPACC_RSL_CONNECT, NM_OC_BASEB_TRANSC, obj_inst, {
tr_OML_IE(NM_ATT_IPACC_STREAM_ID, OML_FOM_IE_Body:{stream_id := stream_id}),
tr_OML_IE(NM_ATT_IPACC_DST_IP_PORT, OML_FOM_IE_Body:{portnr := port_nr})
});
diff --git a/library/BSSAP_CodecPort.ttcn b/library/BSSAP_CodecPort.ttcn
index fdece085..5339b323 100644
--- a/library/BSSAP_CodecPort.ttcn
+++ b/library/BSSAP_CodecPort.ttcn
@@ -126,7 +126,7 @@ type record BSSAP_N_DATA_ind
SCCP_PAR_Importance importance optional
}
-template BSSAP_N_DATA_ind tr_BSSAP_DATA_ind(SCCP_PAR_Connection_Id conn_id,
+template BSSAP_N_DATA_ind tr_BSSAP_DATA_ind(template SCCP_PAR_Connection_Id conn_id,
template PDU_BSSAP bssap := *) := {
userData := bssap,
connectionId := conn_id,
diff --git a/library/BSSAP_LE_Adapter.ttcn b/library/BSSAP_LE_Adapter.ttcn
new file mode 100644
index 00000000..9305c63b
--- /dev/null
+++ b/library/BSSAP_LE_Adapter.ttcn
@@ -0,0 +1,137 @@
+module BSSAP_LE_Adapter {
+
+/* This module implements a 'dumb' BSSAP_LE adapter. It creates the M3UA and SCCP components and stacks a
+ * BSSAP_LE codec port on top. As a result, it provides the ability to transceive SCCP-User-SAP primitives
+ * with deoded BSSAP_LE payload. Use this if you want to have full control about what you transmit or
+ * receive, without any automatisms in place. Allows you to refuse connections or other abnormal behavior. */
+
+/* (C) 2017-2020 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from M3UA_Emulation all;
+import from MTP3asp_Types all;
+import from MTP3asp_PortType all;
+
+import from IPA_Emulation all;
+
+import from SCCP_Types all;
+import from SCCPasp_Types all;
+import from SCCP_Emulation all;
+import from SCCP_Templates all;
+
+import from SCTPasp_Types all;
+import from SCTPasp_PortType all;
+
+import from BSSMAP_LE_Templates all;
+import from BSSAP_LE_Emulation all;
+
+type record BSSAP_LE_Adapter {
+ /* component references */
+ M3UA_CT vc_M3UA, /* only in 3GPP AoIP */
+ SCCP_CT vc_SCCP,
+
+ MSC_SCCP_MTP3_parameters sccp_pars,
+ SCCP_PAR_Address sccp_addr_own,
+ SCCP_PAR_Address sccp_addr_peer,
+
+ /* handler mode */
+ BSSAP_LE_Emulation_CT vc_BSSAP_LE
+}
+
+type record BSSAP_LE_Configuration {
+ charstring sccp_service_type,
+ SCTP_Association_Address sctp_addr,
+ integer own_pc,
+ integer own_ssn,
+ integer peer_pc,
+ integer peer_ssn,
+ octetstring sio,
+ integer rctx optional
+};
+type record of BSSAP_LE_Configuration BSSAP_LE_Configurations;
+
+private function init_pars(inout BSSAP_LE_Adapter ba, in BSSAP_LE_Configuration cfg) {
+ ba.sccp_pars := {
+ sio := {
+ ni := substr(oct2bit(cfg.sio),0,2),
+ prio := substr(oct2bit(cfg.sio),2,2),
+ si := substr(oct2bit(cfg.sio),4,4)
+ },
+ opc := cfg.own_pc,
+ dpc := cfg.peer_pc,
+ sls := 0,
+ sccp_serviceType := cfg.sccp_service_type,
+ ssn := cfg.own_ssn
+ };
+ ba.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(cfg.own_pc, cfg.own_ssn, cfg.sio, cfg.sccp_service_type));
+ ba.sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(cfg.peer_pc, cfg.peer_ssn, cfg.sio, cfg.sccp_service_type));
+}
+
+
+function f_bssap_le_adapter_init(inout BSSAP_LE_Adapter ba, in BSSAP_LE_Configuration cfg, charstring id,
+ template BssapLeOps ops) {
+ init_pars(ba, cfg);
+ ops.sccp_addr_local := ba.sccp_addr_own;
+ ops.sccp_addr_peer := ba.sccp_addr_peer;
+
+ var template (omit) integer rctx;
+ if (not ispresent(cfg.rctx)) {
+ rctx := omit;
+ } else {
+ rctx := cfg.rctx;
+ }
+
+ /* create components */
+ ba.vc_SCCP := SCCP_CT.create(id & "-SCCP") alive;
+ if (isvalue(ops)) {
+ ba.vc_BSSAP_LE := BSSAP_LE_Emulation_CT.create(id & "-BSSAP_LE") alive;
+ } else {
+ ba.vc_BSSAP_LE := null;
+ }
+ ba.vc_M3UA := M3UA_CT.create(id & "-M3UA") alive;
+ map(ba.vc_M3UA:SCTP_PORT, system:sctp);
+ /* connect MTP3 service provider (M3UA) to lower side of SCCP */
+ connect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
+ ba.vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr, rctx));
+
+ if (isvalue(ops)) {
+ timer T := 5.0;
+ T.start;
+ //T.timeout;
+ /* connect BSSNAP component to upper side of SCCP */
+ log("Connecting BSSAP_LE_Emulation to SCCP_SP_PORT");
+ connect(ba.vc_BSSAP_LE:BSSAP_LE, ba.vc_SCCP:SCCP_SP_PORT);
+ log("Starting BSSAP_LE_Emulation");
+ ba.vc_BSSAP_LE.start(BSSAP_LE_Emulation.main(valueof(ops), ""));
+ }
+
+
+}
+
+function f_bssap_le_adapter_start(inout BSSAP_LE_Adapter ba) {
+ ba.vc_SCCP.start(SCCPStart(ba.sccp_pars));
+}
+
+function f_bssap_le_adapter_cleanup(inout BSSAP_LE_Adapter ba) {
+ if (ba.vc_BSSAP_LE != null) {
+ disconnect(ba.vc_BSSAP_LE:BSSAP_LE, ba.vc_SCCP:SCCP_SP_PORT);
+ ba.vc_BSSAP_LE.stop;
+ }
+ unmap(ba.vc_M3UA:SCTP_PORT, system:sctp);
+ disconnect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
+ ba.vc_M3UA.stop;
+ ba.vc_SCCP.stop;
+}
+
+
+}
diff --git a/library/BSSAP_LE_CodecPort.ttcn b/library/BSSAP_LE_CodecPort.ttcn
new file mode 100644
index 00000000..f1d930f5
--- /dev/null
+++ b/library/BSSAP_LE_CodecPort.ttcn
@@ -0,0 +1,380 @@
+module BSSAP_LE_CodecPort {
+
+/* Simple BSSAP_LE Codec Port, translating between raw SCCP primitives with
+ * octetstring payload towards the SCCP provider, and BSSAP_LE-SCCP primitives
+ * which carry the decoded BSSAP_LE data types as payload.
+ *
+ * (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from SCCPasp_Types all;
+import from SCCP_Types all;
+
+import from BSSAP_LE_Types all;
+
+type record BSSAP_LE_N_CONNECT_req
+{
+ SCCP_PAR_Address calledAddress,
+ SCCP_PAR_Address callingAddress optional,
+ SCCP_PAR_Expedited_Data_Sel expeditedDataSel optional,
+ SCCP_PAR_Quality_Of_Service qualityOfService optional,
+ PDU_BSSAP_LE userData optional,
+ SCCP_PAR_Connection_Id connectionId optional,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_CONNECT_req ts_BSSAP_LE_CONNECT_req(SCCP_PAR_Address called,
+ SCCP_PAR_Address calling,
+ SCCP_PAR_Connection_Id conn_id,
+ template PDU_BSSAP_LE bssap := omit) := {
+ calledAddress := called,
+ callingAddress := calling,
+ expeditedDataSel := omit,
+ qualityOfService := omit,
+ userData := bssap,
+ connectionId := conn_id,
+ importance := omit
+}
+
+type record BSSAP_LE_N_CONNECT_ind
+{
+ SCCP_PAR_Address calledAddress,
+ SCCP_PAR_Address callingAddress optional,
+ SCCP_PAR_Quality_Of_Service qualityOfService optional,
+ PDU_BSSAP_LE userData optional,
+ SCCP_PAR_Connection_Id connectionId optional,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_CONNECT_ind tr_BSSAP_LE_CONNECT_ind(template SCCP_PAR_Address called,
+ template SCCP_PAR_Address calling,
+ template PDU_BSSAP_LE payload := *) := {
+ calledAddress := called,
+ callingAddress := calling,
+ qualityOfService := *,
+ userData := payload,
+ connectionId := *,
+ importance := *
+}
+
+type record BSSAP_LE_N_CONNECT_res
+{
+ SCCP_PAR_Address respondingAddress optional,
+ SCCP_PAR_Expedited_Data_Sel expeditedDataSel optional,
+ SCCP_PAR_Quality_Of_Service qualityOfService optional,
+ PDU_BSSAP_LE userData optional,
+ SCCP_PAR_Connection_Id connectionId optional,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_CONNECT_res ts_BSSAP_LE_CONNECT_res(SCCP_PAR_Connection_Id conn_id,
+ template PDU_BSSAP_LE bssap := omit) := {
+ respondingAddress := omit,
+ expeditedDataSel := omit,
+ qualityOfService := omit,
+ userData := bssap,
+ connectionId := conn_id,
+ importance := omit
+}
+
+type record BSSAP_LE_N_CONNECT_cfm
+{
+ SCCP_PAR_Address respondingAddress optional,
+ SCCP_PAR_Quality_Of_Service qualityOfService optional,
+ PDU_BSSAP_LE userData optional,
+ SCCP_PAR_Connection_Id connectionId optional,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_CONNECT_cfm tr_BSSAP_LE_CONNECT_cfm(template SCCP_PAR_Connection_Id conn_id,
+ template PDU_BSSAP_LE bssap := *) := {
+ respondingAddress := *,
+ qualityOfService := *,
+ userData := bssap,
+ connectionId := conn_id,
+ importance := *
+}
+
+type record BSSAP_LE_N_DATA_req
+{
+ PDU_BSSAP_LE userData ,
+ SCCP_PAR_Connection_Id connectionId optional ,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_DATA_req ts_BSSAP_LE_DATA_req(SCCP_PAR_Connection_Id conn_id,
+ template PDU_BSSAP_LE bssap) := {
+ userData := bssap,
+ connectionId := conn_id,
+ importance := omit
+}
+
+
+type record BSSAP_LE_N_DATA_ind
+{
+ PDU_BSSAP_LE userData ,
+ SCCP_PAR_Connection_Id connectionId optional ,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_DATA_ind tr_BSSAP_LE_DATA_ind(SCCP_PAR_Connection_Id conn_id,
+ template PDU_BSSAP_LE bssap := *) := {
+ userData := bssap,
+ connectionId := conn_id,
+ importance := *
+}
+
+
+type record BSSAP_LE_N_DISCONNECT_req
+{
+ SCCP_PAR_Address respondingAddress optional,
+ SCCP_PAR_Reason reason ,
+ PDU_BSSAP_LE userData optional ,
+ SCCP_PAR_Connection_Id connectionId optional ,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_DISCONNECT_req ts_BSSAP_LE_DISC_req(SCCP_PAR_Connection_Id conn_id,
+ template SCCP_PAR_Reason reason,
+ template PDU_BSSAP_LE bssap := omit) := {
+ respondingAddress := omit,
+ reason := reason,
+ userData := bssap,
+ connectionId := conn_id,
+ importance := omit
+}
+
+
+type record BSSAP_LE_N_DISCONNECT_ind
+{
+ SCCP_PAR_Originator originator ,
+ SCCP_PAR_Address respondingAddress optional ,
+ SCCP_PAR_Reason reason ,
+ PDU_BSSAP_LE userData optional ,
+ SCCP_PAR_Connection_Id connectionId optional ,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_DISCONNECT_ind tr_BSSAP_LE_DISC_ind(template SCCP_PAR_Connection_Id conn_id,
+ template SCCP_PAR_Originator originator,
+ template SCCP_PAR_Reason reason,
+ template PDU_BSSAP_LE bssap := *) := {
+ originator := originator,
+ respondingAddress:= *,
+ reason := reason,
+ userData := bssap,
+ connectionId := conn_id,
+ importance := *
+}
+
+type record BSSAP_LE_N_UNITDATA_req
+{
+ SCCP_PAR_Address calledAddress ,
+ SCCP_PAR_Address callingAddress ,
+ SCCP_PAR_Sequence_Control sequenceControl optional ,
+ SCCP_PAR_Return_Option returnOption optional ,
+ PDU_BSSAP_LE userData ,
+ SCCP_PAR_Importance importance optional
+ }
+
+template BSSAP_LE_N_UNITDATA_req ts_BSSAP_LE_UNITDATA_req(SCCP_PAR_Address called, SCCP_PAR_Address calling, template PDU_BSSAP_LE payload) := {
+ calledAddress := called,
+ callingAddress := calling,
+ sequenceControl := omit,
+ returnOption := omit,
+ userData := payload,
+ importance := omit
+}
+
+type record BSSAP_LE_N_UNITDATA_ind
+{
+ SCCP_PAR_Address calledAddress ,
+ SCCP_PAR_Address callingAddress ,
+ SCCP_PAR_Sequence_Control sequenceControl optional ,
+ SCCP_PAR_Return_Option returnOption optional ,
+ PDU_BSSAP_LE userData ,
+ SCCP_PAR_Importance importance optional
+}
+
+template BSSAP_LE_N_UNITDATA_ind tr_BSSAP_LE_UNITDATA_ind(template SCCP_PAR_Address called, template SCCP_PAR_Address calling, template PDU_BSSAP_LE payload) := {
+ calledAddress := called,
+ callingAddress := calling,
+ sequenceControl := *,
+ returnOption := *,
+ userData := payload,
+ importance := *
+}
+
+type record BSSAP_LE_N_NOTICE_ind
+{
+ SCCP_PAR_Address calledAddress ,
+ SCCP_PAR_Address callingAddress ,
+ SCCP_PAR_Reason_For_Return reasonForReturn ,
+ PDU_BSSAP_LE userData ,
+ SCCP_PAR_Importance importance optional
+}
+
+
+
+private function f_dec_ConnectInd(in ASP_SCCP_N_CONNECT_ind pin, out BSSAP_LE_N_CONNECT_ind pout) {
+ pout.calledAddress := pin.calledAddress;
+ pout.callingAddress := pin.callingAddress;
+ pout.qualityOfService := pin.qualityOfService;
+ if (ispresent(pin.userData)) {
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_dec_ConnectCfm(in ASP_SCCP_N_CONNECT_cfm pin, out BSSAP_LE_N_CONNECT_cfm pout) {
+ pout.respondingAddress := pin.respondingAddress;
+ pout.qualityOfService := pin.qualityOfService;
+ if (ispresent(pin.userData)) {
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_dec_DataInd(in ASP_SCCP_N_DATA_ind pin, out BSSAP_LE_N_DATA_ind pout) {
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_dec_DisconnectInd(in ASP_SCCP_N_DISCONNECT_ind pin, out BSSAP_LE_N_DISCONNECT_ind pout) {
+ pout.originator := pin.originator;
+ pout.respondingAddress := pin.respondingAddress;
+ pout.reason := pin.reason;
+ if (ispresent(pin.userData)) {
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_dec_UnitdataInd(in ASP_SCCP_N_UNITDATA_ind pin, out BSSAP_LE_N_UNITDATA_ind pout) {
+ pout.calledAddress := pin.calledAddress;
+ pout.callingAddress := pin.callingAddress;
+ pout.sequenceControl := pin.sequenceControl;
+ pout.returnOption := pin.returnOption;
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_dec_NoticeInd(in ASP_SCCP_N_NOTICE_ind pin, out BSSAP_LE_N_NOTICE_ind pout) {
+ pout.calledAddress := pin.calledAddress;
+ pout.callingAddress := pin.callingAddress;
+ pout.reasonForReturn := pin.reasonForReturn;
+ pout.userData := dec_PDU_BSSAP_LE(pin.userData);
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+
+
+private function f_enc_ConnectReq(in BSSAP_LE_N_CONNECT_req pin, out ASP_SCCP_N_CONNECT_req pout) {
+ pout.calledAddress := pin.calledAddress;
+ pout.callingAddress := pin.callingAddress;
+ pout.expeditedDataSel := pin.expeditedDataSel;
+ pout.qualityOfService := pin.qualityOfService;
+ if (ispresent(pin.userData)) {
+ pout.userData := enc_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_enc_ConnectRes(in BSSAP_LE_N_CONNECT_res pin, out ASP_SCCP_N_CONNECT_res pout) {
+ pout.respondingAddress := pin.respondingAddress;
+ pout.expeditedDataSel := pin.expeditedDataSel;
+ pout.qualityOfService := pin.qualityOfService;
+ if (ispresent(pin.userData)) {
+ pout.userData := enc_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_enc_DataReq(in BSSAP_LE_N_DATA_req pin, out ASP_SCCP_N_DATA_req pout) {
+ pout.userData := enc_PDU_BSSAP_LE(pin.userData);
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_enc_DisconnectReq(in BSSAP_LE_N_DISCONNECT_req pin, out ASP_SCCP_N_DISCONNECT_req pout) {
+ pout.respondingAddress := pin.respondingAddress;
+ pout.reason := pin.reason;
+ if (ispresent(pin.userData)) {
+ pout.userData := enc_PDU_BSSAP_LE(pin.userData);
+ } else {
+ pout.userData := omit;
+ }
+ pout.connectionId := pin.connectionId;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+private function f_enc_UnitdataReq(in BSSAP_LE_N_UNITDATA_req pin, out ASP_SCCP_N_UNITDATA_req pout) {
+ pout.calledAddress := pin.calledAddress;
+ pout.callingAddress := pin.callingAddress;
+ pout.userData := enc_PDU_BSSAP_LE(pin.userData);
+ pout.sequenceControl := pin.sequenceControl;
+ pout.returnOption := pin.returnOption;
+ pout.importance := pin.importance;
+} with {extension "prototype(fast)" }
+
+type port BSSAP_LE_CODEC_PT message {
+ out BSSAP_LE_N_CONNECT_req,
+ BSSAP_LE_N_CONNECT_res,
+ BSSAP_LE_N_DATA_req,
+ BSSAP_LE_N_DISCONNECT_req,
+ BSSAP_LE_N_UNITDATA_req,
+ ASP_SCCP_N_RESET_req;
+ in BSSAP_LE_N_CONNECT_ind,
+ BSSAP_LE_N_CONNECT_cfm,
+ BSSAP_LE_N_DATA_ind,
+ BSSAP_LE_N_DISCONNECT_ind,
+ BSSAP_LE_N_UNITDATA_ind,
+ BSSAP_LE_N_NOTICE_ind,
+ ASP_SCCP_N_RESET_ind,
+ ASP_SCCP_N_RESET_cfm,
+ ASP_SCCP_N_STATE_ind;
+} with { extension "internal user SCCPasp_PT
+ out(BSSAP_LE_N_CONNECT_req -> ASP_SCCP_N_CONNECT_req: function(f_enc_ConnectReq);
+ BSSAP_LE_N_CONNECT_res -> ASP_SCCP_N_CONNECT_res: function(f_enc_ConnectRes);
+ BSSAP_LE_N_DATA_req -> ASP_SCCP_N_DATA_req: function(f_enc_DataReq);
+ BSSAP_LE_N_DISCONNECT_req -> ASP_SCCP_N_DISCONNECT_req: function(f_enc_DisconnectReq);
+ BSSAP_LE_N_UNITDATA_req -> ASP_SCCP_N_UNITDATA_req: function(f_enc_UnitdataReq);
+ ASP_SCCP_N_RESET_req -> ASP_SCCP_N_RESET_req: simple)
+ in(ASP_SCCP_N_CONNECT_ind -> BSSAP_LE_N_CONNECT_ind: function(f_dec_ConnectInd);
+ ASP_SCCP_N_CONNECT_cfm -> BSSAP_LE_N_CONNECT_cfm: function(f_dec_ConnectCfm);
+ ASP_SCCP_N_DATA_ind -> BSSAP_LE_N_DATA_ind: function(f_dec_DataInd);
+ ASP_SCCP_N_DISCONNECT_ind -> BSSAP_LE_N_DISCONNECT_ind: function(f_dec_DisconnectInd);
+ ASP_SCCP_N_UNITDATA_ind -> BSSAP_LE_N_UNITDATA_ind: function(f_dec_UnitdataInd);
+ ASP_SCCP_N_NOTICE_ind -> BSSAP_LE_N_NOTICE_ind: function(f_dec_NoticeInd);
+ ASP_SCCP_N_RESET_ind -> ASP_SCCP_N_RESET_ind: simple;
+ ASP_SCCP_N_RESET_cfm -> ASP_SCCP_N_RESET_cfm: simple;
+ ASP_SCCP_N_STATE_ind -> ASP_SCCP_N_STATE_ind: simple)"
+}
+
+
+}
diff --git a/library/BSSAP_LE_Emulation.ttcn b/library/BSSAP_LE_Emulation.ttcn
new file mode 100644
index 00000000..fe85e58e
--- /dev/null
+++ b/library/BSSAP_LE_Emulation.ttcn
@@ -0,0 +1,731 @@
+module BSSAP_LE_Emulation {
+
+/* BSSAP_LE Emulation, runs on top of BSSAP_LE_CodecPort. It multiplexes/demultiplexes
+ * the individual connections, so there can be separate TTCN-3 components handling
+ * each of the connections.
+ *
+ * The BSSAP_LE_Emulation.main() function processes SCCP primitives from the SCCP
+ * stack via the BSSAP_CodecPort, and dispatches them to the per-connection components.
+ *
+ * Outbound BSSAP/SCCP connections are initiated by sending a BSSAP_LE_Conn_Req primitive
+ * to the component running the BSSAP_LE_Emulation.main() function.
+ *
+ * For each new inbound connections, the BssapLeOps.create_cb() is called. It can create
+ * or resolve a TTCN-3 component, and returns a component reference to which that inbound
+ * connection is routed/dispatched.
+ *
+ * If a pre-existing component wants to register to handle a future inbound connection, it can
+ * do so by registering an "expect" with the expected Layer 3 (DTAP) payload. This is e.g. useful
+ * if you are simulating BTS + MSC, and first trigger a connection from BTS/RSL side in a
+ * component which then subsequently should also handle the MSC emulation.
+ *
+ * Inbound Unit Data messages (such as are dispatched to the BssapLeOps.unitdata_cb() callback,
+ * which is registered with an argument to the main() function below.
+ *
+ * (C) 2017-2020 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from SCCP_Emulation all;
+import from SCCPasp_Types all;
+import from IPA_Emulation all;
+import from MobileL3_Types all;
+import from Misc_Helpers all;
+
+import from BSSAP_LE_Types all;
+import from BSSAP_LE_CodecPort all;
+import from BSSMAP_LE_Templates all;
+import from BSSMAP_Templates all;
+import from RAN_Emulation all;
+
+/* General "base class" component definition, of which specific implementations
+ * derive themselves by means of the "extends" feature */
+type component BSSAP_LE_ConnHdlr {
+ /* port towards MSC Emulator core / SCCP connection dispatchar */
+ port BSSAP_LE_Conn_PT BSSAP_LE;
+ /* procedure based port to register for incoming connections */
+ port BSSAP_LE_PROC_PT BSSAP_LE_PROC;
+}
+
+/* Auxiliary primitive that can happen on the port between per-connection client and this dispatcher */
+type enumerated BSSAP_LE_Conn_Prim {
+ /* SCCP tell us that connection was released */
+ CONN_PRIM_DISC_IND,
+ /* we tell SCCP to release connection */
+ CONN_PRIM_DISC_REQ,
+ /* Connection confirmed indication */
+ CONN_PRIM_CONF_IND
+}
+
+/* port between individual per-connection components and this dispatcher */
+type port BSSAP_LE_Conn_PT message {
+ inout
+ PDU_BSSAP_LE,
+ BSSAP_LE_N_UNITDATA_req,
+ /* Client requests us to create SCCP Connection */
+ BSSAP_LE_Conn_Req,
+ /* direct DTAP messages from/to clients */
+ PDU_DTAP_MO, PDU_DTAP_MT,
+ PDU_DTAP_PS_MO, PDU_DTAP_PS_MT,
+ /* misc indications / requests between SCCP and client */
+ BSSAP_LE_Conn_Prim;
+} with { extension "internal" };
+
+type uint2_t N_Sd_Array[4];
+
+/* represents a single BSSAP connection over SCCP */
+type record ConnectionData {
+ /* reference to the instance of the per-connection component */
+ BSSAP_LE_ConnHdlr comp_ref,
+ integer sccp_conn_id,
+ /* array of N(SD) values for MO DTAP messages, indexed by discriminator */
+ N_Sd_Array n_sd
+}
+
+type record ImsiMapping {
+ BSSAP_LE_ConnHdlr comp_ref,
+ hexstring imsi optional,
+ OCT4 tmsi
+}
+
+type component BSSAP_LE_Emulation_CT {
+ /* SCCP ports on the bottom side, using ASP primitives */
+ port BSSAP_LE_CODEC_PT BSSAP_LE;
+ /* BSSAP port to the per-connection clients */
+ port BSSAP_LE_Conn_PT CLIENT;
+
+ /* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
+ var ConnectionData ConnectionTable[16];
+
+ /* pending expected incoming connections */
+ var ExpectData ExpectTable[8];
+
+ /* tables for mapping inbound unitdata (like paging) */
+ var ImsiMapping ImsiTable[16];
+
+ /* procedure based port to register for incoming connections */
+ port BSSAP_LE_PROC_PT PROC;
+
+ var charstring g_ran_id;
+ var integer g_next_e1_ts := 1;
+ var BssapLeOps g_ran_ops;
+ var boolean g_reset_ack_ready := false;
+};
+
+private function f_conn_id_known(integer sccp_conn_id)
+runs on BSSAP_LE_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].sccp_conn_id == sccp_conn_id){
+ return true;
+ }
+ }
+ return false;
+}
+
+private function f_comp_known(BSSAP_LE_ConnHdlr client)
+runs on BSSAP_LE_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* resolve component reference by connection ID */
+private function f_comp_by_conn_id(integer sccp_conn_id)
+runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].sccp_conn_id == sccp_conn_id) {
+ return ConnectionTable[i].comp_ref;
+ }
+ }
+ setverdict(fail, "BSSAP-LE Connection table not found by SCCP Connection ID ", sccp_conn_id);
+ mtc.stop;
+}
+
+/* resolve connection ID by component reference */
+private function f_conn_id_by_comp(BSSAP_LE_ConnHdlr client)
+runs on BSSAP_LE_Emulation_CT return integer {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return ConnectionTable[i].sccp_conn_id;
+ }
+ }
+ setverdict(fail, "BSSAP-LE Connection table not found by component ", client);
+ mtc.stop;
+}
+
+/* resolve ConnectionTable index component reference */
+private function f_idx_by_comp(BSSAP_LE_ConnHdlr client)
+runs on BSSAP_LE_Emulation_CT return integer {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return i;
+ }
+ }
+ setverdict(fail, "BSSAP-LE Connection table not found by component ", client);
+ mtc.stop;
+}
+
+private function f_gen_conn_id()
+runs on BSSAP_LE_Emulation_CT return integer {
+ var integer conn_id;
+
+ do {
+ conn_id := float2int(rnd()*SCCP_Emulation.tsp_max_ConnectionId);
+ } while (f_conn_id_known(conn_id) == true);
+
+ return conn_id;
+}
+
+private function f_conn_table_init()
+runs on BSSAP_LE_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ ConnectionTable[i].comp_ref := null;
+ ConnectionTable[i].sccp_conn_id := -1;
+ ConnectionTable[i].n_sd := { 0, 0, 0, 0 };
+ }
+ for (var integer i := 0; i < sizeof(ImsiTable); i := i+1) {
+ ImsiTable[i].comp_ref := null;
+ ImsiTable[i].imsi := omit;
+ ImsiTable[i].tmsi := 'FFFFFFFF'O;
+ }
+}
+
+private function f_conn_table_add(BSSAP_LE_ConnHdlr comp_ref, integer sccp_conn_id)
+runs on BSSAP_LE_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].sccp_conn_id == -1) {
+ ConnectionTable[i].comp_ref := comp_ref;
+ ConnectionTable[i].sccp_conn_id := sccp_conn_id;
+ ConnectionTable[i].n_sd := { 0, 0, 0, 0 };
+ log("Added conn table entry ", i, comp_ref, sccp_conn_id);
+ return;
+ }
+ }
+ testcase.stop("BSSAP-LE Connection table full!");
+}
+
+private function f_conn_table_del(integer sccp_conn_id)
+runs on BSSAP_LE_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].sccp_conn_id == sccp_conn_id) {
+ log("Deleted conn table entry ", i,
+ ConnectionTable[i].comp_ref, sccp_conn_id);
+ ConnectionTable[i].sccp_conn_id := -1;
+ ConnectionTable[i].comp_ref := null;
+ return
+ }
+ }
+ setverdict(fail, "BSSAP-LE Connection table attempt to delete non-existant ", sccp_conn_id);
+ mtc.stop;
+}
+
+private function f_imsi_table_find(hexstring imsi, template OCT4 tmsi)
+runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr {
+ for (var integer i := 0; i < sizeof(ImsiTable); i := i+1) {
+ if (ImsiTable[i].imsi == imsi or
+ isvalue(tmsi) and match(ImsiTable[i].tmsi, tmsi)) {
+ return ImsiTable[i].comp_ref;
+ }
+ }
+ return null;
+}
+
+type record BSSAP_LE_Conn_Req {
+ SCCP_PAR_Address addr_peer,
+ SCCP_PAR_Address addr_own,
+ PDU_BSSAP_LE bssap
+}
+template BSSAP_LE_Conn_Req ts_BSSAP_LE_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, PDU_BSSAP_LE bssap) := {
+ addr_peer := peer,
+ addr_own := own,
+ bssap := bssap
+};
+
+/* handle (optional) userData portion of various primitives and dispatch it to the client */
+private function f_handle_userData(BSSAP_LE_ConnHdlr client, PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT {
+ /* decode + send decoded BSSAP to client */
+
+ if (ischosen(bssap.pdu.dtap) and g_ran_ops.decode_dtap) {
+ if (g_ran_ops.role_ms) {
+ /* we are the MS, so any message to us must be MT */
+ var PDU_DTAP_MT mt := {
+ dlci := bssap.dlci,
+ dtap := dec_PDU_ML3_NW_MS(bssap.pdu.dtap)
+ };
+ CLIENT.send(mt) to client;
+ } else {
+ /* we are the Network, so any message to us must be MO */
+ var PDU_DTAP_MO mo := {
+ dlci := bssap.dlci,
+ dtap := dec_PDU_ML3_MS_NW(bssap.pdu.dtap)
+ };
+ CLIENT.send(mo) to client;
+ }
+ } else {
+ CLIENT.send(bssap) to client;
+ }
+}
+
+/* call-back type, to be provided by specific implementation; called when new SCCP connection
+ * arrives */
+type function BssmapLeCreateCallback(BSSAP_LE_N_CONNECT_ind conn_ind, charstring id)
+runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr;
+
+type function BssmapLeUnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE;
+
+/* handle common Unitdata such as Paging */
+private function CommonBssmapUnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
+ if (match(bssap, tr_BSSMAP_LE_Paging)) {
+ var BSSAP_LE_ConnHdlr client := null;
+ client := f_imsi_table_find(bssap.pdu.bssmap.paging.iMSI.digits,
+ bssap.pdu.bssmap.paging.tMSI.tmsiOctets);
+ if (client != null) {
+ log("CommonBssmapUnitdataCallback: IMSI/TMSI found in table, dispatching to ",
+ client);
+ CLIENT.send(bssap) to client;
+ return omit;
+ }
+ log("CommonBssmapUnitdataCallback: IMSI/TMSI not found in table");
+ } else {
+ log("CommonBssmapUnitdataCallback: Not a paging message");
+ }
+ /* ELSE: handle in user callback */
+ return g_ran_ops.unitdata_cb.apply(bssap);
+}
+
+private function f_bssap_le_reset(SCCP_PAR_Address peer, SCCP_PAR_Address own) runs on BSSAP_LE_Emulation_CT {
+ timer T := 5.0;
+
+ BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(peer, own, ts_BSSMAP_LE_Reset(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE)));
+ T.start;
+ alt {
+ [] BSSAP_LE.receive(tr_BSSAP_LE_UNITDATA_ind(own, peer, tr_BSSMAP_LE_ResetAck)) {
+ log("BSSMAP-LE: Received RESET-ACK in response to RESET, we're ready to go!");
+ g_reset_ack_ready := true;
+ }
+ [] as_reset_ack();
+ [] BSSAP_LE.receive { repeat };
+ [] T.timeout {
+ setverdict(fail, "BSSMAP-LE: Timeout waiting for RESET-ACK after sending RESET");
+ mtc.stop;
+ }
+ }
+}
+
+private function f_bssap_l3_is_rr(PDU_BSSAP_LE bssap) return boolean {
+ var template octetstring l3 := f_bssap_le_extract_l3(bssap);
+ return f_L3_is_rr(l3);
+}
+
+
+
+type record BssapLeOps {
+ BssmapLeCreateCallback create_cb optional,
+ BssmapLeUnitdataCallback unitdata_cb optional,
+ boolean decode_dtap,
+ boolean role_ms,
+ /* needed for performing BSSMAP RESET */
+ SCCP_PAR_Address sccp_addr_local optional,
+ SCCP_PAR_Address sccp_addr_peer optional
+}
+
+private altstep as_reset_ack() runs on BSSAP_LE_Emulation_CT {
+ var BSSAP_LE_N_UNITDATA_ind ud_ind;
+ [] BSSAP_LE.receive(tr_BSSAP_LE_UNITDATA_ind(?, ?, tr_BSSMAP_LE_Reset)) -> value ud_ind {
+ log("BSSMAP-LE: Responding to inbound RESET with RESET-ACK");
+ BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
+ ts_BSSMAP_LE_ResetAck));
+ g_reset_ack_ready := true;
+ repeat;
+ }
+}
+
+
+private altstep as_main_bssap_le() runs on BSSAP_LE_Emulation_CT {
+ var BSSAP_LE_N_UNITDATA_ind ud_ind;
+ var BSSAP_LE_N_CONNECT_ind conn_ind;
+ var BSSAP_LE_N_CONNECT_cfm conn_cfm;
+ var BSSAP_LE_N_DATA_ind data_ind;
+ var BSSAP_LE_N_DISCONNECT_ind disc_ind;
+ var BSSAP_LE_Conn_Req creq;
+ var PDU_BSSAP_LE bssap;
+ var BSSAP_LE_N_UNITDATA_req bssap_ud;
+ var BSSAP_LE_ConnHdlr vc_conn;
+ var integer targetPointCode;
+ var N_Sd_Array last_n_sd;
+
+ /* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
+ [] BSSAP_LE.receive(BSSAP_LE_N_UNITDATA_ind:?) -> value ud_ind {
+ /* Connectionless Procedures like RESET */
+ var template PDU_BSSAP_LE resp;
+ resp := CommonBssmapUnitdataCallback(ud_ind.userData);
+ if (isvalue(resp)) {
+ BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(ud_ind.callingAddress,
+ ud_ind.calledAddress, resp));
+ }
+ }
+ /* SCCP -> Client: new connection from BSC */
+ [] BSSAP_LE.receive(BSSAP_LE_N_CONNECT_ind:?) -> value conn_ind {
+ vc_conn := g_ran_ops.create_cb.apply(conn_ind, g_ran_id);
+ /* store mapping between client components and SCCP connectionId */
+ f_conn_table_add(vc_conn, conn_ind.connectionId);
+ /* handle user payload */
+ f_handle_userData(vc_conn, conn_ind.userData);
+ /* confirm connection establishment */
+ BSSAP_LE.send(ts_BSSAP_LE_CONNECT_res(conn_ind.connectionId, omit));
+ }
+ /* SCCP -> Client: connection-oriented data in existing connection */
+ [] BSSAP_LE.receive(BSSAP_LE_N_DATA_ind:?) -> value data_ind {
+ vc_conn := f_comp_by_conn_id(data_ind.connectionId);
+ if (ispresent(data_ind.userData)) {
+ f_handle_userData(vc_conn, data_ind.userData);
+ }
+ }
+ /* SCCP -> Client: disconnect of an existing connection */
+ [] BSSAP_LE.receive(BSSAP_LE_N_DISCONNECT_ind:?) -> value disc_ind {
+ vc_conn := f_comp_by_conn_id(disc_ind.connectionId);
+ if (ispresent(disc_ind.userData)) {
+ f_handle_userData(vc_conn, disc_ind.userData);
+ }
+ /* notify client about termination */
+ var BSSAP_LE_Conn_Prim prim := CONN_PRIM_DISC_IND;
+ CLIENT.send(prim) to vc_conn;
+ f_conn_table_del(disc_ind.connectionId);
+ /* TOOD: return confirm to other side? */
+ }
+ /* SCCP -> Client: connection confirm for outbound connection */
+ [] BSSAP_LE.receive(BSSAP_LE_N_CONNECT_cfm:?) -> value conn_cfm {
+ vc_conn := f_comp_by_conn_id(conn_cfm.connectionId);
+ var BSSAP_LE_Conn_Prim prim := CONN_PRIM_CONF_IND;
+ CLIENT.send(prim) to vc_conn;
+ /* handle user payload */
+ if (ispresent(conn_cfm.userData)) {
+ f_handle_userData(vc_conn, conn_cfm.userData);
+ }
+ }
+ [] CLIENT.receive(PDU_BSSAP_LE:?) -> value bssap sender vc_conn {
+ var integer conn_id := f_conn_id_by_comp(vc_conn);
+ /* send it to dispatcher */
+ BSSAP_LE.send(ts_BSSAP_LE_DATA_req(conn_id, bssap));
+ }
+
+ [] CLIENT.receive(BSSAP_LE_N_UNITDATA_req:?) -> value bssap_ud sender vc_conn {
+ BSSAP_LE.send(bssap_ud);
+ }
+
+ /* Disconnect request client -> SCCP */
+ [] CLIENT.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_DISC_REQ) -> sender vc_conn {
+ var integer conn_id := f_conn_id_by_comp(vc_conn);
+ BSSAP_LE.send(ts_BSSAP_LE_DISC_req(conn_id, 0));
+ f_conn_table_del(conn_id);
+ }
+
+ /* BSSAP from client -> SCCP */
+ [] CLIENT.receive(BSSAP_LE_Conn_Req:?) -> value creq sender vc_conn {
+ var integer conn_id;
+ /* send to dispatcher */
+
+ if (f_comp_known(vc_conn) == false) {
+ /* unknown client, create new connection */
+ conn_id := f_gen_conn_id();
+
+ /* store mapping between client components and SCCP connectionId */
+ f_conn_table_add(vc_conn, conn_id);
+
+ BSSAP_LE.send(ts_BSSAP_LE_CONNECT_req(creq.addr_peer, creq.addr_own, conn_id,
+ creq.bssap));
+ } else {
+ /* known client, send via existing connection */
+ conn_id := f_conn_id_by_comp(vc_conn);
+ BSSAP_LE.send(ts_BSSAP_LE_DATA_req(conn_id, creq.bssap));
+ }
+
+ /* InitialL3 contains RR (PAG RESP) or MM (CM SRV REQ), we must increment
+ * counter only on MM/CC/SS, but not on RR */
+ if (g_ran_ops.role_ms and not f_bssap_l3_is_rr(creq.bssap)) {
+ /* we have just sent the first MM message, increment the counter */
+ var integer idx := f_idx_by_comp(vc_conn);
+ ConnectionTable[idx].n_sd[0] := 1;
+ log("patch: N(SD) for ConnIdx ", idx, " set to 1");
+ }
+ }
+
+ [] PROC.getcall(BSSAP_LE_last_n_sd:{?,-}) -> param(vc_conn) {
+ var integer idx := f_idx_by_comp(vc_conn);
+ last_n_sd := ConnectionTable[idx].n_sd;
+ PROC.reply(BSSAP_LE_last_n_sd:{vc_conn, last_n_sd}) to vc_conn;
+ }
+
+ [] PROC.getcall(BSSAP_LE_continue_after_n_sd:{?,?}) -> param(last_n_sd, vc_conn) {
+ var integer idx := f_idx_by_comp(vc_conn);
+ ConnectionTable[idx].n_sd := last_n_sd;
+ PROC.reply(BSSAP_LE_continue_after_n_sd:{last_n_sd, vc_conn}) to vc_conn;
+ }
+}
+
+
+/* send a raw (encoded) L3 message over given SCCP connection */
+private function f_xmit_raw_l3(integer sccp_conn_id, OCT1 dlci, octetstring l3_enc) runs on BSSAP_LE_Emulation_CT
+{
+ var PDU_BSSAP_LE bssap;
+ bssap := valueof(ts_BSSAP_LE_DTAP(l3_enc, dlci));
+ BSSAP_LE.send(ts_BSSAP_LE_DATA_req(sccp_conn_id, bssap));
+}
+
+/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
+private function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+ var integer n_sd_idx := f_ML3_n_sd_idx(dtap);
+ if (n_sd_idx < 0) {
+ return;
+ }
+ var uint2_t seq_nr := f_next_n_sd(cd.n_sd, n_sd_idx);
+ f_ML3_patch_seq_nr(seq_nr, enc_l3);
+}
+
+function main(BssapLeOps ops, charstring id) runs on BSSAP_LE_Emulation_CT {
+
+ g_ran_id := id;
+ g_ran_ops := ops;
+ f_conn_table_init();
+ f_expect_table_init();
+
+ if (isvalue(ops.sccp_addr_peer) and isvalue(ops.sccp_addr_local)) {
+ f_sleep(1.0); /* HACK to wait for M3UA/ASP to be ACTIVE */
+ f_bssap_le_reset(ops.sccp_addr_peer, ops.sccp_addr_local);
+ }
+
+ while (true) {
+ var BSSAP_LE_ConnHdlr vc_conn;
+ var PDU_DTAP_MO dtap_mo;
+ var PDU_DTAP_MT dtap_mt;
+ var BSSAP_LE_ConnHdlr vc_hdlr;
+ var octetstring l3_info;
+ var hexstring imsi;
+ var OCT4 tmsi;
+ var integer targetPointCode;
+
+ alt {
+ [] as_main_bssap_le();
+
+ [g_ran_ops.role_ms] CLIENT.receive(PDU_DTAP_MO:?) -> value dtap_mo sender vc_conn {
+ var integer idx := f_idx_by_comp(vc_conn);
+ /* convert from decoded DTAP to encoded DTAP */
+ var octetstring l3_enc := enc_PDU_ML3_MS_NW(dtap_mo.dtap);
+ /* patch correct L3 send sequence number N(SD) into l3_enc */
+ if (dtap_mo.skip_seq_patching == false) {
+ f_ML3_patch_seq(ConnectionTable[idx], dtap_mo.dtap, l3_enc);
+ }
+ f_xmit_raw_l3(ConnectionTable[idx].sccp_conn_id, dtap_mo.dlci, l3_enc);
+ }
+
+ [not g_ran_ops.role_ms] CLIENT.receive(PDU_DTAP_MT:?) -> value dtap_mt sender vc_conn {
+ var integer idx := f_idx_by_comp(vc_conn);
+ /* convert from decoded DTAP to encoded DTAP */
+ var octetstring l3_enc := enc_PDU_ML3_NW_MS(dtap_mt.dtap);
+ f_xmit_raw_l3(ConnectionTable[idx].sccp_conn_id, dtap_mt.dlci, l3_enc);
+ }
+
+ [] PROC.getcall(BSSAP_LE_register:{?,?}) -> param(l3_info, vc_hdlr) {
+ f_create_expect(l3_info, vc_hdlr);
+ PROC.reply(BSSAP_LE_register:{l3_info, vc_hdlr}) to vc_hdlr;
+ }
+
+ [] PROC.getcall(BSSAP_LE_register_handoverRequest:{?,?}) -> param(targetPointCode, vc_hdlr) {
+ f_create_expect(omit, vc_hdlr, targetPointCode);
+ PROC.reply(BSSAP_LE_register_handoverRequest:{targetPointCode, vc_hdlr}) to vc_hdlr;
+ }
+
+ [] PROC.getcall(BSSAP_LE_register_imsi:{?,?,?}) -> param(imsi, tmsi, vc_hdlr) {
+ f_create_imsi(imsi, tmsi, vc_hdlr);
+
+ /* Wait for RESET-ACK if not received yet */
+ if (not g_reset_ack_ready) {
+ var integer wait_seconds := 10;
+ timer T_reset_ack := 1.0;
+ T_reset_ack.start;
+ alt {
+ [wait_seconds > 0] T_reset_ack.timeout {
+ if (g_reset_ack_ready) {
+ break;
+ }
+ wait_seconds := wait_seconds - 1;
+ T_reset_ack.start;
+ repeat;
+ }
+
+ [wait_seconds == 0] T_reset_ack.timeout {
+ setverdict(fail, "BSSMAP-LE: Timeout waiting for RESET-ACK");
+ mtc.stop;
+ }
+ }
+ }
+
+ PROC.reply(BSSAP_LE_register_imsi:{imsi, tmsi, vc_hdlr}) to vc_hdlr;
+ }
+
+
+ }
+ }
+}
+
+/***********************************************************************
+ * "Expect" Handling (mapping for expected incoming SCCP connections)
+ ***********************************************************************/
+
+/* data about an expected future incoming connection */
+type record ExpectData {
+ /* L3 payload based on which we can match it */
+ octetstring l3_payload optional,
+ integer handoverRequestPointCode optional,
+ /* component reference for this connection */
+ BSSAP_LE_ConnHdlr vc_conn
+}
+
+/* procedure based port to register for incoming connections */
+signature BSSAP_LE_register(in octetstring l3, in BSSAP_LE_ConnHdlr hdlr);
+signature BSSAP_LE_register_handoverRequest(in integer targetPointCode, in BSSAP_LE_ConnHdlr hdlr);
+
+/* procedure based port to register for incoming IMSI/TMSI */
+signature BSSAP_LE_register_imsi(in hexstring imsi, in OCT4 tmsi, in BSSAP_LE_ConnHdlr hdlr);
+
+/* If DTAP happens across other channels (e.g. GSUP), provide manual advancing of the n_sd sequence number */
+signature BSSAP_LE_last_n_sd(in BSSAP_LE_ConnHdlr hdlr, out N_Sd_Array last_n_sd);
+
+/* Update conn's n_sd sequence nr after the connection was taken over from elsewhere */
+signature BSSAP_LE_continue_after_n_sd(N_Sd_Array last_n_sd, in BSSAP_LE_ConnHdlr hdlr);
+
+type port BSSAP_LE_PROC_PT procedure {
+ inout BSSAP_LE_register, BSSAP_LE_register_imsi, BSSAP_LE_register_handoverRequest, BSSAP_LE_last_n_sd, BSSAP_LE_continue_after_n_sd;
+} with { extension "internal" };
+
+/* CreateCallback that can be used as create_cb and will use the expectation table */
+function ExpectedCreateCallback(BSSAP_LE_N_CONNECT_ind conn_ind, charstring id)
+runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr {
+ var BSSAP_LE_ConnHdlr ret := null;
+ var octetstring l3_info;
+ var integer i;
+
+ if (ischosen(conn_ind.userData.pdu.bssmap.perf_loc_req)) {
+ var BSSMAP_LE_PerfLocReq plr := conn_ind.userData.pdu.bssmap.perf_loc_req;
+ if (not ispresent(plr.imsi)) {
+ log("ExpectedCreateCallback: Cannot handle PerformLocReq without IMSI!");
+ mtc.stop;
+ }
+ var hexstring imsi := plr.imsi.imsi.oddEvenInd_identity.imsi.digits;
+ /* Find the component by the IMSI [usually] contained in this message */
+ ret := f_imsi_table_find(imsi, omit);
+ if (ret != null) {
+ log("ExpectedCreateCallback: Found ConnHdlr ", ret, " for IMSI ", imsi);
+ return ret;
+ }
+ } else if (ischosen(conn_ind.userData.pdu.bssmap.completeLayer3Information)) {
+ l3_info := conn_ind.userData.pdu.bssmap.completeLayer3Information.layer3Information.layer3info;
+ log("ExpectedCreateCallback completeLayer3Information");
+ } else {
+ setverdict(fail, "N-CONNECT.ind with L3 != { PerformLocReq | COMPLETE L3 }");
+ mtc.stop;
+ }
+
+ for (i := 0; i < sizeof(ExpectTable); i:= i+1) {
+ if (not ispresent(ExpectTable[i].l3_payload)) {
+ continue;
+ }
+ if (l3_info == ExpectTable[i].l3_payload) {
+ ret := ExpectTable[i].vc_conn;
+ /* release this entry to be used again */
+ ExpectTable[i].l3_payload := omit;
+ ExpectTable[i].vc_conn := null;
+ log("Found Expect[", i, "] for ", l3_info, " handled at ", ret);
+ /* return the component reference */
+ return ret;
+ }
+ }
+ setverdict(fail, "Couldn't find Expect for incoming connection ", conn_ind);
+ mtc.stop;
+}
+
+
+private function f_create_expect(template octetstring l3, BSSAP_LE_ConnHdlr hdlr,
+ template integer handoverRequestPointCode := omit)
+runs on BSSAP_LE_Emulation_CT {
+ var integer i;
+ log("f_create_expect(l3 := ", l3, ", handoverRequest := ", handoverRequestPointCode);
+ for (i := 0; i < sizeof(ExpectTable); i := i+1) {
+ if (not ispresent(ExpectTable[i].l3_payload)
+ and not ispresent(ExpectTable[i].handoverRequestPointCode)) {
+ if (ispresent(l3)) {
+ ExpectTable[i].l3_payload := valueof(l3);
+ }
+ if (ispresent(handoverRequestPointCode)) {
+ ExpectTable[i].handoverRequestPointCode := valueof(handoverRequestPointCode);
+ }
+ ExpectTable[i].vc_conn := hdlr;
+ if (ispresent(handoverRequestPointCode)) {
+ log("Created Expect[", i, "] for handoverRequest to be handled at ", hdlr);
+ } else {
+ log("Created Expect[", i, "] for ", l3, " to be handled at ", hdlr);
+ }
+ return;
+ }
+ }
+ testcase.stop("No space left in ExpectTable");
+}
+
+private function f_create_imsi(hexstring imsi, OCT4 tmsi, BSSAP_LE_ConnHdlr hdlr)
+runs on BSSAP_LE_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ImsiTable); i := i+1) {
+ if (not ispresent(ImsiTable[i].imsi)) {
+ ImsiTable[i].imsi := imsi;
+ ImsiTable[i].tmsi := tmsi;
+ ImsiTable[i].comp_ref := hdlr;
+ log("Created IMSI[", i, "] for ", imsi, tmsi, " to be handled at ", hdlr);
+ return;
+ }
+ }
+ testcase.stop("No space left in ImsiTable");
+}
+
+
+private function f_expect_table_init()
+runs on BSSAP_LE_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) {
+ ExpectTable[i].l3_payload := omit;
+ ExpectTable[i].handoverRequestPointCode := omit;
+ }
+}
+
+/* helper function for clients to register their IMSI/TMSI */
+/* FIXME: there is no TMSI in BSSMAP-LE */
+function f_bssap_le_register_imsi(hexstring imsi, template (omit) OCT4 tmsi_or_omit)
+runs on BSSAP_LE_ConnHdlr {
+ var OCT4 tmsi;
+
+ /* Resolve omit to a special reserved value */
+ if (istemplatekind(tmsi_or_omit, "omit")) {
+ tmsi := 'FFFFFFFF'O;
+ } else {
+ tmsi := valueof(tmsi_or_omit);
+ }
+
+ BSSAP_LE_PROC.call(BSSAP_LE_register_imsi:{imsi, tmsi, self}) {
+ [] BSSAP_LE_PROC.getreply(BSSAP_LE_register_imsi:{?,?,?}) {};
+ }
+}
+
+
+}
diff --git a/library/BSSAP_LE_Types.ttcn b/library/BSSAP_LE_Types.ttcn
new file mode 100644
index 00000000..e0071802
--- /dev/null
+++ b/library/BSSAP_LE_Types.ttcn
@@ -0,0 +1,594 @@
+module BSSAP_LE_Types {
+
+/* BSSAP_LE_Types, defining abstract TTCN-3 data types for the 3GPP BSSMAP-LE protocol.
+ *
+ * BSSMAP-LE is a 3GPP standard protocol used by SMLC and its peers in a GSM network.
+ * This file covers 3GPP TS 49.031 version 15.0.0 Release 15
+ *
+ * (C) 2020 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from BSSAP_Types all;
+import from BSSLAP_Types all;
+import from MobileL3_CommonIE_Types all;
+
+/* TS 49.031 Section 10.1 */
+type enumerated BSSMAP_LE_MsgType {
+ BSSMAP_LE_PERFORM_LOC_REQ ('00101011'B),
+ BSSMAP_LE_PERFORM_LOC_RESP ('00101101'B),
+ BSSMAP_LE_PERFORM_LOC_ABORT ('00101110'B),
+ BSSMAP_LE_PERFORM_LOC_INFO ('00101111'B),
+ BSSMAP_LE_ASSIST_INFO_REQ ('00100000'B),
+ BSSMAP_LE_ASSIST_INFO_RESP ('00100001'B),
+
+ BSSMAP_LE_CONN_ORIENTED_INFO ('00101010'B),
+ BSSMAP_LE_CONN_LESS_INFO ('00111010'B),
+
+ BSSMAP_LE_RESET ('00110000'B),
+ BSSMAP_LE_RESET_ACK ('00110001'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* TS 49.031 Section 10.2 */
+type enumerated BSSMAP_LE_IEI {
+ BSSMAP_LE_IEI_LCS_QoS ('00111110'B),
+ BSSMAP_LE_IEI_LCS_PRIORITY ('01000011'B),
+ BSSMAP_LE_IEI_LOCATION_TYPE ('01000100'B),
+ BSSMAP_LE_IEI_GANSS_LOCATION_TYPE ('10000010'B),
+ BSSMAP_LE_IEI_GEO_LOCATION ('01000101'B),
+ BSSMAP_LE_IEI_POSITIONING_DATA ('01000110'B),
+ BSSMAP_LE_IEI_GANSS_POS_DATA ('10000011'B),
+ BSSMAP_LE_IEI_VELOCITY_DATA ('01010101'B),
+ BSSMAP_LE_IEI_LCS_CAUSE ('01000111'B),
+ BSSMAP_LE_IEI_LCS_CLIENT_TYPE ('01001000'B),
+ BSSMAP_LE_IEI_APDU ('01001001'B),
+ BSSMAP_LE_IEI_NET_ELEM_ID ('01001010'B),
+ BSSMAP_LE_IEI_REQ_GPS_ASS_D ('01001011'B),
+ BSSMAP_LE_IEI_REQ_GANSS_ASS_D ('01000001'B),
+ BSSMAP_LE_IEI_DECIPH_KEYS ('01001100'B),
+ BSSMAP_LE_IEI_RET_ERR_REQ ('01001101'B),
+ BSSMAP_LE_IEI_RET_ERR_CAUSE ('01001110'B),
+ BSSMAP_LE_IEI_SEGMENTATION ('01001111'B),
+ BSSMAP_LE_IEI_CLASSMARK3_INFO ('00010011'B),
+ BSSMAP_LE_IEI_CAUSE ('00000100'B),
+ BSSMAP_LE_IEI_CELL_ID ('00000101'B),
+ BSSMAP_LE_IEI_CHOSEN_CHAN ('00100001'B),
+ BSSMAP_LE_IEI_IMSI ('00000000'B),
+ BSSMAP_LE_IEI_LCS_CAPABILITY ('01010000'B),
+ BSSMAP_LE_IEI_PKT_MEAS_REP ('01010001'B),
+ BSSMAP_LE_IEI_CELL_ID_LIST ('01010010'B),
+ BSSMAP_LE_IEI_IMEI ('10000000'B),
+ BSSMAP_LE_IEI_BSS_MLAT_CAP ('10000100'B),
+ BSSMAP_LE_IEI_CELL_INFO_LIST ('10000101'B),
+ BSSMAP_LE_IEI_BTS_RX_ACC_LVL ('10000110'B),
+ BSSMAP_LE_IEI_MLAT_METHOD ('10000111'B),
+ BSSMAP_LE_IEI_MLAT_TA ('10001000'B),
+ BSSMAP_LE_IEI_MS_SYNC_ACC ('10001001'B),
+ BSSMAP_LE_IEI_SHORT_ID_SET ('10001010'B),
+ BSSMAP_LE_IEI_RANDOM_ID_SET ('10001011'B),
+ BSSMAP_LE_IEI_SHORT_BSS_ID ('10001100'B),
+ BSSMAP_LE_IEI_RANDOM_ID ('10001101'B),
+ BSSMAP_LE_IEI_SHORT_ID ('10001110'B),
+ BSSMAP_LE_IEI_COVERAGE_CLASS ('10001111'B),
+ BSSMAP_LE_IEI_MTA_ACC_SEC_RQD ('10010000'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* Section 9.1 */
+type record BSSMAP_LE_PerfLocReq {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_LE_IE_LocationType location_type,
+ BSSMAP_IE_CellIdentifier cell_id,
+ BSSMAP_IE_ClassmarkInformationType3 cm3 optional,
+ BSSMAP_LE_IE_LcsClientType lcs_client_type optional,
+ BSSMAP_IE_ChosenChannel chosen_channel optional,
+ BSSMAP_LE_IE_LcsPriority lcs_priority optional,
+ BSSMAP_LE_IE_LcsQoS lcs_qos optional,
+ BSSMAP_LE_IE_ReqGpsAssD req_gps_ass_d optional,
+ BSSMAP_LE_IE_APDU bsslap_apdu optional,
+ BSSMAP_LE_IE_LcsCapability lcs_capability optional,
+ BSSMAP_LE_IE_PacketMeasRep packet_meas_rep optional,
+ BSSMAP_LE_IE_CellIdList meas_cell_id_list optional,
+ BSSMAP_LE_IE_IMSI imsi optional,
+ BSSMAP_LE_IE_IMEI imei optional
+ // TODO: more optional IEs
+};
+
+/* Section 9.2 */
+type record BSSMAP_LE_PerfLocResp {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_LE_IE_GeographicLoc geographic_loc optional,
+ BSSMAP_LE_IE_PositioningData pos_data optional,
+ BSSMAP_LE_IE_DecipheringKeys deciph_keys optional,
+ BSSMAP_LE_IE_LcsCause lcs_cause optional,
+ BSSMAP_LE_IE_VelocityData velocity_data optional,
+ BSSMAP_LE_IE_GanssPosData ganss_pos_data optional
+};
+
+/* Section 9.4 */
+type record BSSMAP_LE_PerfLocAbort {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_LE_IE_LcsCause lcs_cause
+};
+
+/* Section 9.8 */
+type record BSSMAP_LE_ConnOrientedInfo {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_LE_IE_APDU bsslap_apdu,
+ BSSMAP_LE_IE_Segmentation segmentation optional
+ // TODO: MLA related optional IEs
+};
+
+/* Section 9.9 */
+type record BSSMAP_LE_ConnLessInfo {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_LE_IE_NetElementId source_id,
+ BSSMAP_LE_IE_NetElementId dest_id,
+ BSSMAP_LE_IE_APDU bsslap_apdu optional,
+ BSSMAP_LE_IE_Segmentation segmentation optional,
+ BSSMAP_LE_IE_RetErrReq ret_err_req optional,
+ BSSMAP_LE_IE_RetErrCause ret_err_cause optional
+};
+
+/* Section 9.10 */
+type record BSSMAP_LE_Reset {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_IE_Cause cause
+};
+
+/* Section 9.11 */
+type record BSSMAP_LE_ResetAck {
+ BSSMAP_LE_MsgType msg_type
+};
+
+/* Section 9.12 */
+type record BSSMAP_LE_PerformLocInfo {
+ BSSMAP_LE_MsgType msg_type,
+ BSSMAP_IE_CellIdentifier cell_id,
+ BSSMAP_LE_IE_APDU bsslap_apdu optional
+};
+
+type union BSSMAP_LE_PDU {
+ BSSMAP_LE_PerfLocReq perf_loc_req,
+ BSSMAP_LE_PerfLocResp perf_loc_resp,
+ BSSMAP_LE_PerfLocAbort perf_loc_abort,
+ BSSMAP_LE_ConnOrientedInfo co_info,
+ BSSMAP_LE_ConnLessInfo cl_info,
+ BSSMAP_LE_Reset reset,
+ BSSMAP_LE_ResetAck reset_ack,
+ BSSMAP_LE_PerformLocInfo perf_loc_info,
+ /* The following BSSMAP messages defined in 3GPP TS 48.008 are applicable to the Lb interface to
+ * support signaling to a Type A LMU using an SDCCH */
+ PDU_BSSMAP_CipherModeCommand cipherModeCommand,
+ PDU_BSSMAP_CipherModeComplete cipherModeComplete,
+ PDU_BSSMAP_CipherModeReject cipherModeReject,
+ PDU_BSSMAP_ClassmarkUpdate classmarkUpdate,
+ PDU_BSSMAP_ClearCommand clearCommand,
+ PDU_BSSMAP_ClearComplete clearComplete,
+ PDU_BSSMAP_ClearRequest clearRequest,
+ PDU_BSSMAP_CompleteLayer3Information completeLayer3Information,
+ PDU_BSSMAP_Confusion confusion,
+ PDU_BSSMAP_HandoverRequired handoverRequired,
+ PDU_BSSMAP_HandoverRequiredReject handoverRequiredReject,
+ PDU_BSSMAP_HandoverPerformed handoverPerformed,
+ PDU_BSSMAP_Paging paging
+} with {
+ variant "TAG(
+ perf_loc_req, msg_type = BSSMAP_LE_PERFORM_LOC_REQ;
+ perf_loc_resp, msg_type = BSSMAP_LE_PERFORM_LOC_RESP;
+ perf_loc_abort, msg_type = BSSMAP_LE_PERFORM_LOC_ABORT;
+ co_info, msg_type = BSSMAP_LE_CONN_ORIENTED_INFO;
+ cl_info, msg_type = BSSMAP_LE_CONN_LESS_INFO;
+ reset, msg_type = BSSMAP_LE_RESET;
+ reset_ack, msg_type = BSSMAP_LE_RESET_ACK;
+ perf_loc_info, msg_type = BSSMAP_LE_PERFORM_LOC_INFO;
+ )"
+};
+
+/* Section 10.3 */
+type record BSSMAP_LE_IE_APDU {
+ BSSMAP_LE_IEI iei,
+ uint16_t len,
+ BSSMAP_LE_ProtocolId protocol_id,
+ BIT1 spare,
+ octetstring data
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_APDU)"
+ variant (len) "LENGTHTO(protocol_id,spare,data)"
+};
+type enumerated BSSMAP_LE_ProtocolId {
+ BSSMAP_LE_PROT_RESERVED ('0000000'B),
+ BSSMAP_LE_PROT_BSSLAP ('0000001'B),
+ BSSMAP_LE_PROT_LLP ('0000010'B),
+ BSSMAP_LE_PROT_SMLCPP ('0000011'B)
+} with { variant "FIELDLENGTH(7)" };
+
+/* Section 10.8 */
+type record BSSMAP_LE_IE_DecipheringKeys {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BIT7 spare,
+ boolean ciph_key_flag,
+ OCT7 cur_deciph_key,
+ OCT7 next_deciph_key
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_DECIPH_KEYS)"
+ variant (len) "LENGTHTO(spare,ciph_key_flag,cur_deciph_key,next_deciph_key)"
+}
+
+/* Section 10.9 */
+type record BSSMAP_LE_IE_GeographicLoc {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ octetstring location
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_GEO_LOCATION)"
+ variant (len) "LENGTHTO(location)"
+}
+
+/* Section 10.10 */
+type record BSSMAP_LE_IE_ReqGpsAssD {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BIT16 flags,
+ octetstring sat_data
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_REQ_GPS_ASS_D)"
+ variant (len) "LENGTHTO(flags,sat_data)"
+}
+
+/* Section 10.11 */
+type record BSSMAP_LE_IE_IMSI {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ MobileIdentityV imsi
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_IMSI)"
+ variant (len) "LENGTHTO(imsi)"
+}
+
+/* Section 10.13 */
+type record BSSMAP_LE_IE_LcsCause {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSMAP_LE_LcsCause cause,
+ OCT1 diag_val optional
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LCS_CAUSE)"
+ variant (len) "LENGTHTO(cause,diag_val)"
+}
+type enumerated BSSMAP_LE_LcsCause {
+ BSSMAP_LE_LCS_CAUSE_UNSPECIFIED ('00000000'B),
+ BSSMAP_LE_LCS_CAUSE_SYSTEM_FAILURE ('00000001'B),
+ BSSMAP_LE_LCS_CAUSE_PROTOCOL_ERROR ('00000010'B),
+ BSSMAP_LE_LCS_CAUSE_DATA_MISSING_IN_REQ ('00000011'B),
+ BSSMAP_LE_LCS_CAUSE_UNEXP_DATA_IN_REQ ('00000100'B),
+ BSSMAP_LE_LCS_CAUSE_POS_METH_FAILURE ('00000101'B),
+ BSSMAP_LE_LCS_CAUSE_TGT_MS_UNREACHABLE ('00000110'B),
+ BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED ('00000111'B),
+ BSSMAP_LE_LCS_CAUSE_FACILITY_NOTSUPP ('00001000'B),
+ BSSMAP_LE_LCS_CAUSE_INTER_BSC_HO ('00001001'B),
+ BSSMAP_LE_LCS_CAUSE_INTRA_BSC_HO ('00001010'B),
+ BSSMAP_LE_LCS_CAUSE_CONGESTION ('00001011'B),
+ BSSMAP_LE_LCS_CAUSE_INTER_NSE_CHG ('00001100'B),
+ BSSMAP_LE_LCS_CAUSE_RA_UPDAT ('00001101'B),
+ BSSMAP_LE_LCS_CAUSE_PTMSI_REALLOC ('00001110'B),
+ BSSMAP_LE_LCS_CAUSE_GPRS_SUSPENSION ('00001111'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* Section 10.14 */
+type record BSSMAP_LE_IE_LcsClientType {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSMAP_LE_ClientType cltype
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LCS_CLIENT_TYPE)"
+ variant (len) "LENGTHTO(cltype)"
+}
+type enumerated BSSMAP_LE_ClientType {
+ BSSMAP_LE_LCS_CTYPE_VALUE_ADDED_UNSPECIFIED ('00000000'B),
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_UNSPECIFIED ('00100000'B),
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_BCAST_SERVICE ('00100001'B),
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_OAM ('00100010'B),
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_ANON_STATS ('00100011'B),
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_TGT_MS_SVC ('00100100'B),
+ BSSMAP_LE_LCS_CTYPE_EMERG_SVC_UNSPECIFIED ('00110000'B),
+ BSSMAP_LE_LCS_CTYPE_LI_UNSPECIFIED ('01000000'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* Section 10.15 */
+type record BSSMAP_LE_IE_LcsPriority {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ OCT1 priority
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LCS_PRIORITY)"
+ variant (len) "LENGTHTO(priority)"
+}
+
+/* Section 10.16 */
+type record BSSMAP_LE_IE_LcsQoS {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+
+ BIT6 spare,
+ boolean vel,
+ boolean vert,
+
+ boolean ha,
+ uint7_t horiz_acc,
+
+ boolean va,
+ uint7_t vert_acc,
+
+ BIT2 rt,
+ BIT6 spare2
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LCS_QoS)"
+ variant (len) "LENGTHTO(spare,vel,vert,ha,horiz_acc,va,vert_acc,rt,spare2)"
+}
+
+/* Section 10.18 */
+type record BSSMAP_LE_IE_LocationType {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSMAP_LE_LocInfo loc_info,
+ BSSMAP_LE_PosMethod pos_method optional
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LOCATION_TYPE)"
+ variant (len) "LENGTHTO(loc_info,pos_method)"
+ variant (pos_method) "PRESENCE(loc_info = BSSMAP_LE_LOC_INFO_ASS_INFO_FOR_TGT_MS,
+ loc_info = BSSMAP_LE_LOC_INFO_DECIPH_KEYS_FOR_BCAST)"
+}
+type enumerated BSSMAP_LE_LocInfo {
+ BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC ('00000000'B),
+ BSSMAP_LE_LOC_INFO_ASS_INFO_FOR_TGT_MS ('00000001'B),
+ BSSMAP_LE_LOC_INFO_DECIPH_KEYS_FOR_BCAST ('00000010'B)
+} with { variant "FIELDLENGTH(8)" };
+type enumerated BSSMAP_LE_PosMethod {
+ BSSMAP_LE_POS_METHOD_RESERVED ('00000000'B),
+ BSSMAP_LE_POS_MOBILE_ASSISTED_EOTD ('00000001'B),
+ BSSMAP_LE_POS_MOBILE_BASED_EOTD ('00000010'B),
+ BSSMAP_LE_POS_ASSISTED_GPS ('00000011'B),
+ BSSMAP_LE_POS_ASSISTED_GANSS ('00000100'B),
+ BSSMAP_LE_POS_ASSISTED_GPS_AND_GANSS ('00000101'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* Section 10.19 */
+type record BSSMAP_LE_IE_NetElementId {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BIT4 spare,
+ BSSMAP_LE_IdDiscr id_discr,
+ BSSMAP_LE_IdU u
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_NET_ELEM_ID)"
+ variant (len) "LENGTHTO(spare,id_discr,u)"
+ variant (u) "CROSSTAG(
+ cgi, id_discr = BSSMAP_LE_ID_DISC_CGI;
+ lac_ci, id_discr = BSSMAP_LE_ID_DISC_LAC_CI;
+ lai, id_discr = BSSMAP_LE_ID_DISC_LAI;
+ lac, id_discr = BSSMAP_LE_ID_DISC_LAC;
+ lmu, id_discr = BSSMAP_LE_ID_LMU;
+ )"
+};
+type enumerated BSSMAP_LE_IdDiscr {
+ BSSMAP_LE_ID_DISC_CGI ('0000'B),
+ BSSMAP_LE_ID_DISC_LAC_CI ('0001'B),
+ BSSMAP_LE_ID_DISC_LAI ('0100'B),
+ BSSMAP_LE_ID_DISC_LAC ('0101'B),
+ BSSMAP_LE_ID_LMU ('0110'B)
+} with { variant "FIELDLENGTH(4)" };
+type union BSSMAP_LE_IdU {
+ BSSMAP_LE_Id_CGI cgi,
+ BSSMAP_LE_Id_LAC_CI lac_ci,
+ BSSMAP_LE_Id_LAI lai,
+ uint16_t lac,
+ octetstring lmu
+};
+type record BSSMAP_LE_Id_CGI {
+ HEX6n mcc_mnc,
+ uint16_t lac,
+ uint16_t ci
+};
+type record BSSMAP_LE_Id_LAC_CI {
+ uint16_t lac,
+ uint16_t ci
+};
+type record BSSMAP_LE_Id_LAI {
+ HEX6n mcc_mnc,
+ uint16_t lac
+};
+
+/* Section 10.20 */
+type record BSSMAP_LE_IE_PositioningData {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BIT4 spare,
+ uint4_t discr,
+ BSSMAP_LE_PosMethList pos_meth
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_POSITIONING_DATA)"
+ variant (len) "LENGTHTO(spare,discr,pos_meth)"
+};
+type record of BSSMAP_LE_PosMethodN BSSMAP_LE_PosMethList;
+type record BSSMAP_LE_PosMethodN {
+ BSSMAP_LE_Method method,
+ BSSMAP_LE_Usage usage
+};
+type enumerated BSSMAP_LE_Method {
+ BSSMAP_LE_METHOD_TA ('00000'B),
+ BSSMAP_LE_METHOD_RESERVED0 ('00001'B),
+ BSSMAP_LE_METHOD_RESERVED1 ('00010'B),
+ BSSMAP_LE_METHOD_MOBILE_ASS_EOTD ('00011'B),
+ BSSMAP_LE_METHOD_MOBILE_BASED_EOTD ('00100'B),
+ BSSMAP_LE_METHOD_MOBILE_ASS_GPS ('00101'B),
+ BSSMAP_LE_METHOD_MOBILE_BASED_GPS ('00110'B),
+ BSSMAP_LE_METHOD_CONVENTIONAL_GPS ('00111'B),
+ BSSMAP_LE_METHOD_UTDOA ('01000'B),
+ BSSMAP_LE_METHOD_CELL_ID ('01100'B)
+} with { variant "FIELDLENGTH(5)" };
+type enumerated BSSMAP_LE_Usage {
+ BSSMAP_LE_USAGE_ATTEMPTED_UNSUCC ('000'B),
+ BSSMAP_LE_USAGE_ATTEMPTED_SUCC_NOT_USED ('001'B),
+ BSSMAP_LE_USAGE_ATTEMPTED_SUCC_USED_VRFY_NOT_GEN ('010'B),
+ BSSMAP_LE_USAGE_ATTEMPTED_SUCC_USED_GEN ('011'B),
+ BSSMAP_LE_USAGE_ATTEMPTED_SUCC_USAGE_UNDETERMINED ('100'B)
+} with { variant "FIELDLENGTH(3)" };
+
+/* Section 10.21 */
+type record BSSMAP_LE_IE_RetErrReq {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ OCT1 ret_err_type
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_RET_ERR_REQ)"
+ variant (len) "LENGTHTO(ret_err_type)"
+}
+
+/* Section 10.22 */
+type record BSSMAP_LE_IE_RetErrCause {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSMAP_LE_RetErrCause cause
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_RET_ERR_REQ)"
+ variant (len) "LENGTHTO(cause)"
+}
+type enumerated BSSMAP_LE_RetErrCause {
+ BSSMAP_LE_RE_CAUSE_UNSPECIFIED ('00000000'B),
+ BSSMAP_LE_RE_CAUSE_SYSTEM_FAILURE ('00000001'B),
+ BSSMAP_LE_RE_CAUSE_PROTOCOL_ERROR ('00000010'B),
+ BSSMAP_LE_RE_CAUSE_DEST_UNKNOWN ('00000011'B),
+ BSSMAP_LE_RE_CAUSE_DEST_UNREACHABLE ('00000100'B),
+ BSSMAP_LE_RE_CAUSE_CONGESTION ('00000101'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* Section 10.24 */
+type record BSSMAP_LE_IE_Segmentation {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BIT3 spare,
+ boolean s_non_final,
+ uint4_t seg_nr,
+ OCT2 msg_id optional
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_SEGMENTATION)"
+ variant (len) "LENGTHTO(spare,s_non_final,seg_nr,msg_id)"
+}
+
+/* Section 10.26 */
+type record BSSMAP_LE_IE_LcsCapability {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ octetstring lcs_cap
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_LCS_CAPABILITY)"
+ variant (len) "LENGTHTO(lcs_cap)"
+}
+
+type record BSSMAP_LE_IE_PacketMeasRep {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ octetstring pkt_meas_rep
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_PKT_MEAS_REP)"
+ variant (len) "LENGTHTO(pkt_meas_rep)"
+}
+
+type record BSSMAP_LE_IE_CellIdList {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSLAP_CellIdList cell_id_list
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_CELL_ID_LIST)"
+ variant (len) "LENGTHTO(cell_id_list)"
+}
+
+/* Section 10.29 */
+type record BSSMAP_LE_IE_IMEI {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ MobileIdentityV imei
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_IMEI)"
+ variant (len) "LENGTHTO(imei)"
+}
+
+/* Section 10.30 */
+type record BSSMAP_LE_IE_VelocityData {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ octetstring data
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_VELOCITY_DATA)"
+ variant (len) "LENGTHTO(data)"
+}
+
+/* Section 10.32 */
+type record BSSMAP_LE_IE_GanssPosData {
+ BSSMAP_LE_IEI iei,
+ uint8_t len,
+ BSSMAP_LE_GanssList list
+} with {
+ variant "PRESENCE(iei = BSSMAP_LE_IEI_VELOCITY_DATA)"
+ variant (len) "LENGTHTO(list)"
+}
+type record of BSSMAP_LE_Ganss BSSMAP_LE_GanssList;
+type record BSSMAP_LE_Ganss {
+ BSSMAP_LE_GanssMethod method,
+ BSSMAP_LE_GanssId id,
+ BSSMAP_LE_Usage usage
+};
+type enumerated BSSMAP_LE_GanssMethod {
+ BSSMAP_LE_GANSS_METH_MS_BASED ('00'B),
+ BSSMAP_LE_GANSS_METH_MS_ASSISTED ('01'B),
+ BSSMAP_LE_GANSS_METH_MS_CONVENTIONAL ('10'B),
+ BSSMAP_LE_GANSS_METH_MS_RESERVED ('11'B)
+} with { variant "FIELDLENGTH(2)" };
+type enumerated BSSMAP_LE_GanssId {
+ BSSMAP_LE_GANSS_ID_GALILEO ('000'B),
+ BSSMAP_LE_GANSS_ID_SBAS ('001'B),
+ BSSMAP_LE_GANSS_ID_MODERNIZED_GPS ('010'B),
+ BSSMAP_LE_GANSS_ID_QZSS ('011'B),
+ BSSMAP_LE_GANSS_ID_GLONASS ('100'B),
+ BSSMAP_LE_GANSS_ID_BDS ('101'B)
+} with { variant "FIELDLENGTH(3)" };
+
+/* FIXME: Further IEs */
+
+
+
+
+type union BSSMAPLEorDTAP {
+ BSSMAP_LE_PDU bssmap,
+ octetstring dtap
+}
+
+type record PDU_BSSAP_LE {
+ BIT1 discriminator, // 0 = BSSMAP-LE; 1 = DTAP-LE
+ BIT7 spare, // always '0000000'B
+ OCT1 dlci optional,
+ LIN1 lengthIndicator,
+ BSSMAPLEorDTAP pdu
+} with {
+ variant (lengthIndicator) "LENGTHTO(pdu)"
+ variant (pdu) "CROSSTAG(bssmap, discriminator='0'B;
+ dtap, discriminator='1'B)"
+ variant (dlci) "PRESENCE(discriminator='1'B)"
+}
+
+
+external function enc_PDU_BSSAP_LE(in PDU_BSSAP_LE pdu) return octetstring
+with { extension "prototype(convert) encode(RAW)" }
+external function dec_PDU_BSSAP_LE(in octetstring stream) return PDU_BSSAP_LE
+with { extension "prototype(convert) decode(RAW)" }
+
+
+} with { encode "RAW" ; }
diff --git a/library/BSSGP_Emulation.ttcn b/library/BSSGP_Emulation.ttcn
deleted file mode 100644
index e3023edf..00000000
--- a/library/BSSGP_Emulation.ttcn
+++ /dev/null
@@ -1,769 +0,0 @@
-module BSSGP_Emulation {
-
-/* BSSGP Emulation in TTCN-3
- * (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
- * 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
- */
-
-import from General_Types all;
-import from Osmocom_Types all;
-import from NS_Types all;
-import from NS_Emulation all;
-import from BSSGP_Types all;
-import from Osmocom_Gb_Types all;
-import from IPL4asp_Types all;
-
-import from MobileL3_GMM_SM_Types all;
-import from MobileL3_Types all;
-
-import from LLC_Types all;
-import from LLC_Templates all;
-
-import from SNDCP_Types all;
-
-/***********************************************************************
- * Communication between Client Components and Main Component
- ***********************************************************************/
-
-type record BssgpStatusIndication {
- Nsei nsei,
- BssgpBvci bvci,
- BvcState state
-}
-
-template BssgpStatusIndication t_BssgpStsInd(template Nsei nsei, template BssgpBvci bvci, template BvcState state) := {
- nsei := nsei,
- bvci := bvci,
- state := state
-}
-
-type enumerated BvcState {
- BVC_S_BLOCKED,
- BVC_S_UNBLOCKED
-};
-
-/* port from our (internal) point of view */
-type port BSSGP_SP_PT message {
- in PDU_BSSGP,
- PDU_LLC,
- PDU_L3_MS_SGSN,
- PDU_L3_SGSN_MS;
- out PDU_BSSGP,
- PDU_LLC,
- PDU_SN,
- NsStatusIndication,
- BssgpStatusIndication,
- ASP_Event,
- PDU_L3_MS_SGSN,
- PDU_L3_SGSN_MS;
-} with { extension "internal" };
-
-/* port from the user point of view */
-type port BSSGP_PT message {
- in ASP_Event,
- NsStatusIndication,
- BssgpStatusIndication,
- PDU_BSSGP,
- PDU_LLC,
- PDU_SN,
- PDU_L3_MS_SGSN,
- PDU_L3_SGSN_MS;
- out PDU_BSSGP,
- PDU_LLC,
- PDU_L3_SGSN_MS,
- PDU_L3_MS_SGSN;
-} with { extension "internal" };
-
-signature BSSGP_register_client(hexstring imsi, OCT4 tlli, BssgpCellId cell_id);
-signature BSSGP_unregister_client(hexstring imsi);
-signature BSSGP_llgmm_assign(OCT4 tlli_old, OCT4 tlli);
-
-type port BSSGP_PROC_PT procedure {
- inout BSSGP_register_client, BSSGP_unregister_client, BSSGP_llgmm_assign;
-} with { extension "internal" };
-
-
-/***********************************************************************
- * Client Component for a single MS/TLLI
- ***********************************************************************/
-
-type component BSSGP_Client_CT {
- port BSSGP_PT BSSGP[3];
- port BSSGP_PT BSSGP_SIG[3];
- port BSSGP_PROC_PT BSSGP_PROC[3];
-};
-
-/***********************************************************************
- * Main Component
- ***********************************************************************/
-
-function BssgpStart(BssgpConfig cfg) runs on BSSGP_CT {
- g_cfg := cfg;
- f_init();
- f_ScanEvents();
-}
-
-private function f_init() runs on BSSGP_CT {
- /* Connect the UDP socket */
- f_change_state(BVC_S_BLOCKED);
-}
-
-type component BSSGP_CT {
- /* UDP ports towards the bottom (IUT) */
- port NS_PT BSCP;
- /* NS-User SAP towards the user */
- port BSSGP_SP_PT BSSGP_SP;
- port BSSGP_SP_PT BSSGP_SP_SIG;
- port BSSGP_PROC_PT BSSGP_PROC;
-
- var BssgpConfig g_cfg;
-
- var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
- timer g_T1 := 15.0;
- timer g_T2 := 60.0;
-
- var ClientEntity ClientTable[16];
-}
-
-type record length(16) of LLC_Entity LLC_Entities;
-
-type record ClientEntity {
- OCT4 tlli,
- OCT4 tlli_old optional,
- hexstring imsi,
- BssgpCellId cell_id,
- BSSGP_Client_CT comp_ref,
- /* LLC entities, one for each SAPI */
- LLC_Entity llc[16]
-};
-
-type record LLC_Entity {
- boolean sgsn_role,
- /* N(U) on transmit side for next PDU */
- uint9_t n_u_tx_next,
- /* N(U) on receive side, last PDU */
- uint9_t n_u_rx_last optional
-};
-
-function f_llc_create(boolean sgsn_role := false) return LLC_Entities {
- var LLC_Entities llc;
- for (var integer i := 0; i < 16; i := i+1) {
- llc[i] := valueof(t_LLC_init(sgsn_role));
- }
- return llc;
-}
-
-private template LLC_Entity t_LLC_init(boolean sgsn_role := false) := {
- sgsn_role := sgsn_role,
- n_u_tx_next := 0,
- n_u_rx_last := -
-}
-
-type enumerated BssgpDecodeDepth {
- BSSGP_DECODE_DEPTH_BSSGP,
- BSSGP_DECODE_DEPTH_LLC,
- BSSGP_DECODE_DEPTH_SNDCP,
- BSSGP_DECODE_DEPTH_L3
-};
-
-type record BssgpConfig {
- Nsvci nsei,
- Nsvci bvci,
- BssgpCellId cell_id,
- boolean sgsn_role,
- BssgpDecodeDepth depth
-};
-
-function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci)
-runs on BSSGP_CT return NsUnitdataRequest {
- var NsUnitdataRequest udr := {
- bvci := bvci,
- nsei := g_cfg.nsei,
- /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
- * unbound integer value." when trying to send the reocrd rather than the octetstring */
- //sdu := omit,
- //bssgp := valueof(pdu)
- sdu := enc_PDU_BSSGP(valueof(pdu)),
- bssgp := omit
- }
- return udr;
-}
-
-function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci)
-runs on BSSGP_CT return template NsUnitdataIndication {
- var template NsUnitdataIndication udi := {
- bvci := bvci,
- nsei := g_cfg.nsei,
- sdu := *,
- bssgp := pdu
- }
- return udi;
-}
-
-private function f_change_state(BvcState new_state) runs on BSSGP_CT {
- log("BSSGP State Transition: ", g_ptp_bvc_state, " -> ", new_state);
- g_ptp_bvc_state := new_state;
- for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isbound(ClientTable[i].comp_ref)) {
- BSSGP_SP.send(t_BssgpStsInd(g_cfg.nsei, g_cfg.bvci, g_ptp_bvc_state)) to ClientTable[i].comp_ref;
- }
- }
-}
-
-private function f_sendReset() runs on BSSGP_CT {
- var PDU_BSSGP pdu := valueof(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, g_cfg.bvci, g_cfg.cell_id));
- log("PDU: ", pdu);
- log("ENC: ", enc_PDU_BSSGP(pdu));
-
- /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
- BSCP.send(f_BnsUdReq(pdu, 0));
- g_T2.start;
- //f_change_state(BVC_S_WAIT_RESET);
-}
-
-private function f_sendUnblock() runs on BSSGP_CT {
- BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK(g_cfg.bvci), 0));
- g_T1.start;
-}
-
-private function f_sendBlock(BssgpCause cause) runs on BSSGP_CT {
- BSCP.send(f_BnsUdReq(t_BVC_BLOCK(g_cfg.bvci, cause), 0));
- g_T1.start;
-}
-
-private function f_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_CT {
- /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
- BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci));
-}
-
-/* attempt to extract the TLLI from a BSSGP PDU */
-function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
- if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
- return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
- } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
- return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
- } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
- return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
- return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
- return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS)) {
- return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
- return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
- return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
- return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
- return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
- return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
- return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
- return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
- return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
- return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
- return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
- isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
- return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
- return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
- } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
- return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
- }
- /* TODO: Handover, PFC, LCS */
- return omit;
-}
-
-/*
-private function f_tbl_init() runs on BSSGP_CT {
- var integer i;
- for (i := 0; i < sizeof(ImsiTable); i := i+1) {
- ImsiTable[i] := -;
- }
-
- for (i := 0; i < sizeof(TlliTable); i := i+1) {
- TlliTable[i] := -;
- }
-}
-*/
-
-private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_Client_CT vc_conn)
-runs on BSSGP_CT {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (not isvalue(ClientTable[i].comp_ref)) {
- log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
- ClientTable[i] := {
- tlli := tlli,
- tlli_old := omit,
- imsi := imsi,
- cell_id := cell_id,
- comp_ref := vc_conn,
- llc := -
- };
- for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
- ClientTable[i].llc[j] := valueof(t_LLC_init(g_cfg.sgsn_role));
- }
- return;
- }
- }
- testcase.stop("Client Table full");
-}
-
-private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_CT {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
- if (ClientTable[i].comp_ref != vc_conn) {
- setverdict(fail, "Cannot unregister index=", i, " IMSI ", imsi, " registred to ",
- ClientTable[i].comp_ref, " from ", vc_conn);
- mtc.stop;
- }
- log("Removing Client IMSI=", imsi, ", index=", i);
- ClientTable[i] := {
- tlli := -,
- tlli_old := omit,
- imsi := ''H,
- cell_id := -,
- comp_ref := null,
- llc := - };
- return;
- }
- }
- log("Warning: Could not find client for IMSI ", imsi);
- return;
-}
-
-/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
-private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
-runs on BSSGP_CT {
- var integer i := f_tbl_idx_by_comp(vc_conn);
-
- if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
- /* TLLI assignment */
- ClientTable[i].tlli := tlli_new;
- ClientTable[i].tlli_old := omit;
- } else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
- /* TLLI change: both active */
- ClientTable[i].tlli := tlli_new;
- ClientTable[i].tlli_old := tlli_old;
- } else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
- /* TLLI unassignment: old shall be unassigned; new stays */
- ClientTable[i].tlli_old := omit;
- }
-}
-
-private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_CT return BSSGP_Client_CT {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
- and ClientTable[i].imsi == imsi) {
- return ClientTable[i].comp_ref;
- }
- }
- setverdict(fail, "Couldn't find Component for IMSI ", imsi);
- mtc.stop;
-}
-
-private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_CT return BSSGP_Client_CT {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isvalue(ClientTable[i].comp_ref) and
- (isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
- isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
- return ClientTable[i].comp_ref;
- }
- }
- setverdict(fail, "Couldn't find Component for TLLI ", tlli);
- mtc.stop;
-}
-
-private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return integer {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
- return i;
- }
- }
- setverdict(fail, "Couldn't find Client for Component ", comp_ref);
- mtc.stop;
-}
-
-private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_CT return OCT4 {
- var integer i;
- for (i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
- and ClientTable[i].comp_ref == comp_ref) {
- return ClientTable[i].tlli;
- }
- }
- setverdict(fail, "Couldn't find TLLI for Component ", comp_ref);
- mtc.stop;
-}
-
-altstep as_allstate() runs on BSSGP_CT {
- var BSSGP_Client_CT vc_conn;
- var NsUnitdataIndication udi;
- var NsStatusIndication nsi;
- var ASP_Event evt;
- var hexstring imsi;
- var OCT4 tlli, tlli_old;
- var BssgpCellId cell_id;
-
- /* Respond to BLOCK for wrong NSVCI */
- [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(?, ?), 0)) -> value udi {
- log("Rx BVC-BLOCK for unknown BVCI");
- f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
- }
-
- /* Respond to RESET with correct BVCI/CellID */
- [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
- log("Rx BVC-RESET for Our BVCI=", g_cfg.bvci);
- BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0));
- f_change_state(BVC_S_UNBLOCKED);
- }
-
- /* Respond to RESET for signalling BVCI 0 */
- [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, g_cfg.cell_id), 0)) -> value udi {
- log("Rx BVC-RESET for Signaling BVCI=0");
- BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, g_cfg.cell_id), 0));
- }
-
- /* Respond to RESET with wrong NSEI/NSVCI */
- [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
- log("Rx BVC-RESET for unknown BVCI");
- f_sendStatus(BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp);
- }
-
- /* default case of handling unknown PDUs */
- [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
- log("Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_ptp_bvc_state);
- f_sendStatus(BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp);
- }
- /* Forwarding of ASP_Event and NsStatusIndication to user */
- [] BSCP.receive(ASP_Event:?) -> value evt {
- for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isbound(ClientTable[i].comp_ref)) {
- BSSGP_SP.send(evt) to ClientTable[i].comp_ref;
- }
- }
- }
- [] BSCP.receive(NsStatusIndication:?) -> value nsi {
- /* if we just became NS-unblocked, send a BCC-RESET */
- if (nsi.old_state != NSE_S_ALIVE_UNBLOCKED and nsi.new_state == NSE_S_ALIVE_UNBLOCKED) {
- if (g_cfg.sgsn_role == false) {
- f_sendReset();
- }
- /* Idea: We could send BVC-UNBLOCK here like some SGSN do */
- }
- for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isbound(ClientTable[i].comp_ref)) {
- BSSGP_SP.send(nsi) to ClientTable[i].comp_ref;
- }
- }
- }
-
- [] BSSGP_PROC.getcall(BSSGP_register_client:{?,?,?}) -> param(imsi, tlli, cell_id) sender vc_conn {
- f_tbl_client_add(imsi, tlli, cell_id, vc_conn);
- BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli, cell_id}) to vc_conn;
- }
- [] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
- f_tbl_client_del(imsi, vc_conn);
- BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
- }
- [] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
- f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
- BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
- }
-
-}
-
-altstep as_blocked() runs on BSSGP_CT {
- [g_T1.running] g_T1.timeout {
- f_sendUnblock();
- }
- [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
- g_T1.stop;
- f_change_state(BVC_S_UNBLOCKED);
- }
- [not g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) {
- f_sendUnblock();
- }
-}
-
-private function f_send_bssgp_dec(BssgpDecoded dec, BSSGP_Client_CT vc_conn, BSSGP_SP_PT pt := BSSGP_SP) runs on BSSGP_CT {
- if (ispresent(dec.l3_mt)) {
- pt.send(dec.l3_mt) to vc_conn;
- } else if (ispresent(dec.l3_mo)) {
- pt.send(dec.l3_mo) to vc_conn;
- } else if (ispresent(dec.sndcp)) {
- pt.send(dec.sndcp) to vc_conn;
- } else if (ispresent(dec.llc)) {
- pt.send(dec.llc) to vc_conn;
- } else {
- pt.send(dec.bssgp) to vc_conn;
- }
-}
-
-
-altstep as_unblocked() runs on BSSGP_CT {
- var BSSGP_Client_CT vc_conn;
- var NsUnitdataIndication udi;
- var PDU_BSSGP bs_pdu;
- var PDU_LLC llc;
- var PDU_L3_MS_SGSN l3_mo;
- var PDU_L3_SGSN_MS l3_mt;
-
- /* bogus unblock, just respond with ACK */
- [] BSCP.receive(f_BnsUdInd(t_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
- BSCP.send(f_BnsUdReq(t_BVC_UNBLOCK_ACK(g_cfg.bvci), 0));
- }
- /* Respond to BLOCK with BLOCK-ACK + change state */
- [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
- BSCP.send(f_BnsUdReq(t_BVC_BLOCK_ACK(g_cfg.bvci), 0));
- g_T1.stop;
- f_change_state(BVC_S_BLOCKED);
- }
- [g_T1.running] g_T1.timeout {
- f_sendBlock(BSSGP_CAUSE_OM_INTERVENTION);
- }
- [] BSCP.receive(f_BnsUdInd(t_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
- g_T1.stop;
- f_change_state(BVC_S_BLOCKED);
- }
- [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
- g_T2.stop;
- f_change_state(BVC_S_UNBLOCKED);
- }
-
- /* simply acknowledge all Flow Control Messages */
- [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
- var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
- BSCP.send(f_BnsUdReq(t_BVC_FC_BVC_ACK(tag), g_cfg.bvci));
- }
-/*
- [g_cfg.sgsn_role] BSCP.receive(f_BnsUdInd(t_BVC_FC_MS, g_cfg.bvci)) {
- BSCP.send(f_BnsUdReq(t_BVC_FC_MS_ACK, g_cfg.bvci));
- }
-*/
-
- /* FIXME: CS PAGING: dispatch by IMSI */
-
- /* PS PAGING: dispatch by IMSI */
- [] BSCP.receive(f_BnsUdInd(tr_BSSGP_PS_PAGING(g_cfg.bvci), g_cfg.bvci)) -> value udi {
- var hexstring imsi := udi.bssgp.pDU_BSSGP_PAGING_PS.iMSI.digits
- vc_conn := f_tbl_comp_by_imsi(imsi);
- f_send_bssgp_dec(f_dec_bssgp(udi.bssgp), vc_conn);
- }
-
- /* Any other PTP BSSGP message: If it has TLLi, route to component; otherwise broadcast */
- [] BSCP.receive(f_BnsUdInd(?, g_cfg.bvci)) -> value udi {
- var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
- var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
- if (isvalue(tlli)) {
- vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
- f_send_bssgp_dec(dec, vc_conn);
- } else {
- log("No TLLI: Broadcasting ", dec);
- /* broadcast this message to all components */
- // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
- for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isbound(ClientTable[i].comp_ref)) {
- f_send_bssgp_dec(dec, ClientTable[i].comp_ref);
- }
- }
- }
- }
-
- /* Any other SIG BSSGP message: If it has TLLi, route to component; otherwise broadcast */
- [] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
- var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
- var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
- if (isvalue(tlli)) {
- vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
- f_send_bssgp_dec(dec, vc_conn, BSSGP_SP_SIG);
- } else {
- log("No TLLI: Broadcasting ", dec);
- /* broadcast this message to all components */
- // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
- for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
- if (isbound(ClientTable[i].comp_ref)) {
- f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
- }
- }
- }
- }
-
-
- /* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP Codec Port */
- [] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
- BSCP.send(f_BnsUdReq(bs_pdu, 0));
- }
-
- /* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP Codec Port */
- [] BSSGP_SP.receive(PDU_BSSGP:?) -> value bs_pdu sender vc_conn {
- BSCP.send(f_BnsUdReq(bs_pdu, g_cfg.bvci));
- }
-
- /* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
- [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
- var integer idx := f_tbl_idx_by_comp(vc_conn);
- var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
- var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
- var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
- var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
- BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
- }
- [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
- var integer idx := f_tbl_idx_by_comp(vc_conn);
- var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
- var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
- var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
- var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
- BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
- }
-
- /* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
- [not g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
- var integer idx := f_tbl_idx_by_comp(vc_conn);
- var octetstring llc_enc := enc_PDU_LLC(llc);
- BSCP.send(f_BnsUdReq(ts_BSSGP_UL_UD(ClientTable[idx].tlli, ClientTable[idx].cell_id, llc_enc), g_cfg.bvci));
- }
- [g_cfg.sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
- var integer idx := f_tbl_idx_by_comp(vc_conn);
- var octetstring llc_enc := enc_PDU_LLC(llc);
- BSCP.send(f_BnsUdReq(ts_BSSGP_DL_UD(ClientTable[idx].tlli, llc_enc), g_cfg.bvci));
- }
-
-}
-
-function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
- var uint9_t ret := llc.n_u_tx_next;
- llc.n_u_tx_next := llc.n_u_tx_next + 1;
- return ret;
-}
-
-function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
- if (ischosen(l3_mo.msgs.gprs_mm)) {
- return c_LLC_SAPI_LLGMM;
- } else if (ischosen(l3_mo.msgs.gprs_sm)) {
- return c_LLC_SAPI_LLGMM;
- } else if (ischosen(l3_mo.msgs.sms)) {
- return c_LLC_SAPI_LLSMS;
- }
- setverdict(fail, "No LLC SAPI for ", l3_mo);
- mtc.stop;
-}
-
-private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
- if (ischosen(l3_mt.msgs.gprs_mm)) {
- return c_LLC_SAPI_LLGMM;
- } else if (ischosen(l3_mt.msgs.gprs_sm)) {
- return c_LLC_SAPI_LLGMM;
- } else if (ischosen(l3_mt.msgs.sms)) {
- return c_LLC_SAPI_LLSMS;
- }
- setverdict(fail, "No LLC SAPI for ", l3_mt);
- mtc.stop;
-}
-
-
-
-private function f_ScanEvents() runs on BSSGP_CT {
- log("matching against ", tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id));
-
- while (true) {
- alt {
- [g_ptp_bvc_state == BVC_S_BLOCKED] as_blocked();
- [g_ptp_bvc_state == BVC_S_UNBLOCKED] as_unblocked();
- [] as_allstate();
- }
- } /* while */
-}
-
-/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
-type record BssgpDecoded {
- PDU_BSSGP bssgp,
- PDU_LLC llc optional,
- PDU_L3_MS_SGSN l3_mo optional,
- PDU_L3_SGSN_MS l3_mt optional,
- PDU_SN sndcp optional
-}
-
-/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
-private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_CT return BssgpDecoded {
- var BssgpDecoded dec := {
- bssgp := bssgp,
- llc := omit,
- l3_mo := omit,
- l3_mt := omit,
- sndcp := omit
- };
-
- /* Decode LLC, if it is a PDU that contains LLC */
- if (g_cfg.depth >= BSSGP_DECODE_DEPTH_LLC) {
- if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
- dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
- } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
- dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
- }
- }
-
- /* Decode SNDCP, if it is a LLC PDU containing user plane data */
- if (g_cfg.depth >= BSSGP_DECODE_DEPTH_SNDCP) {
- if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
- dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
- }
- }
-
- /* Decode L3, if it is a LLC PDU containing L3 */
- if (g_cfg.depth >= BSSGP_DECODE_DEPTH_L3) {
- if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
- if (g_cfg.sgsn_role) {
- dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
- } else {
- dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
- }
- }
- }
-
- return dec;
-}
-
-function f_bssgp_client_register(hexstring imsi, OCT4 tlli, BssgpCellId cell_id, BSSGP_PROC_PT PT := BSSGP_PROC[0])
-runs on BSSGP_Client_CT {
- PT.call(BSSGP_register_client:{imsi, tlli, cell_id}) {
- [] PT.getreply(BSSGP_register_client:{imsi, tlli, cell_id}) {};
- }
-}
-
-function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
-runs on BSSGP_Client_CT {
- PT.call(BSSGP_unregister_client:{imsi}) {
- [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
- }
-}
-
-/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
-function f_bssgp_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_PROC_PT PT := BSSGP_PROC[0])
-runs on BSSGP_Client_CT {
- PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
- [] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
- }
-}
-
-
-}
diff --git a/library/BSSGP_Emulation.ttcnpp b/library/BSSGP_Emulation.ttcnpp
new file mode 100644
index 00000000..d01c7a21
--- /dev/null
+++ b/library/BSSGP_Emulation.ttcnpp
@@ -0,0 +1,1459 @@
+module BSSGP_Emulation {
+
+/* BSSGP Emulation in TTCN-3
+ * (C) 2018-2021 Harald Welte <laforge@gnumonks.org>
+ * 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
+ *
+ * This code implements BSSGP asa hierarchy of components:
+ * - the main BSSGP_CT which runs on top of a NSE (NS Entity).
+ * - demultiplex based on BVCI. BVCI=0 is handled to a user port
+ * - a per-BVC BSSGP_BVC_CT which runs on top of BSSGP_CT, it handles
+ * one PTP BVCI (i.e. one cell)
+ * - demultiplex based on TLLI
+ * - a per-TLLI BSSGP_Client_CT which runs on top of BSSGP_BVC_CT
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from NS_Types all;
+import from NS_Emulation all;
+import from BSSGP_Types all;
+import from Osmocom_Gb_Types all;
+import from IPL4asp_Types all;
+import from Misc_Helpers all;
+
+#ifdef BSSGP_EM_L3
+import from MobileL3_GMM_SM_Types all;
+import from MobileL3_Types all;
+#endif
+
+import from LLC_Types all;
+import from LLC_Templates all;
+
+import from SNDCP_Types all;
+
+/***********************************************************************
+ * Communication between Client Components and per-BVC component
+ ***********************************************************************/
+
+type record BssgpStatusIndication {
+ Nsei nsei optional,
+ BssgpBvci bvci,
+ BvcState state
+};
+
+type record BssgpResetIndication {
+ BssgpBvci bvci
+};
+
+template (value) BssgpStatusIndication
+ts_BssgpStsInd(template (omit) Nsei nsei, template (value) BssgpBvci bvci,
+ template (value) BvcState state) := {
+ nsei := nsei,
+ bvci := bvci,
+ state := state
+}
+
+template (present) BssgpStatusIndication
+tr_BssgpStsInd(template Nsei nsei, template (present) BssgpBvci bvci,
+ template (present) BvcState state) := {
+ nsei := nsei,
+ bvci := bvci,
+ state := state
+}
+
+type enumerated BvcState {
+ /* SGSN role: waiting to be reset by the peer */
+ BVC_S_WAIT_RESET,
+ /* PCU role: waiting for NS_ALIVE_UNBLOCKED */
+ BVC_S_WAIT_NS_ALIVE_UNBLOCKED,
+ /* BVC-BLOCKED state */
+ BVC_S_BLOCKED,
+ /* BVC-UNBLOCKED state */
+ BVC_S_UNBLOCKED
+};
+
+/* port from our (internal) point of view */
+type port BSSGP_SP_PT message {
+ in PDU_BSSGP,
+ PDU_LLC
+#ifdef BSSGP_EM_L3
+ ,
+ PDU_L3_MS_SGSN,
+ PDU_L3_SGSN_MS
+#endif
+ ;
+ out PDU_BSSGP,
+ PDU_LLC,
+ PDU_SN,
+ NsStatusIndication,
+ BssgpStatusIndication,
+ ASP_Event
+#ifdef BSSGP_EM_L3
+ ,
+ PDU_L3_MS_SGSN,
+ PDU_L3_SGSN_MS
+#endif
+ ;
+} with { extension "internal" };
+
+/* port from the user point of view */
+type port BSSGP_PT message {
+ in ASP_Event,
+ NsStatusIndication,
+ BssgpStatusIndication,
+ PDU_BSSGP,
+ PDU_LLC,
+ PDU_SN
+#ifdef BSSGP_EM_L3
+ ,
+ PDU_L3_MS_SGSN,
+ PDU_L3_SGSN_MS
+#endif
+ ;
+ out PDU_BSSGP,
+ PDU_LLC
+#ifdef BSSGP_EM_L3
+ ,
+ PDU_L3_SGSN_MS,
+ PDU_L3_MS_SGSN
+#endif
+ ;
+} with { extension "internal" };
+
+signature BSSGP_register_client(hexstring imsi, OCT4 tlli);
+signature BSSGP_unregister_client(hexstring imsi);
+signature BSSGP_llgmm_assign(OCT4 tlli_old, OCT4 tlli);
+
+type port BSSGP_PROC_PT procedure {
+ inout BSSGP_register_client, BSSGP_unregister_client, BSSGP_llgmm_assign;
+} with { extension "internal" };
+
+
+
+/***********************************************************************
+ * Client Component for a single MS/TLLI
+ ***********************************************************************
+ * This is what most users will want to derive their test cases from. It
+ * provides a set of three different ports (PTP, signaling, procedure)
+ * for (currently up to 3) different Cells. Those ports are all connected
+ * to one or multiple different per-BVC compoennts, depending on whether
+ * they share the same BSS or not.
+ ***********************************************************************/
+
+type component BSSGP_Client_CT {
+ /* one port array for each client; allows talking to up to 3 BVC/Cell (handover, ...) */
+ port BSSGP_PT BSSGP[3]; /* PTP-BVC */
+ port BSSGP_PT BSSGP_SIG[3]; /* Signaling BVC */
+ port BSSGP_PT BSSGP_GLOBAL[3]; /* Signaling BVC */
+ port BSSGP_PROC_PT BSSGP_PROC[3]; /* registration / deregistration */
+};
+
+function f_bssgp_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT := BSSGP_PROC[0])
+runs on BSSGP_Client_CT {
+ PT.call(BSSGP_register_client:{imsi, tlli}) {
+ [] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
+ }
+}
+
+function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
+runs on BSSGP_Client_CT {
+ PT.call(BSSGP_unregister_client:{imsi}) {
+ [] PT.getreply(BSSGP_unregister_client:{imsi}) {};
+ }
+}
+
+/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
+function f_bssgp_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_PROC_PT PT := BSSGP_PROC[0])
+runs on BSSGP_Client_CT {
+ PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
+ [] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
+ }
+}
+
+/***********************************************************************
+ * Main Component
+ ***********************************************************************
+ * This component exists once, and it runs on to of the NS_Emulation.
+ * It handles the BVC-RESET for the signaling BVCI, and dispatches messages
+ * to the per-BVC components running above it. Messages are routed by:
+ * - PTP BVCI in NS header (if non-0)
+ * - BVCI IE in messages on BVCI=0 in NS header
+ * Messages for which no unique BVC can be identified (like paging without
+ * a BVCI IE set) are broadcast to all BVC components.
+ * We also broadcast state changes (BssgpStatusIndication) and reset events
+ * (BssgpResetIndication) of the signaling BVC to all per-BVC components.
+ ***********************************************************************/
+
+function BssgpStart(BssgpConfig cfg, charstring id) runs on BSSGP_CT {
+ g_cfg := cfg;
+
+ /* create the per-BVC components based on the configuration */
+ for (var integer i := 0; i < lengthof(g_cfg.bvc); i := i+1) {
+ var BssgpBvcConfig bvc_cfg := g_cfg.bvc[i];
+ var charstring bvc_id := id & "-BVCI" & int2str(bvc_cfg.bvci);
+ /* create, connect and start the BVC component */
+ var BSSGP_BVC_CT bvc_ct := BSSGP_BVC_CT.create(bvc_id) alive;
+ connect(bvc_ct:BVC, self:BVC);
+ bvc_ct.start(f_bssgp_bvc_main(bvc_cfg, g_cfg.sgsn_role, g_cfg.nsei, bvc_id));
+ /* populate the BVC state table */
+ BvcTable[i] := {
+ bvci := bvc_cfg.bvci,
+ cell_id := bvc_cfg.cell_id,
+ comp_ref := bvc_ct
+ };
+ }
+
+ if (g_cfg.sgsn_role) {
+ /* The SGSN side waits for an inbound BVC-RESET on the signaling BVC */
+ f_sign_change_state(BVC_S_WAIT_RESET);
+ } else {
+ /* The BSS/PCU side waits for an inbound NsStatusIndication to Tx BVC-RESET */
+ f_sign_change_state(BVC_S_WAIT_NS_ALIVE_UNBLOCKED);
+ }
+
+ /* main loop */
+ f_bssgp_ScanEvents();
+}
+
+/* master component, exists once per BSSGP instance (NSE) */
+type component BSSGP_CT {
+ /* UDP ports towards the bottom (IUT) */
+ port NS_PT BSCP;
+
+ /* control by the user */
+ port BSSGP_CT_PROC_PT PROC;
+
+ /* global port for procedures without any relation to a BVC
+ * (currently only) SUSPEND/RESUME */
+ port BSSGP_SP_PT GLOBAL;
+
+ /* RAN INFORMATION MGMT */
+ port BSSGP_SP_PT RIM;
+
+ /* port to a management instance */
+ port BSSGP_BVC_MGMT_SP_PT MGMT;
+
+ var BssgpConfig g_cfg;
+
+ /* Signaling BVC (BVCI=0) */
+ var BvcState g_sign_bvc_state := BVC_S_WAIT_RESET;
+ timer g_T2 := 60.0;
+
+ /* port to per-BVC components */
+ port BSSGP_BVC_SP_PT BVC;
+ /* per-BVC state table */
+ var BvcEntity BvcTable[64];
+};
+
+/* one element in the per-BVC state table */
+type record BvcEntity {
+ /* PTP BVCI of this BVC/Cell */
+ BssgpBvci bvci,
+ /* Cell Identity of this cell */
+ BssgpCellId cell_id,
+ /* reference to the per-BVC/cell component */
+ BSSGP_BVC_CT comp_ref
+};
+
+/* find the per-BVC component for a given BVCI */
+private function f_comp_for_bvci(BssgpBvci bvci) runs on BSSGP_CT return BSSGP_BVC_CT {
+ var integer i;
+
+ for (i := 0; i < lengthof(BvcTable); i := i+1) {
+ if (BvcTable[i].bvci == bvci) {
+ return BvcTable[i].comp_ref;
+ }
+ }
+ return null;
+}
+
+/* We are in BVC_S_WAIT_RSET state (only happens in SGSN role) */
+altstep as_sig_wait_reset() runs on BSSGP_CT {
+ var NsUnitdataIndication udi;
+
+ /* Respond to RESET for signalling BVCI 0 */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
+ log("Rx BVC-RESET for Signaling BVCI=0");
+ f_sign_change_state(BVC_S_UNBLOCKED);
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{0});
+ }
+ BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
+ }
+}
+
+private template PDU_BSSGP tr_GLOBAL_SIG := (
+ {pDU_BSSGP_SUSPEND:=?}, {pDU_BSSGP_SUSPEND_ACK:=?}, {pDU_BSSGP_SUSPEND_NACK:=?},
+ {pDU_BSSGP_RESUME:=?}, {pDU_BSSGP_RESUME_ACK:=?}, {pDU_BSSGP_RESUME_NACK:=?},
+ {pDU_BSSGP_SGSN_INVOKE_TRACE:=?}, {pDU_BSSGP_OVERLOAD:=?}, {pDU_BSSGP_STATUS:=?}
+);
+
+/* BSSGP messages that should arrive on the RIM port */
+private template PDU_BSSGP tr_RIM := (
+ {pDU_BSSGP_RAN_INFORMATION:=?}, {pDU_BSSGP_RAN_INFORMATION_REQUEST:=?},
+ {pDU_BSSGP_RAN_INFORMATION_ACK:=?}, {pDU_BSSGP_RAN_INFORMATION_ERROR:=?},
+ {pDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR:=?}
+);
+
+/* We are in BVC_S_UNBLOCKED state */
+altstep as_sig_unblocked() runs on BSSGP_CT {
+ var BSSGP_BVC_CT bvc_comp_ref;
+ var BSSGP_Client_CT vc_conn;
+ var NsUnitdataIndication udi;
+ var NsUnitdataRequest udr;
+ var PDU_BSSGP bssgp;
+
+ /* Messages PTP BVCI in BVCI field of NS: dispatch by that */
+ [] BSCP.receive(f_BnsUdInd(?, (2..65535))) -> value udi {
+ bvc_comp_ref := f_comp_for_bvci(valueof(udi.bvci));
+ if (isbound(bvc_comp_ref) and bvc_comp_ref != null) {
+ /* dispatch to BVC component */
+ BVC.send(udi) to bvc_comp_ref;
+ } else {
+ setverdict(fail, "Rx BSSGP for unknown PTP BVCI ", udi.bvci, ": ", udi.bssgp);
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), udi.bvci, 0));
+ }
+ }
+
+ /* Messages with BVCI = 0 (Signaling) in BVCI field of NS */
+ [] BSCP.receive(f_BnsUdInd(tr_GLOBAL_SIG, 0)) -> value udi {
+ if (GLOBAL.checkstate("Connected")) {
+ GLOBAL.send(udi.bssgp);
+ }
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_RIM, 0)) -> value udi {
+ if (RIM.checkstate("Connected")) {
+ RIM.send(udi.bssgp);
+ }
+ }
+
+ /* Broadcast FLUSH_LL_ACK no matter the BVCI */
+ [] BSCP.receive(f_BnsUdInd(tr_BSSGP_FLUSH_LL_ACK(?, ?, ?), 0)) -> value udi {
+ log("Rx FLUSH_LL_ACK: broadcasting");
+ for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(udi) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+
+ /* Route based on PTP BVCI in payload/IE of signaling PDU */
+ [] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
+ var template (omit) BssgpBvci ptp_bvci := f_BSSGP_BVCI_get(udi.bssgp);
+ if (istemplatekind(ptp_bvci, "omit")) {
+ log("Rx on SIG BVCI without PTP BVCI: broadcasting");
+ for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(udi) to BvcTable[i].comp_ref;
+ }
+ }
+ } else {
+ bvc_comp_ref := f_comp_for_bvci(valueof(ptp_bvci));
+ if (isbound(bvc_comp_ref) and bvc_comp_ref != null) {
+ /* dispatch to BVC component */
+ BVC.send(udi) to bvc_comp_ref;
+ } else {
+ setverdict(fail, "Rx SIG BSSGP for unknown PTP BVCI ", ptp_bvci, ": ", udi.bssgp);
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
+ }
+ }
+ }
+
+ /* Handle PS-PAGING on SIGN BVCI with no conditional BVCI IE */
+ [] BSCP.receive(f_BnsUdInd(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}, 0)) -> value udi {
+ /* FIXME: use LA, RA or BSS Area to dispatch instead of broadcast */
+ for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(udi) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+ /* Handle CS-PAGING on SIGN BVCI with no conditional BVCI IE */
+ [] BSCP.receive(f_BnsUdInd(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}, 0)) -> value udi {
+ /* FIXME: use LA, RA or BSS Area to dispatch instead of broadcast */
+ for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(udi) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+
+ /* per-BVC component sends us something; forward to NS without any validation */
+ [] BVC.receive(NsUnitdataRequest:?) -> value udr {
+ /* patch in the NSEI, as the per-BVC components have no idea about it */
+ udr.nsei := g_cfg.nsei;
+ BSCP.send(udr);
+ }
+
+ [] GLOBAL.receive(tr_GLOBAL_SIG) -> value bssgp {
+ BSCP.send(f_BnsUdReq(bssgp, 0, 0));
+ }
+
+ [] RIM.receive(tr_RIM) -> value bssgp {
+ BSCP.send(f_BnsUdReq(bssgp, 0, 0));
+ }
+
+}
+
+/* We are in BVC_S_WAIT_NS_ALIVE_UNBLOCKED (only happens in BSS role) */
+altstep as_sig_wait_ns_alive_unblocked() runs on BSSGP_CT {
+ var NsStatusIndication nsi;
+ [] BSCP.receive(NsStatusIndication:{g_cfg.nsei,?, complement (NSVC_S_ALIVE_UNBLOCKED), NSVC_S_ALIVE_UNBLOCKED, true}) -> value nsi {
+ /* if we just became NS-unblocked, send a BCC-RESET */
+ if (g_cfg.sgsn_role == false) {
+ BSCP.send(f_BnsUdReq(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, 0, omit), 0, 0));
+ g_T2.start;
+ /* The BVC_RESET_ACK is handled in the as_sig_allstate() below */
+ }
+ /* Idea: We could send BVC-UNBLOCK here like some SGSN do */
+ }
+
+}
+
+/* handling of events irrespective of BVC state (before state-specific handling) */
+altstep as_sig_allstate_pre() runs on BSSGP_CT {
+ var NsUnitdataIndication udi;
+
+ /* Respond to RESET for signalling BVCI 0 */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
+ log("Rx BVC-RESET for Signaling BVCI=0");
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{0});
+ }
+ BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+
+ /* any BLOCK or UNBLOCK for the SIGNALING BVCI are illegal */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(0, ?), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-BLOCK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-UNBLOCK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK_ACK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-BLOCK-ACK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK_ACK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-UNBLOCK-ACK illegal for BVCI=0: ", udi);
+ }
+
+ /* BVC-RESET-ACK for BVCI=0 while T2 is running: Answer to a BVC-RESET we sent earlier */
+ [g_T2.running] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(0, omit), 0)) -> value udi {
+ log("BVCI(0) Rx BVC-RESET-ACK");
+ g_T2.stop;
+ f_sign_change_state(BVC_S_UNBLOCKED);
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+ [g_T2.running] g_T2.timeout {
+ setverdict(fail, "Timeout waiting for BVC-RESET-ACK on BVCI=0");
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
+ g_T2.start;
+ }
+}
+
+/* handling of events irrespective of BVC state (after state-specific handling) */
+altstep as_sig_allstate_post() runs on BSSGP_CT {
+ var BSSGP_Client_CT vc_conn;
+ var NsUnitdataIndication udi;
+ var NsStatusIndication nsi;
+ var ASP_Event evt;
+ var BSSGP_BVC_CT bvc_comp_ref;
+ var BssgpBvci bvci;
+ var BssgpResetRequest brr;
+
+ /* Respond to RESET for signalling BVCI 0 */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
+ log("Rx BVC-RESET for Signaling BVCI=0");
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{0});
+ }
+ BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+
+ /* any BLOCK or UNBLOCK for the SIGNALING BVCI are illegal */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(0, ?), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-BLOCK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-UNBLOCK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK_ACK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-BLOCK-ACK illegal for BVCI=0: ", udi);
+ }
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK_ACK(0), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-UNBLOCK-ACK illegal for BVCI=0: ", udi);
+ }
+
+ /* Respond to BLOCK for wrong BVCI */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(?, ?), 0)) -> value udi {
+ setverdict(fail, "Rx BVC-BLOCK for unknown BVCI");
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
+ }
+
+ /* Respond to RESET with wrong BVCI */
+ [] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
+ var BssgpBvci ptp_bvci := oct2int(udi.bssgp.pDU_BSSGP_BVC_RESET.bVCI.unstructured_value);
+ setverdict(fail, "Rx BVC-RESET for unknown BVCI ", ptp_bvci);
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(ptp_bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
+ }
+
+ /* Forwarding of ASP_Event to per-BVC components */
+ [] BSCP.receive(ASP_Event:?) -> value evt {
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(evt) to BvcTable[i].comp_ref;
+ }
+ }
+ }
+ /* Keep NS Status Indicaitons to us; no need to inform per-BVC components [for now?] */
+ [] BSCP.receive(tr_NsStsInd(g_cfg.nsei)) -> value nsi { }
+ /* We should never see any different NSEI: There's one BSSGP_CT per NSE */
+ [] BSCP.receive(tr_NsStsInd(?)) -> value nsi {
+ setverdict(fail, "Rx NsStatusInd for wrong NSEI ", nsi);
+ }
+
+ /* Procedure port request to resolve the per-BVC component for a given ptp BVCI */
+ [] PROC.getcall(BSSGP_get_bvci_ct:{?}) -> param(bvci) sender vc_conn {
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (BvcTable[i].bvci == bvci) {
+ PROC.reply(BSSGP_get_bvci_ct:{bvci} value BvcTable[i].comp_ref) to vc_conn;
+ return;
+ }
+ }
+ }
+
+ /* default case of handling unknown PDUs */
+ [] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
+ setverdict(fail, "Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_sign_bvc_state);
+ BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp), 0, 0));
+ }
+
+ [] MGMT.receive(BssgpResetRequest:?) -> value brr {
+ BSCP.send(f_BnsUdReq(ts_BVC_RESET(brr.cause, 0, omit), 0, 0));
+ g_T2.start;
+ }
+}
+
+/* send the highest decoded layer of the message through given port */
+private function f_send_bssgp_dec(BssgpDecoded dec, BSSGP_Client_CT vc_conn, BSSGP_SP_PT pt) {
+#ifdef BSSGP_EM_L3
+ if (ispresent(dec.l3_mt)) {
+ pt.send(dec.l3_mt) to vc_conn;
+ } else if (ispresent(dec.l3_mo)) {
+ pt.send(dec.l3_mo) to vc_conn;
+ } else
+#endif
+ if (ispresent(dec.sndcp)) {
+ pt.send(dec.sndcp) to vc_conn;
+ } else if (ispresent(dec.llc)) {
+ pt.send(dec.llc) to vc_conn;
+ } else {
+ pt.send(dec.bssgp) to vc_conn;
+ }
+}
+
+
+function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
+ var uint9_t ret := llc.n_u_tx_next;
+ llc.n_u_tx_next := llc.n_u_tx_next + 1;
+ return ret;
+}
+
+#ifdef BSSGP_EM_L3
+function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
+ if (ischosen(l3_mo.msgs.gprs_mm)) {
+ return c_LLC_SAPI_LLGMM;
+ } else if (ischosen(l3_mo.msgs.gprs_sm)) {
+ return c_LLC_SAPI_LLGMM;
+ } else if (ischosen(l3_mo.msgs.sms)) {
+ return c_LLC_SAPI_LLSMS;
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No LLC SAPI for ", l3_mo));
+ return '0000'B;
+}
+
+private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
+ if (ischosen(l3_mt.msgs.gprs_mm)) {
+ return c_LLC_SAPI_LLGMM;
+ } else if (ischosen(l3_mt.msgs.gprs_sm)) {
+ return c_LLC_SAPI_LLGMM;
+ } else if (ischosen(l3_mt.msgs.sms)) {
+ return c_LLC_SAPI_LLSMS;
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No LLC SAPI for ", l3_mt));
+ return '0000'B;
+}
+#endif
+
+/* main loop of BSSGP_CT */
+private function f_bssgp_ScanEvents() runs on BSSGP_CT {
+ while (true) {
+ alt {
+ [g_sign_bvc_state == BVC_S_WAIT_RESET] as_sig_wait_reset();
+ [] as_sig_allstate_pre();
+ [g_sign_bvc_state == BVC_S_WAIT_NS_ALIVE_UNBLOCKED] as_sig_wait_ns_alive_unblocked();
+ [g_sign_bvc_state == BVC_S_UNBLOCKED] as_sig_unblocked();
+ [g_sign_bvc_state == BVC_S_WAIT_RESET] as_sig_wait_reset();
+ [] as_sig_allstate_post();
+ }
+ } /* while */
+}
+
+/* generate a send template. Cannot be a real template as we want to use g_cfg.nsei */
+private function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci, integer lsp)
+runs on BSSGP_CT return NsUnitdataRequest {
+ var NsUnitdataRequest udr := {
+ bvci := bvci,
+ nsei := g_cfg.nsei,
+ lsp := lsp,
+ /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
+ * unbound integer value." when trying to send the reocrd rather than the octetstring */
+ //sdu := omit,
+ //bssgp := valueof(pdu)
+ sdu := enc_PDU_BSSGP(valueof(pdu)),
+ bssgp := omit
+ }
+ return udr;
+}
+
+/* generate a receive template. Cannot be a real template as we want to use g_cfg.nsei */
+private function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci)
+runs on BSSGP_CT return template (present) NsUnitdataIndication {
+ var template (present) NsUnitdataIndication udi := {
+ bvci := bvci,
+ nsei := g_cfg.nsei,
+ nsvci := ?,
+ sdu := *,
+ bssgp := pdu
+ }
+ return udi;
+}
+
+/* change state of signaling BVCI; notify per-BVC components */
+private function f_sign_change_state(BvcState new_state) runs on BSSGP_CT {
+ if (new_state == g_sign_bvc_state) {
+ return;
+ }
+ log("BVCI(0) State Transition: ", g_sign_bvc_state, " -> ", new_state);
+ g_sign_bvc_state := new_state;
+ for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
+ if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
+ BVC.send(ts_BssgpStsInd(g_cfg.nsei, 0, g_sign_bvc_state)) to BvcTable[i].comp_ref;
+ }
+ }
+}
+
+/* User wants to get per-BVC component reference from BSSGP_CT */
+signature BSSGP_get_bvci_ct(BssgpBvci bvci) return BSSGP_BVC_CT;
+
+type port BSSGP_CT_PROC_PT procedure {
+ inout BSSGP_get_bvci_ct
+} with { extension "internal" };
+
+/* convenience wrapper function for user */
+function f_bssgp_get_bvci_ct(BssgpBvci bvci, BSSGP_CT_PROC_PT PT) return BSSGP_BVC_CT {
+ var BSSGP_BVC_CT res;
+ PT.call(BSSGP_get_bvci_ct:{bvci}) {
+ [] PT.getreply(BSSGP_get_bvci_ct:{bvci})-> value res {
+ return res;
+ }
+ }
+}
+
+/***********************************************************************
+ * per-BVC (Cell) Component
+ ***********************************************************************
+ * Any number of these components runs on top of the BSSGP_CT, each
+ * representing one PTP BVC within this NSE. Users (test cases) can
+ * register with TLLI and/or IMSI via the procedure port.
+ ***********************************************************************/
+
+/* per-BVC component. Exists once per cell within a BSSGP_CT */
+type component BSSGP_BVC_CT {
+ /* port towards the underlying BSSGP_CT */
+ port BSSGP_BVC_PT BVC;
+
+ /* port to a management instance */
+ port BSSGP_BVC_MGMT_SP_PT MGMT;
+
+ /* per-BVC global port for e.g. BVC Flow Control */
+ port BSSGP_SP_PT GLOBAL;
+
+ /* BSSGP-User SAP towards the user (per-TLLI, Client) */
+ port BSSGP_SP_PT BSSGP_SP;
+ port BSSGP_SP_PT BSSGP_SP_SIG;
+ port BSSGP_PROC_PT BSSGP_PROC;
+
+ var BssgpBvcConfig g_cfg;
+ var boolean g_sgsn_role;
+ var Nsei g_nsei;
+
+ /* default Link Selector Parameter for this BVC (for traffic unrelated to a TLLI) */
+ var integer g_bvc_lsp;
+
+ var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
+ timer g_T1 := 15.0;
+ timer g_T2 := 60.0;
+ var boolean g_t1_waits_for_block_ack := false;
+ /* for re-transmissions */
+ var BssgpCause g_last_block_cause;
+ var BssgpCause g_last_reset_cause;
+
+ var ClientEntity ClientTable[64];
+};
+
+/* port between global BSSGP_CT and per-BVC BSSGP_BVC_CT */
+type port BSSGP_BVC_SP_PT message {
+ in NsUnitdataRequest;
+ out ASP_Event,
+ BssgpStatusIndication,
+ BssgpResetIndication,
+ NsUnitdataIndication;
+} with { extension "internal" };
+type port BSSGP_BVC_PT message {
+ in ASP_Event,
+ BssgpStatusIndication,
+ BssgpResetIndication,
+ NsUnitdataIndication;
+ out NsUnitdataRequest;
+} with { extension "internal" };
+
+/* port between BSSGP_BVC_CT and a management instance */
+type port BSSGP_BVC_MGMT_SP_PT message {
+ in BssgpResetRequest,
+ BssgpBlockRequest,
+ BssgpUnblockRequest;
+ out BssgpStatusIndication,
+ BssgpResetIndication;
+} with { extension "internal" };
+type port BSSGP_BVC_MGMT_PT message {
+ in BssgpStatusIndication,
+ BssgpResetIndication;
+ out BssgpResetRequest,
+ BssgpBlockRequest,
+ BssgpUnblockRequest;
+} with { extension "internal" };
+
+type record BssgpResetRequest {
+ BssgpCause cause
+};
+type record BssgpBlockRequest {
+ BssgpCause cause
+};
+type record BssgpUnblockRequest {
+};
+
+/* one element in the per-TLLI state table */
+type record ClientEntity {
+ OCT4 tlli,
+ OCT4 tlli_old optional,
+ hexstring imsi,
+ BSSGP_Client_CT comp_ref,
+ /* LLC entities, one for each SAPI */
+ LLC_Entity llc[16]
+};
+type record LLC_Entity {
+ boolean sgsn_role,
+ /* N(U) on transmit side for next PDU */
+ uint9_t n_u_tx_next,
+ /* N(U) on receive side, last PDU */
+ uint9_t n_u_rx_last optional
+};
+type record length(16) of LLC_Entity LLC_Entities;
+
+private template PDU_BSSGP tr_GLOBAL_PTP := (
+ {pDU_BSSGP_STATUS:=?}
+);
+
+function f_llc_create(boolean sgsn_role := false) return LLC_Entities {
+ var LLC_Entities llc;
+ for (var integer i := 0; i < 16; i := i+1) {
+ llc[i] := valueof(t_LLC_init(sgsn_role));
+ }
+ return llc;
+}
+
+private template LLC_Entity t_LLC_init(boolean sgsn_role := false) := {
+ sgsn_role := sgsn_role,
+ n_u_tx_next := 0,
+ n_u_rx_last := -
+}
+
+/* configuration of BSSGP_CT */
+type record BssgpConfig {
+ Nsvci nsei,
+ boolean sgsn_role,
+ BssgpBvcConfigs bvc
+};
+/* Configuration of one BVC (Cell) BSSGP_BVC_CT */
+type record BssgpBvcConfig {
+ BssgpBvci bvci,
+ BssgpCellId cell_id,
+ BssgpDecodeDepth depth,
+ BssgpCreateCallback create_cb
+};
+type record of BssgpBvcConfig BssgpBvcConfigs;
+type enumerated BssgpDecodeDepth {
+ BSSGP_DECODE_DEPTH_BSSGP,
+ BSSGP_DECODE_DEPTH_LLC,
+ BSSGP_DECODE_DEPTH_SNDCP
+#ifdef BSSGP_EM_L3
+ ,
+ BSSGP_DECODE_DEPTH_L3
+#endif
+};
+/* call-back function type: Called for inbound BSSGP for unknown TLLIs; could create BSSGP_ClienT_CT */
+type function BssgpCreateCallback(BssgpBvci bvci, BssgpCellId cell_id, OCT4 tlli, BssgpDecoded dec) runs on BSSGP_BVC_CT;
+
+/* Default Create Callback function: Fail and terminate */
+function DefaultCreateCallback(BssgpBvci bvci, BssgpCellId cell_id, OCT4 tlli, BssgpDecoded dec) runs on BSSGP_BVC_CT {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Component for TLLI ", tlli));
+}
+
+/*
+private function f_tbl_init() runs on BSSGP_BVC_CT {
+ var integer i;
+ for (i := 0; i < sizeof(ImsiTable); i := i+1) {
+ ImsiTable[i] := -;
+ }
+
+ for (i := 0; i < sizeof(TlliTable); i := i+1) {
+ TlliTable[i] := -;
+ }
+}
+*/
+
+private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BSSGP_Client_CT vc_conn)
+runs on BSSGP_BVC_CT {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (not isvalue(ClientTable[i].comp_ref)) {
+ log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
+ ClientTable[i] := {
+ tlli := tlli,
+ tlli_old := omit,
+ imsi := imsi,
+ comp_ref := vc_conn,
+ llc := -
+ };
+ for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
+ ClientTable[i].llc[j] := valueof(t_LLC_init(g_sgsn_role));
+ }
+ return;
+ }
+ }
+ testcase.stop("Client Table full");
+}
+
+private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_BVC_CT {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
+ if (ClientTable[i].comp_ref != vc_conn) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Cannot unregister index=", i, " IMSI ",
+ imsi, " registred to ", ClientTable[i].comp_ref,
+ " from ", vc_conn));
+ }
+ log("Removing Client IMSI=", imsi, ", index=", i);
+ ClientTable[i] := {
+ tlli := -,
+ tlli_old := omit,
+ imsi := ''H,
+ comp_ref := null,
+ llc := - };
+ return;
+ }
+ }
+ log("Warning: Could not find client for IMSI ", imsi);
+ return;
+}
+
+/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
+private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
+runs on BSSGP_BVC_CT {
+ var integer i := f_tbl_idx_by_comp(vc_conn);
+
+ if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
+ /* TLLI assignment */
+ ClientTable[i].tlli := tlli_new;
+ ClientTable[i].tlli_old := omit;
+ } else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
+ /* TLLI change: both active */
+ ClientTable[i].tlli := tlli_new;
+ ClientTable[i].tlli_old := tlli_old;
+ } else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
+ /* TLLI unassignment: old shall be unassigned; new stays */
+ ClientTable[i].tlli_old := omit;
+ }
+}
+
+private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_BVC_CT return BSSGP_Client_CT {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
+ and ClientTable[i].imsi == imsi) {
+ return ClientTable[i].comp_ref;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Component for IMSI ", imsi));
+ return ClientTable[0].comp_ref;
+}
+
+private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_BVC_CT return BSSGP_Client_CT {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isvalue(ClientTable[i].comp_ref) and
+ (isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
+ isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
+ return ClientTable[i].comp_ref;
+ }
+ }
+ return null;
+}
+
+private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_BVC_CT return integer {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
+ return i;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Client for Component ", comp_ref));
+ return 1;
+}
+
+private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_BVC_CT return OCT4 {
+ var integer i;
+ for (i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
+ and ClientTable[i].comp_ref == comp_ref) {
+ return ClientTable[i].tlli;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find TLLI for Component ", comp_ref));
+ return '00000000'O;
+}
+
+/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
+type record BssgpDecoded {
+ PDU_BSSGP bssgp,
+ PDU_LLC llc optional,
+#ifdef BSSGP_EM_L3
+ PDU_L3_MS_SGSN l3_mo optional,
+ PDU_L3_SGSN_MS l3_mt optional,
+#endif
+ PDU_SN sndcp optional
+}
+
+/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
+private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_BVC_CT return BssgpDecoded {
+ var BssgpDecoded dec := {
+ bssgp := bssgp,
+ llc := omit,
+#ifdef BSSGP_EM_L3
+ l3_mo := omit,
+ l3_mt := omit,
+#endif
+ sndcp := omit
+ };
+
+ /* Decode LLC, if it is a PDU that contains LLC */
+ if (g_cfg.depth >= BSSGP_DECODE_DEPTH_LLC) {
+ if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
+ dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
+ } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
+ dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
+ }
+ }
+
+ /* Decode SNDCP, if it is a LLC PDU containing user plane data */
+ if (g_cfg.depth >= BSSGP_DECODE_DEPTH_SNDCP) {
+ if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
+ dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
+ }
+ }
+
+#ifdef BSSGP_EM_L3
+ /* Decode L3, if it is a LLC PDU containing L3 */
+ if (g_cfg.depth >= BSSGP_DECODE_DEPTH_L3) {
+ if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
+ if (g_sgsn_role) {
+ dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
+ } else {
+ dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
+ }
+ }
+ }
+#endif
+
+ return dec;
+}
+
+private function f_ptp_sendUnblock() runs on BSSGP_BVC_CT {
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK(g_cfg.bvci), 0, g_bvc_lsp));
+ g_t1_waits_for_block_ack := false;
+ g_T1.start;
+}
+
+private function f_ptp_sendBlock(BssgpCause cause) runs on BSSGP_BVC_CT {
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_BLOCK(g_cfg.bvci, cause), 0, g_bvc_lsp));
+ g_t1_waits_for_block_ack := true;
+ g_T1.start;
+ g_last_block_cause := cause;
+}
+
+private function f_ptp_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_BVC_CT {
+ /* FIXME: Make sure correct Signaling or PTP BVCI is used! */
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci, g_bvc_lsp));
+}
+
+private function f_ptp_sendReset(BssgpCause cause := BSSGP_CAUSE_OM_INTERVENTION) runs on BSSGP_BVC_CT {
+ var PDU_BSSGP pdu;
+
+ /* The Cell Identifier IE is mandatory in the BVC-RESET PDU sent from BSS to
+ * SGSN in order to reset a BVC corresponding to a PTP functional entity. The
+ * Cell Identifier IE shall not be used in any other BVC-RESET PDU. */
+ if (g_sgsn_role) {
+ pdu := valueof(ts_BVC_RESET(cause, g_cfg.bvci, omit));
+ } else {
+ pdu := valueof(ts_BVC_RESET(cause, g_cfg.bvci, g_cfg.cell_id));
+ }
+
+ /* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
+ BVC.send(ts_ptp_BnsUdReq(pdu, 0, g_bvc_lsp));
+ g_T2.start;
+ //f_change_state(BVC_S_WAIT_RESET);
+ g_last_reset_cause := cause;
+}
+
+/* PTP-BVC is in BVC_S_BLOCKED state */
+private altstep as_ptp_blocked() runs on BSSGP_BVC_CT {
+ var NsUnitdataIndication udi;
+
+ [g_T1.running and not g_t1_waits_for_block_ack] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
+ g_T1.stop;
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+
+ /* Inbound BVC-UNBLOCK from peer */
+ [g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK(g_cfg.bvci), 0)) {
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+
+ /* RESET-ACK before T2 timeout: reset successful. In SGSN role, CellID must be present */
+ [g_T2.running and g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
+ g_T2.stop;
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+ /* RESET-ACK before T2 timeout: reset successful. In BSS role, CellID must be absent */
+ [g_T2.running and not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) -> value udi {
+ g_T2.stop;
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+
+ [] as_ptp_handle_inbound_reset();
+
+ [] g_T2.timeout {
+ /* BVC-RESET-ACK PDU was not received within T2: retransmit */
+ f_ptp_sendReset(g_last_reset_cause);
+ }
+
+ [] MGMT.receive(BssgpUnblockRequest:?) {
+ f_ptp_sendUnblock();
+ }
+}
+
+/* PTP-BVC is in UNBLOCKED state */
+private altstep as_ptp_unblocked() runs on BSSGP_BVC_CT {
+ var NsUnitdataIndication udi;
+ var NsStatusIndication nsi;
+ var BssgpBlockRequest bbr;
+ var BSSGP_Client_CT vc_conn;
+ var ASP_Event evt;
+ var PDU_BSSGP bs_pdu;
+ var PDU_LLC llc;
+#ifdef BSSGP_EM_L3
+ var PDU_L3_MS_SGSN l3_mo;
+ var PDU_L3_SGSN_MS l3_mt;
+#endif
+
+ /* bogus unblock, just respond with ACK */
+ [] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
+ }
+ /* Respond to BLOCK with BLOCK-ACK + change state */
+ [] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_BLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
+ g_T1.stop;
+ f_ptp_change_state(BVC_S_BLOCKED);
+ }
+ /* BLOCK-ACK before T1 timeout: mark as blocked */
+ [g_T1.running and g_t1_waits_for_block_ack] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
+ g_T1.stop;
+ f_ptp_change_state(BVC_S_BLOCKED);
+ }
+ /* Re-transmit BLOCK / UNBLOCK on T1 timeout */
+ [g_T1.running and not g_t1_waits_for_block_ack] g_T1.timeout {
+ f_ptp_sendUnblock();
+ }
+ [g_T1.running and g_t1_waits_for_block_ack] g_T1.timeout {
+ f_ptp_sendBlock(g_last_block_cause);
+ }
+
+ [] as_ptp_handle_inbound_reset();
+
+ [g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
+ if (GLOBAL.checkstate("Connected")) {
+ GLOBAL.send(udi.bssgp);
+ } else {
+ /* simply acknowledge all per-BVC Flow Control Messages */
+ var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_FC_BVC_ACK(tag), g_cfg.bvci, g_bvc_lsp));
+ }
+ }
+
+ [not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_FC_BVC_ACK(?), g_cfg.bvci)) -> value udi {
+ if (GLOBAL.checkstate("Connected")) {
+ GLOBAL.send(udi.bssgp);
+ } else {
+ /* ignore any incoming flow control ACK */
+ }
+ }
+
+ [] BVC.receive(tr_ptp_BnsUdInd(tr_GLOBAL_PTP, g_cfg.bvci)) -> value udi {
+ if (GLOBAL.checkstate("Connected")) {
+ GLOBAL.send(udi.bssgp);
+ } else {
+ setverdict(fail, "Received BSSGP STATUS ", udi.bssgp);
+ }
+ }
+
+ /* Any other PTP BSSGP message: If it has TLLI, route to component; otherwise broadcast */
+ [] BVC.receive(tr_ptp_BnsUdInd(?, g_cfg.bvci)) -> value udi {
+ var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
+ var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
+ if (isvalue(tlli)) {
+ vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
+ if (vc_conn == null) {
+ g_cfg.create_cb.apply(g_cfg.bvci, g_cfg.cell_id, valueof(tlli), dec);
+ } else {
+ f_send_bssgp_dec(dec, vc_conn, BSSGP_SP);
+ }
+ } else {
+ log("No TLLI: Broadcasting ", dec);
+ /* broadcast this message to all components */
+ // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
+ for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
+ f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP);
+ }
+ }
+ }
+ }
+
+ [] BVC.receive(tr_ptp_BnsUdInd(tr_BSSGP_FLUSH_LL_ACK(?, ?, ?), 0)) -> value udi {
+ var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
+
+ log("Broadcasting FLUSH_LL_ACK ", dec);
+ /* broadcast this message to all components */
+ // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
+ for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
+ f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
+ }
+ }
+ }
+
+ /* Any other SIG BSSGP message: If it has TLLI, route to component; otherwise broadcast */
+ [] BVC.receive(tr_ptp_BnsUdInd(?, 0)) -> value udi {
+ var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
+ var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
+ if (isvalue(tlli)) {
+ vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
+ if (vc_conn == null) {
+ g_cfg.create_cb.apply(g_cfg.bvci, g_cfg.cell_id, valueof(tlli), dec);
+ } else {
+ f_send_bssgp_dec(dec, vc_conn, BSSGP_SP_SIG);
+ }
+ } else {
+ log("No TLLI: Broadcasting ", dec);
+ /* broadcast this message to all components */
+ // TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
+ for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
+ f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
+ }
+ }
+ }
+ }
+
+ /* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP_CT */
+ [] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
+ BVC.send(ts_ptp_BnsUdReq(bs_pdu, 0, g_bvc_lsp));
+ }
+
+ /* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP_CT */
+ [] BSSGP_SP.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
+ BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci, g_bvc_lsp));
+ }
+
+#ifdef BSSGP_EM_L3
+ /* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
+ [g_sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
+ var integer idx := f_tbl_idx_by_comp(vc_conn);
+ var OCT4 tlli := ClientTable[idx].tlli;
+ var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
+ var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
+ var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
+ var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
+ }
+ [not g_sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
+ var integer idx := f_tbl_idx_by_comp(vc_conn);
+ var OCT4 tlli := ClientTable[idx].tlli;
+ var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
+ var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
+ var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
+ var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
+ }
+#endif
+
+ /* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
+ [not g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
+ var integer idx := f_tbl_idx_by_comp(vc_conn);
+ var OCT4 tlli := ClientTable[idx].tlli;
+ var octetstring llc_enc := enc_PDU_LLC(llc);
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
+ }
+ [g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
+ var integer idx := f_tbl_idx_by_comp(vc_conn);
+ var OCT4 tlli := ClientTable[idx].tlli;
+ var octetstring llc_enc := enc_PDU_LLC(llc);
+ BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
+ }
+
+ /* Testcase sends us BSSGP on global port */
+ [] GLOBAL.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
+ BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci, g_bvc_lsp));
+ }
+
+ [] MGMT.receive(BssgpBlockRequest:?) -> value bbr {
+ f_ptp_sendBlock(bbr.cause);
+ }
+}
+
+private altstep as_ptp_handle_inbound_reset() runs on BSSGP_BVC_CT {
+ var NsUnitdataIndication udi;
+ /* we are a SGSN: BSS/PCU-originated RESET must have a cell ID */
+ [g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
+ log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{g_cfg.bvci});
+ }
+ /* Respond to RESET with correct BVCI but without CellID */
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, omit), 0, g_bvc_lsp));
+ /* FIXME: reset all state? What about clients? */
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+ /* we are a BSS/PCU: SGSN-originated RESET must not have a cell ID */
+ [not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, omit), 0)) -> value udi {
+ log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{g_cfg.bvci});
+ }
+ /* Respond to RESET with correct BVCI with CellID */
+ BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0, g_bvc_lsp));
+ /* FIXME: reset all state? What about clients? */
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+}
+
+/* Events permitted in all states */
+private altstep as_ptp_allstate() runs on BSSGP_BVC_CT {
+ var NsUnitdataIndication udi;
+ var BssgpResetRequest brr;
+ var BSSGP_Client_CT vc_conn;
+ var OCT4 tlli, tlli_old;
+ var hexstring imsi;
+
+ /* Signaling BVC was reset */
+ [] BVC.receive(BssgpResetIndication:{0}) {
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(BssgpResetIndication:{0});
+ }
+ if (not g_sgsn_role) {
+ f_ptp_change_state(BVC_S_BLOCKED);
+ /* when the BSS side signaling PTP is RESET, all PTP BVC must start the
+ * reset procedure */
+ f_ptp_sendReset();
+ } else {
+ f_ptp_change_state(BVC_S_UNBLOCKED);
+ }
+ }
+
+ /* Ignore those for now */
+ [] BVC.receive(ASP_Event:?) { }
+ [] BVC.receive(BssgpStatusIndication:?) { }
+
+ /* catch-all */
+ [] BVC.receive(tr_ptp_BnsUdInd(?, 0)) -> value udi {
+ setverdict(fail, "Received unexpected NS (SIG): ", udi);
+ }
+ [] BVC.receive(tr_ptp_BnsUdInd(?, ?)) -> value udi {
+ setverdict(fail, "Received unexpected NS (PTP): ", udi);
+ }
+ [] BVC.receive {
+ setverdict(fail, "Received unexpected message from BSSGP_CT");
+ }
+
+ /* registration/deregistration of Clients (per-TLLI components) */
+ [] BSSGP_PROC.getcall(BSSGP_register_client:{?,?}) -> param(imsi, tlli) sender vc_conn {
+ f_tbl_client_add(imsi, tlli, vc_conn);
+ BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli}) to vc_conn;
+ }
+ [] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
+ f_tbl_client_del(imsi, vc_conn);
+ BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
+ }
+ [] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
+ f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
+ BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
+ }
+
+ [] MGMT.receive(BssgpResetRequest:?) -> value brr {
+ f_ptp_change_state(BVC_S_BLOCKED);
+ f_ptp_sendReset(brr.cause);
+ }
+}
+
+/* main loop for per-BVC component */
+private function f_bssgp_bvc_ScanEvents() runs on BSSGP_BVC_CT {
+ while (true) {
+ alt {
+ [g_ptp_bvc_state == BVC_S_BLOCKED] as_ptp_blocked();
+ [g_ptp_bvc_state == BVC_S_UNBLOCKED] as_ptp_unblocked();
+ [] as_ptp_allstate();
+ }
+ }
+}
+
+/* main function for per-BVC Component */
+private function f_bssgp_bvc_main(BssgpBvcConfig cfg, boolean sgsn_role, Nsei nsei, charstring id) runs on BSSGP_BVC_CT {
+ g_cfg := cfg;
+ g_nsei := nsei;
+ g_bvc_lsp := cfg.bvci;
+ g_sgsn_role := sgsn_role;
+ f_bssgp_bvc_ScanEvents();
+}
+
+template (value) NsUnitdataRequest ts_ptp_BnsUdReq(template (value) PDU_BSSGP pdu, template (value) BssgpBvci bvci,
+ template (value) integer lsp) := {
+ bvci := bvci,
+ nsei := 0, // overwritten in BSSGP_CT
+ lsp := lsp,
+ /* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
+ * unbound integer value." when trying to send the reocrd rather than the octetstring */
+ //sdu := omit,
+ //bssgp := valueof(pdu)
+ sdu := enc_PDU_BSSGP(valueof(pdu)),
+ bssgp := omit
+}
+
+template (present) NsUnitdataIndication tr_ptp_BnsUdInd(template (present) PDU_BSSGP pdu, template (present) BssgpBvci bvci) := {
+ bvci := bvci,
+ nsei := ?,
+ nsvci := ?,
+ sdu := *,
+ bssgp := pdu
+}
+
+/* change state of PTP BVC; broadcast state change to clients */
+private function f_ptp_change_state(BvcState new_state) runs on BSSGP_BVC_CT {
+ if (new_state == g_ptp_bvc_state) {
+ return;
+ }
+ log("BVCI(", g_cfg.bvci, ") State Transition: ", g_ptp_bvc_state, " -> ", new_state);
+ g_ptp_bvc_state := new_state;
+ if (MGMT.checkstate("Connected")) {
+ MGMT.send(ts_BssgpStsInd(g_nsei, g_cfg.bvci, g_ptp_bvc_state));
+ }
+ for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
+ if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
+ BSSGP_SP.send(ts_BssgpStsInd(g_nsei, g_cfg.bvci, g_ptp_bvc_state)) to ClientTable[i].comp_ref;
+ }
+ }
+}
+
+/* attempt to extract the TLLI from a BSSGP PDU */
+function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
+ if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
+ return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
+ } else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
+ return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
+ } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
+ return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
+ return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
+ return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS) and
+ ispresent(bssgp.pDU_BSSGP_RADIO_STATUS.tLLI)) {
+ return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
+ return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
+ return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
+ return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
+ return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
+ return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
+ return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
+ return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
+ return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
+ return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
+ return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
+ isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
+ return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
+ return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
+ } else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
+ return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
+ }
+ /* TODO: Handover, PFC, LCS */
+ return omit;
+}
+
+
+
+}
diff --git a/library/BSSLAP_Types.ttcn b/library/BSSLAP_Types.ttcn
new file mode 100644
index 00000000..a55f5dad
--- /dev/null
+++ b/library/BSSLAP_Types.ttcn
@@ -0,0 +1,606 @@
+module BSSLAP_Types {
+
+/* BSSLAP_Types, defining abstract TTCN-3 data types for the 3GPP BSSLAP protocol.
+ *
+ * BSSLAP is a 3GPP standard protocol used between BSC and SMLC in a GSM network.
+ * This file covers 3GPP TS 48.071 version 15.0.0 Release 15
+ *
+ * (C) 2020 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+
+/* 3GPP TS 48.071 Table 5.1 */
+type enumerated BSSLAP_IEI {
+ BSSLAP_IEI_TA ('00000001'B),
+ BSSLAP_IEI_CELL_ID ('00001001'B),
+ BSSLAP_IEI_CHAN_DESC ('00010000'B),
+ BSSLAP_IEI_MEAS_REP ('00010100'B),
+ BSSLAP_IEI_CAUSE ('00011000'B),
+ BSSLAP_IEI_RRLP_FLAG ('00011001'B),
+ BSSLAP_IEI_RRLP ('00011011'B),
+ BSSLAP_IEI_CELL_ID_LIST ('00011100'B),
+ BSSLAP_IEI_ENH_MEAS_REP ('00011101'B),
+ BSSLAP_IEI_LAC ('00011110'B),
+ BSSLAP_IEI_FREQ_LIST ('00100001'B),
+ BSSLAP_IEI_MS_POWER ('00100010'B),
+ BSSLAP_IEI_DELTA_TIMER ('00100011'B),
+ BSSLAP_IEI_SERVING_CELL_ID ('00100100'B),
+ BSSLAP_IEI_ENCR_KEY ('00100101'B),
+ BSSLAP_IEI_CIPH_MODE_SET ('00100110'B),
+ BSSLAP_IEI_CHAN_MODE ('00100111'B),
+ BSSLAP_IEI_MR_CONFIG ('00101000'B),
+ BSSLAP_IEI_POLLING_REPETITION ('00101001'B),
+ BSSLAP_IEI_PACKET_CHAN_DESC ('00101010'B),
+ BSSLAP_IEI_TLLI ('00101011'B),
+ BSSLAP_IEI_TFI ('00101100'B),
+ BSSLAP_IEI_TBF_START_TIME ('00101101'B),
+ BSSLAP_IEI_PWRUP_START_TIME ('00101110'B),
+ BSSLAP_IEI_LONG_ENCR_KEY ('00101111'B),
+ BSSLAP_IEI_CONCUR_POS_PROC_F ('00110000'B)
+} with { variant "FIELDLENGTH(8)" };
+
+/* 3GPP TS 48.071 Section 5.1 */
+type enumerated BSSLAP_MsgType {
+ BSSLAP_MSGT_TA_REQUEST ('00000001'B),
+ BSSLAP_MSGT_TA_RESPONSE ('00000010'B),
+ BSSLAP_MSGT_REJECT ('00001010'B),
+ BSSLAP_MSGT_RESET ('00001011'B),
+ BSSLAP_MSGT_ABORT ('00001100'B),
+ BSSLAP_MSGT_TA_LAYER3 ('00001101'B),
+ BSSLAP_MSGT_MS_POS_CMD ('00001111'B),
+ BSSLAP_MSGT_MS_POS_RESP ('00010000'B),
+ BSSLAP_MSGT_UTDOA_REQ ('00010001'B),
+ BSSLAP_MSGT_UTDOA_RESP ('00010010'B)
+} with { variant "FIELDLENGTH(8)" };
+
+
+/* Section 4.2.1 */
+type record BSSLAP_TaRequest {
+ BSSLAP_MsgType msg_type
+};
+
+/* Section 4.2.2 */
+type record BSSLAP_TaResponse {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_CellId serving_cell_id,
+ BSSLAP_IE_TimingAdvance timing_advance,
+ BSSLAP_IE_MeasRep meas_rep optional,
+ BSSLAP_IE_EnhMeasRep enh_meas_rep optional,
+ BSSLAP_IE_CellIdList meas_cell_id_list optional,
+ BSSLAP_IE_ConcurMethodF concur_meth_flag optional
+};
+
+/* Section 4.2.5 */
+type record BSSLAP_Reject {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_Cause cause
+};
+
+/* Section 4.2.6 */
+type record BSSLAP_Reset {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_CellId cell_id,
+ BSSLAP_IE_TimingAdvance timing_advance,
+ BSSLAP_IE_ChanDesc chan_desc,
+ BSSLAP_IE_Cause cause,
+ BSSLAP_IE_MeasRep meas_rep optional,
+ BSSLAP_IE_EnhMeasRep enh_meas_rep optional,
+ BSSLAP_IE_CellIdList meas_cell_id_list optional,
+ BSSLAP_IE_LAC lac optional,
+ BSSLAP_IE_FreqList freq_list optional,
+ BSSLAP_IE_ChanMode chan_mode optional,
+ BSSLAP_IE_MultiRateConfig mr_config optional,
+ BSSLAP_IE_PacketChanDesc pkt_chan_desc optional,
+ BSSLAP_IE_TLLI tlli optional,
+ BSSLAP_IE_TFI tfi optional,
+ BSSLAP_IE_StartingTime tbf_start_time optional,
+ BSSLAP_IE_EncryptionKey encr_key optional,
+ BSSLAP_IE_CiphModeSet ciph_mode_set optional,
+ BSSLAP_IE_LongEncryptionKey long_encr_key optional
+};
+
+/* Section 4.2.7 */
+type record BSSLAP_Abort {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_Cause cause
+};
+
+/* Section 4.2.8 */
+type record BSSLAP_TA_Layer3 {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_TimingAdvance timing_advance,
+ BSSLAP_IE_MeasRep meas_rep optional,
+ BSSLAP_IE_EnhMeasRep enh_meas_rep optional,
+ BSSLAP_IE_CellIdList meas_cell_id_list optional
+};
+
+/* Section 4.2.9 */
+type record BSSLAP_MS_PosCmd {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_RrlpFlag flag,
+ BSSLAP_IE_Rrlp rrlp_info
+};
+
+/* Section 4.2.10 */
+type record BSSLAP_MS_PosResp {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_RrlpFlag flag,
+ BSSLAP_IE_Rrlp rrlp_info,
+ BSSLAP_IE_TimingAdvance timing_advance optional,
+ BSSLAP_IE_MeasRep meas_rep optional,
+ BSSLAP_IE_EnhMeasRep enh_meas_rep optional,
+ BSSLAP_IE_CellIdList meas_cell_id_list optional,
+ BSSLAP_IE_ConcurMethodF concur_meth_flag optional
+};
+
+/* Section 4.2.11 */
+type record BSSLAP_UTDOA_Req {
+ BSSLAP_MsgType msg_type,
+ BSSLAP_IE_DeltaTimer delta_timer optional,
+ BSSLAP_IE_PollingRep polling_repetition optional
+};
+
+type union BSSLAP_PDU {
+ BSSLAP_TaRequest ta_req,
+ BSSLAP_TaResponse ta_resp,
+ BSSLAP_Reject reject,
+ BSSLAP_Reset reset,
+ BSSLAP_Abort abort,
+ BSSLAP_TA_Layer3 ta_layer3,
+ BSSLAP_MS_PosCmd ms_pos_cmd,
+ BSSLAP_MS_PosResp ms_pos_resp,
+ BSSLAP_UTDOA_Req utdoa_req
+ // TODO: U-TDOA Resp
+} with { variant "TAG(
+ ta_req, msg_type = BSSLAP_MSGT_TA_REQUEST;
+ ta_resp, msg_type = BSSLAP_MSGT_TA_RESPONSE;
+ reject, msg_type = BSSLAP_MSGT_REJECT;
+ reset, msg_type = BSSLAP_MSGT_RESET;
+ abort, msg_type = BSSLAP_MSGT_ABORT;
+ ta_layer3, msg_type = BSSLAP_MSGT_TA_LAYER3;
+ ms_pos_cmd, msg_type = BSSLAP_MSGT_MS_POS_CMD;
+ ms_pos_resp, msg_type = BSSLAP_MSGT_MS_POS_RESP;
+ utdoa_req, msg_type = BSSLAP_MSGT_UTDOA_REQ;
+ )"
+};
+
+
+/* Section 5.2 */
+type record BSSLAP_IE_TimingAdvance {
+ BSSLAP_IEI iei,
+ uint8_t ta
+} with { variant "PRESENCE(iei = BSSLAP_IEI_TA)" };
+
+
+/* Section 5.4 */
+type record BSSLAP_IE_CellId {
+ BSSLAP_IEI iei,
+ uint16_t cell_id
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CELL_ID)" };
+
+/* Section 5.8 */
+type record BSSLAP_IE_ChanDesc {
+ BSSLAP_IEI iei,
+ OCT3 chan_desc
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CHAN_DESC)" };
+
+
+/* Section 5.12 */
+type record BSSLAP_IE_MeasRep {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ octetstring meas_rep
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_MEAS_REP)"
+ variant (len) "LENGTHTO(meas_rep)"
+};
+
+/* Section 5.14 */
+type record BSSLAP_IE_Cause {
+ BSSLAP_IEI iei,
+ BSSLAP_Cause cause
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CAUSE)" };
+type enumerated BSSLAP_Cause {
+ BSSLAP_CAUSE_CONGESTION ('00000000'B),
+ BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP ('00000001'B),
+ BSSLAP_CAUSE_POS_PROC_NOT_SUPP ('00000010'B),
+ BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL ('00000011'B),
+ BSSLAP_CAUSE_INTRA_BSS_HO ('00000100'B),
+ BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED ('00000101'B),
+ BSSLAP_CAUSE_INTER_BSS_HO ('00000110'B),
+ BSSLAP_CAUSE_LOSS_SIG_CONN_MS ('00000111'B),
+ BSSLAP_CAUSE_INCORR_SERV_CELL_ID ('00001000'B),
+ BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR ('00001001'B),
+ BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN ('00001010'B)
+};
+
+/* Section 5.15 */
+type record BSSLAP_IE_RrlpFlag {
+ BSSLAP_IEI iei,
+ BIT7 spare,
+ boolean not_a_pos_cmd
+} with { variant "PRESENCE(iei = BSSLAP_IEI_RRLP_FLAG)" };
+
+/* Section 5.16 */
+type record BSSLAP_IE_Rrlp {
+ BSSLAP_IEI iei,
+ uint16_t len,
+ octetstring rrlp_apdu
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_RRLP)"
+ variant (len) "LENGTHTO(rrlp_apdu)"
+};
+
+/* Section 5.17 */
+type record BSSLAP_IE_CellIdList {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ BSSLAP_CellIdList cell_id_list
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_CELL_ID_LIST)"
+ variant (len) "LENGTHTO(cell_id_list)"
+};
+type record of BSSLAP_CellIdListEnt BSSLAP_CellIdList;
+type union BSSLAP_CellIdListEnt {
+ BIT4 spare,
+ BSSLAP_CellIdDiscr discr,
+ BSSLAP_CellIdListEntU u
+}// with {
+//};
+type enumerated BSSLAP_CellIdDiscr {
+ BSSLAP_CIDL_DISC_CGI ('0000'B),
+ BSSLAP_CIDL_DISC_LAC_CI ('0001'B),
+ BSSLAP_CIDL_DISC_3G_1 ('0010'B),
+ BSSLAP_CIDL_DISC_3G_2 ('0011'B)
+} with { variant "FIELDLENGTH(4)" };
+type union BSSLAP_CellIdListEntU {
+ BSSLAP_CellIdListEntCGI cgi,
+ BSSLAP_CellIdListEntLACCI lac_ci,
+ BSSLAP_CellIdListEnt3G1 umts_cont1,
+ BSSLAP_CellIdListEnt3G2 umts_cont2
+};
+type record BSSLAP_CellIdListEntCGI {
+ HEX6n mcc_mnc,
+ uint16_t lac,
+ uint16_t ci
+};
+type record BSSLAP_CellIdListEntLACCI {
+ uint16_t lac,
+ uint16_t ci
+};
+type record BSSLAP_CellIdListEnt3G1 {
+ OCT9 cont
+};
+type record BSSLAP_CellIdListEnt3G2 {
+ OCT6 cont
+};
+
+/* Section 5.18 */
+type record BSSLAP_IE_EnhMeasRep {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ octetstring meas_rep
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_ENH_MEAS_REP)"
+ variant (len) "LENGTHTO(meas_rep)"
+};
+
+/* Section 5.19 */
+type record BSSLAP_IE_LAC {
+ BSSLAP_IEI iei,
+ uint16_t lac
+} with { variant "PRESENCE(iei = BSSLAP_IEI_LAC)" };
+
+/* Section 5.20 */
+type record BSSLAP_IE_FreqList {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ octetstring freq_list
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_FREQ_LIST)"
+ variant (len) "LENGTHTO(freq_list)"
+};
+
+/* Section 5.21 */
+type record BSSLAP_IE_MsPower {
+ BSSLAP_IEI iei,
+ uint8_t ms_pwr
+} with { variant "PRESENCE(iei = BSSLAP_IEI_MS_POWER)" };
+
+/* Section 5.22 */
+type record BSSLAP_IE_DeltaTimer {
+ BSSLAP_IEI iei,
+ uint8_t timer_val
+} with { variant "PRESENCE(iei = BSSLAP_IEI_MS_POWER)" };
+
+/* Section 5.23 */
+type record BSSLAP_IE_ServingCellId {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ octetstring val // FIXME: like TS 08.08
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_SERVING_CELL_ID)"
+ variant (len) "LENGTHTO(val)"
+};
+
+/* Section 5.24 */
+type record BSSLAP_IE_EncryptionKey {
+ BSSLAP_IEI iei,
+ OCT8 kc
+} with { variant "PRESENCE(iei = BSSLAP_IEI_ENCR_KEY)" };
+
+/* Section 5.25 */
+type record BSSLAP_IE_CiphModeSet {
+ BSSLAP_IEI iei,
+ BIT1 spare,
+ BIT3 iei2,
+ BIT3 algo_id,
+ boolean sc
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CIPH_MODE_SET)" };
+
+/* Section 5.26 */
+type record BSSLAP_IE_ChanMode {
+ BSSLAP_IEI iei,
+ OCT1 mode
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CHAN_MODE)" };
+
+/* Section 5.27 */
+type record BSSLAP_IE_MultiRateConfig {
+ BSSLAP_IEI iei,
+ uint8_t len,
+ /* TODO: Unify with TS 48.018 */
+ uint3_t mr_speech_ver,
+ boolean nscb,
+ boolean icmi,
+ BIT1 spare,
+ uint2_t start_mode,
+ octetstring parameters
+} with {
+ variant "PRESENCE(iei = BSSLAP_IEI_MR_CONFIG)"
+ variant (len) "LENGTHTO(mr_speech_ver,nscb,icmi,spare,start_mode,parameters)"
+};
+
+/* Section 5.28 */
+type record BSSLAP_IE_PollingRep {
+ BSSLAP_IEI iei,
+ BIT2 spare,
+ uint6_t num_rep
+} with { variant "PRESENCE(iei = BSSLAP_IEI_MR_CONFIG)" };
+
+/* Section 5.29 */
+type record BSSLAP_IE_PacketChanDesc {
+ BSSLAP_IEI iei,
+ OCT4 chan_desc
+} with { variant "PRESENCE(iei = BSSLAP_IEI_PACKET_CHAN_DESC)" };
+
+/* Section 5.30 */
+type record BSSLAP_IE_TLLI {
+ BSSLAP_IEI iei,
+ OCT4 tlli
+} with { variant "PRESENCE(iei = BSSLAP_IEI_TLLI)" };
+
+/* Section 5.31 */
+type record BSSLAP_IE_TFI {
+ BSSLAP_IEI iei,
+ BIT3 spare,
+ uint5_t tfi
+} with { variant "PRESENCE(iei = BSSLAP_IEI_TFI)" };
+
+/* Section 5.32 */
+type record BSSLAP_IE_StartingTime {
+ BSSLAP_IEI iei,
+ uint5_t t1_p,
+ uint6_t t3,
+ uint6_t t2
+} with { variant "PRESENCE(iei = BSSLAP_IEI_TBF_START_TIME)" };
+
+/* Section 5.33 */
+type record BSSLAP_IE_LongEncryptionKey {
+ BSSLAP_IEI iei,
+ OCT16 kc
+} with { variant "PRESENCE(iei = BSSLAP_IEI_LONG_ENCR_KEY)" };
+
+/* Section 5.34 */
+type record BSSLAP_IE_ConcurMethodF {
+ BSSLAP_IEI iei,
+ BSSLAP_ConcurMethodF flag
+} with { variant "PRESENCE(iei = BSSLAP_IEI_CONCUR_POS_PROC_F)" };
+type enumerated BSSLAP_ConcurMethodF {
+ BSSLAP_SECOND_CONCUR_ALLOWED ('00000000'B),
+ BSSLAP_SECOND_CONCUR_DISALLOWED ('11111111'B)
+} with { variant "FIELDLENGTH(8)" };
+
+
+
+external function enc_BSSLAP_PDU(in BSSLAP_PDU msg) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_BSSLAP_PDU(in octetstring stream) return BSSLAP_PDU
+ with { extension "prototype(convert) decode(RAW)" };
+
+template (value) BSSLAP_PDU ts_BSSLAP_TA_Req := {
+ ta_req := {
+ msg_type := BSSLAP_MSGT_TA_REQUEST
+ }
+}
+template (present) BSSLAP_PDU tr_BSSLAP_TA_Req := {
+ ta_req := {
+ msg_type := BSSLAP_MSGT_TA_REQUEST
+ }
+}
+
+template (value) BSSLAP_PDU
+ts_BSSLAP_TA_Resp(uint16_t cell_id, uint8_t ta) := {
+ ta_resp := {
+ msg_type := BSSLAP_MSGT_TA_RESPONSE,
+ serving_cell_id := ts_BSSLAP_IE_CellId(cell_id),
+ timing_advance := ts_BSSLAP_IE_TA(ta),
+ meas_rep := omit,
+ enh_meas_rep := omit,
+ meas_cell_id_list := omit,
+ concur_meth_flag := omit
+ }
+}
+template (present) BSSLAP_PDU
+tr_BSSLAP_TA_Resp(template (present) uint16_t cell_id, template (present) uint8_t ta) := {
+ ta_resp := {
+ msg_type := BSSLAP_MSGT_TA_RESPONSE,
+ serving_cell_id := tr_BSSLAP_IE_CellId(cell_id),
+ timing_advance := tr_BSSLAP_IE_TA(ta),
+ meas_rep := *,
+ enh_meas_rep := *,
+ meas_cell_id_list := *,
+ concur_meth_flag := *
+ }
+}
+
+template (value) BSSLAP_PDU
+ts_BSSLAP_Reject(BSSLAP_Cause cause) := {
+ reject := {
+ msg_type := BSSLAP_MSGT_REJECT,
+ cause := ts_BSSLAP_IE_Cause(cause)
+ }
+}
+template (present) BSSLAP_PDU
+tr_BSSLAP_Reject(template (present) BSSLAP_Cause cause) := {
+ reject := {
+ msg_type := BSSLAP_MSGT_REJECT,
+ cause := tr_BSSLAP_IE_Cause(cause)
+ }
+}
+
+
+template (value) BSSLAP_PDU
+ts_BSSLAP_Abort(BSSLAP_Cause cause) := {
+ abort := {
+ msg_type := BSSLAP_MSGT_ABORT,
+ cause := ts_BSSLAP_IE_Cause(cause)
+ }
+}
+template (present) BSSLAP_PDU
+tr_BSSLAP_Abort(template (present) BSSLAP_Cause cause) := {
+ abort := {
+ msg_type := BSSLAP_MSGT_ABORT,
+ cause := tr_BSSLAP_IE_Cause(cause)
+ }
+}
+
+template (value) BSSLAP_PDU ts_BSSLAP_TA_Layer3(uint8_t ta) := {
+ ta_layer3 := {
+ msg_type := BSSLAP_MSGT_TA_LAYER3,
+ timing_advance := ts_BSSLAP_IE_TA(ta),
+ meas_rep := omit,
+ enh_meas_rep := omit,
+ meas_cell_id_list := omit
+ }
+}
+
+template (present) BSSLAP_PDU tr_BSSLAP_TA_Layer3(template BSSLAP_IE_TimingAdvance timing_advance := *) := {
+ ta_layer3 := {
+ msg_type := BSSLAP_MSGT_TA_LAYER3,
+ timing_advance := timing_advance,
+ meas_rep := *,
+ enh_meas_rep := *,
+ meas_cell_id_list := *
+ }
+}
+
+template (value) BSSLAP_IE_ChanDesc ts_BSSLAP_IE_ChanDesc := {
+ iei := BSSLAP_IEI_CHAN_DESC,
+ chan_desc := '112233'O /* FIXME */
+}
+
+template (value) BSSLAP_PDU
+ts_BSSLAP_Reset(uint16_t cell_id,
+ uint8_t ta,
+ BSSLAP_IE_ChanDesc chan_desc,
+ BSSLAP_Cause cause) := {
+ reset := {
+ msg_type := BSSLAP_MSGT_RESET,
+ cell_id := ts_BSSLAP_IE_CellId(cell_id),
+ timing_advance := ts_BSSLAP_IE_TA(ta),
+ chan_desc := chan_desc,
+ cause := ts_BSSLAP_IE_Cause(cause),
+ meas_rep := omit,
+ enh_meas_rep := omit,
+ meas_cell_id_list := omit,
+ lac := omit,
+ freq_list := omit,
+ chan_mode := omit,
+ mr_config := omit,
+ pkt_chan_desc := omit,
+ tlli := omit,
+ tfi := omit,
+ tbf_start_time := omit,
+ encr_key := omit,
+ ciph_mode_set := omit,
+ long_encr_key := omit
+ }
+}
+
+template (present) BSSLAP_PDU
+tr_BSSLAP_Reset(template (present) BSSLAP_Cause cause) := {
+ reset := {
+ msg_type := BSSLAP_MSGT_RESET,
+ cell_id := ?,
+ timing_advance := ?,
+ chan_desc := ?,
+ cause := tr_BSSLAP_IE_Cause(cause),
+ meas_rep := *,
+ enh_meas_rep := *,
+ meas_cell_id_list := *,
+ lac := *,
+ freq_list := *,
+ chan_mode := *,
+ mr_config := *,
+ pkt_chan_desc := *,
+ tlli := *,
+ tfi := *,
+ tbf_start_time := *,
+ encr_key := *,
+ ciph_mode_set := *,
+ long_encr_key := *
+ }
+}
+
+template (value) BSSLAP_IE_TimingAdvance ts_BSSLAP_IE_TA(uint8_t ta) := {
+ iei := BSSLAP_IEI_TA,
+ ta := ta
+}
+template (present) BSSLAP_IE_TimingAdvance tr_BSSLAP_IE_TA(template (present) uint8_t ta) := {
+ iei := BSSLAP_IEI_TA,
+ ta := ta
+}
+
+template (value) BSSLAP_IE_CellId ts_BSSLAP_IE_CellId(uint16_t cell_id) := {
+ iei := BSSLAP_IEI_CELL_ID,
+ cell_id := cell_id
+}
+template (present) BSSLAP_IE_CellId tr_BSSLAP_IE_CellId(template (present) uint16_t cell_id) := {
+ iei := BSSLAP_IEI_CELL_ID,
+ cell_id := cell_id
+}
+
+template (value) BSSLAP_IE_Cause ts_BSSLAP_IE_Cause(BSSLAP_Cause cause) := {
+ iei := BSSLAP_IEI_CAUSE,
+ cause := cause
+}
+template (present) BSSLAP_IE_Cause tr_BSSLAP_IE_Cause(template (present) BSSLAP_Cause cause) := {
+ iei := BSSLAP_IEI_CAUSE,
+ cause := cause
+}
+
+
+
+
+
+
+} with { encode "RAW" };
diff --git a/library/BSSMAP_LE_Templates.ttcn b/library/BSSMAP_LE_Templates.ttcn
new file mode 100644
index 00000000..3619a3aa
--- /dev/null
+++ b/library/BSSMAP_LE_Templates.ttcn
@@ -0,0 +1,455 @@
+module BSSMAP_LE_Templates {
+
+/* BSSMAP-LE Templates, building on top of BSSAP_LE_Types.
+ *
+ * (C) 2017-2020 by Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from BSSAP_Types all;
+import from BSSAP_LE_Types all;
+import from BSSMAP_Templates all;
+import from L3_Templates all;
+
+function ts_BSSMAP_LE_LcsCause(template (omit) BSSMAP_LE_LcsCause cause)
+return template (omit) BSSMAP_LE_IE_LcsCause {
+ if (istemplatekind(cause, "omit")) {
+ return omit;
+ }
+ var template (omit) BSSMAP_LE_IE_LcsCause ie := {
+ iei := BSSMAP_LE_IEI_LCS_CAUSE,
+ len := 1,
+ cause := cause,
+ diag_val := omit
+ }
+ return ie;
+}
+function tr_BSSMAP_LE_LcsCause(template BSSMAP_LE_LcsCause cause)
+return template BSSMAP_LE_IE_LcsCause {
+ if (istemplatekind(cause, "omit")) {
+ return omit;
+ }
+ var template BSSMAP_LE_IE_LcsCause ie := {
+ iei := BSSMAP_LE_IEI_LCS_CAUSE,
+ len := ?,
+ cause := cause,
+ diag_val := *
+ }
+ return ie;
+}
+
+
+function ts_BSSMAP_LE_GeographicLoc(template (omit) octetstring loc)
+return template (omit) BSSMAP_LE_IE_GeographicLoc {
+ if (istemplatekind(loc, "omit")) {
+ return omit;
+ }
+ var template (omit) BSSMAP_LE_IE_GeographicLoc ie := {
+ iei := BSSMAP_LE_IEI_GEO_LOCATION,
+ len := 0,
+ location := loc
+ }
+ return ie;
+}
+function tr_BSSMAP_LE_GeographicLoc(template octetstring loc)
+return template BSSMAP_LE_IE_GeographicLoc {
+ if (istemplatekind(loc, "omit")) {
+ return omit;
+ }
+ var template BSSMAP_LE_IE_GeographicLoc ie := {
+ iei := BSSMAP_LE_IEI_GEO_LOCATION,
+ len := ?,
+ location := loc
+ }
+ return ie;
+}
+
+
+
+
+template (value) PDU_BSSAP_LE ts_BSSAP_LE_BSSMAP := {
+ discriminator := '0'B,
+ spare := '0000000'B,
+ dlci := omit,
+ lengthIndicator := 0, /* overwritten by codec */
+ pdu := {
+ bssmap := -
+ }
+}
+
+template (present) PDU_BSSAP_LE tr_BSSAP_LE_BSSMAP := {
+ discriminator := '0'B,
+ spare := '0000000'B,
+ dlci := *,
+ lengthIndicator := ?,
+ pdu := {
+ bssmap := ?
+ }
+}
+
+template (value) PDU_BSSAP_LE ts_BSSAP_LE_DTAP(octetstring dtap, template (value) OCT1 dlci) := {
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := dlci,
+ lengthIndicator := 0, /* overwritten by codec */
+ pdu := {
+ dtap := dtap
+ }
+}
+
+template (present) PDU_BSSAP_LE tr_BSSAP_LE_DTAP := {
+ discriminator := '1'B,
+ spare := '0000000'B,
+ dlci := *,
+ lengthIndicator := ?,
+ pdu := {
+ dtap := ?
+ }
+}
+
+function ts_BSSMAP_LE_IMSI(template (omit) hexstring imsi) return template (omit) BSSMAP_LE_IE_IMSI {
+ if (istemplatekind(imsi, "omit")) {
+ return omit;
+ }
+ template (value) BSSMAP_LE_IE_IMSI res := {
+ iei := BSSMAP_LE_IEI_IMSI,
+ len := 0,
+ imsi := ts_MI_IMSI(valueof(imsi))
+ };
+ return res;
+}
+function tr_BSSMAP_LE_IMSI(template hexstring imsi) return template BSSMAP_LE_IE_IMSI {
+ if (istemplatekind(imsi, "omit")) {
+ return omit;
+ }
+ template BSSMAP_LE_IE_IMSI res := {
+ iei := BSSMAP_LE_IEI_IMSI,
+ len := ?,
+ imsi := tr_MI_IMSI(imsi)
+ };
+ return res;
+}
+
+template (value) BSSMAP_LE_IE_LocationType ts_BSSMAP_LE_LocType(template (value) BSSMAP_LE_LocInfo li,
+ template (omit) BSSMAP_LE_PosMethod pm := omit) := {
+ iei := BSSMAP_LE_IEI_LOCATION_TYPE,
+ len := 0,
+ loc_info := li,
+ pos_method := pm
+}
+template (present) BSSMAP_LE_IE_LocationType tr_BSSMAP_LE_LocType(template (present) BSSMAP_LE_LocInfo li,
+ template BSSMAP_LE_PosMethod pm := omit) := {
+ iei := BSSMAP_LE_IEI_LOCATION_TYPE,
+ len := ?,
+ loc_info := li,
+ pos_method := pm
+}
+
+
+/* Section 9.1 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LocInfo loc_info := BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC,
+ template (value) BSSMAP_IE_CellIdentifier cell_id,
+ template (omit) hexstring imsi,
+ template (omit) octetstring bsslap_apdu := omit)
+
+modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_req := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_REQ,
+ location_type := ts_BSSMAP_LE_LocType(loc_info),
+ cell_id := cell_id,
+ cm3 := omit,
+ lcs_client_type := omit,
+ chosen_channel := omit,
+ lcs_priority := omit,
+ lcs_qos := omit,
+ req_gps_ass_d := omit,
+ bsslap_apdu := ts_BSSMAP_LE_APDU(BSSMAP_LE_PROT_BSSLAP, bsslap_apdu),
+ lcs_capability := omit,
+ packet_meas_rep := omit,
+ meas_cell_id_list := omit,
+ imsi := ts_BSSMAP_LE_IMSI(imsi),
+ imei := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LocInfo loc_info := BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC,
+ template (present) BSSMAP_IE_CellIdentifier cell_id,
+ template hexstring imsi)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_req := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_REQ,
+ location_type := tr_BSSMAP_LE_LocType(loc_info),
+ cell_id := cell_id,
+ cm3 := *,
+ lcs_client_type := *,
+ chosen_channel := *,
+ lcs_priority := *,
+ lcs_qos := *,
+ req_gps_ass_d := *,
+ bsslap_apdu := *,
+ lcs_capability := *,
+ packet_meas_rep := *,
+ meas_cell_id_list := *,
+ imsi := tr_BSSMAP_LE_IMSI(imsi),
+ imei := *
+ }
+ }
+ }
+}
+
+
+/* Section 9.2 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocResp(template (omit) octetstring geo_loc,
+ template (omit) BSSMAP_LE_LcsCause cause)
+
+modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_resp := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_RESP,
+ geographic_loc := ts_BSSMAP_LE_GeographicLoc(geo_loc),
+ pos_data := omit,
+ deciph_keys := omit,
+ lcs_cause := ts_BSSMAP_LE_LcsCause(cause),
+ velocity_data := omit,
+ ganss_pos_data := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocResp(template octetstring geo_loc,
+ template BSSMAP_LE_LcsCause cause)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_resp := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_RESP,
+ geographic_loc := tr_BSSMAP_LE_GeographicLoc(geo_loc),
+ pos_data := *,
+ deciph_keys := *,
+ lcs_cause := tr_BSSMAP_LE_LcsCause(cause),
+ velocity_data := *,
+ ganss_pos_data := *
+ }
+ }
+ }
+}
+
+
+/* Section 9.8 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_ProtocolId prot_id, octetstring data,
+ template (omit) BSSMAP_LE_IE_Segmentation segm := omit)
+modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ co_info := {
+ msg_type := BSSMAP_LE_CONN_ORIENTED_INFO,
+ bsslap_apdu := {
+ iei := BSSMAP_LE_IEI_APDU,
+ len := 0,
+ protocol_id := prot_id,
+ spare := '0'B,
+ data := data
+ },
+ segmentation := segm
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_ConnInfo(template (present) BSSMAP_LE_ProtocolId prot_id,
+ template (present) octetstring data,
+ template BSSMAP_LE_IE_Segmentation segm := omit)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ co_info := {
+ msg_type := BSSMAP_LE_CONN_ORIENTED_INFO,
+ bsslap_apdu := {
+ iei := BSSMAP_LE_IEI_APDU,
+ len := ?,
+ protocol_id := prot_id,
+ spare := '0'B,
+ data := data
+ },
+ segmentation := segm
+ }
+ }
+ }
+}
+
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LcsCause cause)
+modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_abort := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_ABORT,
+ lcs_cause := ts_BSSMAP_LE_LcsCause(cause)
+ }
+ }
+ }
+}
+
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerfLocAbort(template BSSMAP_LE_LcsCause cause)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_abort := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_ABORT,
+ lcs_cause := tr_BSSMAP_LE_LcsCause(cause)
+ }
+ }
+ }
+}
+
+/* Section 9.10 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_Reset(myBSSMAP_Cause cause) modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ reset := {
+ msg_type := BSSMAP_LE_RESET,
+ cause := ts_BSSMAP_IE_Cause(enum2int(cause))
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_Reset modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ reset := {
+ msg_type := BSSMAP_LE_RESET,
+ cause := ?
+ }
+ }
+ }
+}
+
+/* Section 9.11 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_ResetAck modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ reset_ack := {
+ msg_type := BSSMAP_LE_RESET_ACK
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_ResetAck modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ reset_ack := {
+ msg_type := BSSMAP_LE_RESET_ACK
+ }
+ }
+ }
+}
+
+function ts_BSSMAP_LE_APDU(BSSMAP_LE_ProtocolId prot_id, template (omit) octetstring data)
+return template (omit) BSSMAP_LE_IE_APDU {
+ var BSSMAP_LE_IE_APDU ie := {
+ iei := BSSMAP_LE_IEI_APDU,
+ len := 0, // overwritten
+ protocol_id := prot_id,
+ spare := '0'B
+ }
+ if (istemplatekind(data, "omit")) {
+ return omit;
+ }
+ ie.data := valueof(data);
+ return ie;
+}
+
+function tr_BSSMAP_LE_APDU(template BSSMAP_LE_ProtocolId prot_id, template octetstring data)
+return template BSSMAP_LE_IE_APDU {
+ var template BSSMAP_LE_IE_APDU ie := {
+ iei := BSSMAP_LE_IEI_APDU,
+ len := ?,
+ protocol_id := prot_id,
+ spare := '0'B
+ }
+ if (istemplatekind(data, "omit")) {
+ return omit;
+ } else if (istemplatekind(data, "*")) {
+ return *;
+ }
+ ie.data := data;
+ return ie;
+}
+
+
+/* Section 9.12 */
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_PerformLocInfo(BSSMAP_IE_CellIdentifier cell_id,
+ BSSMAP_LE_ProtocolId prot_id,
+ template (omit) octetstring data)
+modifies ts_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_info := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_INFO,
+ cell_id := cell_id,
+ bsslap_apdu := ts_BSSMAP_LE_APDU(prot_id, data)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP_LE tr_BSSMAP_LE_PerformLocInfo(template (present) BSSMAP_IE_CellIdentifier cell_id,
+ template BSSMAP_LE_ProtocolId prot_id,
+ template octetstring data)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ perf_loc_info := {
+ msg_type := BSSMAP_LE_PERFORM_LOC_INFO,
+ cell_id := cell_id,
+ bsslap_apdu := tr_BSSMAP_LE_APDU(prot_id, data)
+ }
+ }
+ }
+}
+
+/* return Layer3 octetstring inside BSSAP-LE PDU */
+function f_bssap_le_extract_l3(PDU_BSSAP_LE bssap) return template octetstring {
+ if (ischosen(bssap.pdu.bssmap)) {
+ return omit;
+ } else {
+ return bssap.pdu.dtap;
+ }
+}
+
+
+template PDU_BSSAP_LE tr_BSSMAP_LE_Paging(template hexstring imsi_digits := ?,
+ template OCT4 tmsi := *,
+ template BSSMAP_IE_ChannelNeeded chneed := *)
+modifies tr_BSSAP_LE_BSSMAP := {
+ pdu := {
+ bssmap := {
+ paging := {
+ messageType := '52'O,
+ iMSI := tr_BSSMAP_Imsi(imsi_digits),
+ tMSI := tr_BSSMAP_IE_TMSI(tmsi) ifpresent,
+ cellIdentifierList := ?,
+ channelNeeded := chneed,
+ eMLPP_Priority := omit,
+ pagingInformation := omit /* only VGCS/VBS flag */
+ }
+ }
+ }
+}
+
+
+
+
+} with { encode "RAW" };
diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index 776e8be8..a93fb025 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -2,7 +2,7 @@ module BSSMAP_Templates {
/* BSSMAP Templates, building on top of BSSAP_Types from Ericsson.
*
- * (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2017-2023 by Harald Welte <laforge@gnumonks.org>
* contributions by sysmocom - s.f.m.c. GmbH
* All rights reserved.
*
@@ -14,6 +14,8 @@ module BSSMAP_Templates {
import from General_Types all;
import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
import from GSM_Types all;
import from BSSAP_Types all;
@@ -21,7 +23,16 @@ type integer BssmapCause;
type integer SpeechVersion;
type integer Channel;
type integer ChannelMode;
-type octetstring oldToNewBSSIEs;
+//type octetstring BSSMAP_oldToNewBSSIEs;
+
+// Old BSS to New BSS Information - 48.008 subclause 3.2.2.58
+type record BSSMAP_oldToNewBSSIEs
+{
+ BSSAMAP_IE_LastUsedEUTRANPLMNId LastUsedEUTRANPLMNId optional
+ /* TODO: add other FIELDS here from specs */
+}
+external function enc_BSSMAP_oldToNewBSSIEs(in BSSMAP_oldToNewBSSIEs val) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
/* 48.008 3.2.2.5 - this actually belongs to BSSAP_Types.ttcn */
type enumerated myBSSMAP_Cause {
@@ -101,6 +112,55 @@ type enumerated myBSSMAP_Cause {
GSM0808_CAUSE_DTM_HO_TIMER_EXPIRY ('1100010'B)
} with { variant "FIELDLENGTH(7)" };
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Transparent: Data Rate */
+const OCT1 GSM0808_DATA_RATE_TRANSP_32k0 := ('3a'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_28k8 := ('39'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_14k4 := ('18'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_9k6 := ('10'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_4k8 := ('11'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_2k4 := ('12'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_1k2 := ('13'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_600 := ('14'O);
+const OCT1 GSM0808_DATA_RATE_TRANSP_1200_75 := ('15'O);
+
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Non-Transparent: Radio Interface Data Rate (preferred) */
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_12000_6000 := ('00'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_43k5 := ('34'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_29k0 := ('31'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_14k5 := ('14'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_12k0 := ('10'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_6k0 := ('11'O);
+
+/* 3GPP TS 48.008 3.2.2.11 Channel Type
+ * Non-Transparent: Allowed Radio Interface Data Rate (all possible allowed) */
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_43k5 := ('40'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_32k0 := ('20'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_29k0 := ('10'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_14k5 := ('08'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_12k0 := ('02'O);
+const OCT1 GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_6k0 := ('01'O);
+
+type enumerated BSSMAP_LcsCause {
+ BSSMAP_LCS_CAUSE_UNSPECIFIED ('00000000'B),
+ BSSMAP_LCS_CAUSE_SYSTEM_FAILURE ('00000001'B),
+ BSSMAP_LCS_CAUSE_PROTOCOL_ERROR ('00000010'B),
+ BSSMAP_LCS_CAUSE_DATA_MISSING_IN_REQ ('00000011'B),
+ BSSMAP_LCS_CAUSE_UNEXP_DATA_IN_REQ ('00000100'B),
+ BSSMAP_LCS_CAUSE_POS_METH_FAILURE ('00000101'B),
+ BSSMAP_LCS_CAUSE_TGT_MS_UNREACHABLE ('00000110'B),
+ BSSMAP_LCS_CAUSE_REQUEST_ABORTED ('00000111'B),
+ BSSMAP_LCS_CAUSE_FACILITY_NOTSUPP ('00001000'B),
+ BSSMAP_LCS_CAUSE_INTER_BSC_HO ('00001001'B),
+ BSSMAP_LCS_CAUSE_INTRA_BSC_HO ('00001010'B),
+ BSSMAP_LCS_CAUSE_CONGESTION ('00001011'B),
+ BSSMAP_LCS_CAUSE_INTER_NSE_CHG ('00001100'B),
+ BSSMAP_LCS_CAUSE_RA_UPDAT ('00001101'B),
+ BSSMAP_LCS_CAUSE_PTMSI_REALLOC ('00001110'B),
+ BSSMAP_LCS_CAUSE_GPRS_SUSPENSION ('00001111'B)
+} with { variant "FIELDLENGTH(8)" };
+
template PDU_BSSAP ts_BSSAP_BSSMAP := {
discriminator := '0'B,
spare := '0000000'B,
@@ -148,6 +208,22 @@ template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
extensionCauseValue := '0'B,
spare1 := omit
}
+template BSSMAP_IE_Cause tr_BSSMAP_IE_Cause(template (present) myBSSMAP_Cause val) := {
+ elementIdentifier := '04'O,
+ lengthIndicator := ?,
+ causeValue := f_tr_causeValue(val),
+ extensionCauseValue := ?,
+ spare1 := *
+}
+private function f_tr_causeValue(template (present) myBSSMAP_Cause val)
+return template (present) BIT7 {
+ if (istemplatekind(val, "?")) {
+ return ?;
+ } else {
+ var integer int_val := enum2int(valueof(val));
+ return int2bit(valueof(int_val), 7);
+ }
+}
template (value) BSSMAP_IE_SpeechVersion ts_BSSMAP_IE_SpeechVersion(SpeechVersion val) := {
elementIdentifier := '40'O,
@@ -161,17 +237,54 @@ template (value) BSSMAP_IE_CurrentChannelType1 ts_BSSMAP_IE_CurrentChannelType1(
channelMode := int2bit(cm, 4)
}
-template (value) BSSMAP_IE_OldToNewBSSInfo ts_BSSMAP_IE_OldToNewBSSInfo(oldToNewBSSIEs val) := {
+template (value) BSSMAP_oldToNewBSSIEs ts_BSSMAP_oldToNewBSSIEs(template (omit) BSSAMAP_IE_LastUsedEUTRANPLMNId last_used_eutran_plmn) := {
+ LastUsedEUTRANPLMNId := last_used_eutran_plmn
+}
+function f_ts_BSSMAP_oldToNewBSSIEs(template (omit) BSSAMAP_IE_LastUsedEUTRANPLMNId last_used_eutran_plmn)
+ return template (omit) BSSMAP_oldToNewBSSIEs {
+ if (istemplatekind(last_used_eutran_plmn, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSMAP_oldToNewBSSIEs(last_used_eutran_plmn);
+ }
+}
+template (value) BSSMAP_IE_OldToNewBSSInfo ts_BSSMAP_IE_OldToNewBSSInfo(template (value) BSSMAP_oldToNewBSSIEs val) := {
elementIdentifier := '3A'O,
lengthIndicator := 0, /* overwritten by codec */
- oldToNewBSSIEs := val
+ oldToNewBSSIEs := enc_BSSMAP_oldToNewBSSIEs(valueof(val))
+}
+function f_ts_BSSMAP_IE_OldToNewBSSInfo(template (omit) BSSMAP_oldToNewBSSIEs val)
+ return template (omit) BSSMAP_IE_OldToNewBSSInfo {
+ if (istemplatekind(val, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSMAP_IE_OldToNewBSSInfo(val);
+ }
+}
+
+template BSSMAP_IE_OldToNewBSSInfo tr_BSSMAP_IE_OldToNewBSSInfo(template (value) BSSMAP_oldToNewBSSIEs val) := {
+ elementIdentifier := '3A'O,
+ lengthIndicator := ?, /* overwritten by codec */
+ oldToNewBSSIEs := enc_BSSMAP_oldToNewBSSIEs(valueof(val))
+}
+function f_tr_BSSMAP_IE_OldToNewBSSInfo(template BSSMAP_oldToNewBSSIEs val := *)
+ return template BSSMAP_IE_OldToNewBSSInfo {
+ if (istemplatekind(val, "*")) {
+ return *;
+ } else if (istemplatekind(val, "?")) {
+ return ?;
+ } else if (istemplatekind(val, "omit")) {
+ return omit;
+ } else {
+ return tr_BSSMAP_IE_OldToNewBSSInfo(val);
+ }
}
-template BSSMAP_IE_Osmo_OsmuxSupport tr_BSSMAP_IE_Osmo_OsmuxSupport := {
+template (value) BSSMAP_IE_Osmo_OsmuxSupport tr_BSSMAP_IE_Osmo_OsmuxSupport := {
elementIdentifier := 'F0'O
}
-private function f_enc_osmux_support(boolean osmux_enabled) return template BSSMAP_IE_Osmo_OsmuxSupport {
+private function f_enc_osmux_support(boolean osmux_enabled) return template (omit) BSSMAP_IE_Osmo_OsmuxSupport {
if (osmux_enabled) {
return tr_BSSMAP_IE_Osmo_OsmuxSupport;
}
@@ -236,8 +349,17 @@ template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
cellIdentification := ?
}
+template BSSMAP_IE_CellIdentifier tr_BSSMAP_IE_CellID := {
+ elementIdentifier := '05'O,
+ lengthIndicator := ?,
+ cellIdentifierDiscriminator := ?,
+ spare1_4 := '0000'B,
+ cellIdentification := ?
+}
+
type uint16_t BssmapLAC;
type uint16_t BssmapCI;
+type uint16_t BssmapSAC;
template BSSMAP_IE_CellIdentifier ts_CellId_CGI(hexstring mcc, hexstring mnc, BssmapLAC lac, BssmapCI ci)
modifies ts_BSSMAP_IE_CellID := {
@@ -246,7 +368,16 @@ modifies ts_BSSMAP_IE_CellID := {
}
}
-template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
+template (present) BSSMAP_IE_CellIdentifier tr_CellId_CGI(template (present) OCT3 mcc_mnc,
+ template (present) BssmapLAC lac,
+ template (present) BssmapCI ci)
+modifies tr_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_CGI := tr_BSSMAP_CI_CGI(mcc_mnc, lac, ci)
+ }
+}
+
+template (value) BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
modifies ts_BSSMAP_IE_CellID := {
cellIdentification := {
cI_LAC_CI := {
@@ -256,6 +387,17 @@ modifies ts_BSSMAP_IE_CellID := {
}
}
+template (present) BSSMAP_IE_CellIdentifier tr_CellID_LAC_CI(template (present) BssmapLAC lac,
+ template (present) BssmapCI ci)
+modifies tr_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_LAC_CI := {
+ lac := f_tr_LAC(lac),
+ ci := f_tr_CI(ci)
+ }
+ }
+}
+
template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
modifies ts_BSSMAP_IE_CellID := {
cellIdentification := {
@@ -263,6 +405,13 @@ modifies ts_BSSMAP_IE_CellID := {
}
}
+template (present) BSSMAP_IE_CellIdentifier tr_CellId_CI(template (present) BssmapCI ci)
+modifies tr_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_CI := f_tr_CI(ci)
+ }
+}
+
template BSSMAP_IE_CellIdentifier ts_CellId_none
modifies ts_BSSMAP_IE_CellID := {
cellIdentification := {
@@ -270,14 +419,72 @@ modifies ts_BSSMAP_IE_CellID := {
}
}
+template BSSMAP_IE_CellIdentifier tr_CellId_none
+modifies tr_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_noCell := ''O
+ }
+}
+
+template (value) BSSMAP_IE_CellIdentifier ts_CellID_SAI(OCT3 mcc_mnc, BssmapLAC lac, BssmapSAC sac)
+modifies ts_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_SAI := {
+ mcc_mnc := mcc_mnc,
+ lac := int2oct(lac, 2),
+ sac := int2oct(sac, 2)
+ }
+ }
+}
-template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
+template (present) BSSMAP_IE_CellIdentifier tr_CellID_SAI(template (present) OCT3 mcc_mnc,
+ template (present) BssmapLAC lac,
+ template (present) BssmapSAC sac)
+modifies tr_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_SAI := {
+ mcc_mnc := mcc_mnc,
+ lac := f_tr_LAC(lac),
+ sac := f_tr_SAC(sac)
+ }
+ }
+}
+
+private function f_tr_LAC(template (present) BssmapLAC lac)
+return template (present) OCT2 {
+ if (istemplatekind(lac, "?")) {
+ return ?;
+ } else {
+ return int2oct(valueof(lac), 2);
+ }
+}
+
+private function f_tr_SAC(template (present) BssmapSAC sac)
+return template (present) OCT2 {
+ if (istemplatekind(sac, "?")) {
+ return ?;
+ } else {
+ return int2oct(valueof(sac), 2);
+ }
+}
+
+private function f_tr_CI(template (present) BssmapCI ci)
+return template (present) OCT2 {
+ if (istemplatekind(ci, "?")) {
+ return ?;
+ } else {
+ return int2oct(valueof(ci), 2);
+ }
+}
+
+
+template (value) BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(template (value) octetstring l3info) := {
elementIdentifier := '17'O,
lengthIndicator := 0,
layer3info := l3info
}
-template BSSMAP_IE_Layer3Information tr_BSSMAP_IE_L3Info(template octetstring l3info) := {
+template (present) BSSMAP_IE_Layer3Information tr_BSSMAP_IE_L3Info(template (present) octetstring l3info) := {
elementIdentifier := '17'O,
lengthIndicator := ?,
layer3info := l3info
@@ -305,7 +512,8 @@ modifies ts_BSSAP_BSSMAP := {
}
template PDU_BSSAP tr_BSSMAP_ComplL3(template octetstring l3_info := ?,
- template BSSMAP_IE_CellIdentifier cell_id := ?)
+ template BSSMAP_IE_CellIdentifier cell_id := ?,
+ template BSSMAP_IE_SpeechCodecList codec_list := *)
modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
@@ -316,7 +524,7 @@ modifies tr_BSSAP_BSSMAP := {
chosenChannel := *,
lSAIdentifier := *,
aPDU := *,
- codecList := *,
+ codecList := codec_list,
redirectAttemptFlag := *,
sendSequenceNumber := *,
iMSI := *
@@ -358,6 +566,17 @@ template (value) BSSMAP_IE_ChannelType ts_BSSMAP_IE_ChannelType := {
speechId_DataIndicator := Spdi_TCHF_FR
}
+template (present) BSSMAP_IE_ChannelType tr_BSSMAP_IE_ChannelType(template (present) BIT4 speech_data_ind,
+ template (present) OCT1 chan_rate_type,
+ template (present) octetstring speech_id) := {
+ elementIdentifier := '0B'O,
+ lengthIndicator := ?,
+ speechOrDataIndicator := speech_data_ind,
+ spare1_4 := '0000'B,
+ channelRateAndType := chan_rate_type,
+ speechId_DataIndicator := speech_id
+}
+
template (value) BSSMAP_IE_ChannelType ts_BSSMAP_IE_ChannelTypeCTM modifies ts_BSSMAP_IE_ChannelType := {
speechOrDataIndicator := '0100'B /* speech + CTM */
}
@@ -394,7 +613,15 @@ template BSSMAP_IE_EncryptionInformation tr_BSSMAP_IE_EncrInfo(template OCT8 kc
key := kc
}
+template BSSMAP_IE_ChosenEncryptionAlgorithm ts_BSSMAP_IE_ChosenEncryptionAlgorithm(OCT1 algorithmIdentifier) := {
+ elementIdentifier := '2C'O,
+ algorithmIdentifier := algorithmIdentifier
+}
+template BSSMAP_IE_ChosenEncryptionAlgorithm tr_BSSMAP_IE_ChosenEncryptionAlgorithm(template OCT1 algorithmIdentifier := ?) := {
+ elementIdentifier := '2C'O,
+ algorithmIdentifier := algorithmIdentifier
+}
template (value) BSSMAP_IE_CircuitIdentityCode ts_BSSMAP_IE_CIC(uint11_t span, uint5_t ts) := {
elementIdentifier := '01'O, /* overwritten */
@@ -420,6 +647,17 @@ template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA4(OCT
template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_BSSMAP_IE_AoIP_TLA6(OCT16 ip, uint16_t pt) :=
ts_BSSMAP_IE_AoIP_TLA({ipv6:=ip}, pt, 18);
+function f_ts_BSSMAP_IE_AoIP_TLA(charstring addr, uint16_t udp_port)
+ return template (value) BSSMAP_IE_AoIP_TransportLayerAddress {
+ if (f_addr_is_ipv6(addr)) {
+ var OCT16 ip6 := f_inet6_addr(addr);
+ return ts_BSSMAP_IE_AoIP_TLA6(ip6, udp_port);
+ } else {
+ var OCT4 ip := f_inet_addr(addr);
+ return ts_BSSMAP_IE_AoIP_TLA4(ip, udp_port);
+ }
+}
+
template BSSMAP_IE_AoIP_TransportLayerAddress tr_BSSMAP_IE_AoIP_TLA(template BSSMAP_FIELD_IPAddress addr,
template uint16_t udp_port,
template integer len := ?) := {
@@ -433,6 +671,22 @@ template BSSMAP_IE_AoIP_TransportLayerAddress tr_BSSMAP_IE_AoIP_TLA4(template OC
template BSSMAP_IE_AoIP_TransportLayerAddress tr_BSSMAP_IE_AoIP_TLA6(template OCT16 ip, template uint16_t pt) :=
tr_BSSMAP_IE_AoIP_TLA({ipv6:=ip}, pt, 18);
+function f_tr_BSSMAP_IE_AoIP_TLA(charstring addr, template uint16_t udp_port)
+ return template BSSMAP_IE_AoIP_TransportLayerAddress {
+ if (f_addr_is_ipv6(addr)) {
+ var OCT16 ip6 := f_inet6_addr(addr);
+ return tr_BSSMAP_IE_AoIP_TLA6(ip6, udp_port);
+ } else {
+ var OCT4 ip := f_inet_addr(addr);
+ return tr_BSSMAP_IE_AoIP_TLA4(ip, udp_port);
+ }
+}
+
+template (present) BSSMAP_IE_KC128 tr_BSSMAP_IE_Kc128(template (present) OCT16 kc128) := {
+ elementIdentifier := '83'O,
+ kC128_Value := kc128
+}
+
template (value) BSSMAP_IE_KC128 ts_BSSMAP_IE_Kc128(OCT16 kc128) := {
elementIdentifier := '83'O,
kC128_Value := kc128
@@ -468,6 +722,19 @@ template (value) BSSMAP_FIELD_CodecElement ts_CodecAMR_H modifies ts_CodecBase :
s0_7 := '00111111'B,
s8_15 := '00000111'B /* S6 - S7 and S11 – S15 are reserved and coded with zeroes */
}
+template (value) BSSMAP_FIELD_CodecElement ts_CodecAMR_WB modifies ts_CodecBase := {
+ codecType := FR_AMR_WB,
+ s0_7 := '00000001'B
+}
+template (value) BSSMAP_FIELD_CodecElement ts_CodecCSData modifies ts_CodecBase := {
+ codecType := CodecExtension,
+ tF := '0'B, /* Spare */
+ pT := '0'B, /* CSDoTDM */
+ pI := '1'B, /* CSDoIP */
+ fI := '0'B, /* Spare */
+ extendedCodecType := 'FD'O, /* CSData */
+ s0_7 := '00000000'B /* R2, R3, Spare */
+}
template BSSMAP_IE_SpeechCodecList ts_BSSMAP_IE_CodecList(template BSSMAP_FIELD_CodecElements elem) := {
elementIdentifier := '7D'O,
lengthIndicator := 0, /* overwritten */
@@ -479,6 +746,36 @@ template BSSMAP_IE_SpeechCodec ts_BSSMAP_IE_SpeechCodec(template BSSMAP_FIELD_Co
codecElements := valueof(elem)
}
+function ts_BSSMAP_IE_CallIdentifier(template (omit) OCT4 cid) return template (omit) BSSMAP_IE_CallIdentifier {
+ if (istemplatekind(cid, "omit")) {
+ return omit;
+ } else {
+ var template (present) BSSMAP_IE_CallIdentifier ie := {
+ elementIdentifier := '7F'O,
+ callIdentifierInfo := cid
+ }
+ return ie;
+ }
+}
+function tr_BSSMAP_IE_CallIdentifier(template OCT4 cid) return template BSSMAP_IE_CallIdentifier {
+ if (istemplatekind(cid, "*")) {
+ return *;
+ } else if (istemplatekind(cid, "omit")) {
+ return omit;
+ } else {
+ var template BSSMAP_IE_CallIdentifier ie := {
+ elementIdentifier := '7F'O,
+ callIdentifierInfo := cid
+ }
+ return ie;
+ }
+}
+
+
+template (present) BSSMAP_IE_Osmo_OsmuxCID tr_OsmuxCID(template (present) INT1 cid := ?) := {
+ elementIdentifier := 'F1'O,
+ osmuxCID := cid
+}
template (value) BSSMAP_IE_Osmo_OsmuxCID ts_OsmuxCID(INT1 cid) := {
elementIdentifier := 'F1'O,
osmuxCID := cid
@@ -728,7 +1025,8 @@ template PDU_BSSAP tr_BSSMAP_ClearRequest modifies tr_BSSAP_BSSMAP := {
}
template PDU_BSSAP ts_BSSMAP_HandoverRequired(BssmapCause cause,
- template BSSMAP_FIELD_CellIdentificationList cid_list)
+ template BSSMAP_FIELD_CellIdentificationList cid_list,
+ template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit)
modifies ts_BSSAP_BSSMAP := {
pdu := {
bssmap := {
@@ -741,7 +1039,7 @@ modifies ts_BSSAP_BSSMAP := {
currentChannelType1 := omit,
speechVersion := omit,
queueingIndicator := omit,
- oldToNewBSSInfo := omit,
+ oldToNewBSSInfo := f_ts_BSSMAP_IE_OldToNewBSSInfo(oldToNewBSSIEs),
sourceToTargetRNCTransparentInfo := omit,
sourceToTargetRNCTransparentInfoCDMA := omit,
gERANClassmark := omit,
@@ -754,11 +1052,17 @@ modifies ts_BSSAP_BSSMAP := {
}
-template PDU_BSSAP tr_BSSMAP_HandoverRequired modifies tr_BSSAP_BSSMAP := {
+template PDU_BSSAP tr_BSSMAP_HandoverRequired(template BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := *,
+ template (present) BSSMAP_FIELD_CellIdentificationList cid_list := ?)
+modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
handoverRequired := {
- messageType := '11'O
+ messageType := '11'O,
+ cellIdentifierList := {
+ cellIdentificationList := cid_list
+ },
+ oldToNewBSSInfo := f_tr_BSSMAP_IE_OldToNewBSSInfo(oldToNewBSSIEs)
}
}
}
@@ -834,11 +1138,20 @@ template PDU_BSSAP tr_BSSMAP_HandoverFailure modifies tr_BSSAP_BSSMAP := {
}
}
-template PDU_BSSAP tr_BSSMAP_HandoverRequest modifies tr_BSSAP_BSSMAP := {
+template PDU_BSSAP tr_BSSMAP_HandoverRequest(template BSSMAP_IE_EncryptionInformation encryptionInformation := *,
+ template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := *,
+ template BSSMAP_IE_KC128 kC128 := *,
+ template BSSMAP_IE_SpeechCodecList codecList := *
+ )
+ modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
handoverRequest := {
- messageType := '10'O
+ messageType := '10'O,
+ encryptionInformation := encryptionInformation,
+ chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
+ codecList := codecList,
+ kC128 := kC128
}
}
}
@@ -848,7 +1161,12 @@ template PDU_BSSAP ts_BSSMAP_HandoverRequest(
template BSSMAP_IE_CircuitIdentityCode cic := omit,
template BSSMAP_IE_AoIP_TransportLayerAddress aoip_tla := omit,
template BSSMAP_IE_CellIdentifier cell_id_target := ts_CellID_LAC_CI(1, 0),
- template BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1)
+ template BSSMAP_IE_CellIdentifier cell_id_source := ts_CellID_LAC_CI(1, 1),
+ template (omit) BSSMAP_oldToNewBSSIEs oldToNewBSSIEs := omit,
+ template BSSMAP_IE_EncryptionInformation encryptionInformation := ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O),
+ template (omit) BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit,
+ template (omit) BSSMAP_IE_KC128 kC128 := omit,
+ template (omit) BSSMAP_IE_SpeechCodecList codecList := omit
)
modifies ts_BSSAP_BSSMAP := {
pdu := {
@@ -856,8 +1174,7 @@ modifies ts_BSSAP_BSSMAP := {
handoverRequest := {
messageType := '10'O,
channelType := ts_BSSMAP_IE_ChannelType,
- encryptionInformation :=
- ts_BSSMAP_IE_EncrInfo('0000000000000000'O,'01'O),
+ encryptionInformation := encryptionInformation,
classmarkInformationType := {
classmarkInformationType1 := {
elementIdentifier := '1D'O,
@@ -881,8 +1198,8 @@ modifies ts_BSSAP_BSSMAP := {
groupCallReference := omit,
talkerFlag := omit,
configurationEvolutionIndication := omit,
- chosenEncryptionAlgorithm := omit,
- oldToNewBSSInfo := omit,
+ chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
+ oldToNewBSSInfo := f_ts_BSSMAP_IE_OldToNewBSSInfo(oldToNewBSSIEs),
lSAInformation := omit,
lSAAccessControlSuppression := omit,
serviceHandover := omit,
@@ -892,9 +1209,9 @@ modifies ts_BSSAP_BSSMAP := {
sNAAccessInformation := omit,
talkerPriority := omit,
aoIPTransportLayer := aoip_tla,
- codecList := omit,
+ codecList := codecList,
callIdentifier := omit,
- kC128 := omit,
+ kC128 := kC128,
globalCallReference := omit,
lCLS_Configuration := omit,
connectionStatusControl := omit
@@ -1051,6 +1368,35 @@ template BSSMAP_IE_IMSI tr_BSSMAP_Imsi(template hexstring imsi_digits) := {
digits := imsi_digits
}
+template (value) BSSAMAP_IE_LastUsedEUTRANPLMNId ts_BSSMAP_LastUsedEUTRANPLMNId(OCT3 mcc_mnc) := {
+ elementIdentifier := '95'O,
+ mcc_mnc := mcc_mnc
+}
+template BSSAMAP_IE_LastUsedEUTRANPLMNId tr_BSSMAP_LastUsedEUTRANPLMNId(template OCT3 mcc_mnc) := {
+ elementIdentifier := '95'O,
+ mcc_mnc := mcc_mnc
+}
+function f_ts_BSSMAP_LastUsedEUTRANPLMNId(template (omit) OCT3 mcc_mnc)
+ return template (omit) BSSAMAP_IE_LastUsedEUTRANPLMNId {
+ if (not istemplatekind(mcc_mnc, "omit")) {
+ return ts_BSSMAP_LastUsedEUTRANPLMNId(valueof(mcc_mnc));
+ } else {
+ return omit;
+ }
+}
+function f_tr_BSSMAP_LastUsedEUTRANPLMNId(template OCT3 mcc_mnc)
+return template BSSAMAP_IE_LastUsedEUTRANPLMNId {
+ if (istemplatekind(mcc_mnc, "*")) {
+ return *;
+ } else if (istemplatekind(mcc_mnc, "?")) {
+ return ?;
+ } else if (istemplatekind(mcc_mnc, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSMAP_LastUsedEUTRANPLMNId(valueof(mcc_mnc));
+ }
+}
+
template BSSMAP_FIELD_CellIdentificationList ts_BSSMAP_CIL_noCell := {
cIl_noCell := ''O
}
@@ -1105,7 +1451,7 @@ template BSSMAP_FIELD_CellIdentificationList tr_BSSMAP_CIL_LAC(template RecordOf
}
-private function f_enc_mcc_mnc(GsmMcc mcc, GsmMnc mnc) return OCT3 {
+function f_enc_mcc_mnc(GsmMcc mcc, GsmMnc mnc) return OCT3 {
if (lengthof(mnc) == 2) {
return hex2oct(mcc[1] & mcc[0] & 'F'H & mcc[2] & mnc[1] & mnc[0]);
} else {
@@ -1113,12 +1459,29 @@ private function f_enc_mcc_mnc(GsmMcc mcc, GsmMnc mnc) return OCT3 {
}
}
+function f_dec_mcc_mnc(in OCT3 mcc_mnc, out GsmMcc mcc, out GsmMnc mnc) {
+ var hexstring hs := oct2hex(mcc_mnc);
+ mcc := hs[1] & hs[0] & hs[3];
+ mnc := hs[5] & hs[4];
+ if (hs[2] == 'F'H) {
+ mnc := mnc & hs[2];
+ }
+}
+
template (value) BSSMAP_FIELD_CellIdentification_CGI ts_BSSMAP_CI_CGI(GsmMcc mcc, GsmMnc mnc, GsmLac lac, GsmCellId ci) := {
mcc_mnc := f_enc_mcc_mnc(mcc, mnc),
lac := int2oct(lac, 2),
ci := int2oct(ci, 2)
}
+template (present) BSSMAP_FIELD_CellIdentification_CGI tr_BSSMAP_CI_CGI(template (present) OCT3 mcc_mnc,
+ template (present) GsmLac lac,
+ template (present) GsmCellId ci) := {
+ mcc_mnc := mcc_mnc,
+ lac := f_tr_LAC(lac),
+ ci := f_tr_CI(ci)
+}
+
template (value) BSSMAP_FIELD_CellIdentification_LAC_CI ts_BSSMAP_CI_LAC_CI(GsmLac lac, GsmCellId ci) := {
lac := int2oct(lac, 2),
ci := int2oct(ci, 2)
@@ -1242,21 +1605,25 @@ modifies ts_BSSAP_BSSMAP := {
}
}
-template PDU_BSSAP tr_BSSMAP_CipherModeCmd(template OCT1 alg, template OCT8 key)
+template PDU_BSSAP tr_BSSMAP_CipherModeCmd2(template BSSMAP_IE_EncryptionInformation encryptionInformation := *,
+ template BSSMAP_IE_KC128 kC128 := *)
modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
cipherModeCommand := {
messageType := '53'O,
layer3HeaderInfo := *,
- encryptionInformation := tr_BSSMAP_IE_EncrInfo(key, alg),
+ encryptionInformation := encryptionInformation,
cipherResponseMode := *,
- kC128 := *
+ kC128 := kC128
}
}
}
}
+template PDU_BSSAP tr_BSSMAP_CipherModeCmd(template OCT1 alg, template OCT8 key, template BSSMAP_IE_KC128 kC128 := omit)
+ := tr_BSSMAP_CipherModeCmd2(tr_BSSMAP_IE_EncrInfo(key, alg), kC128);
+
template PDU_BSSAP ts_BSSMAP_CipherModeCompl(OCT1 alg)
modifies ts_BSSAP_BSSMAP := {
pdu := {
@@ -1352,6 +1719,13 @@ template BSSMAP_IE_ClassmarkInformationType2 ts_CM2_default := {
}
}
+
+template BSSMAP_IE_ClassmarkInformationType3 ts_CM3_default := {
+ elementIdentifier := '13'O,
+ lengthIndicator := 0, /* overwritten */
+ classmark3ValuePart := '01'O /* A5/4 supported */
+}
+
template PDU_BSSAP ts_BSSMAP_ClassmarkUpd(template BSSMAP_IE_ClassmarkInformationType2 cm2 := ts_CM2_default,
template BSSMAP_IE_ClassmarkInformationType3 cm3 := omit)
modifies ts_BSSAP_BSSMAP := {
@@ -1394,6 +1768,18 @@ modifies ts_BSSAP_BSSMAP := {
}
}
+template PDU_BSSAP tr_BSSMAP_ClassmarkRequest
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ classmarkRequest := {
+ messageType := '58'O,
+ talkerPriority := *
+ }
+ }
+ }
+}
+
/* return Layer3 octetstring inside BSSAP PDU */
function f_bssap_extract_l3(PDU_BSSAP bssap) return template octetstring {
if (ischosen(bssap.pdu.bssmap)) {
@@ -1599,32 +1985,905 @@ modifies tr_BSSAP_BSSMAP := {
}
}
-template PDU_BSSAP ts_BSSMAP_CommonId(hexstring imsi_digits)
+template PDU_BSSAP ts_BSSMAP_CommonId(hexstring imsi_digits,
+ template (omit) OCT3 last_eutran_plmn := omit)
modifies ts_BSSAP_BSSMAP := {
pdu := {
bssmap := {
commonID := {
messageType := '2F'O,
iMSI := ts_BSSMAP_Imsi(imsi_digits),
- sNAAccessInformation := omit
+ sNAAccessInformation := omit,
+ selectedPLMNId := omit,
+ lastUsedEUTRANPLMNId := f_ts_BSSMAP_LastUsedEUTRANPLMNId(last_eutran_plmn)
}
}
}
}
-template PDU_BSSAP tr_BSSMAP_CommonId(template hexstring imsi_digits)
+template PDU_BSSAP tr_BSSMAP_CommonId(template hexstring imsi_digits,
+ template BSSAMAP_IE_LastUsedEUTRANPLMNId lastUsedEUTRANPLMNId := *)
modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
commonID := {
messageType := '2F'O,
iMSI := tr_BSSMAP_Imsi(imsi_digits),
- sNAAccessInformation := *
+ sNAAccessInformation := *,
+ selectedPLMNId := *,
+ lastUsedEUTRANPLMNId := lastUsedEUTRANPLMNId
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_SAPInReject(template (present) GsmSapi sapi := ?,
+ template BSSMAP_IE_Cause cause := ?)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ sAPInReject := {
+ messageType := '25'O,
+ dLCI := {
+ elementIdentifier := '18'O,
+ sapiValue := f_tr_SAPI(sapi),
+ spare := ?,
+ c1 := ?, c2 := ?
+ },
+ cause := cause
+ }
+ }
+ }
+}
+
+private function f_tr_SAPI(template (present) GsmSapi sapi)
+return template (present) BIT3 {
+ if (istemplatekind(sapi, "?")) {
+ return ?;
+ } else {
+ return int2bit(valueof(sapi), 3);
+ }
+}
+
+template (value) BSSMAP_IE_LocationType ts_BSSMAP_IE_LocationType
+:= {
+ elementIdentifier := '44'O,
+ lengthIndicator := 1,
+ locationInformation := '00'O,
+ positioningMethod := omit
+}
+
+template (value) BSSMAP_IE_LCSClientType
+ts_BSSMAP_IE_LCSClientType(template (value) BIT4 category := '0010'B,
+ template (value) BIT4 subtype := '0000'B) := {
+ elementIdentifier := '48'O,
+ lengthIndicator := 0, /* overwritten */
+ subtype := subtype,
+ category := category
+}
+
+template (value) BSSMAP_IE_LCSPriority
+ts_BSSMAP_IE_LCSPriority(template (value) OCT1 priority := '00'O) := {
+ elementIdentifier := '43'O,
+ lengthIndicator := 0, /* overwritten */
+ priority := priority
+}
+
+template (value) BSSMAP_IE_LCSQOS
+ts_BSSMAP_IE_LCSQOS(template (value) BIT1 vCI := '0'B,
+ template (value) BIT1 vEL := '0'B,
+ template (value) BIT1 hAI := '1'B,
+ template (value) BIT7 hAV := '0010010'B,
+ template (value) BIT1 vAI := '0'B,
+ template (value) BIT7 vAV := '0000000'B) := {
+ elementIdentifier := '3E'O,
+ lengthIndicator := 0, /* overwritten */
+ vCI := vCI, /* Vertical Coordinate Indicator: VC requested ('1'B) or not ('0'B) */
+ vEL := vEL, /* report velocity if available (1) or not(0) */
+ spare_1_6 := '000000'B,
+ horizontalAccuracy := hAV, /* Accuracy Horizontal (HA) */
+ hAI := hAI, /* Horizontal Accuracy Indicator HA is specified (1) or not (0) */
+ verticalAccuracy := vAV, /* Accuracy Vertical (VA) */
+ vAI := vAI, /* Vertical Accuracy Indicator VA is specified (1) or not (0) */
+ spare_2_6 := '000000'B,
+ rTC := '00'B /* Response Time is not specified */
+}
+
+
+/* 3.2.2.55 */
+template (value) BSSMAP_IE_GroupCallReference
+ts_BSSMAP_IE_GroupCallRef(template (value) GroupCallRef group_call_ref) :={
+ elementIdentifier := '37'O,
+ lengthIndicator := 0, // overwritten
+ descrGroupbroadcastCallRef := group_call_ref
+}
+template (present) BSSMAP_IE_GroupCallReference
+tr_BSSMAP_IE_GroupCallRef(template (present) GroupCallRef group_call_ref) :={
+ elementIdentifier := '37'O,
+ lengthIndicator := ?,
+ descrGroupbroadcastCallRef := group_call_ref
+}
+
+/* 3.2.2.88 */
+template (value) BSSMAP_IE_VGCS_FeatureFlags
+ts_BSSMAP_IE_VGCS_FeatureFlags(BIT1 tp_ind, BIT2 as_ind, BIT1 bss_res, BIT1 tcp) := {
+ elementIdentifier := '69'O,
+ lengthIndicator := 0, // overwritten
+ TP_Ind := tp_ind,
+ AS_Ind := as_ind,
+ BSS_Res := bss_res,
+ tCP := tcp,
+ spare := '000'B
+};
+template (present) BSSMAP_IE_VGCS_FeatureFlags
+tr_BSSMAP_IE_VGCS_FeatureFlags(BIT1 tp_ind, BIT2 as_ind, BIT1 bss_res, BIT1 tcp) := {
+ elementIdentifier := '69'O,
+ lengthIndicator := ?,
+ TP_Ind := tp_ind,
+ AS_Ind := as_ind,
+ BSS_Res := bss_res,
+ tCP := tcp,
+ spare := ?
+};
+
+/* 3.2.2.98 */
+template (value) BSSMAP_IE_ApplicationData
+ts_BSSMAP_IE_ApplicationData(template (value) OCT9 adi) := {
+ elementIdentifier := '78'O,
+ lengthIndicator := 0, // overwritten
+ applicationDataInfo := adi
+};
+template (present) BSSMAP_IE_ApplicationData
+tr_BSSMAP_IE_ApplicationData(template (present) OCT9 adi) := {
+ elementIdentifier := '78'O,
+ lengthIndicator := ?,
+ applicationDataInfo := adi
+};
+
+/* 3.2.2.99 */
+template (value) BSSMAP_IE_DataIdentity
+ts_BSSMAP_IE_DataIdentity(template (value) DataIdentity data_id) := {
+ elementIdentifier := '79'O,
+ lengthIndicator := 0, // overwritten
+ dataIdentityInfo := data_id
+};
+template (present) BSSMAP_IE_DataIdentity
+tr_BSSMAP_IE_DataIdentity(template (present) DataIdentity data_id) := {
+ elementIdentifier := '79'O,
+ lengthIndicator := ?,
+ dataIdentityInfo := data_id
+};
+
+/* 3.2.2.52 */
+template (value) BSSMAP_IE_AssignmentRequirement
+ts_BSSMAP_IE_AssRequirement(template (value) OCT1 ass_rqm) := {
+ elementIdentifier := '33'O,
+ assignmentRequirement := ass_rqm
+}
+template (present) BSSMAP_IE_AssignmentRequirement
+tr_BSSMAP_IE_AssRequirement(template (present) OCT1 ass_rqm) := {
+ elementIdentifier := '33'O,
+ assignmentRequirement := ass_rqm
+}
+
+/* 3.2.2.89 */
+function ts_BSSMAP_IE_TalkerPriority(template (omit) BIT2 prio)
+return template (omit) BSSMAP_IE_TalkerPriority {
+ if (istemplatekind(prio, "omit")) {
+ return omit;
+ } else {
+ var template (present) BSSMAP_IE_TalkerPriority tp := {
+ elementIdentifier := '6A'O,
+ priority := prio,
+ spare := '000000'B
+ };
+ return tp;
+ }
+}
+function tr_BSSMAP_IE_TalkerPriority(template BIT2 prio)
+return template BSSMAP_IE_TalkerPriority {
+ if (istemplatekind(prio, "omit")) {
+ return omit;
+ } else if (istemplatekind(prio, "*")) {
+ return *;
+ } else {
+ var template BSSMAP_IE_TalkerPriority tp := {
+ elementIdentifier := '6A'O,
+ priority := prio,
+ spare := ?
+ }
+ return tp;
+ }
+}
+
+/* 3.2.2.90 */
+template (value) BSSMAP_IE_EmergencySetIndication
+ts_BSSMAP_IE_EmergencySetIndication := {
+ elementIdentifier := '6B'O
+}
+template (present) BSSMAP_IE_EmergencySetIndication
+tr_BSSMAP_IE_EmergencySetIndication := {
+ elementIdentifier := '6B'O
+}
+
+
+
+
+/* Section 3.2.1.50 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_Setup(template (value) GroupCallRef group_call_ref,
+ template (omit) BSSMAP_IE_VGCS_FeatureFlags feature_flags := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetup := {
+ messageType := '04'O,
+ groupCallReference := ts_BSSMAP_IE_GroupCallRef(group_call_ref),
+ priority := omit,
+ vGCS_FeatureFlags := feature_flags
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_Setup(template (present) GroupCallRef group_call_ref,
+ template BSSMAP_IE_VGCS_FeatureFlags feature_flags := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetup := {
+ messageType := '04'O,
+ groupCallReference := tr_BSSMAP_IE_GroupCallRef(group_call_ref),
+ priority := *,
+ vGCS_FeatureFlags := feature_flags
+ }
+ }
+ }
+}
+
+/* Section 3.2.1.51 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_SetupAck(template (omit) BSSMAP_IE_VGCS_FeatureFlags feature_flags := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetupAck := {
+ messageType := '05'O,
+ vGCS_FeatureFlags := feature_flags
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_SetupAck(template BSSMAP_IE_VGCS_FeatureFlags feature_flags := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetupAck := {
+ messageType := '05'O,
+ vGCS_FeatureFlags := feature_flags
+ }
+ }
+ }
+}
+
+/* Section 3.2.1.52 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_SetupRefuse(BssmapCause cause)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetupRefuse := {
+ messageType := '06'O,
+ cause := ts_BSSMAP_IE_Cause(cause)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_SetupRefuse(template (present) myBSSMAP_Cause cause := ?)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSSetupRefuse := {
+ messageType := '06'O,
+ cause := tr_BSSMAP_IE_Cause(cause)
+ }
+ }
+ }
+}
+
+/* Section 3.2.1.53 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_AssignmentReq(template (value) BSSMAP_IE_ChannelType ch_type,
+ template (value) OCT1 ass_requirement,
+ template (value) BSSMAP_IE_CellIdentifier cell_id,
+ template (value) GroupCallRef group_call_ref,
+ template (omit) BSSMAP_IE_CircuitIdentityCode cic := omit,
+ template (omit) BSSMAP_IE_AoIP_TransportLayerAddress aoip := omit,
+ template (omit) OCT4 call_id := omit,
+ template (omit) BSSMAP_IE_SpeechCodecList codecList := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentRequest := {
+ messageType := '07'O, /* overwritten */
+ channelType := ch_type,
+ assignmentRequirement := ts_BSSMAP_IE_AssRequirement(ass_requirement),
+ cellIdentifier := cell_id,
+ groupCallReference := ts_BSSMAP_IE_GroupCallRef(group_call_ref),
+ priority := omit,
+ circuitIdentityCode := cic,
+ downLinkDTX_Flag := omit,
+ encryptionInformation := omit,
+ vSTK_RAND := omit,
+ vSTK := omit,
+ cellIdentifierListSegment := omit,
+ aoIPTransportLayer := aoip,
+ callIdentifier := ts_BSSMAP_IE_CallIdentifier(call_id),
+ codecList := codecList
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_AssignmentReq(template (present) BSSMAP_IE_ChannelType ch_type,
+ template (present) OCT1 ass_requirement,
+ template (present) BSSMAP_IE_CellIdentifier cell_id,
+ template (present) GroupCallRef group_call_ref,
+ template BSSMAP_IE_CircuitIdentityCode cic := *,
+ template BSSMAP_IE_AoIP_TransportLayerAddress aoip := *,
+ template OCT4 call_id := *,
+ template BSSMAP_IE_SpeechCodecList codecList := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentRequest := {
+ messageType := '07'O, /* overwritten */
+ channelType := ch_type,
+ assignmentRequirement := tr_BSSMAP_IE_AssRequirement(ass_requirement),
+ cellIdentifier := cell_id,
+ groupCallReference := tr_BSSMAP_IE_GroupCallRef(group_call_ref),
+ priority := omit,
+ circuitIdentityCode := cic,
+ downLinkDTX_Flag := omit,
+ encryptionInformation := omit,
+ vSTK_RAND := omit,
+ vSTK := omit,
+ cellIdentifierListSegment := omit,
+ aoIPTransportLayer := aoip,
+ callIdentifier := tr_BSSMAP_IE_CallIdentifier(call_id),
+ codecList := codecList
}
}
}
}
+/* Section 3.2.1.54 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_AssignmentRes(template (value) BSSMAP_IE_ChannelType ch_type,
+ template (value) BSSMAP_IE_CellIdentifier cell_id,
+ template (omit) BSSMAP_IE_ChosenChannel chosen_ch := omit,
+ template (omit) BSSMAP_IE_CircuitIdentityCode cic := omit,
+ template (omit) BSSMAP_IE_AoIP_TransportLayerAddress aoip := omit,
+ template (omit) BSSMAP_IE_SpeechCodec speech_codec := omit,
+ template (omit) OCT4 call_id := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentResult := {
+ messageType := '1C'O, /* overwritten */
+ channelType := ch_type,
+ cellIdentifier := cell_id,
+ chosenChannel := chosen_ch,
+ circuitIdentityCode := cic,
+ circuitPool := omit,
+ aoIPTransportLayer := aoip,
+ speechCodec := speech_codec,
+ callIdentifier := ts_BSSMAP_IE_CallIdentifier(call_id)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_AssignmentRes(template (present) BSSMAP_IE_ChannelType ch_type,
+ template (present) BSSMAP_IE_CellIdentifier cell_id,
+ template BSSMAP_IE_ChosenChannel chosen_ch := *,
+ template BSSMAP_IE_CircuitIdentityCode cic := omit,
+ template BSSMAP_IE_AoIP_TransportLayerAddress aoip := *,
+ template BSSMAP_IE_SpeechCodec speech_codec := *,
+ template OCT4 call_id := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentResult := {
+ messageType := '1C'O, /* overwritten */
+ channelType := ch_type,
+ cellIdentifier := cell_id,
+ chosenChannel := chosen_ch,
+ circuitIdentityCode := cic,
+ circuitPool := *,
+ aoIPTransportLayer := aoip,
+ speechCodec := speech_codec,
+ callIdentifier := tr_BSSMAP_IE_CallIdentifier(call_id)
+ }
+ }
+ }
+}
+/* Section 3.2.1.55 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_AssignmentFail(BssmapCause cause)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentFailure := {
+ messageType := '1D'O, /* overwritten */
+ cause := ts_BSSMAP_IE_Cause(cause),
+ /* we only implement AoIP for now... */
+ circuitPool := omit,
+ circuitPoolList := omit,
+ codecList := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_AssignmentFail(template (present) myBSSMAP_Cause cause := ?)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSAssignmentFailure := {
+ messageType := '1D'O, /* overwritten */
+ cause := tr_BSSMAP_IE_Cause(cause),
+ /* we only implement AoIP for now... */
+ circuitPool := omit,
+ circuitPoolList := omit,
+ codecList := omit
+ }
+ }
+ }
+}
+
+/* Section 3.2.1.56 */
+template (value) PDU_BSSAP
+ts_BSSMAP_VGCS_VBS_QueuingInd
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSQueuingIndication := {
+ messageType := '1E'O
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_VGCS_VBS_QueuingInd
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ vGCS_VBSQueuingIndication := {
+ messageType := '1E'O
+ }
+ }
+ }
+}
+
+/* Section 3.2.1.57 */
+template (value) PDU_BSSAP ts_BSSMAP_UplinkReq
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := omit,
+ cellIdentifier := omit,
+ layer3Information := omit,
+ mobileIdentity := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP tr_BSSMAP_UplinkReq
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := *,
+ cellIdentifier := *,
+ layer3Information := *,
+ mobileIdentity := *
+ }
+ }
+ }
+}
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkReq_L3(template (value) BIT2 priority,
+ template (omit) BSSMAP_IE_CellIdentifier cell_id,
+ template (value) octetstring l3_info)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := ts_BSSMAP_IE_TalkerPriority(priority),
+ cellIdentifier := cell_id,
+ layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
+ mobileIdentity := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkReq_L3(template (present) BIT2 priority,
+ template BSSMAP_IE_CellIdentifier cell_id,
+ template (present) octetstring l3_info)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := tr_BSSMAP_IE_TalkerPriority(priority),
+ cellIdentifier := cell_id,
+ layer3Information := tr_BSSMAP_IE_L3Info(l3_info),
+ mobileIdentity := omit
+ }
+ }
+ }
+}
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkReq_MI(template (omit) BIT2 priority,
+ template (omit) BSSMAP_IE_CellIdentifier cell_id,
+ template (value) BSSMAP_IE_MobileIdentity mobile_id)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := ts_BSSMAP_IE_TalkerPriority(priority),
+ cellIdentifier := cell_id,
+ layer3Information := omit,
+ mobileIdentity := mobile_id
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkReq_MI(template BIT2 priority,
+ template (omit) BSSMAP_IE_CellIdentifier cell_id,
+ template (present) BSSMAP_IE_MobileIdentity mobile_id)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequest := {
+ messageType := '1F'O,
+ talkerPriority := tr_BSSMAP_IE_TalkerPriority(priority),
+ cellIdentifier := cell_id,
+ layer3Information := omit,
+ mobileIdentity := mobile_id
+ }
+ }
+ }
+}
+
+/* 3.2.1.58 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkReqAck(template (omit) BIT2 priority,
+ template (omit) BSSMAP_IE_EmergencySetIndication ems := omit,
+ template (omit) BSSMAP_IE_TalkerIdentity talker_id := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequestAck := {
+ messageType := '27'O,
+ talkerPriority := ts_BSSMAP_IE_TalkerPriority(priority),
+ emergencySetIndication := ems,
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkReqAck(template BIT2 priority,
+ template BSSMAP_IE_EmergencySetIndication ems := *,
+ template BSSMAP_IE_TalkerIdentity talker_id := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequestAck := {
+ messageType := '27'O,
+ talkerPriority := tr_BSSMAP_IE_TalkerPriority(priority),
+ emergencySetIndication := ems,
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+
+/* 3.2.1.59 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkReqConf(template (value) BSSMAP_IE_CellIdentifier cell_id,
+ template (omit) BSSMAP_IE_TalkerIdentity talker_id := omit,
+ template (value) octetstring l3_info)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequestConfirmation := {
+ messageType := '49'O,
+ cellIdentifier := cell_id,
+ talkerIdentity := talker_id,
+ layer3Information := ts_BSSMAP_IE_L3Info(l3_info)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkReqConf(template (present) BSSMAP_IE_CellIdentifier cell_id,
+ template BSSMAP_IE_TalkerIdentity talker_id := *,
+ template (present) octetstring l3_info)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRequestConfirmation := {
+ messageType := '49'O,
+ cellIdentifier := cell_id,
+ talkerIdentity := talker_id,
+ layer3Information := tr_BSSMAP_IE_L3Info(l3_info)
+ }
+ }
+ }
+}
+
+
+/* 3.2.1.60 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkRelInd(BssmapCause cause, template (omit) BIT2 prio)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkReleaseIndication := {
+ messageType := '4A'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ talkerPriority := ts_BSSMAP_IE_TalkerPriority(prio)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkRelInd(template (present) myBSSMAP_Cause cause, template BIT2 prio)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkReleaseIndication := {
+ messageType := '4A'O,
+ cause := tr_BSSMAP_IE_Cause(cause),
+ talkerPriority := tr_BSSMAP_IE_TalkerPriority(prio)
+ }
+ }
+ }
+}
+
+
+/* 3.2.1.61 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkRejCmd(BssmapCause cause,
+ template (omit) BIT2 cur_talker_prio := omit,
+ template (omit) BIT2 rej_talker_prio := omit,
+ template (omit) BSSMAP_IE_TalkerIdentity talker_id := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRejectCommand := {
+ messageType := '4B'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ currentTalkerPriority := ts_BSSMAP_IE_TalkerPriority(cur_talker_prio),
+ rejectedTalkerPriority := ts_BSSMAP_IE_TalkerPriority(rej_talker_prio),
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkRejCmd(template (present) myBSSMAP_Cause cause,
+ template BIT2 cur_talker_prio := *,
+ template BIT2 rej_talker_prio := *,
+ template BSSMAP_IE_TalkerIdentity talker_id := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkRejectCommand := {
+ messageType := '4B'O,
+ cause := tr_BSSMAP_IE_Cause(cause),
+ currentTalkerPriority := tr_BSSMAP_IE_TalkerPriority(cur_talker_prio),
+ rejectedTalkerPriority := tr_BSSMAP_IE_TalkerPriority(rej_talker_prio),
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+
+
+/* 3.2.1.62 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkRelCmd(BssmapCause cause)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkReleaseCommand := {
+ messageType := '4C'O,
+ cause := ts_BSSMAP_IE_Cause(cause)
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkRelCmd(template (present) myBSSMAP_Cause cause)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkReleaseCommand := {
+ messageType := '4C'O,
+ cause := tr_BSSMAP_IE_Cause(cause)
+ }
+ }
+ }
+}
+
+
+/* 3.2.1.63 */
+template (value) PDU_BSSAP
+ts_BSSMAP_UplinkSeizedCmd(BssmapCause cause,
+ template (omit) BIT2 talker_prio := omit,
+ template (omit) BSSMAP_IE_EmergencySetIndication emerg := omit,
+ template (omit) BSSMAP_IE_TalkerIdentity talker_id := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkSeizedCommand := {
+ messageType := '4D'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ talkerPriority := ts_BSSMAP_IE_TalkerPriority(talker_prio),
+ emergencySetIndication := emerg,
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_UplinkSeizedCmd(template (present) myBSSMAP_Cause cause,
+ template BIT2 talker_prio := *,
+ template BSSMAP_IE_EmergencySetIndication emerg := *,
+ template BSSMAP_IE_TalkerIdentity talker_id := *)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ uplinkSeizedCommand := {
+ messageType := '4D'O,
+ cause := tr_BSSMAP_IE_Cause(cause),
+ talkerPriority := tr_BSSMAP_IE_TalkerPriority(talker_prio),
+ emergencySetIndication := emerg,
+ talkerIdentity := talker_id
+ }
+ }
+ }
+}
+
+
+
+/* Section 3.2.1.82 */
+template (value) PDU_BSSAP
+ts_BSSMAP_NotificationData(template (value) OCT9 app_data, template (value) DataIdentity data_identity)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ notificationData := {
+ messageType := '62'O,
+ applicationData := ts_BSSMAP_IE_ApplicationData(app_data),
+ dataIdentity := ts_BSSMAP_IE_DataIdentity(data_identity),
+ mSISDN := omit
+ }
+ }
+ }
+}
+template (present) PDU_BSSAP
+tr_BSSMAP_NotificationData(template (present) OCT9 app_data, template (present) DataIdentity data_identity)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ notificationData := {
+ messageType := '62'O,
+ applicationData := tr_BSSMAP_IE_ApplicationData(app_data),
+ dataIdentity := tr_BSSMAP_IE_DataIdentity(data_identity),
+ mSISDN := ?
+ }
+ }
+ }
+}
+
+
+
+template (value) PDU_BSSAP
+ts_BSSMAP_Perform_Location_Request(template (omit) BSSMAP_IE_IMSI imsi,
+ template (omit) BSSMAP_IE_CellIdentifier cellIdentifier := omit,
+ template (omit) BSSMAP_IE_LCSClientType clientType := ts_BSSMAP_IE_LCSClientType,
+ template (omit) BSSMAP_IE_LCSPriority priority := ts_BSSMAP_IE_LCSPriority,
+ template (omit) BSSMAP_IE_LCSQOS qos := ts_BSSMAP_IE_LCSQOS)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ performLocationRequest := {
+ messageType := '2B'O,
+ locationType := ts_BSSMAP_IE_LocationType,
+ cellIdentifier := cellIdentifier,
+ classmarkInformationType3 := omit,
+ lCS_ClientType := clientType,
+ chosenChannel := omit,
+ lCS_Priority := priority,
+ lCS_QOS := qos,
+ gPS_AssistanceData := omit,
+ aPDU := omit,
+ iMSI := imsi,
+ iMEI := omit,
+ gANSS_LocationType := omit,
+ gANSS_AssistanceData := omit
+ }
+ }
+ }
+}
+
+template (present) BSSMAP_IE_LocationEstimate tr_BSSMAP_IE_LocationEstimate(template (present) octetstring geo_loc := ?)
+:= {
+ elementIdentifier := '45'O,
+ lengthIndicator := ?,
+ geographicLocation := geo_loc
+}
+
+function tr_BSSMAP_LcsCause(template (present) BSSMAP_LcsCause cause)
+return template (omit) BSSMAP_IE_LCSCause {
+ if (istemplatekind(cause, "omit")) {
+ return omit;
+ }
+ var template BSSMAP_IE_LCSCause ie := {
+ elementIdentifier := '47'O,
+ lengthIndicator := 1,
+ causeValue := int2bit(enum2int(valueof(cause)), 8),
+ diagnosticValue := omit
+ }
+ return ie;
+}
+
+template (present) PDU_BSSAP tr_BSSMAP_Perform_Location_Response(
+ template BSSMAP_IE_LocationEstimate locationEstimate := *,
+ template BSSMAP_IE_PositioningData positioningData := *,
+ template BSSMAP_IE_LCSCause lCS_Cause := *
+ )
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ performLocationResponse := {
+ messageType := '2D'O,
+ locationEstimate := locationEstimate,
+ positioningData := positioningData,
+ decipheringKeys := *,
+ lCS_Cause := lCS_Cause,
+ velocityEstimate := *,
+ gANSS_PositioningData := *
+ }
+ }
+ }
+}
+
+template (present) PDU_BSSAP tr_BSSMAP_Perform_Location_Abort(template (present) BSSMAP_IE_LCSCause lCS_Cause := ?)
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ performLocationAbort := {
+ messageType := '2E'O,
+ lCS_Cause := lCS_Cause
+ }
+ }
+ }
+}
} with { encode "RAW" };
diff --git a/library/CBSP_Adapter.ttcn b/library/CBSP_Adapter.ttcn
index fe399aa4..278a2f24 100644
--- a/library/CBSP_Adapter.ttcn
+++ b/library/CBSP_Adapter.ttcn
@@ -41,6 +41,10 @@ function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
runs on CBSP_Adapter_CT {
var IPL4asp_Types.Result res;
map(self:CBSP[idx], system:CBSP);
+ if (g_cbsp_conn_id[idx] != -1) {
+ CBSP_CodecPort_CtrlFunct.f_IPL4_close(CBSP[idx], g_cbsp_conn_id[idx], {tcp := {}});
+ g_cbsp_conn_id[idx] := -1;
+ }
res := CBSP_CodecPort_CtrlFunct.f_IPL4_connect(CBSP[idx], remote_host, remote_port,
local_host, local_port, 0, { tcp :={} });
if (not ispresent(res.connId)) {
@@ -58,12 +62,31 @@ function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, inte
runs on CBSP_Adapter_CT {
var IPL4asp_Types.Result res;
map(self:CBSP[idx], system:CBSP);
+ if (g_cbsp_conn_id[idx] != -1) {
+ CBSP_CodecPort_CtrlFunct.f_IPL4_close(CBSP[idx], g_cbsp_conn_id[idx], {tcp := {}});
+ g_cbsp_conn_id[idx] := -1;
+ }
res := CBSP_CodecPort_CtrlFunct.f_IPL4_listen(CBSP[idx], local_host, local_port, { tcp:={} });
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not bind to CBSP port, check your configuration ",
+ "{local ", local_host, ":", local_port, "}");
+ mtc.stop;
+ }
g_cbsp_conn_id[idx] := res.connId;
f_set_tcp_segmentation(idx);
}
+function f_wait_client_connect(integer idx := 0) runs on CBSP_Adapter_CT {
+ var IPL4asp_Types.PortEvent rx_event;
+ CBSP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
+ log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
+ /* we want to store the client's connId, not the 'bind socket' one */
+ g_cbsp_conn_id[idx] := rx_event.connOpened.connId;
+ }
+ f_set_tcp_segmentation(idx);
+}
+
function f_cbsp_send(template (value) CBSP_PDU pdu, integer idx := 0) runs on CBSP_Adapter_CT {
CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], pdu));
}
diff --git a/library/CBSP_Templates.ttcn b/library/CBSP_Templates.ttcn
index 49906fe5..e5985668 100644
--- a/library/CBSP_Templates.ttcn
+++ b/library/CBSP_Templates.ttcn
@@ -54,7 +54,7 @@ function tr_CbspChannelInd(template uint8_t val := ?) return template CBSP_IE {
if (istemplatekind(val, "omit")) {
ie := omit;
} else if (istemplatekind(val, "*")) {
- ie := tr_CBSP_IE({channel_ind := ?}) ifpresent;
+ ie := tr_CBSP_IE({channel_ind := ?}); //ifpresent;
} else {
ie := tr_CBSP_IE({channel_ind := val});
}
@@ -134,6 +134,30 @@ template CBSP_IE tr_CbspFailList(template CBSP_FailureListItems items := ?) :=
list := items
}});
+template (present) CBSP_FailureListItem CBSP_FailureListItem_CGI(
+ template (present) BSSMAP_FIELD_CellIdentification_CGI cgi := ?,
+ template (present) CBSP_Cause cause := ?) :=
+{
+ spare1_4 := '0000'B,
+ cell_id_discr := '0000'B,
+ cell_id := {
+ cI_CGI := cgi
+ },
+ cause := cause
+};
+
+template (present) CBSP_FailureListItem CBSP_FailureListItem_LAC_CI(
+ template (present) BSSMAP_FIELD_CellIdentification_LAC_CI lac_ci := ?,
+ template (present) CBSP_Cause cause := ?) :=
+{
+ spare1_4 := '0000'B,
+ cell_id_discr := '0001'B,
+ cell_id := {
+ cI_LAC_CI := lac_ci
+ },
+ cause := cause
+};
+
template (value) CBSP_IE ts_CbspNumComplList(template (value) CBSP_IE_NumBcastComplList list) :=
ts_CBSP_IE(CBSP_IEI_NUM_BCAST_COMPL_LIST, {num_bcast_compl_list := list});
template CBSP_IE tr_CbspNumComplList(template CBSP_IE_NumBcastComplList list := ?) :=
@@ -314,7 +338,6 @@ template (value) CBSP_PDU ts_CBSP_REPLACE_EMERG(uint16_t msg_id, uint16_t new_se
template (value) BSSMAP_FIELD_CellIdentificationList cell_list,
template (value) uint8_t emerg_ind,
template (value) uint16_t warn_type,
- template (value) uint16_t num_bcast_req,
template (value) uint8_t warn_per
) :=
ts_CBSP(CBSP_MSGT_WRITE_REPLACE, {
@@ -331,7 +354,6 @@ template CBSP_PDU tr_CBSP_REPLACE_EMERG(template uint16_t msg_id := ?, template
template BSSMAP_FIELD_CellIdentificationList cell_list := ?,
template uint8_t emerg_ind := ?,
template uint16_t warn_type := ?,
- template uint16_t num_bcast_req := ?,
template uint8_t warn_per := ?
) :=
tr_CBSP(CBSP_MSGT_WRITE_REPLACE, {
@@ -354,14 +376,27 @@ return template (value) CBSP_PDU {
ts_NewSerNo(new_ser_nr)
};
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
}
+function ts_CBSP_WRITE_EMERG_COMPL(uint16_t msg_id, uint16_t new_ser_nr,
+ template (omit) BSSMAP_FIELD_CellIdentificationList cell_list)
+return template (value) CBSP_PDU {
+ var template (value) CBSP_IEs ies := {
+ ts_CbspMsgId(msg_id),
+ ts_NewSerNo(new_ser_nr)
+ };
+ if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
+ }
+ return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
+}
+
function tr_CBSP_WRITE_CBS_COMPL(template uint16_t msg_id, template uint16_t new_ser_nr,
template BSSMAP_FIELD_CellIdentificationList cell_list,
- template uint8_t channel_ind)
+ template (present) uint8_t channel_ind)
return template CBSP_PDU {
var template CBSP_IEs ies := {
tr_CbspMsgId(msg_id),
@@ -375,8 +410,23 @@ return template CBSP_PDU {
} else if (not istemplatekind(cell_list, "omit")) {
ies[lengthof(ies)] := tr_CbspCellList(cell_list);
}
- if (not istemplatekind(channel_ind, "omit")) {
- ies[lengthof(ies)] := tr_CbspChannelInd(channel_ind);
+ ies[lengthof(ies)] := tr_CbspChannelInd(channel_ind);
+ return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
+}
+function tr_CBSP_WRITE_EMERG_COMPL(template uint16_t msg_id, template uint16_t new_ser_nr,
+ template BSSMAP_FIELD_CellIdentificationList cell_list)
+return template CBSP_PDU {
+ var template CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_NewSerNo(new_ser_nr)
+ };
+ if (istemplatekind(cell_list, "*")) {
+ testcase.stop("TITAN > 6.5.0 doesn't support this");
+ //ies[lengthof(ies)] := tr_CbspCellList ifpresent;
+ } else if (istemplatekind(cell_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspCellList(?);
+ } else if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspCellList(cell_list);
}
return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
}
@@ -394,23 +444,44 @@ return template (value) CBSP_PDU {
ts_CbspNumComplList(compl_list)
};
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
}
+function ts_CBSP_REPLACE_EMERG_COMPL(uint16_t msg_id, uint16_t new_ser_nr, uint16_t old_ser_nr,
+ template (omit) BSSMAP_FIELD_CellIdentificationList cell_list)
+return template (value) CBSP_PDU {
+ var template (value) CBSP_IEs ies := {
+ ts_CbspMsgId(msg_id),
+ ts_NewSerNo(new_ser_nr),
+ ts_OldSerNo(old_ser_nr)
+ };
+ if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
+ }
+ return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
+}
function tr_CBSP_REPLACE_CBS_COMPL(template uint16_t msg_id, template uint16_t new_ser_nr,
template uint16_t old_ser_nr,
template CBSP_IE_NumBcastComplList compl_list,
template BSSMAP_FIELD_CellIdentificationList cell_list,
- template uint8_t channel_ind)
+ template (present) uint8_t channel_ind)
return template CBSP_PDU {
var template CBSP_IEs ies := {
tr_CbspMsgId(msg_id),
tr_NewSerNo(new_ser_nr),
- tr_OldSerNo(old_ser_nr),
- tr_CbspNumComplList(compl_list)
+ tr_OldSerNo(old_ser_nr)
};
+ if (istemplatekind(compl_list, "*")) {
+ testcase.stop("TITAN > 6.5.0 doesn't support this");
+ //ies[lengthof(ies)] := tr_CbspNumComplList ifpresent;
+ } else if (istemplatekind(compl_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(?);
+ } else if (not istemplatekind(compl_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(compl_list);
+ }
+
if (istemplatekind(cell_list, "*")) {
testcase.stop("TITAN > 6.5.0 doesn't support this");
//ies[lengthof(ies)] := tr_CbspCellList ifpresent;
@@ -424,6 +495,26 @@ return template CBSP_PDU {
}
return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
}
+function tr_CBSP_REPLACE_EMERG_COMPL(template uint16_t msg_id, template uint16_t new_ser_nr,
+ template uint16_t old_ser_nr,
+ template BSSMAP_FIELD_CellIdentificationList cell_list)
+return template CBSP_PDU {
+ var template CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_NewSerNo(new_ser_nr),
+ tr_OldSerNo(old_ser_nr)
+ };
+
+ if (istemplatekind(cell_list, "*")) {
+ testcase.stop("TITAN > 6.5.0 doesn't support this");
+ //ies[lengthof(ies)] := tr_CbspCellList ifpresent;
+ } else if (istemplatekind(cell_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspCellList(?);
+ } else if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspCellList(cell_list);
+ }
+ return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_COMPL, ies);
+}
/* 8.1.3.3 WRITE-REPLACE FAILURE */
@@ -439,10 +530,10 @@ return template (value) CBSP_PDU {
ts_CbspFailList(fail_list)
};
if (not istemplatekind(compl_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspNumComplList(compl_list);
+ ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
}
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
@@ -451,7 +542,7 @@ function tr_CBSP_WRITE_CBS_FAIL(template uint16_t msg_id, template uint16_t new_
template CBSP_FailureListItems fail_list,
template CBSP_IE_NumBcastComplList compl_list,
template BSSMAP_FIELD_CellIdentificationList cell_list,
- template uint8_t channel_ind)
+ template (present) uint8_t channel_ind)
return template CBSP_PDU {
var template CBSP_IEs ies := {
tr_CbspMsgId(msg_id),
@@ -473,8 +564,33 @@ return template CBSP_PDU {
} else if (not istemplatekind(cell_list, "omit")) {
ies[lengthof(ies)] := tr_CbspCellList(cell_list);
}
- if (not istemplatekind(channel_ind, "omit")) {
- ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
+ ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
+ return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
+}
+function tr_CBSP_WRITE_EMERG_FAIL(template uint16_t msg_id, template uint16_t new_ser_nr,
+ template CBSP_FailureListItems fail_list,
+ template CBSP_IE_NumBcastComplList compl_list,
+ template BSSMAP_FIELD_CellIdentificationList cell_list)
+return template CBSP_PDU {
+ var template CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_NewSerNo(new_ser_nr),
+ tr_CbspFailList(fail_list)
+ };
+ if (istemplatekind(compl_list, "*")) {
+ //ies[lengthof(ies)] := tr_CbspNumComplList ifpresent;
+ } else if (istemplatekind(compl_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(?);
+ } else if (not istemplatekind(compl_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(compl_list);
+ }
+ if (istemplatekind(cell_list, "*")) {
+ testcase.stop("TITAN > 6.5.0 doesn't support this");
+ //ies[lengthof(ies)] := tr_CbspCellList ifpresent;
+ } else if (istemplatekind(cell_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspCellList(?);
+ } else if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspCellList(cell_list);
}
return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
}
@@ -493,10 +609,10 @@ return template (value) CBSP_PDU {
ts_CbspFailList(fail_list)
};
if (not istemplatekind(compl_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspNumComplList(compl_list);
+ ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
}
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
return ts_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
@@ -506,7 +622,7 @@ function tr_CBSP_REPLACE_CBS_FAIL(template uint16_t msg_id, template uint16_t ne
template CBSP_FailureListItems fail_list,
template CBSP_IE_NumBcastComplList compl_list,
template BSSMAP_FIELD_CellIdentificationList cell_list,
- template uint8_t channel_ind)
+ template (present) uint8_t channel_ind)
return template CBSP_PDU {
var template CBSP_IEs ies := {
tr_CbspMsgId(msg_id),
@@ -531,25 +647,65 @@ return template CBSP_PDU {
ies[lengthof(ies)] := tr_CbspChannelInd(channel_ind);
return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
}
+function tr_CBSP_REPLACE_EMERG_FAIL(template uint16_t msg_id, template uint16_t new_ser_nr,
+ template uint16_t old_ser_nr,
+ template CBSP_FailureListItems fail_list,
+ template CBSP_IE_NumBcastComplList compl_list,
+ template BSSMAP_FIELD_CellIdentificationList cell_list)
+return template CBSP_PDU {
+ var template CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_NewSerNo(new_ser_nr),
+ tr_OldSerNo(old_ser_nr),
+ tr_CbspFailList(fail_list)
+ };
+ if (istemplatekind(compl_list, "*")) {
+ //ies[lengthof(ies)] := tr_CbspCellList ifpresent;
+ } else if (istemplatekind(compl_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(?);
+ } else if (not istemplatekind(compl_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(compl_list);
+ }
+ if (istemplatekind(cell_list, "*")) {
+ //ies[lengthof(ies)] := tr_CbspCellList ifpresent;
+ } else if (istemplatekind(cell_list, "?")) {
+ ies[lengthof(ies)] := tr_CbspCellList(?);
+ } else if (not istemplatekind(cell_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspCellList(cell_list);
+ }
+ return tr_CBSP(CBSP_MSGT_WRITE_REPLACE_FAIL, ies);
+}
/* 8.1.3.4 KILL */
-template (value) CBSP_PDU ts_CBSP_KILL(template (value) uint16_t msg_id,
- template (value) uint16_t old_ser_nr,
- template (value) BSSMAP_FIELD_CellIdentificationList cell_list,
- template (omit) uint8_t channel_ind) :=
- ts_CBSP(CBSP_MSGT_KILL, {
- ts_CbspMsgId(msg_id),
- ts_OldSerNo(old_ser_nr),
- ts_CbspCellList(cell_list),
- ts_CbspChannelInd(channel_ind)});
-template CBSP_PDU tr_CBSP_KILL(template uint16_t msg_id := ?, template uint16_t old_ser_nr := ?,
- template BSSMAP_FIELD_CellIdentificationList cell_list := ?,
- template uint8_t channel_ind := ?) :=
- tr_CBSP(CBSP_MSGT_KILL, {
- tr_CbspMsgId(msg_id),
- tr_OldSerNo(old_ser_nr),
- tr_CbspCellList(cell_list),
- tr_CbspChannelInd(channel_ind) });
+function ts_CBSP_KILL(template (value) uint16_t msg_id,
+ template (value) uint16_t old_ser_nr,
+ template (value) BSSMAP_FIELD_CellIdentificationList cell_list,
+ template (omit) uint8_t channel_ind)
+return template (value) CBSP_PDU {
+ var template (value) CBSP_IEs ies := {
+ ts_CbspMsgId(msg_id),
+ ts_OldSerNo(old_ser_nr),
+ ts_CbspCellList(cell_list)
+ };
+ if (not istemplatekind(channel_ind, "omit")) {
+ ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
+ }
+ return ts_CBSP(CBSP_MSGT_KILL, ies);
+}
+function tr_CBSP_KILL(template uint16_t msg_id := ?, template uint16_t old_ser_nr := ?,
+ template BSSMAP_FIELD_CellIdentificationList cell_list := ?,
+ template uint8_t channel_ind := ?)
+return template (present) CBSP_PDU {
+ var template CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_OldSerNo(old_ser_nr),
+ tr_CbspCellList(cell_list)
+ };
+ if (not istemplatekind(channel_ind, "omit")) {
+ ies[lengthof(ies)] := tr_CbspChannelInd(channel_ind);
+ }
+ return tr_CBSP(CBSP_MSGT_KILL, ies);
+}
/* 8.1.3.5 KILL COMPLETE */
function ts_CBSP_KILL_COMPL(template (value) uint16_t msg_id, template (value) uint16_t old_ser_nr,
@@ -562,10 +718,10 @@ return template (value) CBSP_PDU {
ts_OldSerNo(old_ser_nr)
};
if (not istemplatekind(compl_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspNumComplList(compl_list);
+ ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
}
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
if (not istemplatekind(channel_ind, "omit")) {
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
@@ -581,20 +737,29 @@ return template CBSP_PDU {
tr_CbspMsgId(msg_id),
tr_OldSerNo(old_ser_nr)
};
+ /* As soon as adding a '*' IE item, lengthof() no longer works on the ies record. So keep track of the
+ * next index to use separately. */
+ var integer next_idx := lengthof(ies);
if (istemplatekind(compl_list, "*")) {
- ies[lengthof(ies)] := *;
+ ies[next_idx] := *;
+ next_idx := next_idx + 1;
} else if (not istemplatekind(compl_list, "omit")) {
- ies[lengthof(ies)] := tr_CbspNumComplList(compl_list);
+ ies[next_idx] := tr_CbspNumComplList(compl_list);
+ next_idx := next_idx + 1;
}
if (istemplatekind(cell_list, "*")) {
- ies[lengthof(ies)] := *;
+ ies[next_idx] := *;
+ next_idx := next_idx + 1;
} else if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := tr_CbspCellList(cell_list);
+ ies[next_idx] := tr_CbspCellList(cell_list);
+ next_idx := next_idx + 1;
}
if (istemplatekind(channel_ind, "*")) {
- ies[lengthof(ies)] := *;
+ ies[next_idx] := *;
+ next_idx := next_idx + 1;
} else if (not istemplatekind(channel_ind, "omit")) {
- ies[lengthof(ies)] := tr_CbspChannelInd(channel_ind);
+ ies[next_idx] := tr_CbspChannelInd(channel_ind);
+ next_idx := next_idx + 1;
}
return tr_CBSP(CBSP_MSGT_KILL_COMPL, ies);
}
@@ -612,10 +777,10 @@ return template (value) CBSP_PDU {
ts_CbspFailList(fail_list)
};
if (not istemplatekind(compl_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspNumComplList(compl_list);
+ ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
}
if (not istemplatekind(cell_list, "omit")) {
- ies[lengthof(ies)] := ts_CbspCellList(cell_list);
+ ies[lengthof(ies)] := ts_CbspCellList(valueof(cell_list));
}
if (not istemplatekind(channel_ind, "omit")) {
ies[lengthof(ies)] := ts_CbspChannelInd(channel_ind);
@@ -652,6 +817,85 @@ return template CBSP_PDU {
return tr_CBSP(CBSP_MSGT_KILL_FAIL, ies);
}
+/* 8.1.3.10 MESSAGE STATUS QUERY */
+template (value) CBSP_PDU
+ts_CBSP_MSG_STATUS_QUERY(template (value) uint16_t msg_id,
+ template (value) uint16_t old_ser_nr,
+ template (value) BSSMAP_FIELD_CellIdentificationList cell_list,
+ template (value) uint8_t channel_ind) :=
+ ts_CBSP(CBSP_MSGT_MSG_STATUS_QUERY, {
+ ts_CbspMsgId(msg_id),
+ ts_OldSerNo(old_ser_nr),
+ ts_CbspCellList(cell_list),
+ ts_CbspChannelInd(channel_ind)});
+template (present) CBSP_PDU
+tr_CBSP_MSG_STATUS_QUERY(template (present) uint16_t msg_id := ?,
+ template (present) uint16_t old_ser_nr := ?,
+ template (present) BSSMAP_FIELD_CellIdentificationList cell_list := ?,
+ template (present) uint8_t channel_ind := ?) :=
+ ts_CBSP(CBSP_MSGT_MSG_STATUS_QUERY, {
+ ts_CbspMsgId(msg_id),
+ ts_OldSerNo(old_ser_nr),
+ ts_CbspCellList(cell_list),
+ ts_CbspChannelInd(channel_ind)});
+
+/* 8.1.3.11 MESSAGE STATUS QUERY COMPLETE */
+template (value) CBSP_PDU
+ts_CBSP_MSG_STATUS_QUERY_COMPL(template (value) uint16_t msg_id, template (value) uint16_t old_ser_nr,
+ template (value) CBSP_IE_NumBcastComplList compl_list,
+ template (value) uint8_t channel_ind) :=
+ ts_CBSP(CBSP_MSGT_MSG_STATUS_QUERY_COMPL, {
+ ts_CbspMsgId(msg_id),
+ ts_OldSerNo(old_ser_nr),
+ ts_CbspNumComplList(valueof(compl_list)),
+ ts_CbspChannelInd(channel_ind)});
+template (present) CBSP_PDU
+tr_CBSP_MSG_STATUS_QUERY_COMPL(template (present) uint16_t msg_id, template (present) uint16_t old_ser_nr,
+ template (present) CBSP_IE_NumBcastComplList compl_list,
+ template (present) uint8_t channel_ind) :=
+ tr_CBSP(CBSP_MSGT_MSG_STATUS_QUERY_COMPL, {
+ tr_CbspMsgId(msg_id),
+ tr_OldSerNo(old_ser_nr),
+ tr_CbspNumComplList(compl_list),
+ tr_CbspChannelInd(channel_ind)});
+
+/* 8.1.3.12 MESSAGE STATUS QUERY FAILURE */
+function ts_CBSP_MSG_STATUS_QUERY_FAIL(template (value) uint16_t msg_id, template (value) uint16_t old_ser_nr,
+ template (value) CBSP_FailureListItems fail_list,
+ template (value) uint8_t channel_ind,
+ template (omit) CBSP_IE_NumBcastComplList compl_list)
+return template (value) CBSP_PDU {
+ var template (value) CBSP_IEs ies := {
+ ts_CbspMsgId(msg_id),
+ ts_OldSerNo(old_ser_nr),
+ ts_CbspFailList(fail_list),
+ ts_CbspChannelInd(channel_ind)
+ };
+ if (not istemplatekind(compl_list, "omit")) {
+ ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
+ }
+ return ts_CBSP(CBSP_MSGT_MSG_STATUS_QUERY_FAIL, ies);
+}
+function tr_CBSP_MSG_STATUS_QUERY_FAIL(template (present) uint16_t msg_id := ?, template (present) uint16_t old_ser_nr := ?,
+ template (present) CBSP_FailureListItems fail_list := ?,
+ template (present) uint8_t channel_ind := ?,
+ template CBSP_IE_NumBcastComplList compl_list := *)
+return template (present) CBSP_PDU {
+ var template (present) CBSP_IEs ies := {
+ tr_CbspMsgId(msg_id),
+ tr_OldSerNo(old_ser_nr),
+ tr_CbspFailList(fail_list),
+ tr_CbspChannelInd(channel_ind)
+ };
+ if (istemplatekind(compl_list, "*")) {
+ testcase.stop("TITAN > 6.5.0 doesn't support this");
+ //ies[lengthof(ies)] := ts_CbspNumComplList(valueof(compl_list));
+ } else if (not istemplatekind(compl_list, "omit")) {
+ ies[lengthof(ies)] := tr_CbspNumComplList(compl_list);
+ }
+ return tr_CBSP(CBSP_MSGT_MSG_STATUS_QUERY_FAIL, ies);
+}
+
/* 8.1.3.16 RESET */
template (value) CBSP_PDU ts_CBSP_RESET(template (value) BSSMAP_FIELD_CellIdentificationList cell_list) :=
diff --git a/library/CBSP_Types.ttcn b/library/CBSP_Types.ttcn
index c4c6cf25..b282454b 100644
--- a/library/CBSP_Types.ttcn
+++ b/library/CBSP_Types.ttcn
@@ -161,31 +161,31 @@ type union CBSP_FIELD_NumBcastCompl {
};
type record CBSP_FIELD_NumBcastCompl_CGI {
BSSMAP_FIELD_CellIdentification_CGI ci,
- uint16_t num_bcats_compl,
+ uint16_t num_bcast_compl,
CBSP_NumBcastInfo num_bcast_info,
BIT4 spare1_4
};
type record CBSP_FIELD_NumBcastCompl_LAC_CI {
BSSMAP_FIELD_CellIdentification_LAC_CI ci,
- uint16_t num_bcats_compl,
+ uint16_t num_bcast_compl,
CBSP_NumBcastInfo num_bcast_info,
BIT4 spare1_4
};
type record CBSP_FIELD_NumBcastCompl_LAI {
BSSMAP_FIELD_CellIdentification_LAI ci,
- uint16_t num_bcats_compl,
+ uint16_t num_bcast_compl,
CBSP_NumBcastInfo num_bcast_info,
BIT4 spare1_4
};
type record CBSP_FIELD_NumBcastCompl_CI {
OCT2 ci,
- uint16_t num_bcats_compl,
+ uint16_t num_bcast_compl,
CBSP_NumBcastInfo num_bcast_info,
BIT4 spare1_4
};
type record CBSP_FIELD_NumBcastCompl_LAC {
OCT2 lac,
- uint16_t num_bcats_compl,
+ uint16_t num_bcast_compl,
CBSP_NumBcastInfo num_bcast_info,
BIT4 spare1_4
};
@@ -378,5 +378,24 @@ external function enc_CBSP_PDU(in CBSP_PDU msg) return octetstring
external function dec_CBSP_PDU(in octetstring msg) return CBSP_PDU
with { extension "prototype(convert) decode(RAW)" };
+/* convert from warning period encoding to seconds */
+function f_cbsp_period2s(uint8_t period) return integer
+{
+ if (period == 0) {
+ return -1; /* infinite */
+ } else if (period <= 10) {
+ return period;
+ } else if (period <= 20) {
+ return 10 + (period - 10)*2;
+ } else if (period <= 38) {
+ return 30 + (period - 20)*5;
+ } else if (period <= 86) {
+ return 120 + (period - 38)*10;
+ } else if (period <= 186) {
+ return 600 + (period - 86)*30;
+ } else {
+ return 0;
+ }
+}
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/DIAMETER_Emulation.ttcn b/library/DIAMETER_Emulation.ttcn
index f7a0f887..69107d4b 100644
--- a/library/DIAMETER_Emulation.ttcn
+++ b/library/DIAMETER_Emulation.ttcn
@@ -18,6 +18,10 @@ module DIAMETER_Emulation {
* the DiameterOps.unitdata_cb() callback, which is registered with an argument to the
* main() function below.
*
+ * Alternatively, all inbound DIAMETER PDUs can be routed to a single component
+ * regardless of the IMSI. This is called 'raw' mode and can be achieved by
+ * setting the 'raw' field in DIAMETEROps to true.
+ *
* (C) 2019 by Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
@@ -33,6 +37,7 @@ import from DIAMETER_Types all;
import from DIAMETER_Templates all;
import from Osmocom_Types all;
import from IPL4asp_Types all;
+import from TCCConversion_Functions all;
import from Native_Functions all;
type hexstring IMSI;
@@ -66,6 +71,12 @@ type record AssociationData {
hexstring imsi optional
};
+/* represents a single DIAMETER message identified by ete_id field */
+type record ETEIDData {
+ DIAMETER_ConnHdlr comp_ref,
+ UINT32 ete_id optional
+};
+
type component DIAMETER_Emulation_CT {
/* Port facing to the UDP SUT */
port DIAMETER_CODEC_PT DIAMETER;
@@ -74,9 +85,11 @@ type component DIAMETER_Emulation_CT {
* to send where with CLIENT.send() to vc_conn */
port DIAMETER_Conn_PT DIAMETER_CLIENT;
/* currently tracked connections */
- var AssociationData SgsapAssociationTable[16];
+ var AssociationData DiameterAssocTable[256];
+ /* Forward reply messages not containing IMSI to correct client port */
+ var ETEIDData DiameterETEIDTable[256];
/* pending expected CRCX */
- var ExpectData DiameterExpectTable[8];
+ var ExpectData DiameterExpectTable[256];
/* procedure based port to register for incoming connections */
port DIAMETEREM_PROC_PT DIAMETER_PROC;
/* test port for unit data messages */
@@ -94,7 +107,10 @@ runs on DIAMETER_Emulation_CT return template PDU_DIAMETER;
type record DIAMETEROps {
DIAMETERCreateCallback create_cb,
- DIAMETERUnitdataCallback unitdata_cb
+ DIAMETERUnitdataCallback unitdata_cb,
+ /* If true, this parameter disables IMSI based routing, so that all incoming
+ * PDUs get routed to a single component connected via the DIAMETER_UNIT port. */
+ boolean raw
}
type record DIAMETER_conn_parameters {
@@ -104,7 +120,8 @@ type record DIAMETER_conn_parameters {
PortNumber local_sctp_port,
charstring origin_host,
charstring origin_realm,
- uint32_t vendor_app_id
+ uint32_t auth_app_id optional,
+ uint32_t vendor_app_id optional
}
function tr_DIAMETER_RecvFrom_R(template PDU_DIAMETER msg)
@@ -123,8 +140,8 @@ runs on DIAMETER_Emulation_CT return template DIAMETER_RecvFrom {
private function f_imsi_known(hexstring imsi)
runs on DIAMETER_Emulation_CT return boolean {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (SgsapAssociationTable[i].imsi == imsi) {
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (DiameterAssocTable[i].imsi == imsi) {
return true;
}
}
@@ -134,8 +151,8 @@ runs on DIAMETER_Emulation_CT return boolean {
private function f_comp_known(DIAMETER_ConnHdlr client)
runs on DIAMETER_Emulation_CT return boolean {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (SgsapAssociationTable[i].comp_ref == client) {
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (DiameterAssocTable[i].comp_ref == client) {
return true;
}
}
@@ -145,9 +162,9 @@ runs on DIAMETER_Emulation_CT return boolean {
private function f_comp_by_imsi(hexstring imsi)
runs on DIAMETER_Emulation_CT return DIAMETER_ConnHdlr {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (SgsapAssociationTable[i].imsi == imsi) {
- return SgsapAssociationTable[i].comp_ref;
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (DiameterAssocTable[i].imsi == imsi) {
+ return DiameterAssocTable[i].comp_ref;
}
}
setverdict(fail, "DIAMETER Association Table not found by IMSI", imsi);
@@ -157,9 +174,9 @@ runs on DIAMETER_Emulation_CT return DIAMETER_ConnHdlr {
private function f_imsi_by_comp(DIAMETER_ConnHdlr client)
runs on DIAMETER_Emulation_CT return hexstring {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (SgsapAssociationTable[i].comp_ref == client) {
- return SgsapAssociationTable[i].imsi;
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (DiameterAssocTable[i].comp_ref == client) {
+ return DiameterAssocTable[i].imsi;
}
}
setverdict(fail, "DIAMETER Association Table not found by component ", client);
@@ -169,10 +186,10 @@ runs on DIAMETER_Emulation_CT return hexstring {
private function f_imsi_table_add(DIAMETER_ConnHdlr comp_ref, hexstring imsi)
runs on DIAMETER_Emulation_CT {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (not isvalue(SgsapAssociationTable[i].imsi)) {
- SgsapAssociationTable[i].imsi := imsi;
- SgsapAssociationTable[i].comp_ref := comp_ref;
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (not isvalue(DiameterAssocTable[i].imsi)) {
+ DiameterAssocTable[i].imsi := imsi;
+ DiameterAssocTable[i].comp_ref := comp_ref;
return;
}
}
@@ -182,11 +199,11 @@ runs on DIAMETER_Emulation_CT {
private function f_imsi_table_del(DIAMETER_ConnHdlr comp_ref, hexstring imsi)
runs on DIAMETER_Emulation_CT {
var integer i;
- for (i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- if (SgsapAssociationTable[i].comp_ref == comp_ref and
- SgsapAssociationTable[i].imsi == imsi) {
- SgsapAssociationTable[i].imsi := omit;
- SgsapAssociationTable[i].comp_ref := null;
+ for (i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ if (DiameterAssocTable[i].comp_ref == comp_ref and
+ DiameterAssocTable[i].imsi == imsi) {
+ DiameterAssocTable[i].imsi := omit;
+ DiameterAssocTable[i].comp_ref := null;
return;
}
}
@@ -194,30 +211,73 @@ runs on DIAMETER_Emulation_CT {
mtc.stop;
}
-
private function f_imsi_table_init()
runs on DIAMETER_Emulation_CT {
- for (var integer i := 0; i < sizeof(SgsapAssociationTable); i := i+1) {
- SgsapAssociationTable[i].comp_ref := null;
- SgsapAssociationTable[i].imsi := omit;
+ for (var integer i := 0; i < sizeof(DiameterAssocTable); i := i+1) {
+ DiameterAssocTable[i].comp_ref := null;
+ DiameterAssocTable[i].imsi := omit;
}
}
-function f_DIAMETER_get_avp(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
-return template (omit) AVP
-{
+/* End-to-End ID table matching. */
+private function f_ete_id_known(UINT32 ete_id)
+runs on DIAMETER_Emulation_CT return boolean {
var integer i;
+ for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) {
+ if (DiameterETEIDTable[i].ete_id == ete_id) {
+ return true;
+ }
+ }
+ return false;
+}
- for (i := 0; i < lengthof(pdu.avps); i := i+1) {
- if (not ispresent(pdu.avps[i].avp)) {
- continue;
+private function f_comp_by_ete_id(UINT32 ete_id)
+runs on DIAMETER_Emulation_CT return DIAMETER_ConnHdlr {
+ var integer i;
+ for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) {
+ if (DiameterETEIDTable[i].ete_id == ete_id) {
+ return DiameterETEIDTable[i].comp_ref;
}
- var AVP_Header hdr := pdu.avps[i].avp.avp_header;
- if (match(hdr.avp_code, avp_code)) {
- return pdu.avps[i].avp;
+ }
+ setverdict(fail, "DIAMETER ETEID Table not found by ete_id", ete_id);
+ mtc.stop;
+}
+
+private function f_eteid_table_add(DIAMETER_ConnHdlr comp_ref, UINT32 ete_id)
+runs on DIAMETER_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) {
+ if (not isvalue(DiameterETEIDTable[i].ete_id)) {
+ DiameterETEIDTable[i].ete_id := ete_id;
+ DiameterETEIDTable[i].comp_ref := comp_ref;
+ return;
}
}
- return omit;
+ testcase.stop("DIAMETER ETEID Table full!");
+}
+
+private function f_eteid_table_del(DIAMETER_ConnHdlr comp_ref, UINT32 ete_id)
+runs on DIAMETER_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) {
+ if (DiameterETEIDTable[i].comp_ref == comp_ref and
+ DiameterETEIDTable[i].ete_id == ete_id) {
+ DiameterETEIDTable[i].ete_id := omit;
+ DiameterETEIDTable[i].comp_ref := null;
+ return;
+ }
+ }
+ setverdict(fail, "DIAMETER ETEID Table: Couldn't find to-be-deleted entry!");
+ mtc.stop;
+}
+
+
+private function f_eteid_table_init()
+runs on DIAMETER_Emulation_CT {
+ for (var integer i := 0; i < sizeof(DiameterETEIDTable); i := i+1) {
+ DiameterETEIDTable[i].comp_ref := null;
+ DiameterETEIDTable[i].ete_id := omit;
+ }
}
function f_DIAMETER_get_imsi(PDU_DIAMETER pdu) return template (omit) IMSI
@@ -232,13 +292,19 @@ function f_DIAMETER_get_imsi(PDU_DIAMETER pdu) return template (omit) IMSI
return omit;
}
var AVP_Grouped grp := valueof(sid_avp.avp_data.avp_DCC_NONE_Subscription_Id);
- if (not match(grp[0], tr_SubcrIdType(END_USER_IMSI))) {
+ if (not match(grp[0], tr_AVP_SubcrIdType(END_USER_IMSI))) {
return omit;
}
return str2hex(oct2char(grp[1].avp.avp_data.avp_DCC_NONE_Subscription_Id_Data));
} else {
var octetstring imsi_oct := valueof(imsi_avp.avp_data.avp_BASE_NONE_User_Name);
- return str2hex(oct2char(imsi_oct));
+ var charstring imsi_str := oct2char(imsi_oct);
+ /* Username may be a NAI instead of IMSI: "<IMSI>@nai.epc.mnc<MNC>.mcc<MCC>.3gppnetwork.org" */
+ var integer pos := f_strstr(imsi_str, "@");
+ if (pos != -1) {
+ imsi_str := substr(imsi_str, 0, pos);
+ }
+ return str2hex(imsi_str);
}
}
@@ -267,8 +333,13 @@ runs on DIAMETER_Emulation_CT return PDU_DIAMETER {
var DIAMETER_RecvFrom mrf;
DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, tx));
+ T.start;
alt {
[] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(rx_t)) -> value mrf { }
+ [] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
+ setverdict(fail, "Rx unexpected DIAMETER PDU: ", mrf);
+ mtc.stop;
+ }
[] DIAMETER.receive(tr_SctpAssocChange) { repeat; }
[] DIAMETER.receive(tr_SctpPeerAddrChange) { repeat; }
[] T.timeout {
@@ -280,13 +351,15 @@ runs on DIAMETER_Emulation_CT return PDU_DIAMETER {
}
function main(DIAMETEROps ops, DIAMETER_conn_parameters p, charstring id) runs on DIAMETER_Emulation_CT {
+ var boolean server_mode := p.remote_sctp_port == -1;
var Result res;
g_diameter_id := id;
f_imsi_table_init();
+ f_eteid_table_init();
f_expect_table_init();
map(self:DIAMETER, system:DIAMETER_CODEC_PT);
- if (p.remote_sctp_port == -1) {
+ if (server_mode) {
res := DIAMETER_CodecPort_CtrlFunct.f_IPL4_listen(DIAMETER, p.local_ip, p.local_sctp_port, { sctp := valueof(ts_SCTP) });
} else {
res := DIAMETER_CodecPort_CtrlFunct.f_IPL4_connect(DIAMETER, p.remote_ip, p.remote_sctp_port,
@@ -298,10 +371,23 @@ function main(DIAMETEROps ops, DIAMETER_conn_parameters p, charstring id) runs o
}
g_diameter_conn_id := res.connId;
+ /* If in client mode, send CER immediately */
+ if (not server_mode) {
+ var template (value) PDU_DIAMETER req;
+ var PDU_DIAMETER rsp;
+
+ req := ts_DIA_CER(f_inet_addr(p.local_ip), p.vendor_app_id,
+ orig_host := p.origin_host, orig_realm := p.origin_realm);
+ rsp := f_diameter_xceive(req, tr_DIAMETER_A(Capabilities_Exchange, req.application_id));
+ /* notify our user that the CER->CEA exchange has happened */
+ DIAMETER_UNIT.send(DiameterCapabilityExchgInd:{rx := rsp, tx := valueof(req)});
+ }
+
while (true) {
var DIAMETER_ConnHdlr vc_conn;
var template IMSI imsi_t;
var hexstring imsi;
+ var UINT32 ete_id;
var DIAMETER_RecvFrom mrf;
var PDU_DIAMETER msg;
var charstring vlr_name, mme_name;
@@ -322,17 +408,39 @@ function main(DIAMETEROps ops, DIAMETER_conn_parameters p, charstring id) runs o
/* handle CER/CEA handshake */
[] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(tr_DIAMETER_R(cmd_code := Capabilities_Exchange))) -> value mrf {
var template (value) PDU_DIAMETER resp;
- resp := ts_DIA_CEA(mrf.msg.hop_by_hop_id, mrf.msg.end_to_end_id, p.origin_host,
- p.origin_realm, f_inet_addr(p.local_ip), p.vendor_app_id);
+ resp := f_ts_DIA_CEA(mrf.msg.hop_by_hop_id, mrf.msg.end_to_end_id, p.origin_host,
+ p.origin_realm, f_inet_addr(p.local_ip), p.auth_app_id, p.vendor_app_id);
DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, resp));
/* notify our user that the CER->CEA exchange has happened */
DIAMETER_UNIT.send(DiameterCapabilityExchgInd:{rx:=mrf.msg, tx:=valueof(resp)});
}
+ /* handle DWR/DWA ping-pong */
+ [] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(tr_DIA_DWR)) -> value mrf {
+ var template (value) PDU_DIAMETER resp;
+ resp := ts_DIA_DWA('00000001'O, p.origin_host, p.origin_realm,
+ hbh_id := mrf.msg.hop_by_hop_id,
+ ete_id := mrf.msg.end_to_end_id);
+ DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, valueof(resp)));
+ }
- /* DIAMETER from remote peer */
- [] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
+ /* DIAMETER from the test suite */
+ [ops.raw] DIAMETER_UNIT.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER.send(t_DIAMETER_Send(g_diameter_conn_id, msg));
+ }
+ /* DIAMETER from remote peer (raw mode) */
+ [ops.raw] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
+ DIAMETER_UNIT.send(mrf.msg);
+ }
+ /* DIAMETER from remote peer (IMSI based routing) */
+ [not ops.raw] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf {
imsi_t := f_DIAMETER_get_imsi(mrf.msg);
- if (isvalue(imsi_t)) {
+ ete_id := mrf.msg.end_to_end_id;
+ if (f_ete_id_known(ete_id)) {
+ vc_conn := f_comp_by_ete_id(ete_id);
+ /* The ete_id is a single-time expect: */
+ f_eteid_table_del(vc_conn, ete_id);
+ DIAMETER_CLIENT.send(mrf.msg) to vc_conn;
+ } else if (isvalue(imsi_t)) {
imsi := valueof(imsi_t);
if (f_imsi_known(imsi)) {
vc_conn := f_comp_by_imsi(imsi);
@@ -352,9 +460,13 @@ function main(DIAMETEROps ops, DIAMETER_conn_parameters p, charstring id) runs o
}
[] DIAMETER.receive(tr_SctpAssocChange) { }
[] DIAMETER.receive(tr_SctpPeerAddrChange) { }
- [] DIAMETER_PROC.getcall(DIAMETEREM_register:{?,?}) -> param(imsi, vc_conn) {
+ [] DIAMETER_PROC.getcall(DIAMETEREM_register_imsi:{?,?}) -> param(imsi, vc_conn) {
f_create_expect(imsi, vc_conn);
- DIAMETER_PROC.reply(DIAMETEREM_register:{imsi, vc_conn}) to vc_conn;
+ DIAMETER_PROC.reply(DIAMETEREM_register_imsi:{imsi, vc_conn}) to vc_conn;
+ }
+ [] DIAMETER_PROC.getcall(DIAMETEREM_register_eteid:{?,?}) -> param(ete_id, vc_conn) {
+ f_eteid_table_add(vc_conn, ete_id);
+ DIAMETER_PROC.reply(DIAMETEREM_register_eteid:{ete_id, vc_conn}) to vc_conn;
}
}
@@ -362,20 +474,31 @@ function main(DIAMETEROps ops, DIAMETER_conn_parameters p, charstring id) runs o
}
}
-/* "Expect" Handling */
+/* "E2E ID Expect" Handling */
+type record ExpectDataE2EID {
+ UINT32 ete_id optional,
+ DIAMETER_ConnHdlr vc_conn
+}
+
+signature DIAMETEREM_register_eteid(in UINT32 ete_id, in DIAMETER_ConnHdlr hdlr);
+
+/* client/conn_hdlr side function to use procedure port to create expect in emulation */
+function f_diameter_expect_eteid(UINT32 ete_id) runs on DIAMETER_ConnHdlr {
+ DIAMETER_PROC.call(DIAMETEREM_register_eteid:{ete_id, self}) {
+ [] DIAMETER_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {};
+ }
+}
+
+/* "IMSI Expect" Handling */
type record ExpectData {
hexstring imsi optional,
DIAMETER_ConnHdlr vc_conn
}
-signature DIAMETEREM_register(in hexstring imsi, in DIAMETER_ConnHdlr hdlr);
+signature DIAMETEREM_register_imsi(in hexstring imsi, in DIAMETER_ConnHdlr hdlr);
-type port DIAMETEREM_PROC_PT procedure {
- inout DIAMETEREM_register;
-} with { extension "internal" };
-
-/* Function that can be used as create_cb and will usse the expect table */
+/* Function that can be used as create_cb and will use the expect table */
function ExpectedCreateCallback(PDU_DIAMETER msg, hexstring imsi, charstring id)
runs on DIAMETER_Emulation_CT return DIAMETER_ConnHdlr {
var DIAMETER_ConnHdlr ret := null;
@@ -421,9 +544,9 @@ runs on DIAMETER_Emulation_CT {
}
/* client/conn_hdlr side function to use procedure port to create expect in emulation */
-function f_diameter_expect(hexstring imsi) runs on DIAMETER_ConnHdlr {
- DIAMETER_PROC.call(DIAMETEREM_register:{imsi, self}) {
- [] DIAMETER_PROC.getreply(DIAMETEREM_register:{?,?}) {};
+function f_diameter_expect_imsi(hexstring imsi) runs on DIAMETER_ConnHdlr {
+ DIAMETER_PROC.call(DIAMETEREM_register_imsi:{imsi, self}) {
+ [] DIAMETER_PROC.getreply(DIAMETEREM_register_imsi:{?,?}) {};
}
}
@@ -441,6 +564,10 @@ runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
return omit;
}
+type port DIAMETEREM_PROC_PT procedure {
+ inout DIAMETEREM_register_imsi;
+ inout DIAMETEREM_register_eteid;
+} with { extension "internal" };
function f_diameter_wait_capability(DIAMETER_PT pt)
{
diff --git a/library/DIAMETER_Templates.ttcn b/library/DIAMETER_Templates.ttcn
index 2cc29861..71485132 100644
--- a/library/DIAMETER_Templates.ttcn
+++ b/library/DIAMETER_Templates.ttcn
@@ -9,8 +9,10 @@ module DIAMETER_Templates {
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+import from General_Types all;
import from DIAMETER_Types all;
import from Osmocom_Types all;
+import from Misc_Helpers all;
/* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml#aaa-parameters-4 */
type enumerated DIAMETER_Resultcode {
@@ -100,18 +102,19 @@ type enumerated DIAMETER_Resultcode {
DIAMETER_ERROR_EAP_CODE_UNKNOWN (5048)
};
-/* 3GPP TS 29.272 Section 7.1.8 */
-const uint32_t c_DIAMETER_3GPP_Gx_AID := 16777238;
-const uint32_t c_DIAMETER_3GPP_S6_AID := 16777251;
-const uint32_t c_DIAMETER_3GPP_S13_AID := 16777252;
+/* RFC4006 3.1 */
+const uint32_t c_DIAMETER_CREDIT_CONTROL_AID := 4;
+
const uint32_t c_DIAMETER_3GPP_S7_AID := 16777308;
+const octetstring c_def_sess_id := char2oct("ttcn3.session");
+
template (value) PDU_DIAMETER
-ts_DIAMETER(template (value) BIT8 flags,
+ts_DIAMETER(template (value) DIAMETER_Types.BIT8 flags,
template (value) Command_Code cmd_code,
template (value) OCTET4 app_id := '00000000'O,
- template (value) UINT32 hbh_id,
- template (value) UINT32 ete_id,
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O,
template (value) AVP_list avps := {}
) := {
version := 1,
@@ -124,7 +127,7 @@ ts_DIAMETER(template (value) BIT8 flags,
avps := avps
}
template (present) PDU_DIAMETER
-tr_DIAMETER(template (present) BIT8 flags := ?,
+tr_DIAMETER(template (present) DIAMETER_Types.BIT8 flags := ?,
template (present) Command_Code cmd_code := ?,
template (present) OCTET4 app_id := ?,
template (present) UINT32 hbh_id := ?,
@@ -159,7 +162,7 @@ tr_DIAMETER_R(
template (value) AVP_Header
ts_DIA_Hdr(template (value) AVP_Code avp_code,
- template (value) BIT8 flags := '01000000'B) := {
+ template (value) DIAMETER_Types.BIT8 flags := '01000000'B) := {
avp_code := avp_code,
VMPxxxxx := flags,
avp_length := 0, /* overwritten */
@@ -167,7 +170,7 @@ ts_DIA_Hdr(template (value) AVP_Code avp_code,
}
template (present) AVP_Header
tr_DIA_Hdr(template (present) AVP_Code avp_code,
- template (present) BIT8 flags := '0???????'B) := {
+ template (present) DIAMETER_Types.BIT8 flags := '0???????'B) := {
avp_code := avp_code,
VMPxxxxx := flags,
avp_length := ?, /* overwritten */
@@ -176,7 +179,7 @@ tr_DIA_Hdr(template (present) AVP_Code avp_code,
template (value) AVP_Header
ts_DIA_Hdr_3GPP(template (value) AVP_Code avp_code,
- template (value) BIT8 flags := '11000000'B) := {
+ template (value) DIAMETER_Types.BIT8 flags := '11000000'B) := {
avp_code := avp_code,
VMPxxxxx := flags,
avp_length := 0, /* overwritten */
@@ -184,14 +187,29 @@ ts_DIA_Hdr_3GPP(template (value) AVP_Code avp_code,
}
template (present) AVP_Header
tr_DIA_Hdr_3GPP(template (present) AVP_Code avp_code,
- template (present) BIT8 flags := '1???????'B) := {
+ template (present) DIAMETER_Types.BIT8 flags := '1???????'B) := {
avp_code := avp_code,
VMPxxxxx := flags,
avp_length := ?, /* overwritten */
vendor_id := vendor_id_3GPP
}
-template (present) GenericAVP tr_SubcrIdType(template (present) DCC_NONE_Subscription_Id_Type t) := {
+template (present) AVP_Address tr_AVP_Address(template (present) AddressType addr_type := ?,
+ template (present) octetstring addr_data := ?) := {
+ address_type := addr_type,
+ address_data := addr_data
+}
+
+template (present) GenericAVP tr_AVP_SubcrId(template (present) DCC_NONE_Subscription_Id t) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Subscription_Id),
+ avp_data := {
+ avp_DCC_NONE_Subscription_Id := t
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_SubcrIdType(template (present) DCC_NONE_Subscription_Id_Type t) := {
avp := {
avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Subscription_Id_Type),
avp_data := {
@@ -200,6 +218,42 @@ template (present) GenericAVP tr_SubcrIdType(template (present) DCC_NONE_Subscri
}
}
+template (present) GenericAVP tr_AVP_SubcrIdData(template (present) DCC_NONE_Subscription_Id_Data t) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Subscription_Id_Data),
+ avp_data := {
+ avp_DCC_NONE_Subscription_Id_Data := t
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_RequestedAction(template (present) DCC_NONE_Requested_Action t := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Requested_Action),
+ avp_data := {
+ avp_DCC_NONE_Requested_Action := t
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_MultipleServicesIndicator(template (present) DCC_NONE_Multiple_Services_Indicator t := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Multiple_Services_Indicator),
+ avp_data := {
+ avp_DCC_NONE_Multiple_Services_Indicator := t
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_ServiceContextId(template (present) DCC_NONE_Service_Context_Id id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Service_Context_Id),
+ avp_data := {
+ avp_DCC_NONE_Service_Context_Id := id
+ }
+ }
+}
+
template (value) GenericAVP ts_AVP_OriginHost(template (value) charstring host) := {
avp := {
avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Origin_Host),
@@ -244,6 +298,32 @@ template (value) GenericAVP ts_AVP_OriginStateId(template (value) OCTET4 state_i
}
}
}
+template (present) GenericAVP tr_AVP_OriginStateId(template (present) OCTET4 state_id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Origin_State_Id),
+ avp_data := {
+ avp_BASE_NONE_Origin_State_Id := state_id
+ }
+ }
+}
+
+template (value) GenericAVP ts_AVP_TerminationCause(template (value) BASE_NONE_Termination_Cause tc) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Termination_Cause),
+ avp_data := {
+ avp_BASE_NONE_Termination_Cause := tc
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_TerminationCause(template (present) BASE_NONE_Termination_Cause tc) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Termination_Cause),
+ avp_data := {
+ avp_BASE_NONE_Termination_Cause := tc
+ }
+ }
+}
template (value) GenericAVP ts_AVP_HostIpAddr(template (value) OCTET4 ipv4_addr) := {
avp := {
@@ -257,11 +337,29 @@ template (value) GenericAVP ts_AVP_HostIpAddr(template (value) OCTET4 ipv4_addr)
}
}
-template (value) GenericAVP ts_AVP_VendorId(Vendor_Id vendor_id) := {
+template (value) GenericAVP ts_AVP_VendorId(template (value) Vendor_Id vendor_id) := {
avp := {
avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Id, '00000000'B),
avp_data := {
- avp_BASE_NONE_Vendor_Id := int2oct(enum2int(vendor_id), 4)
+ avp_BASE_NONE_Vendor_Id := int2oct(enum2int(valueof(vendor_id)), 4)
+ }
+ }
+}
+private function f_tr_AVP_VendorId(template (present) Vendor_Id vendor_id)
+return template (present) BASE_NONE_Vendor_Id {
+ if (istemplatekind(vendor_id, "?")) {
+ return ?;
+ } else {
+ var template (present) BASE_NONE_Vendor_Id c;
+ c := int2oct(enum2int(valueof(vendor_id)), 4);
+ return c;
+ }
+}
+template (present) GenericAVP tr_AVP_VendorId(template (present) Vendor_Id vendor_id) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Id),
+ avp_data := {
+ avp_BASE_NONE_Vendor_Id := f_tr_AVP_VendorId(vendor_id)
}
}
}
@@ -293,6 +391,44 @@ template (value) GenericAVP ts_AVP_InbSecId(template (value) OCTET4 inb_sec_id)
}
}
+private function enum2int_Vendor_Id_tmpl(template Vendor_Id inp) return template integer
+{
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return enum2int(valueof(inp));
+ }
+}
+
+template (present) GenericAVP tr_AVP_VendorSpecAppId(template (present) Vendor_Id vendor_id := ?,
+ template (present) uint32_t auth_app_id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Specific_Application_Id),
+ avp_data := {
+ avp_BASE_NONE_Vendor_Specific_Application_Id := {
+ {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Id),
+ avp_data := {
+ avp_BASE_NONE_Vendor_Id := int2oct_tmpl(enum2int_Vendor_Id_tmpl(vendor_id), 4)
+ }
+ }
+ }, {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Auth_Application_Id),
+ avp_data := {
+ avp_BASE_NONE_Auth_Application_Id := int2oct_tmpl(auth_app_id, 4)
+ }
+ }
+ }
+ }
+ }
+ }
+}
template (value) GenericAVP ts_AVP_VendorSpecAppId(Vendor_Id vendor_id, uint32_t auth_app_id) := {
avp := {
avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Vendor_Specific_Application_Id),
@@ -369,8 +505,58 @@ template (present) GenericAVP tr_AVP_CcReqNum(template (present) AVP_Unsigned32
}
}
+template (present) GenericAVP tr_AVP_EventTimestamp(template (present) AVP_Unsigned32 n := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Event_Timestamp),
+ avp_data := {
+ avp_BASE_NONE_Event_Timestamp := n
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_ExperimentalResultCode(template (present) AVP_Unsigned32 n := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result_Code),
+ avp_data := {
+ avp_BASE_NONE_Experimental_Result_Code := n
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_ExperimentalResultCode(template (value) AVP_Unsigned32 n) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result_Code),
+ avp_data := {
+ avp_BASE_NONE_Experimental_Result_Code := n
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_ExperimentalResult(template (present) Vendor_Id vendor_id := ?,
+ template (present) AVP_Unsigned32 err_code := ?
+ ) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result),
+ avp_data := {
+ avp_BASE_NONE_Experimental_Result := {
+ tr_AVP_VendorId(vendor_id),
+ tr_AVP_ExperimentalResultCode(err_code)
+ }
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_ExperimentalResult(template (value) Vendor_Id vendor_id := vendor_id_3GPP,
+ template (value) AVP_Unsigned32 err_code
+ ) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Experimental_Result),
+ avp_data := {
+ avp_BASE_NONE_Experimental_Result := {
+ ts_AVP_VendorId(vendor_id),
+ ts_AVP_ExperimentalResultCode(err_code)
+ }
+ }
+ }
+}
template (value) GenericAVP ts_AVP_SuppVendorIdRaw(uint32_t vendor_id) := {
avp := {
@@ -383,11 +569,29 @@ template (value) GenericAVP ts_AVP_SuppVendorIdRaw(uint32_t vendor_id) := {
template (value) GenericAVP ts_AVP_SuppVendorId(Vendor_Id vendor_id) :=
ts_AVP_SuppVendorIdRaw(enum2int(vendor_id));
-template (value) GenericAVP ts_AVP_ResultCode(DIAMETER_Resultcode res_code) := {
+template (value) GenericAVP ts_AVP_ResultCode(template (value) DIAMETER_Resultcode res_code) := {
avp := {
avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Result_Code),
avp_data := {
- avp_BASE_NONE_Result_Code := int2oct(enum2int(res_code), 4)
+ avp_BASE_NONE_Result_Code := int2oct(enum2int(valueof(res_code)), 4)
+ }
+ }
+}
+private function f_tr_DIAMETER_Resultcode(template (present) DIAMETER_Resultcode res_code)
+return template (present) BASE_NONE_Result_Code {
+ if (istemplatekind(res_code, "?")) {
+ return ?;
+ } else {
+ var template (present) BASE_NONE_Result_Code c;
+ c := int2oct(enum2int(valueof(res_code)), 4);
+ return c;
+ }
+}
+template (present) GenericAVP tr_AVP_ResultCode(template (present) DIAMETER_Resultcode res_code) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Result_Code),
+ avp_data := {
+ avp_BASE_NONE_Result_Code := f_tr_DIAMETER_Resultcode(res_code)
}
}
}
@@ -426,6 +630,23 @@ template (present) GenericAVP tr_AVP_SessionId(template (present) octetstring se
}
}
+template (value) GenericAVP ts_AVP_DestinationHost(template (value) charstring dest_host) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Destination_Host),
+ avp_data := {
+ avp_BASE_NONE_Destination_Host := dest_host
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_DestinationHost(template (present) charstring host := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Destination_Host),
+ avp_data := {
+ avp_BASE_NONE_Destination_Host := host
+ }
+ }
+}
+
/* 3.3 Destination Realm */
template (value) GenericAVP ts_AVP_DestinationRealm(template (value) charstring dest_realm) := {
avp := {
@@ -461,376 +682,536 @@ template (present) GenericAVP tr_AVP_UserName(template (present) octetstring uid
}
}
}
-template (value) GenericAVP ts_AVP_UserNameImsi(hexstring imsi) := ts_AVP_UserName(char2oct(hex2str(imsi)));
-template (present) GenericAVP tr_AVP_UserNameImsi(hexstring imsi) := tr_AVP_UserName(char2oct(hex2str(imsi)));
+template (value) GenericAVP ts_AVP_UserNameImsi(template (value) hexstring imsi) := ts_AVP_UserName(char2oct(hex2str(valueof(imsi))));
+template (present) GenericAVP tr_AVP_UserNameImsi(template (present) hexstring imsi := ?) := tr_AVP_UserName(char2oct_tmpl(hex2str_tmpl(imsi)));
+template (value) GenericAVP ts_AVP_NumOfReqVectors(template (value) UINT32 num_req := '00000004'O) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Number_Of_Requested_Vectors),
+ avp_data := {
+ avp_AAA_3GPP_Number_Of_Requested_Vectors := num_req
+ }
+ }
+}
-/* TS 29.262 7.3.53 RAND */
-template (value) GenericAVP ts_AVP_RAND(template (value) octetstring rand) := {
+template (value) GenericAVP ts_AVP_ImmReqPref(template (value) UINT32 par := '00000000'O) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_RAND),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Immediate_Response_Preferred),
avp_data := {
- avp_AAA_3GPP_RAND := rand
+ avp_AAA_3GPP_Immediate_Response_Preferred := par
}
}
}
-/* TS 29.262 7.3.54 XRES */
-template (value) GenericAVP ts_AVP_XRES(template (value) octetstring xres) := {
+
+/* 7.3.11 Requested-EUTRAN-Authentication-Info */
+template (value) GenericAVP ts_AVP_RequestedEutranAuthInfo(template (value) UINT32 num_vec := '00000004'O) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_XRES),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Requested_EUTRAN_Authentication_Info),
avp_data := {
- avp_AAA_3GPP_XRES := xres
+ avp_AAA_3GPP_Requested_EUTRAN_Authentication_Info := {
+ ts_AVP_NumOfReqVectors(num_vec),
+ ts_AVP_ImmReqPref('00000000'O)
+ }
}
}
}
-/* TS 29.262 7.3.55 XRES */
-template (value) GenericAVP ts_AVP_AUTN(template (value) octetstring autn) := {
+template (present) GenericAVP tr_AVP_3GPP_SubscrRauTauTmr(template (present) uint32_t tmr := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AUTN),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer),
avp_data := {
- avp_AAA_3GPP_AUTN := autn
+ avp_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer := int2oct_tmpl(tmr, 4)
}
}
}
-/* TS 29.262 7.3.56 KASME */
-template (value) GenericAVP ts_AVP_KASME(template (value) octetstring kasme) := {
+template (value) GenericAVP ts_AVP_3GPP_SubscrRauTauTmr(uint32_t tmr) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer),
avp_data := {
- avp_AAA_3GPP_KASME := kasme
+ avp_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer := int2oct(tmr, 4)
}
}
}
-/* TS 29.262 7.3.23 Item-Number */
-template (value) GenericAVP ts_AVP_ItemNumber(uint32_t num) := {
+template (present) GenericAVP tr_AVP_PCC_3GPP_QoS_Information(template (present) AVP_list list := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_QoS_Information),
avp_data := {
- avp_AAA_3GPP_Item_Number := int2oct(num, 4)
+ avp_PCC_3GPP_QoS_Information := list
}
}
}
-/* TS 29.262 7.3.18 E-UTRAN Vector */
-template (value) GenericAVP ts_AVP_EutranVec(uint32_t item_num, octetstring rand, octetstring xres,
- octetstring autn, octetstring kasme) := {
+template (value) GenericAVP ts_AVP_PCC_3GPP_QoS_Information(template (value) AVP_list list) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_E_UTRAN_Vector),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_QoS_Information),
avp_data := {
- avp_AAA_3GPP_E_UTRAN_Vector := {
- ts_AVP_ItemNumber(item_num),
- ts_AVP_RAND(rand),
- ts_AVP_XRES(xres),
- ts_AVP_AUTN(autn),
- ts_AVP_KASME(kasme)
- }
+ avp_PCC_3GPP_QoS_Information := list
}
}
}
-/* TS 29.262 7.3.2 Subscription-Data */
-template (value) GenericAVP ts_AVP_3GPP_SubscriptionData(template (value) AVP_list content) := {
+template (value) GenericAVP ts_AVP_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL(uint32_t val) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscription_Data),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL),
avp_data := {
- avp_AAA_3GPP_Subscription_Data := content
+ avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL := int2oct(val, 4)
}
}
}
+template (value) GenericAVP ts_AVP_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL(uint32_t val) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL),
+ avp_data := {
+ avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL := int2oct(val, 4)
+ }
+ }
+}
-/* TS 29.262 7.3.17 Authentication-Info */
-template (value) GenericAVP ts_AVP_3GPP_AuthInfo(template (value) AVP_list content) := {
+template (value) GenericAVP ts_AVP_PCC_3GPP_Default_EPS_Bearer_QoS(template (value) AVP_list list) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Authentication_Info),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Default_EPS_Bearer_QoS),
avp_data := {
- avp_AAA_3GPP_Authentication_Info := content
+ avp_PCC_3GPP_Default_EPS_Bearer_QoS := list
}
}
}
-/* TS 29.262 7.3.9 Visited-PLMN-Id */
-template (value) GenericAVP ts_AVP_3GPP_VisitedPlmnId(template (value) octetstring id) := {
+template (present) GenericAVP tr_AVP_PCC_3GPP_QoS_Class_Identifier(template (present) uint32_t val := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_QoS_Class_Identifier),
avp_data := {
- avp_AAA_3GPP_Visited_PLMN_Id := id
+ avp_PCC_3GPP_QoS_Class_Identifier := int2oct_tmpl(val, 4)
}
}
}
-template (present) GenericAVP tr_AVP_3GPP_VisitedPlmnId(template (present) octetstring id := ?) := {
+
+template (value) GenericAVP ts_AVP_PCC_3GPP_QoS_Class_Identifier(uint32_t val) := {
avp := {
- avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_QoS_Class_Identifier),
avp_data := {
- avp_AAA_3GPP_Visited_PLMN_Id := id
+ avp_PCC_3GPP_QoS_Class_Identifier := int2oct(val, 4)
}
}
}
-/* TS 29.262 7.3.13 RAT-Type */
-template (value) GenericAVP ts_AVP_3GPP_RatType(template (value) PCC_3GPP_RAT_Type rat_type) := {
+template (present) GenericAVP tr_AVP_3GPP_PriorityLevel(template (present) uint32_t prio := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Priority_Level),
avp_data := {
- avp_PCC_3GPP_RAT_Type := rat_type
+ avp_PCC_3GPP_Priority_Level := int2oct_tmpl(prio, 4)
}
}
}
-template (present) GenericAVP tr_AVP_3GPP_RatType(template (present) PCC_3GPP_RAT_Type rat_type := ?) := {
+
+template (value) GenericAVP ts_AVP_3GPP_PriorityLevel(uint32_t prio) := {
avp := {
- avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Priority_Level),
avp_data := {
- avp_PCC_3GPP_RAT_Type := rat_type
+ avp_PCC_3GPP_Priority_Level := int2oct(prio, 4)
}
}
}
-/* TS 29.262 7.3.7 ULR-Flags */
-template (value) GenericAVP ts_AVP_3GPP_UlrFlags(template (value) UINT32 flags) := {
+template (present) GenericAVP tr_AVP_PCC_3GPP_AllocRetenPrio(template (present) uint32_t prio := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Allocation_Retention_Priority),
avp_data := {
- avp_AAA_3GPP_ULR_Flags := flags
+ avp_PCC_3GPP_Allocation_Retention_Priority := superset(
+ tr_AVP_3GPP_PriorityLevel(prio)
+ /* pre-emption capability */
+ /* pre-emption vulnerability */
+ )
}
}
}
-template (present) GenericAVP tr_AVP_3GPP_UlrFlags(template (present) UINT32 flags := ?) := {
+template (value) GenericAVP ts_AVP_PCC_3GPP_AllocRetenPrio(uint32_t prio) := {
avp := {
- avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Allocation_Retention_Priority),
avp_data := {
- avp_AAA_3GPP_ULR_Flags := flags
+ avp_PCC_3GPP_Allocation_Retention_Priority := {
+ ts_AVP_3GPP_PriorityLevel(prio)
+ /* pre-emption capability */
+ /* pre-emption vulnerability */
+ }
}
}
}
-/* TS 29.262 7.3.8 ULA-Flags */
-template (value) GenericAVP ts_AVP_3GPP_UlaFlags(template (value) UINT32 flags) := {
+/* 7.3.37 EPS-Subscribed-QoS-Profile */
+template (present) GenericAVP tr_AVP_3GPP_EpsSubscrQosProfile(template (present) uint32_t qos_class := ?,
+ template (present) uint32_t prio := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_EPS_Subscribed_QoS_Profile),
avp_data := {
- avp_AAA_3GPP_ULA_Flags := flags
+ avp_AAA_3GPP_EPS_Subscribed_QoS_Profile := superset(
+ tr_AVP_PCC_3GPP_QoS_Class_Identifier(qos_class),
+ tr_AVP_PCC_3GPP_AllocRetenPrio(prio)
+ )
}
}
}
-template (present) GenericAVP tr_AVP_3GPP_UlaFlags(template (present) UINT32 flags := ?) := {
+
+template (value) GenericAVP ts_AVP_3GPP_EpsSubscrQosProfile(uint32_t qos_class, uint32_t prio) := {
avp := {
- avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_EPS_Subscribed_QoS_Profile),
avp_data := {
- avp_AAA_3GPP_ULA_Flags := flags
+ avp_AAA_3GPP_EPS_Subscribed_QoS_Profile := {
+ ts_AVP_PCC_3GPP_QoS_Class_Identifier(qos_class),
+ ts_AVP_PCC_3GPP_AllocRetenPrio(prio)
+ }
}
}
}
+template (present) GenericAVP tr_AVP_3GPP_Reporting_Reason(template (present) DCA_3GPP_Reporting_Reason r := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_Reporting_Reason),
+ avp_data := {
+ avp_DCA_3GPP_Reporting_Reason := r
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_3GPP_AoCRequestType(template (present) DCA_3GPP_AoC_Request_Type t := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_AoC_Request_Type),
+ avp_data := {
+ avp_DCA_3GPP_AoC_Request_Type := t
+ }
+ }
+}
-template (value) GenericAVP ts_AVP_NumOfReqVectors(template (value) UINT32 num_req := '00000004'O) := {
+template (present) GenericAVP tr_AVP_3GPP_ServiceInformation(template (present) AVP_list content := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Number_Of_Requested_Vectors),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_Service_Information),
avp_data := {
- avp_AAA_3GPP_Number_Of_Requested_Vectors := num_req
+ avp_DCA_3GPP_Service_Information := content
}
}
}
-template (value) GenericAVP ts_AVP_ImmReqPref(template (value) UINT32 par := '00000000'O) := {
+template (present) GenericAVP tr_AVP_3GPP_PSInformation(template (present) AVP_list content := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Immediate_Response_Preferred),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_PS_Information),
avp_data := {
- avp_AAA_3GPP_Immediate_Response_Preferred := par
+ avp_DCA_3GPP_PS_Information := content
}
}
}
+template (present) GenericAVP tr_AVP_3GPP_ChargingId(template (present) AVP_OctetString id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_Charging_Id),
+ avp_data := {
+ avp_GI_3GPP_3GPP_Charging_Id := id
+ }
+ }
+}
-/* 7.3.11 Requested-EUTRAN-Authentication-Info */
-template (value) GenericAVP ts_AVP_RequestedEutranAuthInfo(template (value) UINT32 num_vec := '00000004'O) := {
+template (present) GenericAVP tr_AVP_3GPP_PDPType(template (present) GI_3GPP_3GPP_PDP_Type t := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Requested_EUTRAN_Authentication_Info),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_PDP_Type),
avp_data := {
- avp_AAA_3GPP_Requested_EUTRAN_Authentication_Info := {
- ts_AVP_NumOfReqVectors(num_vec),
- ts_AVP_ImmReqPref('00000000'O)
- }
+ avp_GI_3GPP_3GPP_PDP_Type := t
}
}
}
+template (present) GenericAVP tr_AVP_3GPP_PDPAddress(template (present) DCA_3GPP_PDP_Address addr := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_PDP_Address),
+ avp_data := {
+ avp_DCA_3GPP_PDP_Address := addr
+ }
+ }
+}
-/* TS 29.262 7.3.27 Context-Identifier */
-template (value) GenericAVP ts_AVP_3GPP_ContextId(uint32_t ctx) := {
+template (present) GenericAVP tr_AVP_3GPP_SGSNAddress(template (present) DCA_3GPP_SGSN_Address addr := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Context_Identifier),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_SGSN_Address),
avp_data := {
- avp_AAA_3GPP_Context_Identifier := int2oct(ctx, 4)
+ avp_DCA_3GPP_SGSN_Address := addr
}
}
}
-/* Ts 29.262 7.3.29 Subscriber-Status */
-template (value) GenericAVP ts_AVP_3GPP_SubscriberStatus(template (value) AAA_3GPP_Subscriber_Status sts) := {
+template (present) GenericAVP tr_AVP_3GPP_GGSNAddress(template (present) DCA_3GPP_GGSN_Address addr := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscriber_Status),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_GGSN_Address),
avp_data := {
- avp_AAA_3GPP_Subscriber_Status := sts
+ avp_DCA_3GPP_GGSN_Address := addr
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_SubscrRauTauTmr(uint32_t tmr) := {
+template (present) GenericAVP tr_AVP_3GPP_SelectionMode(template (present) GI_3GPP_3GPP_Selection_Mode sm := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_Selection_Mode),
avp_data := {
- avp_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer := int2oct(tmr, 4)
+ avp_GI_3GPP_3GPP_Selection_Mode := sm
}
}
}
-/* TS 29.262 7.3.33 All-APN-Configurations-Included-Indicator */
-template (value) GenericAVP ts_AVP_3GPP_AllApnConfigsIncl(template (value) AAA_3GPP_All_APN_Configurations_Included_Indicator ind := All_APN_CONFIGURATIONS_INCLUDED) := {
+template (present) GenericAVP tr_AVP_3GPP_ChargingCharacteristics(template (present) GI_3GPP_3GPP_Charging_Characteristics cc := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_Charging_Characteristics),
avp_data := {
- avp_AAA_3GPP_All_APN_Configurations_Included_Indicator := ind
+ avp_GI_3GPP_3GPP_Charging_Characteristics := cc
}
}
}
-/* TS 29.262 7.3.34 APN-Configuration-Profile */
-template (value) GenericAVP ts_AVP_3GPP_ApnConfigProfile(template (value) AVP_list content) := {
+template (present) GenericAVP tr_AVP_3GPP_SGSNMCCMNC(template (present) GI_3GPP_3GPP_SGSN_MCC_MNC smn := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_SGSN_MCC_MNC),
avp_data := {
- avp_AAA_3GPP_APN_Configuration_Profile := content
+ avp_GI_3GPP_3GPP_SGSN_MCC_MNC := smn
}
}
}
-/* TS 29.262 7.3.35 APN-Configuration */
-template (value) GenericAVP ts_AVP_3GPP_ApnConfig(uint32_t ctx, AAA_3GPP_PDN_Type pdn_type,
- charstring apn) := {
+template (present) GenericAVP tr_AVP_3GPP_NSAPI(template (present) GI_3GPP_3GPP_NSAPI nsapi := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_NSAPI),
avp_data := {
- avp_AAA_3GPP_APN_Configuration := {
- ts_AVP_3GPP_ContextId(ctx),
- ts_AVP_3GPP_PdnType(pdn_type),
- ts_AVP_3GPP_EpsSubscrQosProfile(1, 1),
- ts_AVP_ServiceSelection(apn)
- }
+ avp_GI_3GPP_3GPP_NSAPI := nsapi
}
}
}
-/* TS 29.262 7.3.36 Service-Selection (refers to RFC 5778) */
-template (value) GenericAVP ts_AVP_ServiceSelection(charstring apn) := {
+template (present) GenericAVP tr_AVP_3GPP_MS_TimeZone(template (present) GI_3GPP_3GPP_MS_TimeZone ms_tz := ?) := {
avp := {
- avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv6_NONE_Service_Selection),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_MS_TimeZone),
avp_data := {
- avp_MIPv6_NONE_Service_Selection := char2oct(apn)
+ avp_GI_3GPP_3GPP_MS_TimeZone := ms_tz
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_QosClassId(uint32_t id) := {
+template (present) GenericAVP tr_AVP_3GPP_ULI(template (present) GI_3GPP_3GPP_User_Location_Info uli := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_QoS_Class_Identifier),
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_User_Location_Info),
avp_data := {
- avp_PCC_3GPP_QoS_Class_Identifier := int2oct(id, 4)
+ avp_GI_3GPP_3GPP_User_Location_Info := uli
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_PriorityLevel(uint32_t prio) := {
+template (present) GenericAVP tr_AVP_UserEquipmentInfo(template (present) DCC_NONE_User_Equipment_Info uei := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Priority_Level),
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_User_Equipment_Info),
avp_data := {
- avp_PCC_3GPP_Priority_Level := int2oct(prio, 4)
+ avp_DCC_NONE_User_Equipment_Info := uei
}
}
}
+template (present) GenericAVP tr_AVP_UserEquipmentInfoType(template (present) DCC_NONE_User_Equipment_Info_Type ueit := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_User_Equipment_Info_Type),
+ avp_data := {
+ avp_DCC_NONE_User_Equipment_Info_Type := ueit
+ }
+ }
+}
-template (value) GenericAVP ts_AVP_3GPP_AllocRetenPrio(uint32_t prio) := {
+template (present) GenericAVP tr_AVP_UserEquipmentInfoValue(template (present) DCC_NONE_User_Equipment_Info_Value ueiv := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_Allocation_Retention_Priority),
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_User_Equipment_Info_Value),
avp_data := {
- avp_PCC_3GPP_Allocation_Retention_Priority := {
- ts_AVP_3GPP_PriorityLevel(prio)
- /* pre-emption capability */
- /* pre-emption vulnerability */
- }
+ avp_DCC_NONE_User_Equipment_Info_Value := ueiv
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_EpsSubscrQosProfile(uint32_t qos_class, uint32_t prio) := {
+/* RFC4006 8.16 Multiple-Services-Credit-Control AVP */
+template (value) GenericAVP ts_AVP_Multiple_Services_Credit_Control(template (value) AVP_list content) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_EPS_Subscribed_QoS_Profile),
+ avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control),
avp_data := {
- avp_AAA_3GPP_EPS_Subscribed_QoS_Profile := {
- ts_AVP_3GPP_QosClassId(qos_class),
- ts_AVP_3GPP_AllocRetenPrio(prio)
- }
+ avp_DCC_NONE_Multiple_Services_Credit_Control := content
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_Multiple_Services_Credit_Control(template (present) AVP_list content := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control),
+ avp_data := {
+ avp_DCC_NONE_Multiple_Services_Credit_Control := content
}
}
}
+/* Requested-Service-Unit AVP */
+template (present) GenericAVP tr_AVP_Requested_Service_Unit(template (present) AVP_list content := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Requested_Service_Unit),
+ avp_data := {
+ avp_DCC_NONE_Requested_Service_Unit := content
+ }
+ }
+}
-/* TS 29.262 7.3.41 AMBR */
-template (value) GenericAVP ts_AVP_3GPP_AMBR(uint32_t ul, uint32_t dl) := {
+/* Used-Service-Unit AVP */
+template (present) GenericAVP tr_AVP_Used_Service_Unit(template (present) AVP_list content := ?) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AMBR),
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DCC_NONE_Used_Service_Unit),
avp_data := {
- avp_AAA_3GPP_AMBR := {
- ts_AVP_3GPP_MaxReqBwUL(ul),
- ts_AVP_3GPP_MaxReqBwDL(dl)
- }
+ avp_DCC_NONE_Used_Service_Unit := content
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_MaxReqBwUL(uint32_t bw) := {
+/* RFC4006 8.17 Granted-Service-Unit AVP */
+template (value) GenericAVP ts_AVP_Granted_Service_Unit(template (value) AVP_list content) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL),
+ avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_Granted_Service_Unit),
avp_data := {
- avp_RX_3GPP_Max_Requested_Bandwidth_UL := int2oct(bw, 4)
+ avp_DCC_NONE_Granted_Service_Unit := content
}
}
}
-template (value) GenericAVP ts_AVP_3GPP_MaxReqBwDL(uint32_t bw) := {
+/* RFC4006 8.21 CC-Time AVP */
+template (value) GenericAVP ts_AVP_CC_Time(uint32_t cc_time_val) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL),
+ avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Time),
avp_data := {
- avp_RX_3GPP_Max_Requested_Bandwidth_DL := int2oct(bw, 4)
+ avp_DCC_NONE_CC_Time := int2oct(cc_time_val, 4)
}
}
}
+/* RFC4006 8.23 CC-Total-Octets AVP */
+template (value) GenericAVP ts_AVP_CC_Total_Octets(uint64_t cc_total_octets_val) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_CC_Total_Octets),
+ avp_data := {
+ avp_DCC_NONE_CC_Total_Octets := int2oct(cc_total_octets_val, 8)
+ }
+ }
+}
+/* RFC4006 8.33 Validity-Time AVP */
+template (value) GenericAVP ts_AVP_Validity_Time(uint32_t validity_time_val) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_DCC_NONE_Validity_Time),
+ avp_data := {
+ avp_DCC_NONE_Validity_Time := int2oct(validity_time_val, 4)
+ }
+ }
+}
-/* TS 29.262 7.3.62 PDN-Type */
-template (value) GenericAVP ts_AVP_3GPP_PdnType(template (value) AAA_3GPP_PDN_Type pdn_type) := {
+template (value) GenericAVP ts_AVP_3GPP_VolumeQuotaThreshold(uint32_t volume_quota_thresh_val) := {
avp := {
- avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_PDN_Type),
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_DCA_3GPP_Volume_Quota_Threshold),
avp_data := {
- avp_AAA_3GPP_PDN_Type := pdn_type
+ avp_DCA_3GPP_Volume_Quota_Threshold := int2oct(volume_quota_thresh_val, 4)
}
}
}
+template (present) GenericAVP tr_AVP_3GPP_CalledStationId(template (present) DNAS_NONE_Called_Station_Id id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_DNAS_NONE_Called_Station_Id),
+ avp_data := {
+ avp_DNAS_NONE_Called_Station_Id := id
+ }
+ }
+}
+
+/* RFC6733 8.7. Auth-Request-Type AVP */
+template (value) GenericAVP ts_AVP_AuthRequestType(BASE_NONE_Auth_Request_Type auth_req_type) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Auth_Request_Type, '00000000'B),
+ avp_data := {
+ avp_BASE_NONE_Auth_Request_Type := auth_req_type
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_AuthRequestType(template (present) BASE_NONE_Auth_Request_Type auth_req_type) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Auth_Request_Type),
+ avp_data := {
+ avp_BASE_NONE_Auth_Request_Type := auth_req_type
+ }
+ }
+}
+
+/* RFC6733 8.12. Re-Auth-Request-Type AVP */
+template (value) GenericAVP ts_AVP_ReAuthRequestType(BASE_NONE_Re_Auth_Request_Type reauth_req_type) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Re_Auth_Request_Type, '00000000'B),
+ avp_data := {
+ avp_BASE_NONE_Re_Auth_Request_Type := reauth_req_type
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_ReAuthRequestType(template (present) BASE_NONE_Re_Auth_Request_Type reauth_req_type) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_BASE_NONE_Re_Auth_Request_Type),
+ avp_data := {
+ avp_BASE_NONE_Re_Auth_Request_Type := reauth_req_type
+ }
+ }
+}
+
+/* 5.3.1 Capabilities Exchange Request */
+template (value) PDU_DIAMETER
+ts_DIA_CER(octetstring host_ip, uint32_t vendor_app_id,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '10000000'B,
+ cmd_code := Capabilities_Exchange,
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_HostIpAddr(host_ip),
+ ts_AVP_VendorId(vendor_id_3GPP),
+ ts_AVP_ProductName("TTCN-3 Testsuite"),
+ ts_AVP_FwRevision('00000000'O),
+ ts_AVP_InbSecId('00000000'O),
+ ts_AVP_AuthAppId('FFFFFFFF'O),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, vendor_app_id)
+ });
/* 5.3.2 Capabilities Exchange Answer */
template (value) PDU_DIAMETER
-ts_DIA_CEA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
- template (value) charstring origin_host, template (value) charstring origin_realm,
- template (value) octetstring host_ip, uint32_t vendor_app_id)
+ts_DIA_CEA_AUTH_APP_ID(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) charstring origin_host,
+ template (value) charstring origin_realm,
+ template (value) octetstring host_ip, uint32_t auth_app_id)
+:= ts_DIAMETER(flags:='00000000'B, cmd_code:=Capabilities_Exchange, hbh_id:=hbh_id, ete_id:=ete_id,
+ avps := {
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost(origin_host),
+ ts_AVP_OriginRealm(origin_realm),
+ ts_AVP_HostIpAddr(host_ip),
+ ts_AVP_VendorId(vendor_id_3GPP),
+ ts_AVP_ProductName("TTCN-3 Testsuite"),
+ ts_AVP_OriginStateId('00000001'O),
+ ts_AVP_SuppVendorIdRaw(5535), /* 3GPP2 */
+ ts_AVP_SuppVendorId(vendor_id_3GPP),
+ ts_AVP_SuppVendorIdRaw(13019), /* ETSI */
+ ts_AVP_AuthAppId(int2oct(auth_app_id, 4)),
+ ts_AVP_InbSecId('00000000'O)
+ });
+template (value) PDU_DIAMETER
+ts_DIA_CEA_VENDOR_APP_ID(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) charstring origin_host,
+ template (value) charstring origin_realm,
+ template (value) octetstring host_ip, uint32_t vendor_app_id)
:= ts_DIAMETER(flags:='00000000'B, cmd_code:=Capabilities_Exchange, hbh_id:=hbh_id, ete_id:=ete_id,
avps := {
ts_AVP_ResultCode(DIAMETER_SUCCESS),
@@ -843,124 +1224,315 @@ ts_DIA_CEA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
ts_AVP_SuppVendorIdRaw(5535), /* 3GPP2 */
ts_AVP_SuppVendorId(vendor_id_3GPP),
ts_AVP_SuppVendorIdRaw(13019), /* ETSI */
- ts_AVP_AuthAppId('FFFFFFFF'O),
ts_AVP_InbSecId('00000000'O),
ts_AVP_VendorSpecAppId(vendor_id_3GPP, vendor_app_id)
});
+function f_ts_DIA_CEA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) charstring origin_host,
+ template (value) charstring origin_realm,
+ template (value) octetstring host_ip, template (omit) uint32_t auth_app_id,
+ template (omit) uint32_t vendor_app_id)
+ return template (value) PDU_DIAMETER
+{
+ var template (value) PDU_DIAMETER diam_pdu;
+ if (istemplatekind(vendor_app_id, "omit")) {
+ diam_pdu := ts_DIA_CEA_AUTH_APP_ID(hbh_id, ete_id, origin_host, origin_realm, host_ip, valueof(auth_app_id));
+ } else {
+ diam_pdu := ts_DIA_CEA_VENDOR_APP_ID(hbh_id, ete_id, origin_host, origin_realm, host_ip, valueof(vendor_app_id));
+ }
+ return diam_pdu;
+}
-
+/* RFC 6733, section 5.5.1 "Device-Watchdog-Request" */
template (value) PDU_DIAMETER
-ts_DIA_AIR(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
- template (value) octetstring sess_id,
- template (value) charstring dest_realm, hexstring imsi)
-:= ts_DIAMETER(flags:='00000000'B, cmd_code:=Authentication_Information, hbh_id:=hbh_id, ete_id:=ete_id,
- avps := {
- ts_AVP_SessionId(sess_id),
- ts_AVP_DestinationRealm(dest_realm),
- ts_AVP_UserNameImsi(imsi),
- /* Requested EUTRAN Auth Info */
- ts_AVP_RequestedEutranAuthInfo,
- ts_AVP_3GPP_VisitedPlmnId('11111F'O)
+ts_DIA_DWR(template (value) OCTET4 state_id := '00000000'O,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '10000000'B,
+ cmd_code := Device_Watchdog,
+ app_id := '00000000'O,
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_OriginStateId(state_id)
});
-
template (present) PDU_DIAMETER
-tr_DIA_AIR(hexstring imsi) := tr_DIAMETER(flags := '11000000'B, cmd_code:=Authentication_Information,
- app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
- avps := superset(
- tr_AVP_SessionId,
- tr_AVP_DestinationRealm,
- tr_AVP_UserNameImsi(imsi),
- tr_AVP_3GPP_VisitedPlmnId
+tr_DIA_DWR(template (present) OCTET4 state_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Device_Watchdog,
+ app_id := '00000000'O,
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ /* tr_AVP_OriginStateId(state_id) is optional */
));
-/* TS 29.262 5.2.3.1 + 7.2.6 Authentication Information Answer */
+/* RFC 6733, section 5.5.2 "Device-Watchdog-Answer" */
template (value) PDU_DIAMETER
-ts_DIA_AIA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
- template (value) octetstring sess_id,
- template (value) AVP_list auth_info_contents)
-:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Authentication_Information,
- app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
- avps := {
- ts_AVP_SessionId(sess_id),
- ts_AVP_ResultCode(DIAMETER_SUCCESS),
- ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
- ts_AVP_OriginHost("hss.localdomain"),
- ts_AVP_OriginRealm("localdomain"),
- ts_AVP_3GPP_AuthInfo(auth_info_contents)
+ts_DIA_DWA(template (value) OCTET4 state_id := '00000000'O,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '00000000'B,
+ cmd_code := Device_Watchdog,
+ app_id := '00000000'O,
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_OriginStateId(state_id)
});
-
-
-/* TS 29.262 7.2.3 Update Location Request */
template (present) PDU_DIAMETER
-tr_DIA_ULR(hexstring imsi) := tr_DIAMETER(flags:='11000000'B, cmd_code:=Update_Location,
- app_id:=int2oct(c_DIAMETER_3GPP_S6_AID, 4),
- avps := superset(
- tr_AVP_SessionId,
- tr_AVP_AuthSessionState,
- tr_AVP_OriginHost,
- tr_AVP_OriginRealm,
- tr_AVP_DestinationRealm,
- tr_AVP_UserNameImsi(imsi),
- tr_AVP_3GPP_RatType(EUTRAN),
- tr_AVP_3GPP_UlrFlags,
- tr_AVP_3GPP_VisitedPlmnId
+tr_DIA_DWA(template (present) OCTET4 state_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Device_Watchdog,
+ app_id := '00000000'O,
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ /* tr_AVP_OriginStateId(state_id) is optional */
));
-template (value) PDU_DIAMETER
-ts_DIA_ULA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
- template (value) octetstring sess_id,
- template (value) AVP_list sub_data_content)
-:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Update_Location,
- app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
- avps := {
- ts_AVP_SessionId(sess_id),
- ts_AVP_ResultCode(DIAMETER_SUCCESS), /* optional */
- ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
- ts_AVP_OriginHost("hss.localdomain"),
- ts_AVP_OriginRealm("localdomain"),
- ts_AVP_3GPP_UlaFlags('00000002'O),
- ts_AVP_3GPP_SubscriptionData(sub_data_content)
- });
+function f_DIAMETER_get_avp(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
+return template (omit) AVP
+{
+ var integer i;
+ for (i := 0; i < lengthof(pdu.avps); i := i+1) {
+ if (not ispresent(pdu.avps[i].avp)) {
+ continue;
+ }
+ var AVP_Header hdr := pdu.avps[i].avp.avp_header;
+ if (match(hdr.avp_code, avp_code)) {
+ return pdu.avps[i].avp;
+ }
+ }
+ return omit;
+}
+function f_DIAMETER_get_avp_or_fail(PDU_DIAMETER pdu, template (present) AVP_Code avp_code)
+return AVP
+{
+ var template (omit) AVP avp;
+ avp := f_DIAMETER_get_avp(pdu, avp_code);
+ if (istemplatekind(avp, "omit")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("AVP ", avp_code, " not found in ", pdu));
+ }
+ return valueof(avp);
+}
+function f_AVP_Grouped_get_avp(AVP_Grouped avp_grp, template (present) AVP_Code avp_code)
+return template (omit) AVP
+{
+ var integer i;
-/* RFC 4006 3.1. Credit-Control-Request (CCR) Command */
-template (present) PDU_DIAMETER
-tr_DIA_CCR(template (present) DCC_NONE_CC_Request_Type req_type := INITIAL_REQUEST)
-:= tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
- app_id:=int2oct(c_DIAMETER_3GPP_Gx_AID, 4),
- avps := superset(
- tr_AVP_SessionId,
- tr_AVP_OriginHost,
- tr_AVP_OriginRealm,
- tr_AVP_DestinationRealm,
- tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
- tr_AVP_CcReqType(req_type),
- tr_AVP_CcReqNum(?)
- ));
+ for (i := 0; i < lengthof(avp_grp); i := i+1) {
+ if (not ispresent(avp_grp[i].avp)) {
+ continue;
+ }
+ var AVP_Header hdr := avp_grp[i].avp.avp_header;
+ if (match(hdr.avp_code, avp_code)) {
+ return avp_grp[i].avp;
+ }
+ }
+ return omit;
+}
+function f_AVP_Grouped_get_avp_or_fail(AVP_Grouped avp_grp, template (present) AVP_Code avp_code)
+return AVP
+{
+ var template (omit) AVP avp;
+ avp := f_AVP_Grouped_get_avp(avp_grp, avp_code);
+ if (istemplatekind(avp, "omit")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("AVP ", avp_code, " not found in ", avp_grp));
+ }
+ return valueof(avp);
+}
-/* RFC 4006 3.2. Credit-Control-Answer (CCA) Command */
-template (value) PDU_DIAMETER
-ts_DIA_CCA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
- template (value) octetstring sess_id,
- template (value) DCC_NONE_CC_Request_Type req_type,
- template (value) AVP_Unsigned32 req_num)
+/*****************************
+ * Cx, Dx, 3GPP TS 29.229
+ *****************************/
+/* SIP-Auth-Data-Item, 3GPP TS 29.229 6.3.8 */
+template (present) GenericAVP tr_AVP_3GPP_SIPNumAuthDataItems(template (present) uint32_t num := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Number_Auth_Items),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Number_Auth_Items := int2oct_tmpl(num, 4) /* CxDx_3GPP_SIP_Number_Auth_Items */
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPNumAuthDataItems(uint32_t num) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Number_Auth_Items),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Number_Auth_Items := int2oct(num, 4) /* CxDx_3GPP_SIP_Number_Auth_Items */
+ }
+ }
+}
-:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
- app_id:=int2oct(c_DIAMETER_3GPP_Gx_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
- avps := {
- ts_AVP_SessionId(sess_id),
- ts_AVP_ResultCode(DIAMETER_SUCCESS),
- ts_AVP_OriginHost("pcrf.localdomain"),
- ts_AVP_OriginRealm("localdomain"),
- ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
- ts_AVP_CcReqType(req_type),
- ts_AVP_CcReqNum(req_num)//,
- // qos
- // default eps bearer qos
- // supported features
- // origin
- });
+/* SIP-Authentication-Scheme, 3GPP TS 29.229 6.3.9 */
+template (present) GenericAVP tr_AVP_3GPP_SIPAuthScheme(template (present) CxDx_3GPP_SIP_Authentication_Scheme scheme := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authentication_Scheme),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authentication_Scheme := scheme
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPAuthScheme(template (value) CxDx_3GPP_SIP_Authentication_Scheme scheme) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authentication_Scheme),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authentication_Scheme := scheme
+ }
+ }
+}
+
+/* SIP-Authenticate, 3GPP TS 29.229 6.3.10 */
+template (present) GenericAVP tr_AVP_3GPP_SIPAuthenticate(template (present) CxDx_3GPP_SIP_Authenticate rand_autn_concatenated := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authenticate),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authenticate := rand_autn_concatenated
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPAuthenticate(template (value) CxDx_3GPP_SIP_Authenticate rand_autn_concatenated) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authenticate),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authenticate := rand_autn_concatenated
+ }
+ }
+}
+
+/* SIP-Authorization, 3GPP TS 29.229 6.3.11 */
+template (present) GenericAVP tr_AVP_3GPP_SIPAuthorization(template (present) CxDx_3GPP_SIP_Authorization rand_autn_concatenated := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authorization),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authorization := rand_autn_concatenated
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPAuthorization(template (value) CxDx_3GPP_SIP_Authorization rand_autn_concatenated) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authorization),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authorization := rand_autn_concatenated
+ }
+ }
+}
+
+/* SIP-Authentication-Context, 3GPP TS 29.229 6.3.12 */
+template (present) GenericAVP tr_AVP_3GPP_SIPAuthContext(template (present) CxDx_3GPP_SIP_Authentication_Context val := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authentication_Context),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authentication_Context := val
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPAuthContext(template (value) CxDx_3GPP_SIP_Authentication_Context val) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Authentication_Context),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Authentication_Context := val
+ }
+ }
+}
+
+/* SIP-Item-Number, 3GPP TS 29.229 6.3.14 */
+template (present) GenericAVP tr_AVP_3GPP_SIPItemNumber(template (present) uint32_t num := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Item_Number),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Item_Number := int2oct_tmpl(num, 4) /* CxDx_3GPP_SIP_Item_Number */
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPItemNumber(uint32_t num) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Item_Number),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Item_Number := int2oct(num, 4) /* CxDx_3GPP_SIP_Item_Number */
+ }
+ }
+}
+
+/* Confidentiality-Key, 3GPP TS 29.229 6.3.27 */
+template (present) GenericAVP tr_AVP_3GPP_ConfidentialityKey(template (present) CxDx_3GPP_Confidentiality_Key ckey := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Confidentiality_Key),
+ avp_data := {
+ avp_CxDx_3GPP_Confidentiality_Key := ckey
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_ConfidentialityKey(template (value) CxDx_3GPP_Confidentiality_Key ckey) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Confidentiality_Key),
+ avp_data := {
+ avp_CxDx_3GPP_Confidentiality_Key := ckey
+ }
+ }
+}
+
+/* Inegrity-Key, 3GPP TS 29.229 6.3.28 */
+template (present) GenericAVP tr_AVP_3GPP_IntegrityKey(template (present) CxDx_3GPP_Integrity_Key ckey := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Integrity_Key),
+ avp_data := {
+ avp_CxDx_3GPP_Integrity_Key := ckey
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_IntegrityKey(template (value) CxDx_3GPP_Integrity_Key ckey) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Integrity_Key),
+ avp_data := {
+ avp_CxDx_3GPP_Integrity_Key := ckey
+ }
+ }
+}
+
+/* Server-Assignment-Type, 3GPP TS 29.273 8.2.3.12, 3GPP TS 29.229 6.3.15 */
+template (present) GenericAVP tr_AVP_3GPP_ServerAssignmentType(template (present) CxDx_3GPP_Server_Assignment_Type t := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Server_Assignment_Type),
+ avp_data := {
+ avp_CxDx_3GPP_Server_Assignment_Type := t
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_ServerAssignmentType(template (value) CxDx_3GPP_Server_Assignment_Type t) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Server_Assignment_Type),
+ avp_data := {
+ avp_CxDx_3GPP_Server_Assignment_Type := t
+ }
+ }
+}
}
diff --git a/library/DIAMETER_Types.ttcn b/library/DIAMETER_Types.ttcn
index 972cd6e0..a714be2f 100644
--- a/library/DIAMETER_Types.ttcn
+++ b/library/DIAMETER_Types.ttcn
@@ -4,7 +4,7 @@
// //
///////////////////////////////////////////////////
// Generated with command:
-// AVP.sh Base_IETF_RFC3588.ddf BaseTypes_IETF_RFC3588.ddf AAAInterface_3GPP_TS29272_f10.ddf GxInterface_PCC_3GPP_TS29212_f10.ddf S6Interfaces_3GPP_TS29336_f00.ddf MobileIPv6_HA_IETF_RFC5778.ddf RxInterface_PCC_3GPP_TS29214_f20.ddf NetworkAccessServer_IETF_RFC4005.ddf CreditControl_IETF_RFC4006.ddf CxDxInterface_3GPP_TS29229_c30.ddf GiSGiInterface_3GPP_TS29061_d70.ddf
+// AVP.sh Base_IETF_RFC3588.ddf BaseTypes_IETF_RFC3588.ddf MobileIPv4_Application_IETF_RFC4004.ddf NetworkAccessServer_IETF_RFC4005.ddf CreditControl_IETF_RFC4006.ddf MobileIPv6_NAS_IETF_RFC5447.ddf MobileIPv6_HA_IETF_RFC5778.ddf AAAInterface_3GPP_TS29272_f10.ddf GxInterface_PCC_3GPP_TS29212_f10.ddf S6Interfaces_3GPP_TS29336_f00.ddf RxInterface_PCC_3GPP_TS29214_f20.ddf CxDxInterface_3GPP_TS29229_c30.ddf GiSGiInterface_3GPP_TS29061_d70.ddf ChargingApplications_3GPP_TS32299_d90.ddf AAAInterface_3GPP_TS29273_f00.ddf
module DIAMETER_Types {
/******************************************************************************
* Copyright (c) 2000-2019 Ericsson Telecom AB
@@ -640,6 +640,1377 @@ command_code, application_id, hop_by_hop_id, end_to_end_id, avps)";
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
+* Roland Gecse - initial implementation and initial documentation
+* Akos Pernek
+* Antal Wuh.Hen.Chang
+* Attila Fulop
+* Balazs Barcsik
+* Bence Molnar
+* Csaba Koppany
+* David Juhasz
+* Eduard Czimbalmos
+* Elemer Lelik
+* Endre Kiss
+* Endre Kulcsar
+* Gabor Szalai
+* Gabor Tatarka
+* Gergely Futo
+* Istvan Sandor
+* Krisztian Pandi
+* Kulcsár Endre
+* Laszlo Tamas Zeke
+* Norbert Pinter
+* Roland Gecse
+* Tibor Bende
+* Tibor Szabo
+* Timea Moder
+* Zoltan Medve
+* Zsolt Nandor Torok
+* Zsolt Szalai
+******************************************************************************/
+//
+// File: MobileIPv4_Application_IETF_RFC4004.ddf
+// Description: DDF for Mobile IPv4 Application
+// Rev: R55A
+// Prodnr: CNL 113 462
+// Reference: IETF RFC 4004
+//
+//
+
+// APPLICATION-NAME: MIPv4
+// APPLICATION-REVISION: RFC4004
+
+// RFC 4004 7.1
+// AVP: MIP-Reg-Request (320)
+type AVP_OctetString MIPv4_NONE_MIP_Reg_Request
+
+// RFC 4004 7.2
+// AVP: MIP-Reg-Reply (321)
+type AVP_OctetString MIPv4_NONE_MIP_Reg_Reply
+
+// RFC 4004 7.3
+// AVP: MIP-Mobile-Node-Address (333)
+type AVP_Address MIPv4_NONE_MIP_Mobile_Node_Address
+
+// RFC 4004 7.4
+// AVP: MIP-Home-Agent-Address (334)
+type AVP_Address MIPv4_NONE_MIP_Home_Agent_Address
+
+// RFC 4004 7.5
+// AVP: MIP-Feature-Vector (337)
+type AVP_Unsigned32 MIPv4_NONE_MIP_Feature_Vector
+
+// RFC 4004 7.6
+// AVP: MIP-MN-AAA-Auth (322)
+type AVP_Grouped MIPv4_NONE_MIP_MN_AAA_Auth
+
+// RFC 4004 7.6.1
+// AVP: MIP-MN-AAA-SPI (341)
+type AVP_Unsigned32 MIPv4_NONE_MIP_MN_AAA_SPI
+
+// RFC 4004 7.6.2
+// AVP: MIP-Auth-Input-Data-Length (338)
+type AVP_Unsigned32 MIPv4_NONE_MIP_Auth_Input_Data_Length
+
+
+// RFC 4004 7.6.3
+// AVP: MIP-Authenticator-Length (339)
+type AVP_Unsigned32 MIPv4_NONE_MIP_Authenticator_Length
+
+// RFC 4004 7.6.4
+// AVP: MIP-Authenticator-Offset (340)
+type AVP_Unsigned32 MIPv4_NONE_MIP_Authenticator_Offset
+
+// RFC 4004 7.7
+// AVP: MIP-FA-Challenge (344)
+type AVP_OctetString MIPv4_NONE_MIP_FA_Challenge
+
+// RFC 4004 7.8
+// AVP: MIP-Filter-Rule (342)
+type AVP_IPFilterRule MIPv4_NONE_MIP_Filter_Rule
+
+// RFC 4004 7.9
+// AVP: MIP-Candidate-Home-Agent-Host (336)
+type AVP_DiameterIdentity MIPv4_NONE_MIP_Candidate_Home_Agent_Host
+
+// RFC 4004 7.10
+// AVP: MIP-Originating-Foreign-AAA (347)
+type AVP_Grouped MIPv4_NONE_MIP_Originating_Foreign_AAA
+
+// RFC 4004 7.11
+// AVP: MIP-Home-Agent-Host (348)
+type AVP_Grouped MIPv4_NONE_MIP_Home_Agent_Host
+
+// RFC 4004 9.1
+// AVP: MIP-FA-to-MN-MSA (326)
+type AVP_Grouped MIPv4_NONE_MIP_FA_to_MN_MSA
+
+// RFC 4004 9.2
+// AVP: MIP-FA-to-HA-MSA (328)
+type AVP_Grouped MIPv4_NONE_MIP_FA_to_HA_MSA
+
+// RFC 4004 9.3
+// AVP: MIP-HA-to-FA-MSA (329)
+type AVP_Grouped MIPv4_NONE_MIP_HA_to_FA_MSA
+
+// RFC 4004 9.4
+// AVP: MIP-HA-to-MN-MSA (332)
+type AVP_Grouped MIPv4_NONE_MIP_HA_to_MN_MSA
+
+// RFC 4004 9.5
+// AVP: MIP-MN-to-FA-MSA (325)
+type AVP_Grouped MIPv4_NONE_MIP_MN_to_FA_MSA
+
+// RFC 4004 9.6
+// AVP: MIP-MN-to-HA-MSA (331)
+type AVP_Grouped MIPv4_NONE_MIP_MN_to_HA_MSA
+
+// RFC 4004 9.7
+// AVP: MIP-Session-Key (343)
+type AVP_OctetString MIPv4_NONE_MIP_Session_Key
+
+// RFC 4004 9.8
+// AVP: MIP-Algorithm-Type (345)
+type enumerated MIPv4_NONE_MIP_Algorithm_Type {
+ HMAC_SHA_1 (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4004 9.9
+// AVP: MIP-Replay-Mode (346)
+type enumerated MIPv4_NONE_MIP_Replay_Mode {
+ None (1),
+ Timestamps (2),
+ Nonces (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4004 9.10
+// AVP: MIP-FA-to-MN-SPI (319)
+type AVP_Unsigned32 MIPv4_NONE_MIP_FA_to_MN_SPI
+
+// RFC 4004 9.11
+// AVP: MIP-FA-to-HA-SPI (318)
+type AVP_Unsigned32 MIPv4_NONE_MIP_FA_to_HA_SPI
+
+// RFC 4004 9.12
+// AVP: MIP-Nonce (335)
+type AVP_OctetString MIPv4_NONE_MIP_Nonce
+
+// RFC 4004 9.13
+// AVP: MIP-MSA-Lifetime (367)
+type AVP_Unsigned32 MIPv4_NONE_MIP_MSA_Lifetime
+
+// RFC 4004 9.14
+// AVP: MIP-HA-to-FA-SPI (323)
+type AVP_Unsigned32 MIPv4_NONE_MIP_HA_to_FA_SPI
+
+// RFC 4004 10.1
+// AVP: Accounting-Input-Octets (363)
+type AVP_Unsigned64 MIPv4_NONE_Accounting_Input_Octets
+
+// RFC 4004 10.2
+// AVP: Accounting-Output-Octets (364)
+type AVP_Unsigned64 MIPv4_NONE_Accounting_Output_Octets
+
+// RFC 4004 10.3
+// AVP: Acct-Session-Time (46)
+type AVP_Unsigned32 MIPv4_NONE_Acct_Session_Time
+
+// RFC 4004 10.4
+// AVP: Accounting-Input-Packets (365)
+type AVP_Unsigned64 MIPv4_NONE_Accounting_Input_Packets
+
+// RFC 4004 10.5
+// AVP: Accounting-Output-Packets (366)
+type AVP_Unsigned64 MIPv4_NONE_Accounting_Output_Packets
+
+// RFC 4004 10.6
+// AVP: Event-Timestamp (55)
+// WARNING: Duplicated AVP definition removed by gawk script!
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Roland Gecse - initial implementation and initial documentation
+* Akos Pernek
+* Antal Wuh.Hen.Chang
+* Attila Fulop
+* Balazs Barcsik
+* Bence Molnar
+* Csaba Koppany
+* David Juhasz
+* Eduard Czimbalmos
+* Elemer Lelik
+* Endre Kiss
+* Endre Kulcsar
+* Gabor Szalai
+* Gabor Tatarka
+* Gergely Futo
+* Istvan Sandor
+* Krisztian Pandi
+* Kulcsár Endre
+* Laszlo Tamas Zeke
+* Norbert Pinter
+* Roland Gecse
+* Tibor Bende
+* Tibor Szabo
+* Timea Moder
+* Zoltan Medve
+* Zsolt Nandor Torok
+* Zsolt Szalai
+******************************************************************************/
+//
+// File: NetworkAccessServer_IETF_RFC4005.ddf
+// Description: DDF for NAS according to RFC 4005
+// Rev: R55A
+// Prodnr: CNL113462
+///////////////////////////////////////////////
+
+// APPLICATION-NAME: DNAS
+// APPLICATION-REVISION: RFC4005
+
+// AVP implementations according to:
+// RFC 4005 - Diameter Network Access Server Application
+//
+
+// RFC 4005 3
+// WARNING: Enumeration item with code (258) exists in type Command_Code
+// WARNING: Enumeration item with code (275) exists in type Command_Code
+// WARNING: Enumeration item with code (274) exists in type Command_Code
+// WARNING: Enumeration item with code (271) exists in type Command_Code
+
+
+// RFC 4005
+// AVP: NAS-Port (5)
+// 4.2
+type AVP_Unsigned32 DNAS_NONE_NAS_Port
+
+// RFC 4005
+// AVP: NAS-Port-Id (87)
+// 4.3
+type AVP_UTF8String DNAS_NONE_NAS_Port_Id
+
+// RFC 4005
+// AVP: NAS-Port-Type (61)
+// 4.4
+type AVP_Unsigned32 DNAS_NONE_NAS_Port_Type
+
+// RFC 4005
+// AVP: Called-Station-Id (30)
+// 4.5
+type AVP_UTF8String DNAS_NONE_Called_Station_Id
+
+// RFC 4005
+// AVP: Calling-Station-Id (31)
+// 4.6
+type AVP_UTF8String DNAS_NONE_Calling_Station_Id
+
+// RFC 4005
+// AVP: Connect-Info (77)
+// 4.7
+type AVP_UTF8String DNAS_NONE_Connect_Info
+
+// RFC 4005
+// AVP: Originating-Line-Info (94)
+// 4.8
+type AVP_OctetString DNAS_NONE_Originating_Line_Info
+
+// RFC 4005
+// AVP: Reply-Message (18)
+// 4.9
+type AVP_UTF8String DNAS_NONE_Reply_Message
+
+
+
+// RFC 4005
+// AVP: User-Password (2)
+// 5.1
+type AVP_OctetString DNAS_NONE_User_Password
+
+// RFC 4005
+// AVP: Password-Retry (75)
+// 5.2
+type AVP_Unsigned32 DNAS_NONE_Password_Retry
+
+// RFC 4005
+// AVP: Prompt (76)
+// 5.3
+type enumerated DNAS_NONE_Prompt {
+ NO_ECHO (0),
+ ECHO (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: CHAP-Auth (402)
+// 5.4
+type AVP_Grouped DNAS_NONE_CHAP_Auth
+
+// RFC 4005
+// AVP: CHAP-Algorithm (403)
+// 5.5
+type enumerated DNAS_NONE_CHAP_Algorithm {
+ CHAP_with_MD5 (5)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: CHAP-Ident (404)
+// 5.6
+type AVP_OctetString DNAS_NONE_CHAP_Ident
+
+// RFC 4005
+// AVP: CHAP-Response (405)
+// 5.7
+type AVP_OctetString DNAS_NONE_CHAP_Response
+
+// RFC 4005
+// AVP: CHAP-Challenge (60)
+// 5.8
+type AVP_OctetString DNAS_NONE_CHAP_Challenge
+
+// RFC 4005
+// AVP: ARAP-Password (70)
+// 5.9
+type AVP_OctetString DNAS_NONE_ARAP_Password
+
+// RFC 4005
+// AVP: ARAP-Challenge-Response (84)
+// 5.10
+type AVP_OctetString DNAS_NONE_ARAP_Challenge_Response
+
+// RFC 4005
+// AVP: ARAP-Security (73)
+// 5.11
+type AVP_Unsigned32 DNAS_NONE_ARAP_Security
+
+// RFC 4005
+// AVP: ARAP-Security-Data (74)
+// 5.12
+type AVP_OctetString DNAS_NONE_ARAP_Security_Data
+
+
+
+// RFC 4005
+// AVP: Service-Type (6)
+// 6.1
+type AVP_Unsigned32 DNAS_NONE_Service_Type
+
+// RFC 4005
+// AVP: Callback-Number (19)
+// 6.2
+type AVP_UTF8String DNAS_NONE_Callback_Number
+
+// RFC 4005
+// AVP: Callback-Id (20)
+// 6.3
+type AVP_UTF8String DNAS_NONE_Callback_Id
+
+// RFC 4005
+// AVP: Idle-Timeout (28)
+// 6.4
+type AVP_Unsigned32 DNAS_NONE_Idle_Timeout
+
+// RFC 4005
+// AVP: Port-Limit (62)
+// 6.5
+type AVP_Unsigned32 DNAS_NONE_Port_Limit
+
+// RFC 4005
+// AVP: NAS-Filter-Rule (400)
+// 6.6
+type AVP_IPFilterRule DNAS_NONE_NAS_Filter_Rule
+
+// RFC 4005
+// AVP: Filter-Id (11)
+// 6.7
+type AVP_UTF8String DNAS_NONE_Filter_Id
+
+// RFC 4005
+// AVP: Configuration-Token (78)
+// 6.8
+type AVP_OctetString DNAS_NONE_Configuration_Token
+
+// RFC 4005
+// AVP: QoS-Filter-Rule (407)
+// 6.9
+type AVP_QoSFilterRule DNAS_NONE_QoS_Filter_Rule
+
+// RFC 4005
+// AVP: Framed-Protocol (7)
+// 6.10.1
+type enumerated DNAS_NONE_Framed_Protocol {
+ PPP (1),
+ SLIP (2),
+ ARAP (3),
+ GANDALF (4),
+ XYLOGICS (5),
+ X_75_SYNCHRONOUS (6),
+ GPRS_PDP_CONTEXT (7)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Framed-Routing (10)
+// 6.10.2
+type enumerated DNAS_NONE_Framed_Routing {
+ NONE (0),
+ SEND_ROUTING_PACKETS (1),
+ LISTEN_FOR_ROUTING_PACKETS (2),
+ SEND_AND_LISTEN (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Framed-MTU (12)
+// 6.10.3
+type AVP_Unsigned32 DNAS_NONE_Framed_MTU
+
+// RFC 4005
+// AVP: Framed-Compression (13)
+// 6.10.4
+type enumerated DNAS_NONE_Framed_Compression {
+ NONE (0),
+ VJ_TCP_IP_HEADER_COMPRESSION (1),
+ IPX_HEADER_COMPRESSION (2),
+ STAC_LZS_COMPRESSION (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Framed-IP-Address (8)
+// 6.11.1
+type AVP_OctetString DNAS_NONE_Framed_IP_Address
+
+// RFC 4005
+// AVP: Framed-IP-Netmask (9)
+// 6.11.2
+type AVP_OctetString DNAS_NONE_Framed_IP_Netmask
+
+// RFC 4005
+// AVP: Framed-Route (22)
+// 6.11.3
+type AVP_UTF8String DNAS_NONE_Framed_Route
+
+// RFC 4005
+// AVP: Framed-Pool (88)
+// 6.11.4
+type AVP_OctetString DNAS_NONE_Framed_Pool
+
+// RFC 4005
+// AVP: Framed-Interface-Id (96)
+// 6.11.5
+type AVP_Unsigned64 DNAS_NONE_Framed_Interface_Id
+
+// RFC 4005
+// AVP: Framed-IPv6-Prefix (97)
+// 6.11.6
+type AVP_OctetString DNAS_NONE_Framed_IPv6_Prefix
+
+// RFC 4005
+// AVP: Framed-IPv6-Route (99)
+// 6.11.7
+type AVP_UTF8String DNAS_NONE_Framed_IPv6_Route
+
+// RFC 4005
+// AVP: Framed-IPv6-Pool (100)
+// 6.11.8
+type AVP_OctetString DNAS_NONE_Framed_IPv6_Pool
+
+// RFC 4005
+// AVP: Framed-IPX-Network (23)
+// 6.12.1
+type AVP_UTF8String DNAS_NONE_Framed_IPX_Network
+
+// RFC 4005
+// AVP: Framed-Appletalk-Link (37)
+// 6.13.1
+type AVP_Unsigned32 DNAS_NONE_Framed_Appletalk_Link
+
+// RFC 4005
+// AVP: Framed-Appletalk-Network (38)
+// 6.13.2
+type AVP_Unsigned32 DNAS_NONE_Framed_Appletalk_Network
+
+// RFC 4005
+// AVP: Framed-Appletalk-Zone (39)
+// 6.13.3
+type AVP_OctetString DNAS_NONE_Framed_Appletalk_Zone
+
+// RFC 4005
+// AVP: ARAP-Features (71)
+// 6.14.1
+type AVP_OctetString DNAS_NONE_ARAP_Features
+
+// RFC 4005
+// AVP: ARAP-Zone-Access (72)
+// 6.14.2
+type enumerated DNAS_NONE_ARAP_Zone_Access {
+ ONLY_ALLOW_ACCESS_TO_DEFAULT_ZONE (1),
+ USE_ZONE_FILTER_INCLUSIVELY (2),
+ USE_ZONE_FILTER_EXCLUSIVELY (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Login-IP-Host (14)
+// 6.15.1
+type AVP_OctetString DNAS_NONE_Login_IP_Host
+
+// RFC 4005
+// AVP: Login-IPv6-Host (98)
+// 6.15.2
+type AVP_OctetString DNAS_NONE_Login_IPv6_Host
+
+// RFC 4005
+// AVP: Login-Service (15)
+// 6.15.3
+type enumerated DNAS_NONE_Login_Service {
+ TELNET (0),
+ RLOGIN (1),
+ TCP_CLEAR (2),
+ PORTMASTER (3),
+ LAT (4),
+ X25_PAD (5),
+ X25_T3POS (6),
+ TCP_CLEAR_QUIET (8)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Login-TCP-Port (16)
+// 6.16.1
+type AVP_Unsigned32 DNAS_NONE_Login_TCP_Port
+
+// RFC 4005
+// AVP: Login-LAT-Service (34)
+// 6.17.1
+type AVP_OctetString DNAS_NONE_Login_LAT_Service
+
+// RFC 4005
+// AVP: Login-LAT-Node (35)
+// 6.17.2
+type AVP_OctetString DNAS_NONE_Login_LAT_Node
+
+// RFC 4005
+// AVP: Login-LAT-Group (36)
+// 6.17.3
+type AVP_OctetString DNAS_NONE_Login_LAT_Group
+
+// RFC 4005
+// AVP: Login-LAT-Port (63)
+// 6.17.4
+type AVP_OctetString DNAS_NONE_Login_LAT_Port
+
+
+
+// RFC 4005
+// AVP: Tunneling (401)
+// 7.1
+type AVP_Grouped DNAS_NONE_Tunneling
+
+// RFC 4005
+// AVP: Tunnel-Type (64)
+// 7.2
+type AVP_Unsigned32 DNAS_NONE_Tunnel_Type
+
+// RFC 4005
+// AVP: Tunnel-Medium-Type (65)
+// 7.3
+type AVP_Unsigned32 DNAS_NONE_Tunnel_Medium_Type
+
+// RFC 4005
+// AVP: Tunnel-Client-Endpoint (66)
+// 7.4
+type AVP_UTF8String DNAS_NONE_Tunnel_Client_Endpoint
+
+// RFC 4005
+// AVP: Tunnel-Server-Endpoint (67)
+// 7.5
+type AVP_UTF8String DNAS_NONE_Tunnel_Server_Endpoint
+
+// RFC 4005
+// AVP: Tunnel-Password (69)
+// 7.6
+type AVP_OctetString DNAS_NONE_Tunnel_Password
+
+// RFC 4005
+// AVP: Tunnel-Private-Group-Id (81)
+// 7.7
+type AVP_OctetString DNAS_NONE_Tunnel_Private_Group_Id
+
+// RFC 4005
+// AVP: Tunnel-Assignment-Id (82)
+// 7.8
+type AVP_OctetString DNAS_NONE_Tunnel_Assignment_Id
+
+// RFC 4005
+// AVP: Tunnel-Preference (83)
+// 7.9
+type AVP_Unsigned32 DNAS_NONE_Tunnel_Preference
+
+// RFC 4005
+// AVP: Tunnel-Client-Auth-Id (90)
+// 7.10
+type AVP_UTF8String DNAS_NONE_Tunnel_Client_Auth_Id
+
+// RFC 4005
+// AVP: Tunnel-Server-Auth-Id (91)
+// 7.11
+type AVP_UTF8String DNAS_NONE_Tunnel_Server_Auth_Id
+
+
+
+// RFC 4005
+// AVP: Accounting-Input-Octets (363)
+// 8.1
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 4005
+// AVP: Accounting-Output-Octets (364)
+// 8.2
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 4005
+// AVP: Accounting-Input-Packets (365)
+// 8.3
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 4005
+// AVP: Accounting-Output-Packets (366)
+// 8.4
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 4005
+// AVP: Acct-Session-Time (46)
+// 8.5
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 4005
+// AVP: Acct-Authentic (45)
+// 8.6
+type enumerated DNAS_NONE_Acct_Authentic {
+ RADIUS (1),
+ LOCAL (2),
+ REMOTE (3),
+ DIAMETER (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Accounting-Auth-Method (406)
+// 8.7
+type enumerated DNAS_NONE_Accounting_Auth_Method {
+ PAP (1),
+ CHAP (2),
+ MS_CHAP_1 (3),
+ MS_CHAP_2 (4),
+ EAP (5),
+ None (7)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4005
+// AVP: Acct-Delay-Time (41)
+// 8.8
+type AVP_Unsigned32 DNAS_NONE_Acct_Delay_Time
+
+// RFC 4005
+// AVP: Acct-Link-Count (51)
+// 8.9
+type AVP_Unsigned32 DNAS_NONE_Acct_Link_Count
+
+// RFC 4005
+// AVP: Acct-Tunnel-Connection (68)
+// 8.10
+type AVP_OctetString DNAS_NONE_Acct_Tunnel_Connection
+
+// RFC 4005
+// AVP: Acct-Tunnel-Packets-Lost (86)
+// 8.11
+type AVP_Unsigned32 DNAS_NONE_Acct_Tunnel_Packets_Lost
+
+
+
+// RFC 4005
+// AVP: NAS-Identifier (32)
+// 9.3.1
+type AVP_UTF8String DNAS_NONE_NAS_Identifier
+
+// RFC 4005
+// AVP: NAS-IP-Address (4)
+// 9.3.2
+type AVP_OctetString DNAS_NONE_NAS_IP_Address
+
+// RFC 4005
+// AVP: NAS-IPv6-Address (95)
+// 9.3.3
+type AVP_OctetString DNAS_NONE_NAS_IPv6_Address
+
+// RFC 4005
+// AVP: State (24)
+// 9.3.4
+type AVP_OctetString DNAS_NONE_State
+
+// RFC 4005
+// AVP: Origin-AAA-Protocol (408)
+// 9.3.6
+type enumerated DNAS_NONE_Origin_AAA_Protocol {
+ RADIUS (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Roland Gecse - initial implementation and initial documentation
+* Akos Pernek
+* Antal Wuh.Hen.Chang
+* Attila Fulop
+* Balazs Barcsik
+* Bence Molnar
+* Csaba Koppany
+* David Juhasz
+* Eduard Czimbalmos
+* Elemer Lelik
+* Endre Kiss
+* Endre Kulcsar
+* Gabor Szalai
+* Gabor Tatarka
+* Gergely Futo
+* Istvan Sandor
+* Krisztian Pandi
+* Kulcsár Endre
+* Laszlo Tamas Zeke
+* Norbert Pinter
+* Roland Gecse
+* Tibor Bende
+* Tibor Szabo
+* Timea Moder
+* Zoltan Medve
+* Zsolt Nandor Torok
+* Zsolt Szalai
+******************************************************************************/
+//
+// File: CreditControl_IETF_RFC4006.ddf
+// Description: DDF for DCC according to RFC 4006
+// Rev: R55A
+// Prodnr: CNL 1134 62
+///////////////////////////////////////////////
+
+// APPLICATION-NAME: DCC
+// APPLICATION-REVISION: RFC4006
+
+// AVP implementations according to:
+// RFC 4006 - Diameter Credit Control Application
+// IS for Additional Billing for Verizon in MTAS 125/1594-FCP 101 8664 Uen PA8
+
+// RFC 4006 12.2
+
+
+// RFC 4006
+// AVP: CC-Correlation-Id (411)
+// 8.1
+type AVP_OctetString DCC_NONE_CC_Correlation_Id
+
+// RFC 4006
+// AVP: CC-Input-Octets (412)
+// 8.24
+type AVP_Unsigned64 DCC_NONE_CC_Input_Octets
+
+// RFC 4006
+// AVP: CC-Money (413)
+// 8.22
+type AVP_Grouped DCC_NONE_CC_Money
+
+// RFC 4006
+// AVP: CC-Output-Octets (414)
+// 8.25
+type AVP_Unsigned64 DCC_NONE_CC_Output_Octets
+
+// RFC 4006
+// AVP: CC-Request-Number (415)
+// 8.2
+type AVP_Unsigned32 DCC_NONE_CC_Request_Number
+
+// RFC 4006
+// AVP: CC-Request-Type (416)
+// 8.3
+type enumerated DCC_NONE_CC_Request_Type {
+ INITIAL_REQUEST (1),
+ UPDATE_REQUEST (2),
+ TERMINATION_REQUEST (3),
+ EVENT_REQUEST (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: CC-Service-Specific-Units (417)
+// 8.26
+type AVP_Unsigned64 DCC_NONE_CC_Service_Specific_Units
+
+// RFC 4006
+// AVP: CC-Session-Failover (418)
+// 8.4
+type enumerated DCC_NONE_CC_Session_Failover {
+ FAILOVER_NOT_SUPPORTED (0),
+ FAILOVER_SUPPORTED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: CC-Sub-Session-Id (419)
+// 8.5
+type AVP_Unsigned64 DCC_NONE_CC_Sub_Session_Id
+
+// RFC 4006
+// AVP: CC-Time (420)
+// 8.21
+type AVP_Unsigned32 DCC_NONE_CC_Time
+
+// RFC 4006
+// AVP: CC-Total-Octets (421)
+// 8.23
+type AVP_Unsigned64 DCC_NONE_CC_Total_Octets
+
+// RFC 4006
+// AVP: CC-Unit-Type (454)
+// 8.32
+type enumerated DCC_NONE_CC_Unit_Type {
+ TIME (0),
+ MONEY (1),
+ TOTAL_OCTETS (2),
+ INPUT_OCTETS (3),
+ OUTPUT_OCTETS (4),
+ SERVICE_SPECIFIC_UNITS (5)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Check-Balance-Result (422)
+// 8.6
+type enumerated DCC_NONE_Check_Balance_Result {
+ ENOUGH_CREDIT (0),
+ NO_CREDIT (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Cost-Information (423)
+// 8.7
+type AVP_Grouped DCC_NONE_Cost_Information
+
+// RFC 4006
+// AVP: Cost-Unit (424)
+// 8.12
+type AVP_UTF8String DCC_NONE_Cost_Unit
+
+// RFC 4006
+// AVP: Credit-Control (426)
+// 8.13
+type enumerated DCC_NONE_Credit_Control {
+ CREDIT_AUTHORIZATION (0),
+ RE_AUTHORIZATION (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Credit-Control-Failure-Handling (427)
+// 8.14
+type enumerated DCC_NONE_Credit_Control_Failure_Handling {
+ TERMINATE (0),
+ CONTINUE (1),
+ RETRY_AND_TERMINATE (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Currency-Code (425)
+// 8.11
+type AVP_Unsigned32 DCC_NONE_Currency_Code
+
+// RFC 4006
+// AVP: Direct-Debiting-Failure-Handling (428)
+// 8.15
+type enumerated DCC_NONE_Direct_Debiting_Failure_Handling {
+ TERMINATE_OR_BUFFER (0),
+ CONTINUE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Exponent (429)
+// 8.9
+type AVP_Integer32 DCC_NONE_Exponent
+
+// RFC 4006
+// AVP: Final-Unit-Action (449)
+// 8.35
+type enumerated DCC_NONE_Final_Unit_Action {
+ TERMINATE (0),
+ REDIRECT (1),
+ RESTRICT_ACCESS (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Final-Unit-Indication (430)
+// 8.34
+type AVP_Grouped DCC_NONE_Final_Unit_Indication
+
+// RFC 4006
+// AVP: Granted-Service-Unit (431)
+// 8.17
+type AVP_Grouped DCC_NONE_Granted_Service_Unit
+
+// RFC 4006
+// AVP: G-S-U-Pool-Identifier (453)
+// 8.31
+type AVP_Unsigned32 DCC_NONE_G_S_U_Pool_Identifier
+
+// RFC 4006
+// AVP: G-S-U-Pool-Reference (457)
+// 8.30
+type AVP_Grouped DCC_NONE_G_S_U_Pool_Reference
+
+// RFC 4006
+// AVP: Multiple-Services-Credit-Control (456)
+// 8.16
+type AVP_Grouped DCC_NONE_Multiple_Services_Credit_Control
+
+// RFC 4006
+// AVP: Multiple-Services-Indicator (455)
+// 8.40
+type enumerated DCC_NONE_Multiple_Services_Indicator {
+ MULTIPLE_SERVICES_NOT_SUPPORTED (0),
+ MULTIPLE_SERVICES_SUPPORTED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Rating-Group (432)
+// 8.29
+type AVP_Unsigned32 DCC_NONE_Rating_Group
+
+// RFC 4006
+// AVP: Redirect-Address-Type (433)
+// 8.38
+type enumerated DCC_NONE_Redirect_Address_Type {
+ IPV4_ADDRESS (0),
+ IPV6_ADDRESS (1),
+ URL (2),
+ SIP_URI (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Redirect-Server (434)
+type AVP_Grouped DCC_NONE_Redirect_Server
+
+// RFC 4006
+// AVP: Redirect-Server-Address (435)
+// 8.37
+type AVP_UTF8String DCC_NONE_Redirect_Server_Address
+
+// RFC 4006
+// AVP: Requested-Action (436)
+// 8.41
+type enumerated DCC_NONE_Requested_Action {
+ DIRECT_DEBITING (0),
+ REFUND_ACCOUNT (1),
+ CHECK_BALANCE (2),
+ PRICE_ENQUIRY (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Requested-Service-Unit (437)
+// 8.18
+type AVP_Grouped DCC_NONE_Requested_Service_Unit
+
+// RFC 4006
+// AVP: Restriction-Filter-Rule (438)
+// 8.36
+type AVP_IPFilterRule DCC_NONE_Restriction_Filter_Rule
+
+// RFC 4006
+// AVP: Service-Context-Id (461)
+// 8.42
+type AVP_UTF8String DCC_NONE_Service_Context_Id
+
+// RFC 4006
+// AVP: Service-Identifier (439)
+// 8.28
+type AVP_Unsigned32 DCC_NONE_Service_Identifier
+
+// RFC 4006
+// AVP: Service-Parameter-Info (440)
+// 8.43
+type AVP_Grouped DCC_NONE_Service_Parameter_Info
+
+// RFC 4006
+// AVP: Service-Parameter-Type (441)
+// 8.44
+type AVP_Unsigned32 DCC_NONE_Service_Parameter_Type
+
+// RFC 4006
+// AVP: Service-Parameter-Value (442)
+// 8.45
+type AVP_OctetString DCC_NONE_Service_Parameter_Value
+
+// RFC 4006
+// AVP: Subscription-Id (443)
+// 8.46
+type AVP_Grouped DCC_NONE_Subscription_Id
+
+// RFC 4006
+// AVP: Subscription-Id-Data (444)
+// 8.48
+type AVP_UTF8String DCC_NONE_Subscription_Id_Data
+
+// RFC 4006
+// AVP: Subscription-Id-Type (450)
+// 8.47
+type enumerated DCC_NONE_Subscription_Id_Type {
+ END_USER_E164 (0),
+ END_USER_IMSI (1),
+ END_USER_SIP_URI (2),
+ END_USER_NAI (3),
+ END_USER_PRIVATE (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Tariff-Change-Usage (452)
+// 8.27
+type enumerated DCC_NONE_Tariff_Change_Usage {
+ UNIT_BEFORE_TARIFF_CHANGE (0),
+ UNIT_AFTER_TARIFF_CHANGE (1),
+ UNIT_INDETERMINATE (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: Tariff-Time-Change (451)
+// 8.20
+type AVP_Time DCC_NONE_Tariff_Time_Change
+
+// RFC 4006
+// AVP: Unit-Value (445)
+// 8.8
+type AVP_Grouped DCC_NONE_Unit_Value
+
+// RFC 4006
+// AVP: Used-Service-Unit (446)
+// 8.19
+type AVP_Grouped DCC_NONE_Used_Service_Unit
+
+// RFC 4006
+// AVP: User-Equipment-Info (458)
+// 8.49
+type AVP_Grouped DCC_NONE_User_Equipment_Info
+
+// RFC 4006, 125/1594-FCP 101 8664
+// AVP: User-Equipment-Info-Type (459)
+// RFC 4006 section 8.50, 125/1594-FCP 101 8664 section 3.3.12
+type enumerated DCC_NONE_User_Equipment_Info_Type {
+ IMEISV (0),
+ MAC (1),
+ EUI64 (2),
+ MODIFIED_EUI64 (3),
+ ESN (4),
+ MEID (5)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// RFC 4006
+// AVP: User-Equipment-Info-Value (460)
+// 8.51
+type AVP_OctetString DCC_NONE_User_Equipment_Info_Value
+
+// RFC 4006
+// AVP: Value-Digits (447)
+// 8.10
+type AVP_Integer64 DCC_NONE_Value_Digits
+
+// RFC 4006
+// AVP: Validity-Time (448)
+// 8.33
+type AVP_Unsigned32 DCC_NONE_Validity_Time
+
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Roland Gecse - initial implementation and initial documentation
+* Akos Pernek
+* Antal Wuh.Hen.Chang
+* Attila Fulop
+* Balazs Barcsik
+* Bence Molnar
+* Csaba Koppany
+* David Juhasz
+* Eduard Czimbalmos
+* Elemer Lelik
+* Endre Kiss
+* Endre Kulcsar
+* Gabor Szalai
+* Gabor Tatarka
+* Gergely Futo
+* Istvan Sandor
+* Krisztian Pandi
+* Kulcsár Endre
+* Laszlo Tamas Zeke
+* Norbert Pinter
+* Roland Gecse
+* Tibor Bende
+* Tibor Szabo
+* Timea Moder
+* Zoltan Medve
+* Zsolt Nandor Torok
+* Zsolt Szalai
+******************************************************************************/
+//
+// File: MobileIPv6_NAS_IETF_RFC5447.ddf
+// Description: DDF for Mobile IPv6 according to RFC 5447
+// Rev: R55A
+// Prodnr: CNL113462
+///////////////////////////////////////////////
+
+// APPLICATION-NAME: MIPv6
+// APPLICATION-REVISION: RFC5447
+
+// RFC 5447 4.2.1
+// AVP: MIP6-Agent-Info (486)
+type AVP_Grouped MIPv6_NONE_MIP6_Agent_Info
+
+// RFC 5447 4.2.2
+// AVP: MIP6-Home-Agent-Address (334)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5447 4.2.3
+// AVP: MIP6-Home-Agent-Host (348)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5447 4.2.4
+// AVP: MIP6-Home-Link-Prefix (125)
+type AVP_OctetString MIPv6_NONE_MIP6_Home_Link_Prefix
+
+// RFC 5447 4.2.5
+// AVP: MIP6-Feature-Vector (124)
+type AVP_Unsigned64 MIPv6_NONE_MIP6_Feature_Vector
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Roland Gecse - initial implementation and initial documentation
+* Akos Pernek
+* Antal Wuh.Hen.Chang
+* Attila Fulop
+* Balazs Barcsik
+* Bence Molnar
+* Csaba Koppany
+* David Juhasz
+* Eduard Czimbalmos
+* Elemer Lelik
+* Endre Kiss
+* Endre Kulcsar
+* Gabor Szalai
+* Gabor Tatarka
+* Gergely Futo
+* Istvan Sandor
+* Krisztian Pandi
+* Kulcsár Endre
+* Laszlo Tamas Zeke
+* Norbert Pinter
+* Roland Gecse
+* Tibor Bende
+* Tibor Szabo
+* Timea Moder
+* Zoltan Medve
+* Zsolt Nandor Torok
+* Zsolt Szalai
+******************************************************************************/
+//
+// File: MobileIPv6_HA_IETF_RFC5778.ddf
+// Description: DDF for Mobile IPv6 according to RFC 5778
+// Rev: R55A
+// Prodnr: CNL113462
+///////////////////////////////////////////////
+
+// APPLICATION-NAME: MIPv6
+// APPLICATION-REVISION: RFC5778
+
+// RFC 5778 6.2
+// AVP: Service-Selection (493)
+type AVP_UTF8String MIPv6_NONE_Service_Selection
+
+// RFC 5778 6.3
+// AVP: MIP-MN-AAA-SPI (341)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.4
+// AVP: MIP-MN-HA-SPI (491)
+type AVP_Unsigned32 MIPv6_NONE_MIP_MN_HA_SPI
+
+// RFC 5778 6.5
+// AVP: MIP-Mobile-Node-Address (333)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.7
+// AVP: MIP-Careof-Address (487)
+type AVP_Address MIPv6_NONE_MIP_Careof_Address
+
+// RFC 5778 6.8
+// AVP: MIP-Authenticator (488)
+type AVP_OctetString MIPv6_NONE_MIP_Authenticator
+
+// RFC 5778 6.9
+// AVP: MIP-MAC-Mobility-Data (489)
+type AVP_OctetString MIPv6_NONE_MIP_MAC_Mobility_Data
+
+// RFC 5778 6.10
+// AVP: MIP-Session-Key (343)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.11
+// AVP: MIP-MSA-Lifetime (367)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.12
+// AVP: MIP-MN-HA-MSA (492)
+type AVP_Grouped MIPv6_NONE_MIP_MN_HA_MSA
+
+// RFC 5778 6.13
+// AVP: MIP-Algorithm-Type (345)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.14
+// AVP: MIP-Replay-Mode (346)
+// WARNING: Duplicated AVP definition removed by gawk script!
+
+// RFC 5778 6.16
+// AVP: MIP-Timestamp (490)
+type AVP_OctetString MIPv6_NONE_MIP_Timestamp
+
+// RFC 5778 6.17
+// AVP: QoS-Capability (578)
+type AVP_Grouped MIPv6_NONE_QoS_Capability
+
+// RFC 5778 6.18
+// AVP: QoS-Resources (508)
+type AVP_Grouped MIPv6_NONE_QoS_Resources
+
+// RFC 5778 6.19
+// AVP: Chargable-User-Identity (89)
+type AVP_OctetString MIPv6_NONE_Chargable_User_Identity
+
+// RFC 5778 6.20
+// AVP: MIP6-Auth-Mode (494)
+type AVP_Unsigned32 MIPv6_NONE_MIP6_Auth_Mode
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
* Timea Moder - initial implementation and initial documentation
******************************************************************************/
//
@@ -1838,6 +3209,7 @@ type enumerated AAA_3GPP_RDS_Indicator {
// 3GPP TS 29.212 V15.1.0
// 5.6, 5b.6, 5c.6
+// WARNING: Enumeration item with code (272) exists in type Command_Code
// WARNING: Enumeration item with code (258) exists in type Command_Code
@@ -3368,126 +4740,6 @@ type AVP_Grouped S6_3GPP_APN_Validity_Time
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
-* Roland Gecse - initial implementation and initial documentation
-* Akos Pernek
-* Antal Wuh.Hen.Chang
-* Attila Fulop
-* Balazs Barcsik
-* Bence Molnar
-* Csaba Koppany
-* David Juhasz
-* Eduard Czimbalmos
-* Elemer Lelik
-* Endre Kiss
-* Endre Kulcsar
-* Gabor Szalai
-* Gabor Tatarka
-* Gergely Futo
-* Istvan Sandor
-* Krisztian Pandi
-* Kulcsár Endre
-* Laszlo Tamas Zeke
-* Norbert Pinter
-* Roland Gecse
-* Tibor Bende
-* Tibor Szabo
-* Timea Moder
-* Zoltan Medve
-* Zsolt Nandor Torok
-* Zsolt Szalai
-******************************************************************************/
-//
-// File: MobileIPv6_HA_IETF_RFC5778.ddf
-// Description: DDF for Mobile IPv6 according to RFC 5778
-// Rev: R55A
-// Prodnr: CNL113462
-///////////////////////////////////////////////
-
-// APPLICATION-NAME: MIPv6
-// APPLICATION-REVISION: RFC5778
-
-// RFC 5778 6.2
-// AVP: Service-Selection (493)
-type AVP_UTF8String MIPv6_NONE_Service_Selection
-
-// RFC 5778 6.3
-// AVP: MIP-MN-AAA-SPI (341)
-type AVP_Unsigned32 MIPv6_NONE_MIP_MN_AAA_SPI
-
-// RFC 5778 6.4
-// AVP: MIP-MN-HA-SPI (491)
-type AVP_Unsigned32 MIPv6_NONE_MIP_MN_HA_SPI
-
-// RFC 5778 6.5
-// AVP: MIP-Mobile-Node-Address (333)
-type AVP_Address MIPv6_NONE_MIP_Mobile_Node_Address
-
-// RFC 5778 6.7
-// AVP: MIP-Careof-Address (487)
-type AVP_Address MIPv6_NONE_MIP_Careof_Address
-
-// RFC 5778 6.8
-// AVP: MIP-Authenticator (488)
-type AVP_OctetString MIPv6_NONE_MIP_Authenticator
-
-// RFC 5778 6.9
-// AVP: MIP-MAC-Mobility-Data (489)
-type AVP_OctetString MIPv6_NONE_MIP_MAC_Mobility_Data
-
-// RFC 5778 6.10
-// AVP: MIP-Session-Key (343)
-type AVP_OctetString MIPv6_NONE_MIP_Session_Key
-
-// RFC 5778 6.11
-// AVP: MIP-MSA-Lifetime (367)
-type AVP_Unsigned32 MIPv6_NONE_MIP_MSA_Lifetime
-
-// RFC 5778 6.12
-// AVP: MIP-MN-HA-MSA (492)
-type AVP_Grouped MIPv6_NONE_MIP_MN_HA_MSA
-
-// RFC 5778 6.13
-// AVP: MIP-Algorithm-Type (345)
-type AVP_Unsigned32 MIPv6_NONE_MIP_Algorithm_Type
-
-// RFC 5778 6.14
-// AVP: MIP-Replay-Mode (346)
-type enumerated MIPv6_NONE_MIP_Replay_Mode {
- None (1),
- Timestamp (2)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 5778 6.16
-// AVP: MIP-Timestamp (490)
-type AVP_OctetString MIPv6_NONE_MIP_Timestamp
-
-// RFC 5778 6.17
-// AVP: QoS-Capability (578)
-type AVP_Grouped MIPv6_NONE_QoS_Capability
-
-// RFC 5778 6.18
-// AVP: QoS-Resources (508)
-type AVP_Grouped MIPv6_NONE_QoS_Resources
-
-// RFC 5778 6.19
-// AVP: Chargable-User-Identity (89)
-type AVP_OctetString MIPv6_NONE_Chargable_User_Identity
-
-// RFC 5778 6.20
-// AVP: MIP6-Auth-Mode (494)
-type AVP_Unsigned32 MIPv6_NONE_MIP6_Auth_Mode
-/******************************************************************************
-* Copyright (c) 2000-2019 Ericsson Telecom AB
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Eclipse Public License v2.0
-* which accompanies this distribution, and is available at
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
-*
-* Contributors:
* Gabor Szalai - initial implementation
******************************************************************************/
//
@@ -3521,6 +4773,7 @@ type AVP_Unsigned32 MIPv6_NONE_MIP6_Auth_Mode
//
// 3GPP TS 29.214 15.2.0 5.6
+// WARNING: Enumeration item with code (265) exists in type Command_Code
// WARNING: Enumeration item with code (258) exists in type Command_Code
// WARNING: Enumeration item with code (275) exists in type Command_Code
// WARNING: Enumeration item with code (274) exists in type Command_Code
@@ -3955,999 +5208,6 @@ type AVP_Unsigned32 RX_3GPP_Extended_Min_Requested_BW_UL
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
-* Roland Gecse - initial implementation and initial documentation
-* Akos Pernek
-* Antal Wuh.Hen.Chang
-* Attila Fulop
-* Balazs Barcsik
-* Bence Molnar
-* Csaba Koppany
-* David Juhasz
-* Eduard Czimbalmos
-* Elemer Lelik
-* Endre Kiss
-* Endre Kulcsar
-* Gabor Szalai
-* Gabor Tatarka
-* Gergely Futo
-* Istvan Sandor
-* Krisztian Pandi
-* Kulcsár Endre
-* Laszlo Tamas Zeke
-* Norbert Pinter
-* Roland Gecse
-* Tibor Bende
-* Tibor Szabo
-* Timea Moder
-* Zoltan Medve
-* Zsolt Nandor Torok
-* Zsolt Szalai
-******************************************************************************/
-//
-// File: NetworkAccessServer_IETF_RFC4005.ddf
-// Description: DDF for NAS according to RFC 4005
-// Rev: R55A
-// Prodnr: CNL113462
-///////////////////////////////////////////////
-
-// APPLICATION-NAME: DNAS
-// APPLICATION-REVISION: RFC4005
-
-// AVP implementations according to:
-// RFC 4005 - Diameter Network Access Server Application
-//
-
-// RFC 4005 3
-// WARNING: Enumeration item with code (265) exists in type Command_Code
-// WARNING: Enumeration item with code (258) exists in type Command_Code
-// WARNING: Enumeration item with code (275) exists in type Command_Code
-// WARNING: Enumeration item with code (274) exists in type Command_Code
-// WARNING: Enumeration item with code (271) exists in type Command_Code
-
-
-// RFC 4005
-// AVP: NAS-Port (5)
-// 4.2
-type AVP_Unsigned32 DNAS_NONE_NAS_Port
-
-// RFC 4005
-// AVP: NAS-Port-Id (87)
-// 4.3
-type AVP_UTF8String DNAS_NONE_NAS_Port_Id
-
-// RFC 4005
-// AVP: NAS-Port-Type (61)
-// 4.4
-type AVP_Unsigned32 DNAS_NONE_NAS_Port_Type
-
-// RFC 4005
-// AVP: Called-Station-Id (30)
-// 4.5
-type AVP_UTF8String DNAS_NONE_Called_Station_Id
-
-// RFC 4005
-// AVP: Calling-Station-Id (31)
-// 4.6
-type AVP_UTF8String DNAS_NONE_Calling_Station_Id
-
-// RFC 4005
-// AVP: Connect-Info (77)
-// 4.7
-type AVP_UTF8String DNAS_NONE_Connect_Info
-
-// RFC 4005
-// AVP: Originating-Line-Info (94)
-// 4.8
-type AVP_OctetString DNAS_NONE_Originating_Line_Info
-
-// RFC 4005
-// AVP: Reply-Message (18)
-// 4.9
-type AVP_UTF8String DNAS_NONE_Reply_Message
-
-
-
-// RFC 4005
-// AVP: User-Password (2)
-// 5.1
-type AVP_OctetString DNAS_NONE_User_Password
-
-// RFC 4005
-// AVP: Password-Retry (75)
-// 5.2
-type AVP_Unsigned32 DNAS_NONE_Password_Retry
-
-// RFC 4005
-// AVP: Prompt (76)
-// 5.3
-type enumerated DNAS_NONE_Prompt {
- NO_ECHO (0),
- ECHO (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: CHAP-Auth (402)
-// 5.4
-type AVP_Grouped DNAS_NONE_CHAP_Auth
-
-// RFC 4005
-// AVP: CHAP-Algorithm (403)
-// 5.5
-type enumerated DNAS_NONE_CHAP_Algorithm {
- CHAP_with_MD5 (5)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: CHAP-Ident (404)
-// 5.6
-type AVP_OctetString DNAS_NONE_CHAP_Ident
-
-// RFC 4005
-// AVP: CHAP-Response (405)
-// 5.7
-type AVP_OctetString DNAS_NONE_CHAP_Response
-
-// RFC 4005
-// AVP: CHAP-Challenge (60)
-// 5.8
-type AVP_OctetString DNAS_NONE_CHAP_Challenge
-
-// RFC 4005
-// AVP: ARAP-Password (70)
-// 5.9
-type AVP_OctetString DNAS_NONE_ARAP_Password
-
-// RFC 4005
-// AVP: ARAP-Challenge-Response (84)
-// 5.10
-type AVP_OctetString DNAS_NONE_ARAP_Challenge_Response
-
-// RFC 4005
-// AVP: ARAP-Security (73)
-// 5.11
-type AVP_Unsigned32 DNAS_NONE_ARAP_Security
-
-// RFC 4005
-// AVP: ARAP-Security-Data (74)
-// 5.12
-type AVP_OctetString DNAS_NONE_ARAP_Security_Data
-
-
-
-// RFC 4005
-// AVP: Service-Type (6)
-// 6.1
-type AVP_Unsigned32 DNAS_NONE_Service_Type
-
-// RFC 4005
-// AVP: Callback-Number (19)
-// 6.2
-type AVP_UTF8String DNAS_NONE_Callback_Number
-
-// RFC 4005
-// AVP: Callback-Id (20)
-// 6.3
-type AVP_UTF8String DNAS_NONE_Callback_Id
-
-// RFC 4005
-// AVP: Idle-Timeout (28)
-// 6.4
-type AVP_Unsigned32 DNAS_NONE_Idle_Timeout
-
-// RFC 4005
-// AVP: Port-Limit (62)
-// 6.5
-type AVP_Unsigned32 DNAS_NONE_Port_Limit
-
-// RFC 4005
-// AVP: NAS-Filter-Rule (400)
-// 6.6
-type AVP_IPFilterRule DNAS_NONE_NAS_Filter_Rule
-
-// RFC 4005
-// AVP: Filter-Id (11)
-// 6.7
-type AVP_UTF8String DNAS_NONE_Filter_Id
-
-// RFC 4005
-// AVP: Configuration-Token (78)
-// 6.8
-type AVP_OctetString DNAS_NONE_Configuration_Token
-
-// RFC 4005
-// AVP: QoS-Filter-Rule (407)
-// 6.9
-type AVP_QoSFilterRule DNAS_NONE_QoS_Filter_Rule
-
-// RFC 4005
-// AVP: Framed-Protocol (7)
-// 6.10.1
-type enumerated DNAS_NONE_Framed_Protocol {
- PPP (1),
- SLIP (2),
- ARAP (3),
- GANDALF (4),
- XYLOGICS (5),
- X_75_SYNCHRONOUS (6),
- GPRS_PDP_CONTEXT (7)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Framed-Routing (10)
-// 6.10.2
-type enumerated DNAS_NONE_Framed_Routing {
- NONE (0),
- SEND_ROUTING_PACKETS (1),
- LISTEN_FOR_ROUTING_PACKETS (2),
- SEND_AND_LISTEN (3)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Framed-MTU (12)
-// 6.10.3
-type AVP_Unsigned32 DNAS_NONE_Framed_MTU
-
-// RFC 4005
-// AVP: Framed-Compression (13)
-// 6.10.4
-type enumerated DNAS_NONE_Framed_Compression {
- NONE (0),
- VJ_TCP_IP_HEADER_COMPRESSION (1),
- IPX_HEADER_COMPRESSION (2),
- STAC_LZS_COMPRESSION (3)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Framed-IP-Address (8)
-// 6.11.1
-type AVP_OctetString DNAS_NONE_Framed_IP_Address
-
-// RFC 4005
-// AVP: Framed-IP-Netmask (9)
-// 6.11.2
-type AVP_OctetString DNAS_NONE_Framed_IP_Netmask
-
-// RFC 4005
-// AVP: Framed-Route (22)
-// 6.11.3
-type AVP_UTF8String DNAS_NONE_Framed_Route
-
-// RFC 4005
-// AVP: Framed-Pool (88)
-// 6.11.4
-type AVP_OctetString DNAS_NONE_Framed_Pool
-
-// RFC 4005
-// AVP: Framed-Interface-Id (96)
-// 6.11.5
-type AVP_Unsigned64 DNAS_NONE_Framed_Interface_Id
-
-// RFC 4005
-// AVP: Framed-IPv6-Prefix (97)
-// 6.11.6
-type AVP_OctetString DNAS_NONE_Framed_IPv6_Prefix
-
-// RFC 4005
-// AVP: Framed-IPv6-Route (99)
-// 6.11.7
-type AVP_UTF8String DNAS_NONE_Framed_IPv6_Route
-
-// RFC 4005
-// AVP: Framed-IPv6-Pool (100)
-// 6.11.8
-type AVP_OctetString DNAS_NONE_Framed_IPv6_Pool
-
-// RFC 4005
-// AVP: Framed-IPX-Network (23)
-// 6.12.1
-type AVP_UTF8String DNAS_NONE_Framed_IPX_Network
-
-// RFC 4005
-// AVP: Framed-Appletalk-Link (37)
-// 6.13.1
-type AVP_Unsigned32 DNAS_NONE_Framed_Appletalk_Link
-
-// RFC 4005
-// AVP: Framed-Appletalk-Network (38)
-// 6.13.2
-type AVP_Unsigned32 DNAS_NONE_Framed_Appletalk_Network
-
-// RFC 4005
-// AVP: Framed-Appletalk-Zone (39)
-// 6.13.3
-type AVP_OctetString DNAS_NONE_Framed_Appletalk_Zone
-
-// RFC 4005
-// AVP: ARAP-Features (71)
-// 6.14.1
-type AVP_OctetString DNAS_NONE_ARAP_Features
-
-// RFC 4005
-// AVP: ARAP-Zone-Access (72)
-// 6.14.2
-type enumerated DNAS_NONE_ARAP_Zone_Access {
- ONLY_ALLOW_ACCESS_TO_DEFAULT_ZONE (1),
- USE_ZONE_FILTER_INCLUSIVELY (2),
- USE_ZONE_FILTER_EXCLUSIVELY (4)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Login-IP-Host (14)
-// 6.15.1
-type AVP_OctetString DNAS_NONE_Login_IP_Host
-
-// RFC 4005
-// AVP: Login-IPv6-Host (98)
-// 6.15.2
-type AVP_OctetString DNAS_NONE_Login_IPv6_Host
-
-// RFC 4005
-// AVP: Login-Service (15)
-// 6.15.3
-type enumerated DNAS_NONE_Login_Service {
- TELNET (0),
- RLOGIN (1),
- TCP_CLEAR (2),
- PORTMASTER (3),
- LAT (4),
- X25_PAD (5),
- X25_T3POS (6),
- TCP_CLEAR_QUIET (8)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Login-TCP-Port (16)
-// 6.16.1
-type AVP_Unsigned32 DNAS_NONE_Login_TCP_Port
-
-// RFC 4005
-// AVP: Login-LAT-Service (34)
-// 6.17.1
-type AVP_OctetString DNAS_NONE_Login_LAT_Service
-
-// RFC 4005
-// AVP: Login-LAT-Node (35)
-// 6.17.2
-type AVP_OctetString DNAS_NONE_Login_LAT_Node
-
-// RFC 4005
-// AVP: Login-LAT-Group (36)
-// 6.17.3
-type AVP_OctetString DNAS_NONE_Login_LAT_Group
-
-// RFC 4005
-// AVP: Login-LAT-Port (63)
-// 6.17.4
-type AVP_OctetString DNAS_NONE_Login_LAT_Port
-
-
-
-// RFC 4005
-// AVP: Tunneling (401)
-// 7.1
-type AVP_Grouped DNAS_NONE_Tunneling
-
-// RFC 4005
-// AVP: Tunnel-Type (64)
-// 7.2
-type AVP_Unsigned32 DNAS_NONE_Tunnel_Type
-
-// RFC 4005
-// AVP: Tunnel-Medium-Type (65)
-// 7.3
-type AVP_Unsigned32 DNAS_NONE_Tunnel_Medium_Type
-
-// RFC 4005
-// AVP: Tunnel-Client-Endpoint (66)
-// 7.4
-type AVP_UTF8String DNAS_NONE_Tunnel_Client_Endpoint
-
-// RFC 4005
-// AVP: Tunnel-Server-Endpoint (67)
-// 7.5
-type AVP_UTF8String DNAS_NONE_Tunnel_Server_Endpoint
-
-// RFC 4005
-// AVP: Tunnel-Password (69)
-// 7.6
-type AVP_OctetString DNAS_NONE_Tunnel_Password
-
-// RFC 4005
-// AVP: Tunnel-Private-Group-Id (81)
-// 7.7
-type AVP_OctetString DNAS_NONE_Tunnel_Private_Group_Id
-
-// RFC 4005
-// AVP: Tunnel-Assignment-Id (82)
-// 7.8
-type AVP_OctetString DNAS_NONE_Tunnel_Assignment_Id
-
-// RFC 4005
-// AVP: Tunnel-Preference (83)
-// 7.9
-type AVP_Unsigned32 DNAS_NONE_Tunnel_Preference
-
-// RFC 4005
-// AVP: Tunnel-Client-Auth-Id (90)
-// 7.10
-type AVP_UTF8String DNAS_NONE_Tunnel_Client_Auth_Id
-
-// RFC 4005
-// AVP: Tunnel-Server-Auth-Id (91)
-// 7.11
-type AVP_UTF8String DNAS_NONE_Tunnel_Server_Auth_Id
-
-
-
-// RFC 4005
-// AVP: Accounting-Input-Octets (363)
-// 8.1
-type AVP_Unsigned64 DNAS_NONE_Accounting_Input_Octets
-
-// RFC 4005
-// AVP: Accounting-Output-Octets (364)
-// 8.2
-type AVP_Unsigned64 DNAS_NONE_Accounting_Output_Octets
-
-// RFC 4005
-// AVP: Accounting-Input-Packets (365)
-// 8.3
-type AVP_Unsigned64 DNAS_NONE_Accounting_Input_Packets
-
-// RFC 4005
-// AVP: Accounting-Output-Packets (366)
-// 8.4
-type AVP_Unsigned64 DNAS_NONE_Accounting_Output_Packets
-
-// RFC 4005
-// AVP: Acct-Session-Time (46)
-// 8.5
-type AVP_Unsigned32 DNAS_NONE_Acct_Session_Time
-
-// RFC 4005
-// AVP: Acct-Authentic (45)
-// 8.6
-type enumerated DNAS_NONE_Acct_Authentic {
- RADIUS (1),
- LOCAL (2),
- REMOTE (3),
- DIAMETER (4)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Accounting-Auth-Method (406)
-// 8.7
-type enumerated DNAS_NONE_Accounting_Auth_Method {
- PAP (1),
- CHAP (2),
- MS_CHAP_1 (3),
- MS_CHAP_2 (4),
- EAP (5),
- None (7)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4005
-// AVP: Acct-Delay-Time (41)
-// 8.8
-type AVP_Unsigned32 DNAS_NONE_Acct_Delay_Time
-
-// RFC 4005
-// AVP: Acct-Link-Count (51)
-// 8.9
-type AVP_Unsigned32 DNAS_NONE_Acct_Link_Count
-
-// RFC 4005
-// AVP: Acct-Tunnel-Connection (68)
-// 8.10
-type AVP_OctetString DNAS_NONE_Acct_Tunnel_Connection
-
-// RFC 4005
-// AVP: Acct-Tunnel-Packets-Lost (86)
-// 8.11
-type AVP_Unsigned32 DNAS_NONE_Acct_Tunnel_Packets_Lost
-
-
-
-// RFC 4005
-// AVP: NAS-Identifier (32)
-// 9.3.1
-type AVP_UTF8String DNAS_NONE_NAS_Identifier
-
-// RFC 4005
-// AVP: NAS-IP-Address (4)
-// 9.3.2
-type AVP_OctetString DNAS_NONE_NAS_IP_Address
-
-// RFC 4005
-// AVP: NAS-IPv6-Address (95)
-// 9.3.3
-type AVP_OctetString DNAS_NONE_NAS_IPv6_Address
-
-// RFC 4005
-// AVP: State (24)
-// 9.3.4
-type AVP_OctetString DNAS_NONE_State
-
-// RFC 4005
-// AVP: Origin-AAA-Protocol (408)
-// 9.3.6
-type enumerated DNAS_NONE_Origin_AAA_Protocol {
- RADIUS (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-/******************************************************************************
-* Copyright (c) 2000-2019 Ericsson Telecom AB
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Eclipse Public License v2.0
-* which accompanies this distribution, and is available at
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
-*
-* Contributors:
-* Roland Gecse - initial implementation and initial documentation
-* Akos Pernek
-* Antal Wuh.Hen.Chang
-* Attila Fulop
-* Balazs Barcsik
-* Bence Molnar
-* Csaba Koppany
-* David Juhasz
-* Eduard Czimbalmos
-* Elemer Lelik
-* Endre Kiss
-* Endre Kulcsar
-* Gabor Szalai
-* Gabor Tatarka
-* Gergely Futo
-* Istvan Sandor
-* Krisztian Pandi
-* Kulcsár Endre
-* Laszlo Tamas Zeke
-* Norbert Pinter
-* Roland Gecse
-* Tibor Bende
-* Tibor Szabo
-* Timea Moder
-* Zoltan Medve
-* Zsolt Nandor Torok
-* Zsolt Szalai
-******************************************************************************/
-//
-// File: CreditControl_IETF_RFC4006.ddf
-// Description: DDF for DCC according to RFC 4006
-// Rev: R55A
-// Prodnr: CNL 1134 62
-///////////////////////////////////////////////
-
-// APPLICATION-NAME: DCC
-// APPLICATION-REVISION: RFC4006
-
-// AVP implementations according to:
-// RFC 4006 - Diameter Credit Control Application
-// IS for Additional Billing for Verizon in MTAS 125/1594-FCP 101 8664 Uen PA8
-
-// RFC 4006 12.2
-// WARNING: Enumeration item with code (272) exists in type Command_Code
-
-
-// RFC 4006
-// AVP: CC-Correlation-Id (411)
-// 8.1
-type AVP_OctetString DCC_NONE_CC_Correlation_Id
-
-// RFC 4006
-// AVP: CC-Input-Octets (412)
-// 8.24
-type AVP_Unsigned64 DCC_NONE_CC_Input_Octets
-
-// RFC 4006
-// AVP: CC-Money (413)
-// 8.22
-type AVP_Grouped DCC_NONE_CC_Money
-
-// RFC 4006
-// AVP: CC-Output-Octets (414)
-// 8.25
-type AVP_Unsigned64 DCC_NONE_CC_Output_Octets
-
-// RFC 4006
-// AVP: CC-Request-Number (415)
-// 8.2
-type AVP_Unsigned32 DCC_NONE_CC_Request_Number
-
-// RFC 4006
-// AVP: CC-Request-Type (416)
-// 8.3
-type enumerated DCC_NONE_CC_Request_Type {
- INITIAL_REQUEST (1),
- UPDATE_REQUEST (2),
- TERMINATION_REQUEST (3),
- EVENT_REQUEST (4)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: CC-Service-Specific-Units (417)
-// 8.26
-type AVP_Unsigned64 DCC_NONE_CC_Service_Specific_Units
-
-// RFC 4006
-// AVP: CC-Session-Failover (418)
-// 8.4
-type enumerated DCC_NONE_CC_Session_Failover {
- FAILOVER_NOT_SUPPORTED (0),
- FAILOVER_SUPPORTED (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: CC-Sub-Session-Id (419)
-// 8.5
-type AVP_Unsigned64 DCC_NONE_CC_Sub_Session_Id
-
-// RFC 4006
-// AVP: CC-Time (420)
-// 8.21
-type AVP_Unsigned32 DCC_NONE_CC_Time
-
-// RFC 4006
-// AVP: CC-Total-Octets (421)
-// 8.23
-type AVP_Unsigned64 DCC_NONE_CC_Total_Octets
-
-// RFC 4006
-// AVP: CC-Unit-Type (454)
-// 8.32
-type enumerated DCC_NONE_CC_Unit_Type {
- TIME (0),
- MONEY (1),
- TOTAL_OCTETS (2),
- INPUT_OCTETS (3),
- OUTPUT_OCTETS (4),
- SERVICE_SPECIFIC_UNITS (5)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Check-Balance-Result (422)
-// 8.6
-type enumerated DCC_NONE_Check_Balance_Result {
- ENOUGH_CREDIT (0),
- NO_CREDIT (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Cost-Information (423)
-// 8.7
-type AVP_Grouped DCC_NONE_Cost_Information
-
-// RFC 4006
-// AVP: Cost-Unit (424)
-// 8.12
-type AVP_UTF8String DCC_NONE_Cost_Unit
-
-// RFC 4006
-// AVP: Credit-Control (426)
-// 8.13
-type enumerated DCC_NONE_Credit_Control {
- CREDIT_AUTHORIZATION (0),
- RE_AUTHORIZATION (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Credit-Control-Failure-Handling (427)
-// 8.14
-type enumerated DCC_NONE_Credit_Control_Failure_Handling {
- TERMINATE (0),
- CONTINUE (1),
- RETRY_AND_TERMINATE (2)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Currency-Code (425)
-// 8.11
-type AVP_Unsigned32 DCC_NONE_Currency_Code
-
-// RFC 4006
-// AVP: Direct-Debiting-Failure-Handling (428)
-// 8.15
-type enumerated DCC_NONE_Direct_Debiting_Failure_Handling {
- TERMINATE_OR_BUFFER (0),
- CONTINUE (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Exponent (429)
-// 8.9
-type AVP_Integer32 DCC_NONE_Exponent
-
-// RFC 4006
-// AVP: Final-Unit-Action (449)
-// 8.35
-type enumerated DCC_NONE_Final_Unit_Action {
- TERMINATE (0),
- REDIRECT (1),
- RESTRICT_ACCESS (2)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Final-Unit-Indication (430)
-// 8.34
-type AVP_Grouped DCC_NONE_Final_Unit_Indication
-
-// RFC 4006
-// AVP: Granted-Service-Unit (431)
-// 8.17
-type AVP_Grouped DCC_NONE_Granted_Service_Unit
-
-// RFC 4006
-// AVP: G-S-U-Pool-Identifier (453)
-// 8.31
-type AVP_Unsigned32 DCC_NONE_G_S_U_Pool_Identifier
-
-// RFC 4006
-// AVP: G-S-U-Pool-Reference (457)
-// 8.30
-type AVP_Grouped DCC_NONE_G_S_U_Pool_Reference
-
-// RFC 4006
-// AVP: Multiple-Services-Credit-Control (456)
-// 8.16
-type AVP_Grouped DCC_NONE_Multiple_Services_Credit_Control
-
-// RFC 4006
-// AVP: Multiple-Services-Indicator (455)
-// 8.40
-type enumerated DCC_NONE_Multiple_Services_Indicator {
- MULTIPLE_SERVICES_NOT_SUPPORTED (0),
- MULTIPLE_SERVICES_SUPPORTED (1)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Rating-Group (432)
-// 8.29
-type AVP_Unsigned32 DCC_NONE_Rating_Group
-
-// RFC 4006
-// AVP: Redirect-Address-Type (433)
-// 8.38
-type enumerated DCC_NONE_Redirect_Address_Type {
- IPV4_ADDRESS (0),
- IPV6_ADDRESS (1),
- URL (2),
- SIP_URI (3)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Redirect-Server (434)
-type AVP_Grouped DCC_NONE_Redirect_Server
-
-// RFC 4006
-// AVP: Redirect-Server-Address (435)
-// 8.37
-type AVP_UTF8String DCC_NONE_Redirect_Server_Address
-
-// RFC 4006
-// AVP: Requested-Action (436)
-// 8.41
-type enumerated DCC_NONE_Requested_Action {
- DIRECT_DEBITING (0),
- REFUND_ACCOUNT (1),
- CHECK_BALANCE (2),
- PRICE_ENQUIRY (3)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Requested-Service-Unit (437)
-// 8.18
-type AVP_Grouped DCC_NONE_Requested_Service_Unit
-
-// RFC 4006
-// AVP: Restriction-Filter-Rule (438)
-// 8.36
-type AVP_IPFilterRule DCC_NONE_Restriction_Filter_Rule
-
-// RFC 4006
-// AVP: Service-Context-Id (461)
-// 8.42
-type AVP_UTF8String DCC_NONE_Service_Context_Id
-
-// RFC 4006
-// AVP: Service-Identifier (439)
-// 8.28
-type AVP_Unsigned32 DCC_NONE_Service_Identifier
-
-// RFC 4006
-// AVP: Service-Parameter-Info (440)
-// 8.43
-type AVP_Grouped DCC_NONE_Service_Parameter_Info
-
-// RFC 4006
-// AVP: Service-Parameter-Type (441)
-// 8.44
-type AVP_Unsigned32 DCC_NONE_Service_Parameter_Type
-
-// RFC 4006
-// AVP: Service-Parameter-Value (442)
-// 8.45
-type AVP_OctetString DCC_NONE_Service_Parameter_Value
-
-// RFC 4006
-// AVP: Subscription-Id (443)
-// 8.46
-type AVP_Grouped DCC_NONE_Subscription_Id
-
-// RFC 4006
-// AVP: Subscription-Id-Data (444)
-// 8.48
-type AVP_UTF8String DCC_NONE_Subscription_Id_Data
-
-// RFC 4006
-// AVP: Subscription-Id-Type (450)
-// 8.47
-type enumerated DCC_NONE_Subscription_Id_Type {
- END_USER_E164 (0),
- END_USER_IMSI (1),
- END_USER_SIP_URI (2),
- END_USER_NAI (3),
- END_USER_PRIVATE (4)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Tariff-Change-Usage (452)
-// 8.27
-type enumerated DCC_NONE_Tariff_Change_Usage {
- UNIT_BEFORE_TARIFF_CHANGE (0),
- UNIT_AFTER_TARIFF_CHANGE (1),
- UNIT_INDETERMINATE (2)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: Tariff-Time-Change (451)
-// 8.20
-type AVP_Time DCC_NONE_Tariff_Time_Change
-
-// RFC 4006
-// AVP: Unit-Value (445)
-// 8.8
-type AVP_Grouped DCC_NONE_Unit_Value
-
-// RFC 4006
-// AVP: Used-Service-Unit (446)
-// 8.19
-type AVP_Grouped DCC_NONE_Used_Service_Unit
-
-// RFC 4006
-// AVP: User-Equipment-Info (458)
-// 8.49
-type AVP_Grouped DCC_NONE_User_Equipment_Info
-
-// RFC 4006, 125/1594-FCP 101 8664
-// AVP: User-Equipment-Info-Type (459)
-// RFC 4006 section 8.50, 125/1594-FCP 101 8664 section 3.3.12
-type enumerated DCC_NONE_User_Equipment_Info_Type {
- IMEISV (0),
- MAC (1),
- EUI64 (2),
- MODIFIED_EUI64 (3),
- ESN (4),
- MEID (5)
-} with {
- variant "FIELDLENGTH(32)"
- variant "BYTEORDER(last)"
- variant "COMP(2scompl)"
-}
-
-// RFC 4006
-// AVP: User-Equipment-Info-Value (460)
-// 8.51
-type AVP_OctetString DCC_NONE_User_Equipment_Info_Value
-
-// RFC 4006
-// AVP: Value-Digits (447)
-// 8.10
-type AVP_Integer64 DCC_NONE_Value_Digits
-
-// RFC 4006
-// AVP: Validity-Time (448)
-// 8.33
-type AVP_Unsigned32 DCC_NONE_Validity_Time
-
-/******************************************************************************
-* Copyright (c) 2000-2019 Ericsson Telecom AB
-* All rights reserved. This program and the accompanying materials
-* are made available under the terms of the Eclipse Public License v2.0
-* which accompanies this distribution, and is available at
-* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
-*
-* Contributors:
* Gabor Szalai - initial implementation and initial documentation
******************************************************************************/
//
@@ -5556,11 +5816,2978 @@ type AVP_Unsigned32 GI_3GPP_3GPP_User_Location_Info_Time
-// STATISTICS: 740 AVP descriptors found
-// STATISTICS: 740 AVP type definitions matching AVP descriptors found
-// STATISTICS: duplicate AVP definitions deleted
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Akos Makovics - initial implementation and initial documentation
+* Gabor Szalai
+* Timea Moder
+******************************************************************************/
+//
+// File: ChargingApplications_3GPP_TS32299_d90.ddf
+// Description: DDF for Diameter Charging Application 3GPP TS 32.299 V13.9.0
+// Rev: R55A
+// Prodnr: CNL 113 462
+///////////////////////////////////////////////
+
+
+// APPLICATION-NAME: DCA
+// APPLICATION-REVISION: V13_9_0
+
+// AVP implementations according to:
+// 3GPP TS 32.299 V13.9.0 - Telecommunication management; Charging management;
+//
+//
+// Dependant applications
+// 3GPP TS 29.229 - Cx and Dx interfaces based on the Diameter protocol
+// IETF RFC 3588 - Diameter Base Protocol
+// RFC 4006 - Diameter Credit Control Application
+//
+// Notes:
+//
+
+
+// 3GPP TS 32.299 V13.9.0
+// WARNING: Enumeration item with code (271) exists in type Command_Code
+// WARNING: Enumeration item with code (258) exists in type Command_Code
+
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Access-Network-Information (1263) 3GPP (10415)
+// 7.2.1
+type AVP_OctetString DCA_3GPP_Access_Network_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Access-Transfer-Information (2709) 3GPP (10415)
+// 7.2.1A
+type AVP_Grouped DCA_3GPP_Access_Transfer_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Access-Transfer-Type (2710) 3GPP (10415)
+// 7.2.1.B
+type enumerated DCA_3GPP_Access_Transfer_Type {
+ PS_to_CS_Transfer (0),
+ CS_to_PS_Transfer (1),
+ PS_to_PS_Transfer (2),
+ CS_to_CS_Transfer (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Account-Expiration (2309) 3GPP (10415)
+// 7.2.2
+type AVP_Time DCA_3GPP_Account_Expiration
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Accumulated-Cost (2052) 3GPP (10415)
+// 7.2.3
+type AVP_Grouped DCA_3GPP_Accumulated_Cost
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Adaptations (1217) 3GPP (10415)
+// 7.2.4
+type enumerated DCA_3GPP_Adaptations {
+ YES (0),
+ NO (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Additional-Content-Information (1207) 3GPP (10415)
+// 7.2.5
+type AVP_Grouped DCA_3GPP_Additional_Content_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Additional-Exception-Reports (3936) 3GPP (10415)
+// 7.2.5A
+type enumerated DCA_3GPP_Additional_Exception_Reports {
+ NOT_ALLOWED (0),
+ ALLOWED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Additional-Type-Information (1205) 3GPP (10415)
+// 7.2.6
+type AVP_UTF8String DCA_3GPP_Additional_Type_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Address-Data (897) 3GPP (10415)
+// 7.2.7
+type AVP_UTF8String DCA_3GPP_Address_Data
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Address-Domain (898) 3GPP (10415)
+// 7.2.8
+type AVP_Grouped DCA_3GPP_Address_Domain
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Address-Type (899) 3GPP (10415)
+// 7.2.9
+type enumerated DCA_3GPP_Address_Type {
+ E_MAIL_ADDRESS (0),
+ MSISDN (1),
+ IPV4_ADDRESS (2),
+ IPV6_ADDRESS (3),
+ NUMERIC_SHORTCODE (4),
+ ALPHANUMERIC_SHORTCODE (5),
+ OTHER (6),
+ IMSI (7)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Addressee-Type (1208) 3GPP (10415)
+// 7.2.10
+type enumerated DCA_3GPP_Addressee_Type {
+ TO (0),
+ CC (1),
+ BCC (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AF-Correlation-Information (1276) 3GPP (10415)
+// 7.2.11
+type AVP_Grouped DCA_3GPP_AF_Correlation_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Alternate-Charged-Party-Address (1280) 3GPP (10415)
+// 7.2.12
+type AVP_UTF8String DCA_3GPP_Alternate_Charged_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Announcement-Identifier (3905) 3GPP (10415)
+// 7.2.12aA
+type AVP_Unsigned32 DCA_3GPP_Announcement_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Announcement-Information (3904) 3GPP (10415)
+// 7.2.12aB
+type AVP_Grouped DCA_3GPP_Announcement_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Announcement-Order (3906) 3GPP (10415)
+// 7.2.12aC
+type AVP_Unsigned32 DCA_3GPP_Announcement_Order
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Announcing-UE-HPLMN-Identifier (3426) 3GPP (10415)
+// 7.2.12A
+type AVP_UTF8String DCA_3GPP_Announcing_UE_HPLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Announcing-UE-VPLMN-Identifier (3427) 3GPP (10415)
+// 7.2.12B
+type AVP_UTF8String DCA_3GPP_Announcing_UE_VPLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Cost-Information (2053) 3GPP (10415)
+// 7.2.13
+type AVP_Grouped DCA_3GPP_AoC_Cost_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Format (2310) 3GPP (10415)
+// 7.2.14
+type enumerated DCA_3GPP_AoC_Format {
+ MONETARY (0),
+ NON_MONETARY (1),
+ CAI (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Information (2054) 3GPP (10415)
+// 7.2.15
+type AVP_Grouped DCA_3GPP_AoC_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Request-Type (2055) 3GPP (10415)
+// 7.2.16
+type enumerated DCA_3GPP_AoC_Request_Type {
+ AoC_NOT_REQUESTED (0),
+ AoC_FULL (1),
+ AoC_COST_ONLY (2),
+ AoC_TARIFF_ONLY (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Service (2311) 3GPP (10415)
+// 7.2.17
+type AVP_Grouped DCA_3GPP_AoC_Service
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Service-Obligatory-Type (2312) 3GPP (10415)
+// 7.2.18
+type enumerated DCA_3GPP_AoC_Service_Obligatory_Type {
+ NON_BINDING (0),
+ BINDING (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Service-Type (2313) 3GPP (10415)
+// 7.2.19
+type enumerated DCA_3GPP_AoC_Service_Type {
+ NONE (0),
+ AOC_S (1),
+ AOC_D (2),
+ AOC_E (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: AoC-Subscription-Information (2314) 3GPP (10415)
+// 7.2.20
+type AVP_Grouped DCA_3GPP_AoC_Subscription_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: APN-Rate-Control (3933) 3GPP (10415)
+// 7.2.20A
+type AVP_Grouped DCA_3GPP_APN_Rate_Control
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: APN-Rate-Control-Downlink (3934) 3GPP (10415)
+// 7.2.20B
+type AVP_Grouped DCA_3GPP_APN_Rate_Control_Downlink
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: APN-Rate-Control-Uplink (3935) 3GPP (10415)
+// 7.2.20B
+type AVP_Grouped DCA_3GPP_APN_Rate_Control_Uplink
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Applic-ID (1218) 3GPP (10415)
+// 7.2.21
+type AVP_UTF8String DCA_3GPP_Applic_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Application-provided-Called-Party-Address (837) 3GPP (10415)
+// 7.2.22
+type AVP_UTF8String DCA_3GPP_Application_provided_Called_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Application-Server (836) 3GPP (10415)
+// 7.2.23
+type AVP_UTF8String DCA_3GPP_Application_Server
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Application-Server-Information (850) 3GPP (10415)
+// 7.2.24
+type AVP_Grouped DCA_3GPP_Application_Server_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Application-Specific-Data (3458) 3GPP (10415)
+// 7.2.24A
+type AVP_OctetString DCA_3GPP_Application_Specific_Data
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Associated-Party-Address (2035) 3GPP (10415)
+// 7.2.25
+type AVP_UTF8String DCA_3GPP_Associated_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Associated-URI (856) 3GPP (10415)
+// 7.2.26
+type AVP_UTF8String DCA_3GPP_Associated_URI
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Authorised-QoS (849) 3GPP (10415)
+// 7.2.27
+type AVP_UTF8String DCA_3GPP_Authorised_QoS
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Aux-Applic-Info (1219) 3GPP (10415)
+// 7.2.28
+type AVP_UTF8String DCA_3GPP_Aux_Applic_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Base-Time-Interval (1265) 3GPP (10415)
+// 7.2.29
+type AVP_Unsigned32 DCA_3GPP_Base_Time_Interval
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Basic-Service-Code (3411) 3GPP (10415)
+// 7.2.29A
+type AVP_Grouped DCA_3GPP_Basic_Service_Code
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Bearer-Capability (3412) 3GPP (10415)
+// 7.2.29B
+type AVP_OctetString DCA_3GPP_Bearer_Capability
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Bearer-Service (854) 3GPP (10415)
+// 7.2.30
+type AVP_OctetString DCA_3GPP_Bearer_Service
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: BSSID (2716) 3GPP (10415)
+// 7.2.30A
+type AVP_UTF8String DCA_3GPP_BSSID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Called-Asserted-Identity (1250) 3GPP (10415)
+// 7.2.31
+type AVP_UTF8String DCA_3GPP_Called_Asserted_Identity
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Called-Identity (3916) 3GPP (10415)
+// 7.2.31A
+type AVP_UTF8String DCA_3GPP_Called_Identity
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Called-Identity-Change (3917) 3GPP (10415)
+// 7.2.31B
+type AVP_Grouped DCA_3GPP_Called_Identity_Change
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Called-Party-Address (832) 3GPP (10415)
+// 7.2.32
+type AVP_UTF8String DCA_3GPP_Called_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Calling-Party-Address (831) 3GPP (10415)
+// 7.2.33
+type AVP_UTF8String DCA_3GPP_Calling_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Carrier-Select-Routing-Information (2023) 3GPP (10415)
+// 7.2.34
+type AVP_UTF8String DCA_3GPP_Carrier_Select_Routing_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Cause-Code (861) 3GPP (10415)
+// 7.2.35
+type AVP_Integer32 DCA_3GPP_Cause_Code
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CG-Address (846) 3GPP (10415)
+// 7.2.36
+type AVP_Address DCA_3GPP_CG_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Change-Condition (2037) 3GPP (10415)
+// 7.2.37
+type AVP_Integer32 DCA_3GPP_Change_Condition
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Change-Time (2038) 3GPP (10415)
+// 7.2.38
+type AVP_Time DCA_3GPP_Change_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Charge-Reason-Code (2118) 3GPP (10415)
+// 7.2.38A
+type enumerated DCA_3GPP_Charge_Reason_Code {
+ UNKNOWN (0),
+ USAGE (1),
+ COMMUNICATION_ATTEMPT_CHARGE (2),
+ SETUP_CHARGE (3),
+ ADD_ON_CHARGE (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Charged-Party (857) 3GPP (10415)
+// 7.2.39
+type AVP_UTF8String DCA_3GPP_Charged_Party
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Charging-Characteristics-Selection-Mode (2066) 3GPP (10415)
+// 7.2.39A
+type enumerated DCA_3GPP_Charging_Characteristics_Selection_Mode {
+ SERVING_NODE_SUPPLIED (0),
+ SUBSCRIPTION_SPECIFIC (1),
+ APN_SPECIFIC (2),
+ HOME_DEFAULT (3),
+ ROAMING_DEFAULT (4),
+ VISITING_DEFAULT (5)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Class-Identifier (1214) 3GPP (10415)
+// 7.2.40
+type enumerated DCA_3GPP_Class_Identifier {
+ PERSONAL (0),
+ ADVERTISMENT (1),
+ INFORMATIONAL (2),
+ AUTO (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Client-Address (2018) 3GPP (10415)
+// 7.2.41
+type AVP_Address DCA_3GPP_Client_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CN-Operator-Selection-Entity (3421) 3GPP (10415)
+// 7.2.41A
+type enumerated DCA_3GPP_CN_Operator_Selection_Entity {
+ SN_selected_by_UE (0),
+ SN_selected_by_network (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Content-Class (1220) 3GPP (10415)
+// 7.2.42
+type enumerated DCA_3GPP_Content_Class {
+ TEXT (0),
+ IMAGE_BASIC (1),
+ IMAGE_RICH (2),
+ VIDEO_BASIC (3),
+ VIDEO_RICH (4),
+ MEGAPIXEL (5),
+ CONTENT_BASIC (6),
+ CONTENT_RICH (7)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Content-Disposition (828) 3GPP (10415)
+// 7.2.43
+type AVP_UTF8String DCA_3GPP_Content_Disposition
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Content-Length (827) 3GPP (10415)
+// 7.2.44
+type AVP_Unsigned32 DCA_3GPP_Content_Length
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Content-Size (1206) 3GPP (10415)
+// 7.2.45
+type AVP_Unsigned32 DCA_3GPP_Content_Size
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Content-Type (826) 3GPP (10415)
+// 7.2.46
+type AVP_UTF8String DCA_3GPP_Content_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Coverage-Status (3428) 3GPP (10415)
+// 7.2.46aA
+type enumerated DCA_3GPP_Coverage_Status {
+ OUT_OF_COVERAGE (0),
+ IN_COVERAGE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Coverage-Info (3459) 3GPP (10415)
+// 7.2.46aaA
+type AVP_Grouped DCA_3GPP_Coverage_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CP-CIoT-EPS-Optimisation-Indicator (3930) 3GPP (10415)
+// 7.2.46abA
+type enumerated DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator {
+ NOT_APPLY (0),
+ APPLY (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CPDT-Information (3927) 3GPP (10415)
+// 7.2.46acA
+type AVP_Grouped DCA_3GPP_CPDT_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CSG-Access-Mode (2317) 3GPP (10415)
+// 7.2.46A
+type enumerated DCA_3GPP_CSG_Access_Mode {
+ CLOSED_MODE (0),
+ HYBRID_MODE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CSG-Membership-Indication (2318) 3GPP (10415)
+// 7.2.46B
+type enumerated DCA_3GPP_CSG_Membership_Indication {
+ NOT_CSG_MEMBER (0),
+ CSG_MEMBER (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Current-Tariff (2056) 3GPP (10415)
+// 7.2.47
+type AVP_Grouped DCA_3GPP_Current_Tariff
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: CUG-Information (2304) 3GPP (10415)
+// 7.2.48
+type AVP_OctetString DCA_3GPP_CUG_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Data-Coding-Scheme (2001) 3GPP (10415)
+// 7.2.49
+type AVP_Integer32 DCA_3GPP_Data_Coding_Scheme
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: DCD-Information (2115) 3GPP (10415)
+// 7.2.50
+type AVP_Grouped DCA_3GPP_DCD_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Deferred-Location-Event-Type (1230) 3GPP (10415)
+// 7.2.51
+type AVP_UTF8String DCA_3GPP_Deferred_Location_Event_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Delivery-Report-Requested (1216) 3GPP (10415)
+// 7.2.52
+type enumerated DCA_3GPP_Delivery_Report_Requested {
+ NO (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Destination-Interface (2002) 3GPP (10415)
+// 7.2.53
+type AVP_Grouped DCA_3GPP_Destination_Interface
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Diagnostics (2039) 3GPP (10415)
+// 7.2.54
+type AVP_Integer32 DCA_3GPP_Diagnostics
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Domain-Name (1200) 3GPP (10415)
+// 7.2.55
+type AVP_UTF8String DCA_3GPP_Domain_Name
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: DRM-Content (1221) 3GPP (10415)
+// 7.2.56
+type enumerated DCA_3GPP_DRM_Content {
+ NO (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Dynamic-Address-Flag (2051) 3GPP (10415)
+// 7.2.57
+type enumerated DCA_3GPP_Dynamic_Address_Flag {
+ STATIC (0),
+ DYNAMIC (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Dynamic-Address-Flag-Extension (2068) 3GPP (10415)
+// 7.2.57A
+type enumerated DCA_3GPP_Dynamic_Address_Flag_Extension {
+ STATIC (0),
+ DYNAMIC (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Early-Media-Description (1272) 3GPP (10415)
+// 7.2.58
+type AVP_Grouped DCA_3GPP_Early_Media_Description
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Enhanced-Diagnostics (3901) 3GPP (10415)
+// 7.2.58A
+type AVP_Grouped DCA_3GPP_Enhanced_Diagnostics
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Envelope (1266) 3GPP (10415)
+// 7.2.59
+type AVP_Grouped DCA_3GPP_Envelope
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Envelope-End-Time (1267) 3GPP (10415)
+// 7.2.60
+type AVP_Time DCA_3GPP_Envelope_End_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Envelope-Reporting (1268) 3GPP (10415)
+// 7.2.61
+type enumerated DCA_3GPP_Envelope_Reporting {
+ DO_NOT_REPORT_ENVELOPES (0),
+ REPORT_ENVELOPES (1),
+ REPORT_ENVELOPES_WITH_VOLUME (2),
+ REPORT_ENVELOPES_WITH_EVENTS (3),
+ REPORT_ENVELOPES_WITH_VOLUME_AND_EVENTS (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Envelope-Start-Time (1269) 3GPP (10415)
+// 7.2.62
+type AVP_Time DCA_3GPP_Envelope_Start_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ePDG-Address (3425) 3GPP (10415)
+// 7.2.62A
+type AVP_Address DCA_3GPP_ePDG_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Event (825) 3GPP (10415)
+// 7.2.63
+type AVP_UTF8String DCA_3GPP_Event
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Event-Charging-TimeStamp (1258) 3GPP (10415)
+// 7.2.64
+type AVP_Time DCA_3GPP_Event_Charging_TimeStamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Event-Type (823) 3GPP (10415)
+// 7.2.65
+type AVP_Grouped DCA_3GPP_Event_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Expires (888) 3GPP (10415)
+// 7.2.66
+type AVP_Unsigned32 DCA_3GPP_Expires
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: File-Repair-Supported (1224) 3GPP (10415)
+// 7.2.67
+type enumerated DCA_3GPP_File_Repair_Supported {
+ SUPPORTED (1),
+ NOT_SUPPORTED (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: From-Address (2708) 3GPP (10415)
+// 7.2.67A
+type AVP_UTF8String DCA_3GPP_From_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Forwarding-Pending (3415) 3GPP (10415)
+// 7.2.67aA
+type enumerated DCA_3GPP_Forwarding_Pending {
+ Forwarding_not_Pending (0),
+ Forwarding_Pending (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: GGSN-Address (847) 3GPP (10415)
+// 7.2.68
+type AVP_Address DCA_3GPP_GGSN_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IM-Information (2110) 3GPP (10415)
+// 7.2.69
+type AVP_Grouped DCA_3GPP_IM_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Incremental-Cost (2062) 3GPP (10415)
+// 7.2.70
+type AVP_Grouped DCA_3GPP_Incremental_Cost
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Instance-Id (3402) 3GPP (10415)
+// 7.2.70A
+type AVP_UTF8String DCA_3GPP_Instance_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Interface-Id (2003) 3GPP (10415)
+// 7.2.71
+type AVP_UTF8String DCA_3GPP_Interface_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Interface-Port (2004) 3GPP (10415)
+// 7.2.72
+type AVP_UTF8String DCA_3GPP_Interface_Port
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Interface-Text (2005) 3GPP (10415)
+// 7.2.73
+type AVP_UTF8String DCA_3GPP_Interface_Text
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Interface-Type (2006) 3GPP (10415)
+// 7.2.74
+type enumerated DCA_3GPP_Interface_Type {
+ UNKNOWN (0),
+ MOBILE_ORIGINATING (1),
+ MOBILE_TERMINATING (2),
+ APPLICATION_ORIGINATING (3),
+ APPLICATION_TERMINATION (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Application-Reference-Identifier (2601) 3GPP (10415)
+// 7.2.74A
+type AVP_UTF8String DCA_3GPP_IMS_Application_Reference_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Inter-UE-Transfer (3902) 3GPP (10415)
+// 7.2.74aA
+type enumerated DCA_3GPP_Inter_UE_Transfer {
+ INTRA_UE_TRANSFER (0),
+ INTER_UE_TRANSFER (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Charging-Identifier (841) 3GPP (10415)
+// 7.2.75
+type AVP_UTF8String DCA_3GPP_IMS_Charging_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Communication-Service-Identifier (1281) 3GPP (10415)
+// 7.2.76
+type AVP_UTF8String DCA_3GPP_IMS_Communication_Service_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Emergency-Indicator (2322) 3GPP (10415)
+// 7.2.76A
+type enumerated DCA_3GPP_IMS_Emergency_Indicator {
+ Non_Emergency (0),
+ Emergency (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Information (876) 3GPP (10415)
+// 7.2.77
+type AVP_Grouped DCA_3GPP_IMS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMS-Visited-Network-Identifier (2713) 3GPP (10415)
+// 7.2.77A
+type AVP_UTF8String DCA_3GPP_IMS_Visited_Network_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IMSI-Unauthenticated-Flag (2308) 3GPP (10415)
+// 7.2.78
+type enumerated DCA_3GPP_IMSI_Unauthenticated_Flag {
+ AUTHENTICATED (0),
+ UNAUTHENTICATED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Incoming-Trunk-Group-Id (852) 3GPP (10415)
+// 7.2.79
+type AVP_UTF8String DCA_3GPP_Incoming_Trunk_Group_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Initial-IMS-Charging-Identifier (2321) 3GPP (10415)
+// 7.2.79A
+type AVP_UTF8String DCA_3GPP_Initial_IMS_Charging_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Inter-Operator-Identifier (838) 3GPP (10415)
+// 7.2.80
+type AVP_Grouped DCA_3GPP_Inter_Operator_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: IP-Realm-Default-Indication (2603) 3GPP (10415)
+// 7.2.80A
+type enumerated DCA_3GPP_IP_Realm_Default_Indication {
+ DEFAULT_IP_REALM_NOT_USED (0),
+ DEFAULT_IP_REALM_USED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ISUP-Cause (3416) 3GPP (10415)
+// 7.2.80B
+type AVP_Grouped DCA_3GPP_ISUP_Cause
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ISUP-Cause-Diagnostics (3422) 3GPP (10415)
+// 7.2.80C
+type AVP_OctetString DCA_3GPP_ISUP_Cause_Diagnostics
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ISUP-Cause-Location (3423) 3GPP (10415)
+// 7.2.80D
+type AVP_Unsigned32 DCA_3GPP_ISUP_Cause_Location
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ISUP-Cause-Value (3424) 3GPP (10415)
+// 7.2.80E
+type AVP_Unsigned32 DCA_3GPP_ISUP_Cause_Value
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ISUP-Location-Number (3414) 3GPP (10415)
+// 7.2.80F
+type AVP_OctetString DCA_3GPP_ISUP_Location_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Language (3914) 3GPP (10415)
+// 7.2.80Fa
+type AVP_UTF8String DCA_3GPP_Language
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Layer-2-Group-ID (3429) 3GPP (10415)
+// 7.2.80G
+type AVP_OctetString DCA_3GPP_Layer_2_Group_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-APN (1231) 3GPP (10415)
+// 7.2.81
+type AVP_UTF8String DCA_3GPP_LCS_APN
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Client-Dialed-By-MS (1233) 3GPP (10415)
+// 7.2.82
+type AVP_UTF8String DCA_3GPP_LCS_Client_Dialed_By_MS
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Client-External-ID (1234) 3GPP (10415)
+// 7.2.83
+type AVP_UTF8String DCA_3GPP_LCS_Client_External_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Client-Id (1232) 3GPP (10415)
+// 7.2.84
+type AVP_Grouped DCA_3GPP_LCS_Client_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Client-Name (1235) 3GPP (10415)
+// 7.2.85
+type AVP_Grouped DCA_3GPP_LCS_Client_Name
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Client-Type (1241) 3GPP (10415)
+// 7.2.86
+type enumerated DCA_3GPP_LCS_Client_Type {
+ EMERGENCY_SERVICES (0),
+ VALUE_ADDED_SERVICES (1),
+ PLMN_OPERATOR_SERVICES (2),
+ LAWFUL_INTERCEPT_SERVICES (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Data-Coding-Scheme (1236) 3GPP (10415)
+// 7.2.87
+type AVP_UTF8String DCA_3GPP_LCS_Data_Coding_Scheme
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Format-Indicator (1237) 3GPP (10415)
+// 7.2.88
+type enumerated DCA_3GPP_LCS_Format_Indicator {
+ LOGICAL_NAME (0),
+ EMAIL_ADDRESS (1),
+ MSISDN (2),
+ URL (3),
+ SIP_URL (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Information (878) 3GPP (10415)
+// 7.2.89
+type AVP_Grouped DCA_3GPP_LCS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Name-String (1238) 3GPP (10415)
+// 7.2.90
+type AVP_UTF8String DCA_3GPP_LCS_Name_String
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Requestor-Id (1239) 3GPP (10415)
+// 7.2.91
+type AVP_Grouped DCA_3GPP_LCS_Requestor_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: LCS-Requestor-Id-String (1240) 3GPP (10415)
+// 7.2.92
+type AVP_UTF8String DCA_3GPP_LCS_Requestor_Id_String
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Local-GW-Inserted-Indication (2604) 3GPP (10415)
+// 7.2.92A
+type enumerated DCA_3GPP_Local_GW_Inserted_Indication {
+ LOCAL_GW_NOT_INSERTED (0),
+ LOCAL_GW_INSERTED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Local-Sequence-Number (2063) 3GPP (10415)
+// 7.2.93
+type AVP_Unsigned32 DCA_3GPP_Local_Sequence_Number
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Location-Estimate (1242) 3GPP (10415)
+// 7.2.94
+type AVP_OctetString DCA_3GPP_Location_Estimate
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Location-Estimate-Type (1243) 3GPP (10415)
+// 7.2.95
+type enumerated DCA_3GPP_Location_Estimate_Type {
+ CURRENT_LOCATION (0),
+ CURRENT_LAST_KNOWN_LOCATION (1),
+ INITIAL_LOCATION (2),
+ ACTIVATE_DEFERRED_LOCATION (3),
+ CANCEL_DEFERRED_LOCATION (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Location-Info (3460) 3GPP (10415)
+// 7.2.95A
+type AVP_Grouped DCA_3GPP_Location_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Location-Type (1244) 3GPP (10415)
+// 7.2.96
+type AVP_Grouped DCA_3GPP_Location_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Low-Balance-Indication (2020) 3GPP (10415)
+// 7.2.97
+type enumerated DCA_3GPP_Low_Balance_Indication {
+ NOT_APPLICABLE (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Low-Priority-Indicator (2602) 3GPP (10415)
+// 7.2.97A
+type enumerated DCA_3GPP_Low_Priority_Indicator {
+ NO (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MBMS-Charged-Party (2323) 3GPP (10415)
+// 7.2.97B
+type enumerated DCA_3GPP_MBMS_Charged_Party {
+ CONTENT_PROVIDER (0),
+ SUBSCRIBER (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MBMS-GW-Address (2307) 3GPP (10415)
+// 7.2.98
+type AVP_Address DCA_3GPP_MBMS_GW_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MBMS-Information (880) 3GPP (10415)
+// 7.2.99
+type AVP_Grouped DCA_3GPP_MBMS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MBMS-User-Service-Type (1225) 3GPP (10415)
+// 7.2.100
+type enumerated DCA_3GPP_MBMS_User_Service_Type {
+ DOWNLOAD (1),
+ STREAMING (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Media-Initiator-Flag (882) 3GPP (10415)
+// 7.2.101
+type enumerated DCA_3GPP_Media_Initiator_Flag {
+ CALLED_PARTY (0),
+ CALLING_PARTY (1),
+ UNKNOWN (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Media-Initiator-Party (1288) 3GPP (10415)
+// 7.2.102
+type AVP_UTF8String DCA_3GPP_Media_Initiator_Party
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Message-Body (889) 3GPP (10415)
+// 7.2.103
+type AVP_Grouped DCA_3GPP_Message_Body
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Message-Class (1213) 3GPP (10415)
+// 7.2.104
+type AVP_Grouped DCA_3GPP_Message_Class
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Message-ID (1210) 3GPP (10415)
+// 7.2.105
+type AVP_UTF8String DCA_3GPP_Message_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Message-Size (1212) 3GPP (10415)
+// 7.2.106
+type AVP_Unsigned32 DCA_3GPP_Message_Size
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Message-Type (1211) 3GPP (10415)
+// 7.2.107
+type enumerated DCA_3GPP_Message_Type {
+ M_SEMD_REQ (1),
+ M_SEMD_CONF (2),
+ M_NOTIFICATION_IND (3),
+ M_NOTIFYRESP_IND (4),
+ M_RETRIEVE_CONF (5),
+ M_ACKNOWLEDGE_IND (6),
+ M_DELIVERY_IND (7),
+ M_READ_REC_IND (8),
+ M_READ_ORIG_IND (9),
+ M_FORWARD_REQ (10),
+ M_FORWARD_CONF (11),
+ M_MBOX_STORE_CONF (12),
+ M_MBOX_VIEW_CONF (13),
+ M_MBOX_UPLOAD_CONF (14),
+ M_MBOX_DELETE_CONF (15)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MM-Content-Type (1203) 3GPP (10415)
+// 7.2.108
+type AVP_Grouped DCA_3GPP_MM_Content_Type
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MMBox-Storage-Requested (1248) 3GPP (10415)
+// 7.2.109
+type enumerated DCA_3GPP_MMBox_Storage_Requested {
+ NO (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+// 3GPP TS 32.299 V13.9.0
+// AVP: MMS-Information (877) 3GPP (10415)
+// 7.2.110
+type AVP_Grouped DCA_3GPP_MMS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MMTel-Information (2030) 3GPP (10415)
+// 7.2.111
+type AVP_Grouped DCA_3GPP_MMTel_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MMTel-SService-Type (2031) 3GPP (10415)
+// 7.2.111A
+type AVP_Unsigned32 DCA_3GPP_MMTel_SService_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitored-PLMN-Identifier (3430) 3GPP (10415)
+// 7.2.111Aa
+type AVP_UTF8String DCA_3GPP_Monitored_PLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-Event-Configuration-Activity (3919) 3GPP (10415)
+// 7.2.111AaA
+type enumerated DCA_3GPP_Monitoring_Event_Configuration_Activity {
+ CREATE (0),
+ TRANSFER (1),
+ UPDATE (2),
+ DELETE (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-Event-Funtionality (3922) 3GPP (10415)
+// 7.2.111AaB
+type enumerated DCA_3GPP_Monitoring_Event_Funtionality {
+ CONFIGURATION (0),
+ REPORTING (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-Event-Information (3921) 3GPP (10415)
+// 7.2.111AaC
+type AVP_Grouped DCA_3GPP_Monitoring_Event_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-Event-Report-Data (3920) 3GPP (10415)
+// 7.2.111AaD
+type AVP_Grouped DCA_3GPP_Monitoring_Event_Report_Data
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-Event-Report-Number (3923) 3GPP (10415)
+// 7.2.111AaE
+type AVP_Unsigned32 DCA_3GPP_Monitoring_Event_Report_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-UE-HPLMN-Identifier (3431) 3GPP (10415)
+// 7.2.111Ab
+type AVP_UTF8String DCA_3GPP_Monitoring_UE_HPLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-UE-Identifier (3432) 3GPP (10415)
+// 7.2.111Ac
+type AVP_UTF8String DCA_3GPP_Monitoring_UE_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Monitoring-UE-VPLMN-Identifier (3433) 3GPP (10415)
+// 7.2.111Ad
+type AVP_UTF8String DCA_3GPP_Monitoring_UE_VPLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MSC-Address (3417) 3GPP (10415)
+// 7.2.111B
+type AVP_OctetString DCA_3GPP_MSC_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: MTC-IWF-Address (3406) 3GPP (10415)
+// 7.2.111C
+type AVP_Address DCA_3GPP_MTC_IWF_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Neighbour-Node-Address (2705) 3GPP (10415)
+// 7.2.111D
+type AVP_Address DCA_3GPP_Neighbour_Node_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Network-Call-Reference-Number (3418) 3GPP (10415)
+// 7.2.111E
+type AVP_OctetString DCA_3GPP_Network_Call_Reference_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Next-Tariff (2057) 3GPP (10415)
+// 7.2.112
+type AVP_Grouped DCA_3GPP_Next_Tariff
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: NNI-Information (2703) 3GPP (10415)
+// 7.2.112A
+type AVP_Grouped DCA_3GPP_NNI_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: NIDD-Submission (3928) 3GPP (10415)
+// 7.2.112aA
+type AVP_Grouped DCA_3GPP_NIDD_Submission
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: NNI-Type (2704) 3GPP (10415)
+// 7.2.112B
+type enumerated DCA_3GPP_NNI_Type {
+ Non_Roaming (0),
+ Roaming_Without_Loopback (1),
+ Roaming_With_Loopback (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Node-Functionality (862) 3GPP (10415)
+// 7.2.113
+type enumerated DCA_3GPP_Node_Functionality {
+ S_CSCF (0),
+ P_CSCF (1),
+ I_CSCF (2),
+ MRFC (3),
+ MGCF (4),
+ BGCF (5),
+ AS (6),
+ IBCF (7),
+ S_GW (8),
+ P_GW (9),
+ HSGW (10),
+ E_CSCF (11),
+ MME (12),
+ TRF (13),
+ TF (14),
+ ATCF (15),
+ Proxy_Function (16),
+ ePDG (17),
+ TDF (18),
+ TWAG (19),
+ SCEF (20),
+ IWK_SCEF (21)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Node-Id (2064) 3GPP (10415)
+// 7.2.114
+type AVP_UTF8String DCA_3GPP_Node_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-Of-Diversions (2034) 3GPP (10415)
+// 7.2.115
+type AVP_Unsigned32 DCA_3GPP_Number_Of_Diversions
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-of-Messages-Sent (2019) 3GPP (10415)
+// 7.2.116
+type AVP_Unsigned32 DCA_3GPP_Number_of_Messages_Sent
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-Of-Participants (885) 3GPP (10415)
+// 7.2.117
+type AVP_Unsigned32 DCA_3GPP_Number_Of_Participants
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-Of-Received-Talk-Bursts (1282) 3GPP (10415)
+// 7.2.118
+type AVP_Unsigned32 DCA_3GPP_Number_Of_Received_Talk_Bursts
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-Of-Talk-Bursts (1283) 3GPP (10415)
+// 7.2.119
+type AVP_Unsigned32 DCA_3GPP_Number_Of_Talk_Bursts
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Number-Portability-Routing-Information (2024) 3GPP (10415)
+// 7.2.120
+type AVP_UTF8String DCA_3GPP_Number_Portability_Routing_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Offline-Charging (1278) 3GPP (10415)
+// 7.2.121
+type AVP_Grouped DCA_3GPP_Offline_Charging
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Online-Charging-Flag (2303) 3GPP (10415)
+// 7.2.122
+type enumerated DCA_3GPP_Online_Charging_Flag {
+ ECF_ADDRESS_NOT_PROVIDED (0),
+ ECF_ADDRESS_PROVIDED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originating-IOI (839) 3GPP (10415)
+// 7.2.123
+type AVP_UTF8String DCA_3GPP_Originating_IOI
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originator (864) 3GPP (10415)
+// 7.2.124
+type enumerated DCA_3GPP_Originator {
+ CALLING_PARTY (0),
+ CALLED_PARTY (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originator-Address (886) 3GPP (10415)
+// 7.2.125
+type AVP_Grouped DCA_3GPP_Originator_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originator-Interface (2009) 3GPP (10415)
+// 7.2.126
+type AVP_Grouped DCA_3GPP_Originator_Interface
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originator-Received-Address (2027) 3GPP (10415)
+// 7.2.127
+type AVP_Grouped DCA_3GPP_Originator_Received_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Originating-SCCP-Address (2008) 3GPP (10415)
+// 7.2.128
+type AVP_Address DCA_3GPP_Originating_SCCP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Outgoing-Session-Id (2320) 3GPP (10415)
+// 7.2.128A
+type AVP_UTF8String DCA_3GPP_Outgoing_Session_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Outgoing-Trunk-Group-Id (853) 3GPP (10415)
+// 7.2.129
+type AVP_UTF8String DCA_3GPP_Outgoing_Trunk_Group_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Participants-Involved (887) 3GPP (10415)
+// 7.2.130
+type AVP_UTF8String DCA_3GPP_Participants_Involved
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Participant-Group (1260) 3GPP (10415)
+// 7.2.131
+type AVP_Grouped DCA_3GPP_Participant_Group
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Participant-Access-Priority (1259) 3GPP (10415)
+// 7.2.132
+type enumerated DCA_3GPP_Participant_Access_Priority {
+ PRE_EMPTIVE_PRIORITY (1),
+ HIGH_PRIORITY (2),
+ NORMAL_PRIORITY (3),
+ LOW_PRIORITY (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Participant-Action-Type (2049) 3GPP (10415)
+// 7.2.133
+type enumerated DCA_3GPP_Participant_Action_Type {
+ CREATE_CONF (0),
+ JOIN_CONF (1),
+ INVITE_INTO_CONF (2),
+ QUIT_CONF (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PC3-Control-Protocol-Cause (3434) 3GPP (10415)
+// 7.2.135A
+type AVP_Integer32 DCA_3GPP_PC3_Control_Protocol_Cause
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PC3-EPC-Control-Protocol-Cause (3435) 3GPP (10415)
+// 7.2.135B
+type AVP_Integer32 DCA_3GPP_PC3_EPC_Control_Protocol_Cause
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PDN-Connection-Charging-ID (2050) 3GPP (10415)
+// 7.2.136
+type AVP_Unsigned32 DCA_3GPP_PDN_Connection_Charging_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PDP-Address (1227) 3GPP (10415)
+// 7.2.137
+type AVP_Address DCA_3GPP_PDP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PDP-Address-Prefix-Length (2606) 3GPP (10415)
+// 7.2.137A
+type AVP_Unsigned32 DCA_3GPP_PDP_Address_Prefix_Length
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PDP-Context-Type (1247) 3GPP (10415)
+// 7.2.138
+type enumerated DCA_3GPP_PDP_Context_Type {
+ PRIMARY (0),
+ SECONDARY (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Play-Alternative (3913) 3GPP (10415)
+// 7.2.138A
+type enumerated DCA_3GPP_Play_Alternative {
+ SERVED_PARTY (0),
+ REMOTE_PARTY (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Change-Conditions (1261) 3GPP (10415)
+// 7.2.139
+type enumerated DCA_3GPP_PoC_Change_Conditions {
+ SERVICE_CHANGE (0),
+ VOLUME_LIMIT (1),
+ TIME_LIMIT (2),
+ NUMBER_OF_TALK_BURST_LIMIT (3),
+ NUMBER_OF_ACTIVE_PARTICIPANTS (4),
+ TARIFF_TIME (5)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Change-Time (1262) 3GPP (10415)
+// 7.2.140
+type AVP_Time DCA_3GPP_PoC_Change_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Controlling-Address (858) 3GPP (10415)
+// 7.2.141
+type AVP_UTF8String DCA_3GPP_PoC_Controlling_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Event-Type (2025) 3GPP (10415)
+// 7.2.142
+type enumerated DCA_3GPP_PoC_Event_Type {
+ NORMAL (0),
+ INSTANT_PERSONAL_ALERT_EVENT (1),
+ POC_GROUP_ADVERTISEMENT_EVENT (2),
+ EARLY_SESSION_SETTING_UP_EVENT (3),
+ POC_TALK_BURST (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Group-Name (859) 3GPP (10415)
+// 7.2.143
+type AVP_UTF8String DCA_3GPP_PoC_Group_Name
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Information (879) 3GPP (10415)
+// 7.2.144
+type AVP_Grouped DCA_3GPP_PoC_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Server-Role (883) 3GPP (10415)
+// 7.2.145
+type enumerated DCA_3GPP_PoC_Server_Role {
+ PARTICIPATING_POC_SERVER (0),
+ CONTROLLING_POC_SERVER (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Session-Id (1229) 3GPP (10415)
+// 7.2.146
+type AVP_UTF8String DCA_3GPP_PoC_Session_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Session-Initiation-Type (1277) 3GPP (10415)
+// 7.2.147
+type enumerated DCA_3GPP_PoC_Session_Initiation_Type {
+ PRE_ESTABLISHED (0),
+ ON_DEMAND (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-Session-Type (884) 3GPP (10415)
+// 7.2.148
+type enumerated DCA_3GPP_PoC_Session_Type {
+ ONE_TO_ONE_POC_SESSION (0),
+ CHAT_POC_GROUP_SESSION (1),
+ PRE_ARRANGED_POC_GROUP_SESSION (2),
+ AD_HOC_POC_GROUP_SESSION (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-User-Role (1252) 3GPP (10415)
+// 7.2.149
+type AVP_Grouped DCA_3GPP_PoC_User_Role
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-User-Role-IDs (1253) 3GPP (10415)
+// 7.2.150
+type AVP_UTF8String DCA_3GPP_PoC_User_Role_IDs
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PoC-User-Role-info-Units (1254) 3GPP (10415)
+// 7.2.151
+type enumerated DCA_3GPP_PoC_User_Role_info_Units {
+ MODERATOR (1),
+ DISPATCHER (2),
+ SESSION_OWNER (3),
+ SESSION_PARTICIPANT (4)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Positioning-Data (1245) 3GPP (10415)
+// 7.2.152
+type AVP_UTF8String DCA_3GPP_Positioning_Data
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Preferred-AoC-Currency (2315) 3GPP (10415)
+// 7.2.153
+type AVP_Unsigned32 DCA_3GPP_Preferred_AoC_Currency
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Priority (1209) 3GPP (10415)
+// 7.2.154
+type enumerated DCA_3GPP_Priority {
+ LOW (0),
+ NORMAL (1),
+ HIGH (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Privacy-Indicator (3915) 3GPP (10415)
+// 7.2.154aA
+type enumerated DCA_3GPP_Privacy_Indicator {
+ NOT_PRIVATE (0),
+ PRIVATE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-3rd-Party-Application-ID (3440) 3GPP (10415)
+// 7.2.154A
+type AVP_UTF8String DCA_3GPP_ProSe_3rd_Party_Application_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Direct-Communication-Reception-Data-Container (3461) 3GPP (10415)
+// 7.2.154Aa
+type AVP_Grouped DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Direct-Communication-Transmission-Data-Container (3441) 3GPP (10415)
+// 7.2.154B
+type AVP_Grouped DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Direct-Discovery-Model (3442) 3GPP (10415)
+// 7.2.154C
+type enumerated DCA_3GPP_ProSe_Direct_Discovery_Model {
+ MODEL_A (0),
+ MODEL_B (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Event-Type (3443) 3GPP (10415)
+// 7.2.154D
+type enumerated DCA_3GPP_ProSe_Event_Type {
+ ANNOUNCING (0),
+ MONITORING (1),
+ MATCH_REPORT (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Function-IP-Address (3444) 3GPP (10415)
+// 7.2.154E
+type AVP_Address DCA_3GPP_ProSe_Function_IP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Function-PLMN-Identifier (3457) 3GPP (10415)
+// 7.2.154F
+type AVP_UTF8String DCA_3GPP_ProSe_Function_PLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Functionality (3445) 3GPP (10415)
+// 7.2.154G
+type enumerated DCA_3GPP_ProSe_Functionality {
+ DIRECT_DISCOVERY (0),
+ EPC_LEVEL_DISCOVERY (1),
+ DIRECT_COMMUNICATION (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Group-IP-Multicast-Address (3446) 3GPP (10415)
+// 7.2.154H
+type AVP_Address DCA_3GPP_ProSe_Group_IP_Multicast_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Information (3447) 3GPP (10415)
+// 7.2.154I
+type AVP_Grouped DCA_3GPP_ProSe_Information
+
+// WARNING: Unsigned32 used instead of enumerated type
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Range-Class (3448) 3GPP (10415)
+// 7.2.154J
+type AVP_Unsigned32 DCA_3GPP_ProSe_Range_Class
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Reason-For-Cancellation (3449) 3GPP (10415)
+// 7.2.154K
+type enumerated DCA_3GPP_ProSe_Reason_For_Cancellation {
+ PROXIMITY_ALERT_SENT (0),
+ TIME_EXPIRED_WITH_NO_RENEWAL (1),
+ REQUESTOR_CANCELLATION (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Request-Timestamp (3450) 3GPP (10415)
+// 7.2.154L
+type AVP_Time DCA_3GPP_ProSe_Request_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Role-Of-UE (3451) 3GPP (10415)
+// 7.2.154M
+type enumerated DCA_3GPP_ProSe_Role_Of_UE {
+ ANNOUNCING_UE (0),
+ MONITORING_UE (1),
+ REQUESTOR_UE (2),
+ REQUESTED_UE (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-Source-IP-Address (3452) 3GPP (10415)
+// 7.2.154N
+type AVP_Address DCA_3GPP_ProSe_Source_IP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: ProSe-UE-ID (3453) 3GPP (10415)
+// 7.2.154O
+type AVP_OctetString DCA_3GPP_ProSe_UE_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Proximity-Alert-Indication (3454) 3GPP (10415)
+// 7.2.154P
+type enumerated DCA_3GPP_Proximity_Alert_Indication {
+ ALERT (0),
+ NO_ALERT (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Proximity-Alert-Timestamp (3455) 3GPP (10415)
+// 7.2.154Q
+type AVP_Time DCA_3GPP_Proximity_Alert_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Proximity-Cancellation-Timestamp (3456) 3GPP (10415)
+// 7.2.154R
+type AVP_Time DCA_3GPP_Proximity_Cancellation_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PS-Append-Free-Format-Data (867) 3GPP (10415)
+// 7.2.155
+type enumerated DCA_3GPP_PS_Append_Free_Format_Data {
+ APPEND (0),
+ OVERWRITE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PS-Free-Format-Data (866) 3GPP (10415)
+// 7.2.156
+type AVP_OctetString DCA_3GPP_PS_Free_Format_Data
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PS-Furnish-Charging-Information (865) 3GPP (10415)
+// 7.2.157
+type AVP_Grouped DCA_3GPP_PS_Furnish_Charging_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: PS-Information (874) 3GPP (10415)
+// 7.2.158
+type AVP_Grouped DCA_3GPP_PS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Quota-Consumption-Time (881) 3GPP (10415)
+// 7.2.159
+type AVP_Unsigned32 DCA_3GPP_Quota_Consumption_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Quota-Holding-Time (871) 3GPP (10415)
+// 7.2.160
+type AVP_Unsigned32 DCA_3GPP_Quota_Holding_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Quota-Indicator (3912) 3GPP (10415)
+// 7.2.160aA
+type enumerated DCA_3GPP_Quota_Indicator {
+ QUOTA_IS_NOT_USED_DURING_PLAYBACK (0),
+ QUOTA_IS_USED_DURING_PLAYBACK (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Radio-Frequency (3462) 3GPP (10415)
+// 7.2.160A
+type AVP_OctetString DCA_3GPP_Radio_Frequency
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Radio-Parameter-Set-Info (3463) 3GPP (10415)
+// 7.2.160B
+type AVP_Grouped DCA_3GPP_Radio_Parameter_Set_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Radio-Parameter-Set-Values (3464) 3GPP (10415)
+// 7.2.160C
+type AVP_OctetString DCA_3GPP_Radio_Parameter_Set_Values
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Radio-Resources-Indicator (3465) 3GPP (10415)
+// 7.2.160D
+type AVP_Integer32 DCA_3GPP_Radio_Resources_Indicator
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Rate-Control-Max-Message-Size (3937) 3GPP (10415)
+// 7.2.160E
+type AVP_Integer32 DCA_3GPP_Rate_Control_Max_Message_Size
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Rate-Control-Max-Rate (3938) 3GPP (10415)
+// 7.2.160F
+type AVP_Integer32 DCA_3GPP_Rate_Control_Max_Rate
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Rate-Control-Time-Unit (3939) 3GPP (10415)
+// 7.2.160G
+type AVP_Integer32 DCA_3GPP_Rate_Control_Time_Unit
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Rate-Element (2058) 3GPP (10415)
+// 7.2.161
+type AVP_Grouped DCA_3GPP_Rate_Element
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Read-Reply-Report-Requested (1222) 3GPP (10415)
+// 7.2.162
+type enumerated DCA_3GPP_Read_Reply_Report_Requested {
+ NO (0),
+ YES (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Real-Time-Tariff-Information (2305) 3GPP (10415)
+// 7.2.164
+type AVP_Grouped DCA_3GPP_Real_Time_Tariff_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Reason-Header (3401) 3GPP (10415)
+// 7.2.164A
+type AVP_UTF8String DCA_3GPP_Reason_Header
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Received-Talk-Burst-Time (1284) 3GPP (10415)
+// 7.2.165
+type AVP_Unsigned32 DCA_3GPP_Received_Talk_Burst_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Received-Talk-Burst-Volume (1285) 3GPP (10415)
+// 7.2.166
+type AVP_Unsigned32 DCA_3GPP_Received_Talk_Burst_Volume
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Recipient-Address (1201) 3GPP (10415)
+// 7.2.167
+type AVP_Grouped DCA_3GPP_Recipient_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Recipient-Info (2026) 3GPP (10415)
+// 7.2.168
+type AVP_Grouped DCA_3GPP_Recipient_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Recipient-Received-Address (2028) 3GPP (10415)
+// 7.2.169
+type AVP_Grouped DCA_3GPP_Recipient_Received_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Recipient-SCCP-Address (2010) 3GPP (10415)
+// 7.2.170
+type AVP_Address DCA_3GPP_Recipient_SCCP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Refund-Information (2022) 3GPP (10415)
+// 7.2.171
+type AVP_OctetString DCA_3GPP_Refund_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Relationship-Mode (2706) 3GPP (10415)
+// 7.2.171A
+type enumerated DCA_3GPP_Relationship_Mode {
+ Trusted (0),
+ Non_Trusted (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Related-Change-Condition-Information (3925) 3GPP (10415)
+// 7.2.171Aa
+type AVP_Grouped DCA_3GPP_Related_Change_Condition_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Related-Trigger (3926) 3GPP (10415)
+// 7.2.171Ab
+type AVP_Grouped DCA_3GPP_Related_Trigger
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Related-IMS-Charging-Identifier (2711) 3GPP (10415)
+// 7.2.171B
+type AVP_UTF8String DCA_3GPP_Related_IMS_Charging_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Related-IMS-Charging-Identifier-Node (2712) 3GPP (10415)
+// 7.2.171C
+type AVP_Address DCA_3GPP_Related_IMS_Charging_Identifier_Node
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Remaining-Balance (2021) 3GPP (10415)
+// 7.2.172
+type AVP_Grouped DCA_3GPP_Remaining_Balance
+
+// 3GPP TS 32.299 V8.5.0
+// AVP: Reply-Applic-ID (1223) 3GPP (10415)
+// 7.2.173
+type AVP_UTF8String DCA_3GPP_Reply_Applic_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Reply-Path-Requested (2011) 3GPP (10415)
+// 7.2.174
+type enumerated DCA_3GPP_Reply_Path_Requested {
+ NO_REPLY_PATH_SET (0),
+ REPLY_PATH_SET (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Reporting-Reason (872) 3GPP (10415)
+// 7.2.175
+type enumerated DCA_3GPP_Reporting_Reason {
+ THRESHOLD (0),
+ QHT (1),
+ FINAL (2),
+ QUOTA_EXHAUSTED (3),
+ VALIDITY_TIME (4),
+ OTHER_QUOTA_TYPE (5),
+ RATING_CONDITION_CHANGE (6),
+ FORCED_REAUTHORISATION (7),
+ POOL_EXHAUSTED (8)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Requested-Party-Address (1251) 3GPP (10415)
+// 7.2.176
+type AVP_UTF8String DCA_3GPP_Requested_Party_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Requested-PLMN-Identifier (3436) 3GPP (10415)
+// 7.2.176A
+type AVP_UTF8String DCA_3GPP_Requested_PLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Requestor-PLMN-Identifier (3437) 3GPP (10415)
+// 7.2.176B
+type AVP_UTF8String DCA_3GPP_Requestor_PLMN_Identifier
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Role-Of-Node (829) 3GPP (10415)
+// Note: not compatible with V9.2.0 or before (see spec.)
+// 7.2.177
+type enumerated DCA_3GPP_Role_Of_Node {
+ ORIGINATING_ROLE (0),
+ TERMINATING_ROLE (1),
+ FORWARDING_ROLE (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Role-Of-ProSe-Function (3438) 3GPP (10415)
+// 7.2.177aA
+type enumerated DCA_3GPP_Role_Of_ProSe_Function {
+ HPLMN (0),
+ VPLMN (1),
+ LOCAL_PLMN (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Route-Header-Received (3403) 3GPP (10415)
+// 7.2.177A
+type AVP_UTF8String DCA_3GPP_Route_Header_Received
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Route-Header-Transmitted (3404) 3GPP (10415)
+// 7.2.177B
+type AVP_UTF8String DCA_3GPP_Route_Header_Transmitted
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Scale-Factor (2059) 3GPP (10415)
+// 7.2.178
+type AVP_Grouped DCA_3GPP_Scale_Factor
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SCS-Address (3941) 3GPP (10415)
+// 7.2.178A
+type AVP_Address DCA_3GPP_SCS_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SCS-AS-Address (3940) 3GPP (10415)
+// 7.2.178B
+type AVP_Grouped DCA_3GPP_SCS_AS_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SCS-Realm (3942) 3GPP (10415)
+// 7.2.178C
+type AVP_DiameterIdentity DCA_3GPP_SCS_Realm
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Answer-Timestamp (1275) 3GPP (10415)
+// 7.2.179
+type AVP_Time DCA_3GPP_SDP_Answer_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Media-Component (843) 3GPP (10415)
+// 7.2.180
+type AVP_Grouped DCA_3GPP_SDP_Media_Component
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Media-Description (845) 3GPP (10415)
+// 7.2.181
+type AVP_UTF8String DCA_3GPP_SDP_Media_Description
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Media-Name (844) 3GPP (10415)
+// 7.2.182
+type AVP_UTF8String DCA_3GPP_SDP_Media_Name
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Offer-Timestamp (1274) 3GPP (10415)
+// 7.2.183
+type AVP_Time DCA_3GPP_SDP_Offer_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Session-Description (842) 3GPP (10415)
+// 7.2.184
+type AVP_UTF8String DCA_3GPP_SDP_Session_Description
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-TimeStamps (1273) 3GPP (10415)
+// 7.2.185
+type AVP_Grouped DCA_3GPP_SDP_TimeStamps
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SDP-Type (2036) 3GPP (10415)
+// 7.2.186
+type enumerated DCA_3GPP_SDP_Type {
+ SDP_OFFER (0),
+ SDP_ANSWER (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Session-Direction (2707) 3GPP (10415)
+// 7.2.186A
+type enumerated DCA_3GPP_Session_Direction {
+ Inbound (0),
+ Outbound (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Served-Party-IP-Address (848) 3GPP (10415)
+// 7.2.187
+type AVP_Address DCA_3GPP_Served_Party_IP_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Data-Container (2040) 3GPP (10415)
+// 7.2.189
+type AVP_Grouped DCA_3GPP_Service_Data_Container
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Id (855) 3GPP (10415)
+// 7.2.190
+type AVP_UTF8String DCA_3GPP_Service_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Generic-Information (1256) 3GPP (10415)
+// 7.2.191
+type AVP_Grouped DCA_3GPP_Service_Generic_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Information (873) 3GPP (10415)
+// 7.2.192
+type AVP_Grouped DCA_3GPP_Service_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Mode (2032) 3GPP (10415)
+// 7.2.193
+type AVP_Unsigned32 DCA_3GPP_Service_Mode
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Specific-Data (863) 3GPP (10415)
+// 7.2.194
+type AVP_UTF8String DCA_3GPP_Service_Specific_Data
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Specific-Info (1249) 3GPP (10415)
+// 7.2.195
+type AVP_Grouped DCA_3GPP_Service_Specific_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Service-Specific-Type (1257) 3GPP (10415)
+// 7.2.196
+type AVP_Unsigned32 DCA_3GPP_Service_Specific_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Serving-Node-Identity (3929) 3GPP (10415)
+// 7.2.197A
+type AVP_DiameterIdentity DCA_3GPP_Serving_Node_Identity
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Serving-Node-Type (2047) 3GPP (10415)
+// 7.2.198
+type enumerated DCA_3GPP_Serving_Node_Type {
+ SGSN (0),
+ PMIPSGW (1),
+ GTPSGW (2),
+ ePDG (3),
+ hSGW (4),
+ MME (5),
+ TWAN (6)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SGi-PtP-Tunnelling-Method (3931) 3GPP (10415)
+// 7.2.198A
+type enumerated DCA_3GPP_SGi_PtP_Tunnelling_Method {
+ UDP_IP_BASED (0),
+ Others (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SGSN-Address (1228) 3GPP (10415)
+// 7.2.199
+type AVP_Address DCA_3GPP_SGSN_Address
+
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SGW-Address (2067) 3GPP (10415)
+// 7.2.199A
+type AVP_Address DCA_3GPP_SGW_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SGW-Change (2065) 3GPP (10415)
+// 7.2.200
+type enumerated DCA_3GPP_SGW_Change {
+ ACR_Start_NOT_due_to_SGW_Change (0),
+ ACR_Start_due_to_SGW_Change (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SIP-Method (824) 3GPP (10415)
+// 7.2.201
+type AVP_UTF8String DCA_3GPP_SIP_Method
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SIP-Request-Timestamp (834) 3GPP (10415)
+// 7.2.202
+type AVP_Time DCA_3GPP_SIP_Request_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SIP-Request-Timestamp-Fraction (2301) 3GPP (10415)
+// 7.2.203
+type AVP_Unsigned32 DCA_3GPP_SIP_Request_Timestamp_Fraction
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SIP-Response-Timestamp (835) 3GPP (10415)
+// 7.2.204
+type AVP_Time DCA_3GPP_SIP_Response_Timestamp
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SIP-Response-Timestamp-Fraction (2302) 3GPP (10415)
+// 7.2.205
+type AVP_Unsigned32 DCA_3GPP_SIP_Response_Timestamp_Fraction
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Device-Trigger-Indicator (3407) 3GPP (10415)
+// 7.2.205A
+type enumerated DCA_3GPP_SM_Device_Trigger_Indicator {
+ Not_Device_Trigger (0),
+ Device_Trigger (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Device-Trigger-Information (3405) 3GPP (10415)
+// 7.2.205B
+type AVP_Grouped DCA_3GPP_SM_Device_Trigger_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Discharge-Time (2012) 3GPP (10415)
+// 7.2.206
+type AVP_Time DCA_3GPP_SM_Discharge_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Message-Type (2007) 3GPP (10415)
+// 7.2.207
+type enumerated DCA_3GPP_SM_Message_Type {
+ SUBMISSION (0),
+ DELIVERY_REPORT (1),
+ SM_SERVICE_REQUEST (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Protocol-ID (2013) 3GPP (10415)
+// 7.2.208
+type AVP_OctetString DCA_3GPP_SM_Protocol_ID
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Sequence-Number (3408) 3GPP (10415)
+// 7.2.208A
+type AVP_Unsigned32 DCA_3GPP_SM_Sequence_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Status (2014) 3GPP (10415)
+// 7.2.209
+type AVP_OctetString DCA_3GPP_SM_Status
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-User-Data-Header (2015) 3GPP (10415)
+// 7.2.210
+type AVP_OctetString DCA_3GPP_SM_User_Data_Header
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SMS-Information (2000) 3GPP (10415)
+// 7.2.211
+type AVP_Grouped DCA_3GPP_SMS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SMS-Node (2016) 3GPP (10415)
+// 7.2.212
+type enumerated DCA_3GPP_SMS_Node {
+ SMS_ROUTER (0),
+ IP_SM_GW (1),
+ SMS_ROUTER_AND_IP_SM_GW (2),
+ SMS_SC (3)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SMS-Result (3409) 3GPP (10415)
+// 7.2.212A
+type AVP_Unsigned32 DCA_3GPP_SMS_Result
+
+// WARNING: Unsigned32 used instead of enumerated type
+// 3GPP TS 32.299 V13.9.0
+// AVP: SM-Service-Type (2029) 3GPP (10415)
+// 7.2.213
+type AVP_Unsigned32 DCA_3GPP_SM_Service_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: SMSC-Address (2017) 3GPP (10415)
+// 7.2.214
+type AVP_Address DCA_3GPP_SMSC_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Start-Of-Charging (3419) 3GPP (10415)
+// 7.2.214A
+type AVP_Time DCA_3GPP_Start_Of_Charging
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Start-Time (2041) 3GPP (10415)
+// 7.2.215
+type AVP_Time DCA_3GPP_Start_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Status-AS-Code (2702) 3GPP (10415)
+// 7.2.215A
+type enumerated DCA_3GPP_Status_AS_Code {
+ code_4xx (0),
+ code_5xx (1),
+ Timeout (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Stop-Time (2042) 3GPP (10415)
+// 7.2.216
+type AVP_Time DCA_3GPP_Stop_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Submission-Time (1202) 3GPP (10415)
+// 7.2.217
+type AVP_Time DCA_3GPP_Submission_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Subscriber-Role (2033) 3GPP (10415)
+// 7.2.218
+type enumerated DCA_3GPP_Subscriber_Role {
+ ORIGINATING (0),
+ TERMINATING (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Supplementary-Service (2048) 3GPP (10415)
+// 7.2.219
+type AVP_Grouped DCA_3GPP_Supplementary_Service
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: TAD-Identifier (2717) 3GPP (10415)
+// 7.2.219A
+type enumerated DCA_3GPP_TAD_Identifier {
+ CS (0),
+ PS (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Talk-Burst-Exchange (1255) 3GPP (10415)
+// 7.2.220
+type AVP_Grouped DCA_3GPP_Talk_Burst_Exchange
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Talk-Burst-Time (1286) 3GPP (10415)
+// 7.2.221
+type AVP_Unsigned32 DCA_3GPP_Talk_Burst_Time
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Talk-Burst-Volume (1287) 3GPP (10415)
+// 7.2.222
+type AVP_Unsigned32 DCA_3GPP_Talk_Burst_Volume
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Tariff-Information (2060) 3GPP (10415)
+// 7.2.223
+type AVP_Grouped DCA_3GPP_Tariff_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Tariff-XML (2306) 3GPP (10415)
+// 7.2.224
+type AVP_UTF8String DCA_3GPP_Tariff_XML
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Teleservice (3413) 3GPP (10415)
+// 7.2.224A
+type AVP_OctetString DCA_3GPP_Teleservice
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Terminating-IOI (840) 3GPP (10415)
+// 7.2.225
+type AVP_UTF8String DCA_3GPP_Terminating_IOI
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-First-Reception (3466) 3GPP (10415)
+// 7.2.225A
+type AVP_Time DCA_3GPP_Time_First_Reception
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-First-Transmission (3467) 3GPP (10415)
+// 7.2.225B
+type AVP_Time DCA_3GPP_Time_First_Transmission
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-First-Usage (2043) 3GPP (10415)
+// 7.2.226
+type AVP_Time DCA_3GPP_Time_First_Usage
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Indicator (3911) 3GPP (10415)
+// 7.2.226A
+type AVP_Unsigned32 DCA_3GPP_Time_Indicator
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Last-Usage (2044) 3GPP (10415)
+// 7.2.227
+type AVP_Time DCA_3GPP_Time_Last_Usage
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Quota-Mechanism (1270) 3GPP (10415)
+// 7.2.228
+type AVP_Grouped DCA_3GPP_Time_Quota_Mechanism
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Quota-Threshold (868) 3GPP (10415)
+// 7.2.229
+type AVP_Unsigned32 DCA_3GPP_Time_Quota_Threshold
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Quota-Type (1271) 3GPP (10415)
+// 7.2.230
+type enumerated DCA_3GPP_Time_Quota_Type {
+ DISCRETE_TIME_PERIOD (0),
+ CONTINUOUS_TIME_PERIOD (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Stamps (833) 3GPP (10415)
+// 7.2.231
+type AVP_Grouped DCA_3GPP_Time_Stamps
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Time-Usage (2045) 3GPP (10415)
+// 7.2.232
+type AVP_Unsigned32 DCA_3GPP_Time_Usage
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Traffic-Data-Volumes (2046) 3GPP (10415)
+// 7.2.233
+type AVP_Grouped DCA_3GPP_Traffic_Data_Volumes
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Transcoder-Inserted-Indication (2605) 3GPP (10415)
+// 7.2.233A
+type enumerated DCA_3GPP_Transcoder_Inserted_Indication {
+ TRANSCODER_NOT_INSERTED (0),
+ TRANSCODER_INSERTED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Transit-IOI-List (2701) 3GPP (10415)
+// 7.2.233B
+type AVP_UTF8String DCA_3GPP_Transit_IOI_List
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Transmitter-Info (3468) 3GPP (10415)
+// 7.2.233C
+type AVP_Grouped DCA_3GPP_Transmitter_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Token-Text (1215) 3GPP (10415)
+// 7.2.234
+type AVP_UTF8String DCA_3GPP_Token_Text
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Trigger (1264) 3GPP (10415)
+// 7.2.235
+type AVP_Grouped DCA_3GPP_Trigger
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Trigger-Type (870) 3GPP (10415)
+// 7.2.236
+type enumerated DCA_3GPP_Trigger_Type {
+ CHANGE_IN_SGSN_IP_ADDRESS (1),
+ CHANGE_IN_QOS (2),
+ CHANGE_IN_LOCATION (3),
+ CHANGE_IN_RAT (4),
+ CHANGE_IN_UE_TIMEZONE (5),
+ CHANGEINQOS_TRAFFIC_CLASS (10),
+ CHANGEINQOS_RELIABILITY_CLASS (11),
+ CHANGEINQOS_DELAY_CLASS (12),
+ CHANGEINQOS_PEAK_THROUGHPUT (13),
+ CHANGEINQOS_PRECEDENCE_CLASS (14),
+ CHANGEINQOS_MEAN_THROUGHPUT (15),
+ CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_UPLINK (16),
+ CHANGEINQOS_MAXIMUM_BIT_RATE_FOR_DOWNLINK (17),
+ CHANGEINQOS_RESIDUAL_BER (18),
+ CHANGEINQOS_SDU_ERROR_RATIO (19),
+ CHANGEINQOS_TRANSFER_DELAY (20),
+ CHANGEINQOS_TRAFFIC_HANDLING_PRIORITY (21),
+ CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_UPLINK (22),
+ CHANGEINQOS_GUARANTEED_BIT_RATE_FOR_DOWNLINK (23),
+ CHANGEINQOS_APN_AGGREGATE_MAXIMUM_BIT_RATE (24),
+ CHANGEINLOCATION_MCC (30),
+ CHANGEINLOCATION_MNC (31),
+ CHANGEINLOCATION_RAC (32),
+ CHANGEINLOCATION_LAC (33),
+ CHANGEINLOCATION_CellId (34),
+ CHANGEINLOCATION_TAC (35),
+ CHANGEINLOCATION_ECGI (36),
+ CHANGE_IN_MEDIA_COMPOSITION (40),
+ CHANGE_IN_PARTICIPANTS_NMB (50),
+ CHANGE_IN_THRSHLD_OF_PARTICIPANTS_NMB (51),
+ CHANGE_IN_USER_PARTICIPATING_TYPE (52),
+ CHANGE_IN_SERVICE_CONDITION (60),
+ CHANGE_IN_SERVING_NODE (61),
+ CHANGE_IN_ACCESS_FOR_A_SERVICE_DATA_FLOW (62),
+ CHANGE_IN_USER_CSG_INFORMATION (70),
+ CHANGE_IN_HYBRID_SUBSCRIBED_USER_CSG_INFORMATION (71),
+ CHANGE_IN_HYBRID_UNSUBSCRIBED_USER_CSG_INFORMATION (72),
+ CHANGE_OF_UE_PRESENCE_IN_PRESENCE_REPORTING_AREA (73),
+ CHANGE_IN_SERVING_PLMN_RATE_CONTROL (74),
+ CHANGE_IN_APN_RATE_CONTROL (75)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Trunk-Group-Id (851) 3GPP (10415)
+// 7.2.237
+type AVP_Grouped DCA_3GPP_Trunk_Group_Id
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: TWAG-Address (3903) 3GPP (10415)
+// 7.2.237Ba
+type AVP_Address DCA_3GPP_TWAG_Address
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: TWAN-User-Location-Info (2714) 3GPP (10415)
+// 7.2.237C
+type AVP_Grouped DCA_3GPP_TWAN_User_Location_Info
+
+// WARNING: Unsigned32 used instead of enumerated type
+// 3GPP TS 32.299 V13.9.0
+// AVP: Type-Number (1204) 3GPP (10415)
+// 7.2.238
+type AVP_Unsigned32 DCA_3GPP_Type_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: UNI-PDU-CP-Only-Flag (3932) 3GPP (10415)
+// 7.2.238A
+type enumerated DCA_3GPP_UNI_PDU_CP_Only_Flag {
+ UNI_PDU_both_UP_CP (0),
+ UNI_PDU_CP_Only (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Unit-Cost (2061) 3GPP (10415)
+// 7.2.239
+type AVP_Grouped DCA_3GPP_Unit_Cost
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Unit-Quota-Threshold (1226) 3GPP (10415)
+// 7.2.240
+type AVP_Unsigned32 DCA_3GPP_Unit_Quota_Threshold
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: User-CSG-Information (2319) 3GPP (10415)
+// 7.2.240A
+type AVP_Grouped DCA_3GPP_User_CSG_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Usage-Information-Report-Sequence-Number (3439) 3GPP (10415)
+// 7.2.240B
+type AVP_Integer32 DCA_3GPP_Usage_Information_Report_Sequence_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: User-Participating-Type (1279) 3GPP (10415)
+// 7.2.241
+type enumerated DCA_3GPP_User_Participating_Type {
+ NORMAL (0),
+ NW_POC_BOX (1),
+ UE_POC_BOX (2)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: User-Session-Id (830) 3GPP (10415)
+// 7.2.242
+type AVP_UTF8String DCA_3GPP_User_Session_Id
+
+// 3GPP TS 32.299 V13.9.0 CR0716
+// AVP: UWAN-User-Location-Info (3918) 3GPP (10415)
+// 7.2.242aaA
+type AVP_Grouped DCA_3GPP_UWAN_User_Location_Info
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Variable-Part (3907) 3GPP (10415)
+// 7.2.242aA
+type AVP_Grouped DCA_3GPP_Variable_Part
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Variable-Part-Order (3908) 3GPP (10415)
+// 7.2.242aB
+type AVP_Unsigned32 DCA_3GPP_Variable_Part_Order
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Variable-Part-Type (3909) 3GPP (10415)
+// 7.2.242aC
+type AVP_Unsigned32 DCA_3GPP_Variable_Part_Type
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Variable-Part-Value (3910) 3GPP (10415)
+// 7.2.242aD
+type AVP_UTF8String DCA_3GPP_Variable_Part_Value
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: VCS-Information (3410) 3GPP (10415)
+// 7.2.242A
+type AVP_Grouped DCA_3GPP_VCS_Information
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: VLR-Number (3420) 3GPP (10415)
+// 7.2.242B
+type AVP_OctetString DCA_3GPP_VLR_Number
+
+// 3GPP TS 32.299 V13.9.0
+// AVP: Volume-Quota-Threshold (869) 3GPP (10415)
+// 7.2.243
+type AVP_Unsigned32 DCA_3GPP_Volume_Quota_Threshold
+
+
+/******************************************************************************
+* Copyright (c) 2000-2019 Ericsson Telecom AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
+*
+* Contributors:
+* Timea Moder
+******************************************************************************/
+//
+// File: AAAInterface_3GPP_TS29273_f00.ddf
+// Description: DDF for EPS AAA according to 3GPP TS 29.273 V15.0.0
+// Rev: R55A
+// Prodnr: CNL 113 462
+///////////////////////////////////////////////
+
+
+// APPLICATION-NAME: AAA
+// APPLICATION-REVISION: V15_0_0
+
+// AVP implementations according to:
+// 3GPP TS 29.273 V15.0.0 - EPS AAA interfaces based on the Diameter protocol
+
+// Dependant applications
+// IETF RFC 3588 - Diameter Base Protocol
+// IETF RFC 4005 - Diameter Network Access Server Application
+
+// 9.2.2
+// WARNING: Enumeration item with code (265) exists in type Command_Code
+// WARNING: Enumeration item with code (275) exists in type Command_Code
+// WARNING: Enumeration item with code (274) exists in type Command_Code
+
+
+// 8.2.3.1
+// AVP: Non-3GPP-User-Data (1500) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_Non_3GPP_User_Data
+
+// 8.2.3.3
+// AVP: Non-3GPP-IP-Access (1501) 3GPP (10415)
+type enumerated AAA_3GPP_Non_3GPP_IP_Access {
+ NON_3GPP_SUBSCRIPTION_ALLOWED (0),
+ NON_3GPP_SUBSCRIPTION_BARRED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 8.2.3.4
+// AVP: Non-3GPP-IP-Access-APN (1502) 3GPP (10415)
+type enumerated AAA_3GPP_Non_3GPP_IP_Access_APN {
+ NON_3GPP_APNS_ENABLE (0),
+ NON_3GPP_APNS_DISABLE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 5.2.3.9
+// AVP: AN-Trusted (1503) 3GPP (10415)
+type enumerated AAA_3GPP_AN_Trusted {
+ TRUSTED (0),
+ UNTRUSTED (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 5.2.3.7
+// AVP: ANID (1504) 3GPP (10415)
+type AVP_UTF8String AAA_3GPP_ANID
+
+// 8.2.3.13
+// AVP: Trace-Info (1505) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_Trace_Info
+
+// 5.2.3.12
+// AVP: MIP-FA-RK (1506) 3GPP (10415)
+type AVP_OctetString AAA_3GPP_MIP_FA_RK
+
+// 5.2.3.13
+// AVP: MIP-FA-RK-SPI (1507) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_MIP_FA_RK_SPI
+
+// 5.2.3.17
+// AVP: PPR-Flags (1508) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_PPR_Flags
+
+// 5.2.3.18
+// AVP: WLAN-Identifier (1509) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_WLAN_Identifier
+
+// 8.2.3.19
+// AVP: TWAN-Access-Info (1510) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_TWAN_Access_Info
+
+// 8.2.3.20
+// AVP: Access-Authorization-Flags (1511) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_Access_Authorization_Flags
+
+// 8.2.3.18
+// AVP: TWAN-Default-APN-Context-Id (1512) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_TWAN_Default_APN_Context_Id
+
+// 9.2.3.1.4
+// AVP: Trust-Relationship-Update (1515) 3GPP (10415)
+type enumerated AAA_3GPP_Trust_Relationship_Update {
+ REQUEST_UPDATE (1)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 5.2.3.14
+// AVP: Full-Network-Name (1516) 3GPP (10415)
+type AVP_OctetString AAA_3GPP_Full_Network_Name
+
+// 5.2.3.15
+// AVP: Short-Network-Name (1517) 3GPP (10415)
+type AVP_OctetString AAA_3GPP_Short_Network_Name
+
+// 8.2.3.21
+// AVP: AAA-Failure-Indication (1518) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_AAA_Failure_Indication
+
+// 5.2.3.19
+// AVP: Transport-Access-Type (1519) 3GPP (10415)
+type enumerated AAA_3GPP_Transport_Access_Type {
+ BBF (0)
+} with {
+ variant "FIELDLENGTH(32)"
+ variant "BYTEORDER(last)"
+ variant "COMP(2scompl)"
+}
+
+// 5.2.3.20
+// AVP: DER-Flags (1520) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_DER_Flags
+
+// 5.2.3.21
+// AVP: DEA-Flags (1521) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_DEA_Flags
+
+// 9.2.3.1.5
+// AVP: RAR-Flags (1522) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_RAR_Flags
+
+// 9.2.3.7
+// AVP: DER-S6b-Flags (1523) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_DER_S6b_Flags
+
+// 5.2.3.22
+// AVP: SSID (1524) 3GPP (10415)
+type AVP_UTF8String AAA_3GPP_SSID
+
+// 5.2.3.23
+// AVP: HESSID (1525) 3GPP (10415)
+type AVP_UTF8String AAA_3GPP_HESSID
+
+
+// 5.2.3.24
+// AVP: Access-Network-Info (1526) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_Access_Network_Info
+
+// 5.2.3.25
+// AVP: TWAN-Connection-Mode (1527) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_TWAN_Connection_Mode
+
+// 5.2.3.26
+// AVP: TWAN-Connectivity-Parameters (1528) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_TWAN_Connectivity_Parameters
+
+// 5.2.3.27
+// AVP: Connectivity-Flags (1529) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_Connectivity_Flags
+
+// 5.2.3.28
+// AVP: TWAN-PCO (1530) 3GPP (10415)
+type AVP_Grouped AAA_3GPP_TWAN_PCO
+
+// 5.2.3.29
+// AVP: TWAG-CP-Address (1531) 3GPP (10415)
+type AVP_Address AAA_3GPP_TWAG_CP_Address
+
+// 5.2.3.30
+// AVP: TWAG-UP-Address (1532) 3GPP (10415)
+type AVP_UTF8String AAA_3GPP_TWAG_UP_Address
+
+// 5.2.3.31
+// AVP: TWAN-S2a-Failure-Cause (1533) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_TWAN_S2a_Failure_Cause
+
+// 5.2.3.33
+// AVP: SM-Back-Off-Timer (1534) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_SM_Back_Off_Timer
+
+// 5.2.3.33
+// AVP: WLCP-Key (1535) 3GPP (10415)
+type AVP_OctetString AAA_3GPP_WLCP_Key
+
+// 9.2.3.2.6
+// AVP: Origination-Time-Stamp (1536) 3GPP (10415)
+type AVP_Unsigned64 AAA_3GPP_Origination_Time_Stamp
+
+// 9.2.3.2.7
+// AVP: Maximum-Wait-Time (1537) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_Maximum_Wait_Time
+
+// 7.2.3.5
+// AVP: Emergency-Services (1538) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_Emergency_Services
+
+// 7.2.3.5
+// AVP: AAR-Flags (1539) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_AAR_Flags
+
+// 5.2.3.35
+// AVP: IMEI-Check-In-VPLMN-Result (1540) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_IMEI_Check_In_VPLMN_Result
+
+// 8.2.3.27
+// AVP: ERP-Authorization (1541) 3GPP (10415)
+type AVP_Unsigned32 AAA_3GPP_ERP_Authorization
+
+
+// STATISTICS: 1201 AVP descriptors found
+// STATISTICS: 1187 AVP type definitions matching AVP descriptors found
+// STATISTICS: 14 duplicate AVP definitions deleted
type enumerated Command_Code {
- Abort_Session (274), Accounting (271), Capabilities_Exchange (257), Device_Watchdog (280), Disconnect_Peer (282), Re_Auth (258), Session_Termination (275), Experimental1 (16777214), Experimental2 (16777215) , Update_Location (316), Cancel_Location (317), Authentication_Information (318), Insert_Subscriber_Data (319), Delete_Subscriber_Data (320), Purge_UE (321), Reset (322), Notify (323), ME_Identity_Check (324), Update_VCSG_Location (8388638), Cancel_VCSG_Location (8388642), Credit_Control (272), TDF_Session (8388637), Subscriber_Information (8388641), Configuration_Information (8388718), Reporting_Information (8388719), NIDD_Information (8388726), Authorize_Authenticate (265), User_Authorization (300), Server_Assignment (301), Location_Info (302), Multimedia_Auth (303), Registration_Termination (304), Push_Profile (305)
+ Abort_Session (274), Accounting (271), Capabilities_Exchange (257), Device_Watchdog (280), Disconnect_Peer (282), Re_Auth (258), Session_Termination (275), Experimental1 (16777214), Experimental2 (16777215) , Authorize_Authenticate (265), Credit_Control (272), Update_Location (316), Cancel_Location (317), Authentication_Information (318), Insert_Subscriber_Data (319), Delete_Subscriber_Data (320), Purge_UE (321), Reset (322), Notify (323), ME_Identity_Check (324), Update_VCSG_Location (8388638), Cancel_VCSG_Location (8388642), TDF_Session (8388637), Subscriber_Information (8388641), Configuration_Information (8388718), Reporting_Information (8388719), NIDD_Information (8388726), User_Authorization (300), Server_Assignment (301), Location_Info (302), Multimedia_Auth (303), Registration_Termination (304), Push_Profile (305)
} with {
variant "FIELDLENGTH(24)"
variant "BYTEORDER(last)"
@@ -5586,32 +8813,38 @@ type enumerated AVP_Code_NONE {
avp_code_DNAS_NONE_Login_LAT_Service (34),
avp_code_DCC_NONE_Direct_Debiting_Failure_Handling (428),
avp_code_MIPv6_NONE_MIP_Careof_Address (487),
+ avp_code_MIPv4_NONE_MIP_HA_to_FA_MSA (329),
avp_code_BASE_NONE_Session_Id (263),
avp_code_DCC_NONE_Requested_Service_Unit (437),
avp_code_DNAS_NONE_Framed_Pool (88),
avp_code_DCC_NONE_CC_Time (420),
avp_code_DCC_NONE_Used_Service_Unit (446),
+ avp_code_MIPv4_NONE_MIP_Reg_Reply (321),
avp_code_BASE_NONE_Auth_Application_Id (258),
avp_code_DNAS_NONE_Framed_Appletalk_Network (38),
avp_code_DNAS_NONE_Framed_IPv6_Prefix (97),
avp_code_BASE_NONE_Firmware_Revision (267),
avp_code_BASE_NONE_Auth_Grace_Period (276),
+ avp_code_MIPv4_NONE_MIP_MN_to_FA_MSA (325),
avp_code_BASE_NONE_Re_Auth_Request_Type (285),
avp_code_DCC_NONE_Redirect_Address_Type (433),
avp_code_MIPv6_NONE_MIP_MN_HA_MSA (492),
avp_code_DNAS_NONE_Tunnel_Medium_Type (65),
avp_code_DCC_NONE_User_Equipment_Info_Type (459),
+ avp_code_MIPv4_NONE_MIP_Home_Agent_Address (334),
avp_code_MIPv6_NONE_QoS_Resources (508),
avp_code_DCC_NONE_Service_Parameter_Value (442),
- avp_code_MIPv6_NONE_MIP_Session_Key (343),
+ avp_code_MIPv4_NONE_MIP_Session_Key (343),
avp_code_DCC_NONE_Tariff_Time_Change (451),
avp_code_DNAS_NONE_Tunnel_Password (69),
- avp_code_DCC_NONE_User_Equipment_Info_Value (460),
avp_code_DNAS_NONE_Tunneling (401),
+ avp_code_DCC_NONE_User_Equipment_Info_Value (460),
+ avp_code_MIPv4_NONE_MIP_Auth_Input_Data_Length (338),
avp_code_BASE_NONE_Multi_Round_Time_Out (272),
avp_code_BASE_NONE_Experimental_Result_Code (298),
- avp_code_DNAS_NONE_Configuration_Token (78),
avp_code_DNAS_NONE_Callback_Number (19),
+ avp_code_DNAS_NONE_Configuration_Token (78),
+ avp_code_MIPv4_NONE_MIP_Originating_Foreign_AAA (347),
avp_code_BASE_NONE_Error_Message (281),
avp_code_DNAS_NONE_NAS_Port_Type (61),
avp_code_DCC_NONE_Multiple_Services_Indicator (455),
@@ -5619,7 +8852,7 @@ type enumerated AVP_Code_NONE {
avp_code_DNAS_NONE_Filter_Id (11),
avp_code_DNAS_NONE_ARAP_Password (70),
avp_code_DNAS_NONE_CHAP_Response (405),
- avp_code_DNAS_NONE_Accounting_Input_Packets (365),
+ avp_code_MIPv4_NONE_Accounting_Input_Packets (365),
avp_code_DNAS_NONE_Callback_Id (20),
avp_code_DCC_NONE_CC_Output_Octets (414),
avp_code_DCC_NONE_Cost_Information (423),
@@ -5629,37 +8862,43 @@ type enumerated AVP_Code_NONE {
avp_code_DNAS_NONE_State (24),
avp_code_DNAS_NONE_Tunnel_Preference (83),
avp_code_DCC_NONE_CC_Session_Failover (418),
+ avp_code_MIPv4_NONE_MIP_FA_to_MN_SPI (319),
avp_code_BASE_NONE_Proxy_State (33),
avp_code_DCC_NONE_Credit_Control_Failure_Handling (427),
+ avp_code_MIPv6_NONE_MIP6_Agent_Info (486),
avp_code_BASE_NONE_Redirect_Max_Cache_Time (262),
avp_code_DCC_NONE_Requested_Action (436),
avp_code_DNAS_NONE_Idle_Timeout (28),
avp_code_DNAS_NONE_NAS_Port_Id (87),
avp_code_BASE_NONE_Host_IP_Address (257),
+ avp_code_MIPv4_NONE_MIP_Reg_Request (320),
avp_code_DNAS_NONE_Framed_Appletalk_Link (37),
avp_code_DNAS_NONE_Framed_Interface_Id (96),
avp_code_BASE_NONE_Vendor_Id (266),
- avp_code_DNAS_NONE_Acct_Session_Time (46),
+ avp_code_MIPv4_NONE_Acct_Session_Time (46),
avp_code_BASE_NONE_Event_Timestamp (55),
avp_code_DCC_NONE_Final_Unit_Action (449),
avp_code_DNAS_NONE_Framed_IPv6_Pool (100),
avp_code_DCC_NONE_Rating_Group (432),
avp_code_MIPv6_NONE_MIP_MN_HA_SPI (491),
avp_code_DCC_NONE_User_Equipment_Info (458),
- avp_code_MIPv6_NONE_MIP_Mobile_Node_Address (333),
+ avp_code_MIPv4_NONE_MIP_Mobile_Node_Address (333),
avp_code_DCC_NONE_Service_Parameter_Type (441),
+ avp_code_MIPv4_NONE_MIP_Filter_Rule (342),
avp_code_BASE_NONE_Failed_AVP (279),
avp_code_DCC_NONE_Subscription_Id_Type (450),
+ avp_code_MIPv4_NONE_MIP_FA_to_HA_MSA (328),
avp_code_DNAS_NONE_User_Password (2),
avp_code_DNAS_NONE_Acct_Tunnel_Connection (68),
avp_code_DNAS_NONE_NAS_Filter_Rule (400),
+ avp_code_MIPv4_NONE_MIP_Feature_Vector (337),
avp_code_BASE_NONE_Session_Server_Failover (271),
avp_code_BASE_NONE_Experimental_Result (297),
avp_code_DNAS_NONE_Acct_Link_Count (51),
avp_code_DCC_NONE_Unit_Value (445),
avp_code_DNAS_NONE_Reply_Message (18),
avp_code_DNAS_NONE_Connect_Info (77),
- avp_code_MIPv6_NONE_MIP_Replay_Mode (346),
+ avp_code_MIPv4_NONE_MIP_Replay_Mode (346),
avp_code_BASE_NONE_Proxy_Host (280),
avp_code_DNAS_NONE_CHAP_Challenge (60),
avp_code_DCC_NONE_CC_Unit_Type (454),
@@ -5674,9 +8913,10 @@ type enumerated AVP_Code_NONE {
avp_code_DNAS_NONE_Login_IP_Host (14),
avp_code_DNAS_NONE_ARAP_Security (73),
avp_code_DNAS_NONE_Origin_AAA_Protocol (408),
- avp_code_DNAS_NONE_Tunnel_Assignment_Id (82),
avp_code_DNAS_NONE_Framed_IPX_Network (23),
+ avp_code_DNAS_NONE_Tunnel_Assignment_Id (82),
avp_code_DCC_NONE_CC_Service_Specific_Units (417),
+ avp_code_MIPv4_NONE_MIP_FA_to_HA_SPI (318),
avp_code_DNAS_NONE_NAS_Identifier (32),
avp_code_DNAS_NONE_Tunnel_Server_Auth_Id (91),
avp_code_DCC_NONE_Credit_Control (426),
@@ -5684,21 +8924,23 @@ type enumerated AVP_Code_NONE {
avp_code_BASE_NONE_Redirect_Host_Usage (261),
avp_code_DCC_NONE_Redirect_Server_Address (435),
avp_code_MIPv6_NONE_MIP6_Auth_Mode (494),
- avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost (86),
avp_code_BASE_NONE_Session_Timeout (27),
- avp_code_DNAS_NONE_NAS_IPv6_Address (95),
+ avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost (86),
avp_code_DNAS_NONE_Login_LAT_Group (36),
+ avp_code_DNAS_NONE_NAS_IPv6_Address (95),
avp_code_MIPv6_NONE_MIP_MAC_Mobility_Data (489),
- avp_code_DNAS_NONE_Accounting_Output_Octets (364),
+ avp_code_MIPv4_NONE_Accounting_Output_Octets (364),
avp_code_BASE_NONE_Supported_Vendor_Id (265),
avp_code_DNAS_NONE_Acct_Authentic (45),
avp_code_DCC_NONE_Service_Identifier (439),
avp_code_BASE_NONE_Auth_Request_Type (274),
avp_code_DCC_NONE_Validity_Time (448),
+ avp_code_MIPv4_NONE_MIP_HA_to_FA_SPI (323),
avp_code_DNAS_NONE_Framed_IPv6_Route (99),
avp_code_DCC_NONE_Granted_Service_Unit (431),
avp_code_MIPv6_NONE_MIP_Timestamp (490),
avp_code_BASE_NONE_Product_Name (269),
+ avp_code_MIPv4_NONE_MIP_HA_to_MN_MSA (332),
avp_code_DNAS_NONE_Framed_IP_Netmask (9),
avp_code_DCC_NONE_Service_Parameter_Info (440),
avp_code_BASE_NONE_Origin_State_Id (278),
@@ -5706,30 +8948,32 @@ type enumerated AVP_Code_NONE {
avp_code_BASE_NONE_Accounting_Sub_Session_Id (287),
avp_code_DNAS_NONE_Acct_Delay_Time (41),
avp_code_DNAS_NONE_Tunnel_Server_Endpoint (67),
+ avp_code_MIPv4_NONE_MIP_Candidate_Home_Agent_Host (336),
avp_code_BASE_NONE_Session_Binding (270),
avp_code_BASE_NONE_Acct_Multi_Session_Id (50),
avp_code_DCC_NONE_Subscription_Id_Data (444),
- avp_code_MIPv6_NONE_MIP_Algorithm_Type (345),
+ avp_code_MIPv4_NONE_MIP_Algorithm_Type (345),
avp_code_MIPv6_NONE_QoS_Capability (578),
avp_code_DCC_NONE_G_S_U_Pool_Identifier (453),
avp_code_DNAS_NONE_NAS_Port (5),
avp_code_DNAS_NONE_CHAP_Algorithm (403),
avp_code_DCC_NONE_CC_Input_Octets (412),
avp_code_BASE_NONE_Destination_Realm (283),
+ avp_code_MIPv6_NONE_MIP6_Home_Link_Prefix (125),
avp_code_DNAS_NONE_Login_LAT_Port (63),
avp_code_DCC_NONE_G_S_U_Pool_Reference (457),
avp_code_MIPv6_NONE_Chargable_User_Identity (89),
avp_code_BASE_NONE_Redirect_Host (292),
- avp_code_DNAS_NONE_ARAP_Zone_Access (72),
avp_code_DNAS_NONE_Framed_Compression (13),
+ avp_code_DNAS_NONE_ARAP_Zone_Access (72),
avp_code_DNAS_NONE_QoS_Filter_Rule (407),
- avp_code_MIPv6_NONE_MIP_MN_AAA_SPI (341),
- avp_code_MIPv6_NONE_MIP_MSA_Lifetime (367),
- avp_code_DNAS_NONE_Tunnel_Private_Group_Id (81),
+ avp_code_MIPv4_NONE_MIP_MN_AAA_SPI (341),
+ avp_code_MIPv4_NONE_MIP_MSA_Lifetime (367),
avp_code_DNAS_NONE_Framed_Route (22),
+ avp_code_DNAS_NONE_Tunnel_Private_Group_Id (81),
avp_code_DCC_NONE_CC_Request_Type (416),
- avp_code_DNAS_NONE_Tunnel_Client_Auth_Id (90),
avp_code_DNAS_NONE_Calling_Station_Id (31),
+ avp_code_DNAS_NONE_Tunnel_Client_Auth_Id (90),
avp_code_DCC_NONE_Currency_Code (425),
avp_code_BASE_NONE_E2E_Sequence (300),
avp_code_BASE_NONE_Origin_Realm (296),
@@ -5740,7 +8984,7 @@ type enumerated AVP_Code_NONE {
avp_code_DNAS_NONE_Originating_Line_Info (94),
avp_code_DCC_NONE_Exponent (429),
avp_code_MIPv6_NONE_MIP_Authenticator (488),
- avp_code_DNAS_NONE_Accounting_Input_Octets (363),
+ avp_code_MIPv4_NONE_Accounting_Input_Octets (363),
avp_code_BASE_NONE_Origin_Host (264),
avp_code_BASE_NONE_Accounting_Session_Id (44),
avp_code_DCC_NONE_Restriction_Filter_Rule (438),
@@ -5748,31 +8992,40 @@ type enumerated AVP_Code_NONE {
avp_code_DCC_NONE_CC_Total_Octets (421),
avp_code_BASE_NONE_Accounting_Record_Type (480),
avp_code_DCC_NONE_Value_Digits (447),
+ avp_code_MIPv4_NONE_MIP_MN_AAA_Auth (322),
avp_code_BASE_NONE_Acct_Application_Id (259),
- avp_code_DNAS_NONE_Login_IPv6_Host (98),
avp_code_DNAS_NONE_Framed_Appletalk_Zone (39),
+ avp_code_DNAS_NONE_Login_IPv6_Host (98),
avp_code_DCC_NONE_Final_Unit_Indication (430),
+ avp_code_MIPv4_NONE_MIP_MN_to_HA_MSA (331),
avp_code_BASE_NONE_Result_Code (268),
avp_code_DNAS_NONE_Framed_IP_Address (8),
avp_code_BASE_NONE_Auth_Session_State (277),
+ avp_code_MIPv4_NONE_MIP_FA_to_MN_MSA (326),
avp_code_BASE_NONE_Vendor_Specific_Application_Id (260),
avp_code_MIPv6_NONE_Service_Selection (493),
avp_code_DNAS_NONE_Tunnel_Client_Endpoint (66),
+ avp_code_MIPv4_NONE_MIP_Nonce (335),
avp_code_DCC_NONE_Subscription_Id (443),
+ avp_code_MIPv4_NONE_MIP_FA_Challenge (344),
avp_code_DCC_NONE_Tariff_Change_Usage (452),
avp_code_DNAS_NONE_NAS_IP_Address (4),
- avp_code_DCC_NONE_Service_Context_Id (461),
avp_code_DNAS_NONE_CHAP_Auth (402),
+ avp_code_DCC_NONE_Service_Context_Id (461),
+ avp_code_MIPv4_NONE_MIP_Authenticator_Length (339),
avp_code_BASE_NONE_Inband_Security_Id (299),
avp_code_DCC_NONE_CC_Correlation_Id (411),
+ avp_code_MIPv4_NONE_MIP_Home_Agent_Host (348),
avp_code_BASE_NONE_Route_Record (282),
avp_code_DNAS_NONE_Port_Limit (62),
+ avp_code_MIPv6_NONE_MIP6_Feature_Vector (124),
avp_code_DCC_NONE_Multiple_Services_Credit_Control (456),
avp_code_BASE_NONE_Authorization_Lifetime (291),
avp_code_DNAS_NONE_ARAP_Features (71),
avp_code_DNAS_NONE_Framed_MTU (12),
avp_code_DNAS_NONE_Accounting_Auth_Method (406),
- avp_code_DNAS_NONE_Accounting_Output_Packets (366),
+ avp_code_MIPv4_NONE_MIP_Authenticator_Offset (340),
+ avp_code_MIPv4_NONE_Accounting_Output_Packets (366),
avp_code_DCC_NONE_CC_Request_Number (415),
avp_code_DNAS_NONE_Called_Station_Id (30),
avp_code_DCC_NONE_Cost_Unit (424),
@@ -5780,8 +9033,8 @@ type enumerated AVP_Code_NONE {
avp_code_BASE_NONE_Termination_Cause (295),
avp_code_DNAS_NONE_Login_TCP_Port (16),
avp_code_DNAS_NONE_Password_Retry (75),
- avp_code_DNAS_NONE_ARAP_Challenge_Response (84),
avp_code_BASE_NONE_Class (25),
+ avp_code_DNAS_NONE_ARAP_Challenge_Response (84),
avp_code_DCC_NONE_CC_Sub_Session_Id (419)
} with {
variant "FIELDLENGTH(32)"
@@ -5790,544 +9043,965 @@ type enumerated AVP_Code_NONE {
}
type enumerated AVP_Code_3GPP {
avp_code_GI_3GPP_3GPP_SGSN_IPv6_Address (15),
+ avp_code_AAA_3GPP_RAR_Flags (1522),
+ avp_code_DCA_3GPP_SCS_Address (3941),
avp_code_GI_3GPP_3GPP_GGSN_MCC_MNC (9),
+ avp_code_DCA_3GPP_TWAN_User_Location_Info (2714),
+ avp_code_DCA_3GPP_PoC_User_Role_IDs (1253),
+ avp_code_DCA_3GPP_Announcement_Order (3906),
avp_code_PCC_3GPP_Bearer_Identifier (1020),
avp_code_RX_3GPP_Content_Version (552),
+ avp_code_DCA_3GPP_Applic_ID (1218),
+ avp_code_DCA_3GPP_Route_Header_Transmitted (3404),
+ avp_code_DCA_3GPP_Reporting_Reason (872),
+ avp_code_AAA_3GPP_Emergency_Services (1538),
avp_code_RX_3GPP_Media_Component_Description (517),
avp_code_PCC_3GPP_CSG_Information_Reporting (1071),
avp_code_AAA_3GPP_Measurement_Quantity (1660),
avp_code_S6_3GPP_Location_Information_Configuration (3135),
avp_code_PCC_3GPP_Bearer_Usage (1000),
+ avp_code_DCA_3GPP_Application_provided_Called_Party_Address (837),
+ avp_code_DCA_3GPP_Proximity_Alert_Timestamp (3455),
avp_code_PCC_3GPP_Tunnel_Header_Filter (1036),
avp_code_AAA_3GPP_List_Of_Measurements (1625),
avp_code_PCC_3GPP_Default_QoS_Name (2817),
avp_code_AAA_3GPP_UVA_Flags (1640),
+ avp_code_DCA_3GPP_Expires (888),
avp_code_CxDx_3GPP_SAR_Flags (655),
- avp_code_AAA_3GPP_Group_Service_Id (1676),
avp_code_PCC_3GPP_TDF_Information (1087),
+ avp_code_AAA_3GPP_Group_Service_Id (1676),
+ avp_code_DCA_3GPP_Recipient_SCCP_Address (2010),
+ avp_code_DCA_3GPP_Preferred_AoC_Currency (2315),
+ avp_code_DCA_3GPP_Traffic_Data_Volumes (2046),
avp_code_AAA_3GPP_Requested_EUTRAN_Authentication_Info (1408),
+ avp_code_DCA_3GPP_Unit_Cost (2061),
avp_code_CxDx_3GPP_SIP_Digest_Authenticate (635),
avp_code_AAA_3GPP_Last_UE_Activity_Time (1494),
avp_code_AAA_3GPP_Context_Identifier (1423),
avp_code_AAA_3GPP_Trace_Reference (1459),
+ avp_code_AAA_3GPP_TWAN_Access_Info (1510),
+ avp_code_DCA_3GPP_Status_AS_Code (2702),
+ avp_code_DCA_3GPP_LCS_Client_Type (1241),
+ avp_code_DCA_3GPP_PoC_Session_Initiation_Type (1277),
avp_code_RX_3GPP_Sharing_Key_UL (540),
+ avp_code_DCA_3GPP_Content_Size (1206),
+ avp_code_AAA_3GPP_Access_Network_Info (1526),
avp_code_RX_3GPP_AF_Charging_Identifier (505),
avp_code_S6_3GPP_Monitoring_Event_Report (3123),
+ avp_code_DCA_3GPP_Service_Specific_Type (1257),
+ avp_code_DCA_3GPP_Event (825),
avp_code_RX_3GPP_Media_Type (520),
avp_code_PCC_3GPP_Conditional_Policy_Information (2840),
- avp_code_AAA_3GPP_SIPTO_Permission (1613),
+ avp_code_DCA_3GPP_ProSe_Event_Type (3443),
avp_code_PCC_3GPP_Network_Request_Support (1024),
+ avp_code_AAA_3GPP_SIPTO_Permission (1613),
+ avp_code_DCA_3GPP_Terminating_IOI (840),
avp_code_RX_3GPP_Extended_Max_Supported_BW_DL (556),
avp_code_PCC_3GPP_UE_Local_IP_Address (2805),
+ avp_code_DCA_3GPP_SM_Sequence_Number (3408),
+ avp_code_DCA_3GPP_IMS_Information (876),
avp_code_PCC_3GPP_Presence_Reporting_Area_Elements_List (2820),
- avp_code_AAA_3GPP_SGs_MME_Identity (1664),
avp_code_PCC_3GPP_Routing_Rule_Remove (1075),
+ avp_code_AAA_3GPP_SGs_MME_Identity (1664),
avp_code_S6_3GPP_Roaming_Information (3139),
+ avp_code_DCA_3GPP_Number_Of_Diversions (2034),
+ avp_code_DCA_3GPP_Coverage_Info (3459),
avp_code_CxDx_3GPP_SIP_Authentication_Scheme (608),
avp_code_AAA_3GPP_Event_Threshold_RSRP (1629),
avp_code_CxDx_3GPP_User_Authorization_Type (623),
avp_code_AAA_3GPP_PLMN_Client (1482),
avp_code_AAA_3GPP_Re_Synchronization_Info (1411),
+ avp_code_DCA_3GPP_User_CSG_Information (2319),
+ avp_code_DCA_3GPP_SM_Status (2014),
+ avp_code_DCA_3GPP_IP_Realm_Default_Indication (2603),
avp_code_AAA_3GPP_RAND (1447),
avp_code_AAA_3GPP_Trace_Depth (1462),
avp_code_AAA_3GPP_SGSN_User_State (1498),
avp_code_AAA_3GPP_APN_OI_Replacement (1427),
+ avp_code_DCA_3GPP_Alternate_Charged_Party_Address (1280),
+ avp_code_DCA_3GPP_APN_Rate_Control (3933),
+ avp_code_DCA_3GPP_Relationship_Mode (2706),
avp_code_S6_3GPP_External_Identifier (3111),
+ avp_code_DCA_3GPP_Positioning_Data (1245),
+ avp_code_DCA_3GPP_Monitoring_UE_HPLMN_Identifier (3431),
avp_code_PCC_3GPP_TFT_Filter (1012),
avp_code_RX_3GPP_Max_Supported_Bandwidth_UL (544),
avp_code_S6_3GPP_Loss_Of_Connectivity_Reason (3162),
+ avp_code_DCA_3GPP_Originator (864),
avp_code_RX_3GPP_Flow_Number (509),
avp_code_PCC_3GPP_Resource_Allocation_Notification (1063),
+ avp_code_DCA_3GPP_Basic_Service_Code (3411),
avp_code_S6_3GPP_Monitoring_Type (3127),
+ avp_code_DCA_3GPP_Role_Of_Node (829),
avp_code_PCC_3GPP_Default_Bearer_Indication (2844),
- avp_code_AAA_3GPP_VPLMN_LIPA_Allowed (1617),
+ avp_code_DCA_3GPP_ProSe_Information (3447),
avp_code_PCC_3GPP_QoS_Class_Identifier (1028),
+ avp_code_AAA_3GPP_VPLMN_LIPA_Allowed (1617),
avp_code_PCC_3GPP_Mute_Notification (2809),
avp_code_CxDx_3GPP_SIP_Authentication_Context (611),
avp_code_AAA_3GPP_Logging_Duration (1632),
avp_code_CxDx_3GPP_Associated_Registered_Identities (647),
- avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN (1668),
avp_code_PCC_3GPP_Routing_IP_Address (1079),
+ avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN (1668),
+ avp_code_DCA_3GPP_MBMS_GW_Address (2307),
+ avp_code_DCA_3GPP_Destination_Interface (2002),
+ avp_code_DCA_3GPP_IMS_Emergency_Indicator (2322),
+ avp_code_DCA_3GPP_Change_Time (2038),
avp_code_AAA_3GPP_KASME (1450),
+ avp_code_DCA_3GPP_AoC_Cost_Information (2053),
avp_code_GI_3GPP_3GPP_User_Location_Info_Time (30),
avp_code_AAA_3GPP_Teleservice_List (1486),
avp_code_AAA_3GPP_UTRAN_Vector (1415),
+ avp_code_AAA_3GPP_Non_3GPP_IP_Access_APN (1502),
+ avp_code_DCA_3GPP_Monitoring_Event_Information (3921),
avp_code_GI_3GPP_3GPP_NSAPI (10),
+ avp_code_DCA_3GPP_LCS_Client_Dialed_By_MS (1233),
avp_code_GI_3GPP_3GPP_CG_Address (4),
+ avp_code_DCA_3GPP_Envelope_Start_Time (1269),
avp_code_RX_3GPP_Application_Service_Provider_Identity (532),
avp_code_S6_3GPP_NIDD_Authorization_Request (3150),
+ avp_code_DCA_3GPP_Received_Talk_Burst_Time (1284),
+ avp_code_DCA_3GPP_Incoming_Trunk_Group_Id (852),
+ avp_code_AAA_3GPP_AAA_Failure_Indication (1518),
+ avp_code_DCA_3GPP_Rate_Control_Max_Message_Size (3937),
avp_code_PCC_3GPP_QoS_Rule_Install (1051),
avp_code_S6_3GPP_Periodic_Communication_Indicator (3115),
+ avp_code_DCA_3GPP_Service_Specific_Info (1249),
avp_code_RX_3GPP_Flow_Usage (512),
avp_code_PCC_3GPP_RAN_Rule_Support (2832),
+ avp_code_DCA_3GPP_PC3_EPC_Control_Protocol_Cause (3435),
avp_code_S6_3GPP_Monitoring_Duration (3130),
- avp_code_AAA_3GPP_Routing_Area_Identity (1605),
avp_code_PCC_3GPP_QoS_Information (1016),
+ avp_code_AAA_3GPP_Routing_Area_Identity (1605),
+ avp_code_DCA_3GPP_Called_Party_Address (832),
avp_code_RX_3GPP_Service_Authorization_Info (548),
avp_code_AAA_3GPP_eDRX_Cycle_Length (1691),
avp_code_S6_3GPP_Group_Monitoring_Event_Report_Item (3166),
- avp_code_AAA_3GPP_Ext_PDP_Type (1620),
avp_code_PCC_3GPP_Rule_Failure_Code (1031),
+ avp_code_AAA_3GPP_Ext_PDP_Type (1620),
+ avp_code_DCA_3GPP_Time_Quota_Threshold (868),
avp_code_PCC_3GPP_User_Location_Info_Time (2812),
- avp_code_AAA_3GPP_Measurement_Period_LTE (1656),
avp_code_PCC_3GPP_Usage_Monitoring_Information (1067),
+ avp_code_AAA_3GPP_Measurement_Period_LTE (1656),
avp_code_PCC_3GPP_Extended_APN_AMBR_DL (2848),
avp_code_CxDx_3GPP_Session_Priority (650),
+ avp_code_DCA_3GPP_Recipient_Info (2026),
+ avp_code_DCA_3GPP_AoC_Format (2310),
+ avp_code_DCA_3GPP_Start_Time (2041),
avp_code_CxDx_3GPP_Deregistration_Reason (615),
avp_code_AAA_3GPP_GMLC_Number (1474),
avp_code_AAA_3GPP_Software_Version (1403),
+ avp_code_DCA_3GPP_Interface_Type (2006),
avp_code_AAA_3GPP_Expiration_Date (1439),
avp_code_AAA_3GPP_SRES (1454),
+ avp_code_DCA_3GPP_DRM_Content (1221),
avp_code_AAA_3GPP_Item_Number (1419),
+ avp_code_AAA_3GPP_ERP_Authorization (1541),
+ avp_code_DCA_3GPP_Early_Media_Description (1272),
+ avp_code_AAA_3GPP_MIP_FA_RK (1506),
+ avp_code_DCA_3GPP_Related_Change_Condition_Information (3925),
avp_code_S6_3GPP_Service_ID (3103),
+ avp_code_DCA_3GPP_LCS_Format_Indicator (1237),
avp_code_GI_3GPP_3GPP_IMSI_MCC_MNC (8),
avp_code_RX_3GPP_Abort_Cause (500),
+ avp_code_DCA_3GPP_ISUP_Cause_Location (3423),
avp_code_PCC_3GPP_Charging_Rule_Base_Name (1004),
avp_code_RX_3GPP_Required_Access_Info (536),
avp_code_PCC_3GPP_TDF_Destination_Realm (1090),
avp_code_S6_3GPP_S6t_HSS_Cause (3154),
+ avp_code_DCA_3GPP_Media_Initiator_Party (1288),
+ avp_code_DCA_3GPP_Associated_URI (856),
avp_code_RX_3GPP_AF_Requested_Data (551),
avp_code_PCC_3GPP_QoS_Rule_Report (1055),
+ avp_code_DCA_3GPP_Route_Header_Received (3403),
avp_code_S6_3GPP_Stationary_Indication (3119),
avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL (2836),
+ avp_code_DCA_3GPP_Usage_Information_Report_Sequence_Number (3439),
avp_code_AAA_3GPP_Geodetic_Information (1609),
avp_code_PCC_3GPP_Extended_GBR_UL (2851),
avp_code_AAA_3GPP_MBSFN_Area_ID (1695),
avp_code_CxDx_3GPP_Server_Capabilities (603),
avp_code_AAA_3GPP_Area_Scope (1624),
+ avp_code_DCA_3GPP_SGW_Change (2065),
avp_code_CxDx_3GPP_SCSCF_Restoration_Info (639),
avp_code_CxDx_3GPP_Initial_CSeq_Sequence_Number (654),
+ avp_code_DCA_3GPP_AoC_Subscription_Information (2314),
avp_code_AAA_3GPP_PUA_Flags (1442),
+ avp_code_DCA_3GPP_Time_Usage (2045),
avp_code_CxDx_3GPP_Primary_Event_Charging_Function_Name (619),
avp_code_GI_3GPP_3GPP_User_Location_Info (22),
avp_code_AAA_3GPP_Notification_To_UE_User (1478),
avp_code_AAA_3GPP_Visited_PLMN_Id (1407),
avp_code_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions (1493),
+ avp_code_DCA_3GPP_Participant_Group (1260),
+ avp_code_DCA_3GPP_Play_Alternative (3913),
+ avp_code_DCA_3GPP_MBMS_User_Service_Type (1225),
+ avp_code_DCA_3GPP_Transit_IOI_List (2701),
avp_code_RX_3GPP_Codec_Data (524),
avp_code_S6_3GPP_Monitoring_Event_Config_Status (3142),
+ avp_code_DCA_3GPP_SDP_Media_Name (844),
+ avp_code_DCA_3GPP_AF_Correlation_Information (1276),
+ avp_code_DCA_3GPP_Serving_Node_Identity (3929),
+ avp_code_DCA_3GPP_Radio_Frequency (3462),
avp_code_PCC_3GPP_Rule_Activation_Time (1043),
avp_code_S6_3GPP_Service_Data (3107),
avp_code_RX_3GPP_AF_Application_Identifier (504),
avp_code_PCC_3GPP_NetLoc_Access_Support (2824),
+ avp_code_DCA_3GPP_Announcing_UE_VPLMN_Identifier (3427),
avp_code_S6_3GPP_Monitoring_Event_Configuration (3122),
avp_code_PCC_3GPP_Offline (1008),
- avp_code_AAA_3GPP_Additional_Context_ID (1683),
+ avp_code_DCA_3GPP_SIP_Method (824),
avp_code_PCC_3GPP_ADC_Rule_Definition (1094),
+ avp_code_AAA_3GPP_Additional_Context_ID (1683),
avp_code_S6_3GPP_Allowed_PLMN_List (3158),
- avp_code_AAA_3GPP_Active_APN (1612),
avp_code_PCC_3GPP_Bearer_Control_Mode (1023),
+ avp_code_AAA_3GPP_Active_APN (1612),
avp_code_PCC_3GPP_HeNB_Local_IP_Address (2804),
- avp_code_AAA_3GPP_SMS_Register_Request (1648),
avp_code_PCC_3GPP_Packet_Filter_Content (1059),
+ avp_code_AAA_3GPP_SMS_Register_Request (1648),
avp_code_CxDx_3GPP_Subscription_Info (642),
+ avp_code_DCA_3GPP_SIP_Response_Timestamp_Fraction (2302),
+ avp_code_DCA_3GPP_Client_Address (2018),
avp_code_AAA_3GPP_APN_Configuration (1430),
+ avp_code_DCA_3GPP_Subscriber_Role (2033),
avp_code_CxDx_3GPP_SIP_Number_Auth_Items (607),
avp_code_AAA_3GPP_OMC_Id (1466),
avp_code_AAA_3GPP_GMLC_Restriction (1481),
+ avp_code_DCA_3GPP_Enhanced_Diagnostics (3901),
+ avp_code_DCA_3GPP_CSG_Membership_Indication (2318),
avp_code_AAA_3GPP_Regional_Subscription_Zone_Code (1446),
+ avp_code_DCA_3GPP_Message_Class (1213),
avp_code_GI_3GPP_3GPP_Negotiated_DSCP (26),
+ avp_code_AAA_3GPP_TWAN_S2a_Failure_Cause (1533),
+ avp_code_DCA_3GPP_Trigger (1264),
+ avp_code_DCA_3GPP_Called_Identity_Change (3917),
+ avp_code_DCA_3GPP_ProSe_Request_Timestamp (3450),
+ avp_code_DCA_3GPP_PoC_Session_Id (1229),
+ avp_code_DCA_3GPP_PoC_Server_Role (883),
+ avp_code_DCA_3GPP_Forwarding_Pending (3415),
avp_code_S6_3GPP_SIR_Flags (3110),
avp_code_RX_3GPP_MPS_Identifier (528),
- avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id (1671),
avp_code_PCC_3GPP_Credit_Management_Status (1082),
+ avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id (1671),
+ avp_code_DCA_3GPP_Monitored_PLMN_Identifier (3430),
avp_code_S6_3GPP_Service_Result (3146),
- avp_code_AAA_3GPP_MME_Location_Information (1600),
avp_code_PCC_3GPP_Reporting_Level (1011),
+ avp_code_AAA_3GPP_MME_Location_Information (1600),
+ avp_code_DCA_3GPP_Served_Party_IP_Address (848),
avp_code_RX_3GPP_Max_Supported_Bandwidth_DL (543),
- avp_code_AAA_3GPP_Subscribed_VSRVCC (1636),
+ avp_code_DCA_3GPP_Time_First_Reception (3466),
avp_code_PCC_3GPP_Pre_emption_Capability (1047),
+ avp_code_AAA_3GPP_Subscribed_VSRVCC (1636),
avp_code_PCC_3GPP_Monitoring_Flags (2828),
avp_code_CxDx_3GPP_Feature_List (630),
+ avp_code_DCA_3GPP_Address_Type (899),
avp_code_PCC_3GPP_TCP_Source_Port (2843),
avp_code_PCC_3GPP_Application_Detection_Information (1098),
avp_code_AAA_3GPP_Emergency_Info (1687),
+ avp_code_DCA_3GPP_Remaining_Balance (2021),
avp_code_AAA_3GPP_MPS_Priority (1616),
+ avp_code_DCA_3GPP_Next_Tariff (2057),
avp_code_CxDx_3GPP_Record_Route (646),
+ avp_code_DCA_3GPP_Tariff_XML (2306),
avp_code_AAA_3GPP_Alert_Reason (1434),
+ avp_code_DCA_3GPP_Recipient_Address (1201),
+ avp_code_DCA_3GPP_Change_Condition (2037),
avp_code_GI_3GPP_3GPP_CG_IPv6_Address (14),
+ avp_code_AAA_3GPP_DEA_Flags (1521),
+ avp_code_DCA_3GPP_SCS_AS_Address (3940),
avp_code_AAA_3GPP_MO_LR (1485),
+ avp_code_DCA_3GPP_IMS_Visited_Network_Identifier (2713),
+ avp_code_DCA_3GPP_PoC_User_Role (1252),
+ avp_code_DCA_3GPP_Announcement_Identifier (3905),
+ avp_code_AAA_3GPP_Non_3GPP_IP_Access (1501),
+ avp_code_DCA_3GPP_Monitoring_Event_Report_Data (3920),
+ avp_code_DCA_3GPP_Adaptations (1217),
+ avp_code_DCA_3GPP_Quota_Holding_Time (871),
+ avp_code_AAA_3GPP_Maximum_Wait_Time (1537),
avp_code_RX_3GPP_Max_Requested_Bandwidth_UL (516),
avp_code_PCC_3GPP_Usage_Monitoring_Support (1070),
avp_code_S6_3GPP_Maximum_Response_Time (3134),
+ avp_code_DCA_3GPP_Envelope_Reporting (1268),
+ avp_code_DCA_3GPP_Application_Server (836),
avp_code_RX_3GPP_Sponsor_Identity (531),
+ avp_code_DCA_3GPP_Proximity_Alert_Indication (3454),
avp_code_PCC_3GPP_CoA_IP_Address (1035),
+ avp_code_DCA_3GPP_Trunk_Group_Id (851),
avp_code_PCC_3GPP_Default_QoS_Information (2816),
avp_code_PCC_3GPP_AN_GW_Address (1050),
+ avp_code_DCA_3GPP_Start_Of_Charging (3419),
+ avp_code_DCA_3GPP_Participants_Involved (887),
avp_code_PCC_3GPP_NBIFOM_Support (2831),
avp_code_PCC_3GPP_Redirect_Support (1086),
avp_code_AAA_3GPP_IMSI_Group_Id (1675),
avp_code_AAA_3GPP_Cell_Global_Identity (1604),
avp_code_AAA_3GPP_PDN_Connection_Continuity (1690),
+ avp_code_DCA_3GPP_Tariff_Information (2060),
avp_code_CxDx_3GPP_Wildcarded_Public_Identity (634),
avp_code_AAA_3GPP_DSA_Flags (1422),
+ avp_code_DCA_3GPP_PoC_Event_Type (2025),
avp_code_AAA_3GPP_Trace_Data (1458),
avp_code_AAA_3GPP_LCS_Info (1473),
+ avp_code_DCA_3GPP_LCS_Requestor_Id_String (1240),
avp_code_AAA_3GPP_PDN_GW_Allocation_Type (1438),
+ avp_code_DCA_3GPP_Additional_Type_Information (1205),
avp_code_GI_3GPP_3GPP_SGSN_MCC_MNC (18),
+ avp_code_AAA_3GPP_HESSID (1525),
+ avp_code_DCA_3GPP_Content_Class (1220),
+ avp_code_DCA_3GPP_TAD_Identifier (2717),
+ avp_code_AAA_3GPP_IMEI_Check_In_VPLMN_Result (1540),
+ avp_code_DCA_3GPP_Service_Generic_Information (1256),
+ avp_code_DCA_3GPP_Variable_Part_Type (3909),
+ avp_code_DCA_3GPP_ProSe_Direct_Discovery_Model (3442),
avp_code_RX_3GPP_Extended_Max_Requested_BW_UL (555),
+ avp_code_DCA_3GPP_SM_Device_Trigger_Indicator (3407),
avp_code_S6_3GPP_User_Identifier (3102),
avp_code_PCC_3GPP_QoS_Rule_Base_Name (1074),
avp_code_AAA_3GPP_Restoration_Priority (1663),
+ avp_code_DCA_3GPP_ISUP_Cause_Diagnostics (3422),
avp_code_S6_3GPP_Association_Type (3138),
avp_code_PCC_3GPP_Charging_Rule_Definition (1003),
avp_code_RX_3GPP_Min_Requested_Bandwidth_UL (535),
- avp_code_AAA_3GPP_Report_Amount (1628),
+ avp_code_DCA_3GPP_Application_Specific_Data (3458),
avp_code_PCC_3GPP_CoA_Information (1039),
+ avp_code_AAA_3GPP_Report_Amount (1628),
avp_code_CxDx_3GPP_Secondary_Charging_Collection_Function_Name (622),
avp_code_AAA_3GPP_A_MSISDN (1643),
avp_code_PCC_3GPP_Routing_Rule_Report (2835),
avp_code_AAA_3GPP_Number_Of_Requested_Vectors (1410),
avp_code_AAA_3GPP_AIR_Flags (1679),
+ avp_code_DCA_3GPP_SM_Protocol_ID (2013),
+ avp_code_DCA_3GPP_Low_Priority_Indicator (2602),
avp_code_AAA_3GPP_Geographical_Information (1608),
+ avp_code_DCA_3GPP_Participant_Action_Type (2049),
+ avp_code_DCA_3GPP_Node_Id (2064),
avp_code_CxDx_3GPP_Loose_Route_Indication (638),
avp_code_AAA_3GPP_MME_User_State (1497),
avp_code_AAA_3GPP_Access_Restriction_Data (1426),
+ avp_code_DCA_3GPP_SM_Service_Type (2029),
+ avp_code_DCA_3GPP_UNI_PDU_CP_Only_Flag (3932),
avp_code_GI_3GPP_3GPP_RAT_Type (21),
avp_code_AAA_3GPP_SS_Status (1477),
+ avp_code_DCA_3GPP_Neighbour_Node_Address (2705),
+ avp_code_DCA_3GPP_Location_Type (1244),
+ avp_code_DCA_3GPP_Quota_Indicator (3912),
+ avp_code_DCA_3GPP_Priority (1209),
avp_code_S6_3GPP_NIDD_Authorization_Update (3161),
+ avp_code_DCA_3GPP_Service_Specific_Data (863),
+ avp_code_AAA_3GPP_Connectivity_Flags (1529),
avp_code_PCC_3GPP_Packet_Filter_Operation (1062),
+ avp_code_DCA_3GPP_VCS_Information (3410),
avp_code_S6_3GPP_SCEF_Reference_ID_for_Deletion (3126),
+ avp_code_DCA_3GPP_Content_Disposition (828),
avp_code_RX_3GPP_SIP_Forking_Indication (523),
+ avp_code_DCA_3GPP_ProSe_Group_IP_Multicast_Address (3446),
avp_code_S6_3GPP_IMEI_Change (3141),
avp_code_PCC_3GPP_IP_CAN_Type (1027),
+ avp_code_DCA_3GPP_SDP_Media_Component (843),
avp_code_RX_3GPP_Extended_Min_Desired_BW_UL (559),
+ avp_code_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container (3461),
avp_code_CxDx_3GPP_SIP_Authorization (610),
avp_code_PCC_3GPP_Revalidation_Time (1042),
avp_code_AAA_3GPP_Logging_Interval (1631),
+ avp_code_DCA_3GPP_PoC_Information (879),
avp_code_PCC_3GPP_Presence_Reporting_Area_Status (2823),
- avp_code_AAA_3GPP_WLAN_offloadability (1667),
avp_code_PCC_3GPP_Routing_Filter (1078),
+ avp_code_AAA_3GPP_WLAN_offloadability (1667),
+ avp_code_DCA_3GPP_Data_Coding_Scheme (2001),
avp_code_PCC_3GPP_Metering_Method (1007),
avp_code_AAA_3GPP_Non_IP_Data_Delivery_Mechanism (1682),
+ avp_code_DCA_3GPP_Initial_IMS_Charging_Identifier (2321),
+ avp_code_DCA_3GPP_Accumulated_Cost (2052),
avp_code_CxDx_3GPP_Integrity_Key (626),
avp_code_AAA_3GPP_E_UTRAN_Vector (1414),
+ avp_code_DCA_3GPP_SMSC_Address (2017),
+ avp_code_DCA_3GPP_PDP_Address_Prefix_Length (2606),
avp_code_AAA_3GPP_Trace_Event_List (1465),
+ avp_code_DCA_3GPP_LCS_Client_Id (1232),
avp_code_GI_3GPP_3GPP_PDP_Type (3),
+ avp_code_DCA_3GPP_Number_Of_Talk_Bursts (1283),
+ avp_code_AAA_3GPP_Short_Network_Name (1517),
+ avp_code_DCA_3GPP_Message_Size (1212),
+ avp_code_DCA_3GPP_Additional_Exception_Reports (3936),
+ avp_code_DCA_3GPP_Access_Transfer_Information (2709),
avp_code_S6_3GPP_Communication_Pattern_Set (3114),
+ avp_code_AAA_3GPP_TWAG_UP_Address (1532),
+ avp_code_DCA_3GPP_MMBox_Storage_Requested (1248),
avp_code_RX_3GPP_Flow_Status (511),
+ avp_code_DCA_3GPP_PC3_Control_Protocol_Cause (3434),
+ avp_code_DCA_3GPP_Calling_Party_Address (831),
avp_code_RX_3GPP_MCPTT_Identifier (547),
avp_code_S6_3GPP_Group_Monitoring_Event_Report (3165),
avp_code_PCC_3GPP_QoS_Upgrade (1030),
+ avp_code_DCA_3GPP_PS_Append_Free_Format_Data (867),
avp_code_PCC_3GPP_AN_GW_Status (2811),
- avp_code_AAA_3GPP_Measurement_Period_UMTS (1655),
avp_code_PCC_3GPP_Monitoring_Key (1066),
+ avp_code_AAA_3GPP_Measurement_Period_UMTS (1655),
+ avp_code_DCA_3GPP_Media_Initiator_Flag (882),
+ avp_code_DCA_3GPP_ISUP_Location_Number (3414),
avp_code_PCC_3GPP_3GPP_PS_Data_Off_Status (2847),
- avp_code_AAA_3GPP_Reset_ID (1670),
avp_code_PCC_3GPP_Routing_Rule_Install (1081),
+ avp_code_AAA_3GPP_Reset_ID (1670),
+ avp_code_DCA_3GPP_Service_Data_Container (2040),
avp_code_CxDx_3GPP_Server_Assignment_Type (614),
avp_code_AAA_3GPP_PUR_Flags (1635),
avp_code_PCC_3GPP_IP_CAN_Session_Charging_Scope (2827),
avp_code_AAA_3GPP_IMEI (1402),
+ avp_code_DCA_3GPP_Interface_Text (2005),
avp_code_AAA_3GPP_Kc (1453),
+ avp_code_DCA_3GPP_Current_Tariff (2056),
avp_code_AAA_3GPP_SGSN_Number (1489),
avp_code_AAA_3GPP_HPLMN_ODB (1418),
+ avp_code_DCA_3GPP_Time_Quota_Type (1271),
+ avp_code_AAA_3GPP_Trace_Info (1505),
+ avp_code_DCA_3GPP_Domain_Name (1200),
avp_code_GI_3GPP_3GPP_Charging_Characteristics (13),
avp_code_AAA_3GPP_PDP_Context (1469),
+ avp_code_AAA_3GPP_DER_Flags (1520),
+ avp_code_DCA_3GPP_LCS_Data_Coding_Scheme (1236),
avp_code_GI_3GPP_3GPP_GGSN_Address (7),
+ avp_code_DCA_3GPP_Related_IMS_Charging_Identifier_Node (2712),
avp_code_S6_3GPP_Node_Type (3153),
+ avp_code_DCA_3GPP_Talk_Burst_Volume (1287),
+ avp_code_DCA_3GPP_Service_Id (855),
avp_code_RX_3GPP_Priority_Sharing_Indicator (550),
avp_code_PCC_3GPP_QoS_Rule_Name (1054),
+ avp_code_DCA_3GPP_Trigger_Type (870),
+ avp_code_DCA_3GPP_Instance_Id (3402),
avp_code_S6_3GPP_Scheduled_Communication_Time (3118),
avp_code_RX_3GPP_Max_Requested_Bandwidth_DL (515),
+ avp_code_DCA_3GPP_Role_Of_ProSe_Function (3438),
avp_code_S6_3GPP_Maximum_Latency (3133),
avp_code_PCC_3GPP_PCC_Rule_Status (1019),
+ avp_code_DCA_3GPP_SIP_Response_Timestamp (835),
avp_code_PCC_3GPP_Extended_GBR_DL (2850),
avp_code_AAA_3GPP_MBSFN_Area (1694),
+ avp_code_DCA_3GPP_ProSe_UE_ID (3453),
avp_code_CxDx_3GPP_Server_Name (602),
avp_code_S6_3GPP_APN_Validity_Time (3169),
- avp_code_AAA_3GPP_Job_Type (1623),
avp_code_PCC_3GPP_Allocation_Retention_Priority (1034),
+ avp_code_AAA_3GPP_Job_Type (1623),
avp_code_AAA_3GPP_Positioning_Method (1659),
avp_code_CxDx_3GPP_LIA_Flags (653),
avp_code_AAA_3GPP_DL_Buffering_Suggested_Packet_Count (1674),
+ avp_code_DCA_3GPP_AoC_Service_Type (2313),
avp_code_AAA_3GPP_IDA_Flags (1441),
+ avp_code_DCA_3GPP_Time_Last_Usage (2044),
avp_code_CxDx_3GPP_Charging_Information (618),
avp_code_AAA_3GPP_ULA_Flags (1406),
+ avp_code_DCA_3GPP_Originator_Interface (2009),
avp_code_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported (1492),
avp_code_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature (1457),
+ avp_code_DCA_3GPP_File_Repair_Supported (1224),
+ avp_code_DCA_3GPP_SDP_Answer_Timestamp (1275),
+ avp_code_AAA_3GPP_WLAN_Identifier (1509),
+ avp_code_DCA_3GPP_Type_Number (1204),
+ avp_code_DCA_3GPP_NIDD_Submission (3928),
avp_code_S6_3GPP_T4_Parameters (3106),
avp_code_RX_3GPP_Access_Network_Charging_Identifier_Value (503),
+ avp_code_DCA_3GPP_Announcing_UE_HPLMN_Identifier (3426),
avp_code_S6_3GPP_AESE_Error_Report (3121),
+ avp_code_DCA_3GPP_Event_Type (823),
avp_code_RX_3GPP_Sharing_Key_DL (539),
avp_code_PCC_3GPP_ADC_Rule_Remove (1093),
+ avp_code_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container (3441),
avp_code_S6_3GPP_Restricted_PLMN_List (3157),
- avp_code_AAA_3GPP_Age_Of_Location_Information (1611),
avp_code_PCC_3GPP_Access_Network_Charging_Identifier_Gx (1022),
+ avp_code_AAA_3GPP_Age_Of_Location_Information (1611),
+ avp_code_DCA_3GPP_PoC_Group_Name (859),
avp_code_RX_3GPP_Extended_Max_Requested_BW_DL (554),
avp_code_PCC_3GPP_Flow_Information (1058),
+ avp_code_DCA_3GPP_PS_Information (874),
+ avp_code_DCA_3GPP_MTC_IWF_Address (3406),
avp_code_PCC_3GPP_Execution_Time (2839),
avp_code_CxDx_3GPP_Contact (641),
- avp_code_AAA_3GPP_Event_Threshold_Event_1I (1662),
avp_code_PCC_3GPP_Charging_Correlation_Indicator (1073),
+ avp_code_AAA_3GPP_Event_Threshold_Event_1I (1662),
+ avp_code_DCA_3GPP_SIP_Request_Timestamp_Fraction (2301),
+ avp_code_DCA_3GPP_Service_Mode (2032),
avp_code_CxDx_3GPP_User_Data (606),
avp_code_AAA_3GPP_Report_Interval (1627),
avp_code_PCC_3GPP_RAN_NAS_Release_Cause (2819),
+ avp_code_DCA_3GPP_Dynamic_Address_Flag_Extension (2068),
avp_code_AAA_3GPP_Client_Identity (1480),
+ avp_code_DCA_3GPP_CSG_Access_Mode (2317),
avp_code_AAA_3GPP_Equipment_Status (1445),
+ avp_code_DCA_3GPP_Supplementary_Service (2048),
avp_code_GI_3GPP_3GPP_Packet_Filter (25),
avp_code_AAA_3GPP_EPS_Location_Information (1496),
+ avp_code_DCA_3GPP_Access_Network_Information (1263),
+ avp_code_DCA_3GPP_Called_Identity (3916),
+ avp_code_AAA_3GPP_TWAN_Default_APN_Context_Id (1512),
+ avp_code_DCA_3GPP_SGSN_Address (1228),
+ avp_code_DCA_3GPP_SGi_PtP_Tunnelling_Method (3931),
+ avp_code_DCA_3GPP_NNI_Type (2704),
avp_code_RX_3GPP_Service_Info_Status (527),
avp_code_S6_3GPP_CIR_Flags (3145),
avp_code_PCC_3GPP_Precedence (1010),
+ avp_code_DCA_3GPP_User_Participating_Type (1279),
+ avp_code_DCA_3GPP_GGSN_Address (847),
avp_code_RX_3GPP_Sponsoring_Action (542),
+ avp_code_DCA_3GPP_Radio_Resources_Indicator (3465),
avp_code_S6_3GPP_Granted_Validity_Time (3160),
avp_code_PCC_3GPP_Priority_Level (1046),
+ avp_code_DCA_3GPP_Node_Functionality (862),
avp_code_RX_3GPP_Flow_Description (507),
- avp_code_AAA_3GPP_Daylight_Saving_Time (1650),
avp_code_PCC_3GPP_Packet_Filter_Information (1061),
+ avp_code_AAA_3GPP_Daylight_Saving_Time (1650),
+ avp_code_DCA_3GPP_Address_Domain (898),
avp_code_S6_3GPP_SCEF_ID (3125),
+ avp_code_DCA_3GPP_Content_Length (827),
avp_code_PCC_3GPP_Removal_Of_Access (2842),
- avp_code_AAA_3GPP_Preferred_Data_Mode (1686),
avp_code_PCC_3GPP_ADC_Rule_Report (1097),
- avp_code_AAA_3GPP_UE_SRVCC_Capability (1615),
+ avp_code_AAA_3GPP_Preferred_Data_Mode (1686),
+ avp_code_DCA_3GPP_ProSe_Functionality (3445),
+ avp_code_DCA_3GPP_Low_Balance_Indication (2020),
avp_code_PCC_3GPP_Guaranteed_Bitrate_UL (1026),
+ avp_code_AAA_3GPP_UE_SRVCC_Capability (1615),
avp_code_CxDx_3GPP_To_SIP_Header (645),
avp_code_AAA_3GPP_Coupled_Node_Diameter_ID (1666),
+ avp_code_DCA_3GPP_Real_Time_Tariff_Information (2305),
avp_code_AAA_3GPP_STN_SR (1433),
+ avp_code_DCA_3GPP_SDP_Type (2036),
avp_code_AAA_3GPP_ServiceTypeIdentity (1484),
+ avp_code_DCA_3GPP_Requested_Party_Address (1251),
+ avp_code_DCA_3GPP_Announcement_Information (3904),
avp_code_AAA_3GPP_AUTN (1449),
+ avp_code_AAA_3GPP_Non_3GPP_User_Data (1500),
+ avp_code_DCA_3GPP_Delivery_Report_Requested (1216),
avp_code_GI_3GPP_TWAN_Identifier (29),
+ avp_code_AAA_3GPP_Origination_Time_Stamp (1536),
+ avp_code_DCA_3GPP_LCS_APN (1231),
+ avp_code_DCA_3GPP_Envelope_End_Time (1267),
avp_code_RX_3GPP_Sponsored_Connectivity_Data (530),
+ avp_code_DCA_3GPP_Application_Server_Information (850),
+ avp_code_DCA_3GPP_Originator_Address (886),
+ avp_code_DCA_3GPP_Network_Call_Reference_Number (3418),
avp_code_S6_3GPP_AESE_Communication_Pattern (3113),
avp_code_PCC_3GPP_NBIFOM_Mode (2830),
avp_code_PCC_3GPP_Redirect_Information (1085),
+ avp_code_DCA_3GPP_Monitoring_UE_VPLMN_Identifier (3433),
avp_code_S6_3GPP_Event_Handling (3149),
- avp_code_AAA_3GPP_Tracking_Area_Identity (1603),
avp_code_PCC_3GPP_ToS_Traffic_Class (1014),
+ avp_code_AAA_3GPP_Tracking_Area_Identity (1603),
avp_code_RX_3GPP_Min_Desired_Bandwidth_UL (546),
avp_code_AAA_3GPP_UVR_Flags (1639),
+ avp_code_DCA_3GPP_PS_Free_Format_Data (866),
avp_code_CxDx_3GPP_Originating_Request (633),
- avp_code_AAA_3GPP_Subscription_Data_Flags (1654),
avp_code_PCC_3GPP_PDN_Connection_ID (1065),
- avp_code_AAA_3GPP_DSR_Flags (1421),
+ avp_code_AAA_3GPP_Subscription_Data_Flags (1654),
avp_code_PCC_3GPP_PRA_Remove (2846),
+ avp_code_AAA_3GPP_DSR_Flags (1421),
+ avp_code_DCA_3GPP_Number_Portability_Routing_Information (2024),
avp_code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer (1619),
avp_code_AAA_3GPP_Specific_APN_Info (1472),
avp_code_AAA_3GPP_Terminal_Information (1401),
avp_code_CxDx_3GPP_Restoration_Info (649),
+ avp_code_DCA_3GPP_Account_Expiration (2309),
avp_code_AAA_3GPP_CSG_Id (1437),
avp_code_GI_3GPP_3GPP_IPv6_DNS_Servers (17),
+ avp_code_AAA_3GPP_SSID (1524),
avp_code_AAA_3GPP_Call_Barring_Info (1488),
+ avp_code_DCA_3GPP_BSSID (2716),
+ avp_code_DCA_3GPP_Talk_Burst_Exchange (1255),
+ avp_code_DCA_3GPP_Variable_Part_Order (3908),
+ avp_code_DCA_3GPP_Time_Quota_Mechanism (1270),
+ avp_code_AAA_3GPP_ANID (1504),
+ avp_code_DCA_3GPP_Monitoring_Event_Report_Number (3923),
avp_code_S6_3GPP_IP_SM_GW_Name (3101),
avp_code_RX_3GPP_Media_Sub_Component (519),
+ avp_code_DCA_3GPP_CN_Operator_Selection_Entity (3421),
avp_code_S6_3GPP_Accuracy (3137),
avp_code_PCC_3GPP_Charging_Rule_Remove (1002),
+ avp_code_DCA_3GPP_Originating_IOI (839),
avp_code_RX_3GPP_Min_Requested_Bandwidth_DL (534),
+ avp_code_DCA_3GPP_ProSe_Function_PLMN_Identifier (3457),
avp_code_S6_3GPP_Service_Report (3152),
avp_code_PCC_3GPP_Tunnel_Information (1038),
+ avp_code_DCA_3GPP_Bearer_Service (854),
avp_code_CxDx_3GPP_Primary_Charging_Collection_Function_Name (621),
- avp_code_AAA_3GPP_Time_Zone (1642),
avp_code_PCC_3GPP_QoS_Rule_Definition (1053),
+ avp_code_AAA_3GPP_Time_Zone (1642),
avp_code_S6_3GPP_Periodic_Time (3117),
avp_code_PCC_3GPP_Routing_Rule_Failure_Code (2834),
avp_code_PCC_3GPP_TDF_Destination_Host (1089),
avp_code_AAA_3GPP_Local_Group_Id (1678),
- avp_code_AAA_3GPP_Service_Area_Identity (1607),
+ avp_code_DCA_3GPP_SM_Discharge_Time (2012),
+ avp_code_DCA_3GPP_Requestor_PLMN_Identifier (3437),
+ avp_code_DCA_3GPP_IMS_Application_Reference_Identifier (2601),
avp_code_PCC_3GPP_Charging_Rule_Report (1018),
+ avp_code_AAA_3GPP_Service_Area_Identity (1607),
avp_code_AAA_3GPP_UE_PC5_AMBR (1693),
avp_code_CxDx_3GPP_Public_Identity (601),
+ avp_code_DCA_3GPP_Local_Sequence_Number (2063),
avp_code_CxDx_3GPP_UAR_Flags (637),
avp_code_AAA_3GPP_Collection_Period_RRM_UMTS (1658),
avp_code_AAA_3GPP_Operator_Determined_Barring (1425),
+ avp_code_DCA_3GPP_Recipient_Received_Address (2028),
avp_code_GI_3GPP_3GPP_IMEISV (20),
avp_code_AAA_3GPP_SS_Code (1476),
+ avp_code_DCA_3GPP_DCD_Information (2115),
+ avp_code_DCA_3GPP_Location_Estimate_Type (1243),
+ avp_code_DCA_3GPP_Time_Indicator (3911),
+ avp_code_DCA_3GPP_Addressee_Type (1208),
+ avp_code_AAA_3GPP_TWAN_Connectivity_Parameters (1528),
+ avp_code_DCA_3GPP_Reply_Applic_ID (1223),
+ avp_code_DCA_3GPP_Participant_Access_Priority (1259),
avp_code_RX_3GPP_RS_Bandwidth (522),
avp_code_S6_3GPP_Reachability_Information (3140),
+ avp_code_DCA_3GPP_SDP_Session_Description (842),
avp_code_RX_3GPP_Extended_Min_Desired_BW_DL (558),
- avp_code_AAA_3GPP_Event_Threshold_RSRQ (1630),
+ avp_code_DCA_3GPP_Location_Info (3460),
avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL (1041),
+ avp_code_AAA_3GPP_Event_Threshold_RSRQ (1630),
+ avp_code_DCA_3GPP_LCS_Information (878),
avp_code_S6_3GPP_Service_Parameters (3105),
avp_code_PCC_3GPP_Presence_Reporting_Area_Information (2822),
avp_code_PCC_3GPP_Routing_Rule_Identifier (1077),
+ avp_code_DCA_3GPP_SMS_Information (2000),
+ avp_code_DCA_3GPP_ePDG_Address (3425),
avp_code_PCC_3GPP_Event_Trigger (1006),
avp_code_RX_3GPP_GCS_Identifier (538),
- avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator (1681),
avp_code_PCC_3GPP_ADC_Rule_Install (1092),
+ avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator (1681),
+ avp_code_DCA_3GPP_Outgoing_Session_Id (2320),
+ avp_code_DCA_3GPP_PoC_Controlling_Address (858),
+ avp_code_DCA_3GPP_Dynamic_Address_Flag (2051),
avp_code_CxDx_3GPP_Confidentiality_Key (625),
avp_code_PCC_3GPP_Flow_Label (1057),
avp_code_AAA_3GPP_Authentication_Info (1413),
+ avp_code_DCA_3GPP_Transcoder_Inserted_Indication (2605),
+ avp_code_DCA_3GPP_SMS_Node (2016),
avp_code_AAA_3GPP_Trace_Interface_List (1464),
+ avp_code_DCA_3GPP_SGW_Address (2067),
avp_code_GI_3GPP_3GPP_Charging_Id (2),
avp_code_AAA_3GPP_APN_Configuration_Profile (1429),
+ avp_code_DCA_3GPP_Number_Of_Received_Talk_Bursts (1282),
+ avp_code_AAA_3GPP_Full_Network_Name (1516),
+ avp_code_DCA_3GPP_Message_Type (1211),
+ avp_code_DCA_3GPP_APN_Rate_Control_Uplink (3935),
avp_code_GI_3GPP_3GPP_CAMEL_Charging_Info (24),
+ avp_code_DCA_3GPP_From_Address (2708),
+ avp_code_AAA_3GPP_TWAG_CP_Address (1531),
+ avp_code_DCA_3GPP_PDP_Context_Type (1247),
avp_code_RX_3GPP_Flows (510),
+ avp_code_DCA_3GPP_User_Session_Id (830),
+ avp_code_DCA_3GPP_PoC_Change_Time (1262),
+ avp_code_DCA_3GPP_Privacy_Indicator (3915),
avp_code_S6_3GPP_CIA_Flags (3164),
avp_code_RX_3GPP_Extended_Min_Requested_BW_UL (561),
avp_code_PCC_3GPP_Monitoring_Time (2810),
+ avp_code_DCA_3GPP_Teleservice (3413),
+ avp_code_DCA_3GPP_Quota_Consumption_Time (881),
avp_code_S6_3GPP_UE_Reachability_Configuration (3129),
avp_code_RX_3GPP_Acceptable_Service_Info (526),
avp_code_PCC_3GPP_Flow_Direction (1080),
+ avp_code_DCA_3GPP_ProSe_Reason_For_Cancellation (3449),
avp_code_S6_3GPP_Supported_Monitoring_Events (3144),
+ avp_code_DCA_3GPP_CG_Address (846),
+ avp_code_DCA_3GPP_Radio_Parameter_Set_Values (3464),
avp_code_CxDx_3GPP_SIP_Item_Number (613),
avp_code_PCC_3GPP_Session_Release_Cause (1045),
avp_code_AAA_3GPP_MDT_User_Consent (1634),
avp_code_S6_3GPP_HSS_Cause (3109),
avp_code_PCC_3GPP_PCSCF_Restoration_Indication (2826),
+ avp_code_DCA_3GPP_Layer_2_Group_ID (3429),
+ avp_code_DCA_3GPP_Interface_Port (2004),
avp_code_AAA_3GPP_Subscription_Data_Deletion (1685),
avp_code_AAA_3GPP_Trace_Collection_Entity (1452),
+ avp_code_DCA_3GPP_AoC_Request_Type (2055),
avp_code_CxDx_3GPP_Feature_List_ID (629),
avp_code_AAA_3GPP_Network_Access_Mode (1417),
avp_code_GI_3GPP_3GPP_Selection_Mode (12),
avp_code_AAA_3GPP_Complete_Data_List_Included_Indicator (1468),
+ avp_code_DCA_3GPP_LCS_Client_Name (1235),
avp_code_GI_3GPP_3GPP_SGSN_Address (6),
+ avp_code_DCA_3GPP_Related_IMS_Charging_Identifier (2711),
+ avp_code_DCA_3GPP_Called_Asserted_Identity (1250),
+ avp_code_DCA_3GPP_TWAG_Address (3903),
+ avp_code_DCA_3GPP_Talk_Burst_Time (1286),
+ avp_code_DCA_3GPP_Token_Text (1215),
+ avp_code_DCA_3GPP_Rate_Control_Time_Unit (3939),
avp_code_GI_3GPP_External_Identifier (28),
+ avp_code_DCA_3GPP_Reason_Header (3401),
+ avp_code_AAA_3GPP_WLCP_Key (1535),
avp_code_S6_3GPP_Reachability_Type (3132),
+ avp_code_DCA_3GPP_SIP_Request_Timestamp (834),
+ avp_code_DCA_3GPP_ProSe_Source_IP_Address (3452),
avp_code_S6_3GPP_Type_Of_External_Identifier (3168),
avp_code_PCC_3GPP_Event_Report_Indication (1033),
avp_code_AAA_3GPP_MDT_Configuration (1622),
avp_code_PCC_3GPP_Usage_Monitoring_Report (1069),
+ avp_code_DCA_3GPP_Number_Of_Participants (885),
+ avp_code_DCA_3GPP_MSC_Address (3417),
avp_code_CxDx_3GPP_Priviledged_Sender_Indication (652),
avp_code_AAA_3GPP_Adjacent_Access_Restriction_Data (1673),
+ avp_code_DCA_3GPP_AoC_Service_Obligatory_Type (2312),
avp_code_AAA_3GPP_RAT_Frequency_Selection_Priority_ID (1440),
+ avp_code_DCA_3GPP_Time_First_Usage (2043),
avp_code_CxDx_3GPP_Reason_Info (617),
- avp_code_AAA_3GPP_CLR_Flags (1638),
avp_code_PCC_3GPP_Default_EPS_Bearer_QoS (1049),
+ avp_code_AAA_3GPP_CLR_Flags (1638),
avp_code_AAA_3GPP_ULR_Flags (1405),
+ avp_code_DCA_3GPP_Originating_SCCP_Address (2008),
avp_code_AAA_3GPP_ICS_Indicator (1491),
avp_code_AAA_3GPP_Cancellation_Type (1420),
avp_code_AAA_3GPP_PDN_Type (1456),
+ avp_code_DCA_3GPP_Scale_Factor (2059),
+ avp_code_DCA_3GPP_IM_Information (2110),
+ avp_code_DCA_3GPP_SDP_Offer_Timestamp (1274),
+ avp_code_AAA_3GPP_PPR_Flags (1508),
+ avp_code_DCA_3GPP_MM_Content_Type (1203),
+ avp_code_DCA_3GPP_CPDT_Information (3927),
avp_code_GI_3GPP_3GPP_GGSN_IPv6_Address (16),
+ avp_code_AAA_3GPP_DER_S6b_Flags (1523),
+ avp_code_DCA_3GPP_SCS_Realm (3942),
+ avp_code_DCA_3GPP_LCS_Requestor_Id (1239),
avp_code_RX_3GPP_Access_Network_Charging_Identifier (502),
avp_code_S6_3GPP_AESE_Communication_Pattern_Config_Status (3120),
+ avp_code_DCA_3GPP_PoC_User_Role_info_Units (1254),
+ avp_code_DCA_3GPP_Variable_Part (3907),
+ avp_code_DCA_3GPP_ProSe_3rd_Party_Application_ID (3440),
avp_code_S6_3GPP_Enhanced_Coverage_Restriction_Data (3156),
avp_code_PCC_3GPP_Bearer_Operation (1021),
avp_code_AAA_3GPP_Current_Location_Retrieved (1610),
avp_code_RX_3GPP_Pre_emption_Control_Info (553),
avp_code_PCC_3GPP_TDF_Application_Instance_Identifier (2802),
+ avp_code_DCA_3GPP_SM_Device_Trigger_Information (3405),
+ avp_code_DCA_3GPP_Service_Information (873),
avp_code_RX_3GPP_Media_Component_Number (518),
avp_code_CxDx_3GPP_Path (640),
- avp_code_AAA_3GPP_Event_Threshold_Event_1F (1661),
avp_code_PCC_3GPP_Packet_Filter_Usage (1072),
+ avp_code_AAA_3GPP_Event_Threshold_Event_1F (1661),
avp_code_S6_3GPP_MONTE_Location_Type (3136),
+ avp_code_DCA_3GPP_Inter_Operator_Identifier (838),
avp_code_AAA_3GPP_RDS_Indicator (1697),
+ avp_code_DCA_3GPP_Proximity_Cancellation_Timestamp (3456),
+ avp_code_DCA_3GPP_MMTel_SService_Type (2031),
avp_code_CxDx_3GPP_Optional_Capability (605),
- avp_code_AAA_3GPP_Reporting_Trigger (1626),
avp_code_PCC_3GPP_Tunnel_Header_Length (1037),
+ avp_code_AAA_3GPP_Reporting_Trigger (1626),
avp_code_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate (2818),
avp_code_CxDx_3GPP_Secondary_Event_Charging_Function_Name (620),
avp_code_AAA_3GPP_Group_PLMN_Id (1677),
+ avp_code_DCA_3GPP_Reply_Path_Requested (2011),
avp_code_AAA_3GPP_User_Id (1444),
+ avp_code_DCA_3GPP_Serving_Node_Type (2047),
avp_code_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info (1409),
avp_code_AAA_3GPP_EPS_User_State (1495),
+ avp_code_AAA_3GPP_Access_Authorization_Flags (1511),
+ avp_code_DCA_3GPP_PDP_Address (1227),
+ avp_code_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator (3930),
+ avp_code_DCA_3GPP_NNI_Information (2703),
+ avp_code_DCA_3GPP_Location_Estimate (1242),
+ avp_code_DCA_3GPP_Offline_Charging (1278),
avp_code_RX_3GPP_Retry_Interval (541),
+ avp_code_DCA_3GPP_Additional_Content_Information (1207),
+ avp_code_DCA_3GPP_Cause_Code (861),
+ avp_code_AAA_3GPP_TWAN_Connection_Mode (1527),
avp_code_PCC_3GPP_Packet_Filter_Identifier (1060),
+ avp_code_DCA_3GPP_Address_Data (897),
avp_code_S6_3GPP_SCEF_Reference_ID (3124),
+ avp_code_DCA_3GPP_Content_Type (826),
avp_code_PCC_3GPP_Resource_Release_Notification (2841),
avp_code_PCC_3GPP_ADC_Rule_Name (1096),
- avp_code_AAA_3GPP_Error_Diagnostic (1614),
+ avp_code_DCA_3GPP_ProSe_Function_IP_Address (3444),
avp_code_PCC_3GPP_Guaranteed_Bitrate_DL (1025),
+ avp_code_AAA_3GPP_Error_Diagnostic (1614),
avp_code_RX_3GPP_Extended_Max_Supported_BW_UL (557),
avp_code_PCC_3GPP_UDP_Source_Port (2806),
+ avp_code_DCA_3GPP_SMS_Result (3409),
+ avp_code_DCA_3GPP_MMS_Information (877),
avp_code_CxDx_3GPP_From_SIP_Header (644),
- avp_code_AAA_3GPP_SIPTO_Local_Network_Permission (1665),
avp_code_PCC_3GPP_Routing_Rule_Definition (1076),
+ avp_code_AAA_3GPP_SIPTO_Local_Network_Permission (1665),
+ avp_code_DCA_3GPP_CUG_Information (2304),
avp_code_AAA_3GPP_VPLMN_Dynamic_Address_Allowed (1432),
+ avp_code_DCA_3GPP_Associated_Party_Address (2035),
avp_code_CxDx_3GPP_SIP_Authenticate (609),
avp_code_AAA_3GPP_Service_Type (1483),
avp_code_AAA_3GPP_Immediate_Response_Preferred (1412),
+ avp_code_DCA_3GPP_Local_GW_Inserted_Indication (2604),
avp_code_AAA_3GPP_XRES (1448),
+ avp_code_DCA_3GPP_Deferred_Location_Event_Type (1230),
avp_code_GI_3GPP_3GPP_IMSI (1),
avp_code_AAA_3GPP_User_State (1499),
+ avp_code_DCA_3GPP_Envelope (1266),
+ avp_code_DCA_3GPP_Monitoring_Event_Configuration_Activity (3919),
+ avp_code_DCA_3GPP_IMS_Communication_Service_Identifier (1281),
+ avp_code_AAA_3GPP_Trust_Relationship_Update (1515),
+ avp_code_DCA_3GPP_APN_Rate_Control_Downlink (3934),
+ avp_code_DCA_3GPP_Session_Direction (2707),
avp_code_S6_3GPP_IP_SM_GW_Realm (3112),
+ avp_code_DCA_3GPP_Monitoring_UE_Identifier (3432),
avp_code_S6_3GPP_Reference_ID_Validity_Time (3148),
- avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity (1602),
avp_code_PCC_3GPP_TFT_Packet_Filter_Information (1013),
+ avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity (1602),
avp_code_RX_3GPP_Min_Desired_Bandwidth_DL (545),
+ avp_code_DCA_3GPP_Transmitter_Info (3468),
avp_code_S6_3GPP_Group_Reporting_Guard_Timer (3163),
+ avp_code_DCA_3GPP_PS_Furnish_Charging_Information (865),
avp_code_CxDx_3GPP_Associated_Identities (632),
avp_code_PCC_3GPP_Session_Linking_Indicator (1064),
avp_code_S6_3GPP_Maximum_Number_of_Reports (3128),
avp_code_PCC_3GPP_PRA_Install (2845),
avp_code_AAA_3GPP_V2X_Permission (1689),
- avp_code_AAA_3GPP_LIPA_Permission (1618),
+ avp_code_DCA_3GPP_ProSe_Range_Class (3448),
+ avp_code_DCA_3GPP_Carrier_Select_Routing_Information (2023),
avp_code_PCC_3GPP_QoS_Negotiation (1029),
+ avp_code_AAA_3GPP_LIPA_Permission (1618),
avp_code_CxDx_3GPP_SIP_Auth_Data_Item (612),
avp_code_AAA_3GPP_3GPP2_MEID (1471),
avp_code_AAA_3GPP_Subscription_Data (1400),
avp_code_CxDx_3GPP_Multiple_Registration_Indication (648),
avp_code_AAA_3GPP_WLAN_offloadability_UTRAN (1669),
+ avp_code_DCA_3GPP_IMSI_Unauthenticated_Flag (2308),
+ avp_code_DCA_3GPP_Interface_Id (2003),
avp_code_AAA_3GPP_CSG_Subscription_Data (1436),
+ avp_code_DCA_3GPP_Diagnostics (2039),
avp_code_AAA_3GPP_TS_Code (1487),
+ avp_code_AAA_3GPP_AN_Trusted (1503),
+ avp_code_DCA_3GPP_Monitoring_Event_Funtionality (3922),
+ avp_code_DCA_3GPP_Aux_Applic_Info (1219),
avp_code_S6_3GPP_IP_SM_GW_Number (3100),
+ avp_code_AAA_3GPP_AAR_Flags (1539),
+ avp_code_DCA_3GPP_LCS_Client_External_ID (1234),
+ avp_code_DCA_3GPP_VLR_Number (3420),
avp_code_PCC_3GPP_Charging_Rule_Install (1001),
avp_code_RX_3GPP_Rx_Request_Type (533),
avp_code_S6_3GPP_NIDD_Authorization_Response (3151),
- avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data (1641),
+ avp_code_DCA_3GPP_Outgoing_Trunk_Group_Id (853),
+ avp_code_AAA_3GPP_Transport_Access_Type (1519),
avp_code_PCC_3GPP_QoS_Rule_Remove (1052),
+ avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data (1641),
+ avp_code_DCA_3GPP_Message_Body (889),
avp_code_S6_3GPP_Communication_Duration_Time (3116),
avp_code_PCC_3GPP_Access_Availability_Change_Reason (2833),
avp_code_PCC_3GPP_TDF_Application_Identifier (1088),
+ avp_code_DCA_3GPP_Requested_PLMN_Identifier (3436),
avp_code_AAA_3GPP_Location_Area_Identity (1606),
avp_code_RX_3GPP_Media_Component_Status (549),
avp_code_AAA_3GPP_eDRX_Cycle_Length_Value (1692),
avp_code_CxDx_3GPP_Visited_Network_Identifier (600),
avp_code_S6_3GPP_RIR_Flags (3167),
- avp_code_AAA_3GPP_Collection_Period_RRM_LTE (1657),
+ avp_code_DCA_3GPP_Volume_Quota_Threshold (869),
+ avp_code_DCA_3GPP_Incremental_Cost (2062),
avp_code_PCC_3GPP_Usage_Monitoring_Level (1068),
- avp_code_AAA_3GPP_Subscriber_Status (1424),
+ avp_code_AAA_3GPP_Collection_Period_RRM_LTE (1657),
avp_code_PCC_3GPP_Extended_APN_AMBR_UL (2849),
+ avp_code_AAA_3GPP_Subscriber_Status (1424),
avp_code_CxDx_3GPP_Identity_with_Emergency_Registration (651),
+ avp_code_DCA_3GPP_Originator_Received_Address (2027),
+ avp_code_DCA_3GPP_AoC_Service (2311),
avp_code_AAA_3GPP_LCS_PrivacyException (1475),
avp_code_AAA_3GPP_QoS_Subscribed (1404),
+ avp_code_DCA_3GPP_Variable_Part_Value (3910),
+ avp_code_DCA_3GPP_Read_Reply_Report_Requested (1222),
+ avp_code_DCA_3GPP_Event_Charging_TimeStamp (1258),
avp_code_RX_3GPP_RR_Bandwidth (521),
+ avp_code_DCA_3GPP_SDP_TimeStamps (1273),
+ avp_code_DCA_3GPP_IMS_Charging_Identifier (841),
+ avp_code_AAA_3GPP_MIP_FA_RK_SPI (1507),
+ avp_code_DCA_3GPP_Related_Trigger (3926),
avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL (1040),
avp_code_S6_3GPP_SCS_Identity (3104),
+ avp_code_DCA_3GPP_LCS_Name_String (1238),
avp_code_RX_3GPP_Access_Network_Charging_Address (501),
avp_code_PCC_3GPP_Presence_Reporting_Area_Identifier (2821),
+ avp_code_DCA_3GPP_ISUP_Cause_Value (3424),
avp_code_PCC_3GPP_Charging_Rule_Name (1005),
avp_code_RX_3GPP_Ip_Domain_Id (537),
- avp_code_AAA_3GPP_UE_Usage_Type (1680),
avp_code_PCC_3GPP_TDF_IP_Address (1091),
+ avp_code_AAA_3GPP_UE_Usage_Type (1680),
avp_code_S6_3GPP_Enhanced_Coverage_Restriction (3155),
+ avp_code_DCA_3GPP_Charged_Party (857),
+ avp_code_DCA_3GPP_PDN_Connection_Charging_ID (2050),
avp_code_CxDx_3GPP_User_Data_Already_Available (624),
- avp_code_AAA_3GPP_MME_Number_for_MT_SMS (1645),
avp_code_PCC_3GPP_Security_Parameter_Index (1056),
+ avp_code_AAA_3GPP_MME_Number_for_MT_SMS (1645),
avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL (2837),
+ avp_code_DCA_3GPP_SM_User_Data_Header (2015),
avp_code_AAA_3GPP_Carrier_Frequency (1696),
+ avp_code_DCA_3GPP_MMTel_Information (2030),
avp_code_CxDx_3GPP_Mandatory_Capability (604),
avp_code_AAA_3GPP_Trace_NE_Type_List (1463),
+ avp_code_DCA_3GPP_Charging_Characteristics_Selection_Mode (2066),
avp_code_AAA_3GPP_All_APN_Configurations_Included_Indicator (1428),
avp_code_AAA_3GPP_NOR_Flags (1443),
+ avp_code_DCA_3GPP_Message_ID (1210),
avp_code_GI_3GPP_3GPP_MS_TimeZone (23),
avp_code_AAA_3GPP_External_Client (1479),
+ avp_code_DCA_3GPP_Charge_Reason_Code (2118),
+ avp_code_AAA_3GPP_TWAN_PCO (1530),
+ avp_code_DCA_3GPP_PoC_Change_Conditions (1261),
+ avp_code_DCA_3GPP_Language (3914),
avp_code_RX_3GPP_Extended_Min_Requested_BW_DL (560),
+ avp_code_DCA_3GPP_Unit_Quota_Threshold (1226),
+ avp_code_DCA_3GPP_MBMS_Information (880),
+ avp_code_DCA_3GPP_Bearer_Capability (3412),
avp_code_RX_3GPP_Service_URN (525),
avp_code_S6_3GPP_Supported_Services (3143),
- avp_code_AAA_3GPP_Relay_Node_Indicator (1633),
+ avp_code_DCA_3GPP_SDP_Media_Description (845),
+ avp_code_DCA_3GPP_Radio_Parameter_Set_Info (3463),
avp_code_PCC_3GPP_Rule_DeActivation_Time (1044),
+ avp_code_AAA_3GPP_Relay_Node_Indicator (1633),
avp_code_S6_3GPP_T4_Data (3108),
avp_code_PCC_3GPP_Fixed_User_Location_Info (2825),
+ avp_code_DCA_3GPP_Coverage_Status (3428),
avp_code_PCC_3GPP_Online (1009),
avp_code_PCC_3GPP_ADC_Rule_Base_Name (1095),
avp_code_AAA_3GPP_SCEF_Realm (1684),
+ avp_code_DCA_3GPP_MBMS_Charged_Party (2323),
avp_code_S6_3GPP_Requested_Validity_Time (3159),
+ avp_code_DCA_3GPP_AoC_Information (2054),
avp_code_CxDx_3GPP_Supported_Features (628),
avp_code_AAA_3GPP_Local_Time_Zone (1649),
avp_code_AAA_3GPP_GERAN_Vector (1416),
avp_code_CxDx_3GPP_Call_ID_SIP_Header (643),
+ avp_code_DCA_3GPP_Online_Charging_Flag (2303),
+ avp_code_DCA_3GPP_Number_of_Messages_Sent (2019),
avp_code_AAA_3GPP_EPS_Subscribed_QoS_Profile (1431),
avp_code_GI_3GPP_3GPP_Session_Stop_Indicator (11),
avp_code_AAA_3GPP_GPRS_Subscription_Data (1467),
avp_code_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile (5),
+ avp_code_DCA_3GPP_Access_Transfer_Type (2710),
+ avp_code_DCA_3GPP_Inter_UE_Transfer (3902),
+ avp_code_DCA_3GPP_Received_Talk_Burst_Volume (1285),
+ avp_code_DCA_3GPP_Rate_Control_Max_Rate (3938),
+ avp_code_DCA_3GPP_Class_Identifier (1214),
avp_code_GI_3GPP_3GPP_Allocate_IP_Type (27),
+ avp_code_AAA_3GPP_SM_Back_Off_Timer (1534),
avp_code_RX_3GPP_Specific_Action (513),
avp_code_S6_3GPP_Maximum_Detection_Time (3131),
- avp_code_AAA_3GPP_Ext_PDP_Address (1621),
+ avp_code_DCA_3GPP_Time_Stamps (833),
+ avp_code_DCA_3GPP_Base_Time_Interval (1265),
+ avp_code_DCA_3GPP_UWAN_User_Location_Info (3918),
+ avp_code_DCA_3GPP_ProSe_Role_Of_UE (3451),
avp_code_PCC_3GPP_RAT_Type (1032),
+ avp_code_AAA_3GPP_Ext_PDP_Address (1621),
+ avp_code_DCA_3GPP_PoC_Session_Type (884),
+ avp_code_DCA_3GPP_ISUP_Cause (3416),
avp_code_RX_3GPP_AF_Signalling_Protocol (529),
avp_code_AAA_3GPP_Adjacent_PLMNs (1672),
avp_code_S6_3GPP_Service_Result_Code (3147),
avp_code_AAA_3GPP_SGSN_Location_Information (1601),
+ avp_code_DCA_3GPP_Authorised_QoS (849),
+ avp_code_DCA_3GPP_Time_First_Transmission (3467),
+ avp_code_DCA_3GPP_Stop_Time (2042),
avp_code_CxDx_3GPP_Reason_Code (616),
avp_code_PCC_3GPP_Pre_emption_Vulnerability (1048),
avp_code_AAA_3GPP_Equivalent_PLMN_List (1637),
avp_code_PCC_3GPP_Default_Access (2829),
avp_code_CxDx_3GPP_Supported_Applications (631),
+ avp_code_DCA_3GPP_SM_Message_Type (2007),
avp_code_AAA_3GPP_IDR_Flags (1490),
- avp_code_AAA_3GPP_V2X_Subscription_Data (1688),
avp_code_PCC_3GPP_PS_to_CS_Session_Continuity (1099),
+ avp_code_AAA_3GPP_V2X_Subscription_Data (1688),
+ avp_code_DCA_3GPP_Refund_Information (2022),
+ avp_code_DCA_3GPP_Rate_Element (2058),
avp_code_AAA_3GPP_PDP_Type (1470),
- avp_code_AAA_3GPP_AMBR (1435)
+ avp_code_AAA_3GPP_AMBR (1435),
+ avp_code_DCA_3GPP_Submission_Time (1202)
} with {
variant "FIELDLENGTH(32)"
variant "BYTEORDER(last)"
@@ -6359,744 +10033,1191 @@ type record AVP_Header {
type union AVP_Data {
GI_3GPP_3GPP_SGSN_IPv6_Address avp_GI_3GPP_3GPP_SGSN_IPv6_Address,
DNAS_NONE_Login_LAT_Service avp_DNAS_NONE_Login_LAT_Service,
+ AAA_3GPP_RAR_Flags avp_AAA_3GPP_RAR_Flags,
+ DCA_3GPP_SCS_Address avp_DCA_3GPP_SCS_Address,
GI_3GPP_3GPP_GGSN_MCC_MNC avp_GI_3GPP_3GPP_GGSN_MCC_MNC,
DCC_NONE_Direct_Debiting_Failure_Handling avp_DCC_NONE_Direct_Debiting_Failure_Handling,
MIPv6_NONE_MIP_Careof_Address avp_MIPv6_NONE_MIP_Careof_Address,
+ DCA_3GPP_TWAN_User_Location_Info avp_DCA_3GPP_TWAN_User_Location_Info,
+ DCA_3GPP_PoC_User_Role_IDs avp_DCA_3GPP_PoC_User_Role_IDs,
+ DCA_3GPP_Announcement_Order avp_DCA_3GPP_Announcement_Order,
CxDx_ETSI_Line_Identifier avp_CxDx_ETSI_Line_Identifier,
PCC_3GPP_Bearer_Identifier avp_PCC_3GPP_Bearer_Identifier,
RX_3GPP_Content_Version avp_RX_3GPP_Content_Version,
+ DCA_3GPP_Applic_ID avp_DCA_3GPP_Applic_ID,
+ MIPv4_NONE_MIP_HA_to_FA_MSA avp_MIPv4_NONE_MIP_HA_to_FA_MSA,
BASE_NONE_Session_Id avp_BASE_NONE_Session_Id,
+ DCA_3GPP_Route_Header_Transmitted avp_DCA_3GPP_Route_Header_Transmitted,
+ DCA_3GPP_Reporting_Reason avp_DCA_3GPP_Reporting_Reason,
+ AAA_3GPP_Emergency_Services avp_AAA_3GPP_Emergency_Services,
RX_3GPP_Media_Component_Description avp_RX_3GPP_Media_Component_Description,
PCC_3GPP_CSG_Information_Reporting avp_PCC_3GPP_CSG_Information_Reporting,
AAA_3GPP_Measurement_Quantity avp_AAA_3GPP_Measurement_Quantity,
S6_3GPP_Location_Information_Configuration avp_S6_3GPP_Location_Information_Configuration,
PCC_3GPP_Bearer_Usage avp_PCC_3GPP_Bearer_Usage,
+ DCA_3GPP_Application_provided_Called_Party_Address avp_DCA_3GPP_Application_provided_Called_Party_Address,
+ DCA_3GPP_Proximity_Alert_Timestamp avp_DCA_3GPP_Proximity_Alert_Timestamp,
PCC_3GPP_Tunnel_Header_Filter avp_PCC_3GPP_Tunnel_Header_Filter,
AAA_3GPP_List_Of_Measurements avp_AAA_3GPP_List_Of_Measurements,
DCC_NONE_Requested_Service_Unit avp_DCC_NONE_Requested_Service_Unit,
PCC_3GPP_Default_QoS_Name avp_PCC_3GPP_Default_QoS_Name,
AAA_3GPP_UVA_Flags avp_AAA_3GPP_UVA_Flags,
+ DCA_3GPP_Expires avp_DCA_3GPP_Expires,
CxDx_3GPP_SAR_Flags avp_CxDx_3GPP_SAR_Flags,
- AAA_3GPP_Group_Service_Id avp_AAA_3GPP_Group_Service_Id,
PCC_3GPP_TDF_Information avp_PCC_3GPP_TDF_Information,
+ AAA_3GPP_Group_Service_Id avp_AAA_3GPP_Group_Service_Id,
+ DCA_3GPP_Recipient_SCCP_Address avp_DCA_3GPP_Recipient_SCCP_Address,
+ DCA_3GPP_Preferred_AoC_Currency avp_DCA_3GPP_Preferred_AoC_Currency,
DNAS_NONE_Framed_Pool avp_DNAS_NONE_Framed_Pool,
+ DCA_3GPP_Traffic_Data_Volumes avp_DCA_3GPP_Traffic_Data_Volumes,
DCC_NONE_CC_Time avp_DCC_NONE_CC_Time,
AAA_3GPP_Requested_EUTRAN_Authentication_Info avp_AAA_3GPP_Requested_EUTRAN_Authentication_Info,
+ DCA_3GPP_Unit_Cost avp_DCA_3GPP_Unit_Cost,
CxDx_3GPP_SIP_Digest_Authenticate avp_CxDx_3GPP_SIP_Digest_Authenticate,
AAA_3GPP_Last_UE_Activity_Time avp_AAA_3GPP_Last_UE_Activity_Time,
AAA_3GPP_Context_Identifier avp_AAA_3GPP_Context_Identifier,
DCC_NONE_Used_Service_Unit avp_DCC_NONE_Used_Service_Unit,
+ MIPv4_NONE_MIP_Reg_Reply avp_MIPv4_NONE_MIP_Reg_Reply,
BASE_NONE_Auth_Application_Id avp_BASE_NONE_Auth_Application_Id,
AAA_3GPP_Trace_Reference avp_AAA_3GPP_Trace_Reference,
+ AAA_3GPP_TWAN_Access_Info avp_AAA_3GPP_TWAN_Access_Info,
+ DCA_3GPP_Status_AS_Code avp_DCA_3GPP_Status_AS_Code,
+ DCA_3GPP_LCS_Client_Type avp_DCA_3GPP_LCS_Client_Type,
DNAS_NONE_Framed_Appletalk_Network avp_DNAS_NONE_Framed_Appletalk_Network,
DNAS_NONE_Framed_IPv6_Prefix avp_DNAS_NONE_Framed_IPv6_Prefix,
+ DCA_3GPP_PoC_Session_Initiation_Type avp_DCA_3GPP_PoC_Session_Initiation_Type,
RX_3GPP_Sharing_Key_UL avp_RX_3GPP_Sharing_Key_UL,
+ DCA_3GPP_Content_Size avp_DCA_3GPP_Content_Size,
+ AAA_3GPP_Access_Network_Info avp_AAA_3GPP_Access_Network_Info,
RX_3GPP_AF_Charging_Identifier avp_RX_3GPP_AF_Charging_Identifier,
S6_3GPP_Monitoring_Event_Report avp_S6_3GPP_Monitoring_Event_Report,
+ DCA_3GPP_Service_Specific_Type avp_DCA_3GPP_Service_Specific_Type,
+ DCA_3GPP_Event avp_DCA_3GPP_Event,
RX_3GPP_Media_Type avp_RX_3GPP_Media_Type,
PCC_3GPP_Conditional_Policy_Information avp_PCC_3GPP_Conditional_Policy_Information,
BASE_NONE_Firmware_Revision avp_BASE_NONE_Firmware_Revision,
- AAA_3GPP_SIPTO_Permission avp_AAA_3GPP_SIPTO_Permission,
+ DCA_3GPP_ProSe_Event_Type avp_DCA_3GPP_ProSe_Event_Type,
PCC_3GPP_Network_Request_Support avp_PCC_3GPP_Network_Request_Support,
+ AAA_3GPP_SIPTO_Permission avp_AAA_3GPP_SIPTO_Permission,
+ DCA_3GPP_Terminating_IOI avp_DCA_3GPP_Terminating_IOI,
RX_3GPP_Extended_Max_Supported_BW_DL avp_RX_3GPP_Extended_Max_Supported_BW_DL,
PCC_3GPP_UE_Local_IP_Address avp_PCC_3GPP_UE_Local_IP_Address,
+ DCA_3GPP_SM_Sequence_Number avp_DCA_3GPP_SM_Sequence_Number,
+ DCA_3GPP_IMS_Information avp_DCA_3GPP_IMS_Information,
PCC_3GPP_Presence_Reporting_Area_Elements_List avp_PCC_3GPP_Presence_Reporting_Area_Elements_List,
- AAA_3GPP_SGs_MME_Identity avp_AAA_3GPP_SGs_MME_Identity,
PCC_3GPP_Routing_Rule_Remove avp_PCC_3GPP_Routing_Rule_Remove,
+ AAA_3GPP_SGs_MME_Identity avp_AAA_3GPP_SGs_MME_Identity,
S6_3GPP_Roaming_Information avp_S6_3GPP_Roaming_Information,
+ DCA_3GPP_Number_Of_Diversions avp_DCA_3GPP_Number_Of_Diversions,
+ DCA_3GPP_Coverage_Info avp_DCA_3GPP_Coverage_Info,
CxDx_3GPP_SIP_Authentication_Scheme avp_CxDx_3GPP_SIP_Authentication_Scheme,
AAA_3GPP_Event_Threshold_RSRP avp_AAA_3GPP_Event_Threshold_RSRP,
CxDx_3GPP_User_Authorization_Type avp_CxDx_3GPP_User_Authorization_Type,
AAA_3GPP_PLMN_Client avp_AAA_3GPP_PLMN_Client,
AAA_3GPP_Re_Synchronization_Info avp_AAA_3GPP_Re_Synchronization_Info,
BASE_NONE_Auth_Grace_Period avp_BASE_NONE_Auth_Grace_Period,
+ DCA_3GPP_User_CSG_Information avp_DCA_3GPP_User_CSG_Information,
+ DCA_3GPP_SM_Status avp_DCA_3GPP_SM_Status,
+ DCA_3GPP_IP_Realm_Default_Indication avp_DCA_3GPP_IP_Realm_Default_Indication,
AAA_3GPP_RAND avp_AAA_3GPP_RAND,
AAA_3GPP_Trace_Depth avp_AAA_3GPP_Trace_Depth,
+ MIPv4_NONE_MIP_MN_to_FA_MSA avp_MIPv4_NONE_MIP_MN_to_FA_MSA,
AAA_3GPP_SGSN_User_State avp_AAA_3GPP_SGSN_User_State,
AAA_3GPP_APN_OI_Replacement avp_AAA_3GPP_APN_OI_Replacement,
+ DCA_3GPP_Alternate_Charged_Party_Address avp_DCA_3GPP_Alternate_Charged_Party_Address,
+ DCA_3GPP_APN_Rate_Control avp_DCA_3GPP_APN_Rate_Control,
BASE_NONE_Re_Auth_Request_Type avp_BASE_NONE_Re_Auth_Request_Type,
+ DCA_3GPP_Relationship_Mode avp_DCA_3GPP_Relationship_Mode,
S6_3GPP_External_Identifier avp_S6_3GPP_External_Identifier,
+ DCA_3GPP_Positioning_Data avp_DCA_3GPP_Positioning_Data,
DCC_NONE_Redirect_Address_Type avp_DCC_NONE_Redirect_Address_Type,
MIPv6_NONE_MIP_MN_HA_MSA avp_MIPv6_NONE_MIP_MN_HA_MSA,
+ DCA_3GPP_Monitoring_UE_HPLMN_Identifier avp_DCA_3GPP_Monitoring_UE_HPLMN_Identifier,
PCC_3GPP_TFT_Filter avp_PCC_3GPP_TFT_Filter,
RX_3GPP_Max_Supported_Bandwidth_UL avp_RX_3GPP_Max_Supported_Bandwidth_UL,
- DNAS_NONE_Tunnel_Medium_Type avp_DNAS_NONE_Tunnel_Medium_Type,
S6_3GPP_Loss_Of_Connectivity_Reason avp_S6_3GPP_Loss_Of_Connectivity_Reason,
+ DNAS_NONE_Tunnel_Medium_Type avp_DNAS_NONE_Tunnel_Medium_Type,
+ DCA_3GPP_Originator avp_DCA_3GPP_Originator,
DCC_NONE_User_Equipment_Info_Type avp_DCC_NONE_User_Equipment_Info_Type,
RX_3GPP_Flow_Number avp_RX_3GPP_Flow_Number,
+ MIPv4_NONE_MIP_Home_Agent_Address avp_MIPv4_NONE_MIP_Home_Agent_Address,
PCC_3GPP_Resource_Allocation_Notification avp_PCC_3GPP_Resource_Allocation_Notification,
+ DCA_3GPP_Basic_Service_Code avp_DCA_3GPP_Basic_Service_Code,
S6_3GPP_Monitoring_Type avp_S6_3GPP_Monitoring_Type,
+ DCA_3GPP_Role_Of_Node avp_DCA_3GPP_Role_Of_Node,
PCC_3GPP_Default_Bearer_Indication avp_PCC_3GPP_Default_Bearer_Indication,
- AAA_3GPP_VPLMN_LIPA_Allowed avp_AAA_3GPP_VPLMN_LIPA_Allowed,
+ DCA_3GPP_ProSe_Information avp_DCA_3GPP_ProSe_Information,
PCC_3GPP_QoS_Class_Identifier avp_PCC_3GPP_QoS_Class_Identifier,
+ AAA_3GPP_VPLMN_LIPA_Allowed avp_AAA_3GPP_VPLMN_LIPA_Allowed,
PCC_3GPP_Mute_Notification avp_PCC_3GPP_Mute_Notification,
CxDx_3GPP_SIP_Authentication_Context avp_CxDx_3GPP_SIP_Authentication_Context,
MIPv6_NONE_QoS_Resources avp_MIPv6_NONE_QoS_Resources,
AAA_3GPP_Logging_Duration avp_AAA_3GPP_Logging_Duration,
DCC_NONE_Service_Parameter_Value avp_DCC_NONE_Service_Parameter_Value,
CxDx_3GPP_Associated_Registered_Identities avp_CxDx_3GPP_Associated_Registered_Identities,
- AAA_3GPP_WLAN_offloadability_EUTRAN avp_AAA_3GPP_WLAN_offloadability_EUTRAN,
PCC_3GPP_Routing_IP_Address avp_PCC_3GPP_Routing_IP_Address,
- MIPv6_NONE_MIP_Session_Key avp_MIPv6_NONE_MIP_Session_Key,
+ AAA_3GPP_WLAN_offloadability_EUTRAN avp_AAA_3GPP_WLAN_offloadability_EUTRAN,
+ DCA_3GPP_MBMS_GW_Address avp_DCA_3GPP_MBMS_GW_Address,
+ DCA_3GPP_Destination_Interface avp_DCA_3GPP_Destination_Interface,
+ DCA_3GPP_IMS_Emergency_Indicator avp_DCA_3GPP_IMS_Emergency_Indicator,
+ DCA_3GPP_Change_Time avp_DCA_3GPP_Change_Time,
AAA_3GPP_KASME avp_AAA_3GPP_KASME,
+ MIPv4_NONE_MIP_Session_Key avp_MIPv4_NONE_MIP_Session_Key,
+ DCA_3GPP_AoC_Cost_Information avp_DCA_3GPP_AoC_Cost_Information,
GI_3GPP_3GPP_User_Location_Info_Time avp_GI_3GPP_3GPP_User_Location_Info_Time,
AAA_3GPP_Teleservice_List avp_AAA_3GPP_Teleservice_List,
AAA_3GPP_UTRAN_Vector avp_AAA_3GPP_UTRAN_Vector,
+ AAA_3GPP_Non_3GPP_IP_Access_APN avp_AAA_3GPP_Non_3GPP_IP_Access_APN,
+ DCA_3GPP_Monitoring_Event_Information avp_DCA_3GPP_Monitoring_Event_Information,
DCC_NONE_Tariff_Time_Change avp_DCC_NONE_Tariff_Time_Change,
GI_3GPP_3GPP_NSAPI avp_GI_3GPP_3GPP_NSAPI,
+ DCA_3GPP_LCS_Client_Dialed_By_MS avp_DCA_3GPP_LCS_Client_Dialed_By_MS,
GI_3GPP_3GPP_CG_Address avp_GI_3GPP_3GPP_CG_Address,
+ DCA_3GPP_Envelope_Start_Time avp_DCA_3GPP_Envelope_Start_Time,
RX_3GPP_Application_Service_Provider_Identity avp_RX_3GPP_Application_Service_Provider_Identity,
S6_3GPP_NIDD_Authorization_Request avp_S6_3GPP_NIDD_Authorization_Request,
+ DCA_3GPP_Received_Talk_Burst_Time avp_DCA_3GPP_Received_Talk_Burst_Time,
+ DCA_3GPP_Incoming_Trunk_Group_Id avp_DCA_3GPP_Incoming_Trunk_Group_Id,
+ AAA_3GPP_AAA_Failure_Indication avp_AAA_3GPP_AAA_Failure_Indication,
+ DCA_3GPP_Rate_Control_Max_Message_Size avp_DCA_3GPP_Rate_Control_Max_Message_Size,
PCC_3GPP_QoS_Rule_Install avp_PCC_3GPP_QoS_Rule_Install,
S6_3GPP_Periodic_Communication_Indicator avp_S6_3GPP_Periodic_Communication_Indicator,
+ DCA_3GPP_Service_Specific_Info avp_DCA_3GPP_Service_Specific_Info,
RX_3GPP_Flow_Usage avp_RX_3GPP_Flow_Usage,
PCC_3GPP_RAN_Rule_Support avp_PCC_3GPP_RAN_Rule_Support,
DNAS_NONE_Tunnel_Password avp_DNAS_NONE_Tunnel_Password,
+ DCA_3GPP_PC3_EPC_Control_Protocol_Cause avp_DCA_3GPP_PC3_EPC_Control_Protocol_Cause,
S6_3GPP_Monitoring_Duration avp_S6_3GPP_Monitoring_Duration,
- AAA_3GPP_Routing_Area_Identity avp_AAA_3GPP_Routing_Area_Identity,
PCC_3GPP_QoS_Information avp_PCC_3GPP_QoS_Information,
- DCC_NONE_User_Equipment_Info_Value avp_DCC_NONE_User_Equipment_Info_Value,
- DNAS_NONE_Tunneling avp_DNAS_NONE_Tunneling,
+ AAA_3GPP_Routing_Area_Identity avp_AAA_3GPP_Routing_Area_Identity,
+ DCA_3GPP_Called_Party_Address avp_DCA_3GPP_Called_Party_Address,
RX_3GPP_Service_Authorization_Info avp_RX_3GPP_Service_Authorization_Info,
- BASE_NONE_Multi_Round_Time_Out avp_BASE_NONE_Multi_Round_Time_Out,
+ DNAS_NONE_Tunneling avp_DNAS_NONE_Tunneling,
+ DCC_NONE_User_Equipment_Info_Value avp_DCC_NONE_User_Equipment_Info_Value,
+ MIPv4_NONE_MIP_Auth_Input_Data_Length avp_MIPv4_NONE_MIP_Auth_Input_Data_Length,
AAA_3GPP_eDRX_Cycle_Length avp_AAA_3GPP_eDRX_Cycle_Length,
+ BASE_NONE_Multi_Round_Time_Out avp_BASE_NONE_Multi_Round_Time_Out,
S6_3GPP_Group_Monitoring_Event_Report_Item avp_S6_3GPP_Group_Monitoring_Event_Report_Item,
- AAA_3GPP_Ext_PDP_Type avp_AAA_3GPP_Ext_PDP_Type,
PCC_3GPP_Rule_Failure_Code avp_PCC_3GPP_Rule_Failure_Code,
+ AAA_3GPP_Ext_PDP_Type avp_AAA_3GPP_Ext_PDP_Type,
+ DCA_3GPP_Time_Quota_Threshold avp_DCA_3GPP_Time_Quota_Threshold,
PCC_3GPP_User_Location_Info_Time avp_PCC_3GPP_User_Location_Info_Time,
- AAA_3GPP_Measurement_Period_LTE avp_AAA_3GPP_Measurement_Period_LTE,
PCC_3GPP_Usage_Monitoring_Information avp_PCC_3GPP_Usage_Monitoring_Information,
- BASE_NONE_Experimental_Result_Code avp_BASE_NONE_Experimental_Result_Code,
+ AAA_3GPP_Measurement_Period_LTE avp_AAA_3GPP_Measurement_Period_LTE,
PCC_3GPP_Extended_APN_AMBR_DL avp_PCC_3GPP_Extended_APN_AMBR_DL,
+ BASE_NONE_Experimental_Result_Code avp_BASE_NONE_Experimental_Result_Code,
CxDx_3GPP_Session_Priority avp_CxDx_3GPP_Session_Priority,
+ DCA_3GPP_Recipient_Info avp_DCA_3GPP_Recipient_Info,
+ DCA_3GPP_AoC_Format avp_DCA_3GPP_AoC_Format,
+ DCA_3GPP_Start_Time avp_DCA_3GPP_Start_Time,
CxDx_3GPP_Deregistration_Reason avp_CxDx_3GPP_Deregistration_Reason,
AAA_3GPP_GMLC_Number avp_AAA_3GPP_GMLC_Number,
- DNAS_NONE_Configuration_Token avp_DNAS_NONE_Configuration_Token,
- DNAS_NONE_Callback_Number avp_DNAS_NONE_Callback_Number,
AAA_3GPP_Software_Version avp_AAA_3GPP_Software_Version,
+ DNAS_NONE_Callback_Number avp_DNAS_NONE_Callback_Number,
+ DNAS_NONE_Configuration_Token avp_DNAS_NONE_Configuration_Token,
+ DCA_3GPP_Interface_Type avp_DCA_3GPP_Interface_Type,
+ MIPv4_NONE_MIP_Originating_Foreign_AAA avp_MIPv4_NONE_MIP_Originating_Foreign_AAA,
AAA_3GPP_Expiration_Date avp_AAA_3GPP_Expiration_Date,
BASE_NONE_Error_Message avp_BASE_NONE_Error_Message,
AAA_3GPP_SRES avp_AAA_3GPP_SRES,
- DNAS_NONE_NAS_Port_Type avp_DNAS_NONE_NAS_Port_Type,
+ DCA_3GPP_DRM_Content avp_DCA_3GPP_DRM_Content,
AAA_3GPP_Item_Number avp_AAA_3GPP_Item_Number,
+ DNAS_NONE_NAS_Port_Type avp_DNAS_NONE_NAS_Port_Type,
+ AAA_3GPP_ERP_Authorization avp_AAA_3GPP_ERP_Authorization,
DCC_NONE_Multiple_Services_Indicator avp_DCC_NONE_Multiple_Services_Indicator,
+ DCA_3GPP_Early_Media_Description avp_DCA_3GPP_Early_Media_Description,
+ AAA_3GPP_MIP_FA_RK avp_AAA_3GPP_MIP_FA_RK,
+ DCA_3GPP_Related_Change_Condition_Information avp_DCA_3GPP_Related_Change_Condition_Information,
DNAS_NONE_Framed_Protocol avp_DNAS_NONE_Framed_Protocol,
S6_3GPP_Service_ID avp_S6_3GPP_Service_ID,
+ DCA_3GPP_LCS_Format_Indicator avp_DCA_3GPP_LCS_Format_Indicator,
GI_3GPP_3GPP_IMSI_MCC_MNC avp_GI_3GPP_3GPP_IMSI_MCC_MNC,
RX_3GPP_Abort_Cause avp_RX_3GPP_Abort_Cause,
+ DCA_3GPP_ISUP_Cause_Location avp_DCA_3GPP_ISUP_Cause_Location,
PCC_3GPP_Charging_Rule_Base_Name avp_PCC_3GPP_Charging_Rule_Base_Name,
RX_3GPP_Required_Access_Info avp_RX_3GPP_Required_Access_Info,
PCC_3GPP_TDF_Destination_Realm avp_PCC_3GPP_TDF_Destination_Realm,
S6_3GPP_S6t_HSS_Cause avp_S6_3GPP_S6t_HSS_Cause,
+ DCA_3GPP_Media_Initiator_Party avp_DCA_3GPP_Media_Initiator_Party,
+ DCA_3GPP_Associated_URI avp_DCA_3GPP_Associated_URI,
RX_3GPP_AF_Requested_Data avp_RX_3GPP_AF_Requested_Data,
+ PCC_3GPP_QoS_Rule_Report avp_PCC_3GPP_QoS_Rule_Report,
DNAS_NONE_Filter_Id avp_DNAS_NONE_Filter_Id,
DNAS_NONE_ARAP_Password avp_DNAS_NONE_ARAP_Password,
- PCC_3GPP_QoS_Rule_Report avp_PCC_3GPP_QoS_Rule_Report,
- DNAS_NONE_CHAP_Response avp_DNAS_NONE_CHAP_Response,
+ DCA_3GPP_Route_Header_Received avp_DCA_3GPP_Route_Header_Received,
S6_3GPP_Stationary_Indication avp_S6_3GPP_Stationary_Indication,
+ DNAS_NONE_CHAP_Response avp_DNAS_NONE_CHAP_Response,
PCC_3GPP_Traffic_Steering_Policy_Identifier_DL avp_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL,
+ DCA_3GPP_Usage_Information_Report_Sequence_Number avp_DCA_3GPP_Usage_Information_Report_Sequence_Number,
AAA_3GPP_Geodetic_Information avp_AAA_3GPP_Geodetic_Information,
PCC_3GPP_Extended_GBR_UL avp_PCC_3GPP_Extended_GBR_UL,
AAA_3GPP_MBSFN_Area_ID avp_AAA_3GPP_MBSFN_Area_ID,
CxDx_3GPP_Server_Capabilities avp_CxDx_3GPP_Server_Capabilities,
AAA_3GPP_Area_Scope avp_AAA_3GPP_Area_Scope,
- DNAS_NONE_Accounting_Input_Packets avp_DNAS_NONE_Accounting_Input_Packets,
+ MIPv4_NONE_Accounting_Input_Packets avp_MIPv4_NONE_Accounting_Input_Packets,
+ DCA_3GPP_SGW_Change avp_DCA_3GPP_SGW_Change,
CxDx_3GPP_SCSCF_Restoration_Info avp_CxDx_3GPP_SCSCF_Restoration_Info,
CxDx_3GPP_Initial_CSeq_Sequence_Number avp_CxDx_3GPP_Initial_CSeq_Sequence_Number,
+ DCA_3GPP_AoC_Subscription_Information avp_DCA_3GPP_AoC_Subscription_Information,
AAA_3GPP_PUA_Flags avp_AAA_3GPP_PUA_Flags,
DNAS_NONE_Callback_Id avp_DNAS_NONE_Callback_Id,
+ DCA_3GPP_Time_Usage avp_DCA_3GPP_Time_Usage,
CxDx_3GPP_Primary_Event_Charging_Function_Name avp_CxDx_3GPP_Primary_Event_Charging_Function_Name,
DCC_NONE_CC_Output_Octets avp_DCC_NONE_CC_Output_Octets,
GI_3GPP_3GPP_User_Location_Info avp_GI_3GPP_3GPP_User_Location_Info,
AAA_3GPP_Notification_To_UE_User avp_AAA_3GPP_Notification_To_UE_User,
AAA_3GPP_Visited_PLMN_Id avp_AAA_3GPP_Visited_PLMN_Id,
AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions avp_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions,
+ DCA_3GPP_Participant_Group avp_DCA_3GPP_Participant_Group,
+ DCA_3GPP_Play_Alternative avp_DCA_3GPP_Play_Alternative,
+ DCA_3GPP_MBMS_User_Service_Type avp_DCA_3GPP_MBMS_User_Service_Type,
+ DCA_3GPP_Transit_IOI_List avp_DCA_3GPP_Transit_IOI_List,
RX_3GPP_Codec_Data avp_RX_3GPP_Codec_Data,
S6_3GPP_Monitoring_Event_Config_Status avp_S6_3GPP_Monitoring_Event_Config_Status,
+ DCA_3GPP_SDP_Media_Name avp_DCA_3GPP_SDP_Media_Name,
+ DCA_3GPP_AF_Correlation_Information avp_DCA_3GPP_AF_Correlation_Information,
DCC_NONE_Cost_Information avp_DCC_NONE_Cost_Information,
+ DCA_3GPP_Serving_Node_Identity avp_DCA_3GPP_Serving_Node_Identity,
BASE_NONE_Error_Reporting_Host avp_BASE_NONE_Error_Reporting_Host,
+ DCA_3GPP_Radio_Frequency avp_DCA_3GPP_Radio_Frequency,
PCC_3GPP_Rule_Activation_Time avp_PCC_3GPP_Rule_Activation_Time,
S6_3GPP_Service_Data avp_S6_3GPP_Service_Data,
RX_3GPP_AF_Application_Identifier avp_RX_3GPP_AF_Application_Identifier,
PCC_3GPP_NetLoc_Access_Support avp_PCC_3GPP_NetLoc_Access_Support,
+ DCA_3GPP_Announcing_UE_VPLMN_Identifier avp_DCA_3GPP_Announcing_UE_VPLMN_Identifier,
S6_3GPP_Monitoring_Event_Configuration avp_S6_3GPP_Monitoring_Event_Configuration,
PCC_3GPP_Offline avp_PCC_3GPP_Offline,
+ DCA_3GPP_SIP_Method avp_DCA_3GPP_SIP_Method,
+ PCC_3GPP_ADC_Rule_Definition avp_PCC_3GPP_ADC_Rule_Definition,
+ AAA_3GPP_Additional_Context_ID avp_AAA_3GPP_Additional_Context_ID,
DNAS_NONE_Login_Service avp_DNAS_NONE_Login_Service,
DNAS_NONE_ARAP_Security_Data avp_DNAS_NONE_ARAP_Security_Data,
- AAA_3GPP_Additional_Context_ID avp_AAA_3GPP_Additional_Context_ID,
- PCC_3GPP_ADC_Rule_Definition avp_PCC_3GPP_ADC_Rule_Definition,
S6_3GPP_Allowed_PLMN_List avp_S6_3GPP_Allowed_PLMN_List,
- AAA_3GPP_Active_APN avp_AAA_3GPP_Active_APN,
PCC_3GPP_Bearer_Control_Mode avp_PCC_3GPP_Bearer_Control_Mode,
+ AAA_3GPP_Active_APN avp_AAA_3GPP_Active_APN,
PCC_3GPP_HeNB_Local_IP_Address avp_PCC_3GPP_HeNB_Local_IP_Address,
- AAA_3GPP_SMS_Register_Request avp_AAA_3GPP_SMS_Register_Request,
PCC_3GPP_Packet_Filter_Content avp_PCC_3GPP_Packet_Filter_Content,
+ AAA_3GPP_SMS_Register_Request avp_AAA_3GPP_SMS_Register_Request,
CxDx_3GPP_Subscription_Info avp_CxDx_3GPP_Subscription_Info,
+ DCA_3GPP_SIP_Response_Timestamp_Fraction avp_DCA_3GPP_SIP_Response_Timestamp_Fraction,
+ DCA_3GPP_Client_Address avp_DCA_3GPP_Client_Address,
AAA_3GPP_APN_Configuration avp_AAA_3GPP_APN_Configuration,
+ DCA_3GPP_Subscriber_Role avp_DCA_3GPP_Subscriber_Role,
CxDx_3GPP_SIP_Number_Auth_Items avp_CxDx_3GPP_SIP_Number_Auth_Items,
AAA_3GPP_OMC_Id avp_AAA_3GPP_OMC_Id,
AAA_3GPP_GMLC_Restriction avp_AAA_3GPP_GMLC_Restriction,
DNAS_NONE_State avp_DNAS_NONE_State,
DNAS_NONE_Tunnel_Preference avp_DNAS_NONE_Tunnel_Preference,
DCC_NONE_CC_Session_Failover avp_DCC_NONE_CC_Session_Failover,
+ DCA_3GPP_Enhanced_Diagnostics avp_DCA_3GPP_Enhanced_Diagnostics,
+ DCA_3GPP_CSG_Membership_Indication avp_DCA_3GPP_CSG_Membership_Indication,
AAA_3GPP_Regional_Subscription_Zone_Code avp_AAA_3GPP_Regional_Subscription_Zone_Code,
+ DCA_3GPP_Message_Class avp_DCA_3GPP_Message_Class,
GI_3GPP_3GPP_Negotiated_DSCP avp_GI_3GPP_3GPP_Negotiated_DSCP,
+ AAA_3GPP_TWAN_S2a_Failure_Cause avp_AAA_3GPP_TWAN_S2a_Failure_Cause,
+ MIPv4_NONE_MIP_FA_to_MN_SPI avp_MIPv4_NONE_MIP_FA_to_MN_SPI,
+ DCA_3GPP_Trigger avp_DCA_3GPP_Trigger,
+ DCA_3GPP_Called_Identity_Change avp_DCA_3GPP_Called_Identity_Change,
+ DCA_3GPP_ProSe_Request_Timestamp avp_DCA_3GPP_ProSe_Request_Timestamp,
+ DCA_3GPP_PoC_Session_Id avp_DCA_3GPP_PoC_Session_Id,
BASE_NONE_Proxy_State avp_BASE_NONE_Proxy_State,
- DCC_NONE_Credit_Control_Failure_Handling avp_DCC_NONE_Credit_Control_Failure_Handling,
+ DCA_3GPP_PoC_Server_Role avp_DCA_3GPP_PoC_Server_Role,
+ DCA_3GPP_Forwarding_Pending avp_DCA_3GPP_Forwarding_Pending,
S6_3GPP_SIR_Flags avp_S6_3GPP_SIR_Flags,
+ DCC_NONE_Credit_Control_Failure_Handling avp_DCC_NONE_Credit_Control_Failure_Handling,
+ MIPv6_NONE_MIP6_Agent_Info avp_MIPv6_NONE_MIP6_Agent_Info,
RX_3GPP_MPS_Identifier avp_RX_3GPP_MPS_Identifier,
- AAA_3GPP_MDT_Allowed_PLMN_Id avp_AAA_3GPP_MDT_Allowed_PLMN_Id,
PCC_3GPP_Credit_Management_Status avp_PCC_3GPP_Credit_Management_Status,
+ AAA_3GPP_MDT_Allowed_PLMN_Id avp_AAA_3GPP_MDT_Allowed_PLMN_Id,
+ DCA_3GPP_Monitored_PLMN_Identifier avp_DCA_3GPP_Monitored_PLMN_Identifier,
S6_3GPP_Service_Result avp_S6_3GPP_Service_Result,
- AAA_3GPP_MME_Location_Information avp_AAA_3GPP_MME_Location_Information,
PCC_3GPP_Reporting_Level avp_PCC_3GPP_Reporting_Level,
+ AAA_3GPP_MME_Location_Information avp_AAA_3GPP_MME_Location_Information,
+ DCA_3GPP_Served_Party_IP_Address avp_DCA_3GPP_Served_Party_IP_Address,
RX_3GPP_Max_Supported_Bandwidth_DL avp_RX_3GPP_Max_Supported_Bandwidth_DL,
- AAA_3GPP_Subscribed_VSRVCC avp_AAA_3GPP_Subscribed_VSRVCC,
+ DCA_3GPP_Time_First_Reception avp_DCA_3GPP_Time_First_Reception,
PCC_3GPP_Pre_emption_Capability avp_PCC_3GPP_Pre_emption_Capability,
+ AAA_3GPP_Subscribed_VSRVCC avp_AAA_3GPP_Subscribed_VSRVCC,
PCC_3GPP_Monitoring_Flags avp_PCC_3GPP_Monitoring_Flags,
BASE_NONE_Redirect_Max_Cache_Time avp_BASE_NONE_Redirect_Max_Cache_Time,
CxDx_3GPP_Feature_List avp_CxDx_3GPP_Feature_List,
+ DCA_3GPP_Address_Type avp_DCA_3GPP_Address_Type,
PCC_3GPP_TCP_Source_Port avp_PCC_3GPP_TCP_Source_Port,
PCC_3GPP_Application_Detection_Information avp_PCC_3GPP_Application_Detection_Information,
AAA_3GPP_Emergency_Info avp_AAA_3GPP_Emergency_Info,
+ DCA_3GPP_Remaining_Balance avp_DCA_3GPP_Remaining_Balance,
AAA_3GPP_MPS_Priority avp_AAA_3GPP_MPS_Priority,
+ DCA_3GPP_Next_Tariff avp_DCA_3GPP_Next_Tariff,
DCC_NONE_Requested_Action avp_DCC_NONE_Requested_Action,
CxDx_3GPP_Record_Route avp_CxDx_3GPP_Record_Route,
+ DCA_3GPP_Tariff_XML avp_DCA_3GPP_Tariff_XML,
AAA_3GPP_Alert_Reason avp_AAA_3GPP_Alert_Reason,
+ DCA_3GPP_Recipient_Address avp_DCA_3GPP_Recipient_Address,
+ DCA_3GPP_Change_Condition avp_DCA_3GPP_Change_Condition,
GI_3GPP_3GPP_CG_IPv6_Address avp_GI_3GPP_3GPP_CG_IPv6_Address,
DNAS_NONE_Idle_Timeout avp_DNAS_NONE_Idle_Timeout,
DNAS_NONE_NAS_Port_Id avp_DNAS_NONE_NAS_Port_Id,
+ AAA_3GPP_DEA_Flags avp_AAA_3GPP_DEA_Flags,
+ DCA_3GPP_SCS_AS_Address avp_DCA_3GPP_SCS_AS_Address,
AAA_3GPP_MO_LR avp_AAA_3GPP_MO_LR,
+ DCA_3GPP_IMS_Visited_Network_Identifier avp_DCA_3GPP_IMS_Visited_Network_Identifier,
+ DCA_3GPP_PoC_User_Role avp_DCA_3GPP_PoC_User_Role,
+ DCA_3GPP_Announcement_Identifier avp_DCA_3GPP_Announcement_Identifier,
+ AAA_3GPP_Non_3GPP_IP_Access avp_AAA_3GPP_Non_3GPP_IP_Access,
+ DCA_3GPP_Monitoring_Event_Report_Data avp_DCA_3GPP_Monitoring_Event_Report_Data,
+ DCA_3GPP_Adaptations avp_DCA_3GPP_Adaptations,
BASE_NONE_Host_IP_Address avp_BASE_NONE_Host_IP_Address,
+ MIPv4_NONE_MIP_Reg_Request avp_MIPv4_NONE_MIP_Reg_Request,
+ DCA_3GPP_Quota_Holding_Time avp_DCA_3GPP_Quota_Holding_Time,
+ AAA_3GPP_Maximum_Wait_Time avp_AAA_3GPP_Maximum_Wait_Time,
RX_3GPP_Max_Requested_Bandwidth_UL avp_RX_3GPP_Max_Requested_Bandwidth_UL,
PCC_3GPP_Usage_Monitoring_Support avp_PCC_3GPP_Usage_Monitoring_Support,
S6_3GPP_Maximum_Response_Time avp_S6_3GPP_Maximum_Response_Time,
+ DCA_3GPP_Envelope_Reporting avp_DCA_3GPP_Envelope_Reporting,
+ DCA_3GPP_Application_Server avp_DCA_3GPP_Application_Server,
RX_3GPP_Sponsor_Identity avp_RX_3GPP_Sponsor_Identity,
DNAS_NONE_Framed_Appletalk_Link avp_DNAS_NONE_Framed_Appletalk_Link,
DNAS_NONE_Framed_Interface_Id avp_DNAS_NONE_Framed_Interface_Id,
+ DCA_3GPP_Proximity_Alert_Indication avp_DCA_3GPP_Proximity_Alert_Indication,
PCC_3GPP_CoA_IP_Address avp_PCC_3GPP_CoA_IP_Address,
+ DCA_3GPP_Trunk_Group_Id avp_DCA_3GPP_Trunk_Group_Id,
PCC_3GPP_Default_QoS_Information avp_PCC_3GPP_Default_QoS_Information,
PCC_3GPP_AN_GW_Address avp_PCC_3GPP_AN_GW_Address,
+ DCA_3GPP_Start_Of_Charging avp_DCA_3GPP_Start_Of_Charging,
+ DCA_3GPP_Participants_Involved avp_DCA_3GPP_Participants_Involved,
PCC_3GPP_NBIFOM_Support avp_PCC_3GPP_NBIFOM_Support,
PCC_3GPP_Redirect_Support avp_PCC_3GPP_Redirect_Support,
AAA_3GPP_IMSI_Group_Id avp_AAA_3GPP_IMSI_Group_Id,
AAA_3GPP_Cell_Global_Identity avp_AAA_3GPP_Cell_Global_Identity,
BASE_NONE_Vendor_Id avp_BASE_NONE_Vendor_Id,
AAA_3GPP_PDN_Connection_Continuity avp_AAA_3GPP_PDN_Connection_Continuity,
+ DCA_3GPP_Tariff_Information avp_DCA_3GPP_Tariff_Information,
CxDx_3GPP_Wildcarded_Public_Identity avp_CxDx_3GPP_Wildcarded_Public_Identity,
- DNAS_NONE_Acct_Session_Time avp_DNAS_NONE_Acct_Session_Time,
+ MIPv4_NONE_Acct_Session_Time avp_MIPv4_NONE_Acct_Session_Time,
AAA_3GPP_DSA_Flags avp_AAA_3GPP_DSA_Flags,
+ DCA_3GPP_PoC_Event_Type avp_DCA_3GPP_PoC_Event_Type,
AAA_3GPP_Trace_Data avp_AAA_3GPP_Trace_Data,
AAA_3GPP_LCS_Info avp_AAA_3GPP_LCS_Info,
+ DCA_3GPP_LCS_Requestor_Id_String avp_DCA_3GPP_LCS_Requestor_Id_String,
AAA_3GPP_PDN_GW_Allocation_Type avp_AAA_3GPP_PDN_GW_Allocation_Type,
+ DCA_3GPP_Additional_Type_Information avp_DCA_3GPP_Additional_Type_Information,
GI_3GPP_3GPP_SGSN_MCC_MNC avp_GI_3GPP_3GPP_SGSN_MCC_MNC,
+ AAA_3GPP_HESSID avp_AAA_3GPP_HESSID,
+ DCA_3GPP_Content_Class avp_DCA_3GPP_Content_Class,
BASE_NONE_Event_Timestamp avp_BASE_NONE_Event_Timestamp,
+ DCA_3GPP_TAD_Identifier avp_DCA_3GPP_TAD_Identifier,
DCC_NONE_Final_Unit_Action avp_DCC_NONE_Final_Unit_Action,
+ AAA_3GPP_IMEI_Check_In_VPLMN_Result avp_AAA_3GPP_IMEI_Check_In_VPLMN_Result,
+ DCA_3GPP_Service_Generic_Information avp_DCA_3GPP_Service_Generic_Information,
+ DCA_3GPP_Variable_Part_Type avp_DCA_3GPP_Variable_Part_Type,
+ DCA_3GPP_ProSe_Direct_Discovery_Model avp_DCA_3GPP_ProSe_Direct_Discovery_Model,
RX_3GPP_Extended_Max_Requested_BW_UL avp_RX_3GPP_Extended_Max_Requested_BW_UL,
+ DCA_3GPP_SM_Device_Trigger_Indicator avp_DCA_3GPP_SM_Device_Trigger_Indicator,
S6_3GPP_User_Identifier avp_S6_3GPP_User_Identifier,
- DNAS_NONE_Framed_IPv6_Pool avp_DNAS_NONE_Framed_IPv6_Pool,
PCC_3GPP_QoS_Rule_Base_Name avp_PCC_3GPP_QoS_Rule_Base_Name,
+ DNAS_NONE_Framed_IPv6_Pool avp_DNAS_NONE_Framed_IPv6_Pool,
AAA_3GPP_Restoration_Priority avp_AAA_3GPP_Restoration_Priority,
- DCC_NONE_Rating_Group avp_DCC_NONE_Rating_Group,
- MIPv6_NONE_MIP_MN_HA_SPI avp_MIPv6_NONE_MIP_MN_HA_SPI,
+ DCA_3GPP_ISUP_Cause_Diagnostics avp_DCA_3GPP_ISUP_Cause_Diagnostics,
S6_3GPP_Association_Type avp_S6_3GPP_Association_Type,
PCC_3GPP_Charging_Rule_Definition avp_PCC_3GPP_Charging_Rule_Definition,
+ DCC_NONE_Rating_Group avp_DCC_NONE_Rating_Group,
+ MIPv6_NONE_MIP_MN_HA_SPI avp_MIPv6_NONE_MIP_MN_HA_SPI,
RX_3GPP_Min_Requested_Bandwidth_UL avp_RX_3GPP_Min_Requested_Bandwidth_UL,
- AAA_3GPP_Report_Amount avp_AAA_3GPP_Report_Amount,
+ DCA_3GPP_Application_Specific_Data avp_DCA_3GPP_Application_Specific_Data,
PCC_3GPP_CoA_Information avp_PCC_3GPP_CoA_Information,
+ AAA_3GPP_Report_Amount avp_AAA_3GPP_Report_Amount,
CxDx_3GPP_Secondary_Charging_Collection_Function_Name avp_CxDx_3GPP_Secondary_Charging_Collection_Function_Name,
DCC_NONE_User_Equipment_Info avp_DCC_NONE_User_Equipment_Info,
AAA_3GPP_A_MSISDN avp_AAA_3GPP_A_MSISDN,
- MIPv6_NONE_MIP_Mobile_Node_Address avp_MIPv6_NONE_MIP_Mobile_Node_Address,
+ MIPv4_NONE_MIP_Mobile_Node_Address avp_MIPv4_NONE_MIP_Mobile_Node_Address,
PCC_3GPP_Routing_Rule_Report avp_PCC_3GPP_Routing_Rule_Report,
AAA_3GPP_Number_Of_Requested_Vectors avp_AAA_3GPP_Number_Of_Requested_Vectors,
AAA_3GPP_AIR_Flags avp_AAA_3GPP_AIR_Flags,
+ DCA_3GPP_SM_Protocol_ID avp_DCA_3GPP_SM_Protocol_ID,
+ DCA_3GPP_Low_Priority_Indicator avp_DCA_3GPP_Low_Priority_Indicator,
AAA_3GPP_Geographical_Information avp_AAA_3GPP_Geographical_Information,
+ DCA_3GPP_Participant_Action_Type avp_DCA_3GPP_Participant_Action_Type,
+ DCA_3GPP_Node_Id avp_DCA_3GPP_Node_Id,
CxDx_3GPP_Loose_Route_Indication avp_CxDx_3GPP_Loose_Route_Indication,
DCC_NONE_Service_Parameter_Type avp_DCC_NONE_Service_Parameter_Type,
AAA_3GPP_MME_User_State avp_AAA_3GPP_MME_User_State,
AAA_3GPP_Access_Restriction_Data avp_AAA_3GPP_Access_Restriction_Data,
+ DCA_3GPP_SM_Service_Type avp_DCA_3GPP_SM_Service_Type,
+ DCA_3GPP_UNI_PDU_CP_Only_Flag avp_DCA_3GPP_UNI_PDU_CP_Only_Flag,
+ MIPv4_NONE_MIP_Filter_Rule avp_MIPv4_NONE_MIP_Filter_Rule,
BASE_NONE_Failed_AVP avp_BASE_NONE_Failed_AVP,
GI_3GPP_3GPP_RAT_Type avp_GI_3GPP_3GPP_RAT_Type,
AAA_3GPP_SS_Status avp_AAA_3GPP_SS_Status,
+ DCA_3GPP_Neighbour_Node_Address avp_DCA_3GPP_Neighbour_Node_Address,
+ DCA_3GPP_Location_Type avp_DCA_3GPP_Location_Type,
+ DCA_3GPP_Quota_Indicator avp_DCA_3GPP_Quota_Indicator,
+ DCA_3GPP_Priority avp_DCA_3GPP_Priority,
S6_3GPP_NIDD_Authorization_Update avp_S6_3GPP_NIDD_Authorization_Update,
+ DCA_3GPP_Service_Specific_Data avp_DCA_3GPP_Service_Specific_Data,
DCC_NONE_Subscription_Id_Type avp_DCC_NONE_Subscription_Id_Type,
+ MIPv4_NONE_MIP_FA_to_HA_MSA avp_MIPv4_NONE_MIP_FA_to_HA_MSA,
+ AAA_3GPP_Connectivity_Flags avp_AAA_3GPP_Connectivity_Flags,
PCC_3GPP_Packet_Filter_Operation avp_PCC_3GPP_Packet_Filter_Operation,
+ DCA_3GPP_VCS_Information avp_DCA_3GPP_VCS_Information,
S6_3GPP_SCEF_Reference_ID_for_Deletion avp_S6_3GPP_SCEF_Reference_ID_for_Deletion,
+ DCA_3GPP_Content_Disposition avp_DCA_3GPP_Content_Disposition,
RX_3GPP_SIP_Forking_Indication avp_RX_3GPP_SIP_Forking_Indication,
DNAS_NONE_User_Password avp_DNAS_NONE_User_Password,
+ DCA_3GPP_ProSe_Group_IP_Multicast_Address avp_DCA_3GPP_ProSe_Group_IP_Multicast_Address,
S6_3GPP_IMEI_Change avp_S6_3GPP_IMEI_Change,
PCC_3GPP_IP_CAN_Type avp_PCC_3GPP_IP_CAN_Type,
+ DCA_3GPP_SDP_Media_Component avp_DCA_3GPP_SDP_Media_Component,
RX_3GPP_Extended_Min_Desired_BW_UL avp_RX_3GPP_Extended_Min_Desired_BW_UL,
+ DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container avp_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container,
CxDx_3GPP_SIP_Authorization avp_CxDx_3GPP_SIP_Authorization,
PCC_3GPP_Revalidation_Time avp_PCC_3GPP_Revalidation_Time,
AAA_3GPP_Logging_Interval avp_AAA_3GPP_Logging_Interval,
+ DCA_3GPP_PoC_Information avp_DCA_3GPP_PoC_Information,
PCC_3GPP_Presence_Reporting_Area_Status avp_PCC_3GPP_Presence_Reporting_Area_Status,
- AAA_3GPP_WLAN_offloadability avp_AAA_3GPP_WLAN_offloadability,
PCC_3GPP_Routing_Filter avp_PCC_3GPP_Routing_Filter,
+ AAA_3GPP_WLAN_offloadability avp_AAA_3GPP_WLAN_offloadability,
+ DCA_3GPP_Data_Coding_Scheme avp_DCA_3GPP_Data_Coding_Scheme,
PCC_3GPP_Metering_Method avp_PCC_3GPP_Metering_Method,
DNAS_NONE_Acct_Tunnel_Connection avp_DNAS_NONE_Acct_Tunnel_Connection,
AAA_3GPP_Non_IP_Data_Delivery_Mechanism avp_AAA_3GPP_Non_IP_Data_Delivery_Mechanism,
+ DCA_3GPP_Initial_IMS_Charging_Identifier avp_DCA_3GPP_Initial_IMS_Charging_Identifier,
DNAS_NONE_NAS_Filter_Rule avp_DNAS_NONE_NAS_Filter_Rule,
+ MIPv4_NONE_MIP_Feature_Vector avp_MIPv4_NONE_MIP_Feature_Vector,
BASE_NONE_Session_Server_Failover avp_BASE_NONE_Session_Server_Failover,
+ DCA_3GPP_Accumulated_Cost avp_DCA_3GPP_Accumulated_Cost,
CxDx_3GPP_Integrity_Key avp_CxDx_3GPP_Integrity_Key,
AAA_3GPP_E_UTRAN_Vector avp_AAA_3GPP_E_UTRAN_Vector,
+ DCA_3GPP_SMSC_Address avp_DCA_3GPP_SMSC_Address,
+ DCA_3GPP_PDP_Address_Prefix_Length avp_DCA_3GPP_PDP_Address_Prefix_Length,
BASE_NONE_Experimental_Result avp_BASE_NONE_Experimental_Result,
DNAS_NONE_Acct_Link_Count avp_DNAS_NONE_Acct_Link_Count,
DCC_NONE_Unit_Value avp_DCC_NONE_Unit_Value,
AAA_3GPP_Trace_Event_List avp_AAA_3GPP_Trace_Event_List,
+ DCA_3GPP_LCS_Client_Id avp_DCA_3GPP_LCS_Client_Id,
GI_3GPP_3GPP_PDP_Type avp_GI_3GPP_3GPP_PDP_Type,
DNAS_NONE_Reply_Message avp_DNAS_NONE_Reply_Message,
DNAS_NONE_Connect_Info avp_DNAS_NONE_Connect_Info,
- MIPv6_NONE_MIP_Replay_Mode avp_MIPv6_NONE_MIP_Replay_Mode,
+ MIPv4_NONE_MIP_Replay_Mode avp_MIPv4_NONE_MIP_Replay_Mode,
BASE_NONE_Proxy_Host avp_BASE_NONE_Proxy_Host,
+ DCA_3GPP_Number_Of_Talk_Bursts avp_DCA_3GPP_Number_Of_Talk_Bursts,
+ AAA_3GPP_Short_Network_Name avp_AAA_3GPP_Short_Network_Name,
+ DCA_3GPP_Message_Size avp_DCA_3GPP_Message_Size,
+ DCA_3GPP_Additional_Exception_Reports avp_DCA_3GPP_Additional_Exception_Reports,
+ DCA_3GPP_Access_Transfer_Information avp_DCA_3GPP_Access_Transfer_Information,
S6_3GPP_Communication_Pattern_Set avp_S6_3GPP_Communication_Pattern_Set,
+ AAA_3GPP_TWAG_UP_Address avp_AAA_3GPP_TWAG_UP_Address,
+ DCA_3GPP_MMBox_Storage_Requested avp_DCA_3GPP_MMBox_Storage_Requested,
RX_3GPP_Flow_Status avp_RX_3GPP_Flow_Status,
DNAS_NONE_CHAP_Challenge avp_DNAS_NONE_CHAP_Challenge,
+ DCA_3GPP_PC3_Control_Protocol_Cause avp_DCA_3GPP_PC3_Control_Protocol_Cause,
DCC_NONE_CC_Unit_Type avp_DCC_NONE_CC_Unit_Type,
+ DCA_3GPP_Calling_Party_Address avp_DCA_3GPP_Calling_Party_Address,
RX_3GPP_MCPTT_Identifier avp_RX_3GPP_MCPTT_Identifier,
S6_3GPP_Group_Monitoring_Event_Report avp_S6_3GPP_Group_Monitoring_Event_Report,
PCC_3GPP_QoS_Upgrade avp_PCC_3GPP_QoS_Upgrade,
- DNAS_NONE_Service_Type avp_DNAS_NONE_Service_Type,
+ DCA_3GPP_PS_Append_Free_Format_Data avp_DCA_3GPP_PS_Append_Free_Format_Data,
PCC_3GPP_AN_GW_Status avp_PCC_3GPP_AN_GW_Status,
- AAA_3GPP_Measurement_Period_UMTS avp_AAA_3GPP_Measurement_Period_UMTS,
+ DNAS_NONE_Service_Type avp_DNAS_NONE_Service_Type,
PCC_3GPP_Monitoring_Key avp_PCC_3GPP_Monitoring_Key,
+ AAA_3GPP_Measurement_Period_UMTS avp_AAA_3GPP_Measurement_Period_UMTS,
+ DCA_3GPP_Media_Initiator_Flag avp_DCA_3GPP_Media_Initiator_Flag,
+ DCA_3GPP_ISUP_Location_Number avp_DCA_3GPP_ISUP_Location_Number,
PCC_3GPP_3GPP_PS_Data_Off_Status avp_PCC_3GPP_3GPP_PS_Data_Off_Status,
- AAA_3GPP_Reset_ID avp_AAA_3GPP_Reset_ID,
PCC_3GPP_Routing_Rule_Install avp_PCC_3GPP_Routing_Rule_Install,
+ AAA_3GPP_Reset_ID avp_AAA_3GPP_Reset_ID,
+ DCA_3GPP_Service_Data_Container avp_DCA_3GPP_Service_Data_Container,
CxDx_3GPP_Server_Assignment_Type avp_CxDx_3GPP_Server_Assignment_Type,
AAA_3GPP_PUR_Flags avp_AAA_3GPP_PUR_Flags,
- DNAS_NONE_Framed_Routing avp_DNAS_NONE_Framed_Routing,
PCC_3GPP_IP_CAN_Session_Charging_Scope avp_PCC_3GPP_IP_CAN_Session_Charging_Scope,
+ DNAS_NONE_Framed_Routing avp_DNAS_NONE_Framed_Routing,
AAA_3GPP_IMEI avp_AAA_3GPP_IMEI,
DNAS_NONE_CHAP_Ident avp_DNAS_NONE_CHAP_Ident,
+ DCA_3GPP_Interface_Text avp_DCA_3GPP_Interface_Text,
AAA_3GPP_Kc avp_AAA_3GPP_Kc,
+ DCA_3GPP_Current_Tariff avp_DCA_3GPP_Current_Tariff,
AAA_3GPP_SGSN_Number avp_AAA_3GPP_SGSN_Number,
AAA_3GPP_HPLMN_ODB avp_AAA_3GPP_HPLMN_ODB,
+ DCA_3GPP_Time_Quota_Type avp_DCA_3GPP_Time_Quota_Type,
+ AAA_3GPP_Trace_Info avp_AAA_3GPP_Trace_Info,
+ DCA_3GPP_Domain_Name avp_DCA_3GPP_Domain_Name,
GI_3GPP_3GPP_Charging_Characteristics avp_GI_3GPP_3GPP_Charging_Characteristics,
AAA_3GPP_PDP_Context avp_AAA_3GPP_PDP_Context,
DCC_NONE_CC_Money avp_DCC_NONE_CC_Money,
+ AAA_3GPP_DER_Flags avp_AAA_3GPP_DER_Flags,
+ DCA_3GPP_LCS_Data_Coding_Scheme avp_DCA_3GPP_LCS_Data_Coding_Scheme,
GI_3GPP_3GPP_GGSN_Address avp_GI_3GPP_3GPP_GGSN_Address,
BASE_NONE_Proxy_Info avp_BASE_NONE_Proxy_Info,
+ DCA_3GPP_Related_IMS_Charging_Identifier_Node avp_DCA_3GPP_Related_IMS_Charging_Identifier_Node,
S6_3GPP_Node_Type avp_S6_3GPP_Node_Type,
+ DCA_3GPP_Talk_Burst_Volume avp_DCA_3GPP_Talk_Burst_Volume,
+ DCA_3GPP_Service_Id avp_DCA_3GPP_Service_Id,
RX_3GPP_Priority_Sharing_Indicator avp_RX_3GPP_Priority_Sharing_Indicator,
DNAS_NONE_Tunnel_Type avp_DNAS_NONE_Tunnel_Type,
PCC_3GPP_QoS_Rule_Name avp_PCC_3GPP_QoS_Rule_Name,
+ DCA_3GPP_Trigger_Type avp_DCA_3GPP_Trigger_Type,
+ DCA_3GPP_Instance_Id avp_DCA_3GPP_Instance_Id,
S6_3GPP_Scheduled_Communication_Time avp_S6_3GPP_Scheduled_Communication_Time,
RX_3GPP_Max_Requested_Bandwidth_DL avp_RX_3GPP_Max_Requested_Bandwidth_DL,
+ DCA_3GPP_Role_Of_ProSe_Function avp_DCA_3GPP_Role_Of_ProSe_Function,
S6_3GPP_Maximum_Latency avp_S6_3GPP_Maximum_Latency,
PCC_3GPP_PCC_Rule_Status avp_PCC_3GPP_PCC_Rule_Status,
+ DCA_3GPP_SIP_Response_Timestamp avp_DCA_3GPP_SIP_Response_Timestamp,
PCC_3GPP_Extended_GBR_DL avp_PCC_3GPP_Extended_GBR_DL,
AAA_3GPP_MBSFN_Area avp_AAA_3GPP_MBSFN_Area,
+ DCA_3GPP_ProSe_UE_ID avp_DCA_3GPP_ProSe_UE_ID,
CxDx_3GPP_Server_Name avp_CxDx_3GPP_Server_Name,
- DCC_NONE_Check_Balance_Result avp_DCC_NONE_Check_Balance_Result,
S6_3GPP_APN_Validity_Time avp_S6_3GPP_APN_Validity_Time,
- AAA_3GPP_Job_Type avp_AAA_3GPP_Job_Type,
PCC_3GPP_Allocation_Retention_Priority avp_PCC_3GPP_Allocation_Retention_Priority,
+ DCC_NONE_Check_Balance_Result avp_DCC_NONE_Check_Balance_Result,
+ AAA_3GPP_Job_Type avp_AAA_3GPP_Job_Type,
BASE_NONE_Destination_Host avp_BASE_NONE_Destination_Host,
AAA_3GPP_Positioning_Method avp_AAA_3GPP_Positioning_Method,
CxDx_3GPP_LIA_Flags avp_CxDx_3GPP_LIA_Flags,
AAA_3GPP_DL_Buffering_Suggested_Packet_Count avp_AAA_3GPP_DL_Buffering_Suggested_Packet_Count,
+ DCA_3GPP_AoC_Service_Type avp_DCA_3GPP_AoC_Service_Type,
DNAS_NONE_Login_IP_Host avp_DNAS_NONE_Login_IP_Host,
- DNAS_NONE_ARAP_Security avp_DNAS_NONE_ARAP_Security,
AAA_3GPP_IDA_Flags avp_AAA_3GPP_IDA_Flags,
+ DNAS_NONE_ARAP_Security avp_DNAS_NONE_ARAP_Security,
DNAS_NONE_Origin_AAA_Protocol avp_DNAS_NONE_Origin_AAA_Protocol,
+ DCA_3GPP_Time_Last_Usage avp_DCA_3GPP_Time_Last_Usage,
CxDx_3GPP_Charging_Information avp_CxDx_3GPP_Charging_Information,
AAA_3GPP_ULA_Flags avp_AAA_3GPP_ULA_Flags,
+ DCA_3GPP_Originator_Interface avp_DCA_3GPP_Originator_Interface,
AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported avp_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported,
AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature avp_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature,
- DNAS_NONE_Tunnel_Assignment_Id avp_DNAS_NONE_Tunnel_Assignment_Id,
+ DCA_3GPP_File_Repair_Supported avp_DCA_3GPP_File_Repair_Supported,
DNAS_NONE_Framed_IPX_Network avp_DNAS_NONE_Framed_IPX_Network,
+ DNAS_NONE_Tunnel_Assignment_Id avp_DNAS_NONE_Tunnel_Assignment_Id,
DCC_NONE_CC_Service_Specific_Units avp_DCC_NONE_CC_Service_Specific_Units,
+ DCA_3GPP_SDP_Answer_Timestamp avp_DCA_3GPP_SDP_Answer_Timestamp,
+ AAA_3GPP_WLAN_Identifier avp_AAA_3GPP_WLAN_Identifier,
+ DCA_3GPP_Type_Number avp_DCA_3GPP_Type_Number,
+ DCA_3GPP_NIDD_Submission avp_DCA_3GPP_NIDD_Submission,
S6_3GPP_T4_Parameters avp_S6_3GPP_T4_Parameters,
RX_3GPP_Access_Network_Charging_Identifier_Value avp_RX_3GPP_Access_Network_Charging_Identifier_Value,
+ DCA_3GPP_Announcing_UE_HPLMN_Identifier avp_DCA_3GPP_Announcing_UE_HPLMN_Identifier,
S6_3GPP_AESE_Error_Report avp_S6_3GPP_AESE_Error_Report,
+ MIPv4_NONE_MIP_FA_to_HA_SPI avp_MIPv4_NONE_MIP_FA_to_HA_SPI,
+ DCA_3GPP_Event_Type avp_DCA_3GPP_Event_Type,
RX_3GPP_Sharing_Key_DL avp_RX_3GPP_Sharing_Key_DL,
PCC_3GPP_ADC_Rule_Remove avp_PCC_3GPP_ADC_Rule_Remove,
+ DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container avp_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container,
S6_3GPP_Restricted_PLMN_List avp_S6_3GPP_Restricted_PLMN_List,
- AAA_3GPP_Age_Of_Location_Information avp_AAA_3GPP_Age_Of_Location_Information,
PCC_3GPP_Access_Network_Charging_Identifier_Gx avp_PCC_3GPP_Access_Network_Charging_Identifier_Gx,
+ AAA_3GPP_Age_Of_Location_Information avp_AAA_3GPP_Age_Of_Location_Information,
+ DCA_3GPP_PoC_Group_Name avp_DCA_3GPP_PoC_Group_Name,
RX_3GPP_Extended_Max_Requested_BW_DL avp_RX_3GPP_Extended_Max_Requested_BW_DL,
PCC_3GPP_Flow_Information avp_PCC_3GPP_Flow_Information,
+ DCA_3GPP_PS_Information avp_DCA_3GPP_PS_Information,
+ DCA_3GPP_MTC_IWF_Address avp_DCA_3GPP_MTC_IWF_Address,
+ PCC_3GPP_Execution_Time avp_PCC_3GPP_Execution_Time,
DNAS_NONE_NAS_Identifier avp_DNAS_NONE_NAS_Identifier,
DNAS_NONE_Tunnel_Server_Auth_Id avp_DNAS_NONE_Tunnel_Server_Auth_Id,
- PCC_3GPP_Execution_Time avp_PCC_3GPP_Execution_Time,
CxDx_3GPP_Contact avp_CxDx_3GPP_Contact,
+ PCC_3GPP_Charging_Correlation_Indicator avp_PCC_3GPP_Charging_Correlation_Indicator,
DCC_NONE_Credit_Control avp_DCC_NONE_Credit_Control,
BASE_NONE_Accounting_Record_Number avp_BASE_NONE_Accounting_Record_Number,
AAA_3GPP_Event_Threshold_Event_1I avp_AAA_3GPP_Event_Threshold_Event_1I,
- PCC_3GPP_Charging_Correlation_Indicator avp_PCC_3GPP_Charging_Correlation_Indicator,
+ DCA_3GPP_SIP_Request_Timestamp_Fraction avp_DCA_3GPP_SIP_Request_Timestamp_Fraction,
+ DCA_3GPP_Service_Mode avp_DCA_3GPP_Service_Mode,
CxDx_3GPP_User_Data avp_CxDx_3GPP_User_Data,
AAA_3GPP_Report_Interval avp_AAA_3GPP_Report_Interval,
PCC_3GPP_RAN_NAS_Release_Cause avp_PCC_3GPP_RAN_NAS_Release_Cause,
+ DCA_3GPP_Dynamic_Address_Flag_Extension avp_DCA_3GPP_Dynamic_Address_Flag_Extension,
AAA_3GPP_Client_Identity avp_AAA_3GPP_Client_Identity,
BASE_NONE_Redirect_Host_Usage avp_BASE_NONE_Redirect_Host_Usage,
+ DCA_3GPP_CSG_Access_Mode avp_DCA_3GPP_CSG_Access_Mode,
AAA_3GPP_Equipment_Status avp_AAA_3GPP_Equipment_Status,
+ DCA_3GPP_Supplementary_Service avp_DCA_3GPP_Supplementary_Service,
GI_3GPP_3GPP_Packet_Filter avp_GI_3GPP_3GPP_Packet_Filter,
DCC_NONE_Redirect_Server_Address avp_DCC_NONE_Redirect_Server_Address,
MIPv6_NONE_MIP6_Auth_Mode avp_MIPv6_NONE_MIP6_Auth_Mode,
AAA_3GPP_EPS_Location_Information avp_AAA_3GPP_EPS_Location_Information,
- DNAS_NONE_Acct_Tunnel_Packets_Lost avp_DNAS_NONE_Acct_Tunnel_Packets_Lost,
+ DCA_3GPP_Access_Network_Information avp_DCA_3GPP_Access_Network_Information,
+ DCA_3GPP_Called_Identity avp_DCA_3GPP_Called_Identity,
+ AAA_3GPP_TWAN_Default_APN_Context_Id avp_AAA_3GPP_TWAN_Default_APN_Context_Id,
+ DCA_3GPP_SGSN_Address avp_DCA_3GPP_SGSN_Address,
+ DCA_3GPP_SGi_PtP_Tunnelling_Method avp_DCA_3GPP_SGi_PtP_Tunnelling_Method,
BASE_NONE_Session_Timeout avp_BASE_NONE_Session_Timeout,
+ DNAS_NONE_Acct_Tunnel_Packets_Lost avp_DNAS_NONE_Acct_Tunnel_Packets_Lost,
+ DCA_3GPP_NNI_Type avp_DCA_3GPP_NNI_Type,
RX_3GPP_Service_Info_Status avp_RX_3GPP_Service_Info_Status,
S6_3GPP_CIR_Flags avp_S6_3GPP_CIR_Flags,
PCC_3GPP_Precedence avp_PCC_3GPP_Precedence,
+ DCA_3GPP_User_Participating_Type avp_DCA_3GPP_User_Participating_Type,
+ DCA_3GPP_GGSN_Address avp_DCA_3GPP_GGSN_Address,
RX_3GPP_Sponsoring_Action avp_RX_3GPP_Sponsoring_Action,
+ DCA_3GPP_Radio_Resources_Indicator avp_DCA_3GPP_Radio_Resources_Indicator,
S6_3GPP_Granted_Validity_Time avp_S6_3GPP_Granted_Validity_Time,
PCC_3GPP_Priority_Level avp_PCC_3GPP_Priority_Level,
+ DCA_3GPP_Node_Functionality avp_DCA_3GPP_Node_Functionality,
RX_3GPP_Flow_Description avp_RX_3GPP_Flow_Description,
- AAA_3GPP_Daylight_Saving_Time avp_AAA_3GPP_Daylight_Saving_Time,
PCC_3GPP_Packet_Filter_Information avp_PCC_3GPP_Packet_Filter_Information,
+ AAA_3GPP_Daylight_Saving_Time avp_AAA_3GPP_Daylight_Saving_Time,
+ DCA_3GPP_Address_Domain avp_DCA_3GPP_Address_Domain,
S6_3GPP_SCEF_ID avp_S6_3GPP_SCEF_ID,
+ DCA_3GPP_Content_Length avp_DCA_3GPP_Content_Length,
PCC_3GPP_Removal_Of_Access avp_PCC_3GPP_Removal_Of_Access,
- AAA_3GPP_Preferred_Data_Mode avp_AAA_3GPP_Preferred_Data_Mode,
PCC_3GPP_ADC_Rule_Report avp_PCC_3GPP_ADC_Rule_Report,
- AAA_3GPP_UE_SRVCC_Capability avp_AAA_3GPP_UE_SRVCC_Capability,
+ AAA_3GPP_Preferred_Data_Mode avp_AAA_3GPP_Preferred_Data_Mode,
+ DCA_3GPP_ProSe_Functionality avp_DCA_3GPP_ProSe_Functionality,
+ DCA_3GPP_Low_Balance_Indication avp_DCA_3GPP_Low_Balance_Indication,
PCC_3GPP_Guaranteed_Bitrate_UL avp_PCC_3GPP_Guaranteed_Bitrate_UL,
- DNAS_NONE_NAS_IPv6_Address avp_DNAS_NONE_NAS_IPv6_Address,
+ AAA_3GPP_UE_SRVCC_Capability avp_AAA_3GPP_UE_SRVCC_Capability,
DNAS_NONE_Login_LAT_Group avp_DNAS_NONE_Login_LAT_Group,
+ DNAS_NONE_NAS_IPv6_Address avp_DNAS_NONE_NAS_IPv6_Address,
MIPv6_NONE_MIP_MAC_Mobility_Data avp_MIPv6_NONE_MIP_MAC_Mobility_Data,
- DNAS_NONE_Accounting_Output_Octets avp_DNAS_NONE_Accounting_Output_Octets,
+ MIPv4_NONE_Accounting_Output_Octets avp_MIPv4_NONE_Accounting_Output_Octets,
CxDx_3GPP_To_SIP_Header avp_CxDx_3GPP_To_SIP_Header,
AAA_3GPP_Coupled_Node_Diameter_ID avp_AAA_3GPP_Coupled_Node_Diameter_ID,
+ DCA_3GPP_Real_Time_Tariff_Information avp_DCA_3GPP_Real_Time_Tariff_Information,
AAA_3GPP_STN_SR avp_AAA_3GPP_STN_SR,
+ DCA_3GPP_SDP_Type avp_DCA_3GPP_SDP_Type,
BASE_NONE_Supported_Vendor_Id avp_BASE_NONE_Supported_Vendor_Id,
AAA_3GPP_ServiceTypeIdentity avp_AAA_3GPP_ServiceTypeIdentity,
+ DCA_3GPP_Requested_Party_Address avp_DCA_3GPP_Requested_Party_Address,
+ DCA_3GPP_Announcement_Information avp_DCA_3GPP_Announcement_Information,
DNAS_NONE_Acct_Authentic avp_DNAS_NONE_Acct_Authentic,
DCC_NONE_Service_Identifier avp_DCC_NONE_Service_Identifier,
AAA_3GPP_AUTN avp_AAA_3GPP_AUTN,
+ AAA_3GPP_Non_3GPP_User_Data avp_AAA_3GPP_Non_3GPP_User_Data,
+ DCA_3GPP_Delivery_Report_Requested avp_DCA_3GPP_Delivery_Report_Requested,
GI_3GPP_TWAN_Identifier avp_GI_3GPP_TWAN_Identifier,
+ AAA_3GPP_Origination_Time_Stamp avp_AAA_3GPP_Origination_Time_Stamp,
+ DCA_3GPP_LCS_APN avp_DCA_3GPP_LCS_APN,
+ DCA_3GPP_Envelope_End_Time avp_DCA_3GPP_Envelope_End_Time,
RX_3GPP_Sponsored_Connectivity_Data avp_RX_3GPP_Sponsored_Connectivity_Data,
BASE_NONE_Auth_Request_Type avp_BASE_NONE_Auth_Request_Type,
+ DCA_3GPP_Application_Server_Information avp_DCA_3GPP_Application_Server_Information,
+ DCA_3GPP_Originator_Address avp_DCA_3GPP_Originator_Address,
+ DCA_3GPP_Network_Call_Reference_Number avp_DCA_3GPP_Network_Call_Reference_Number,
S6_3GPP_AESE_Communication_Pattern avp_S6_3GPP_AESE_Communication_Pattern,
PCC_3GPP_NBIFOM_Mode avp_PCC_3GPP_NBIFOM_Mode,
- DCC_NONE_Validity_Time avp_DCC_NONE_Validity_Time,
PCC_3GPP_Redirect_Information avp_PCC_3GPP_Redirect_Information,
+ DCC_NONE_Validity_Time avp_DCC_NONE_Validity_Time,
+ DCA_3GPP_Monitoring_UE_VPLMN_Identifier avp_DCA_3GPP_Monitoring_UE_VPLMN_Identifier,
S6_3GPP_Event_Handling avp_S6_3GPP_Event_Handling,
- AAA_3GPP_Tracking_Area_Identity avp_AAA_3GPP_Tracking_Area_Identity,
PCC_3GPP_ToS_Traffic_Class avp_PCC_3GPP_ToS_Traffic_Class,
+ AAA_3GPP_Tracking_Area_Identity avp_AAA_3GPP_Tracking_Area_Identity,
+ MIPv4_NONE_MIP_HA_to_FA_SPI avp_MIPv4_NONE_MIP_HA_to_FA_SPI,
RX_3GPP_Min_Desired_Bandwidth_UL avp_RX_3GPP_Min_Desired_Bandwidth_UL,
AAA_3GPP_UVR_Flags avp_AAA_3GPP_UVR_Flags,
+ DCA_3GPP_PS_Free_Format_Data avp_DCA_3GPP_PS_Free_Format_Data,
CxDx_3GPP_Originating_Request avp_CxDx_3GPP_Originating_Request,
- AAA_3GPP_Subscription_Data_Flags avp_AAA_3GPP_Subscription_Data_Flags,
PCC_3GPP_PDN_Connection_ID avp_PCC_3GPP_PDN_Connection_ID,
+ AAA_3GPP_Subscription_Data_Flags avp_AAA_3GPP_Subscription_Data_Flags,
DNAS_NONE_Framed_IPv6_Route avp_DNAS_NONE_Framed_IPv6_Route,
- AAA_3GPP_DSR_Flags avp_AAA_3GPP_DSR_Flags,
PCC_3GPP_PRA_Remove avp_PCC_3GPP_PRA_Remove,
+ AAA_3GPP_DSR_Flags avp_AAA_3GPP_DSR_Flags,
DCC_NONE_Granted_Service_Unit avp_DCC_NONE_Granted_Service_Unit,
MIPv6_NONE_MIP_Timestamp avp_MIPv6_NONE_MIP_Timestamp,
+ DCA_3GPP_Number_Portability_Routing_Information avp_DCA_3GPP_Number_Portability_Routing_Information,
AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer avp_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer,
AAA_3GPP_Specific_APN_Info avp_AAA_3GPP_Specific_APN_Info,
AAA_3GPP_Terminal_Information avp_AAA_3GPP_Terminal_Information,
CxDx_3GPP_Restoration_Info avp_CxDx_3GPP_Restoration_Info,
BASE_NONE_Product_Name avp_BASE_NONE_Product_Name,
+ MIPv4_NONE_MIP_HA_to_MN_MSA avp_MIPv4_NONE_MIP_HA_to_MN_MSA,
+ DCA_3GPP_Account_Expiration avp_DCA_3GPP_Account_Expiration,
AAA_3GPP_CSG_Id avp_AAA_3GPP_CSG_Id,
DNAS_NONE_Framed_IP_Netmask avp_DNAS_NONE_Framed_IP_Netmask,
GI_3GPP_3GPP_IPv6_DNS_Servers avp_GI_3GPP_3GPP_IPv6_DNS_Servers,
+ AAA_3GPP_SSID avp_AAA_3GPP_SSID,
AAA_3GPP_Call_Barring_Info avp_AAA_3GPP_Call_Barring_Info,
+ DCA_3GPP_BSSID avp_DCA_3GPP_BSSID,
DCC_NONE_Service_Parameter_Info avp_DCC_NONE_Service_Parameter_Info,
- BASE_NONE_Origin_State_Id avp_BASE_NONE_Origin_State_Id,
+ DCA_3GPP_Talk_Burst_Exchange avp_DCA_3GPP_Talk_Burst_Exchange,
+ DCA_3GPP_Variable_Part_Order avp_DCA_3GPP_Variable_Part_Order,
+ DCA_3GPP_Time_Quota_Mechanism avp_DCA_3GPP_Time_Quota_Mechanism,
+ AAA_3GPP_ANID avp_AAA_3GPP_ANID,
+ DCA_3GPP_Monitoring_Event_Report_Number avp_DCA_3GPP_Monitoring_Event_Report_Number,
S6_3GPP_IP_SM_GW_Name avp_S6_3GPP_IP_SM_GW_Name,
+ BASE_NONE_Origin_State_Id avp_BASE_NONE_Origin_State_Id,
RX_3GPP_Media_Sub_Component avp_RX_3GPP_Media_Sub_Component,
+ DCA_3GPP_CN_Operator_Selection_Entity avp_DCA_3GPP_CN_Operator_Selection_Entity,
S6_3GPP_Accuracy avp_S6_3GPP_Accuracy,
PCC_3GPP_Charging_Rule_Remove avp_PCC_3GPP_Charging_Rule_Remove,
+ DCA_3GPP_Originating_IOI avp_DCA_3GPP_Originating_IOI,
RX_3GPP_Min_Requested_Bandwidth_DL avp_RX_3GPP_Min_Requested_Bandwidth_DL,
+ DCA_3GPP_ProSe_Function_PLMN_Identifier avp_DCA_3GPP_ProSe_Function_PLMN_Identifier,
S6_3GPP_Service_Report avp_S6_3GPP_Service_Report,
PCC_3GPP_Tunnel_Information avp_PCC_3GPP_Tunnel_Information,
+ DCA_3GPP_Bearer_Service avp_DCA_3GPP_Bearer_Service,
CxDx_3GPP_Primary_Charging_Collection_Function_Name avp_CxDx_3GPP_Primary_Charging_Collection_Function_Name,
- AAA_3GPP_Time_Zone avp_AAA_3GPP_Time_Zone,
PCC_3GPP_QoS_Rule_Definition avp_PCC_3GPP_QoS_Rule_Definition,
+ AAA_3GPP_Time_Zone avp_AAA_3GPP_Time_Zone,
S6_3GPP_Periodic_Time avp_S6_3GPP_Periodic_Time,
PCC_3GPP_Routing_Rule_Failure_Code avp_PCC_3GPP_Routing_Rule_Failure_Code,
PCC_3GPP_TDF_Destination_Host avp_PCC_3GPP_TDF_Destination_Host,
AAA_3GPP_Local_Group_Id avp_AAA_3GPP_Local_Group_Id,
- AAA_3GPP_Service_Area_Identity avp_AAA_3GPP_Service_Area_Identity,
+ DCA_3GPP_SM_Discharge_Time avp_DCA_3GPP_SM_Discharge_Time,
+ DCA_3GPP_Requestor_PLMN_Identifier avp_DCA_3GPP_Requestor_PLMN_Identifier,
+ DCA_3GPP_IMS_Application_Reference_Identifier avp_DCA_3GPP_IMS_Application_Reference_Identifier,
PCC_3GPP_Charging_Rule_Report avp_PCC_3GPP_Charging_Rule_Report,
+ AAA_3GPP_Service_Area_Identity avp_AAA_3GPP_Service_Area_Identity,
BASE_NONE_User_Name avp_BASE_NONE_User_Name,
AAA_3GPP_UE_PC5_AMBR avp_AAA_3GPP_UE_PC5_AMBR,
CxDx_3GPP_Public_Identity avp_CxDx_3GPP_Public_Identity,
BASE_NONE_Accounting_Sub_Session_Id avp_BASE_NONE_Accounting_Sub_Session_Id,
DNAS_NONE_Acct_Delay_Time avp_DNAS_NONE_Acct_Delay_Time,
+ DCA_3GPP_Local_Sequence_Number avp_DCA_3GPP_Local_Sequence_Number,
CxDx_3GPP_UAR_Flags avp_CxDx_3GPP_UAR_Flags,
AAA_3GPP_Collection_Period_RRM_UMTS avp_AAA_3GPP_Collection_Period_RRM_UMTS,
AAA_3GPP_Operator_Determined_Barring avp_AAA_3GPP_Operator_Determined_Barring,
+ DCA_3GPP_Recipient_Received_Address avp_DCA_3GPP_Recipient_Received_Address,
DNAS_NONE_Tunnel_Server_Endpoint avp_DNAS_NONE_Tunnel_Server_Endpoint,
+ MIPv4_NONE_MIP_Candidate_Home_Agent_Host avp_MIPv4_NONE_MIP_Candidate_Home_Agent_Host,
BASE_NONE_Session_Binding avp_BASE_NONE_Session_Binding,
GI_3GPP_3GPP_IMEISV avp_GI_3GPP_3GPP_IMEISV,
AAA_3GPP_SS_Code avp_AAA_3GPP_SS_Code,
+ DCA_3GPP_DCD_Information avp_DCA_3GPP_DCD_Information,
+ DCA_3GPP_Location_Estimate_Type avp_DCA_3GPP_Location_Estimate_Type,
+ DCA_3GPP_Time_Indicator avp_DCA_3GPP_Time_Indicator,
+ DCA_3GPP_Addressee_Type avp_DCA_3GPP_Addressee_Type,
BASE_NONE_Acct_Multi_Session_Id avp_BASE_NONE_Acct_Multi_Session_Id,
DCC_NONE_Subscription_Id_Data avp_DCC_NONE_Subscription_Id_Data,
+ AAA_3GPP_TWAN_Connectivity_Parameters avp_AAA_3GPP_TWAN_Connectivity_Parameters,
+ DCA_3GPP_Reply_Applic_ID avp_DCA_3GPP_Reply_Applic_ID,
+ DCA_3GPP_Participant_Access_Priority avp_DCA_3GPP_Participant_Access_Priority,
RX_3GPP_RS_Bandwidth avp_RX_3GPP_RS_Bandwidth,
- MIPv6_NONE_MIP_Algorithm_Type avp_MIPv6_NONE_MIP_Algorithm_Type,
S6_3GPP_Reachability_Information avp_S6_3GPP_Reachability_Information,
+ MIPv4_NONE_MIP_Algorithm_Type avp_MIPv4_NONE_MIP_Algorithm_Type,
+ DCA_3GPP_SDP_Session_Description avp_DCA_3GPP_SDP_Session_Description,
RX_3GPP_Extended_Min_Desired_BW_DL avp_RX_3GPP_Extended_Min_Desired_BW_DL,
- AAA_3GPP_Event_Threshold_RSRQ avp_AAA_3GPP_Event_Threshold_RSRQ,
+ DCA_3GPP_Location_Info avp_DCA_3GPP_Location_Info,
PCC_3GPP_APN_Aggregate_Max_Bitrate_UL avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL,
+ AAA_3GPP_Event_Threshold_RSRQ avp_AAA_3GPP_Event_Threshold_RSRQ,
+ DCA_3GPP_LCS_Information avp_DCA_3GPP_LCS_Information,
S6_3GPP_Service_Parameters avp_S6_3GPP_Service_Parameters,
PCC_3GPP_Presence_Reporting_Area_Information avp_PCC_3GPP_Presence_Reporting_Area_Information,
PCC_3GPP_Routing_Rule_Identifier avp_PCC_3GPP_Routing_Rule_Identifier,
+ DCA_3GPP_SMS_Information avp_DCA_3GPP_SMS_Information,
+ DCA_3GPP_ePDG_Address avp_DCA_3GPP_ePDG_Address,
PCC_3GPP_Event_Trigger avp_PCC_3GPP_Event_Trigger,
RX_3GPP_GCS_Identifier avp_RX_3GPP_GCS_Identifier,
MIPv6_NONE_QoS_Capability avp_MIPv6_NONE_QoS_Capability,
- DCC_NONE_G_S_U_Pool_Identifier avp_DCC_NONE_G_S_U_Pool_Identifier,
- AAA_3GPP_Non_IP_PDN_Type_Indicator avp_AAA_3GPP_Non_IP_PDN_Type_Indicator,
PCC_3GPP_ADC_Rule_Install avp_PCC_3GPP_ADC_Rule_Install,
+ AAA_3GPP_Non_IP_PDN_Type_Indicator avp_AAA_3GPP_Non_IP_PDN_Type_Indicator,
+ DCC_NONE_G_S_U_Pool_Identifier avp_DCC_NONE_G_S_U_Pool_Identifier,
+ DCA_3GPP_Outgoing_Session_Id avp_DCA_3GPP_Outgoing_Session_Id,
+ DCA_3GPP_PoC_Controlling_Address avp_DCA_3GPP_PoC_Controlling_Address,
+ DCA_3GPP_Dynamic_Address_Flag avp_DCA_3GPP_Dynamic_Address_Flag,
CxDx_3GPP_Confidentiality_Key avp_CxDx_3GPP_Confidentiality_Key,
PCC_3GPP_Flow_Label avp_PCC_3GPP_Flow_Label,
DNAS_NONE_NAS_Port avp_DNAS_NONE_NAS_Port,
AAA_3GPP_Authentication_Info avp_AAA_3GPP_Authentication_Info,
+ DCA_3GPP_Transcoder_Inserted_Indication avp_DCA_3GPP_Transcoder_Inserted_Indication,
+ DCA_3GPP_SMS_Node avp_DCA_3GPP_SMS_Node,
AAA_3GPP_Trace_Interface_List avp_AAA_3GPP_Trace_Interface_List,
+ DCA_3GPP_SGW_Address avp_DCA_3GPP_SGW_Address,
GI_3GPP_3GPP_Charging_Id avp_GI_3GPP_3GPP_Charging_Id,
DNAS_NONE_CHAP_Algorithm avp_DNAS_NONE_CHAP_Algorithm,
AAA_3GPP_APN_Configuration_Profile avp_AAA_3GPP_APN_Configuration_Profile,
+ DCA_3GPP_Number_Of_Received_Talk_Bursts avp_DCA_3GPP_Number_Of_Received_Talk_Bursts,
+ AAA_3GPP_Full_Network_Name avp_AAA_3GPP_Full_Network_Name,
+ DCA_3GPP_Message_Type avp_DCA_3GPP_Message_Type,
+ DCA_3GPP_APN_Rate_Control_Uplink avp_DCA_3GPP_APN_Rate_Control_Uplink,
GI_3GPP_3GPP_CAMEL_Charging_Info avp_GI_3GPP_3GPP_CAMEL_Charging_Info,
+ DCA_3GPP_From_Address avp_DCA_3GPP_From_Address,
+ AAA_3GPP_TWAG_CP_Address avp_AAA_3GPP_TWAG_CP_Address,
+ DCA_3GPP_PDP_Context_Type avp_DCA_3GPP_PDP_Context_Type,
RX_3GPP_Flows avp_RX_3GPP_Flows,
+ DCA_3GPP_User_Session_Id avp_DCA_3GPP_User_Session_Id,
+ DCA_3GPP_PoC_Change_Time avp_DCA_3GPP_PoC_Change_Time,
+ DCA_3GPP_Privacy_Indicator avp_DCA_3GPP_Privacy_Indicator,
S6_3GPP_CIA_Flags avp_S6_3GPP_CIA_Flags,
RX_3GPP_Extended_Min_Requested_BW_UL avp_RX_3GPP_Extended_Min_Requested_BW_UL,
PCC_3GPP_Monitoring_Time avp_PCC_3GPP_Monitoring_Time,
DCC_NONE_CC_Input_Octets avp_DCC_NONE_CC_Input_Octets,
+ DCA_3GPP_Teleservice avp_DCA_3GPP_Teleservice,
+ DCA_3GPP_Quota_Consumption_Time avp_DCA_3GPP_Quota_Consumption_Time,
S6_3GPP_UE_Reachability_Configuration avp_S6_3GPP_UE_Reachability_Configuration,
BASE_NONE_Destination_Realm avp_BASE_NONE_Destination_Realm,
RX_3GPP_Acceptable_Service_Info avp_RX_3GPP_Acceptable_Service_Info,
PCC_3GPP_Flow_Direction avp_PCC_3GPP_Flow_Direction,
+ DCA_3GPP_ProSe_Reason_For_Cancellation avp_DCA_3GPP_ProSe_Reason_For_Cancellation,
S6_3GPP_Supported_Monitoring_Events avp_S6_3GPP_Supported_Monitoring_Events,
+ DCA_3GPP_CG_Address avp_DCA_3GPP_CG_Address,
+ DCA_3GPP_Radio_Parameter_Set_Values avp_DCA_3GPP_Radio_Parameter_Set_Values,
CxDx_3GPP_SIP_Item_Number avp_CxDx_3GPP_SIP_Item_Number,
PCC_3GPP_Session_Release_Cause avp_PCC_3GPP_Session_Release_Cause,
AAA_3GPP_MDT_User_Consent avp_AAA_3GPP_MDT_User_Consent,
- DNAS_NONE_Login_LAT_Port avp_DNAS_NONE_Login_LAT_Port,
S6_3GPP_HSS_Cause avp_S6_3GPP_HSS_Cause,
- DCC_NONE_G_S_U_Pool_Reference avp_DCC_NONE_G_S_U_Pool_Reference,
+ MIPv6_NONE_MIP6_Home_Link_Prefix avp_MIPv6_NONE_MIP6_Home_Link_Prefix,
+ DNAS_NONE_Login_LAT_Port avp_DNAS_NONE_Login_LAT_Port,
PCC_3GPP_PCSCF_Restoration_Indication avp_PCC_3GPP_PCSCF_Restoration_Indication,
+ DCC_NONE_G_S_U_Pool_Reference avp_DCC_NONE_G_S_U_Pool_Reference,
+ DCA_3GPP_Layer_2_Group_ID avp_DCA_3GPP_Layer_2_Group_ID,
+ DCA_3GPP_Interface_Port avp_DCA_3GPP_Interface_Port,
AAA_3GPP_Subscription_Data_Deletion avp_AAA_3GPP_Subscription_Data_Deletion,
MIPv6_NONE_Chargable_User_Identity avp_MIPv6_NONE_Chargable_User_Identity,
AAA_3GPP_Trace_Collection_Entity avp_AAA_3GPP_Trace_Collection_Entity,
+ DCA_3GPP_AoC_Request_Type avp_DCA_3GPP_AoC_Request_Type,
CxDx_3GPP_Feature_List_ID avp_CxDx_3GPP_Feature_List_ID,
BASE_NONE_Redirect_Host avp_BASE_NONE_Redirect_Host,
AAA_3GPP_Network_Access_Mode avp_AAA_3GPP_Network_Access_Mode,
- DNAS_NONE_ARAP_Zone_Access avp_DNAS_NONE_ARAP_Zone_Access,
DNAS_NONE_Framed_Compression avp_DNAS_NONE_Framed_Compression,
+ DNAS_NONE_ARAP_Zone_Access avp_DNAS_NONE_ARAP_Zone_Access,
GI_3GPP_3GPP_Selection_Mode avp_GI_3GPP_3GPP_Selection_Mode,
DNAS_NONE_QoS_Filter_Rule avp_DNAS_NONE_QoS_Filter_Rule,
AAA_3GPP_Complete_Data_List_Included_Indicator avp_AAA_3GPP_Complete_Data_List_Included_Indicator,
- MIPv6_NONE_MIP_MN_AAA_SPI avp_MIPv6_NONE_MIP_MN_AAA_SPI,
+ MIPv4_NONE_MIP_MN_AAA_SPI avp_MIPv4_NONE_MIP_MN_AAA_SPI,
+ DCA_3GPP_LCS_Client_Name avp_DCA_3GPP_LCS_Client_Name,
GI_3GPP_3GPP_SGSN_Address avp_GI_3GPP_3GPP_SGSN_Address,
- MIPv6_NONE_MIP_MSA_Lifetime avp_MIPv6_NONE_MIP_MSA_Lifetime,
+ DCA_3GPP_Related_IMS_Charging_Identifier avp_DCA_3GPP_Related_IMS_Charging_Identifier,
+ DCA_3GPP_Called_Asserted_Identity avp_DCA_3GPP_Called_Asserted_Identity,
+ DCA_3GPP_TWAG_Address avp_DCA_3GPP_TWAG_Address,
+ MIPv4_NONE_MIP_MSA_Lifetime avp_MIPv4_NONE_MIP_MSA_Lifetime,
+ DCA_3GPP_Talk_Burst_Time avp_DCA_3GPP_Talk_Burst_Time,
+ DCA_3GPP_Token_Text avp_DCA_3GPP_Token_Text,
+ DCA_3GPP_Rate_Control_Time_Unit avp_DCA_3GPP_Rate_Control_Time_Unit,
GI_3GPP_External_Identifier avp_GI_3GPP_External_Identifier,
+ DCA_3GPP_Reason_Header avp_DCA_3GPP_Reason_Header,
+ AAA_3GPP_WLCP_Key avp_AAA_3GPP_WLCP_Key,
S6_3GPP_Reachability_Type avp_S6_3GPP_Reachability_Type,
- DNAS_NONE_Tunnel_Private_Group_Id avp_DNAS_NONE_Tunnel_Private_Group_Id,
+ DCA_3GPP_SIP_Request_Timestamp avp_DCA_3GPP_SIP_Request_Timestamp,
DNAS_NONE_Framed_Route avp_DNAS_NONE_Framed_Route,
+ DNAS_NONE_Tunnel_Private_Group_Id avp_DNAS_NONE_Tunnel_Private_Group_Id,
DCC_NONE_CC_Request_Type avp_DCC_NONE_CC_Request_Type,
+ DCA_3GPP_ProSe_Source_IP_Address avp_DCA_3GPP_ProSe_Source_IP_Address,
S6_3GPP_Type_Of_External_Identifier avp_S6_3GPP_Type_Of_External_Identifier,
PCC_3GPP_Event_Report_Indication avp_PCC_3GPP_Event_Report_Indication,
AAA_3GPP_MDT_Configuration avp_AAA_3GPP_MDT_Configuration,
PCC_3GPP_Usage_Monitoring_Report avp_PCC_3GPP_Usage_Monitoring_Report,
+ DCA_3GPP_Number_Of_Participants avp_DCA_3GPP_Number_Of_Participants,
+ DCA_3GPP_MSC_Address avp_DCA_3GPP_MSC_Address,
CxDx_3GPP_Priviledged_Sender_Indication avp_CxDx_3GPP_Priviledged_Sender_Indication,
AAA_3GPP_Adjacent_Access_Restriction_Data avp_AAA_3GPP_Adjacent_Access_Restriction_Data,
+ DCA_3GPP_AoC_Service_Obligatory_Type avp_DCA_3GPP_AoC_Service_Obligatory_Type,
AAA_3GPP_RAT_Frequency_Selection_Priority_ID avp_AAA_3GPP_RAT_Frequency_Selection_Priority_ID,
+ DCA_3GPP_Time_First_Usage avp_DCA_3GPP_Time_First_Usage,
CxDx_3GPP_Reason_Info avp_CxDx_3GPP_Reason_Info,
- AAA_3GPP_CLR_Flags avp_AAA_3GPP_CLR_Flags,
PCC_3GPP_Default_EPS_Bearer_QoS avp_PCC_3GPP_Default_EPS_Bearer_QoS,
+ AAA_3GPP_CLR_Flags avp_AAA_3GPP_CLR_Flags,
AAA_3GPP_ULR_Flags avp_AAA_3GPP_ULR_Flags,
- DNAS_NONE_Tunnel_Client_Auth_Id avp_DNAS_NONE_Tunnel_Client_Auth_Id,
- DNAS_NONE_Calling_Station_Id avp_DNAS_NONE_Calling_Station_Id,
+ DCA_3GPP_Originating_SCCP_Address avp_DCA_3GPP_Originating_SCCP_Address,
AAA_3GPP_ICS_Indicator avp_AAA_3GPP_ICS_Indicator,
+ DNAS_NONE_Calling_Station_Id avp_DNAS_NONE_Calling_Station_Id,
+ DNAS_NONE_Tunnel_Client_Auth_Id avp_DNAS_NONE_Tunnel_Client_Auth_Id,
DCC_NONE_Currency_Code avp_DCC_NONE_Currency_Code,
AAA_3GPP_Cancellation_Type avp_AAA_3GPP_Cancellation_Type,
BASE_NONE_E2E_Sequence avp_BASE_NONE_E2E_Sequence,
BASE_NONE_Origin_Realm avp_BASE_NONE_Origin_Realm,
AAA_3GPP_PDN_Type avp_AAA_3GPP_PDN_Type,
+ DCA_3GPP_Scale_Factor avp_DCA_3GPP_Scale_Factor,
+ DCA_3GPP_IM_Information avp_DCA_3GPP_IM_Information,
DNAS_NONE_Prompt avp_DNAS_NONE_Prompt,
+ DCA_3GPP_SDP_Offer_Timestamp avp_DCA_3GPP_SDP_Offer_Timestamp,
+ AAA_3GPP_PPR_Flags avp_AAA_3GPP_PPR_Flags,
+ DCA_3GPP_MM_Content_Type avp_DCA_3GPP_MM_Content_Type,
+ DCA_3GPP_CPDT_Information avp_DCA_3GPP_CPDT_Information,
GI_3GPP_3GPP_GGSN_IPv6_Address avp_GI_3GPP_3GPP_GGSN_IPv6_Address,
+ AAA_3GPP_DER_S6b_Flags avp_AAA_3GPP_DER_S6b_Flags,
+ DCA_3GPP_SCS_Realm avp_DCA_3GPP_SCS_Realm,
+ DCA_3GPP_LCS_Requestor_Id avp_DCA_3GPP_LCS_Requestor_Id,
RX_3GPP_Access_Network_Charging_Identifier avp_RX_3GPP_Access_Network_Charging_Identifier,
DCC_NONE_Redirect_Server avp_DCC_NONE_Redirect_Server,
S6_3GPP_AESE_Communication_Pattern_Config_Status avp_S6_3GPP_AESE_Communication_Pattern_Config_Status,
+ DCA_3GPP_PoC_User_Role_info_Units avp_DCA_3GPP_PoC_User_Role_info_Units,
+ DCA_3GPP_Variable_Part avp_DCA_3GPP_Variable_Part,
+ DCA_3GPP_ProSe_3rd_Party_Application_ID avp_DCA_3GPP_ProSe_3rd_Party_Application_ID,
S6_3GPP_Enhanced_Coverage_Restriction_Data avp_S6_3GPP_Enhanced_Coverage_Restriction_Data,
PCC_3GPP_Bearer_Operation avp_PCC_3GPP_Bearer_Operation,
AAA_3GPP_Current_Location_Retrieved avp_AAA_3GPP_Current_Location_Retrieved,
RX_3GPP_Pre_emption_Control_Info avp_RX_3GPP_Pre_emption_Control_Info,
PCC_3GPP_TDF_Application_Instance_Identifier avp_PCC_3GPP_TDF_Application_Instance_Identifier,
+ DCA_3GPP_SM_Device_Trigger_Information avp_DCA_3GPP_SM_Device_Trigger_Information,
+ DCA_3GPP_Service_Information avp_DCA_3GPP_Service_Information,
BASE_NONE_Acct_Interim_Interval avp_BASE_NONE_Acct_Interim_Interval,
RX_3GPP_Media_Component_Number avp_RX_3GPP_Media_Component_Number,
CxDx_3GPP_Path avp_CxDx_3GPP_Path,
- AAA_3GPP_Event_Threshold_Event_1F avp_AAA_3GPP_Event_Threshold_Event_1F,
PCC_3GPP_Packet_Filter_Usage avp_PCC_3GPP_Packet_Filter_Usage,
+ AAA_3GPP_Event_Threshold_Event_1F avp_AAA_3GPP_Event_Threshold_Event_1F,
S6_3GPP_MONTE_Location_Type avp_S6_3GPP_MONTE_Location_Type,
+ DCA_3GPP_Inter_Operator_Identifier avp_DCA_3GPP_Inter_Operator_Identifier,
AAA_3GPP_RDS_Indicator avp_AAA_3GPP_RDS_Indicator,
+ DCA_3GPP_Proximity_Cancellation_Timestamp avp_DCA_3GPP_Proximity_Cancellation_Timestamp,
+ DCA_3GPP_MMTel_SService_Type avp_DCA_3GPP_MMTel_SService_Type,
CxDx_3GPP_Optional_Capability avp_CxDx_3GPP_Optional_Capability,
- AAA_3GPP_Reporting_Trigger avp_AAA_3GPP_Reporting_Trigger,
PCC_3GPP_Tunnel_Header_Length avp_PCC_3GPP_Tunnel_Header_Length,
+ AAA_3GPP_Reporting_Trigger avp_AAA_3GPP_Reporting_Trigger,
PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate avp_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate,
CxDx_3GPP_Secondary_Event_Charging_Function_Name avp_CxDx_3GPP_Secondary_Event_Charging_Function_Name,
AAA_3GPP_Group_PLMN_Id avp_AAA_3GPP_Group_PLMN_Id,
+ DCA_3GPP_Reply_Path_Requested avp_DCA_3GPP_Reply_Path_Requested,
AAA_3GPP_User_Id avp_AAA_3GPP_User_Id,
+ DCA_3GPP_Serving_Node_Type avp_DCA_3GPP_Serving_Node_Type,
DNAS_NONE_Login_LAT_Node avp_DNAS_NONE_Login_LAT_Node,
DNAS_NONE_Originating_Line_Info avp_DNAS_NONE_Originating_Line_Info,
DCC_NONE_Exponent avp_DCC_NONE_Exponent,
MIPv6_NONE_MIP_Authenticator avp_MIPv6_NONE_MIP_Authenticator,
- DNAS_NONE_Accounting_Input_Octets avp_DNAS_NONE_Accounting_Input_Octets,
AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info avp_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info,
+ MIPv4_NONE_Accounting_Input_Octets avp_MIPv4_NONE_Accounting_Input_Octets,
AAA_3GPP_EPS_User_State avp_AAA_3GPP_EPS_User_State,
BASE_NONE_Origin_Host avp_BASE_NONE_Origin_Host,
+ AAA_3GPP_Access_Authorization_Flags avp_AAA_3GPP_Access_Authorization_Flags,
+ DCA_3GPP_PDP_Address avp_DCA_3GPP_PDP_Address,
+ DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator avp_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator,
+ DCA_3GPP_NNI_Information avp_DCA_3GPP_NNI_Information,
+ DCA_3GPP_Location_Estimate avp_DCA_3GPP_Location_Estimate,
+ DCA_3GPP_Offline_Charging avp_DCA_3GPP_Offline_Charging,
RX_3GPP_Retry_Interval avp_RX_3GPP_Retry_Interval,
BASE_NONE_Accounting_Session_Id avp_BASE_NONE_Accounting_Session_Id,
+ DCA_3GPP_Additional_Content_Information avp_DCA_3GPP_Additional_Content_Information,
DCC_NONE_Restriction_Filter_Rule avp_DCC_NONE_Restriction_Filter_Rule,
+ DCA_3GPP_Cause_Code avp_DCA_3GPP_Cause_Code,
+ AAA_3GPP_TWAN_Connection_Mode avp_AAA_3GPP_TWAN_Connection_Mode,
PCC_3GPP_Packet_Filter_Identifier avp_PCC_3GPP_Packet_Filter_Identifier,
+ DCA_3GPP_Address_Data avp_DCA_3GPP_Address_Data,
S6_3GPP_SCEF_Reference_ID avp_S6_3GPP_SCEF_Reference_ID,
+ DCA_3GPP_Content_Type avp_DCA_3GPP_Content_Type,
PCC_3GPP_Resource_Release_Notification avp_PCC_3GPP_Resource_Release_Notification,
PCC_3GPP_ADC_Rule_Name avp_PCC_3GPP_ADC_Rule_Name,
+ DCA_3GPP_ProSe_Function_IP_Address avp_DCA_3GPP_ProSe_Function_IP_Address,
+ PCC_3GPP_Guaranteed_Bitrate_DL avp_PCC_3GPP_Guaranteed_Bitrate_DL,
BASE_NONE_Disconnect_Cause avp_BASE_NONE_Disconnect_Cause,
AAA_3GPP_Error_Diagnostic avp_AAA_3GPP_Error_Diagnostic,
- PCC_3GPP_Guaranteed_Bitrate_DL avp_PCC_3GPP_Guaranteed_Bitrate_DL,
RX_3GPP_Extended_Max_Supported_BW_UL avp_RX_3GPP_Extended_Max_Supported_BW_UL,
- DCC_NONE_CC_Total_Octets avp_DCC_NONE_CC_Total_Octets,
PCC_3GPP_UDP_Source_Port avp_PCC_3GPP_UDP_Source_Port,
+ DCC_NONE_CC_Total_Octets avp_DCC_NONE_CC_Total_Octets,
BASE_NONE_Accounting_Record_Type avp_BASE_NONE_Accounting_Record_Type,
+ DCA_3GPP_SMS_Result avp_DCA_3GPP_SMS_Result,
+ DCA_3GPP_MMS_Information avp_DCA_3GPP_MMS_Information,
CxDx_3GPP_From_SIP_Header avp_CxDx_3GPP_From_SIP_Header,
- AAA_3GPP_SIPTO_Local_Network_Permission avp_AAA_3GPP_SIPTO_Local_Network_Permission,
PCC_3GPP_Routing_Rule_Definition avp_PCC_3GPP_Routing_Rule_Definition,
- DCC_NONE_Value_Digits avp_DCC_NONE_Value_Digits,
+ AAA_3GPP_SIPTO_Local_Network_Permission avp_AAA_3GPP_SIPTO_Local_Network_Permission,
+ DCA_3GPP_CUG_Information avp_DCA_3GPP_CUG_Information,
AAA_3GPP_VPLMN_Dynamic_Address_Allowed avp_AAA_3GPP_VPLMN_Dynamic_Address_Allowed,
+ DCC_NONE_Value_Digits avp_DCC_NONE_Value_Digits,
+ MIPv4_NONE_MIP_MN_AAA_Auth avp_MIPv4_NONE_MIP_MN_AAA_Auth,
BASE_NONE_Acct_Application_Id avp_BASE_NONE_Acct_Application_Id,
+ DCA_3GPP_Associated_Party_Address avp_DCA_3GPP_Associated_Party_Address,
CxDx_3GPP_SIP_Authenticate avp_CxDx_3GPP_SIP_Authenticate,
AAA_3GPP_Service_Type avp_AAA_3GPP_Service_Type,
AAA_3GPP_Immediate_Response_Preferred avp_AAA_3GPP_Immediate_Response_Preferred,
- DNAS_NONE_Login_IPv6_Host avp_DNAS_NONE_Login_IPv6_Host,
DNAS_NONE_Framed_Appletalk_Zone avp_DNAS_NONE_Framed_Appletalk_Zone,
- DCC_NONE_Final_Unit_Indication avp_DCC_NONE_Final_Unit_Indication,
+ DNAS_NONE_Login_IPv6_Host avp_DNAS_NONE_Login_IPv6_Host,
+ DCA_3GPP_Local_GW_Inserted_Indication avp_DCA_3GPP_Local_GW_Inserted_Indication,
AAA_3GPP_XRES avp_AAA_3GPP_XRES,
+ DCC_NONE_Final_Unit_Indication avp_DCC_NONE_Final_Unit_Indication,
+ DCA_3GPP_Deferred_Location_Event_Type avp_DCA_3GPP_Deferred_Location_Event_Type,
GI_3GPP_3GPP_IMSI avp_GI_3GPP_3GPP_IMSI,
AAA_3GPP_User_State avp_AAA_3GPP_User_State,
+ MIPv4_NONE_MIP_MN_to_HA_MSA avp_MIPv4_NONE_MIP_MN_to_HA_MSA,
BASE_NONE_Result_Code avp_BASE_NONE_Result_Code,
+ DCA_3GPP_Envelope avp_DCA_3GPP_Envelope,
+ DCA_3GPP_Monitoring_Event_Configuration_Activity avp_DCA_3GPP_Monitoring_Event_Configuration_Activity,
+ DCA_3GPP_IMS_Communication_Service_Identifier avp_DCA_3GPP_IMS_Communication_Service_Identifier,
DNAS_NONE_Framed_IP_Address avp_DNAS_NONE_Framed_IP_Address,
+ AAA_3GPP_Trust_Relationship_Update avp_AAA_3GPP_Trust_Relationship_Update,
+ DCA_3GPP_APN_Rate_Control_Downlink avp_DCA_3GPP_APN_Rate_Control_Downlink,
+ DCA_3GPP_Session_Direction avp_DCA_3GPP_Session_Direction,
S6_3GPP_IP_SM_GW_Realm avp_S6_3GPP_IP_SM_GW_Realm,
+ DCA_3GPP_Monitoring_UE_Identifier avp_DCA_3GPP_Monitoring_UE_Identifier,
S6_3GPP_Reference_ID_Validity_Time avp_S6_3GPP_Reference_ID_Validity_Time,
- AAA_3GPP_E_UTRAN_Cell_Global_Identity avp_AAA_3GPP_E_UTRAN_Cell_Global_Identity,
PCC_3GPP_TFT_Packet_Filter_Information avp_PCC_3GPP_TFT_Packet_Filter_Information,
+ AAA_3GPP_E_UTRAN_Cell_Global_Identity avp_AAA_3GPP_E_UTRAN_Cell_Global_Identity,
RX_3GPP_Min_Desired_Bandwidth_DL avp_RX_3GPP_Min_Desired_Bandwidth_DL,
+ DCA_3GPP_Transmitter_Info avp_DCA_3GPP_Transmitter_Info,
S6_3GPP_Group_Reporting_Guard_Timer avp_S6_3GPP_Group_Reporting_Guard_Timer,
+ DCA_3GPP_PS_Furnish_Charging_Information avp_DCA_3GPP_PS_Furnish_Charging_Information,
CxDx_3GPP_Associated_Identities avp_CxDx_3GPP_Associated_Identities,
- BASE_NONE_Auth_Session_State avp_BASE_NONE_Auth_Session_State,
PCC_3GPP_Session_Linking_Indicator avp_PCC_3GPP_Session_Linking_Indicator,
+ BASE_NONE_Auth_Session_State avp_BASE_NONE_Auth_Session_State,
S6_3GPP_Maximum_Number_of_Reports avp_S6_3GPP_Maximum_Number_of_Reports,
PCC_3GPP_PRA_Install avp_PCC_3GPP_PRA_Install,
AAA_3GPP_V2X_Permission avp_AAA_3GPP_V2X_Permission,
- AAA_3GPP_LIPA_Permission avp_AAA_3GPP_LIPA_Permission,
+ DCA_3GPP_ProSe_Range_Class avp_DCA_3GPP_ProSe_Range_Class,
+ DCA_3GPP_Carrier_Select_Routing_Information avp_DCA_3GPP_Carrier_Select_Routing_Information,
PCC_3GPP_QoS_Negotiation avp_PCC_3GPP_QoS_Negotiation,
+ AAA_3GPP_LIPA_Permission avp_AAA_3GPP_LIPA_Permission,
CxDx_3GPP_SIP_Auth_Data_Item avp_CxDx_3GPP_SIP_Auth_Data_Item,
AAA_3GPP_3GPP2_MEID avp_AAA_3GPP_3GPP2_MEID,
+ MIPv4_NONE_MIP_FA_to_MN_MSA avp_MIPv4_NONE_MIP_FA_to_MN_MSA,
AAA_3GPP_Subscription_Data avp_AAA_3GPP_Subscription_Data,
CxDx_3GPP_Multiple_Registration_Indication avp_CxDx_3GPP_Multiple_Registration_Indication,
- BASE_NONE_Vendor_Specific_Application_Id avp_BASE_NONE_Vendor_Specific_Application_Id,
AAA_3GPP_WLAN_offloadability_UTRAN avp_AAA_3GPP_WLAN_offloadability_UTRAN,
+ BASE_NONE_Vendor_Specific_Application_Id avp_BASE_NONE_Vendor_Specific_Application_Id,
+ DCA_3GPP_IMSI_Unauthenticated_Flag avp_DCA_3GPP_IMSI_Unauthenticated_Flag,
+ DCA_3GPP_Interface_Id avp_DCA_3GPP_Interface_Id,
AAA_3GPP_CSG_Subscription_Data avp_AAA_3GPP_CSG_Subscription_Data,
+ DCA_3GPP_Diagnostics avp_DCA_3GPP_Diagnostics,
MIPv6_NONE_Service_Selection avp_MIPv6_NONE_Service_Selection,
AAA_3GPP_TS_Code avp_AAA_3GPP_TS_Code,
DNAS_NONE_Tunnel_Client_Endpoint avp_DNAS_NONE_Tunnel_Client_Endpoint,
+ AAA_3GPP_AN_Trusted avp_AAA_3GPP_AN_Trusted,
+ DCA_3GPP_Monitoring_Event_Funtionality avp_DCA_3GPP_Monitoring_Event_Funtionality,
+ DCA_3GPP_Aux_Applic_Info avp_DCA_3GPP_Aux_Applic_Info,
+ MIPv4_NONE_MIP_Nonce avp_MIPv4_NONE_MIP_Nonce,
S6_3GPP_IP_SM_GW_Number avp_S6_3GPP_IP_SM_GW_Number,
+ AAA_3GPP_AAR_Flags avp_AAA_3GPP_AAR_Flags,
+ DCA_3GPP_LCS_Client_External_ID avp_DCA_3GPP_LCS_Client_External_ID,
+ DCA_3GPP_VLR_Number avp_DCA_3GPP_VLR_Number,
PCC_3GPP_Charging_Rule_Install avp_PCC_3GPP_Charging_Rule_Install,
RX_3GPP_Rx_Request_Type avp_RX_3GPP_Rx_Request_Type,
S6_3GPP_NIDD_Authorization_Response avp_S6_3GPP_NIDD_Authorization_Response,
+ DCA_3GPP_Outgoing_Trunk_Group_Id avp_DCA_3GPP_Outgoing_Trunk_Group_Id,
+ AAA_3GPP_Transport_Access_Type avp_AAA_3GPP_Transport_Access_Type,
DCC_NONE_Subscription_Id avp_DCC_NONE_Subscription_Id,
- AAA_3GPP_VPLMN_CSG_Subscription_Data avp_AAA_3GPP_VPLMN_CSG_Subscription_Data,
PCC_3GPP_QoS_Rule_Remove avp_PCC_3GPP_QoS_Rule_Remove,
+ AAA_3GPP_VPLMN_CSG_Subscription_Data avp_AAA_3GPP_VPLMN_CSG_Subscription_Data,
+ DCA_3GPP_Message_Body avp_DCA_3GPP_Message_Body,
S6_3GPP_Communication_Duration_Time avp_S6_3GPP_Communication_Duration_Time,
PCC_3GPP_Access_Availability_Change_Reason avp_PCC_3GPP_Access_Availability_Change_Reason,
PCC_3GPP_TDF_Application_Identifier avp_PCC_3GPP_TDF_Application_Identifier,
+ DCA_3GPP_Requested_PLMN_Identifier avp_DCA_3GPP_Requested_PLMN_Identifier,
AAA_3GPP_Location_Area_Identity avp_AAA_3GPP_Location_Area_Identity,
RX_3GPP_Media_Component_Status avp_RX_3GPP_Media_Component_Status,
AAA_3GPP_eDRX_Cycle_Length_Value avp_AAA_3GPP_eDRX_Cycle_Length_Value,
+ MIPv4_NONE_MIP_FA_Challenge avp_MIPv4_NONE_MIP_FA_Challenge,
CxDx_3GPP_Visited_Network_Identifier avp_CxDx_3GPP_Visited_Network_Identifier,
S6_3GPP_RIR_Flags avp_S6_3GPP_RIR_Flags,
- AAA_3GPP_Collection_Period_RRM_LTE avp_AAA_3GPP_Collection_Period_RRM_LTE,
+ DCA_3GPP_Volume_Quota_Threshold avp_DCA_3GPP_Volume_Quota_Threshold,
+ DCA_3GPP_Incremental_Cost avp_DCA_3GPP_Incremental_Cost,
PCC_3GPP_Usage_Monitoring_Level avp_PCC_3GPP_Usage_Monitoring_Level,
- AAA_3GPP_Subscriber_Status avp_AAA_3GPP_Subscriber_Status,
+ AAA_3GPP_Collection_Period_RRM_LTE avp_AAA_3GPP_Collection_Period_RRM_LTE,
PCC_3GPP_Extended_APN_AMBR_UL avp_PCC_3GPP_Extended_APN_AMBR_UL,
+ AAA_3GPP_Subscriber_Status avp_AAA_3GPP_Subscriber_Status,
CxDx_3GPP_Identity_with_Emergency_Registration avp_CxDx_3GPP_Identity_with_Emergency_Registration,
+ DCA_3GPP_Originator_Received_Address avp_DCA_3GPP_Originator_Received_Address,
+ DCA_3GPP_AoC_Service avp_DCA_3GPP_AoC_Service,
DCC_NONE_Tariff_Change_Usage avp_DCC_NONE_Tariff_Change_Usage,
AAA_3GPP_LCS_PrivacyException avp_AAA_3GPP_LCS_PrivacyException,
AAA_3GPP_QoS_Subscribed avp_AAA_3GPP_QoS_Subscribed,
DNAS_NONE_NAS_IP_Address avp_DNAS_NONE_NAS_IP_Address,
+ DCA_3GPP_Variable_Part_Value avp_DCA_3GPP_Variable_Part_Value,
+ DCA_3GPP_Read_Reply_Report_Requested avp_DCA_3GPP_Read_Reply_Report_Requested,
+ DCA_3GPP_Event_Charging_TimeStamp avp_DCA_3GPP_Event_Charging_TimeStamp,
RX_3GPP_RR_Bandwidth avp_RX_3GPP_RR_Bandwidth,
- DCC_NONE_Service_Context_Id avp_DCC_NONE_Service_Context_Id,
DNAS_NONE_CHAP_Auth avp_DNAS_NONE_CHAP_Auth,
+ DCC_NONE_Service_Context_Id avp_DCC_NONE_Service_Context_Id,
+ MIPv4_NONE_MIP_Authenticator_Length avp_MIPv4_NONE_MIP_Authenticator_Length,
+ DCA_3GPP_SDP_TimeStamps avp_DCA_3GPP_SDP_TimeStamps,
+ DCA_3GPP_IMS_Charging_Identifier avp_DCA_3GPP_IMS_Charging_Identifier,
+ AAA_3GPP_MIP_FA_RK_SPI avp_AAA_3GPP_MIP_FA_RK_SPI,
+ DCA_3GPP_Related_Trigger avp_DCA_3GPP_Related_Trigger,
PCC_3GPP_APN_Aggregate_Max_Bitrate_DL avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL,
S6_3GPP_SCS_Identity avp_S6_3GPP_SCS_Identity,
+ DCA_3GPP_LCS_Name_String avp_DCA_3GPP_LCS_Name_String,
RX_3GPP_Access_Network_Charging_Address avp_RX_3GPP_Access_Network_Charging_Address,
PCC_3GPP_Presence_Reporting_Area_Identifier avp_PCC_3GPP_Presence_Reporting_Area_Identifier,
BASE_NONE_Inband_Security_Id avp_BASE_NONE_Inband_Security_Id,
+ DCA_3GPP_ISUP_Cause_Value avp_DCA_3GPP_ISUP_Cause_Value,
PCC_3GPP_Charging_Rule_Name avp_PCC_3GPP_Charging_Rule_Name,
RX_3GPP_Ip_Domain_Id avp_RX_3GPP_Ip_Domain_Id,
- AAA_3GPP_UE_Usage_Type avp_AAA_3GPP_UE_Usage_Type,
PCC_3GPP_TDF_IP_Address avp_PCC_3GPP_TDF_IP_Address,
+ AAA_3GPP_UE_Usage_Type avp_AAA_3GPP_UE_Usage_Type,
S6_3GPP_Enhanced_Coverage_Restriction avp_S6_3GPP_Enhanced_Coverage_Restriction,
+ DCA_3GPP_Charged_Party avp_DCA_3GPP_Charged_Party,
+ DCA_3GPP_PDN_Connection_Charging_ID avp_DCA_3GPP_PDN_Connection_Charging_ID,
CxDx_3GPP_User_Data_Already_Available avp_CxDx_3GPP_User_Data_Already_Available,
- AAA_3GPP_MME_Number_for_MT_SMS avp_AAA_3GPP_MME_Number_for_MT_SMS,
PCC_3GPP_Security_Parameter_Index avp_PCC_3GPP_Security_Parameter_Index,
- DCC_NONE_CC_Correlation_Id avp_DCC_NONE_CC_Correlation_Id,
+ AAA_3GPP_MME_Number_for_MT_SMS avp_AAA_3GPP_MME_Number_for_MT_SMS,
PCC_3GPP_Traffic_Steering_Policy_Identifier_UL avp_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL,
+ DCC_NONE_CC_Correlation_Id avp_DCC_NONE_CC_Correlation_Id,
+ MIPv4_NONE_MIP_Home_Agent_Host avp_MIPv4_NONE_MIP_Home_Agent_Host,
BASE_NONE_Route_Record avp_BASE_NONE_Route_Record,
+ DCA_3GPP_SM_User_Data_Header avp_DCA_3GPP_SM_User_Data_Header,
AAA_3GPP_Carrier_Frequency avp_AAA_3GPP_Carrier_Frequency,
+ DCA_3GPP_MMTel_Information avp_DCA_3GPP_MMTel_Information,
CxDx_3GPP_Mandatory_Capability avp_CxDx_3GPP_Mandatory_Capability,
AAA_3GPP_Trace_NE_Type_List avp_AAA_3GPP_Trace_NE_Type_List,
+ DCA_3GPP_Charging_Characteristics_Selection_Mode avp_DCA_3GPP_Charging_Characteristics_Selection_Mode,
DNAS_NONE_Port_Limit avp_DNAS_NONE_Port_Limit,
+ MIPv6_NONE_MIP6_Feature_Vector avp_MIPv6_NONE_MIP6_Feature_Vector,
DCC_NONE_Multiple_Services_Credit_Control avp_DCC_NONE_Multiple_Services_Credit_Control,
AAA_3GPP_All_APN_Configurations_Included_Indicator avp_AAA_3GPP_All_APN_Configurations_Included_Indicator,
AAA_3GPP_NOR_Flags avp_AAA_3GPP_NOR_Flags,
+ DCA_3GPP_Message_ID avp_DCA_3GPP_Message_ID,
GI_3GPP_3GPP_MS_TimeZone avp_GI_3GPP_3GPP_MS_TimeZone,
AAA_3GPP_External_Client avp_AAA_3GPP_External_Client,
+ DCA_3GPP_Charge_Reason_Code avp_DCA_3GPP_Charge_Reason_Code,
BASE_NONE_Authorization_Lifetime avp_BASE_NONE_Authorization_Lifetime,
+ AAA_3GPP_TWAN_PCO avp_AAA_3GPP_TWAN_PCO,
+ DCA_3GPP_PoC_Change_Conditions avp_DCA_3GPP_PoC_Change_Conditions,
+ DCA_3GPP_Language avp_DCA_3GPP_Language,
+ RX_3GPP_Extended_Min_Requested_BW_DL avp_RX_3GPP_Extended_Min_Requested_BW_DL,
DNAS_NONE_ARAP_Features avp_DNAS_NONE_ARAP_Features,
DNAS_NONE_Framed_MTU avp_DNAS_NONE_Framed_MTU,
- RX_3GPP_Extended_Min_Requested_BW_DL avp_RX_3GPP_Extended_Min_Requested_BW_DL,
+ DCA_3GPP_Unit_Quota_Threshold avp_DCA_3GPP_Unit_Quota_Threshold,
DNAS_NONE_Accounting_Auth_Method avp_DNAS_NONE_Accounting_Auth_Method,
+ MIPv4_NONE_MIP_Authenticator_Offset avp_MIPv4_NONE_MIP_Authenticator_Offset,
+ DCA_3GPP_MBMS_Information avp_DCA_3GPP_MBMS_Information,
+ DCA_3GPP_Bearer_Capability avp_DCA_3GPP_Bearer_Capability,
RX_3GPP_Service_URN avp_RX_3GPP_Service_URN,
S6_3GPP_Supported_Services avp_S6_3GPP_Supported_Services,
- DNAS_NONE_Accounting_Output_Packets avp_DNAS_NONE_Accounting_Output_Packets,
- AAA_3GPP_Relay_Node_Indicator avp_AAA_3GPP_Relay_Node_Indicator,
+ DCA_3GPP_SDP_Media_Description avp_DCA_3GPP_SDP_Media_Description,
+ MIPv4_NONE_Accounting_Output_Packets avp_MIPv4_NONE_Accounting_Output_Packets,
+ DCA_3GPP_Radio_Parameter_Set_Info avp_DCA_3GPP_Radio_Parameter_Set_Info,
PCC_3GPP_Rule_DeActivation_Time avp_PCC_3GPP_Rule_DeActivation_Time,
+ AAA_3GPP_Relay_Node_Indicator avp_AAA_3GPP_Relay_Node_Indicator,
S6_3GPP_T4_Data avp_S6_3GPP_T4_Data,
PCC_3GPP_Fixed_User_Location_Info avp_PCC_3GPP_Fixed_User_Location_Info,
+ DCA_3GPP_Coverage_Status avp_DCA_3GPP_Coverage_Status,
PCC_3GPP_Online avp_PCC_3GPP_Online,
PCC_3GPP_ADC_Rule_Base_Name avp_PCC_3GPP_ADC_Rule_Base_Name,
AAA_3GPP_SCEF_Realm avp_AAA_3GPP_SCEF_Realm,
+ DCA_3GPP_MBMS_Charged_Party avp_DCA_3GPP_MBMS_Charged_Party,
S6_3GPP_Requested_Validity_Time avp_S6_3GPP_Requested_Validity_Time,
DCC_NONE_CC_Request_Number avp_DCC_NONE_CC_Request_Number,
+ DCA_3GPP_AoC_Information avp_DCA_3GPP_AoC_Information,
CxDx_3GPP_Supported_Features avp_CxDx_3GPP_Supported_Features,
AAA_3GPP_Local_Time_Zone avp_AAA_3GPP_Local_Time_Zone,
AAA_3GPP_GERAN_Vector avp_AAA_3GPP_GERAN_Vector,
CxDx_3GPP_Call_ID_SIP_Header avp_CxDx_3GPP_Call_ID_SIP_Header,
+ DCA_3GPP_Online_Charging_Flag avp_DCA_3GPP_Online_Charging_Flag,
+ DCA_3GPP_Number_of_Messages_Sent avp_DCA_3GPP_Number_of_Messages_Sent,
AAA_3GPP_EPS_Subscribed_QoS_Profile avp_AAA_3GPP_EPS_Subscribed_QoS_Profile,
GI_3GPP_3GPP_Session_Stop_Indicator avp_GI_3GPP_3GPP_Session_Stop_Indicator,
AAA_3GPP_GPRS_Subscription_Data avp_AAA_3GPP_GPRS_Subscription_Data,
GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile avp_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile,
+ DCA_3GPP_Access_Transfer_Type avp_DCA_3GPP_Access_Transfer_Type,
DNAS_NONE_Called_Station_Id avp_DNAS_NONE_Called_Station_Id,
+ DCA_3GPP_Inter_UE_Transfer avp_DCA_3GPP_Inter_UE_Transfer,
DCC_NONE_Cost_Unit avp_DCC_NONE_Cost_Unit,
BASE_NONE_Accounting_Realtime_Required avp_BASE_NONE_Accounting_Realtime_Required,
BASE_NONE_Termination_Cause avp_BASE_NONE_Termination_Cause,
+ DCA_3GPP_Received_Talk_Burst_Volume avp_DCA_3GPP_Received_Talk_Burst_Volume,
+ DCA_3GPP_Rate_Control_Max_Rate avp_DCA_3GPP_Rate_Control_Max_Rate,
+ DCA_3GPP_Class_Identifier avp_DCA_3GPP_Class_Identifier,
GI_3GPP_3GPP_Allocate_IP_Type avp_GI_3GPP_3GPP_Allocate_IP_Type,
+ AAA_3GPP_SM_Back_Off_Timer avp_AAA_3GPP_SM_Back_Off_Timer,
RX_3GPP_Specific_Action avp_RX_3GPP_Specific_Action,
+ S6_3GPP_Maximum_Detection_Time avp_S6_3GPP_Maximum_Detection_Time,
DNAS_NONE_Login_TCP_Port avp_DNAS_NONE_Login_TCP_Port,
DNAS_NONE_Password_Retry avp_DNAS_NONE_Password_Retry,
- S6_3GPP_Maximum_Detection_Time avp_S6_3GPP_Maximum_Detection_Time,
- AAA_3GPP_Ext_PDP_Address avp_AAA_3GPP_Ext_PDP_Address,
+ DCA_3GPP_Time_Stamps avp_DCA_3GPP_Time_Stamps,
+ DCA_3GPP_Base_Time_Interval avp_DCA_3GPP_Base_Time_Interval,
+ DCA_3GPP_UWAN_User_Location_Info avp_DCA_3GPP_UWAN_User_Location_Info,
+ DCA_3GPP_ProSe_Role_Of_UE avp_DCA_3GPP_ProSe_Role_Of_UE,
PCC_3GPP_RAT_Type avp_PCC_3GPP_RAT_Type,
+ AAA_3GPP_Ext_PDP_Address avp_AAA_3GPP_Ext_PDP_Address,
+ DCA_3GPP_PoC_Session_Type avp_DCA_3GPP_PoC_Session_Type,
+ DCA_3GPP_ISUP_Cause avp_DCA_3GPP_ISUP_Cause,
RX_3GPP_AF_Signalling_Protocol avp_RX_3GPP_AF_Signalling_Protocol,
AAA_3GPP_Adjacent_PLMNs avp_AAA_3GPP_Adjacent_PLMNs,
S6_3GPP_Service_Result_Code avp_S6_3GPP_Service_Result_Code,
AAA_3GPP_SGSN_Location_Information avp_AAA_3GPP_SGSN_Location_Information,
+ DCA_3GPP_Authorised_QoS avp_DCA_3GPP_Authorised_QoS,
+ DCA_3GPP_Time_First_Transmission avp_DCA_3GPP_Time_First_Transmission,
+ DCA_3GPP_Stop_Time avp_DCA_3GPP_Stop_Time,
CxDx_3GPP_Reason_Code avp_CxDx_3GPP_Reason_Code,
PCC_3GPP_Pre_emption_Vulnerability avp_PCC_3GPP_Pre_emption_Vulnerability,
AAA_3GPP_Equivalent_PLMN_List avp_AAA_3GPP_Equivalent_PLMN_List,
PCC_3GPP_Default_Access avp_PCC_3GPP_Default_Access,
CxDx_3GPP_Supported_Applications avp_CxDx_3GPP_Supported_Applications,
- DNAS_NONE_ARAP_Challenge_Response avp_DNAS_NONE_ARAP_Challenge_Response,
BASE_NONE_Class avp_BASE_NONE_Class,
+ DNAS_NONE_ARAP_Challenge_Response avp_DNAS_NONE_ARAP_Challenge_Response,
+ DCA_3GPP_SM_Message_Type avp_DCA_3GPP_SM_Message_Type,
DCC_NONE_CC_Sub_Session_Id avp_DCC_NONE_CC_Sub_Session_Id,
AAA_3GPP_IDR_Flags avp_AAA_3GPP_IDR_Flags,
- AAA_3GPP_V2X_Subscription_Data avp_AAA_3GPP_V2X_Subscription_Data,
PCC_3GPP_PS_to_CS_Session_Continuity avp_PCC_3GPP_PS_to_CS_Session_Continuity,
+ AAA_3GPP_V2X_Subscription_Data avp_AAA_3GPP_V2X_Subscription_Data,
+ DCA_3GPP_Refund_Information avp_DCA_3GPP_Refund_Information,
+ DCA_3GPP_Rate_Element avp_DCA_3GPP_Rate_Element,
AAA_3GPP_PDP_Type avp_AAA_3GPP_PDP_Type,
AAA_3GPP_AMBR avp_AAA_3GPP_AMBR,
+ DCA_3GPP_Submission_Time avp_DCA_3GPP_Submission_Time,
octetstring avp_UNKNOWN
}
type union GenericAVP {
@@ -7130,744 +11251,1191 @@ type record AVP {
variant (avp_data) "CROSSTAG(
avp_GI_3GPP_3GPP_SGSN_IPv6_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_SGSN_IPv6_Address;
avp_DNAS_NONE_Login_LAT_Service, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_LAT_Service;
+ avp_AAA_3GPP_RAR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_RAR_Flags;
+ avp_DCA_3GPP_SCS_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SCS_Address;
avp_GI_3GPP_3GPP_GGSN_MCC_MNC, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_GGSN_MCC_MNC;
avp_DCC_NONE_Direct_Debiting_Failure_Handling, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Direct_Debiting_Failure_Handling;
avp_MIPv6_NONE_MIP_Careof_Address, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Careof_Address;
+ avp_DCA_3GPP_TWAN_User_Location_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_TWAN_User_Location_Info;
+ avp_DCA_3GPP_PoC_User_Role_IDs, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_User_Role_IDs;
+ avp_DCA_3GPP_Announcement_Order, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Announcement_Order;
avp_CxDx_ETSI_Line_Identifier, avp_header.avp_code.vendor_id_ETSI = avp_code_CxDx_ETSI_Line_Identifier;
avp_PCC_3GPP_Bearer_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Bearer_Identifier;
avp_RX_3GPP_Content_Version, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Content_Version;
+ avp_DCA_3GPP_Applic_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Applic_ID;
+ avp_MIPv4_NONE_MIP_HA_to_FA_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_HA_to_FA_MSA;
avp_BASE_NONE_Session_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Session_Id;
+ avp_DCA_3GPP_Route_Header_Transmitted, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Route_Header_Transmitted;
+ avp_DCA_3GPP_Reporting_Reason, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Reporting_Reason;
+ avp_AAA_3GPP_Emergency_Services, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Emergency_Services;
avp_RX_3GPP_Media_Component_Description, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Media_Component_Description;
avp_PCC_3GPP_CSG_Information_Reporting, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_CSG_Information_Reporting;
avp_AAA_3GPP_Measurement_Quantity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Measurement_Quantity;
avp_S6_3GPP_Location_Information_Configuration, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Location_Information_Configuration;
avp_PCC_3GPP_Bearer_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Bearer_Usage;
+ avp_DCA_3GPP_Application_provided_Called_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Application_provided_Called_Party_Address;
+ avp_DCA_3GPP_Proximity_Alert_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Proximity_Alert_Timestamp;
avp_PCC_3GPP_Tunnel_Header_Filter, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Tunnel_Header_Filter;
avp_AAA_3GPP_List_Of_Measurements, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_List_Of_Measurements;
avp_DCC_NONE_Requested_Service_Unit, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Requested_Service_Unit;
avp_PCC_3GPP_Default_QoS_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Default_QoS_Name;
avp_AAA_3GPP_UVA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UVA_Flags;
+ avp_DCA_3GPP_Expires, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Expires;
avp_CxDx_3GPP_SAR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SAR_Flags;
- avp_AAA_3GPP_Group_Service_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Group_Service_Id;
avp_PCC_3GPP_TDF_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_Information;
+ avp_AAA_3GPP_Group_Service_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Group_Service_Id;
+ avp_DCA_3GPP_Recipient_SCCP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Recipient_SCCP_Address;
+ avp_DCA_3GPP_Preferred_AoC_Currency, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Preferred_AoC_Currency;
avp_DNAS_NONE_Framed_Pool, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Pool;
+ avp_DCA_3GPP_Traffic_Data_Volumes, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Traffic_Data_Volumes;
avp_DCC_NONE_CC_Time, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Time;
avp_AAA_3GPP_Requested_EUTRAN_Authentication_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Requested_EUTRAN_Authentication_Info;
+ avp_DCA_3GPP_Unit_Cost, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Unit_Cost;
avp_CxDx_3GPP_SIP_Digest_Authenticate, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Digest_Authenticate;
avp_AAA_3GPP_Last_UE_Activity_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Last_UE_Activity_Time;
avp_AAA_3GPP_Context_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Context_Identifier;
avp_DCC_NONE_Used_Service_Unit, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Used_Service_Unit;
+ avp_MIPv4_NONE_MIP_Reg_Reply, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Reg_Reply;
avp_BASE_NONE_Auth_Application_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Auth_Application_Id;
avp_AAA_3GPP_Trace_Reference, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Reference;
+ avp_AAA_3GPP_TWAN_Access_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_Access_Info;
+ avp_DCA_3GPP_Status_AS_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Status_AS_Code;
+ avp_DCA_3GPP_LCS_Client_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Client_Type;
avp_DNAS_NONE_Framed_Appletalk_Network, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Appletalk_Network;
avp_DNAS_NONE_Framed_IPv6_Prefix, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IPv6_Prefix;
+ avp_DCA_3GPP_PoC_Session_Initiation_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Session_Initiation_Type;
avp_RX_3GPP_Sharing_Key_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Sharing_Key_UL;
+ avp_DCA_3GPP_Content_Size, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Content_Size;
+ avp_AAA_3GPP_Access_Network_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Access_Network_Info;
avp_RX_3GPP_AF_Charging_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_AF_Charging_Identifier;
avp_S6_3GPP_Monitoring_Event_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Monitoring_Event_Report;
+ avp_DCA_3GPP_Service_Specific_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Specific_Type;
+ avp_DCA_3GPP_Event, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Event;
avp_RX_3GPP_Media_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Media_Type;
avp_PCC_3GPP_Conditional_Policy_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Conditional_Policy_Information;
avp_BASE_NONE_Firmware_Revision, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Firmware_Revision;
- avp_AAA_3GPP_SIPTO_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SIPTO_Permission;
+ avp_DCA_3GPP_ProSe_Event_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Event_Type;
avp_PCC_3GPP_Network_Request_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Network_Request_Support;
+ avp_AAA_3GPP_SIPTO_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SIPTO_Permission;
+ avp_DCA_3GPP_Terminating_IOI, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Terminating_IOI;
avp_RX_3GPP_Extended_Max_Supported_BW_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Max_Supported_BW_DL;
avp_PCC_3GPP_UE_Local_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_UE_Local_IP_Address;
+ avp_DCA_3GPP_SM_Sequence_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Sequence_Number;
+ avp_DCA_3GPP_IMS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Information;
avp_PCC_3GPP_Presence_Reporting_Area_Elements_List, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Presence_Reporting_Area_Elements_List;
- avp_AAA_3GPP_SGs_MME_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SGs_MME_Identity;
avp_PCC_3GPP_Routing_Rule_Remove, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Remove;
+ avp_AAA_3GPP_SGs_MME_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SGs_MME_Identity;
avp_S6_3GPP_Roaming_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Roaming_Information;
+ avp_DCA_3GPP_Number_Of_Diversions, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_Of_Diversions;
+ avp_DCA_3GPP_Coverage_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Coverage_Info;
avp_CxDx_3GPP_SIP_Authentication_Scheme, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Authentication_Scheme;
avp_AAA_3GPP_Event_Threshold_RSRP, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_RSRP;
avp_CxDx_3GPP_User_Authorization_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_User_Authorization_Type;
avp_AAA_3GPP_PLMN_Client, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PLMN_Client;
avp_AAA_3GPP_Re_Synchronization_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Re_Synchronization_Info;
avp_BASE_NONE_Auth_Grace_Period, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Auth_Grace_Period;
+ avp_DCA_3GPP_User_CSG_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_User_CSG_Information;
+ avp_DCA_3GPP_SM_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Status;
+ avp_DCA_3GPP_IP_Realm_Default_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IP_Realm_Default_Indication;
avp_AAA_3GPP_RAND, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_RAND;
avp_AAA_3GPP_Trace_Depth, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Depth;
+ avp_MIPv4_NONE_MIP_MN_to_FA_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_MN_to_FA_MSA;
avp_AAA_3GPP_SGSN_User_State, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SGSN_User_State;
avp_AAA_3GPP_APN_OI_Replacement, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_APN_OI_Replacement;
+ avp_DCA_3GPP_Alternate_Charged_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Alternate_Charged_Party_Address;
+ avp_DCA_3GPP_APN_Rate_Control, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_APN_Rate_Control;
avp_BASE_NONE_Re_Auth_Request_Type, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Re_Auth_Request_Type;
+ avp_DCA_3GPP_Relationship_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Relationship_Mode;
avp_S6_3GPP_External_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_External_Identifier;
+ avp_DCA_3GPP_Positioning_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Positioning_Data;
avp_DCC_NONE_Redirect_Address_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Redirect_Address_Type;
avp_MIPv6_NONE_MIP_MN_HA_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MN_HA_MSA;
+ avp_DCA_3GPP_Monitoring_UE_HPLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_UE_HPLMN_Identifier;
avp_PCC_3GPP_TFT_Filter, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TFT_Filter;
avp_RX_3GPP_Max_Supported_Bandwidth_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Max_Supported_Bandwidth_UL;
- avp_DNAS_NONE_Tunnel_Medium_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Medium_Type;
avp_S6_3GPP_Loss_Of_Connectivity_Reason, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Loss_Of_Connectivity_Reason;
+ avp_DNAS_NONE_Tunnel_Medium_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Medium_Type;
+ avp_DCA_3GPP_Originator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originator;
avp_DCC_NONE_User_Equipment_Info_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_User_Equipment_Info_Type;
avp_RX_3GPP_Flow_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Flow_Number;
+ avp_MIPv4_NONE_MIP_Home_Agent_Address, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Home_Agent_Address;
avp_PCC_3GPP_Resource_Allocation_Notification, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Resource_Allocation_Notification;
+ avp_DCA_3GPP_Basic_Service_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Basic_Service_Code;
avp_S6_3GPP_Monitoring_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Monitoring_Type;
+ avp_DCA_3GPP_Role_Of_Node, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Role_Of_Node;
avp_PCC_3GPP_Default_Bearer_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Default_Bearer_Indication;
- avp_AAA_3GPP_VPLMN_LIPA_Allowed, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_VPLMN_LIPA_Allowed;
+ avp_DCA_3GPP_ProSe_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Information;
avp_PCC_3GPP_QoS_Class_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Class_Identifier;
+ avp_AAA_3GPP_VPLMN_LIPA_Allowed, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_VPLMN_LIPA_Allowed;
avp_PCC_3GPP_Mute_Notification, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Mute_Notification;
avp_CxDx_3GPP_SIP_Authentication_Context, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Authentication_Context;
avp_MIPv6_NONE_QoS_Resources, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_QoS_Resources;
avp_AAA_3GPP_Logging_Duration, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Logging_Duration;
avp_DCC_NONE_Service_Parameter_Value, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Parameter_Value;
avp_CxDx_3GPP_Associated_Registered_Identities, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Associated_Registered_Identities;
- avp_AAA_3GPP_WLAN_offloadability_EUTRAN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN;
avp_PCC_3GPP_Routing_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_IP_Address;
- avp_MIPv6_NONE_MIP_Session_Key, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Session_Key;
+ avp_AAA_3GPP_WLAN_offloadability_EUTRAN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN;
+ avp_DCA_3GPP_MBMS_GW_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MBMS_GW_Address;
+ avp_DCA_3GPP_Destination_Interface, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Destination_Interface;
+ avp_DCA_3GPP_IMS_Emergency_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Emergency_Indicator;
+ avp_DCA_3GPP_Change_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Change_Time;
avp_AAA_3GPP_KASME, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_KASME;
+ avp_MIPv4_NONE_MIP_Session_Key, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Session_Key;
+ avp_DCA_3GPP_AoC_Cost_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Cost_Information;
avp_GI_3GPP_3GPP_User_Location_Info_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_User_Location_Info_Time;
avp_AAA_3GPP_Teleservice_List, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Teleservice_List;
avp_AAA_3GPP_UTRAN_Vector, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UTRAN_Vector;
+ avp_AAA_3GPP_Non_3GPP_IP_Access_APN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_3GPP_IP_Access_APN;
+ avp_DCA_3GPP_Monitoring_Event_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_Event_Information;
avp_DCC_NONE_Tariff_Time_Change, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Tariff_Time_Change;
avp_GI_3GPP_3GPP_NSAPI, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_NSAPI;
+ avp_DCA_3GPP_LCS_Client_Dialed_By_MS, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Client_Dialed_By_MS;
avp_GI_3GPP_3GPP_CG_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_CG_Address;
+ avp_DCA_3GPP_Envelope_Start_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Envelope_Start_Time;
avp_RX_3GPP_Application_Service_Provider_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Application_Service_Provider_Identity;
avp_S6_3GPP_NIDD_Authorization_Request, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_NIDD_Authorization_Request;
+ avp_DCA_3GPP_Received_Talk_Burst_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Received_Talk_Burst_Time;
+ avp_DCA_3GPP_Incoming_Trunk_Group_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Incoming_Trunk_Group_Id;
+ avp_AAA_3GPP_AAA_Failure_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AAA_Failure_Indication;
+ avp_DCA_3GPP_Rate_Control_Max_Message_Size, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Rate_Control_Max_Message_Size;
avp_PCC_3GPP_QoS_Rule_Install, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Install;
avp_S6_3GPP_Periodic_Communication_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Periodic_Communication_Indicator;
+ avp_DCA_3GPP_Service_Specific_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Specific_Info;
avp_RX_3GPP_Flow_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Flow_Usage;
avp_PCC_3GPP_RAN_Rule_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_RAN_Rule_Support;
avp_DNAS_NONE_Tunnel_Password, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Password;
+ avp_DCA_3GPP_PC3_EPC_Control_Protocol_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PC3_EPC_Control_Protocol_Cause;
avp_S6_3GPP_Monitoring_Duration, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Monitoring_Duration;
- avp_AAA_3GPP_Routing_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Routing_Area_Identity;
avp_PCC_3GPP_QoS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Information;
- avp_DCC_NONE_User_Equipment_Info_Value, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_User_Equipment_Info_Value;
- avp_DNAS_NONE_Tunneling, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunneling;
+ avp_AAA_3GPP_Routing_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Routing_Area_Identity;
+ avp_DCA_3GPP_Called_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Called_Party_Address;
avp_RX_3GPP_Service_Authorization_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Service_Authorization_Info;
- avp_BASE_NONE_Multi_Round_Time_Out, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Multi_Round_Time_Out;
+ avp_DNAS_NONE_Tunneling, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunneling;
+ avp_DCC_NONE_User_Equipment_Info_Value, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_User_Equipment_Info_Value;
+ avp_MIPv4_NONE_MIP_Auth_Input_Data_Length, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Auth_Input_Data_Length;
avp_AAA_3GPP_eDRX_Cycle_Length, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_eDRX_Cycle_Length;
+ avp_BASE_NONE_Multi_Round_Time_Out, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Multi_Round_Time_Out;
avp_S6_3GPP_Group_Monitoring_Event_Report_Item, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Group_Monitoring_Event_Report_Item;
- avp_AAA_3GPP_Ext_PDP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Ext_PDP_Type;
avp_PCC_3GPP_Rule_Failure_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Rule_Failure_Code;
+ avp_AAA_3GPP_Ext_PDP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Ext_PDP_Type;
+ avp_DCA_3GPP_Time_Quota_Threshold, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Quota_Threshold;
avp_PCC_3GPP_User_Location_Info_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_User_Location_Info_Time;
- avp_AAA_3GPP_Measurement_Period_LTE, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Measurement_Period_LTE;
avp_PCC_3GPP_Usage_Monitoring_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Usage_Monitoring_Information;
- avp_BASE_NONE_Experimental_Result_Code, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Experimental_Result_Code;
+ avp_AAA_3GPP_Measurement_Period_LTE, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Measurement_Period_LTE;
avp_PCC_3GPP_Extended_APN_AMBR_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Extended_APN_AMBR_DL;
+ avp_BASE_NONE_Experimental_Result_Code, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Experimental_Result_Code;
avp_CxDx_3GPP_Session_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Session_Priority;
+ avp_DCA_3GPP_Recipient_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Recipient_Info;
+ avp_DCA_3GPP_AoC_Format, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Format;
+ avp_DCA_3GPP_Start_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Start_Time;
avp_CxDx_3GPP_Deregistration_Reason, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Deregistration_Reason;
avp_AAA_3GPP_GMLC_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_GMLC_Number;
- avp_DNAS_NONE_Configuration_Token, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Configuration_Token;
- avp_DNAS_NONE_Callback_Number, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Callback_Number;
avp_AAA_3GPP_Software_Version, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Software_Version;
+ avp_DNAS_NONE_Callback_Number, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Callback_Number;
+ avp_DNAS_NONE_Configuration_Token, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Configuration_Token;
+ avp_DCA_3GPP_Interface_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Interface_Type;
+ avp_MIPv4_NONE_MIP_Originating_Foreign_AAA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Originating_Foreign_AAA;
avp_AAA_3GPP_Expiration_Date, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Expiration_Date;
avp_BASE_NONE_Error_Message, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Error_Message;
avp_AAA_3GPP_SRES, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SRES;
- avp_DNAS_NONE_NAS_Port_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Port_Type;
+ avp_DCA_3GPP_DRM_Content, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_DRM_Content;
avp_AAA_3GPP_Item_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Item_Number;
+ avp_DNAS_NONE_NAS_Port_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Port_Type;
+ avp_AAA_3GPP_ERP_Authorization, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ERP_Authorization;
avp_DCC_NONE_Multiple_Services_Indicator, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Multiple_Services_Indicator;
+ avp_DCA_3GPP_Early_Media_Description, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Early_Media_Description;
+ avp_AAA_3GPP_MIP_FA_RK, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MIP_FA_RK;
+ avp_DCA_3GPP_Related_Change_Condition_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Related_Change_Condition_Information;
avp_DNAS_NONE_Framed_Protocol, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Protocol;
avp_S6_3GPP_Service_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_ID;
+ avp_DCA_3GPP_LCS_Format_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Format_Indicator;
avp_GI_3GPP_3GPP_IMSI_MCC_MNC, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_IMSI_MCC_MNC;
avp_RX_3GPP_Abort_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Abort_Cause;
+ avp_DCA_3GPP_ISUP_Cause_Location, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ISUP_Cause_Location;
avp_PCC_3GPP_Charging_Rule_Base_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Base_Name;
avp_RX_3GPP_Required_Access_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Required_Access_Info;
avp_PCC_3GPP_TDF_Destination_Realm, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_Destination_Realm;
avp_S6_3GPP_S6t_HSS_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_S6t_HSS_Cause;
+ avp_DCA_3GPP_Media_Initiator_Party, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Media_Initiator_Party;
+ avp_DCA_3GPP_Associated_URI, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Associated_URI;
avp_RX_3GPP_AF_Requested_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_AF_Requested_Data;
+ avp_PCC_3GPP_QoS_Rule_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Report;
avp_DNAS_NONE_Filter_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Filter_Id;
avp_DNAS_NONE_ARAP_Password, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Password;
- avp_PCC_3GPP_QoS_Rule_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Report;
- avp_DNAS_NONE_CHAP_Response, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Response;
+ avp_DCA_3GPP_Route_Header_Received, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Route_Header_Received;
avp_S6_3GPP_Stationary_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Stationary_Indication;
+ avp_DNAS_NONE_CHAP_Response, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Response;
avp_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL;
+ avp_DCA_3GPP_Usage_Information_Report_Sequence_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Usage_Information_Report_Sequence_Number;
avp_AAA_3GPP_Geodetic_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Geodetic_Information;
avp_PCC_3GPP_Extended_GBR_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Extended_GBR_UL;
avp_AAA_3GPP_MBSFN_Area_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MBSFN_Area_ID;
avp_CxDx_3GPP_Server_Capabilities, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Server_Capabilities;
avp_AAA_3GPP_Area_Scope, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Area_Scope;
- avp_DNAS_NONE_Accounting_Input_Packets, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Accounting_Input_Packets;
+ avp_MIPv4_NONE_Accounting_Input_Packets, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_Accounting_Input_Packets;
+ avp_DCA_3GPP_SGW_Change, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SGW_Change;
avp_CxDx_3GPP_SCSCF_Restoration_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SCSCF_Restoration_Info;
avp_CxDx_3GPP_Initial_CSeq_Sequence_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Initial_CSeq_Sequence_Number;
+ avp_DCA_3GPP_AoC_Subscription_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Subscription_Information;
avp_AAA_3GPP_PUA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PUA_Flags;
avp_DNAS_NONE_Callback_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Callback_Id;
+ avp_DCA_3GPP_Time_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Usage;
avp_CxDx_3GPP_Primary_Event_Charging_Function_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Primary_Event_Charging_Function_Name;
avp_DCC_NONE_CC_Output_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Output_Octets;
avp_GI_3GPP_3GPP_User_Location_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_User_Location_Info;
avp_AAA_3GPP_Notification_To_UE_User, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Notification_To_UE_User;
avp_AAA_3GPP_Visited_PLMN_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Visited_PLMN_Id;
avp_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions;
+ avp_DCA_3GPP_Participant_Group, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Participant_Group;
+ avp_DCA_3GPP_Play_Alternative, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Play_Alternative;
+ avp_DCA_3GPP_MBMS_User_Service_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MBMS_User_Service_Type;
+ avp_DCA_3GPP_Transit_IOI_List, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Transit_IOI_List;
avp_RX_3GPP_Codec_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Codec_Data;
avp_S6_3GPP_Monitoring_Event_Config_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Monitoring_Event_Config_Status;
+ avp_DCA_3GPP_SDP_Media_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Media_Name;
+ avp_DCA_3GPP_AF_Correlation_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AF_Correlation_Information;
avp_DCC_NONE_Cost_Information, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Cost_Information;
+ avp_DCA_3GPP_Serving_Node_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Serving_Node_Identity;
avp_BASE_NONE_Error_Reporting_Host, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Error_Reporting_Host;
+ avp_DCA_3GPP_Radio_Frequency, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Radio_Frequency;
avp_PCC_3GPP_Rule_Activation_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Rule_Activation_Time;
avp_S6_3GPP_Service_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_Data;
avp_RX_3GPP_AF_Application_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_AF_Application_Identifier;
avp_PCC_3GPP_NetLoc_Access_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_NetLoc_Access_Support;
+ avp_DCA_3GPP_Announcing_UE_VPLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Announcing_UE_VPLMN_Identifier;
avp_S6_3GPP_Monitoring_Event_Configuration, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Monitoring_Event_Configuration;
avp_PCC_3GPP_Offline, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Offline;
+ avp_DCA_3GPP_SIP_Method, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SIP_Method;
+ avp_PCC_3GPP_ADC_Rule_Definition, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Definition;
+ avp_AAA_3GPP_Additional_Context_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Additional_Context_ID;
avp_DNAS_NONE_Login_Service, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_Service;
avp_DNAS_NONE_ARAP_Security_Data, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Security_Data;
- avp_AAA_3GPP_Additional_Context_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Additional_Context_ID;
- avp_PCC_3GPP_ADC_Rule_Definition, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Definition;
avp_S6_3GPP_Allowed_PLMN_List, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Allowed_PLMN_List;
- avp_AAA_3GPP_Active_APN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Active_APN;
avp_PCC_3GPP_Bearer_Control_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Bearer_Control_Mode;
+ avp_AAA_3GPP_Active_APN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Active_APN;
avp_PCC_3GPP_HeNB_Local_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_HeNB_Local_IP_Address;
- avp_AAA_3GPP_SMS_Register_Request, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SMS_Register_Request;
avp_PCC_3GPP_Packet_Filter_Content, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Packet_Filter_Content;
+ avp_AAA_3GPP_SMS_Register_Request, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SMS_Register_Request;
avp_CxDx_3GPP_Subscription_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Subscription_Info;
+ avp_DCA_3GPP_SIP_Response_Timestamp_Fraction, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SIP_Response_Timestamp_Fraction;
+ avp_DCA_3GPP_Client_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Client_Address;
avp_AAA_3GPP_APN_Configuration, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_APN_Configuration;
+ avp_DCA_3GPP_Subscriber_Role, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Subscriber_Role;
avp_CxDx_3GPP_SIP_Number_Auth_Items, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Number_Auth_Items;
avp_AAA_3GPP_OMC_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_OMC_Id;
avp_AAA_3GPP_GMLC_Restriction, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_GMLC_Restriction;
avp_DNAS_NONE_State, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_State;
avp_DNAS_NONE_Tunnel_Preference, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Preference;
avp_DCC_NONE_CC_Session_Failover, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Session_Failover;
+ avp_DCA_3GPP_Enhanced_Diagnostics, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Enhanced_Diagnostics;
+ avp_DCA_3GPP_CSG_Membership_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CSG_Membership_Indication;
avp_AAA_3GPP_Regional_Subscription_Zone_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Regional_Subscription_Zone_Code;
+ avp_DCA_3GPP_Message_Class, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Message_Class;
avp_GI_3GPP_3GPP_Negotiated_DSCP, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Negotiated_DSCP;
+ avp_AAA_3GPP_TWAN_S2a_Failure_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_S2a_Failure_Cause;
+ avp_MIPv4_NONE_MIP_FA_to_MN_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_FA_to_MN_SPI;
+ avp_DCA_3GPP_Trigger, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Trigger;
+ avp_DCA_3GPP_Called_Identity_Change, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Called_Identity_Change;
+ avp_DCA_3GPP_ProSe_Request_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Request_Timestamp;
+ avp_DCA_3GPP_PoC_Session_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Session_Id;
avp_BASE_NONE_Proxy_State, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Proxy_State;
- avp_DCC_NONE_Credit_Control_Failure_Handling, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Credit_Control_Failure_Handling;
+ avp_DCA_3GPP_PoC_Server_Role, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Server_Role;
+ avp_DCA_3GPP_Forwarding_Pending, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Forwarding_Pending;
avp_S6_3GPP_SIR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_SIR_Flags;
+ avp_DCC_NONE_Credit_Control_Failure_Handling, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Credit_Control_Failure_Handling;
+ avp_MIPv6_NONE_MIP6_Agent_Info, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP6_Agent_Info;
avp_RX_3GPP_MPS_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_MPS_Identifier;
- avp_AAA_3GPP_MDT_Allowed_PLMN_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id;
avp_PCC_3GPP_Credit_Management_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Credit_Management_Status;
+ avp_AAA_3GPP_MDT_Allowed_PLMN_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id;
+ avp_DCA_3GPP_Monitored_PLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitored_PLMN_Identifier;
avp_S6_3GPP_Service_Result, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_Result;
- avp_AAA_3GPP_MME_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MME_Location_Information;
avp_PCC_3GPP_Reporting_Level, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Reporting_Level;
+ avp_AAA_3GPP_MME_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MME_Location_Information;
+ avp_DCA_3GPP_Served_Party_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Served_Party_IP_Address;
avp_RX_3GPP_Max_Supported_Bandwidth_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Max_Supported_Bandwidth_DL;
- avp_AAA_3GPP_Subscribed_VSRVCC, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscribed_VSRVCC;
+ avp_DCA_3GPP_Time_First_Reception, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_First_Reception;
avp_PCC_3GPP_Pre_emption_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Pre_emption_Capability;
+ avp_AAA_3GPP_Subscribed_VSRVCC, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscribed_VSRVCC;
avp_PCC_3GPP_Monitoring_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Monitoring_Flags;
avp_BASE_NONE_Redirect_Max_Cache_Time, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Redirect_Max_Cache_Time;
avp_CxDx_3GPP_Feature_List, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Feature_List;
+ avp_DCA_3GPP_Address_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Address_Type;
avp_PCC_3GPP_TCP_Source_Port, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TCP_Source_Port;
avp_PCC_3GPP_Application_Detection_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Application_Detection_Information;
avp_AAA_3GPP_Emergency_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Emergency_Info;
+ avp_DCA_3GPP_Remaining_Balance, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Remaining_Balance;
avp_AAA_3GPP_MPS_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MPS_Priority;
+ avp_DCA_3GPP_Next_Tariff, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Next_Tariff;
avp_DCC_NONE_Requested_Action, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Requested_Action;
avp_CxDx_3GPP_Record_Route, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Record_Route;
+ avp_DCA_3GPP_Tariff_XML, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Tariff_XML;
avp_AAA_3GPP_Alert_Reason, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Alert_Reason;
+ avp_DCA_3GPP_Recipient_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Recipient_Address;
+ avp_DCA_3GPP_Change_Condition, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Change_Condition;
avp_GI_3GPP_3GPP_CG_IPv6_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_CG_IPv6_Address;
avp_DNAS_NONE_Idle_Timeout, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Idle_Timeout;
avp_DNAS_NONE_NAS_Port_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Port_Id;
+ avp_AAA_3GPP_DEA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DEA_Flags;
+ avp_DCA_3GPP_SCS_AS_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SCS_AS_Address;
avp_AAA_3GPP_MO_LR, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MO_LR;
+ avp_DCA_3GPP_IMS_Visited_Network_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Visited_Network_Identifier;
+ avp_DCA_3GPP_PoC_User_Role, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_User_Role;
+ avp_DCA_3GPP_Announcement_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Announcement_Identifier;
+ avp_AAA_3GPP_Non_3GPP_IP_Access, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_3GPP_IP_Access;
+ avp_DCA_3GPP_Monitoring_Event_Report_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_Event_Report_Data;
+ avp_DCA_3GPP_Adaptations, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Adaptations;
avp_BASE_NONE_Host_IP_Address, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Host_IP_Address;
+ avp_MIPv4_NONE_MIP_Reg_Request, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Reg_Request;
+ avp_DCA_3GPP_Quota_Holding_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Quota_Holding_Time;
+ avp_AAA_3GPP_Maximum_Wait_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Maximum_Wait_Time;
avp_RX_3GPP_Max_Requested_Bandwidth_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Max_Requested_Bandwidth_UL;
avp_PCC_3GPP_Usage_Monitoring_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Usage_Monitoring_Support;
avp_S6_3GPP_Maximum_Response_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Maximum_Response_Time;
+ avp_DCA_3GPP_Envelope_Reporting, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Envelope_Reporting;
+ avp_DCA_3GPP_Application_Server, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Application_Server;
avp_RX_3GPP_Sponsor_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Sponsor_Identity;
avp_DNAS_NONE_Framed_Appletalk_Link, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Appletalk_Link;
avp_DNAS_NONE_Framed_Interface_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Interface_Id;
+ avp_DCA_3GPP_Proximity_Alert_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Proximity_Alert_Indication;
avp_PCC_3GPP_CoA_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_CoA_IP_Address;
+ avp_DCA_3GPP_Trunk_Group_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Trunk_Group_Id;
avp_PCC_3GPP_Default_QoS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Default_QoS_Information;
avp_PCC_3GPP_AN_GW_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_AN_GW_Address;
+ avp_DCA_3GPP_Start_Of_Charging, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Start_Of_Charging;
+ avp_DCA_3GPP_Participants_Involved, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Participants_Involved;
avp_PCC_3GPP_NBIFOM_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_NBIFOM_Support;
avp_PCC_3GPP_Redirect_Support, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Redirect_Support;
avp_AAA_3GPP_IMSI_Group_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IMSI_Group_Id;
avp_AAA_3GPP_Cell_Global_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Cell_Global_Identity;
avp_BASE_NONE_Vendor_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Vendor_Id;
avp_AAA_3GPP_PDN_Connection_Continuity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PDN_Connection_Continuity;
+ avp_DCA_3GPP_Tariff_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Tariff_Information;
avp_CxDx_3GPP_Wildcarded_Public_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Wildcarded_Public_Identity;
- avp_DNAS_NONE_Acct_Session_Time, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Session_Time;
+ avp_MIPv4_NONE_Acct_Session_Time, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_Acct_Session_Time;
avp_AAA_3GPP_DSA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DSA_Flags;
+ avp_DCA_3GPP_PoC_Event_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Event_Type;
avp_AAA_3GPP_Trace_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Data;
avp_AAA_3GPP_LCS_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_LCS_Info;
+ avp_DCA_3GPP_LCS_Requestor_Id_String, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Requestor_Id_String;
avp_AAA_3GPP_PDN_GW_Allocation_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PDN_GW_Allocation_Type;
+ avp_DCA_3GPP_Additional_Type_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Additional_Type_Information;
avp_GI_3GPP_3GPP_SGSN_MCC_MNC, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_SGSN_MCC_MNC;
+ avp_AAA_3GPP_HESSID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_HESSID;
+ avp_DCA_3GPP_Content_Class, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Content_Class;
avp_BASE_NONE_Event_Timestamp, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Event_Timestamp;
+ avp_DCA_3GPP_TAD_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_TAD_Identifier;
avp_DCC_NONE_Final_Unit_Action, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Final_Unit_Action;
+ avp_AAA_3GPP_IMEI_Check_In_VPLMN_Result, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IMEI_Check_In_VPLMN_Result;
+ avp_DCA_3GPP_Service_Generic_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Generic_Information;
+ avp_DCA_3GPP_Variable_Part_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Variable_Part_Type;
+ avp_DCA_3GPP_ProSe_Direct_Discovery_Model, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Direct_Discovery_Model;
avp_RX_3GPP_Extended_Max_Requested_BW_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Max_Requested_BW_UL;
+ avp_DCA_3GPP_SM_Device_Trigger_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Device_Trigger_Indicator;
avp_S6_3GPP_User_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_User_Identifier;
- avp_DNAS_NONE_Framed_IPv6_Pool, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IPv6_Pool;
avp_PCC_3GPP_QoS_Rule_Base_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Base_Name;
+ avp_DNAS_NONE_Framed_IPv6_Pool, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IPv6_Pool;
avp_AAA_3GPP_Restoration_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Restoration_Priority;
- avp_DCC_NONE_Rating_Group, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Rating_Group;
- avp_MIPv6_NONE_MIP_MN_HA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MN_HA_SPI;
+ avp_DCA_3GPP_ISUP_Cause_Diagnostics, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ISUP_Cause_Diagnostics;
avp_S6_3GPP_Association_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Association_Type;
avp_PCC_3GPP_Charging_Rule_Definition, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Definition;
+ avp_DCC_NONE_Rating_Group, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Rating_Group;
+ avp_MIPv6_NONE_MIP_MN_HA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MN_HA_SPI;
avp_RX_3GPP_Min_Requested_Bandwidth_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Min_Requested_Bandwidth_UL;
- avp_AAA_3GPP_Report_Amount, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Report_Amount;
+ avp_DCA_3GPP_Application_Specific_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Application_Specific_Data;
avp_PCC_3GPP_CoA_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_CoA_Information;
+ avp_AAA_3GPP_Report_Amount, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Report_Amount;
avp_CxDx_3GPP_Secondary_Charging_Collection_Function_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Secondary_Charging_Collection_Function_Name;
avp_DCC_NONE_User_Equipment_Info, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_User_Equipment_Info;
avp_AAA_3GPP_A_MSISDN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_A_MSISDN;
- avp_MIPv6_NONE_MIP_Mobile_Node_Address, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Mobile_Node_Address;
+ avp_MIPv4_NONE_MIP_Mobile_Node_Address, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Mobile_Node_Address;
avp_PCC_3GPP_Routing_Rule_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Report;
avp_AAA_3GPP_Number_Of_Requested_Vectors, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Number_Of_Requested_Vectors;
avp_AAA_3GPP_AIR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AIR_Flags;
+ avp_DCA_3GPP_SM_Protocol_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Protocol_ID;
+ avp_DCA_3GPP_Low_Priority_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Low_Priority_Indicator;
avp_AAA_3GPP_Geographical_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Geographical_Information;
+ avp_DCA_3GPP_Participant_Action_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Participant_Action_Type;
+ avp_DCA_3GPP_Node_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Node_Id;
avp_CxDx_3GPP_Loose_Route_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Loose_Route_Indication;
avp_DCC_NONE_Service_Parameter_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Parameter_Type;
avp_AAA_3GPP_MME_User_State, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MME_User_State;
avp_AAA_3GPP_Access_Restriction_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Access_Restriction_Data;
+ avp_DCA_3GPP_SM_Service_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Service_Type;
+ avp_DCA_3GPP_UNI_PDU_CP_Only_Flag, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_UNI_PDU_CP_Only_Flag;
+ avp_MIPv4_NONE_MIP_Filter_Rule, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Filter_Rule;
avp_BASE_NONE_Failed_AVP, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Failed_AVP;
avp_GI_3GPP_3GPP_RAT_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_RAT_Type;
avp_AAA_3GPP_SS_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SS_Status;
+ avp_DCA_3GPP_Neighbour_Node_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Neighbour_Node_Address;
+ avp_DCA_3GPP_Location_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Location_Type;
+ avp_DCA_3GPP_Quota_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Quota_Indicator;
+ avp_DCA_3GPP_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Priority;
avp_S6_3GPP_NIDD_Authorization_Update, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_NIDD_Authorization_Update;
+ avp_DCA_3GPP_Service_Specific_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Specific_Data;
avp_DCC_NONE_Subscription_Id_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Subscription_Id_Type;
+ avp_MIPv4_NONE_MIP_FA_to_HA_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_FA_to_HA_MSA;
+ avp_AAA_3GPP_Connectivity_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Connectivity_Flags;
avp_PCC_3GPP_Packet_Filter_Operation, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Packet_Filter_Operation;
+ avp_DCA_3GPP_VCS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_VCS_Information;
avp_S6_3GPP_SCEF_Reference_ID_for_Deletion, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_SCEF_Reference_ID_for_Deletion;
+ avp_DCA_3GPP_Content_Disposition, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Content_Disposition;
avp_RX_3GPP_SIP_Forking_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_SIP_Forking_Indication;
avp_DNAS_NONE_User_Password, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_User_Password;
+ avp_DCA_3GPP_ProSe_Group_IP_Multicast_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Group_IP_Multicast_Address;
avp_S6_3GPP_IMEI_Change, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_IMEI_Change;
avp_PCC_3GPP_IP_CAN_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_IP_CAN_Type;
+ avp_DCA_3GPP_SDP_Media_Component, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Media_Component;
avp_RX_3GPP_Extended_Min_Desired_BW_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Min_Desired_BW_UL;
+ avp_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container;
avp_CxDx_3GPP_SIP_Authorization, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Authorization;
avp_PCC_3GPP_Revalidation_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Revalidation_Time;
avp_AAA_3GPP_Logging_Interval, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Logging_Interval;
+ avp_DCA_3GPP_PoC_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Information;
avp_PCC_3GPP_Presence_Reporting_Area_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Presence_Reporting_Area_Status;
- avp_AAA_3GPP_WLAN_offloadability, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_offloadability;
avp_PCC_3GPP_Routing_Filter, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Filter;
+ avp_AAA_3GPP_WLAN_offloadability, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_offloadability;
+ avp_DCA_3GPP_Data_Coding_Scheme, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Data_Coding_Scheme;
avp_PCC_3GPP_Metering_Method, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Metering_Method;
avp_DNAS_NONE_Acct_Tunnel_Connection, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Tunnel_Connection;
avp_AAA_3GPP_Non_IP_Data_Delivery_Mechanism, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_IP_Data_Delivery_Mechanism;
+ avp_DCA_3GPP_Initial_IMS_Charging_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Initial_IMS_Charging_Identifier;
avp_DNAS_NONE_NAS_Filter_Rule, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Filter_Rule;
+ avp_MIPv4_NONE_MIP_Feature_Vector, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Feature_Vector;
avp_BASE_NONE_Session_Server_Failover, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Session_Server_Failover;
+ avp_DCA_3GPP_Accumulated_Cost, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Accumulated_Cost;
avp_CxDx_3GPP_Integrity_Key, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Integrity_Key;
avp_AAA_3GPP_E_UTRAN_Vector, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_E_UTRAN_Vector;
+ avp_DCA_3GPP_SMSC_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SMSC_Address;
+ avp_DCA_3GPP_PDP_Address_Prefix_Length, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PDP_Address_Prefix_Length;
avp_BASE_NONE_Experimental_Result, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Experimental_Result;
avp_DNAS_NONE_Acct_Link_Count, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Link_Count;
avp_DCC_NONE_Unit_Value, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Unit_Value;
avp_AAA_3GPP_Trace_Event_List, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Event_List;
+ avp_DCA_3GPP_LCS_Client_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Client_Id;
avp_GI_3GPP_3GPP_PDP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_PDP_Type;
avp_DNAS_NONE_Reply_Message, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Reply_Message;
avp_DNAS_NONE_Connect_Info, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Connect_Info;
- avp_MIPv6_NONE_MIP_Replay_Mode, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Replay_Mode;
+ avp_MIPv4_NONE_MIP_Replay_Mode, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Replay_Mode;
avp_BASE_NONE_Proxy_Host, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Proxy_Host;
+ avp_DCA_3GPP_Number_Of_Talk_Bursts, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_Of_Talk_Bursts;
+ avp_AAA_3GPP_Short_Network_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Short_Network_Name;
+ avp_DCA_3GPP_Message_Size, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Message_Size;
+ avp_DCA_3GPP_Additional_Exception_Reports, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Additional_Exception_Reports;
+ avp_DCA_3GPP_Access_Transfer_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Access_Transfer_Information;
avp_S6_3GPP_Communication_Pattern_Set, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Communication_Pattern_Set;
+ avp_AAA_3GPP_TWAG_UP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAG_UP_Address;
+ avp_DCA_3GPP_MMBox_Storage_Requested, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MMBox_Storage_Requested;
avp_RX_3GPP_Flow_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Flow_Status;
avp_DNAS_NONE_CHAP_Challenge, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Challenge;
+ avp_DCA_3GPP_PC3_Control_Protocol_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PC3_Control_Protocol_Cause;
avp_DCC_NONE_CC_Unit_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Unit_Type;
+ avp_DCA_3GPP_Calling_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Calling_Party_Address;
avp_RX_3GPP_MCPTT_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_MCPTT_Identifier;
avp_S6_3GPP_Group_Monitoring_Event_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Group_Monitoring_Event_Report;
avp_PCC_3GPP_QoS_Upgrade, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Upgrade;
- avp_DNAS_NONE_Service_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Service_Type;
+ avp_DCA_3GPP_PS_Append_Free_Format_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PS_Append_Free_Format_Data;
avp_PCC_3GPP_AN_GW_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_AN_GW_Status;
- avp_AAA_3GPP_Measurement_Period_UMTS, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Measurement_Period_UMTS;
+ avp_DNAS_NONE_Service_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Service_Type;
avp_PCC_3GPP_Monitoring_Key, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Monitoring_Key;
+ avp_AAA_3GPP_Measurement_Period_UMTS, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Measurement_Period_UMTS;
+ avp_DCA_3GPP_Media_Initiator_Flag, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Media_Initiator_Flag;
+ avp_DCA_3GPP_ISUP_Location_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ISUP_Location_Number;
avp_PCC_3GPP_3GPP_PS_Data_Off_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_3GPP_PS_Data_Off_Status;
- avp_AAA_3GPP_Reset_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Reset_ID;
avp_PCC_3GPP_Routing_Rule_Install, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Install;
+ avp_AAA_3GPP_Reset_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Reset_ID;
+ avp_DCA_3GPP_Service_Data_Container, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Data_Container;
avp_CxDx_3GPP_Server_Assignment_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Server_Assignment_Type;
avp_AAA_3GPP_PUR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PUR_Flags;
- avp_DNAS_NONE_Framed_Routing, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Routing;
avp_PCC_3GPP_IP_CAN_Session_Charging_Scope, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_IP_CAN_Session_Charging_Scope;
+ avp_DNAS_NONE_Framed_Routing, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Routing;
avp_AAA_3GPP_IMEI, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IMEI;
avp_DNAS_NONE_CHAP_Ident, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Ident;
+ avp_DCA_3GPP_Interface_Text, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Interface_Text;
avp_AAA_3GPP_Kc, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Kc;
+ avp_DCA_3GPP_Current_Tariff, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Current_Tariff;
avp_AAA_3GPP_SGSN_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SGSN_Number;
avp_AAA_3GPP_HPLMN_ODB, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_HPLMN_ODB;
+ avp_DCA_3GPP_Time_Quota_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Quota_Type;
+ avp_AAA_3GPP_Trace_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Info;
+ avp_DCA_3GPP_Domain_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Domain_Name;
avp_GI_3GPP_3GPP_Charging_Characteristics, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Charging_Characteristics;
avp_AAA_3GPP_PDP_Context, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PDP_Context;
avp_DCC_NONE_CC_Money, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Money;
+ avp_AAA_3GPP_DER_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DER_Flags;
+ avp_DCA_3GPP_LCS_Data_Coding_Scheme, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Data_Coding_Scheme;
avp_GI_3GPP_3GPP_GGSN_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_GGSN_Address;
avp_BASE_NONE_Proxy_Info, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Proxy_Info;
+ avp_DCA_3GPP_Related_IMS_Charging_Identifier_Node, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Related_IMS_Charging_Identifier_Node;
avp_S6_3GPP_Node_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Node_Type;
+ avp_DCA_3GPP_Talk_Burst_Volume, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Talk_Burst_Volume;
+ avp_DCA_3GPP_Service_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Id;
avp_RX_3GPP_Priority_Sharing_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Priority_Sharing_Indicator;
avp_DNAS_NONE_Tunnel_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Type;
avp_PCC_3GPP_QoS_Rule_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Name;
+ avp_DCA_3GPP_Trigger_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Trigger_Type;
+ avp_DCA_3GPP_Instance_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Instance_Id;
avp_S6_3GPP_Scheduled_Communication_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Scheduled_Communication_Time;
avp_RX_3GPP_Max_Requested_Bandwidth_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Max_Requested_Bandwidth_DL;
+ avp_DCA_3GPP_Role_Of_ProSe_Function, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Role_Of_ProSe_Function;
avp_S6_3GPP_Maximum_Latency, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Maximum_Latency;
avp_PCC_3GPP_PCC_Rule_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PCC_Rule_Status;
+ avp_DCA_3GPP_SIP_Response_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SIP_Response_Timestamp;
avp_PCC_3GPP_Extended_GBR_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Extended_GBR_DL;
avp_AAA_3GPP_MBSFN_Area, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MBSFN_Area;
+ avp_DCA_3GPP_ProSe_UE_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_UE_ID;
avp_CxDx_3GPP_Server_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Server_Name;
- avp_DCC_NONE_Check_Balance_Result, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Check_Balance_Result;
avp_S6_3GPP_APN_Validity_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_APN_Validity_Time;
- avp_AAA_3GPP_Job_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Job_Type;
avp_PCC_3GPP_Allocation_Retention_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Allocation_Retention_Priority;
+ avp_DCC_NONE_Check_Balance_Result, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Check_Balance_Result;
+ avp_AAA_3GPP_Job_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Job_Type;
avp_BASE_NONE_Destination_Host, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Destination_Host;
avp_AAA_3GPP_Positioning_Method, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Positioning_Method;
avp_CxDx_3GPP_LIA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_LIA_Flags;
avp_AAA_3GPP_DL_Buffering_Suggested_Packet_Count, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DL_Buffering_Suggested_Packet_Count;
+ avp_DCA_3GPP_AoC_Service_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Service_Type;
avp_DNAS_NONE_Login_IP_Host, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_IP_Host;
- avp_DNAS_NONE_ARAP_Security, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Security;
avp_AAA_3GPP_IDA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IDA_Flags;
+ avp_DNAS_NONE_ARAP_Security, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Security;
avp_DNAS_NONE_Origin_AAA_Protocol, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Origin_AAA_Protocol;
+ avp_DCA_3GPP_Time_Last_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Last_Usage;
avp_CxDx_3GPP_Charging_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Charging_Information;
avp_AAA_3GPP_ULA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ULA_Flags;
+ avp_DCA_3GPP_Originator_Interface, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originator_Interface;
avp_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported;
avp_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature;
- avp_DNAS_NONE_Tunnel_Assignment_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Assignment_Id;
+ avp_DCA_3GPP_File_Repair_Supported, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_File_Repair_Supported;
avp_DNAS_NONE_Framed_IPX_Network, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IPX_Network;
+ avp_DNAS_NONE_Tunnel_Assignment_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Assignment_Id;
avp_DCC_NONE_CC_Service_Specific_Units, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Service_Specific_Units;
+ avp_DCA_3GPP_SDP_Answer_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Answer_Timestamp;
+ avp_AAA_3GPP_WLAN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_Identifier;
+ avp_DCA_3GPP_Type_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Type_Number;
+ avp_DCA_3GPP_NIDD_Submission, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_NIDD_Submission;
avp_S6_3GPP_T4_Parameters, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_T4_Parameters;
avp_RX_3GPP_Access_Network_Charging_Identifier_Value, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Access_Network_Charging_Identifier_Value;
+ avp_DCA_3GPP_Announcing_UE_HPLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Announcing_UE_HPLMN_Identifier;
avp_S6_3GPP_AESE_Error_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_AESE_Error_Report;
+ avp_MIPv4_NONE_MIP_FA_to_HA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_FA_to_HA_SPI;
+ avp_DCA_3GPP_Event_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Event_Type;
avp_RX_3GPP_Sharing_Key_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Sharing_Key_DL;
avp_PCC_3GPP_ADC_Rule_Remove, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Remove;
+ avp_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container;
avp_S6_3GPP_Restricted_PLMN_List, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Restricted_PLMN_List;
- avp_AAA_3GPP_Age_Of_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Age_Of_Location_Information;
avp_PCC_3GPP_Access_Network_Charging_Identifier_Gx, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Access_Network_Charging_Identifier_Gx;
+ avp_AAA_3GPP_Age_Of_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Age_Of_Location_Information;
+ avp_DCA_3GPP_PoC_Group_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Group_Name;
avp_RX_3GPP_Extended_Max_Requested_BW_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Max_Requested_BW_DL;
avp_PCC_3GPP_Flow_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Flow_Information;
+ avp_DCA_3GPP_PS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PS_Information;
+ avp_DCA_3GPP_MTC_IWF_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MTC_IWF_Address;
+ avp_PCC_3GPP_Execution_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Execution_Time;
avp_DNAS_NONE_NAS_Identifier, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Identifier;
avp_DNAS_NONE_Tunnel_Server_Auth_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Server_Auth_Id;
- avp_PCC_3GPP_Execution_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Execution_Time;
avp_CxDx_3GPP_Contact, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Contact;
+ avp_PCC_3GPP_Charging_Correlation_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Correlation_Indicator;
avp_DCC_NONE_Credit_Control, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Credit_Control;
avp_BASE_NONE_Accounting_Record_Number, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Accounting_Record_Number;
avp_AAA_3GPP_Event_Threshold_Event_1I, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_Event_1I;
- avp_PCC_3GPP_Charging_Correlation_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Correlation_Indicator;
+ avp_DCA_3GPP_SIP_Request_Timestamp_Fraction, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SIP_Request_Timestamp_Fraction;
+ avp_DCA_3GPP_Service_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Mode;
avp_CxDx_3GPP_User_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_User_Data;
avp_AAA_3GPP_Report_Interval, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Report_Interval;
avp_PCC_3GPP_RAN_NAS_Release_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_RAN_NAS_Release_Cause;
+ avp_DCA_3GPP_Dynamic_Address_Flag_Extension, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Dynamic_Address_Flag_Extension;
avp_AAA_3GPP_Client_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Client_Identity;
avp_BASE_NONE_Redirect_Host_Usage, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Redirect_Host_Usage;
+ avp_DCA_3GPP_CSG_Access_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CSG_Access_Mode;
avp_AAA_3GPP_Equipment_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Equipment_Status;
+ avp_DCA_3GPP_Supplementary_Service, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Supplementary_Service;
avp_GI_3GPP_3GPP_Packet_Filter, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Packet_Filter;
avp_DCC_NONE_Redirect_Server_Address, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Redirect_Server_Address;
avp_MIPv6_NONE_MIP6_Auth_Mode, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP6_Auth_Mode;
avp_AAA_3GPP_EPS_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_EPS_Location_Information;
- avp_DNAS_NONE_Acct_Tunnel_Packets_Lost, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost;
+ avp_DCA_3GPP_Access_Network_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Access_Network_Information;
+ avp_DCA_3GPP_Called_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Called_Identity;
+ avp_AAA_3GPP_TWAN_Default_APN_Context_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_Default_APN_Context_Id;
+ avp_DCA_3GPP_SGSN_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SGSN_Address;
+ avp_DCA_3GPP_SGi_PtP_Tunnelling_Method, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SGi_PtP_Tunnelling_Method;
avp_BASE_NONE_Session_Timeout, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Session_Timeout;
+ avp_DNAS_NONE_Acct_Tunnel_Packets_Lost, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost;
+ avp_DCA_3GPP_NNI_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_NNI_Type;
avp_RX_3GPP_Service_Info_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Service_Info_Status;
avp_S6_3GPP_CIR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_CIR_Flags;
avp_PCC_3GPP_Precedence, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Precedence;
+ avp_DCA_3GPP_User_Participating_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_User_Participating_Type;
+ avp_DCA_3GPP_GGSN_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_GGSN_Address;
avp_RX_3GPP_Sponsoring_Action, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Sponsoring_Action;
+ avp_DCA_3GPP_Radio_Resources_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Radio_Resources_Indicator;
avp_S6_3GPP_Granted_Validity_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Granted_Validity_Time;
avp_PCC_3GPP_Priority_Level, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Priority_Level;
+ avp_DCA_3GPP_Node_Functionality, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Node_Functionality;
avp_RX_3GPP_Flow_Description, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Flow_Description;
- avp_AAA_3GPP_Daylight_Saving_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Daylight_Saving_Time;
avp_PCC_3GPP_Packet_Filter_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Packet_Filter_Information;
+ avp_AAA_3GPP_Daylight_Saving_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Daylight_Saving_Time;
+ avp_DCA_3GPP_Address_Domain, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Address_Domain;
avp_S6_3GPP_SCEF_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_SCEF_ID;
+ avp_DCA_3GPP_Content_Length, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Content_Length;
avp_PCC_3GPP_Removal_Of_Access, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Removal_Of_Access;
- avp_AAA_3GPP_Preferred_Data_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Preferred_Data_Mode;
avp_PCC_3GPP_ADC_Rule_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Report;
- avp_AAA_3GPP_UE_SRVCC_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UE_SRVCC_Capability;
+ avp_AAA_3GPP_Preferred_Data_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Preferred_Data_Mode;
+ avp_DCA_3GPP_ProSe_Functionality, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Functionality;
+ avp_DCA_3GPP_Low_Balance_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Low_Balance_Indication;
avp_PCC_3GPP_Guaranteed_Bitrate_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Guaranteed_Bitrate_UL;
- avp_DNAS_NONE_NAS_IPv6_Address, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_IPv6_Address;
+ avp_AAA_3GPP_UE_SRVCC_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UE_SRVCC_Capability;
avp_DNAS_NONE_Login_LAT_Group, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_LAT_Group;
+ avp_DNAS_NONE_NAS_IPv6_Address, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_IPv6_Address;
avp_MIPv6_NONE_MIP_MAC_Mobility_Data, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MAC_Mobility_Data;
- avp_DNAS_NONE_Accounting_Output_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Accounting_Output_Octets;
+ avp_MIPv4_NONE_Accounting_Output_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_Accounting_Output_Octets;
avp_CxDx_3GPP_To_SIP_Header, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_To_SIP_Header;
avp_AAA_3GPP_Coupled_Node_Diameter_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Coupled_Node_Diameter_ID;
+ avp_DCA_3GPP_Real_Time_Tariff_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Real_Time_Tariff_Information;
avp_AAA_3GPP_STN_SR, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_STN_SR;
+ avp_DCA_3GPP_SDP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Type;
avp_BASE_NONE_Supported_Vendor_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Supported_Vendor_Id;
avp_AAA_3GPP_ServiceTypeIdentity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ServiceTypeIdentity;
+ avp_DCA_3GPP_Requested_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Requested_Party_Address;
+ avp_DCA_3GPP_Announcement_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Announcement_Information;
avp_DNAS_NONE_Acct_Authentic, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Authentic;
avp_DCC_NONE_Service_Identifier, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Identifier;
avp_AAA_3GPP_AUTN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AUTN;
+ avp_AAA_3GPP_Non_3GPP_User_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_3GPP_User_Data;
+ avp_DCA_3GPP_Delivery_Report_Requested, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Delivery_Report_Requested;
avp_GI_3GPP_TWAN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_TWAN_Identifier;
+ avp_AAA_3GPP_Origination_Time_Stamp, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Origination_Time_Stamp;
+ avp_DCA_3GPP_LCS_APN, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_APN;
+ avp_DCA_3GPP_Envelope_End_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Envelope_End_Time;
avp_RX_3GPP_Sponsored_Connectivity_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Sponsored_Connectivity_Data;
avp_BASE_NONE_Auth_Request_Type, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Auth_Request_Type;
+ avp_DCA_3GPP_Application_Server_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Application_Server_Information;
+ avp_DCA_3GPP_Originator_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originator_Address;
+ avp_DCA_3GPP_Network_Call_Reference_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Network_Call_Reference_Number;
avp_S6_3GPP_AESE_Communication_Pattern, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_AESE_Communication_Pattern;
avp_PCC_3GPP_NBIFOM_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_NBIFOM_Mode;
- avp_DCC_NONE_Validity_Time, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Validity_Time;
avp_PCC_3GPP_Redirect_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Redirect_Information;
+ avp_DCC_NONE_Validity_Time, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Validity_Time;
+ avp_DCA_3GPP_Monitoring_UE_VPLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_UE_VPLMN_Identifier;
avp_S6_3GPP_Event_Handling, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Event_Handling;
- avp_AAA_3GPP_Tracking_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Tracking_Area_Identity;
avp_PCC_3GPP_ToS_Traffic_Class, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ToS_Traffic_Class;
+ avp_AAA_3GPP_Tracking_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Tracking_Area_Identity;
+ avp_MIPv4_NONE_MIP_HA_to_FA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_HA_to_FA_SPI;
avp_RX_3GPP_Min_Desired_Bandwidth_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Min_Desired_Bandwidth_UL;
avp_AAA_3GPP_UVR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UVR_Flags;
+ avp_DCA_3GPP_PS_Free_Format_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PS_Free_Format_Data;
avp_CxDx_3GPP_Originating_Request, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Originating_Request;
- avp_AAA_3GPP_Subscription_Data_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscription_Data_Flags;
avp_PCC_3GPP_PDN_Connection_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PDN_Connection_ID;
+ avp_AAA_3GPP_Subscription_Data_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscription_Data_Flags;
avp_DNAS_NONE_Framed_IPv6_Route, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IPv6_Route;
- avp_AAA_3GPP_DSR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DSR_Flags;
avp_PCC_3GPP_PRA_Remove, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PRA_Remove;
+ avp_AAA_3GPP_DSR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DSR_Flags;
avp_DCC_NONE_Granted_Service_Unit, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Granted_Service_Unit;
avp_MIPv6_NONE_MIP_Timestamp, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Timestamp;
+ avp_DCA_3GPP_Number_Portability_Routing_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_Portability_Routing_Information;
avp_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer;
avp_AAA_3GPP_Specific_APN_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Specific_APN_Info;
avp_AAA_3GPP_Terminal_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Terminal_Information;
avp_CxDx_3GPP_Restoration_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Restoration_Info;
avp_BASE_NONE_Product_Name, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Product_Name;
+ avp_MIPv4_NONE_MIP_HA_to_MN_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_HA_to_MN_MSA;
+ avp_DCA_3GPP_Account_Expiration, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Account_Expiration;
avp_AAA_3GPP_CSG_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_CSG_Id;
avp_DNAS_NONE_Framed_IP_Netmask, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IP_Netmask;
avp_GI_3GPP_3GPP_IPv6_DNS_Servers, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_IPv6_DNS_Servers;
+ avp_AAA_3GPP_SSID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SSID;
avp_AAA_3GPP_Call_Barring_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Call_Barring_Info;
+ avp_DCA_3GPP_BSSID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_BSSID;
avp_DCC_NONE_Service_Parameter_Info, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Parameter_Info;
- avp_BASE_NONE_Origin_State_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Origin_State_Id;
+ avp_DCA_3GPP_Talk_Burst_Exchange, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Talk_Burst_Exchange;
+ avp_DCA_3GPP_Variable_Part_Order, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Variable_Part_Order;
+ avp_DCA_3GPP_Time_Quota_Mechanism, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Quota_Mechanism;
+ avp_AAA_3GPP_ANID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ANID;
+ avp_DCA_3GPP_Monitoring_Event_Report_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_Event_Report_Number;
avp_S6_3GPP_IP_SM_GW_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_IP_SM_GW_Name;
+ avp_BASE_NONE_Origin_State_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Origin_State_Id;
avp_RX_3GPP_Media_Sub_Component, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Media_Sub_Component;
+ avp_DCA_3GPP_CN_Operator_Selection_Entity, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CN_Operator_Selection_Entity;
avp_S6_3GPP_Accuracy, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Accuracy;
avp_PCC_3GPP_Charging_Rule_Remove, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Remove;
+ avp_DCA_3GPP_Originating_IOI, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originating_IOI;
avp_RX_3GPP_Min_Requested_Bandwidth_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Min_Requested_Bandwidth_DL;
+ avp_DCA_3GPP_ProSe_Function_PLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Function_PLMN_Identifier;
avp_S6_3GPP_Service_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_Report;
avp_PCC_3GPP_Tunnel_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Tunnel_Information;
+ avp_DCA_3GPP_Bearer_Service, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Bearer_Service;
avp_CxDx_3GPP_Primary_Charging_Collection_Function_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Primary_Charging_Collection_Function_Name;
- avp_AAA_3GPP_Time_Zone, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Time_Zone;
avp_PCC_3GPP_QoS_Rule_Definition, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Definition;
+ avp_AAA_3GPP_Time_Zone, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Time_Zone;
avp_S6_3GPP_Periodic_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Periodic_Time;
avp_PCC_3GPP_Routing_Rule_Failure_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Failure_Code;
avp_PCC_3GPP_TDF_Destination_Host, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_Destination_Host;
avp_AAA_3GPP_Local_Group_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Local_Group_Id;
- avp_AAA_3GPP_Service_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Service_Area_Identity;
+ avp_DCA_3GPP_SM_Discharge_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Discharge_Time;
+ avp_DCA_3GPP_Requestor_PLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Requestor_PLMN_Identifier;
+ avp_DCA_3GPP_IMS_Application_Reference_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Application_Reference_Identifier;
avp_PCC_3GPP_Charging_Rule_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Report;
+ avp_AAA_3GPP_Service_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Service_Area_Identity;
avp_BASE_NONE_User_Name, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_User_Name;
avp_AAA_3GPP_UE_PC5_AMBR, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UE_PC5_AMBR;
avp_CxDx_3GPP_Public_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Public_Identity;
avp_BASE_NONE_Accounting_Sub_Session_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Accounting_Sub_Session_Id;
avp_DNAS_NONE_Acct_Delay_Time, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Acct_Delay_Time;
+ avp_DCA_3GPP_Local_Sequence_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Local_Sequence_Number;
avp_CxDx_3GPP_UAR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_UAR_Flags;
avp_AAA_3GPP_Collection_Period_RRM_UMTS, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Collection_Period_RRM_UMTS;
avp_AAA_3GPP_Operator_Determined_Barring, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Operator_Determined_Barring;
+ avp_DCA_3GPP_Recipient_Received_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Recipient_Received_Address;
avp_DNAS_NONE_Tunnel_Server_Endpoint, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Server_Endpoint;
+ avp_MIPv4_NONE_MIP_Candidate_Home_Agent_Host, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Candidate_Home_Agent_Host;
avp_BASE_NONE_Session_Binding, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Session_Binding;
avp_GI_3GPP_3GPP_IMEISV, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_IMEISV;
avp_AAA_3GPP_SS_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SS_Code;
+ avp_DCA_3GPP_DCD_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_DCD_Information;
+ avp_DCA_3GPP_Location_Estimate_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Location_Estimate_Type;
+ avp_DCA_3GPP_Time_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Indicator;
+ avp_DCA_3GPP_Addressee_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Addressee_Type;
avp_BASE_NONE_Acct_Multi_Session_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Acct_Multi_Session_Id;
avp_DCC_NONE_Subscription_Id_Data, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Subscription_Id_Data;
+ avp_AAA_3GPP_TWAN_Connectivity_Parameters, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_Connectivity_Parameters;
+ avp_DCA_3GPP_Reply_Applic_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Reply_Applic_ID;
+ avp_DCA_3GPP_Participant_Access_Priority, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Participant_Access_Priority;
avp_RX_3GPP_RS_Bandwidth, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_RS_Bandwidth;
- avp_MIPv6_NONE_MIP_Algorithm_Type, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Algorithm_Type;
avp_S6_3GPP_Reachability_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Reachability_Information;
+ avp_MIPv4_NONE_MIP_Algorithm_Type, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Algorithm_Type;
+ avp_DCA_3GPP_SDP_Session_Description, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Session_Description;
avp_RX_3GPP_Extended_Min_Desired_BW_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Min_Desired_BW_DL;
- avp_AAA_3GPP_Event_Threshold_RSRQ, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_RSRQ;
+ avp_DCA_3GPP_Location_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Location_Info;
avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL;
+ avp_AAA_3GPP_Event_Threshold_RSRQ, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_RSRQ;
+ avp_DCA_3GPP_LCS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Information;
avp_S6_3GPP_Service_Parameters, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_Parameters;
avp_PCC_3GPP_Presence_Reporting_Area_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Presence_Reporting_Area_Information;
avp_PCC_3GPP_Routing_Rule_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Identifier;
+ avp_DCA_3GPP_SMS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SMS_Information;
+ avp_DCA_3GPP_ePDG_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ePDG_Address;
avp_PCC_3GPP_Event_Trigger, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Event_Trigger;
avp_RX_3GPP_GCS_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_GCS_Identifier;
avp_MIPv6_NONE_QoS_Capability, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_QoS_Capability;
- avp_DCC_NONE_G_S_U_Pool_Identifier, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_G_S_U_Pool_Identifier;
- avp_AAA_3GPP_Non_IP_PDN_Type_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator;
avp_PCC_3GPP_ADC_Rule_Install, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Install;
+ avp_AAA_3GPP_Non_IP_PDN_Type_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator;
+ avp_DCC_NONE_G_S_U_Pool_Identifier, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_G_S_U_Pool_Identifier;
+ avp_DCA_3GPP_Outgoing_Session_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Outgoing_Session_Id;
+ avp_DCA_3GPP_PoC_Controlling_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Controlling_Address;
+ avp_DCA_3GPP_Dynamic_Address_Flag, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Dynamic_Address_Flag;
avp_CxDx_3GPP_Confidentiality_Key, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Confidentiality_Key;
avp_PCC_3GPP_Flow_Label, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Flow_Label;
avp_DNAS_NONE_NAS_Port, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_Port;
avp_AAA_3GPP_Authentication_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Authentication_Info;
+ avp_DCA_3GPP_Transcoder_Inserted_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Transcoder_Inserted_Indication;
+ avp_DCA_3GPP_SMS_Node, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SMS_Node;
avp_AAA_3GPP_Trace_Interface_List, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Interface_List;
+ avp_DCA_3GPP_SGW_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SGW_Address;
avp_GI_3GPP_3GPP_Charging_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Charging_Id;
avp_DNAS_NONE_CHAP_Algorithm, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Algorithm;
avp_AAA_3GPP_APN_Configuration_Profile, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_APN_Configuration_Profile;
+ avp_DCA_3GPP_Number_Of_Received_Talk_Bursts, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_Of_Received_Talk_Bursts;
+ avp_AAA_3GPP_Full_Network_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Full_Network_Name;
+ avp_DCA_3GPP_Message_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Message_Type;
+ avp_DCA_3GPP_APN_Rate_Control_Uplink, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_APN_Rate_Control_Uplink;
avp_GI_3GPP_3GPP_CAMEL_Charging_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_CAMEL_Charging_Info;
+ avp_DCA_3GPP_From_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_From_Address;
+ avp_AAA_3GPP_TWAG_CP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAG_CP_Address;
+ avp_DCA_3GPP_PDP_Context_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PDP_Context_Type;
avp_RX_3GPP_Flows, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Flows;
+ avp_DCA_3GPP_User_Session_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_User_Session_Id;
+ avp_DCA_3GPP_PoC_Change_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Change_Time;
+ avp_DCA_3GPP_Privacy_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Privacy_Indicator;
avp_S6_3GPP_CIA_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_CIA_Flags;
avp_RX_3GPP_Extended_Min_Requested_BW_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Min_Requested_BW_UL;
avp_PCC_3GPP_Monitoring_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Monitoring_Time;
avp_DCC_NONE_CC_Input_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Input_Octets;
+ avp_DCA_3GPP_Teleservice, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Teleservice;
+ avp_DCA_3GPP_Quota_Consumption_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Quota_Consumption_Time;
avp_S6_3GPP_UE_Reachability_Configuration, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_UE_Reachability_Configuration;
avp_BASE_NONE_Destination_Realm, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Destination_Realm;
avp_RX_3GPP_Acceptable_Service_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Acceptable_Service_Info;
avp_PCC_3GPP_Flow_Direction, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Flow_Direction;
+ avp_DCA_3GPP_ProSe_Reason_For_Cancellation, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Reason_For_Cancellation;
avp_S6_3GPP_Supported_Monitoring_Events, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Supported_Monitoring_Events;
+ avp_DCA_3GPP_CG_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CG_Address;
+ avp_DCA_3GPP_Radio_Parameter_Set_Values, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Radio_Parameter_Set_Values;
avp_CxDx_3GPP_SIP_Item_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Item_Number;
avp_PCC_3GPP_Session_Release_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Session_Release_Cause;
avp_AAA_3GPP_MDT_User_Consent, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MDT_User_Consent;
- avp_DNAS_NONE_Login_LAT_Port, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_LAT_Port;
avp_S6_3GPP_HSS_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_HSS_Cause;
- avp_DCC_NONE_G_S_U_Pool_Reference, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_G_S_U_Pool_Reference;
+ avp_MIPv6_NONE_MIP6_Home_Link_Prefix, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP6_Home_Link_Prefix;
+ avp_DNAS_NONE_Login_LAT_Port, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_LAT_Port;
avp_PCC_3GPP_PCSCF_Restoration_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PCSCF_Restoration_Indication;
+ avp_DCC_NONE_G_S_U_Pool_Reference, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_G_S_U_Pool_Reference;
+ avp_DCA_3GPP_Layer_2_Group_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Layer_2_Group_ID;
+ avp_DCA_3GPP_Interface_Port, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Interface_Port;
avp_AAA_3GPP_Subscription_Data_Deletion, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscription_Data_Deletion;
avp_MIPv6_NONE_Chargable_User_Identity, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_Chargable_User_Identity;
avp_AAA_3GPP_Trace_Collection_Entity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_Collection_Entity;
+ avp_DCA_3GPP_AoC_Request_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Request_Type;
avp_CxDx_3GPP_Feature_List_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Feature_List_ID;
avp_BASE_NONE_Redirect_Host, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Redirect_Host;
avp_AAA_3GPP_Network_Access_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Network_Access_Mode;
- avp_DNAS_NONE_ARAP_Zone_Access, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Zone_Access;
avp_DNAS_NONE_Framed_Compression, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Compression;
+ avp_DNAS_NONE_ARAP_Zone_Access, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Zone_Access;
avp_GI_3GPP_3GPP_Selection_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Selection_Mode;
avp_DNAS_NONE_QoS_Filter_Rule, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_QoS_Filter_Rule;
avp_AAA_3GPP_Complete_Data_List_Included_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Complete_Data_List_Included_Indicator;
- avp_MIPv6_NONE_MIP_MN_AAA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MN_AAA_SPI;
+ avp_MIPv4_NONE_MIP_MN_AAA_SPI, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_MN_AAA_SPI;
+ avp_DCA_3GPP_LCS_Client_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Client_Name;
avp_GI_3GPP_3GPP_SGSN_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_SGSN_Address;
- avp_MIPv6_NONE_MIP_MSA_Lifetime, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_MSA_Lifetime;
+ avp_DCA_3GPP_Related_IMS_Charging_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Related_IMS_Charging_Identifier;
+ avp_DCA_3GPP_Called_Asserted_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Called_Asserted_Identity;
+ avp_DCA_3GPP_TWAG_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_TWAG_Address;
+ avp_MIPv4_NONE_MIP_MSA_Lifetime, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_MSA_Lifetime;
+ avp_DCA_3GPP_Talk_Burst_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Talk_Burst_Time;
+ avp_DCA_3GPP_Token_Text, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Token_Text;
+ avp_DCA_3GPP_Rate_Control_Time_Unit, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Rate_Control_Time_Unit;
avp_GI_3GPP_External_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_External_Identifier;
+ avp_DCA_3GPP_Reason_Header, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Reason_Header;
+ avp_AAA_3GPP_WLCP_Key, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLCP_Key;
avp_S6_3GPP_Reachability_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Reachability_Type;
- avp_DNAS_NONE_Tunnel_Private_Group_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Private_Group_Id;
+ avp_DCA_3GPP_SIP_Request_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SIP_Request_Timestamp;
avp_DNAS_NONE_Framed_Route, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Route;
+ avp_DNAS_NONE_Tunnel_Private_Group_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Private_Group_Id;
avp_DCC_NONE_CC_Request_Type, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Request_Type;
+ avp_DCA_3GPP_ProSe_Source_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Source_IP_Address;
avp_S6_3GPP_Type_Of_External_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Type_Of_External_Identifier;
avp_PCC_3GPP_Event_Report_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Event_Report_Indication;
avp_AAA_3GPP_MDT_Configuration, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MDT_Configuration;
avp_PCC_3GPP_Usage_Monitoring_Report, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Usage_Monitoring_Report;
+ avp_DCA_3GPP_Number_Of_Participants, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_Of_Participants;
+ avp_DCA_3GPP_MSC_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MSC_Address;
avp_CxDx_3GPP_Priviledged_Sender_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Priviledged_Sender_Indication;
avp_AAA_3GPP_Adjacent_Access_Restriction_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Adjacent_Access_Restriction_Data;
+ avp_DCA_3GPP_AoC_Service_Obligatory_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Service_Obligatory_Type;
avp_AAA_3GPP_RAT_Frequency_Selection_Priority_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_RAT_Frequency_Selection_Priority_ID;
+ avp_DCA_3GPP_Time_First_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_First_Usage;
avp_CxDx_3GPP_Reason_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Reason_Info;
- avp_AAA_3GPP_CLR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_CLR_Flags;
avp_PCC_3GPP_Default_EPS_Bearer_QoS, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Default_EPS_Bearer_QoS;
+ avp_AAA_3GPP_CLR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_CLR_Flags;
avp_AAA_3GPP_ULR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ULR_Flags;
- avp_DNAS_NONE_Tunnel_Client_Auth_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Client_Auth_Id;
- avp_DNAS_NONE_Calling_Station_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Calling_Station_Id;
+ avp_DCA_3GPP_Originating_SCCP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originating_SCCP_Address;
avp_AAA_3GPP_ICS_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_ICS_Indicator;
+ avp_DNAS_NONE_Calling_Station_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Calling_Station_Id;
+ avp_DNAS_NONE_Tunnel_Client_Auth_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Client_Auth_Id;
avp_DCC_NONE_Currency_Code, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Currency_Code;
avp_AAA_3GPP_Cancellation_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Cancellation_Type;
avp_BASE_NONE_E2E_Sequence, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_E2E_Sequence;
avp_BASE_NONE_Origin_Realm, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Origin_Realm;
avp_AAA_3GPP_PDN_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PDN_Type;
+ avp_DCA_3GPP_Scale_Factor, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Scale_Factor;
+ avp_DCA_3GPP_IM_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IM_Information;
avp_DNAS_NONE_Prompt, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Prompt;
+ avp_DCA_3GPP_SDP_Offer_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Offer_Timestamp;
+ avp_AAA_3GPP_PPR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PPR_Flags;
+ avp_DCA_3GPP_MM_Content_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MM_Content_Type;
+ avp_DCA_3GPP_CPDT_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CPDT_Information;
avp_GI_3GPP_3GPP_GGSN_IPv6_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_GGSN_IPv6_Address;
+ avp_AAA_3GPP_DER_S6b_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_DER_S6b_Flags;
+ avp_DCA_3GPP_SCS_Realm, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SCS_Realm;
+ avp_DCA_3GPP_LCS_Requestor_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Requestor_Id;
avp_RX_3GPP_Access_Network_Charging_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Access_Network_Charging_Identifier;
avp_DCC_NONE_Redirect_Server, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Redirect_Server;
avp_S6_3GPP_AESE_Communication_Pattern_Config_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_AESE_Communication_Pattern_Config_Status;
+ avp_DCA_3GPP_PoC_User_Role_info_Units, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_User_Role_info_Units;
+ avp_DCA_3GPP_Variable_Part, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Variable_Part;
+ avp_DCA_3GPP_ProSe_3rd_Party_Application_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_3rd_Party_Application_ID;
avp_S6_3GPP_Enhanced_Coverage_Restriction_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Enhanced_Coverage_Restriction_Data;
avp_PCC_3GPP_Bearer_Operation, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Bearer_Operation;
avp_AAA_3GPP_Current_Location_Retrieved, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Current_Location_Retrieved;
avp_RX_3GPP_Pre_emption_Control_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Pre_emption_Control_Info;
avp_PCC_3GPP_TDF_Application_Instance_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_Application_Instance_Identifier;
+ avp_DCA_3GPP_SM_Device_Trigger_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Device_Trigger_Information;
+ avp_DCA_3GPP_Service_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Service_Information;
avp_BASE_NONE_Acct_Interim_Interval, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Acct_Interim_Interval;
avp_RX_3GPP_Media_Component_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Media_Component_Number;
avp_CxDx_3GPP_Path, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Path;
- avp_AAA_3GPP_Event_Threshold_Event_1F, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_Event_1F;
avp_PCC_3GPP_Packet_Filter_Usage, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Packet_Filter_Usage;
+ avp_AAA_3GPP_Event_Threshold_Event_1F, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Event_Threshold_Event_1F;
avp_S6_3GPP_MONTE_Location_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_MONTE_Location_Type;
+ avp_DCA_3GPP_Inter_Operator_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Inter_Operator_Identifier;
avp_AAA_3GPP_RDS_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_RDS_Indicator;
+ avp_DCA_3GPP_Proximity_Cancellation_Timestamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Proximity_Cancellation_Timestamp;
+ avp_DCA_3GPP_MMTel_SService_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MMTel_SService_Type;
avp_CxDx_3GPP_Optional_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Optional_Capability;
- avp_AAA_3GPP_Reporting_Trigger, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Reporting_Trigger;
avp_PCC_3GPP_Tunnel_Header_Length, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Tunnel_Header_Length;
+ avp_AAA_3GPP_Reporting_Trigger, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Reporting_Trigger;
avp_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate;
avp_CxDx_3GPP_Secondary_Event_Charging_Function_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Secondary_Event_Charging_Function_Name;
avp_AAA_3GPP_Group_PLMN_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Group_PLMN_Id;
+ avp_DCA_3GPP_Reply_Path_Requested, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Reply_Path_Requested;
avp_AAA_3GPP_User_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_User_Id;
+ avp_DCA_3GPP_Serving_Node_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Serving_Node_Type;
avp_DNAS_NONE_Login_LAT_Node, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_LAT_Node;
avp_DNAS_NONE_Originating_Line_Info, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Originating_Line_Info;
avp_DCC_NONE_Exponent, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Exponent;
avp_MIPv6_NONE_MIP_Authenticator, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP_Authenticator;
- avp_DNAS_NONE_Accounting_Input_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Accounting_Input_Octets;
avp_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info;
+ avp_MIPv4_NONE_Accounting_Input_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_Accounting_Input_Octets;
avp_AAA_3GPP_EPS_User_State, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_EPS_User_State;
avp_BASE_NONE_Origin_Host, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Origin_Host;
+ avp_AAA_3GPP_Access_Authorization_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Access_Authorization_Flags;
+ avp_DCA_3GPP_PDP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PDP_Address;
+ avp_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator;
+ avp_DCA_3GPP_NNI_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_NNI_Information;
+ avp_DCA_3GPP_Location_Estimate, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Location_Estimate;
+ avp_DCA_3GPP_Offline_Charging, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Offline_Charging;
avp_RX_3GPP_Retry_Interval, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Retry_Interval;
avp_BASE_NONE_Accounting_Session_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Accounting_Session_Id;
+ avp_DCA_3GPP_Additional_Content_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Additional_Content_Information;
avp_DCC_NONE_Restriction_Filter_Rule, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Restriction_Filter_Rule;
+ avp_DCA_3GPP_Cause_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Cause_Code;
+ avp_AAA_3GPP_TWAN_Connection_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_Connection_Mode;
avp_PCC_3GPP_Packet_Filter_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Packet_Filter_Identifier;
+ avp_DCA_3GPP_Address_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Address_Data;
avp_S6_3GPP_SCEF_Reference_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_SCEF_Reference_ID;
+ avp_DCA_3GPP_Content_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Content_Type;
avp_PCC_3GPP_Resource_Release_Notification, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Resource_Release_Notification;
avp_PCC_3GPP_ADC_Rule_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Name;
+ avp_DCA_3GPP_ProSe_Function_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Function_IP_Address;
+ avp_PCC_3GPP_Guaranteed_Bitrate_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Guaranteed_Bitrate_DL;
avp_BASE_NONE_Disconnect_Cause, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Disconnect_Cause;
avp_AAA_3GPP_Error_Diagnostic, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Error_Diagnostic;
- avp_PCC_3GPP_Guaranteed_Bitrate_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Guaranteed_Bitrate_DL;
avp_RX_3GPP_Extended_Max_Supported_BW_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Max_Supported_BW_UL;
- avp_DCC_NONE_CC_Total_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Total_Octets;
avp_PCC_3GPP_UDP_Source_Port, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_UDP_Source_Port;
+ avp_DCC_NONE_CC_Total_Octets, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Total_Octets;
avp_BASE_NONE_Accounting_Record_Type, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Accounting_Record_Type;
+ avp_DCA_3GPP_SMS_Result, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SMS_Result;
+ avp_DCA_3GPP_MMS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MMS_Information;
avp_CxDx_3GPP_From_SIP_Header, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_From_SIP_Header;
- avp_AAA_3GPP_SIPTO_Local_Network_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SIPTO_Local_Network_Permission;
avp_PCC_3GPP_Routing_Rule_Definition, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Routing_Rule_Definition;
- avp_DCC_NONE_Value_Digits, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Value_Digits;
+ avp_AAA_3GPP_SIPTO_Local_Network_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SIPTO_Local_Network_Permission;
+ avp_DCA_3GPP_CUG_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_CUG_Information;
avp_AAA_3GPP_VPLMN_Dynamic_Address_Allowed, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_VPLMN_Dynamic_Address_Allowed;
+ avp_DCC_NONE_Value_Digits, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Value_Digits;
+ avp_MIPv4_NONE_MIP_MN_AAA_Auth, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_MN_AAA_Auth;
avp_BASE_NONE_Acct_Application_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Acct_Application_Id;
+ avp_DCA_3GPP_Associated_Party_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Associated_Party_Address;
avp_CxDx_3GPP_SIP_Authenticate, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Authenticate;
avp_AAA_3GPP_Service_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Service_Type;
avp_AAA_3GPP_Immediate_Response_Preferred, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Immediate_Response_Preferred;
- avp_DNAS_NONE_Login_IPv6_Host, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_IPv6_Host;
avp_DNAS_NONE_Framed_Appletalk_Zone, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_Appletalk_Zone;
- avp_DCC_NONE_Final_Unit_Indication, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Final_Unit_Indication;
+ avp_DNAS_NONE_Login_IPv6_Host, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_IPv6_Host;
+ avp_DCA_3GPP_Local_GW_Inserted_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Local_GW_Inserted_Indication;
avp_AAA_3GPP_XRES, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_XRES;
+ avp_DCC_NONE_Final_Unit_Indication, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Final_Unit_Indication;
+ avp_DCA_3GPP_Deferred_Location_Event_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Deferred_Location_Event_Type;
avp_GI_3GPP_3GPP_IMSI, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_IMSI;
avp_AAA_3GPP_User_State, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_User_State;
+ avp_MIPv4_NONE_MIP_MN_to_HA_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_MN_to_HA_MSA;
avp_BASE_NONE_Result_Code, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Result_Code;
+ avp_DCA_3GPP_Envelope, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Envelope;
+ avp_DCA_3GPP_Monitoring_Event_Configuration_Activity, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_Event_Configuration_Activity;
+ avp_DCA_3GPP_IMS_Communication_Service_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Communication_Service_Identifier;
avp_DNAS_NONE_Framed_IP_Address, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_IP_Address;
+ avp_AAA_3GPP_Trust_Relationship_Update, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trust_Relationship_Update;
+ avp_DCA_3GPP_APN_Rate_Control_Downlink, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_APN_Rate_Control_Downlink;
+ avp_DCA_3GPP_Session_Direction, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Session_Direction;
avp_S6_3GPP_IP_SM_GW_Realm, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_IP_SM_GW_Realm;
+ avp_DCA_3GPP_Monitoring_UE_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_UE_Identifier;
avp_S6_3GPP_Reference_ID_Validity_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Reference_ID_Validity_Time;
- avp_AAA_3GPP_E_UTRAN_Cell_Global_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity;
avp_PCC_3GPP_TFT_Packet_Filter_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TFT_Packet_Filter_Information;
+ avp_AAA_3GPP_E_UTRAN_Cell_Global_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity;
avp_RX_3GPP_Min_Desired_Bandwidth_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Min_Desired_Bandwidth_DL;
+ avp_DCA_3GPP_Transmitter_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Transmitter_Info;
avp_S6_3GPP_Group_Reporting_Guard_Timer, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Group_Reporting_Guard_Timer;
+ avp_DCA_3GPP_PS_Furnish_Charging_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PS_Furnish_Charging_Information;
avp_CxDx_3GPP_Associated_Identities, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Associated_Identities;
- avp_BASE_NONE_Auth_Session_State, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Auth_Session_State;
avp_PCC_3GPP_Session_Linking_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Session_Linking_Indicator;
+ avp_BASE_NONE_Auth_Session_State, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Auth_Session_State;
avp_S6_3GPP_Maximum_Number_of_Reports, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Maximum_Number_of_Reports;
avp_PCC_3GPP_PRA_Install, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PRA_Install;
avp_AAA_3GPP_V2X_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_V2X_Permission;
- avp_AAA_3GPP_LIPA_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_LIPA_Permission;
+ avp_DCA_3GPP_ProSe_Range_Class, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Range_Class;
+ avp_DCA_3GPP_Carrier_Select_Routing_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Carrier_Select_Routing_Information;
avp_PCC_3GPP_QoS_Negotiation, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Negotiation;
+ avp_AAA_3GPP_LIPA_Permission, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_LIPA_Permission;
avp_CxDx_3GPP_SIP_Auth_Data_Item, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_SIP_Auth_Data_Item;
avp_AAA_3GPP_3GPP2_MEID, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_3GPP2_MEID;
+ avp_MIPv4_NONE_MIP_FA_to_MN_MSA, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_FA_to_MN_MSA;
avp_AAA_3GPP_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscription_Data;
avp_CxDx_3GPP_Multiple_Registration_Indication, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Multiple_Registration_Indication;
- avp_BASE_NONE_Vendor_Specific_Application_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Vendor_Specific_Application_Id;
avp_AAA_3GPP_WLAN_offloadability_UTRAN, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_WLAN_offloadability_UTRAN;
+ avp_BASE_NONE_Vendor_Specific_Application_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Vendor_Specific_Application_Id;
+ avp_DCA_3GPP_IMSI_Unauthenticated_Flag, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMSI_Unauthenticated_Flag;
+ avp_DCA_3GPP_Interface_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Interface_Id;
avp_AAA_3GPP_CSG_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_CSG_Subscription_Data;
+ avp_DCA_3GPP_Diagnostics, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Diagnostics;
avp_MIPv6_NONE_Service_Selection, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_Service_Selection;
avp_AAA_3GPP_TS_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TS_Code;
avp_DNAS_NONE_Tunnel_Client_Endpoint, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Tunnel_Client_Endpoint;
+ avp_AAA_3GPP_AN_Trusted, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AN_Trusted;
+ avp_DCA_3GPP_Monitoring_Event_Funtionality, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Monitoring_Event_Funtionality;
+ avp_DCA_3GPP_Aux_Applic_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Aux_Applic_Info;
+ avp_MIPv4_NONE_MIP_Nonce, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Nonce;
avp_S6_3GPP_IP_SM_GW_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_IP_SM_GW_Number;
+ avp_AAA_3GPP_AAR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AAR_Flags;
+ avp_DCA_3GPP_LCS_Client_External_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Client_External_ID;
+ avp_DCA_3GPP_VLR_Number, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_VLR_Number;
avp_PCC_3GPP_Charging_Rule_Install, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Install;
avp_RX_3GPP_Rx_Request_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Rx_Request_Type;
avp_S6_3GPP_NIDD_Authorization_Response, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_NIDD_Authorization_Response;
+ avp_DCA_3GPP_Outgoing_Trunk_Group_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Outgoing_Trunk_Group_Id;
+ avp_AAA_3GPP_Transport_Access_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Transport_Access_Type;
avp_DCC_NONE_Subscription_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Subscription_Id;
- avp_AAA_3GPP_VPLMN_CSG_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data;
avp_PCC_3GPP_QoS_Rule_Remove, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_QoS_Rule_Remove;
+ avp_AAA_3GPP_VPLMN_CSG_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data;
+ avp_DCA_3GPP_Message_Body, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Message_Body;
avp_S6_3GPP_Communication_Duration_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Communication_Duration_Time;
avp_PCC_3GPP_Access_Availability_Change_Reason, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Access_Availability_Change_Reason;
avp_PCC_3GPP_TDF_Application_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_Application_Identifier;
+ avp_DCA_3GPP_Requested_PLMN_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Requested_PLMN_Identifier;
avp_AAA_3GPP_Location_Area_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Location_Area_Identity;
avp_RX_3GPP_Media_Component_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Media_Component_Status;
avp_AAA_3GPP_eDRX_Cycle_Length_Value, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_eDRX_Cycle_Length_Value;
+ avp_MIPv4_NONE_MIP_FA_Challenge, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_FA_Challenge;
avp_CxDx_3GPP_Visited_Network_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Visited_Network_Identifier;
avp_S6_3GPP_RIR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_RIR_Flags;
- avp_AAA_3GPP_Collection_Period_RRM_LTE, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Collection_Period_RRM_LTE;
+ avp_DCA_3GPP_Volume_Quota_Threshold, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Volume_Quota_Threshold;
+ avp_DCA_3GPP_Incremental_Cost, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Incremental_Cost;
avp_PCC_3GPP_Usage_Monitoring_Level, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Usage_Monitoring_Level;
- avp_AAA_3GPP_Subscriber_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscriber_Status;
+ avp_AAA_3GPP_Collection_Period_RRM_LTE, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Collection_Period_RRM_LTE;
avp_PCC_3GPP_Extended_APN_AMBR_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Extended_APN_AMBR_UL;
+ avp_AAA_3GPP_Subscriber_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Subscriber_Status;
avp_CxDx_3GPP_Identity_with_Emergency_Registration, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Identity_with_Emergency_Registration;
+ avp_DCA_3GPP_Originator_Received_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Originator_Received_Address;
+ avp_DCA_3GPP_AoC_Service, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Service;
avp_DCC_NONE_Tariff_Change_Usage, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Tariff_Change_Usage;
avp_AAA_3GPP_LCS_PrivacyException, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_LCS_PrivacyException;
avp_AAA_3GPP_QoS_Subscribed, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_QoS_Subscribed;
avp_DNAS_NONE_NAS_IP_Address, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_NAS_IP_Address;
+ avp_DCA_3GPP_Variable_Part_Value, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Variable_Part_Value;
+ avp_DCA_3GPP_Read_Reply_Report_Requested, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Read_Reply_Report_Requested;
+ avp_DCA_3GPP_Event_Charging_TimeStamp, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Event_Charging_TimeStamp;
avp_RX_3GPP_RR_Bandwidth, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_RR_Bandwidth;
- avp_DCC_NONE_Service_Context_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Context_Id;
avp_DNAS_NONE_CHAP_Auth, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_CHAP_Auth;
+ avp_DCC_NONE_Service_Context_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Service_Context_Id;
+ avp_MIPv4_NONE_MIP_Authenticator_Length, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Authenticator_Length;
+ avp_DCA_3GPP_SDP_TimeStamps, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_TimeStamps;
+ avp_DCA_3GPP_IMS_Charging_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_IMS_Charging_Identifier;
+ avp_AAA_3GPP_MIP_FA_RK_SPI, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MIP_FA_RK_SPI;
+ avp_DCA_3GPP_Related_Trigger, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Related_Trigger;
avp_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL;
avp_S6_3GPP_SCS_Identity, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_SCS_Identity;
+ avp_DCA_3GPP_LCS_Name_String, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_LCS_Name_String;
avp_RX_3GPP_Access_Network_Charging_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Access_Network_Charging_Address;
avp_PCC_3GPP_Presence_Reporting_Area_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Presence_Reporting_Area_Identifier;
avp_BASE_NONE_Inband_Security_Id, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Inband_Security_Id;
+ avp_DCA_3GPP_ISUP_Cause_Value, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ISUP_Cause_Value;
avp_PCC_3GPP_Charging_Rule_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Charging_Rule_Name;
avp_RX_3GPP_Ip_Domain_Id, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Ip_Domain_Id;
- avp_AAA_3GPP_UE_Usage_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UE_Usage_Type;
avp_PCC_3GPP_TDF_IP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_TDF_IP_Address;
+ avp_AAA_3GPP_UE_Usage_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_UE_Usage_Type;
avp_S6_3GPP_Enhanced_Coverage_Restriction, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Enhanced_Coverage_Restriction;
+ avp_DCA_3GPP_Charged_Party, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Charged_Party;
+ avp_DCA_3GPP_PDN_Connection_Charging_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PDN_Connection_Charging_ID;
avp_CxDx_3GPP_User_Data_Already_Available, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_User_Data_Already_Available;
- avp_AAA_3GPP_MME_Number_for_MT_SMS, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MME_Number_for_MT_SMS;
avp_PCC_3GPP_Security_Parameter_Index, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Security_Parameter_Index;
- avp_DCC_NONE_CC_Correlation_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Correlation_Id;
+ avp_AAA_3GPP_MME_Number_for_MT_SMS, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_MME_Number_for_MT_SMS;
avp_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL;
+ avp_DCC_NONE_CC_Correlation_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Correlation_Id;
+ avp_MIPv4_NONE_MIP_Home_Agent_Host, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Home_Agent_Host;
avp_BASE_NONE_Route_Record, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Route_Record;
+ avp_DCA_3GPP_SM_User_Data_Header, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_User_Data_Header;
avp_AAA_3GPP_Carrier_Frequency, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Carrier_Frequency;
+ avp_DCA_3GPP_MMTel_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MMTel_Information;
avp_CxDx_3GPP_Mandatory_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Mandatory_Capability;
avp_AAA_3GPP_Trace_NE_Type_List, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Trace_NE_Type_List;
+ avp_DCA_3GPP_Charging_Characteristics_Selection_Mode, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Charging_Characteristics_Selection_Mode;
avp_DNAS_NONE_Port_Limit, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Port_Limit;
+ avp_MIPv6_NONE_MIP6_Feature_Vector, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv6_NONE_MIP6_Feature_Vector;
avp_DCC_NONE_Multiple_Services_Credit_Control, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Multiple_Services_Credit_Control;
avp_AAA_3GPP_All_APN_Configurations_Included_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_All_APN_Configurations_Included_Indicator;
avp_AAA_3GPP_NOR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_NOR_Flags;
+ avp_DCA_3GPP_Message_ID, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Message_ID;
avp_GI_3GPP_3GPP_MS_TimeZone, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_MS_TimeZone;
avp_AAA_3GPP_External_Client, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_External_Client;
+ avp_DCA_3GPP_Charge_Reason_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Charge_Reason_Code;
avp_BASE_NONE_Authorization_Lifetime, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Authorization_Lifetime;
+ avp_AAA_3GPP_TWAN_PCO, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_TWAN_PCO;
+ avp_DCA_3GPP_PoC_Change_Conditions, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Change_Conditions;
+ avp_DCA_3GPP_Language, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Language;
+ avp_RX_3GPP_Extended_Min_Requested_BW_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Min_Requested_BW_DL;
avp_DNAS_NONE_ARAP_Features, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Features;
avp_DNAS_NONE_Framed_MTU, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Framed_MTU;
- avp_RX_3GPP_Extended_Min_Requested_BW_DL, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Extended_Min_Requested_BW_DL;
+ avp_DCA_3GPP_Unit_Quota_Threshold, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Unit_Quota_Threshold;
avp_DNAS_NONE_Accounting_Auth_Method, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Accounting_Auth_Method;
+ avp_MIPv4_NONE_MIP_Authenticator_Offset, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_MIP_Authenticator_Offset;
+ avp_DCA_3GPP_MBMS_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MBMS_Information;
+ avp_DCA_3GPP_Bearer_Capability, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Bearer_Capability;
avp_RX_3GPP_Service_URN, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Service_URN;
avp_S6_3GPP_Supported_Services, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Supported_Services;
- avp_DNAS_NONE_Accounting_Output_Packets, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Accounting_Output_Packets;
- avp_AAA_3GPP_Relay_Node_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Relay_Node_Indicator;
+ avp_DCA_3GPP_SDP_Media_Description, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SDP_Media_Description;
+ avp_MIPv4_NONE_Accounting_Output_Packets, avp_header.avp_code.vendor_id_NONE = avp_code_MIPv4_NONE_Accounting_Output_Packets;
+ avp_DCA_3GPP_Radio_Parameter_Set_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Radio_Parameter_Set_Info;
avp_PCC_3GPP_Rule_DeActivation_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Rule_DeActivation_Time;
+ avp_AAA_3GPP_Relay_Node_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Relay_Node_Indicator;
avp_S6_3GPP_T4_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_T4_Data;
avp_PCC_3GPP_Fixed_User_Location_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Fixed_User_Location_Info;
+ avp_DCA_3GPP_Coverage_Status, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Coverage_Status;
avp_PCC_3GPP_Online, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Online;
avp_PCC_3GPP_ADC_Rule_Base_Name, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_ADC_Rule_Base_Name;
avp_AAA_3GPP_SCEF_Realm, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SCEF_Realm;
+ avp_DCA_3GPP_MBMS_Charged_Party, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_MBMS_Charged_Party;
avp_S6_3GPP_Requested_Validity_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Requested_Validity_Time;
avp_DCC_NONE_CC_Request_Number, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Request_Number;
+ avp_DCA_3GPP_AoC_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_AoC_Information;
avp_CxDx_3GPP_Supported_Features, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Supported_Features;
avp_AAA_3GPP_Local_Time_Zone, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Local_Time_Zone;
avp_AAA_3GPP_GERAN_Vector, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_GERAN_Vector;
avp_CxDx_3GPP_Call_ID_SIP_Header, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Call_ID_SIP_Header;
+ avp_DCA_3GPP_Online_Charging_Flag, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Online_Charging_Flag;
+ avp_DCA_3GPP_Number_of_Messages_Sent, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Number_of_Messages_Sent;
avp_AAA_3GPP_EPS_Subscribed_QoS_Profile, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_EPS_Subscribed_QoS_Profile;
avp_GI_3GPP_3GPP_Session_Stop_Indicator, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Session_Stop_Indicator;
avp_AAA_3GPP_GPRS_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_GPRS_Subscription_Data;
avp_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile;
+ avp_DCA_3GPP_Access_Transfer_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Access_Transfer_Type;
avp_DNAS_NONE_Called_Station_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Called_Station_Id;
+ avp_DCA_3GPP_Inter_UE_Transfer, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Inter_UE_Transfer;
avp_DCC_NONE_Cost_Unit, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_Cost_Unit;
avp_BASE_NONE_Accounting_Realtime_Required, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Accounting_Realtime_Required;
avp_BASE_NONE_Termination_Cause, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Termination_Cause;
+ avp_DCA_3GPP_Received_Talk_Burst_Volume, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Received_Talk_Burst_Volume;
+ avp_DCA_3GPP_Rate_Control_Max_Rate, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Rate_Control_Max_Rate;
+ avp_DCA_3GPP_Class_Identifier, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Class_Identifier;
avp_GI_3GPP_3GPP_Allocate_IP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_GI_3GPP_3GPP_Allocate_IP_Type;
+ avp_AAA_3GPP_SM_Back_Off_Timer, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SM_Back_Off_Timer;
avp_RX_3GPP_Specific_Action, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_Specific_Action;
+ avp_S6_3GPP_Maximum_Detection_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Maximum_Detection_Time;
avp_DNAS_NONE_Login_TCP_Port, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Login_TCP_Port;
avp_DNAS_NONE_Password_Retry, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_Password_Retry;
- avp_S6_3GPP_Maximum_Detection_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Maximum_Detection_Time;
- avp_AAA_3GPP_Ext_PDP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Ext_PDP_Address;
+ avp_DCA_3GPP_Time_Stamps, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_Stamps;
+ avp_DCA_3GPP_Base_Time_Interval, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Base_Time_Interval;
+ avp_DCA_3GPP_UWAN_User_Location_Info, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_UWAN_User_Location_Info;
+ avp_DCA_3GPP_ProSe_Role_Of_UE, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ProSe_Role_Of_UE;
avp_PCC_3GPP_RAT_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_RAT_Type;
+ avp_AAA_3GPP_Ext_PDP_Address, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Ext_PDP_Address;
+ avp_DCA_3GPP_PoC_Session_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_PoC_Session_Type;
+ avp_DCA_3GPP_ISUP_Cause, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_ISUP_Cause;
avp_RX_3GPP_AF_Signalling_Protocol, avp_header.avp_code.vendor_id_3GPP = avp_code_RX_3GPP_AF_Signalling_Protocol;
avp_AAA_3GPP_Adjacent_PLMNs, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Adjacent_PLMNs;
avp_S6_3GPP_Service_Result_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_S6_3GPP_Service_Result_Code;
avp_AAA_3GPP_SGSN_Location_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_SGSN_Location_Information;
+ avp_DCA_3GPP_Authorised_QoS, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Authorised_QoS;
+ avp_DCA_3GPP_Time_First_Transmission, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Time_First_Transmission;
+ avp_DCA_3GPP_Stop_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Stop_Time;
avp_CxDx_3GPP_Reason_Code, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Reason_Code;
avp_PCC_3GPP_Pre_emption_Vulnerability, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Pre_emption_Vulnerability;
avp_AAA_3GPP_Equivalent_PLMN_List, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_Equivalent_PLMN_List;
avp_PCC_3GPP_Default_Access, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_Default_Access;
avp_CxDx_3GPP_Supported_Applications, avp_header.avp_code.vendor_id_3GPP = avp_code_CxDx_3GPP_Supported_Applications;
- avp_DNAS_NONE_ARAP_Challenge_Response, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Challenge_Response;
avp_BASE_NONE_Class, avp_header.avp_code.vendor_id_NONE = avp_code_BASE_NONE_Class;
+ avp_DNAS_NONE_ARAP_Challenge_Response, avp_header.avp_code.vendor_id_NONE = avp_code_DNAS_NONE_ARAP_Challenge_Response;
+ avp_DCA_3GPP_SM_Message_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_SM_Message_Type;
avp_DCC_NONE_CC_Sub_Session_Id, avp_header.avp_code.vendor_id_NONE = avp_code_DCC_NONE_CC_Sub_Session_Id;
avp_AAA_3GPP_IDR_Flags, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_IDR_Flags;
- avp_AAA_3GPP_V2X_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_V2X_Subscription_Data;
avp_PCC_3GPP_PS_to_CS_Session_Continuity, avp_header.avp_code.vendor_id_3GPP = avp_code_PCC_3GPP_PS_to_CS_Session_Continuity;
+ avp_AAA_3GPP_V2X_Subscription_Data, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_V2X_Subscription_Data;
+ avp_DCA_3GPP_Refund_Information, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Refund_Information;
+ avp_DCA_3GPP_Rate_Element, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Rate_Element;
avp_AAA_3GPP_PDP_Type, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_PDP_Type;
avp_AAA_3GPP_AMBR, avp_header.avp_code.vendor_id_3GPP = avp_code_AAA_3GPP_AMBR;
+ avp_DCA_3GPP_Submission_Time, avp_header.avp_code.vendor_id_3GPP = avp_code_DCA_3GPP_Submission_Time;
avp_UNKNOWN, OTHERWISE
)"
}
@@ -7876,20 +12444,40 @@ const AVP_Code c_AVP_Code_GI_3GPP_3GPP_SGSN_IPv6_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_SGSN_IPv6_Address };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_LAT_Service := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_LAT_Service };
+const AVP_Code c_AVP_Code_AAA_3GPP_RAR_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_RAR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_SCS_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SCS_Address };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_GGSN_MCC_MNC := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_GGSN_MCC_MNC };
const AVP_Code c_AVP_Code_DCC_NONE_Direct_Debiting_Failure_Handling := {
vendor_id_NONE := avp_code_DCC_NONE_Direct_Debiting_Failure_Handling };
const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Careof_Address := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Careof_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_TWAN_User_Location_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_TWAN_User_Location_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_User_Role_IDs := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_User_Role_IDs };
+const AVP_Code c_AVP_Code_DCA_3GPP_Announcement_Order := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Announcement_Order };
const AVP_Code c_AVP_Code_CxDx_ETSI_Line_Identifier := {
vendor_id_ETSI := avp_code_CxDx_ETSI_Line_Identifier };
const AVP_Code c_AVP_Code_PCC_3GPP_Bearer_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_Bearer_Identifier };
const AVP_Code c_AVP_Code_RX_3GPP_Content_Version := {
vendor_id_3GPP := avp_code_RX_3GPP_Content_Version };
+const AVP_Code c_AVP_Code_DCA_3GPP_Applic_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Applic_ID };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_HA_to_FA_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_HA_to_FA_MSA };
const AVP_Code c_AVP_Code_BASE_NONE_Session_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Session_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Route_Header_Transmitted := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Route_Header_Transmitted };
+const AVP_Code c_AVP_Code_DCA_3GPP_Reporting_Reason := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Reporting_Reason };
+const AVP_Code c_AVP_Code_AAA_3GPP_Emergency_Services := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Emergency_Services };
const AVP_Code c_AVP_Code_RX_3GPP_Media_Component_Description := {
vendor_id_3GPP := avp_code_RX_3GPP_Media_Component_Description };
const AVP_Code c_AVP_Code_PCC_3GPP_CSG_Information_Reporting := {
@@ -7900,6 +12488,10 @@ const AVP_Code c_AVP_Code_S6_3GPP_Location_Information_Configuration := {
vendor_id_3GPP := avp_code_S6_3GPP_Location_Information_Configuration };
const AVP_Code c_AVP_Code_PCC_3GPP_Bearer_Usage := {
vendor_id_3GPP := avp_code_PCC_3GPP_Bearer_Usage };
+const AVP_Code c_AVP_Code_DCA_3GPP_Application_provided_Called_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Application_provided_Called_Party_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Proximity_Alert_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Proximity_Alert_Timestamp };
const AVP_Code c_AVP_Code_PCC_3GPP_Tunnel_Header_Filter := {
vendor_id_3GPP := avp_code_PCC_3GPP_Tunnel_Header_Filter };
const AVP_Code c_AVP_Code_AAA_3GPP_List_Of_Measurements := {
@@ -7910,18 +12502,28 @@ const AVP_Code c_AVP_Code_PCC_3GPP_Default_QoS_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_Default_QoS_Name };
const AVP_Code c_AVP_Code_AAA_3GPP_UVA_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_UVA_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_Expires := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Expires };
const AVP_Code c_AVP_Code_CxDx_3GPP_SAR_Flags := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SAR_Flags };
-const AVP_Code c_AVP_Code_AAA_3GPP_Group_Service_Id := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Group_Service_Id };
const AVP_Code c_AVP_Code_PCC_3GPP_TDF_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_Information };
+const AVP_Code c_AVP_Code_AAA_3GPP_Group_Service_Id := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Group_Service_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Recipient_SCCP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Recipient_SCCP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Preferred_AoC_Currency := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Preferred_AoC_Currency };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Pool := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Pool };
+const AVP_Code c_AVP_Code_DCA_3GPP_Traffic_Data_Volumes := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Traffic_Data_Volumes };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Time := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Time };
const AVP_Code c_AVP_Code_AAA_3GPP_Requested_EUTRAN_Authentication_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Requested_EUTRAN_Authentication_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Unit_Cost := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Unit_Cost };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Digest_Authenticate := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Digest_Authenticate };
const AVP_Code c_AVP_Code_AAA_3GPP_Last_UE_Activity_Time := {
@@ -7930,42 +12532,72 @@ const AVP_Code c_AVP_Code_AAA_3GPP_Context_Identifier := {
vendor_id_3GPP := avp_code_AAA_3GPP_Context_Identifier };
const AVP_Code c_AVP_Code_DCC_NONE_Used_Service_Unit := {
vendor_id_NONE := avp_code_DCC_NONE_Used_Service_Unit };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Reg_Reply := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Reg_Reply };
const AVP_Code c_AVP_Code_BASE_NONE_Auth_Application_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Auth_Application_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Reference := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Reference };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_Access_Info := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_Access_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Status_AS_Code := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Status_AS_Code };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Client_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Client_Type };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Appletalk_Network := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Appletalk_Network };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IPv6_Prefix := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_IPv6_Prefix };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Session_Initiation_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Session_Initiation_Type };
const AVP_Code c_AVP_Code_RX_3GPP_Sharing_Key_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Sharing_Key_UL };
+const AVP_Code c_AVP_Code_DCA_3GPP_Content_Size := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Content_Size };
+const AVP_Code c_AVP_Code_AAA_3GPP_Access_Network_Info := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Access_Network_Info };
const AVP_Code c_AVP_Code_RX_3GPP_AF_Charging_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_AF_Charging_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Monitoring_Event_Report := {
vendor_id_3GPP := avp_code_S6_3GPP_Monitoring_Event_Report };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Specific_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Specific_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Event := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Event };
const AVP_Code c_AVP_Code_RX_3GPP_Media_Type := {
vendor_id_3GPP := avp_code_RX_3GPP_Media_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Conditional_Policy_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Conditional_Policy_Information };
const AVP_Code c_AVP_Code_BASE_NONE_Firmware_Revision := {
vendor_id_NONE := avp_code_BASE_NONE_Firmware_Revision };
-const AVP_Code c_AVP_Code_AAA_3GPP_SIPTO_Permission := {
- vendor_id_3GPP := avp_code_AAA_3GPP_SIPTO_Permission };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Event_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Event_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Network_Request_Support := {
vendor_id_3GPP := avp_code_PCC_3GPP_Network_Request_Support };
+const AVP_Code c_AVP_Code_AAA_3GPP_SIPTO_Permission := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SIPTO_Permission };
+const AVP_Code c_AVP_Code_DCA_3GPP_Terminating_IOI := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Terminating_IOI };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Max_Supported_BW_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Max_Supported_BW_DL };
const AVP_Code c_AVP_Code_PCC_3GPP_UE_Local_IP_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_UE_Local_IP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Sequence_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Sequence_Number };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Presence_Reporting_Area_Elements_List := {
vendor_id_3GPP := avp_code_PCC_3GPP_Presence_Reporting_Area_Elements_List };
-const AVP_Code c_AVP_Code_AAA_3GPP_SGs_MME_Identity := {
- vendor_id_3GPP := avp_code_AAA_3GPP_SGs_MME_Identity };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Remove := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Rule_Remove };
+const AVP_Code c_AVP_Code_AAA_3GPP_SGs_MME_Identity := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SGs_MME_Identity };
const AVP_Code c_AVP_Code_S6_3GPP_Roaming_Information := {
vendor_id_3GPP := avp_code_S6_3GPP_Roaming_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_Of_Diversions := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_Of_Diversions };
+const AVP_Code c_AVP_Code_DCA_3GPP_Coverage_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Coverage_Info };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Authentication_Scheme := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Authentication_Scheme };
const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_RSRP := {
@@ -7978,44 +12610,72 @@ const AVP_Code c_AVP_Code_AAA_3GPP_Re_Synchronization_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Re_Synchronization_Info };
const AVP_Code c_AVP_Code_BASE_NONE_Auth_Grace_Period := {
vendor_id_NONE := avp_code_BASE_NONE_Auth_Grace_Period };
+const AVP_Code c_AVP_Code_DCA_3GPP_User_CSG_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_User_CSG_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Status := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_IP_Realm_Default_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IP_Realm_Default_Indication };
const AVP_Code c_AVP_Code_AAA_3GPP_RAND := {
vendor_id_3GPP := avp_code_AAA_3GPP_RAND };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Depth := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Depth };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_MN_to_FA_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_MN_to_FA_MSA };
const AVP_Code c_AVP_Code_AAA_3GPP_SGSN_User_State := {
vendor_id_3GPP := avp_code_AAA_3GPP_SGSN_User_State };
const AVP_Code c_AVP_Code_AAA_3GPP_APN_OI_Replacement := {
vendor_id_3GPP := avp_code_AAA_3GPP_APN_OI_Replacement };
+const AVP_Code c_AVP_Code_DCA_3GPP_Alternate_Charged_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Alternate_Charged_Party_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_APN_Rate_Control := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_APN_Rate_Control };
const AVP_Code c_AVP_Code_BASE_NONE_Re_Auth_Request_Type := {
vendor_id_NONE := avp_code_BASE_NONE_Re_Auth_Request_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Relationship_Mode := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Relationship_Mode };
const AVP_Code c_AVP_Code_S6_3GPP_External_Identifier := {
vendor_id_3GPP := avp_code_S6_3GPP_External_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Positioning_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Positioning_Data };
const AVP_Code c_AVP_Code_DCC_NONE_Redirect_Address_Type := {
vendor_id_NONE := avp_code_DCC_NONE_Redirect_Address_Type };
const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MN_HA_MSA := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MN_HA_MSA };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_UE_HPLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_UE_HPLMN_Identifier };
const AVP_Code c_AVP_Code_PCC_3GPP_TFT_Filter := {
vendor_id_3GPP := avp_code_PCC_3GPP_TFT_Filter };
const AVP_Code c_AVP_Code_RX_3GPP_Max_Supported_Bandwidth_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Max_Supported_Bandwidth_UL };
-const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Medium_Type := {
- vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Medium_Type };
const AVP_Code c_AVP_Code_S6_3GPP_Loss_Of_Connectivity_Reason := {
vendor_id_3GPP := avp_code_S6_3GPP_Loss_Of_Connectivity_Reason };
+const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Medium_Type := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Medium_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originator };
const AVP_Code c_AVP_Code_DCC_NONE_User_Equipment_Info_Type := {
vendor_id_NONE := avp_code_DCC_NONE_User_Equipment_Info_Type };
const AVP_Code c_AVP_Code_RX_3GPP_Flow_Number := {
vendor_id_3GPP := avp_code_RX_3GPP_Flow_Number };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Home_Agent_Address := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Home_Agent_Address };
const AVP_Code c_AVP_Code_PCC_3GPP_Resource_Allocation_Notification := {
vendor_id_3GPP := avp_code_PCC_3GPP_Resource_Allocation_Notification };
+const AVP_Code c_AVP_Code_DCA_3GPP_Basic_Service_Code := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Basic_Service_Code };
const AVP_Code c_AVP_Code_S6_3GPP_Monitoring_Type := {
vendor_id_3GPP := avp_code_S6_3GPP_Monitoring_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Role_Of_Node := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Role_Of_Node };
const AVP_Code c_AVP_Code_PCC_3GPP_Default_Bearer_Indication := {
vendor_id_3GPP := avp_code_PCC_3GPP_Default_Bearer_Indication };
-const AVP_Code c_AVP_Code_AAA_3GPP_VPLMN_LIPA_Allowed := {
- vendor_id_3GPP := avp_code_AAA_3GPP_VPLMN_LIPA_Allowed };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Class_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Class_Identifier };
+const AVP_Code c_AVP_Code_AAA_3GPP_VPLMN_LIPA_Allowed := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_VPLMN_LIPA_Allowed };
const AVP_Code c_AVP_Code_PCC_3GPP_Mute_Notification := {
vendor_id_3GPP := avp_code_PCC_3GPP_Mute_Notification };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Authentication_Context := {
@@ -8028,104 +12688,164 @@ const AVP_Code c_AVP_Code_DCC_NONE_Service_Parameter_Value := {
vendor_id_NONE := avp_code_DCC_NONE_Service_Parameter_Value };
const AVP_Code c_AVP_Code_CxDx_3GPP_Associated_Registered_Identities := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Associated_Registered_Identities };
-const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_offloadability_EUTRAN := {
- vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_IP_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_IP_Address };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Session_Key := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Session_Key };
+const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_offloadability_EUTRAN := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_offloadability_EUTRAN };
+const AVP_Code c_AVP_Code_DCA_3GPP_MBMS_GW_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MBMS_GW_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Destination_Interface := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Destination_Interface };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Emergency_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Emergency_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Change_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Change_Time };
const AVP_Code c_AVP_Code_AAA_3GPP_KASME := {
vendor_id_3GPP := avp_code_AAA_3GPP_KASME };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Session_Key := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Session_Key };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Cost_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Cost_Information };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_User_Location_Info_Time := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_User_Location_Info_Time };
const AVP_Code c_AVP_Code_AAA_3GPP_Teleservice_List := {
vendor_id_3GPP := avp_code_AAA_3GPP_Teleservice_List };
const AVP_Code c_AVP_Code_AAA_3GPP_UTRAN_Vector := {
vendor_id_3GPP := avp_code_AAA_3GPP_UTRAN_Vector };
+const AVP_Code c_AVP_Code_AAA_3GPP_Non_3GPP_IP_Access_APN := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Non_3GPP_IP_Access_APN };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_Event_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_Event_Information };
const AVP_Code c_AVP_Code_DCC_NONE_Tariff_Time_Change := {
vendor_id_NONE := avp_code_DCC_NONE_Tariff_Time_Change };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_NSAPI := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_NSAPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Client_Dialed_By_MS := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Client_Dialed_By_MS };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_CG_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_CG_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Envelope_Start_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Envelope_Start_Time };
const AVP_Code c_AVP_Code_RX_3GPP_Application_Service_Provider_Identity := {
vendor_id_3GPP := avp_code_RX_3GPP_Application_Service_Provider_Identity };
const AVP_Code c_AVP_Code_S6_3GPP_NIDD_Authorization_Request := {
vendor_id_3GPP := avp_code_S6_3GPP_NIDD_Authorization_Request };
+const AVP_Code c_AVP_Code_DCA_3GPP_Received_Talk_Burst_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Received_Talk_Burst_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Incoming_Trunk_Group_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Incoming_Trunk_Group_Id };
+const AVP_Code c_AVP_Code_AAA_3GPP_AAA_Failure_Indication := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_AAA_Failure_Indication };
+const AVP_Code c_AVP_Code_DCA_3GPP_Rate_Control_Max_Message_Size := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Rate_Control_Max_Message_Size };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Install := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Install };
const AVP_Code c_AVP_Code_S6_3GPP_Periodic_Communication_Indicator := {
vendor_id_3GPP := avp_code_S6_3GPP_Periodic_Communication_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Specific_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Specific_Info };
const AVP_Code c_AVP_Code_RX_3GPP_Flow_Usage := {
vendor_id_3GPP := avp_code_RX_3GPP_Flow_Usage };
const AVP_Code c_AVP_Code_PCC_3GPP_RAN_Rule_Support := {
vendor_id_3GPP := avp_code_PCC_3GPP_RAN_Rule_Support };
const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Password := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Password };
+const AVP_Code c_AVP_Code_DCA_3GPP_PC3_EPC_Control_Protocol_Cause := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PC3_EPC_Control_Protocol_Cause };
const AVP_Code c_AVP_Code_S6_3GPP_Monitoring_Duration := {
vendor_id_3GPP := avp_code_S6_3GPP_Monitoring_Duration };
-const AVP_Code c_AVP_Code_AAA_3GPP_Routing_Area_Identity := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Routing_Area_Identity };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Information };
-const AVP_Code c_AVP_Code_DCC_NONE_User_Equipment_Info_Value := {
- vendor_id_NONE := avp_code_DCC_NONE_User_Equipment_Info_Value };
-const AVP_Code c_AVP_Code_DNAS_NONE_Tunneling := {
- vendor_id_NONE := avp_code_DNAS_NONE_Tunneling };
+const AVP_Code c_AVP_Code_AAA_3GPP_Routing_Area_Identity := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Routing_Area_Identity };
+const AVP_Code c_AVP_Code_DCA_3GPP_Called_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Called_Party_Address };
const AVP_Code c_AVP_Code_RX_3GPP_Service_Authorization_Info := {
vendor_id_3GPP := avp_code_RX_3GPP_Service_Authorization_Info };
-const AVP_Code c_AVP_Code_BASE_NONE_Multi_Round_Time_Out := {
- vendor_id_NONE := avp_code_BASE_NONE_Multi_Round_Time_Out };
+const AVP_Code c_AVP_Code_DNAS_NONE_Tunneling := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Tunneling };
+const AVP_Code c_AVP_Code_DCC_NONE_User_Equipment_Info_Value := {
+ vendor_id_NONE := avp_code_DCC_NONE_User_Equipment_Info_Value };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Auth_Input_Data_Length := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Auth_Input_Data_Length };
const AVP_Code c_AVP_Code_AAA_3GPP_eDRX_Cycle_Length := {
vendor_id_3GPP := avp_code_AAA_3GPP_eDRX_Cycle_Length };
+const AVP_Code c_AVP_Code_BASE_NONE_Multi_Round_Time_Out := {
+ vendor_id_NONE := avp_code_BASE_NONE_Multi_Round_Time_Out };
const AVP_Code c_AVP_Code_S6_3GPP_Group_Monitoring_Event_Report_Item := {
vendor_id_3GPP := avp_code_S6_3GPP_Group_Monitoring_Event_Report_Item };
-const AVP_Code c_AVP_Code_AAA_3GPP_Ext_PDP_Type := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Ext_PDP_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Rule_Failure_Code := {
vendor_id_3GPP := avp_code_PCC_3GPP_Rule_Failure_Code };
+const AVP_Code c_AVP_Code_AAA_3GPP_Ext_PDP_Type := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Ext_PDP_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Quota_Threshold := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Quota_Threshold };
const AVP_Code c_AVP_Code_PCC_3GPP_User_Location_Info_Time := {
vendor_id_3GPP := avp_code_PCC_3GPP_User_Location_Info_Time };
-const AVP_Code c_AVP_Code_AAA_3GPP_Measurement_Period_LTE := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Measurement_Period_LTE };
const AVP_Code c_AVP_Code_PCC_3GPP_Usage_Monitoring_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Usage_Monitoring_Information };
-const AVP_Code c_AVP_Code_BASE_NONE_Experimental_Result_Code := {
- vendor_id_NONE := avp_code_BASE_NONE_Experimental_Result_Code };
+const AVP_Code c_AVP_Code_AAA_3GPP_Measurement_Period_LTE := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Measurement_Period_LTE };
const AVP_Code c_AVP_Code_PCC_3GPP_Extended_APN_AMBR_DL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Extended_APN_AMBR_DL };
+const AVP_Code c_AVP_Code_BASE_NONE_Experimental_Result_Code := {
+ vendor_id_NONE := avp_code_BASE_NONE_Experimental_Result_Code };
const AVP_Code c_AVP_Code_CxDx_3GPP_Session_Priority := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Session_Priority };
+const AVP_Code c_AVP_Code_DCA_3GPP_Recipient_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Recipient_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Format := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Format };
+const AVP_Code c_AVP_Code_DCA_3GPP_Start_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Start_Time };
const AVP_Code c_AVP_Code_CxDx_3GPP_Deregistration_Reason := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Deregistration_Reason };
const AVP_Code c_AVP_Code_AAA_3GPP_GMLC_Number := {
vendor_id_3GPP := avp_code_AAA_3GPP_GMLC_Number };
-const AVP_Code c_AVP_Code_DNAS_NONE_Configuration_Token := {
- vendor_id_NONE := avp_code_DNAS_NONE_Configuration_Token };
-const AVP_Code c_AVP_Code_DNAS_NONE_Callback_Number := {
- vendor_id_NONE := avp_code_DNAS_NONE_Callback_Number };
const AVP_Code c_AVP_Code_AAA_3GPP_Software_Version := {
vendor_id_3GPP := avp_code_AAA_3GPP_Software_Version };
+const AVP_Code c_AVP_Code_DNAS_NONE_Callback_Number := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Callback_Number };
+const AVP_Code c_AVP_Code_DNAS_NONE_Configuration_Token := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Configuration_Token };
+const AVP_Code c_AVP_Code_DCA_3GPP_Interface_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Interface_Type };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Originating_Foreign_AAA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Originating_Foreign_AAA };
const AVP_Code c_AVP_Code_AAA_3GPP_Expiration_Date := {
vendor_id_3GPP := avp_code_AAA_3GPP_Expiration_Date };
const AVP_Code c_AVP_Code_BASE_NONE_Error_Message := {
vendor_id_NONE := avp_code_BASE_NONE_Error_Message };
const AVP_Code c_AVP_Code_AAA_3GPP_SRES := {
vendor_id_3GPP := avp_code_AAA_3GPP_SRES };
-const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Port_Type := {
- vendor_id_NONE := avp_code_DNAS_NONE_NAS_Port_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_DRM_Content := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_DRM_Content };
const AVP_Code c_AVP_Code_AAA_3GPP_Item_Number := {
vendor_id_3GPP := avp_code_AAA_3GPP_Item_Number };
+const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Port_Type := {
+ vendor_id_NONE := avp_code_DNAS_NONE_NAS_Port_Type };
+const AVP_Code c_AVP_Code_AAA_3GPP_ERP_Authorization := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_ERP_Authorization };
const AVP_Code c_AVP_Code_DCC_NONE_Multiple_Services_Indicator := {
vendor_id_NONE := avp_code_DCC_NONE_Multiple_Services_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Early_Media_Description := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Early_Media_Description };
+const AVP_Code c_AVP_Code_AAA_3GPP_MIP_FA_RK := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_MIP_FA_RK };
+const AVP_Code c_AVP_Code_DCA_3GPP_Related_Change_Condition_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Related_Change_Condition_Information };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Protocol := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Protocol };
const AVP_Code c_AVP_Code_S6_3GPP_Service_ID := {
vendor_id_3GPP := avp_code_S6_3GPP_Service_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Format_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Format_Indicator };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_IMSI_MCC_MNC := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_IMSI_MCC_MNC };
const AVP_Code c_AVP_Code_RX_3GPP_Abort_Cause := {
vendor_id_3GPP := avp_code_RX_3GPP_Abort_Cause };
+const AVP_Code c_AVP_Code_DCA_3GPP_ISUP_Cause_Location := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ISUP_Cause_Location };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Base_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Base_Name };
const AVP_Code c_AVP_Code_RX_3GPP_Required_Access_Info := {
@@ -8134,20 +12854,28 @@ const AVP_Code c_AVP_Code_PCC_3GPP_TDF_Destination_Realm := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_Destination_Realm };
const AVP_Code c_AVP_Code_S6_3GPP_S6t_HSS_Cause := {
vendor_id_3GPP := avp_code_S6_3GPP_S6t_HSS_Cause };
+const AVP_Code c_AVP_Code_DCA_3GPP_Media_Initiator_Party := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Media_Initiator_Party };
+const AVP_Code c_AVP_Code_DCA_3GPP_Associated_URI := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Associated_URI };
const AVP_Code c_AVP_Code_RX_3GPP_AF_Requested_Data := {
vendor_id_3GPP := avp_code_RX_3GPP_AF_Requested_Data };
+const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Report := {
+ vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Report };
const AVP_Code c_AVP_Code_DNAS_NONE_Filter_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_Filter_Id };
const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Password := {
vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Password };
-const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Report := {
- vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Report };
-const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Response := {
- vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Response };
+const AVP_Code c_AVP_Code_DCA_3GPP_Route_Header_Received := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Route_Header_Received };
const AVP_Code c_AVP_Code_S6_3GPP_Stationary_Indication := {
vendor_id_3GPP := avp_code_S6_3GPP_Stationary_Indication };
+const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Response := {
+ vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Response };
const AVP_Code c_AVP_Code_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_DL };
+const AVP_Code c_AVP_Code_DCA_3GPP_Usage_Information_Report_Sequence_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Usage_Information_Report_Sequence_Number };
const AVP_Code c_AVP_Code_AAA_3GPP_Geodetic_Information := {
vendor_id_3GPP := avp_code_AAA_3GPP_Geodetic_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Extended_GBR_UL := {
@@ -8158,16 +12886,22 @@ const AVP_Code c_AVP_Code_CxDx_3GPP_Server_Capabilities := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Server_Capabilities };
const AVP_Code c_AVP_Code_AAA_3GPP_Area_Scope := {
vendor_id_3GPP := avp_code_AAA_3GPP_Area_Scope };
-const AVP_Code c_AVP_Code_DNAS_NONE_Accounting_Input_Packets := {
- vendor_id_NONE := avp_code_DNAS_NONE_Accounting_Input_Packets };
+const AVP_Code c_AVP_Code_MIPv4_NONE_Accounting_Input_Packets := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_Accounting_Input_Packets };
+const AVP_Code c_AVP_Code_DCA_3GPP_SGW_Change := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SGW_Change };
const AVP_Code c_AVP_Code_CxDx_3GPP_SCSCF_Restoration_Info := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SCSCF_Restoration_Info };
const AVP_Code c_AVP_Code_CxDx_3GPP_Initial_CSeq_Sequence_Number := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Initial_CSeq_Sequence_Number };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Subscription_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Subscription_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_PUA_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_PUA_Flags };
const AVP_Code c_AVP_Code_DNAS_NONE_Callback_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_Callback_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Usage := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Usage };
const AVP_Code c_AVP_Code_CxDx_3GPP_Primary_Event_Charging_Function_Name := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Primary_Event_Charging_Function_Name };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Output_Octets := {
@@ -8180,14 +12914,30 @@ const AVP_Code c_AVP_Code_AAA_3GPP_Visited_PLMN_Id := {
vendor_id_3GPP := avp_code_AAA_3GPP_Visited_PLMN_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions := {
vendor_id_3GPP := avp_code_AAA_3GPP_Homogeneous_Support_of_IMS_Voice_Over_PS_Sessions };
+const AVP_Code c_AVP_Code_DCA_3GPP_Participant_Group := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Participant_Group };
+const AVP_Code c_AVP_Code_DCA_3GPP_Play_Alternative := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Play_Alternative };
+const AVP_Code c_AVP_Code_DCA_3GPP_MBMS_User_Service_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MBMS_User_Service_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Transit_IOI_List := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Transit_IOI_List };
const AVP_Code c_AVP_Code_RX_3GPP_Codec_Data := {
vendor_id_3GPP := avp_code_RX_3GPP_Codec_Data };
const AVP_Code c_AVP_Code_S6_3GPP_Monitoring_Event_Config_Status := {
vendor_id_3GPP := avp_code_S6_3GPP_Monitoring_Event_Config_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Media_Name := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Media_Name };
+const AVP_Code c_AVP_Code_DCA_3GPP_AF_Correlation_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AF_Correlation_Information };
const AVP_Code c_AVP_Code_DCC_NONE_Cost_Information := {
vendor_id_NONE := avp_code_DCC_NONE_Cost_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Serving_Node_Identity := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Serving_Node_Identity };
const AVP_Code c_AVP_Code_BASE_NONE_Error_Reporting_Host := {
vendor_id_NONE := avp_code_BASE_NONE_Error_Reporting_Host };
+const AVP_Code c_AVP_Code_DCA_3GPP_Radio_Frequency := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Radio_Frequency };
const AVP_Code c_AVP_Code_PCC_3GPP_Rule_Activation_Time := {
vendor_id_3GPP := avp_code_PCC_3GPP_Rule_Activation_Time };
const AVP_Code c_AVP_Code_S6_3GPP_Service_Data := {
@@ -8196,34 +12946,44 @@ const AVP_Code c_AVP_Code_RX_3GPP_AF_Application_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_AF_Application_Identifier };
const AVP_Code c_AVP_Code_PCC_3GPP_NetLoc_Access_Support := {
vendor_id_3GPP := avp_code_PCC_3GPP_NetLoc_Access_Support };
+const AVP_Code c_AVP_Code_DCA_3GPP_Announcing_UE_VPLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Announcing_UE_VPLMN_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Monitoring_Event_Configuration := {
vendor_id_3GPP := avp_code_S6_3GPP_Monitoring_Event_Configuration };
const AVP_Code c_AVP_Code_PCC_3GPP_Offline := {
vendor_id_3GPP := avp_code_PCC_3GPP_Offline };
+const AVP_Code c_AVP_Code_DCA_3GPP_SIP_Method := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SIP_Method };
+const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Definition := {
+ vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Definition };
+const AVP_Code c_AVP_Code_AAA_3GPP_Additional_Context_ID := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Additional_Context_ID };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_Service := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_Service };
const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Security_Data := {
vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Security_Data };
-const AVP_Code c_AVP_Code_AAA_3GPP_Additional_Context_ID := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Additional_Context_ID };
-const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Definition := {
- vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Definition };
const AVP_Code c_AVP_Code_S6_3GPP_Allowed_PLMN_List := {
vendor_id_3GPP := avp_code_S6_3GPP_Allowed_PLMN_List };
-const AVP_Code c_AVP_Code_AAA_3GPP_Active_APN := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Active_APN };
const AVP_Code c_AVP_Code_PCC_3GPP_Bearer_Control_Mode := {
vendor_id_3GPP := avp_code_PCC_3GPP_Bearer_Control_Mode };
+const AVP_Code c_AVP_Code_AAA_3GPP_Active_APN := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Active_APN };
const AVP_Code c_AVP_Code_PCC_3GPP_HeNB_Local_IP_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_HeNB_Local_IP_Address };
-const AVP_Code c_AVP_Code_AAA_3GPP_SMS_Register_Request := {
- vendor_id_3GPP := avp_code_AAA_3GPP_SMS_Register_Request };
const AVP_Code c_AVP_Code_PCC_3GPP_Packet_Filter_Content := {
vendor_id_3GPP := avp_code_PCC_3GPP_Packet_Filter_Content };
+const AVP_Code c_AVP_Code_AAA_3GPP_SMS_Register_Request := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SMS_Register_Request };
const AVP_Code c_AVP_Code_CxDx_3GPP_Subscription_Info := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Subscription_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_SIP_Response_Timestamp_Fraction := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SIP_Response_Timestamp_Fraction };
+const AVP_Code c_AVP_Code_DCA_3GPP_Client_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Client_Address };
const AVP_Code c_AVP_Code_AAA_3GPP_APN_Configuration := {
vendor_id_3GPP := avp_code_AAA_3GPP_APN_Configuration };
+const AVP_Code c_AVP_Code_DCA_3GPP_Subscriber_Role := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Subscriber_Role };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Number_Auth_Items := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Number_Auth_Items };
const AVP_Code c_AVP_Code_AAA_3GPP_OMC_Id := {
@@ -8236,82 +12996,158 @@ const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Preference := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Preference };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Session_Failover := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Session_Failover };
+const AVP_Code c_AVP_Code_DCA_3GPP_Enhanced_Diagnostics := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Enhanced_Diagnostics };
+const AVP_Code c_AVP_Code_DCA_3GPP_CSG_Membership_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CSG_Membership_Indication };
const AVP_Code c_AVP_Code_AAA_3GPP_Regional_Subscription_Zone_Code := {
vendor_id_3GPP := avp_code_AAA_3GPP_Regional_Subscription_Zone_Code };
+const AVP_Code c_AVP_Code_DCA_3GPP_Message_Class := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Message_Class };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Negotiated_DSCP := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Negotiated_DSCP };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_S2a_Failure_Cause := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_S2a_Failure_Cause };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_FA_to_MN_SPI := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_FA_to_MN_SPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_Trigger := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Trigger };
+const AVP_Code c_AVP_Code_DCA_3GPP_Called_Identity_Change := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Called_Identity_Change };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Request_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Request_Timestamp };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Session_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Session_Id };
const AVP_Code c_AVP_Code_BASE_NONE_Proxy_State := {
vendor_id_NONE := avp_code_BASE_NONE_Proxy_State };
-const AVP_Code c_AVP_Code_DCC_NONE_Credit_Control_Failure_Handling := {
- vendor_id_NONE := avp_code_DCC_NONE_Credit_Control_Failure_Handling };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Server_Role := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Server_Role };
+const AVP_Code c_AVP_Code_DCA_3GPP_Forwarding_Pending := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Forwarding_Pending };
const AVP_Code c_AVP_Code_S6_3GPP_SIR_Flags := {
vendor_id_3GPP := avp_code_S6_3GPP_SIR_Flags };
+const AVP_Code c_AVP_Code_DCC_NONE_Credit_Control_Failure_Handling := {
+ vendor_id_NONE := avp_code_DCC_NONE_Credit_Control_Failure_Handling };
+const AVP_Code c_AVP_Code_MIPv6_NONE_MIP6_Agent_Info := {
+ vendor_id_NONE := avp_code_MIPv6_NONE_MIP6_Agent_Info };
const AVP_Code c_AVP_Code_RX_3GPP_MPS_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_MPS_Identifier };
-const AVP_Code c_AVP_Code_AAA_3GPP_MDT_Allowed_PLMN_Id := {
- vendor_id_3GPP := avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id };
const AVP_Code c_AVP_Code_PCC_3GPP_Credit_Management_Status := {
vendor_id_3GPP := avp_code_PCC_3GPP_Credit_Management_Status };
+const AVP_Code c_AVP_Code_AAA_3GPP_MDT_Allowed_PLMN_Id := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_MDT_Allowed_PLMN_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitored_PLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitored_PLMN_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Service_Result := {
vendor_id_3GPP := avp_code_S6_3GPP_Service_Result };
-const AVP_Code c_AVP_Code_AAA_3GPP_MME_Location_Information := {
- vendor_id_3GPP := avp_code_AAA_3GPP_MME_Location_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Reporting_Level := {
vendor_id_3GPP := avp_code_PCC_3GPP_Reporting_Level };
+const AVP_Code c_AVP_Code_AAA_3GPP_MME_Location_Information := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_MME_Location_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Served_Party_IP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Served_Party_IP_Address };
const AVP_Code c_AVP_Code_RX_3GPP_Max_Supported_Bandwidth_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Max_Supported_Bandwidth_DL };
-const AVP_Code c_AVP_Code_AAA_3GPP_Subscribed_VSRVCC := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Subscribed_VSRVCC };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_First_Reception := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_First_Reception };
const AVP_Code c_AVP_Code_PCC_3GPP_Pre_emption_Capability := {
vendor_id_3GPP := avp_code_PCC_3GPP_Pre_emption_Capability };
+const AVP_Code c_AVP_Code_AAA_3GPP_Subscribed_VSRVCC := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Subscribed_VSRVCC };
const AVP_Code c_AVP_Code_PCC_3GPP_Monitoring_Flags := {
vendor_id_3GPP := avp_code_PCC_3GPP_Monitoring_Flags };
const AVP_Code c_AVP_Code_BASE_NONE_Redirect_Max_Cache_Time := {
vendor_id_NONE := avp_code_BASE_NONE_Redirect_Max_Cache_Time };
const AVP_Code c_AVP_Code_CxDx_3GPP_Feature_List := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Feature_List };
+const AVP_Code c_AVP_Code_DCA_3GPP_Address_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Address_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_TCP_Source_Port := {
vendor_id_3GPP := avp_code_PCC_3GPP_TCP_Source_Port };
const AVP_Code c_AVP_Code_PCC_3GPP_Application_Detection_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Application_Detection_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_Emergency_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Emergency_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Remaining_Balance := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Remaining_Balance };
const AVP_Code c_AVP_Code_AAA_3GPP_MPS_Priority := {
vendor_id_3GPP := avp_code_AAA_3GPP_MPS_Priority };
+const AVP_Code c_AVP_Code_DCA_3GPP_Next_Tariff := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Next_Tariff };
const AVP_Code c_AVP_Code_DCC_NONE_Requested_Action := {
vendor_id_NONE := avp_code_DCC_NONE_Requested_Action };
const AVP_Code c_AVP_Code_CxDx_3GPP_Record_Route := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Record_Route };
+const AVP_Code c_AVP_Code_DCA_3GPP_Tariff_XML := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Tariff_XML };
const AVP_Code c_AVP_Code_AAA_3GPP_Alert_Reason := {
vendor_id_3GPP := avp_code_AAA_3GPP_Alert_Reason };
+const AVP_Code c_AVP_Code_DCA_3GPP_Recipient_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Recipient_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Change_Condition := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Change_Condition };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_CG_IPv6_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_CG_IPv6_Address };
const AVP_Code c_AVP_Code_DNAS_NONE_Idle_Timeout := {
vendor_id_NONE := avp_code_DNAS_NONE_Idle_Timeout };
const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Port_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_NAS_Port_Id };
+const AVP_Code c_AVP_Code_AAA_3GPP_DEA_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_DEA_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_SCS_AS_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SCS_AS_Address };
const AVP_Code c_AVP_Code_AAA_3GPP_MO_LR := {
vendor_id_3GPP := avp_code_AAA_3GPP_MO_LR };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Visited_Network_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Visited_Network_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_User_Role := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_User_Role };
+const AVP_Code c_AVP_Code_DCA_3GPP_Announcement_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Announcement_Identifier };
+const AVP_Code c_AVP_Code_AAA_3GPP_Non_3GPP_IP_Access := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Non_3GPP_IP_Access };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_Event_Report_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_Event_Report_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_Adaptations := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Adaptations };
const AVP_Code c_AVP_Code_BASE_NONE_Host_IP_Address := {
vendor_id_NONE := avp_code_BASE_NONE_Host_IP_Address };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Reg_Request := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Reg_Request };
+const AVP_Code c_AVP_Code_DCA_3GPP_Quota_Holding_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Quota_Holding_Time };
+const AVP_Code c_AVP_Code_AAA_3GPP_Maximum_Wait_Time := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Maximum_Wait_Time };
const AVP_Code c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Max_Requested_Bandwidth_UL };
const AVP_Code c_AVP_Code_PCC_3GPP_Usage_Monitoring_Support := {
vendor_id_3GPP := avp_code_PCC_3GPP_Usage_Monitoring_Support };
const AVP_Code c_AVP_Code_S6_3GPP_Maximum_Response_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Maximum_Response_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Envelope_Reporting := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Envelope_Reporting };
+const AVP_Code c_AVP_Code_DCA_3GPP_Application_Server := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Application_Server };
const AVP_Code c_AVP_Code_RX_3GPP_Sponsor_Identity := {
vendor_id_3GPP := avp_code_RX_3GPP_Sponsor_Identity };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Appletalk_Link := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Appletalk_Link };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Interface_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Interface_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Proximity_Alert_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Proximity_Alert_Indication };
const AVP_Code c_AVP_Code_PCC_3GPP_CoA_IP_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_CoA_IP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Trunk_Group_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Trunk_Group_Id };
const AVP_Code c_AVP_Code_PCC_3GPP_Default_QoS_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Default_QoS_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_AN_GW_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_AN_GW_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Start_Of_Charging := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Start_Of_Charging };
+const AVP_Code c_AVP_Code_DCA_3GPP_Participants_Involved := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Participants_Involved };
const AVP_Code c_AVP_Code_PCC_3GPP_NBIFOM_Support := {
vendor_id_3GPP := avp_code_PCC_3GPP_NBIFOM_Support };
const AVP_Code c_AVP_Code_PCC_3GPP_Redirect_Support := {
@@ -8324,64 +13160,100 @@ const AVP_Code c_AVP_Code_BASE_NONE_Vendor_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Vendor_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_PDN_Connection_Continuity := {
vendor_id_3GPP := avp_code_AAA_3GPP_PDN_Connection_Continuity };
+const AVP_Code c_AVP_Code_DCA_3GPP_Tariff_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Tariff_Information };
const AVP_Code c_AVP_Code_CxDx_3GPP_Wildcarded_Public_Identity := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Wildcarded_Public_Identity };
-const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Session_Time := {
- vendor_id_NONE := avp_code_DNAS_NONE_Acct_Session_Time };
+const AVP_Code c_AVP_Code_MIPv4_NONE_Acct_Session_Time := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_Acct_Session_Time };
const AVP_Code c_AVP_Code_AAA_3GPP_DSA_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_DSA_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Event_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Event_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Data };
const AVP_Code c_AVP_Code_AAA_3GPP_LCS_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_LCS_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Requestor_Id_String := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Requestor_Id_String };
const AVP_Code c_AVP_Code_AAA_3GPP_PDN_GW_Allocation_Type := {
vendor_id_3GPP := avp_code_AAA_3GPP_PDN_GW_Allocation_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Additional_Type_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Additional_Type_Information };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_SGSN_MCC_MNC := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_SGSN_MCC_MNC };
+const AVP_Code c_AVP_Code_AAA_3GPP_HESSID := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_HESSID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Content_Class := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Content_Class };
const AVP_Code c_AVP_Code_BASE_NONE_Event_Timestamp := {
vendor_id_NONE := avp_code_BASE_NONE_Event_Timestamp };
+const AVP_Code c_AVP_Code_DCA_3GPP_TAD_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_TAD_Identifier };
const AVP_Code c_AVP_Code_DCC_NONE_Final_Unit_Action := {
vendor_id_NONE := avp_code_DCC_NONE_Final_Unit_Action };
+const AVP_Code c_AVP_Code_AAA_3GPP_IMEI_Check_In_VPLMN_Result := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_IMEI_Check_In_VPLMN_Result };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Generic_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Generic_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Variable_Part_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Variable_Part_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Direct_Discovery_Model := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Direct_Discovery_Model };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Max_Requested_BW_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Max_Requested_BW_UL };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Device_Trigger_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Device_Trigger_Indicator };
const AVP_Code c_AVP_Code_S6_3GPP_User_Identifier := {
vendor_id_3GPP := avp_code_S6_3GPP_User_Identifier };
-const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IPv6_Pool := {
- vendor_id_NONE := avp_code_DNAS_NONE_Framed_IPv6_Pool };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Base_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Base_Name };
+const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IPv6_Pool := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Framed_IPv6_Pool };
const AVP_Code c_AVP_Code_AAA_3GPP_Restoration_Priority := {
vendor_id_3GPP := avp_code_AAA_3GPP_Restoration_Priority };
-const AVP_Code c_AVP_Code_DCC_NONE_Rating_Group := {
- vendor_id_NONE := avp_code_DCC_NONE_Rating_Group };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MN_HA_SPI := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MN_HA_SPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_ISUP_Cause_Diagnostics := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ISUP_Cause_Diagnostics };
const AVP_Code c_AVP_Code_S6_3GPP_Association_Type := {
vendor_id_3GPP := avp_code_S6_3GPP_Association_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Definition := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Definition };
+const AVP_Code c_AVP_Code_DCC_NONE_Rating_Group := {
+ vendor_id_NONE := avp_code_DCC_NONE_Rating_Group };
+const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MN_HA_SPI := {
+ vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MN_HA_SPI };
const AVP_Code c_AVP_Code_RX_3GPP_Min_Requested_Bandwidth_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Min_Requested_Bandwidth_UL };
-const AVP_Code c_AVP_Code_AAA_3GPP_Report_Amount := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Report_Amount };
+const AVP_Code c_AVP_Code_DCA_3GPP_Application_Specific_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Application_Specific_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_CoA_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_CoA_Information };
+const AVP_Code c_AVP_Code_AAA_3GPP_Report_Amount := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Report_Amount };
const AVP_Code c_AVP_Code_CxDx_3GPP_Secondary_Charging_Collection_Function_Name := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Secondary_Charging_Collection_Function_Name };
const AVP_Code c_AVP_Code_DCC_NONE_User_Equipment_Info := {
vendor_id_NONE := avp_code_DCC_NONE_User_Equipment_Info };
const AVP_Code c_AVP_Code_AAA_3GPP_A_MSISDN := {
vendor_id_3GPP := avp_code_AAA_3GPP_A_MSISDN };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Mobile_Node_Address := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Mobile_Node_Address };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Mobile_Node_Address := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Mobile_Node_Address };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Report := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Rule_Report };
const AVP_Code c_AVP_Code_AAA_3GPP_Number_Of_Requested_Vectors := {
vendor_id_3GPP := avp_code_AAA_3GPP_Number_Of_Requested_Vectors };
const AVP_Code c_AVP_Code_AAA_3GPP_AIR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_AIR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Protocol_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Protocol_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Low_Priority_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Low_Priority_Indicator };
const AVP_Code c_AVP_Code_AAA_3GPP_Geographical_Information := {
vendor_id_3GPP := avp_code_AAA_3GPP_Geographical_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Participant_Action_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Participant_Action_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Node_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Node_Id };
const AVP_Code c_AVP_Code_CxDx_3GPP_Loose_Route_Indication := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Loose_Route_Indication };
const AVP_Code c_AVP_Code_DCC_NONE_Service_Parameter_Type := {
@@ -8390,56 +13262,100 @@ const AVP_Code c_AVP_Code_AAA_3GPP_MME_User_State := {
vendor_id_3GPP := avp_code_AAA_3GPP_MME_User_State };
const AVP_Code c_AVP_Code_AAA_3GPP_Access_Restriction_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_Access_Restriction_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Service_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Service_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_UNI_PDU_CP_Only_Flag := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_UNI_PDU_CP_Only_Flag };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Filter_Rule := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Filter_Rule };
const AVP_Code c_AVP_Code_BASE_NONE_Failed_AVP := {
vendor_id_NONE := avp_code_BASE_NONE_Failed_AVP };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_RAT_Type := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_RAT_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_SS_Status := {
vendor_id_3GPP := avp_code_AAA_3GPP_SS_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_Neighbour_Node_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Neighbour_Node_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Location_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Location_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Quota_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Quota_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Priority := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Priority };
const AVP_Code c_AVP_Code_S6_3GPP_NIDD_Authorization_Update := {
vendor_id_3GPP := avp_code_S6_3GPP_NIDD_Authorization_Update };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Specific_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Specific_Data };
const AVP_Code c_AVP_Code_DCC_NONE_Subscription_Id_Type := {
vendor_id_NONE := avp_code_DCC_NONE_Subscription_Id_Type };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_FA_to_HA_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_FA_to_HA_MSA };
+const AVP_Code c_AVP_Code_AAA_3GPP_Connectivity_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Connectivity_Flags };
const AVP_Code c_AVP_Code_PCC_3GPP_Packet_Filter_Operation := {
vendor_id_3GPP := avp_code_PCC_3GPP_Packet_Filter_Operation };
+const AVP_Code c_AVP_Code_DCA_3GPP_VCS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_VCS_Information };
const AVP_Code c_AVP_Code_S6_3GPP_SCEF_Reference_ID_for_Deletion := {
vendor_id_3GPP := avp_code_S6_3GPP_SCEF_Reference_ID_for_Deletion };
+const AVP_Code c_AVP_Code_DCA_3GPP_Content_Disposition := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Content_Disposition };
const AVP_Code c_AVP_Code_RX_3GPP_SIP_Forking_Indication := {
vendor_id_3GPP := avp_code_RX_3GPP_SIP_Forking_Indication };
const AVP_Code c_AVP_Code_DNAS_NONE_User_Password := {
vendor_id_NONE := avp_code_DNAS_NONE_User_Password };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Group_IP_Multicast_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Group_IP_Multicast_Address };
const AVP_Code c_AVP_Code_S6_3GPP_IMEI_Change := {
vendor_id_3GPP := avp_code_S6_3GPP_IMEI_Change };
const AVP_Code c_AVP_Code_PCC_3GPP_IP_CAN_Type := {
vendor_id_3GPP := avp_code_PCC_3GPP_IP_CAN_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Media_Component := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Media_Component };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Min_Desired_BW_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Min_Desired_BW_UL };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Direct_Communication_Reception_Data_Container };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Authorization := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Authorization };
const AVP_Code c_AVP_Code_PCC_3GPP_Revalidation_Time := {
vendor_id_3GPP := avp_code_PCC_3GPP_Revalidation_Time };
const AVP_Code c_AVP_Code_AAA_3GPP_Logging_Interval := {
vendor_id_3GPP := avp_code_AAA_3GPP_Logging_Interval };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Presence_Reporting_Area_Status := {
vendor_id_3GPP := avp_code_PCC_3GPP_Presence_Reporting_Area_Status };
-const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_offloadability := {
- vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_offloadability };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Filter := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Filter };
+const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_offloadability := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_offloadability };
+const AVP_Code c_AVP_Code_DCA_3GPP_Data_Coding_Scheme := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Data_Coding_Scheme };
const AVP_Code c_AVP_Code_PCC_3GPP_Metering_Method := {
vendor_id_3GPP := avp_code_PCC_3GPP_Metering_Method };
const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Tunnel_Connection := {
vendor_id_NONE := avp_code_DNAS_NONE_Acct_Tunnel_Connection };
const AVP_Code c_AVP_Code_AAA_3GPP_Non_IP_Data_Delivery_Mechanism := {
vendor_id_3GPP := avp_code_AAA_3GPP_Non_IP_Data_Delivery_Mechanism };
+const AVP_Code c_AVP_Code_DCA_3GPP_Initial_IMS_Charging_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Initial_IMS_Charging_Identifier };
const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Filter_Rule := {
vendor_id_NONE := avp_code_DNAS_NONE_NAS_Filter_Rule };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Feature_Vector := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Feature_Vector };
const AVP_Code c_AVP_Code_BASE_NONE_Session_Server_Failover := {
vendor_id_NONE := avp_code_BASE_NONE_Session_Server_Failover };
+const AVP_Code c_AVP_Code_DCA_3GPP_Accumulated_Cost := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Accumulated_Cost };
const AVP_Code c_AVP_Code_CxDx_3GPP_Integrity_Key := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Integrity_Key };
const AVP_Code c_AVP_Code_AAA_3GPP_E_UTRAN_Vector := {
vendor_id_3GPP := avp_code_AAA_3GPP_E_UTRAN_Vector };
+const AVP_Code c_AVP_Code_DCA_3GPP_SMSC_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SMSC_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_PDP_Address_Prefix_Length := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PDP_Address_Prefix_Length };
const AVP_Code c_AVP_Code_BASE_NONE_Experimental_Result := {
vendor_id_NONE := avp_code_BASE_NONE_Experimental_Result };
const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Link_Count := {
@@ -8448,102 +13364,160 @@ const AVP_Code c_AVP_Code_DCC_NONE_Unit_Value := {
vendor_id_NONE := avp_code_DCC_NONE_Unit_Value };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Event_List := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Event_List };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Client_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Client_Id };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_PDP_Type := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_PDP_Type };
const AVP_Code c_AVP_Code_DNAS_NONE_Reply_Message := {
vendor_id_NONE := avp_code_DNAS_NONE_Reply_Message };
const AVP_Code c_AVP_Code_DNAS_NONE_Connect_Info := {
vendor_id_NONE := avp_code_DNAS_NONE_Connect_Info };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Replay_Mode := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Replay_Mode };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Replay_Mode := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Replay_Mode };
const AVP_Code c_AVP_Code_BASE_NONE_Proxy_Host := {
vendor_id_NONE := avp_code_BASE_NONE_Proxy_Host };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_Of_Talk_Bursts := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_Of_Talk_Bursts };
+const AVP_Code c_AVP_Code_AAA_3GPP_Short_Network_Name := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Short_Network_Name };
+const AVP_Code c_AVP_Code_DCA_3GPP_Message_Size := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Message_Size };
+const AVP_Code c_AVP_Code_DCA_3GPP_Additional_Exception_Reports := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Additional_Exception_Reports };
+const AVP_Code c_AVP_Code_DCA_3GPP_Access_Transfer_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Access_Transfer_Information };
const AVP_Code c_AVP_Code_S6_3GPP_Communication_Pattern_Set := {
vendor_id_3GPP := avp_code_S6_3GPP_Communication_Pattern_Set };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAG_UP_Address := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAG_UP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_MMBox_Storage_Requested := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MMBox_Storage_Requested };
const AVP_Code c_AVP_Code_RX_3GPP_Flow_Status := {
vendor_id_3GPP := avp_code_RX_3GPP_Flow_Status };
const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Challenge := {
vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Challenge };
+const AVP_Code c_AVP_Code_DCA_3GPP_PC3_Control_Protocol_Cause := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PC3_Control_Protocol_Cause };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Unit_Type := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Unit_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Calling_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Calling_Party_Address };
const AVP_Code c_AVP_Code_RX_3GPP_MCPTT_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_MCPTT_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Group_Monitoring_Event_Report := {
vendor_id_3GPP := avp_code_S6_3GPP_Group_Monitoring_Event_Report };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Upgrade := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Upgrade };
-const AVP_Code c_AVP_Code_DNAS_NONE_Service_Type := {
- vendor_id_NONE := avp_code_DNAS_NONE_Service_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_PS_Append_Free_Format_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PS_Append_Free_Format_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_AN_GW_Status := {
vendor_id_3GPP := avp_code_PCC_3GPP_AN_GW_Status };
-const AVP_Code c_AVP_Code_AAA_3GPP_Measurement_Period_UMTS := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Measurement_Period_UMTS };
+const AVP_Code c_AVP_Code_DNAS_NONE_Service_Type := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Service_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Monitoring_Key := {
vendor_id_3GPP := avp_code_PCC_3GPP_Monitoring_Key };
+const AVP_Code c_AVP_Code_AAA_3GPP_Measurement_Period_UMTS := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Measurement_Period_UMTS };
+const AVP_Code c_AVP_Code_DCA_3GPP_Media_Initiator_Flag := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Media_Initiator_Flag };
+const AVP_Code c_AVP_Code_DCA_3GPP_ISUP_Location_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ISUP_Location_Number };
const AVP_Code c_AVP_Code_PCC_3GPP_3GPP_PS_Data_Off_Status := {
vendor_id_3GPP := avp_code_PCC_3GPP_3GPP_PS_Data_Off_Status };
-const AVP_Code c_AVP_Code_AAA_3GPP_Reset_ID := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Reset_ID };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Install := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Rule_Install };
+const AVP_Code c_AVP_Code_AAA_3GPP_Reset_ID := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Reset_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Data_Container := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Data_Container };
const AVP_Code c_AVP_Code_CxDx_3GPP_Server_Assignment_Type := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Server_Assignment_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_PUR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_PUR_Flags };
-const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Routing := {
- vendor_id_NONE := avp_code_DNAS_NONE_Framed_Routing };
const AVP_Code c_AVP_Code_PCC_3GPP_IP_CAN_Session_Charging_Scope := {
vendor_id_3GPP := avp_code_PCC_3GPP_IP_CAN_Session_Charging_Scope };
+const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Routing := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Framed_Routing };
const AVP_Code c_AVP_Code_AAA_3GPP_IMEI := {
vendor_id_3GPP := avp_code_AAA_3GPP_IMEI };
const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Ident := {
vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Ident };
+const AVP_Code c_AVP_Code_DCA_3GPP_Interface_Text := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Interface_Text };
const AVP_Code c_AVP_Code_AAA_3GPP_Kc := {
vendor_id_3GPP := avp_code_AAA_3GPP_Kc };
+const AVP_Code c_AVP_Code_DCA_3GPP_Current_Tariff := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Current_Tariff };
const AVP_Code c_AVP_Code_AAA_3GPP_SGSN_Number := {
vendor_id_3GPP := avp_code_AAA_3GPP_SGSN_Number };
const AVP_Code c_AVP_Code_AAA_3GPP_HPLMN_ODB := {
vendor_id_3GPP := avp_code_AAA_3GPP_HPLMN_ODB };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Quota_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Quota_Type };
+const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Info := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Domain_Name := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Domain_Name };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Charging_Characteristics := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Charging_Characteristics };
const AVP_Code c_AVP_Code_AAA_3GPP_PDP_Context := {
vendor_id_3GPP := avp_code_AAA_3GPP_PDP_Context };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Money := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Money };
+const AVP_Code c_AVP_Code_AAA_3GPP_DER_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_DER_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Data_Coding_Scheme := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Data_Coding_Scheme };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_GGSN_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_GGSN_Address };
const AVP_Code c_AVP_Code_BASE_NONE_Proxy_Info := {
vendor_id_NONE := avp_code_BASE_NONE_Proxy_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Related_IMS_Charging_Identifier_Node := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Related_IMS_Charging_Identifier_Node };
const AVP_Code c_AVP_Code_S6_3GPP_Node_Type := {
vendor_id_3GPP := avp_code_S6_3GPP_Node_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Talk_Burst_Volume := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Talk_Burst_Volume };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Id };
const AVP_Code c_AVP_Code_RX_3GPP_Priority_Sharing_Indicator := {
vendor_id_3GPP := avp_code_RX_3GPP_Priority_Sharing_Indicator };
const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Type := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Name };
+const AVP_Code c_AVP_Code_DCA_3GPP_Trigger_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Trigger_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Instance_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Instance_Id };
const AVP_Code c_AVP_Code_S6_3GPP_Scheduled_Communication_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Scheduled_Communication_Time };
const AVP_Code c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Max_Requested_Bandwidth_DL };
+const AVP_Code c_AVP_Code_DCA_3GPP_Role_Of_ProSe_Function := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Role_Of_ProSe_Function };
const AVP_Code c_AVP_Code_S6_3GPP_Maximum_Latency := {
vendor_id_3GPP := avp_code_S6_3GPP_Maximum_Latency };
const AVP_Code c_AVP_Code_PCC_3GPP_PCC_Rule_Status := {
vendor_id_3GPP := avp_code_PCC_3GPP_PCC_Rule_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_SIP_Response_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SIP_Response_Timestamp };
const AVP_Code c_AVP_Code_PCC_3GPP_Extended_GBR_DL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Extended_GBR_DL };
const AVP_Code c_AVP_Code_AAA_3GPP_MBSFN_Area := {
vendor_id_3GPP := avp_code_AAA_3GPP_MBSFN_Area };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_UE_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_UE_ID };
const AVP_Code c_AVP_Code_CxDx_3GPP_Server_Name := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Server_Name };
-const AVP_Code c_AVP_Code_DCC_NONE_Check_Balance_Result := {
- vendor_id_NONE := avp_code_DCC_NONE_Check_Balance_Result };
const AVP_Code c_AVP_Code_S6_3GPP_APN_Validity_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_APN_Validity_Time };
-const AVP_Code c_AVP_Code_AAA_3GPP_Job_Type := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Job_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Allocation_Retention_Priority := {
vendor_id_3GPP := avp_code_PCC_3GPP_Allocation_Retention_Priority };
+const AVP_Code c_AVP_Code_DCC_NONE_Check_Balance_Result := {
+ vendor_id_NONE := avp_code_DCC_NONE_Check_Balance_Result };
+const AVP_Code c_AVP_Code_AAA_3GPP_Job_Type := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Job_Type };
const AVP_Code c_AVP_Code_BASE_NONE_Destination_Host := {
vendor_id_NONE := avp_code_BASE_NONE_Destination_Host };
const AVP_Code c_AVP_Code_AAA_3GPP_Positioning_Method := {
@@ -8552,76 +13526,116 @@ const AVP_Code c_AVP_Code_CxDx_3GPP_LIA_Flags := {
vendor_id_3GPP := avp_code_CxDx_3GPP_LIA_Flags };
const AVP_Code c_AVP_Code_AAA_3GPP_DL_Buffering_Suggested_Packet_Count := {
vendor_id_3GPP := avp_code_AAA_3GPP_DL_Buffering_Suggested_Packet_Count };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Service_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Service_Type };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_IP_Host := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_IP_Host };
-const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Security := {
- vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Security };
const AVP_Code c_AVP_Code_AAA_3GPP_IDA_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_IDA_Flags };
+const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Security := {
+ vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Security };
const AVP_Code c_AVP_Code_DNAS_NONE_Origin_AAA_Protocol := {
vendor_id_NONE := avp_code_DNAS_NONE_Origin_AAA_Protocol };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Last_Usage := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Last_Usage };
const AVP_Code c_AVP_Code_CxDx_3GPP_Charging_Information := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Charging_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_ULA_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_ULA_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originator_Interface := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originator_Interface };
const AVP_Code c_AVP_Code_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported := {
vendor_id_3GPP := avp_code_AAA_3GPP_IMS_Voice_Over_PS_Sessions_Supported };
const AVP_Code c_AVP_Code_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature := {
vendor_id_3GPP := avp_code_AAA_3GPP_Roaming_Restricted_Due_To_Unsupported_Feature };
-const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Assignment_Id := {
- vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Assignment_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_File_Repair_Supported := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_File_Repair_Supported };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IPX_Network := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_IPX_Network };
+const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Assignment_Id := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Assignment_Id };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Service_Specific_Units := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Service_Specific_Units };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Answer_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Answer_Timestamp };
+const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_Identifier := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Type_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Type_Number };
+const AVP_Code c_AVP_Code_DCA_3GPP_NIDD_Submission := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_NIDD_Submission };
const AVP_Code c_AVP_Code_S6_3GPP_T4_Parameters := {
vendor_id_3GPP := avp_code_S6_3GPP_T4_Parameters };
const AVP_Code c_AVP_Code_RX_3GPP_Access_Network_Charging_Identifier_Value := {
vendor_id_3GPP := avp_code_RX_3GPP_Access_Network_Charging_Identifier_Value };
+const AVP_Code c_AVP_Code_DCA_3GPP_Announcing_UE_HPLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Announcing_UE_HPLMN_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_AESE_Error_Report := {
vendor_id_3GPP := avp_code_S6_3GPP_AESE_Error_Report };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_FA_to_HA_SPI := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_FA_to_HA_SPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_Event_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Event_Type };
const AVP_Code c_AVP_Code_RX_3GPP_Sharing_Key_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Sharing_Key_DL };
const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Remove := {
vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Remove };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Direct_Communication_Transmission_Data_Container };
const AVP_Code c_AVP_Code_S6_3GPP_Restricted_PLMN_List := {
vendor_id_3GPP := avp_code_S6_3GPP_Restricted_PLMN_List };
-const AVP_Code c_AVP_Code_AAA_3GPP_Age_Of_Location_Information := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Age_Of_Location_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Access_Network_Charging_Identifier_Gx := {
vendor_id_3GPP := avp_code_PCC_3GPP_Access_Network_Charging_Identifier_Gx };
+const AVP_Code c_AVP_Code_AAA_3GPP_Age_Of_Location_Information := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Age_Of_Location_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Group_Name := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Group_Name };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Max_Requested_BW_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Max_Requested_BW_DL };
const AVP_Code c_AVP_Code_PCC_3GPP_Flow_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Flow_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_PS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PS_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_MTC_IWF_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MTC_IWF_Address };
+const AVP_Code c_AVP_Code_PCC_3GPP_Execution_Time := {
+ vendor_id_3GPP := avp_code_PCC_3GPP_Execution_Time };
const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Identifier := {
vendor_id_NONE := avp_code_DNAS_NONE_NAS_Identifier };
const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Server_Auth_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Server_Auth_Id };
-const AVP_Code c_AVP_Code_PCC_3GPP_Execution_Time := {
- vendor_id_3GPP := avp_code_PCC_3GPP_Execution_Time };
const AVP_Code c_AVP_Code_CxDx_3GPP_Contact := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Contact };
+const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Correlation_Indicator := {
+ vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Correlation_Indicator };
const AVP_Code c_AVP_Code_DCC_NONE_Credit_Control := {
vendor_id_NONE := avp_code_DCC_NONE_Credit_Control };
const AVP_Code c_AVP_Code_BASE_NONE_Accounting_Record_Number := {
vendor_id_NONE := avp_code_BASE_NONE_Accounting_Record_Number };
const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_Event_1I := {
vendor_id_3GPP := avp_code_AAA_3GPP_Event_Threshold_Event_1I };
-const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Correlation_Indicator := {
- vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Correlation_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_SIP_Request_Timestamp_Fraction := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SIP_Request_Timestamp_Fraction };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Mode := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Mode };
const AVP_Code c_AVP_Code_CxDx_3GPP_User_Data := {
vendor_id_3GPP := avp_code_CxDx_3GPP_User_Data };
const AVP_Code c_AVP_Code_AAA_3GPP_Report_Interval := {
vendor_id_3GPP := avp_code_AAA_3GPP_Report_Interval };
const AVP_Code c_AVP_Code_PCC_3GPP_RAN_NAS_Release_Cause := {
vendor_id_3GPP := avp_code_PCC_3GPP_RAN_NAS_Release_Cause };
+const AVP_Code c_AVP_Code_DCA_3GPP_Dynamic_Address_Flag_Extension := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Dynamic_Address_Flag_Extension };
const AVP_Code c_AVP_Code_AAA_3GPP_Client_Identity := {
vendor_id_3GPP := avp_code_AAA_3GPP_Client_Identity };
const AVP_Code c_AVP_Code_BASE_NONE_Redirect_Host_Usage := {
vendor_id_NONE := avp_code_BASE_NONE_Redirect_Host_Usage };
+const AVP_Code c_AVP_Code_DCA_3GPP_CSG_Access_Mode := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CSG_Access_Mode };
const AVP_Code c_AVP_Code_AAA_3GPP_Equipment_Status := {
vendor_id_3GPP := avp_code_AAA_3GPP_Equipment_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_Supplementary_Service := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Supplementary_Service };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Packet_Filter := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Packet_Filter };
const AVP_Code c_AVP_Code_DCC_NONE_Redirect_Server_Address := {
@@ -8630,104 +13644,164 @@ const AVP_Code c_AVP_Code_MIPv6_NONE_MIP6_Auth_Mode := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP6_Auth_Mode };
const AVP_Code c_AVP_Code_AAA_3GPP_EPS_Location_Information := {
vendor_id_3GPP := avp_code_AAA_3GPP_EPS_Location_Information };
-const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Tunnel_Packets_Lost := {
- vendor_id_NONE := avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost };
+const AVP_Code c_AVP_Code_DCA_3GPP_Access_Network_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Access_Network_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Called_Identity := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Called_Identity };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_Default_APN_Context_Id := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_Default_APN_Context_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_SGSN_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SGSN_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_SGi_PtP_Tunnelling_Method := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SGi_PtP_Tunnelling_Method };
const AVP_Code c_AVP_Code_BASE_NONE_Session_Timeout := {
vendor_id_NONE := avp_code_BASE_NONE_Session_Timeout };
+const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Tunnel_Packets_Lost := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Acct_Tunnel_Packets_Lost };
+const AVP_Code c_AVP_Code_DCA_3GPP_NNI_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_NNI_Type };
const AVP_Code c_AVP_Code_RX_3GPP_Service_Info_Status := {
vendor_id_3GPP := avp_code_RX_3GPP_Service_Info_Status };
const AVP_Code c_AVP_Code_S6_3GPP_CIR_Flags := {
vendor_id_3GPP := avp_code_S6_3GPP_CIR_Flags };
const AVP_Code c_AVP_Code_PCC_3GPP_Precedence := {
vendor_id_3GPP := avp_code_PCC_3GPP_Precedence };
+const AVP_Code c_AVP_Code_DCA_3GPP_User_Participating_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_User_Participating_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_GGSN_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_GGSN_Address };
const AVP_Code c_AVP_Code_RX_3GPP_Sponsoring_Action := {
vendor_id_3GPP := avp_code_RX_3GPP_Sponsoring_Action };
+const AVP_Code c_AVP_Code_DCA_3GPP_Radio_Resources_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Radio_Resources_Indicator };
const AVP_Code c_AVP_Code_S6_3GPP_Granted_Validity_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Granted_Validity_Time };
const AVP_Code c_AVP_Code_PCC_3GPP_Priority_Level := {
vendor_id_3GPP := avp_code_PCC_3GPP_Priority_Level };
+const AVP_Code c_AVP_Code_DCA_3GPP_Node_Functionality := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Node_Functionality };
const AVP_Code c_AVP_Code_RX_3GPP_Flow_Description := {
vendor_id_3GPP := avp_code_RX_3GPP_Flow_Description };
-const AVP_Code c_AVP_Code_AAA_3GPP_Daylight_Saving_Time := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Daylight_Saving_Time };
const AVP_Code c_AVP_Code_PCC_3GPP_Packet_Filter_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Packet_Filter_Information };
+const AVP_Code c_AVP_Code_AAA_3GPP_Daylight_Saving_Time := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Daylight_Saving_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Address_Domain := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Address_Domain };
const AVP_Code c_AVP_Code_S6_3GPP_SCEF_ID := {
vendor_id_3GPP := avp_code_S6_3GPP_SCEF_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Content_Length := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Content_Length };
const AVP_Code c_AVP_Code_PCC_3GPP_Removal_Of_Access := {
vendor_id_3GPP := avp_code_PCC_3GPP_Removal_Of_Access };
-const AVP_Code c_AVP_Code_AAA_3GPP_Preferred_Data_Mode := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Preferred_Data_Mode };
const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Report := {
vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Report };
-const AVP_Code c_AVP_Code_AAA_3GPP_UE_SRVCC_Capability := {
- vendor_id_3GPP := avp_code_AAA_3GPP_UE_SRVCC_Capability };
+const AVP_Code c_AVP_Code_AAA_3GPP_Preferred_Data_Mode := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Preferred_Data_Mode };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Functionality := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Functionality };
+const AVP_Code c_AVP_Code_DCA_3GPP_Low_Balance_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Low_Balance_Indication };
const AVP_Code c_AVP_Code_PCC_3GPP_Guaranteed_Bitrate_UL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Guaranteed_Bitrate_UL };
-const AVP_Code c_AVP_Code_DNAS_NONE_NAS_IPv6_Address := {
- vendor_id_NONE := avp_code_DNAS_NONE_NAS_IPv6_Address };
+const AVP_Code c_AVP_Code_AAA_3GPP_UE_SRVCC_Capability := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_UE_SRVCC_Capability };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_LAT_Group := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_LAT_Group };
+const AVP_Code c_AVP_Code_DNAS_NONE_NAS_IPv6_Address := {
+ vendor_id_NONE := avp_code_DNAS_NONE_NAS_IPv6_Address };
const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MAC_Mobility_Data := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MAC_Mobility_Data };
-const AVP_Code c_AVP_Code_DNAS_NONE_Accounting_Output_Octets := {
- vendor_id_NONE := avp_code_DNAS_NONE_Accounting_Output_Octets };
+const AVP_Code c_AVP_Code_MIPv4_NONE_Accounting_Output_Octets := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_Accounting_Output_Octets };
const AVP_Code c_AVP_Code_CxDx_3GPP_To_SIP_Header := {
vendor_id_3GPP := avp_code_CxDx_3GPP_To_SIP_Header };
const AVP_Code c_AVP_Code_AAA_3GPP_Coupled_Node_Diameter_ID := {
vendor_id_3GPP := avp_code_AAA_3GPP_Coupled_Node_Diameter_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Real_Time_Tariff_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Real_Time_Tariff_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_STN_SR := {
vendor_id_3GPP := avp_code_AAA_3GPP_STN_SR };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Type };
const AVP_Code c_AVP_Code_BASE_NONE_Supported_Vendor_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Supported_Vendor_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_ServiceTypeIdentity := {
vendor_id_3GPP := avp_code_AAA_3GPP_ServiceTypeIdentity };
+const AVP_Code c_AVP_Code_DCA_3GPP_Requested_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Requested_Party_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Announcement_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Announcement_Information };
const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Authentic := {
vendor_id_NONE := avp_code_DNAS_NONE_Acct_Authentic };
const AVP_Code c_AVP_Code_DCC_NONE_Service_Identifier := {
vendor_id_NONE := avp_code_DCC_NONE_Service_Identifier };
const AVP_Code c_AVP_Code_AAA_3GPP_AUTN := {
vendor_id_3GPP := avp_code_AAA_3GPP_AUTN };
+const AVP_Code c_AVP_Code_AAA_3GPP_Non_3GPP_User_Data := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Non_3GPP_User_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_Delivery_Report_Requested := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Delivery_Report_Requested };
const AVP_Code c_AVP_Code_GI_3GPP_TWAN_Identifier := {
vendor_id_3GPP := avp_code_GI_3GPP_TWAN_Identifier };
+const AVP_Code c_AVP_Code_AAA_3GPP_Origination_Time_Stamp := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Origination_Time_Stamp };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_APN := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_APN };
+const AVP_Code c_AVP_Code_DCA_3GPP_Envelope_End_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Envelope_End_Time };
const AVP_Code c_AVP_Code_RX_3GPP_Sponsored_Connectivity_Data := {
vendor_id_3GPP := avp_code_RX_3GPP_Sponsored_Connectivity_Data };
const AVP_Code c_AVP_Code_BASE_NONE_Auth_Request_Type := {
vendor_id_NONE := avp_code_BASE_NONE_Auth_Request_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Application_Server_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Application_Server_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originator_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originator_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Network_Call_Reference_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Network_Call_Reference_Number };
const AVP_Code c_AVP_Code_S6_3GPP_AESE_Communication_Pattern := {
vendor_id_3GPP := avp_code_S6_3GPP_AESE_Communication_Pattern };
const AVP_Code c_AVP_Code_PCC_3GPP_NBIFOM_Mode := {
vendor_id_3GPP := avp_code_PCC_3GPP_NBIFOM_Mode };
-const AVP_Code c_AVP_Code_DCC_NONE_Validity_Time := {
- vendor_id_NONE := avp_code_DCC_NONE_Validity_Time };
const AVP_Code c_AVP_Code_PCC_3GPP_Redirect_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Redirect_Information };
+const AVP_Code c_AVP_Code_DCC_NONE_Validity_Time := {
+ vendor_id_NONE := avp_code_DCC_NONE_Validity_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_UE_VPLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_UE_VPLMN_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Event_Handling := {
vendor_id_3GPP := avp_code_S6_3GPP_Event_Handling };
-const AVP_Code c_AVP_Code_AAA_3GPP_Tracking_Area_Identity := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Tracking_Area_Identity };
const AVP_Code c_AVP_Code_PCC_3GPP_ToS_Traffic_Class := {
vendor_id_3GPP := avp_code_PCC_3GPP_ToS_Traffic_Class };
+const AVP_Code c_AVP_Code_AAA_3GPP_Tracking_Area_Identity := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Tracking_Area_Identity };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_HA_to_FA_SPI := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_HA_to_FA_SPI };
const AVP_Code c_AVP_Code_RX_3GPP_Min_Desired_Bandwidth_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Min_Desired_Bandwidth_UL };
const AVP_Code c_AVP_Code_AAA_3GPP_UVR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_UVR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_PS_Free_Format_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PS_Free_Format_Data };
const AVP_Code c_AVP_Code_CxDx_3GPP_Originating_Request := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Originating_Request };
-const AVP_Code c_AVP_Code_AAA_3GPP_Subscription_Data_Flags := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Subscription_Data_Flags };
const AVP_Code c_AVP_Code_PCC_3GPP_PDN_Connection_ID := {
vendor_id_3GPP := avp_code_PCC_3GPP_PDN_Connection_ID };
+const AVP_Code c_AVP_Code_AAA_3GPP_Subscription_Data_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Subscription_Data_Flags };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IPv6_Route := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_IPv6_Route };
-const AVP_Code c_AVP_Code_AAA_3GPP_DSR_Flags := {
- vendor_id_3GPP := avp_code_AAA_3GPP_DSR_Flags };
const AVP_Code c_AVP_Code_PCC_3GPP_PRA_Remove := {
vendor_id_3GPP := avp_code_PCC_3GPP_PRA_Remove };
+const AVP_Code c_AVP_Code_AAA_3GPP_DSR_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_DSR_Flags };
const AVP_Code c_AVP_Code_DCC_NONE_Granted_Service_Unit := {
vendor_id_NONE := avp_code_DCC_NONE_Granted_Service_Unit };
const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Timestamp := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Timestamp };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_Portability_Routing_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_Portability_Routing_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer := {
vendor_id_3GPP := avp_code_AAA_3GPP_Subscribed_Periodic_RAU_TAU_Timer };
const AVP_Code c_AVP_Code_AAA_3GPP_Specific_APN_Info := {
@@ -8738,38 +13812,64 @@ const AVP_Code c_AVP_Code_CxDx_3GPP_Restoration_Info := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Restoration_Info };
const AVP_Code c_AVP_Code_BASE_NONE_Product_Name := {
vendor_id_NONE := avp_code_BASE_NONE_Product_Name };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_HA_to_MN_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_HA_to_MN_MSA };
+const AVP_Code c_AVP_Code_DCA_3GPP_Account_Expiration := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Account_Expiration };
const AVP_Code c_AVP_Code_AAA_3GPP_CSG_Id := {
vendor_id_3GPP := avp_code_AAA_3GPP_CSG_Id };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IP_Netmask := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_IP_Netmask };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_IPv6_DNS_Servers := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_IPv6_DNS_Servers };
+const AVP_Code c_AVP_Code_AAA_3GPP_SSID := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SSID };
const AVP_Code c_AVP_Code_AAA_3GPP_Call_Barring_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Call_Barring_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_BSSID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_BSSID };
const AVP_Code c_AVP_Code_DCC_NONE_Service_Parameter_Info := {
vendor_id_NONE := avp_code_DCC_NONE_Service_Parameter_Info };
-const AVP_Code c_AVP_Code_BASE_NONE_Origin_State_Id := {
- vendor_id_NONE := avp_code_BASE_NONE_Origin_State_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Talk_Burst_Exchange := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Talk_Burst_Exchange };
+const AVP_Code c_AVP_Code_DCA_3GPP_Variable_Part_Order := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Variable_Part_Order };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Quota_Mechanism := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Quota_Mechanism };
+const AVP_Code c_AVP_Code_AAA_3GPP_ANID := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_ANID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_Event_Report_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_Event_Report_Number };
const AVP_Code c_AVP_Code_S6_3GPP_IP_SM_GW_Name := {
vendor_id_3GPP := avp_code_S6_3GPP_IP_SM_GW_Name };
+const AVP_Code c_AVP_Code_BASE_NONE_Origin_State_Id := {
+ vendor_id_NONE := avp_code_BASE_NONE_Origin_State_Id };
const AVP_Code c_AVP_Code_RX_3GPP_Media_Sub_Component := {
vendor_id_3GPP := avp_code_RX_3GPP_Media_Sub_Component };
+const AVP_Code c_AVP_Code_DCA_3GPP_CN_Operator_Selection_Entity := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CN_Operator_Selection_Entity };
const AVP_Code c_AVP_Code_S6_3GPP_Accuracy := {
vendor_id_3GPP := avp_code_S6_3GPP_Accuracy };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Remove := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Remove };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originating_IOI := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originating_IOI };
const AVP_Code c_AVP_Code_RX_3GPP_Min_Requested_Bandwidth_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Min_Requested_Bandwidth_DL };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Function_PLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Function_PLMN_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Service_Report := {
vendor_id_3GPP := avp_code_S6_3GPP_Service_Report };
const AVP_Code c_AVP_Code_PCC_3GPP_Tunnel_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Tunnel_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Bearer_Service := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Bearer_Service };
const AVP_Code c_AVP_Code_CxDx_3GPP_Primary_Charging_Collection_Function_Name := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Primary_Charging_Collection_Function_Name };
-const AVP_Code c_AVP_Code_AAA_3GPP_Time_Zone := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Time_Zone };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Definition := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Definition };
+const AVP_Code c_AVP_Code_AAA_3GPP_Time_Zone := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Time_Zone };
const AVP_Code c_AVP_Code_S6_3GPP_Periodic_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Periodic_Time };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Failure_Code := {
@@ -8778,10 +13878,16 @@ const AVP_Code c_AVP_Code_PCC_3GPP_TDF_Destination_Host := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_Destination_Host };
const AVP_Code c_AVP_Code_AAA_3GPP_Local_Group_Id := {
vendor_id_3GPP := avp_code_AAA_3GPP_Local_Group_Id };
-const AVP_Code c_AVP_Code_AAA_3GPP_Service_Area_Identity := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Service_Area_Identity };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Discharge_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Discharge_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Requestor_PLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Requestor_PLMN_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Application_Reference_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Application_Reference_Identifier };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Report := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Report };
+const AVP_Code c_AVP_Code_AAA_3GPP_Service_Area_Identity := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Service_Area_Identity };
const AVP_Code c_AVP_Code_BASE_NONE_User_Name := {
vendor_id_NONE := avp_code_BASE_NONE_User_Name };
const AVP_Code c_AVP_Code_AAA_3GPP_UE_PC5_AMBR := {
@@ -8792,54 +13898,90 @@ const AVP_Code c_AVP_Code_BASE_NONE_Accounting_Sub_Session_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Accounting_Sub_Session_Id };
const AVP_Code c_AVP_Code_DNAS_NONE_Acct_Delay_Time := {
vendor_id_NONE := avp_code_DNAS_NONE_Acct_Delay_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Local_Sequence_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Local_Sequence_Number };
const AVP_Code c_AVP_Code_CxDx_3GPP_UAR_Flags := {
vendor_id_3GPP := avp_code_CxDx_3GPP_UAR_Flags };
const AVP_Code c_AVP_Code_AAA_3GPP_Collection_Period_RRM_UMTS := {
vendor_id_3GPP := avp_code_AAA_3GPP_Collection_Period_RRM_UMTS };
const AVP_Code c_AVP_Code_AAA_3GPP_Operator_Determined_Barring := {
vendor_id_3GPP := avp_code_AAA_3GPP_Operator_Determined_Barring };
+const AVP_Code c_AVP_Code_DCA_3GPP_Recipient_Received_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Recipient_Received_Address };
const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Server_Endpoint := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Server_Endpoint };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Candidate_Home_Agent_Host := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Candidate_Home_Agent_Host };
const AVP_Code c_AVP_Code_BASE_NONE_Session_Binding := {
vendor_id_NONE := avp_code_BASE_NONE_Session_Binding };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_IMEISV := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_IMEISV };
const AVP_Code c_AVP_Code_AAA_3GPP_SS_Code := {
vendor_id_3GPP := avp_code_AAA_3GPP_SS_Code };
+const AVP_Code c_AVP_Code_DCA_3GPP_DCD_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_DCD_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Location_Estimate_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Location_Estimate_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Addressee_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Addressee_Type };
const AVP_Code c_AVP_Code_BASE_NONE_Acct_Multi_Session_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Acct_Multi_Session_Id };
const AVP_Code c_AVP_Code_DCC_NONE_Subscription_Id_Data := {
vendor_id_NONE := avp_code_DCC_NONE_Subscription_Id_Data };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_Connectivity_Parameters := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_Connectivity_Parameters };
+const AVP_Code c_AVP_Code_DCA_3GPP_Reply_Applic_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Reply_Applic_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Participant_Access_Priority := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Participant_Access_Priority };
const AVP_Code c_AVP_Code_RX_3GPP_RS_Bandwidth := {
vendor_id_3GPP := avp_code_RX_3GPP_RS_Bandwidth };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Algorithm_Type := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Algorithm_Type };
const AVP_Code c_AVP_Code_S6_3GPP_Reachability_Information := {
vendor_id_3GPP := avp_code_S6_3GPP_Reachability_Information };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Algorithm_Type := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Algorithm_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Session_Description := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Session_Description };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Min_Desired_BW_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Min_Desired_BW_DL };
-const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_RSRQ := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Event_Threshold_RSRQ };
+const AVP_Code c_AVP_Code_DCA_3GPP_Location_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Location_Info };
const AVP_Code c_AVP_Code_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL := {
vendor_id_3GPP := avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL };
+const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_RSRQ := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Event_Threshold_RSRQ };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Information };
const AVP_Code c_AVP_Code_S6_3GPP_Service_Parameters := {
vendor_id_3GPP := avp_code_S6_3GPP_Service_Parameters };
const AVP_Code c_AVP_Code_PCC_3GPP_Presence_Reporting_Area_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_Presence_Reporting_Area_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Rule_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_SMS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SMS_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_ePDG_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ePDG_Address };
const AVP_Code c_AVP_Code_PCC_3GPP_Event_Trigger := {
vendor_id_3GPP := avp_code_PCC_3GPP_Event_Trigger };
const AVP_Code c_AVP_Code_RX_3GPP_GCS_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_GCS_Identifier };
const AVP_Code c_AVP_Code_MIPv6_NONE_QoS_Capability := {
vendor_id_NONE := avp_code_MIPv6_NONE_QoS_Capability };
-const AVP_Code c_AVP_Code_DCC_NONE_G_S_U_Pool_Identifier := {
- vendor_id_NONE := avp_code_DCC_NONE_G_S_U_Pool_Identifier };
-const AVP_Code c_AVP_Code_AAA_3GPP_Non_IP_PDN_Type_Indicator := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator };
const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Install := {
vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Install };
+const AVP_Code c_AVP_Code_AAA_3GPP_Non_IP_PDN_Type_Indicator := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Non_IP_PDN_Type_Indicator };
+const AVP_Code c_AVP_Code_DCC_NONE_G_S_U_Pool_Identifier := {
+ vendor_id_NONE := avp_code_DCC_NONE_G_S_U_Pool_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Outgoing_Session_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Outgoing_Session_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Controlling_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Controlling_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Dynamic_Address_Flag := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Dynamic_Address_Flag };
const AVP_Code c_AVP_Code_CxDx_3GPP_Confidentiality_Key := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Confidentiality_Key };
const AVP_Code c_AVP_Code_PCC_3GPP_Flow_Label := {
@@ -8848,18 +13990,44 @@ const AVP_Code c_AVP_Code_DNAS_NONE_NAS_Port := {
vendor_id_NONE := avp_code_DNAS_NONE_NAS_Port };
const AVP_Code c_AVP_Code_AAA_3GPP_Authentication_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Authentication_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Transcoder_Inserted_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Transcoder_Inserted_Indication };
+const AVP_Code c_AVP_Code_DCA_3GPP_SMS_Node := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SMS_Node };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Interface_List := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Interface_List };
+const AVP_Code c_AVP_Code_DCA_3GPP_SGW_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SGW_Address };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Charging_Id := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Charging_Id };
const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Algorithm := {
vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Algorithm };
const AVP_Code c_AVP_Code_AAA_3GPP_APN_Configuration_Profile := {
vendor_id_3GPP := avp_code_AAA_3GPP_APN_Configuration_Profile };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_Of_Received_Talk_Bursts := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_Of_Received_Talk_Bursts };
+const AVP_Code c_AVP_Code_AAA_3GPP_Full_Network_Name := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Full_Network_Name };
+const AVP_Code c_AVP_Code_DCA_3GPP_Message_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Message_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_APN_Rate_Control_Uplink := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_APN_Rate_Control_Uplink };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_CAMEL_Charging_Info := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_CAMEL_Charging_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_From_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_From_Address };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAG_CP_Address := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAG_CP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_PDP_Context_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PDP_Context_Type };
const AVP_Code c_AVP_Code_RX_3GPP_Flows := {
vendor_id_3GPP := avp_code_RX_3GPP_Flows };
+const AVP_Code c_AVP_Code_DCA_3GPP_User_Session_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_User_Session_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Change_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Change_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Privacy_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Privacy_Indicator };
const AVP_Code c_AVP_Code_S6_3GPP_CIA_Flags := {
vendor_id_3GPP := avp_code_S6_3GPP_CIA_Flags };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Min_Requested_BW_UL := {
@@ -8868,6 +14036,10 @@ const AVP_Code c_AVP_Code_PCC_3GPP_Monitoring_Time := {
vendor_id_3GPP := avp_code_PCC_3GPP_Monitoring_Time };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Input_Octets := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Input_Octets };
+const AVP_Code c_AVP_Code_DCA_3GPP_Teleservice := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Teleservice };
+const AVP_Code c_AVP_Code_DCA_3GPP_Quota_Consumption_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Quota_Consumption_Time };
const AVP_Code c_AVP_Code_S6_3GPP_UE_Reachability_Configuration := {
vendor_id_3GPP := avp_code_S6_3GPP_UE_Reachability_Configuration };
const AVP_Code c_AVP_Code_BASE_NONE_Destination_Realm := {
@@ -8876,60 +14048,96 @@ const AVP_Code c_AVP_Code_RX_3GPP_Acceptable_Service_Info := {
vendor_id_3GPP := avp_code_RX_3GPP_Acceptable_Service_Info };
const AVP_Code c_AVP_Code_PCC_3GPP_Flow_Direction := {
vendor_id_3GPP := avp_code_PCC_3GPP_Flow_Direction };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Reason_For_Cancellation := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Reason_For_Cancellation };
const AVP_Code c_AVP_Code_S6_3GPP_Supported_Monitoring_Events := {
vendor_id_3GPP := avp_code_S6_3GPP_Supported_Monitoring_Events };
+const AVP_Code c_AVP_Code_DCA_3GPP_CG_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CG_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Radio_Parameter_Set_Values := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Radio_Parameter_Set_Values };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Item_Number := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Item_Number };
const AVP_Code c_AVP_Code_PCC_3GPP_Session_Release_Cause := {
vendor_id_3GPP := avp_code_PCC_3GPP_Session_Release_Cause };
const AVP_Code c_AVP_Code_AAA_3GPP_MDT_User_Consent := {
vendor_id_3GPP := avp_code_AAA_3GPP_MDT_User_Consent };
-const AVP_Code c_AVP_Code_DNAS_NONE_Login_LAT_Port := {
- vendor_id_NONE := avp_code_DNAS_NONE_Login_LAT_Port };
const AVP_Code c_AVP_Code_S6_3GPP_HSS_Cause := {
vendor_id_3GPP := avp_code_S6_3GPP_HSS_Cause };
-const AVP_Code c_AVP_Code_DCC_NONE_G_S_U_Pool_Reference := {
- vendor_id_NONE := avp_code_DCC_NONE_G_S_U_Pool_Reference };
+const AVP_Code c_AVP_Code_MIPv6_NONE_MIP6_Home_Link_Prefix := {
+ vendor_id_NONE := avp_code_MIPv6_NONE_MIP6_Home_Link_Prefix };
+const AVP_Code c_AVP_Code_DNAS_NONE_Login_LAT_Port := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Login_LAT_Port };
const AVP_Code c_AVP_Code_PCC_3GPP_PCSCF_Restoration_Indication := {
vendor_id_3GPP := avp_code_PCC_3GPP_PCSCF_Restoration_Indication };
+const AVP_Code c_AVP_Code_DCC_NONE_G_S_U_Pool_Reference := {
+ vendor_id_NONE := avp_code_DCC_NONE_G_S_U_Pool_Reference };
+const AVP_Code c_AVP_Code_DCA_3GPP_Layer_2_Group_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Layer_2_Group_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Interface_Port := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Interface_Port };
const AVP_Code c_AVP_Code_AAA_3GPP_Subscription_Data_Deletion := {
vendor_id_3GPP := avp_code_AAA_3GPP_Subscription_Data_Deletion };
const AVP_Code c_AVP_Code_MIPv6_NONE_Chargable_User_Identity := {
vendor_id_NONE := avp_code_MIPv6_NONE_Chargable_User_Identity };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_Collection_Entity := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_Collection_Entity };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Request_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Request_Type };
const AVP_Code c_AVP_Code_CxDx_3GPP_Feature_List_ID := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Feature_List_ID };
const AVP_Code c_AVP_Code_BASE_NONE_Redirect_Host := {
vendor_id_NONE := avp_code_BASE_NONE_Redirect_Host };
const AVP_Code c_AVP_Code_AAA_3GPP_Network_Access_Mode := {
vendor_id_3GPP := avp_code_AAA_3GPP_Network_Access_Mode };
-const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Zone_Access := {
- vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Zone_Access };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Compression := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Compression };
+const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Zone_Access := {
+ vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Zone_Access };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Selection_Mode := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Selection_Mode };
const AVP_Code c_AVP_Code_DNAS_NONE_QoS_Filter_Rule := {
vendor_id_NONE := avp_code_DNAS_NONE_QoS_Filter_Rule };
const AVP_Code c_AVP_Code_AAA_3GPP_Complete_Data_List_Included_Indicator := {
vendor_id_3GPP := avp_code_AAA_3GPP_Complete_Data_List_Included_Indicator };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MN_AAA_SPI := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MN_AAA_SPI };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_MN_AAA_SPI := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_MN_AAA_SPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Client_Name := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Client_Name };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_SGSN_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_SGSN_Address };
-const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_MSA_Lifetime := {
- vendor_id_NONE := avp_code_MIPv6_NONE_MIP_MSA_Lifetime };
+const AVP_Code c_AVP_Code_DCA_3GPP_Related_IMS_Charging_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Related_IMS_Charging_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Called_Asserted_Identity := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Called_Asserted_Identity };
+const AVP_Code c_AVP_Code_DCA_3GPP_TWAG_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_TWAG_Address };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_MSA_Lifetime := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_MSA_Lifetime };
+const AVP_Code c_AVP_Code_DCA_3GPP_Talk_Burst_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Talk_Burst_Time };
+const AVP_Code c_AVP_Code_DCA_3GPP_Token_Text := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Token_Text };
+const AVP_Code c_AVP_Code_DCA_3GPP_Rate_Control_Time_Unit := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Rate_Control_Time_Unit };
const AVP_Code c_AVP_Code_GI_3GPP_External_Identifier := {
vendor_id_3GPP := avp_code_GI_3GPP_External_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Reason_Header := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Reason_Header };
+const AVP_Code c_AVP_Code_AAA_3GPP_WLCP_Key := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_WLCP_Key };
const AVP_Code c_AVP_Code_S6_3GPP_Reachability_Type := {
vendor_id_3GPP := avp_code_S6_3GPP_Reachability_Type };
-const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Private_Group_Id := {
- vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Private_Group_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_SIP_Request_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SIP_Request_Timestamp };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Route := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Route };
+const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Private_Group_Id := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Private_Group_Id };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Request_Type := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Request_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Source_IP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Source_IP_Address };
const AVP_Code c_AVP_Code_S6_3GPP_Type_Of_External_Identifier := {
vendor_id_3GPP := avp_code_S6_3GPP_Type_Of_External_Identifier };
const AVP_Code c_AVP_Code_PCC_3GPP_Event_Report_Indication := {
@@ -8938,26 +14146,36 @@ const AVP_Code c_AVP_Code_AAA_3GPP_MDT_Configuration := {
vendor_id_3GPP := avp_code_AAA_3GPP_MDT_Configuration };
const AVP_Code c_AVP_Code_PCC_3GPP_Usage_Monitoring_Report := {
vendor_id_3GPP := avp_code_PCC_3GPP_Usage_Monitoring_Report };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_Of_Participants := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_Of_Participants };
+const AVP_Code c_AVP_Code_DCA_3GPP_MSC_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MSC_Address };
const AVP_Code c_AVP_Code_CxDx_3GPP_Priviledged_Sender_Indication := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Priviledged_Sender_Indication };
const AVP_Code c_AVP_Code_AAA_3GPP_Adjacent_Access_Restriction_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_Adjacent_Access_Restriction_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Service_Obligatory_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Service_Obligatory_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_RAT_Frequency_Selection_Priority_ID := {
vendor_id_3GPP := avp_code_AAA_3GPP_RAT_Frequency_Selection_Priority_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_First_Usage := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_First_Usage };
const AVP_Code c_AVP_Code_CxDx_3GPP_Reason_Info := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Reason_Info };
-const AVP_Code c_AVP_Code_AAA_3GPP_CLR_Flags := {
- vendor_id_3GPP := avp_code_AAA_3GPP_CLR_Flags };
const AVP_Code c_AVP_Code_PCC_3GPP_Default_EPS_Bearer_QoS := {
vendor_id_3GPP := avp_code_PCC_3GPP_Default_EPS_Bearer_QoS };
+const AVP_Code c_AVP_Code_AAA_3GPP_CLR_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_CLR_Flags };
const AVP_Code c_AVP_Code_AAA_3GPP_ULR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_ULR_Flags };
-const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Client_Auth_Id := {
- vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Client_Auth_Id };
-const AVP_Code c_AVP_Code_DNAS_NONE_Calling_Station_Id := {
- vendor_id_NONE := avp_code_DNAS_NONE_Calling_Station_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originating_SCCP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originating_SCCP_Address };
const AVP_Code c_AVP_Code_AAA_3GPP_ICS_Indicator := {
vendor_id_3GPP := avp_code_AAA_3GPP_ICS_Indicator };
+const AVP_Code c_AVP_Code_DNAS_NONE_Calling_Station_Id := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Calling_Station_Id };
+const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Client_Auth_Id := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Client_Auth_Id };
const AVP_Code c_AVP_Code_DCC_NONE_Currency_Code := {
vendor_id_NONE := avp_code_DCC_NONE_Currency_Code };
const AVP_Code c_AVP_Code_AAA_3GPP_Cancellation_Type := {
@@ -8968,16 +14186,40 @@ const AVP_Code c_AVP_Code_BASE_NONE_Origin_Realm := {
vendor_id_NONE := avp_code_BASE_NONE_Origin_Realm };
const AVP_Code c_AVP_Code_AAA_3GPP_PDN_Type := {
vendor_id_3GPP := avp_code_AAA_3GPP_PDN_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Scale_Factor := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Scale_Factor };
+const AVP_Code c_AVP_Code_DCA_3GPP_IM_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IM_Information };
const AVP_Code c_AVP_Code_DNAS_NONE_Prompt := {
vendor_id_NONE := avp_code_DNAS_NONE_Prompt };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Offer_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Offer_Timestamp };
+const AVP_Code c_AVP_Code_AAA_3GPP_PPR_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_PPR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_MM_Content_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MM_Content_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_CPDT_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CPDT_Information };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_GGSN_IPv6_Address := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_GGSN_IPv6_Address };
+const AVP_Code c_AVP_Code_AAA_3GPP_DER_S6b_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_DER_S6b_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_SCS_Realm := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SCS_Realm };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Requestor_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Requestor_Id };
const AVP_Code c_AVP_Code_RX_3GPP_Access_Network_Charging_Identifier := {
vendor_id_3GPP := avp_code_RX_3GPP_Access_Network_Charging_Identifier };
const AVP_Code c_AVP_Code_DCC_NONE_Redirect_Server := {
vendor_id_NONE := avp_code_DCC_NONE_Redirect_Server };
const AVP_Code c_AVP_Code_S6_3GPP_AESE_Communication_Pattern_Config_Status := {
vendor_id_3GPP := avp_code_S6_3GPP_AESE_Communication_Pattern_Config_Status };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_User_Role_info_Units := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_User_Role_info_Units };
+const AVP_Code c_AVP_Code_DCA_3GPP_Variable_Part := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Variable_Part };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_3rd_Party_Application_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_3rd_Party_Application_ID };
const AVP_Code c_AVP_Code_S6_3GPP_Enhanced_Coverage_Restriction_Data := {
vendor_id_3GPP := avp_code_S6_3GPP_Enhanced_Coverage_Restriction_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_Bearer_Operation := {
@@ -8988,34 +14230,48 @@ const AVP_Code c_AVP_Code_RX_3GPP_Pre_emption_Control_Info := {
vendor_id_3GPP := avp_code_RX_3GPP_Pre_emption_Control_Info };
const AVP_Code c_AVP_Code_PCC_3GPP_TDF_Application_Instance_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_Application_Instance_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Device_Trigger_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Device_Trigger_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Service_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Service_Information };
const AVP_Code c_AVP_Code_BASE_NONE_Acct_Interim_Interval := {
vendor_id_NONE := avp_code_BASE_NONE_Acct_Interim_Interval };
const AVP_Code c_AVP_Code_RX_3GPP_Media_Component_Number := {
vendor_id_3GPP := avp_code_RX_3GPP_Media_Component_Number };
const AVP_Code c_AVP_Code_CxDx_3GPP_Path := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Path };
-const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_Event_1F := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Event_Threshold_Event_1F };
const AVP_Code c_AVP_Code_PCC_3GPP_Packet_Filter_Usage := {
vendor_id_3GPP := avp_code_PCC_3GPP_Packet_Filter_Usage };
+const AVP_Code c_AVP_Code_AAA_3GPP_Event_Threshold_Event_1F := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Event_Threshold_Event_1F };
const AVP_Code c_AVP_Code_S6_3GPP_MONTE_Location_Type := {
vendor_id_3GPP := avp_code_S6_3GPP_MONTE_Location_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_Inter_Operator_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Inter_Operator_Identifier };
const AVP_Code c_AVP_Code_AAA_3GPP_RDS_Indicator := {
vendor_id_3GPP := avp_code_AAA_3GPP_RDS_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_Proximity_Cancellation_Timestamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Proximity_Cancellation_Timestamp };
+const AVP_Code c_AVP_Code_DCA_3GPP_MMTel_SService_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MMTel_SService_Type };
const AVP_Code c_AVP_Code_CxDx_3GPP_Optional_Capability := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Optional_Capability };
-const AVP_Code c_AVP_Code_AAA_3GPP_Reporting_Trigger := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Reporting_Trigger };
const AVP_Code c_AVP_Code_PCC_3GPP_Tunnel_Header_Length := {
vendor_id_3GPP := avp_code_PCC_3GPP_Tunnel_Header_Length };
+const AVP_Code c_AVP_Code_AAA_3GPP_Reporting_Trigger := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Reporting_Trigger };
const AVP_Code c_AVP_Code_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate := {
vendor_id_3GPP := avp_code_PCC_3GPP_Conditional_APN_Aggregate_Max_Bitrate };
const AVP_Code c_AVP_Code_CxDx_3GPP_Secondary_Event_Charging_Function_Name := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Secondary_Event_Charging_Function_Name };
const AVP_Code c_AVP_Code_AAA_3GPP_Group_PLMN_Id := {
vendor_id_3GPP := avp_code_AAA_3GPP_Group_PLMN_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Reply_Path_Requested := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Reply_Path_Requested };
const AVP_Code c_AVP_Code_AAA_3GPP_User_Id := {
vendor_id_3GPP := avp_code_AAA_3GPP_User_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Serving_Node_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Serving_Node_Type };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_LAT_Node := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_LAT_Node };
const AVP_Code c_AVP_Code_DNAS_NONE_Originating_Line_Info := {
@@ -9024,164 +14280,266 @@ const AVP_Code c_AVP_Code_DCC_NONE_Exponent := {
vendor_id_NONE := avp_code_DCC_NONE_Exponent };
const AVP_Code c_AVP_Code_MIPv6_NONE_MIP_Authenticator := {
vendor_id_NONE := avp_code_MIPv6_NONE_MIP_Authenticator };
-const AVP_Code c_AVP_Code_DNAS_NONE_Accounting_Input_Octets := {
- vendor_id_NONE := avp_code_DNAS_NONE_Accounting_Input_Octets };
const AVP_Code c_AVP_Code_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info := {
vendor_id_3GPP := avp_code_AAA_3GPP_Requested_UTRAN_GERAN_Authentication_Info };
+const AVP_Code c_AVP_Code_MIPv4_NONE_Accounting_Input_Octets := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_Accounting_Input_Octets };
const AVP_Code c_AVP_Code_AAA_3GPP_EPS_User_State := {
vendor_id_3GPP := avp_code_AAA_3GPP_EPS_User_State };
const AVP_Code c_AVP_Code_BASE_NONE_Origin_Host := {
vendor_id_NONE := avp_code_BASE_NONE_Origin_Host };
+const AVP_Code c_AVP_Code_AAA_3GPP_Access_Authorization_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Access_Authorization_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_PDP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PDP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CP_CIoT_EPS_Optimisation_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_NNI_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_NNI_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Location_Estimate := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Location_Estimate };
+const AVP_Code c_AVP_Code_DCA_3GPP_Offline_Charging := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Offline_Charging };
const AVP_Code c_AVP_Code_RX_3GPP_Retry_Interval := {
vendor_id_3GPP := avp_code_RX_3GPP_Retry_Interval };
const AVP_Code c_AVP_Code_BASE_NONE_Accounting_Session_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Accounting_Session_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Additional_Content_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Additional_Content_Information };
const AVP_Code c_AVP_Code_DCC_NONE_Restriction_Filter_Rule := {
vendor_id_NONE := avp_code_DCC_NONE_Restriction_Filter_Rule };
+const AVP_Code c_AVP_Code_DCA_3GPP_Cause_Code := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Cause_Code };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_Connection_Mode := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_Connection_Mode };
const AVP_Code c_AVP_Code_PCC_3GPP_Packet_Filter_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_Packet_Filter_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Address_Data := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Address_Data };
const AVP_Code c_AVP_Code_S6_3GPP_SCEF_Reference_ID := {
vendor_id_3GPP := avp_code_S6_3GPP_SCEF_Reference_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_Content_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Content_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_Resource_Release_Notification := {
vendor_id_3GPP := avp_code_PCC_3GPP_Resource_Release_Notification };
const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Name };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Function_IP_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Function_IP_Address };
+const AVP_Code c_AVP_Code_PCC_3GPP_Guaranteed_Bitrate_DL := {
+ vendor_id_3GPP := avp_code_PCC_3GPP_Guaranteed_Bitrate_DL };
const AVP_Code c_AVP_Code_BASE_NONE_Disconnect_Cause := {
vendor_id_NONE := avp_code_BASE_NONE_Disconnect_Cause };
const AVP_Code c_AVP_Code_AAA_3GPP_Error_Diagnostic := {
vendor_id_3GPP := avp_code_AAA_3GPP_Error_Diagnostic };
-const AVP_Code c_AVP_Code_PCC_3GPP_Guaranteed_Bitrate_DL := {
- vendor_id_3GPP := avp_code_PCC_3GPP_Guaranteed_Bitrate_DL };
const AVP_Code c_AVP_Code_RX_3GPP_Extended_Max_Supported_BW_UL := {
vendor_id_3GPP := avp_code_RX_3GPP_Extended_Max_Supported_BW_UL };
-const AVP_Code c_AVP_Code_DCC_NONE_CC_Total_Octets := {
- vendor_id_NONE := avp_code_DCC_NONE_CC_Total_Octets };
const AVP_Code c_AVP_Code_PCC_3GPP_UDP_Source_Port := {
vendor_id_3GPP := avp_code_PCC_3GPP_UDP_Source_Port };
+const AVP_Code c_AVP_Code_DCC_NONE_CC_Total_Octets := {
+ vendor_id_NONE := avp_code_DCC_NONE_CC_Total_Octets };
const AVP_Code c_AVP_Code_BASE_NONE_Accounting_Record_Type := {
vendor_id_NONE := avp_code_BASE_NONE_Accounting_Record_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_SMS_Result := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SMS_Result };
+const AVP_Code c_AVP_Code_DCA_3GPP_MMS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MMS_Information };
const AVP_Code c_AVP_Code_CxDx_3GPP_From_SIP_Header := {
vendor_id_3GPP := avp_code_CxDx_3GPP_From_SIP_Header };
-const AVP_Code c_AVP_Code_AAA_3GPP_SIPTO_Local_Network_Permission := {
- vendor_id_3GPP := avp_code_AAA_3GPP_SIPTO_Local_Network_Permission };
const AVP_Code c_AVP_Code_PCC_3GPP_Routing_Rule_Definition := {
vendor_id_3GPP := avp_code_PCC_3GPP_Routing_Rule_Definition };
-const AVP_Code c_AVP_Code_DCC_NONE_Value_Digits := {
- vendor_id_NONE := avp_code_DCC_NONE_Value_Digits };
+const AVP_Code c_AVP_Code_AAA_3GPP_SIPTO_Local_Network_Permission := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SIPTO_Local_Network_Permission };
+const AVP_Code c_AVP_Code_DCA_3GPP_CUG_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_CUG_Information };
const AVP_Code c_AVP_Code_AAA_3GPP_VPLMN_Dynamic_Address_Allowed := {
vendor_id_3GPP := avp_code_AAA_3GPP_VPLMN_Dynamic_Address_Allowed };
+const AVP_Code c_AVP_Code_DCC_NONE_Value_Digits := {
+ vendor_id_NONE := avp_code_DCC_NONE_Value_Digits };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_MN_AAA_Auth := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_MN_AAA_Auth };
const AVP_Code c_AVP_Code_BASE_NONE_Acct_Application_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Acct_Application_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Associated_Party_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Associated_Party_Address };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Authenticate := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Authenticate };
const AVP_Code c_AVP_Code_AAA_3GPP_Service_Type := {
vendor_id_3GPP := avp_code_AAA_3GPP_Service_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_Immediate_Response_Preferred := {
vendor_id_3GPP := avp_code_AAA_3GPP_Immediate_Response_Preferred };
-const AVP_Code c_AVP_Code_DNAS_NONE_Login_IPv6_Host := {
- vendor_id_NONE := avp_code_DNAS_NONE_Login_IPv6_Host };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_Appletalk_Zone := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_Appletalk_Zone };
-const AVP_Code c_AVP_Code_DCC_NONE_Final_Unit_Indication := {
- vendor_id_NONE := avp_code_DCC_NONE_Final_Unit_Indication };
+const AVP_Code c_AVP_Code_DNAS_NONE_Login_IPv6_Host := {
+ vendor_id_NONE := avp_code_DNAS_NONE_Login_IPv6_Host };
+const AVP_Code c_AVP_Code_DCA_3GPP_Local_GW_Inserted_Indication := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Local_GW_Inserted_Indication };
const AVP_Code c_AVP_Code_AAA_3GPP_XRES := {
vendor_id_3GPP := avp_code_AAA_3GPP_XRES };
+const AVP_Code c_AVP_Code_DCC_NONE_Final_Unit_Indication := {
+ vendor_id_NONE := avp_code_DCC_NONE_Final_Unit_Indication };
+const AVP_Code c_AVP_Code_DCA_3GPP_Deferred_Location_Event_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Deferred_Location_Event_Type };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_IMSI := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_IMSI };
const AVP_Code c_AVP_Code_AAA_3GPP_User_State := {
vendor_id_3GPP := avp_code_AAA_3GPP_User_State };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_MN_to_HA_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_MN_to_HA_MSA };
const AVP_Code c_AVP_Code_BASE_NONE_Result_Code := {
vendor_id_NONE := avp_code_BASE_NONE_Result_Code };
+const AVP_Code c_AVP_Code_DCA_3GPP_Envelope := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Envelope };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_Event_Configuration_Activity := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_Event_Configuration_Activity };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Communication_Service_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Communication_Service_Identifier };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_IP_Address := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_IP_Address };
+const AVP_Code c_AVP_Code_AAA_3GPP_Trust_Relationship_Update := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Trust_Relationship_Update };
+const AVP_Code c_AVP_Code_DCA_3GPP_APN_Rate_Control_Downlink := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_APN_Rate_Control_Downlink };
+const AVP_Code c_AVP_Code_DCA_3GPP_Session_Direction := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Session_Direction };
const AVP_Code c_AVP_Code_S6_3GPP_IP_SM_GW_Realm := {
vendor_id_3GPP := avp_code_S6_3GPP_IP_SM_GW_Realm };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_UE_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_UE_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_Reference_ID_Validity_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Reference_ID_Validity_Time };
-const AVP_Code c_AVP_Code_AAA_3GPP_E_UTRAN_Cell_Global_Identity := {
- vendor_id_3GPP := avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity };
const AVP_Code c_AVP_Code_PCC_3GPP_TFT_Packet_Filter_Information := {
vendor_id_3GPP := avp_code_PCC_3GPP_TFT_Packet_Filter_Information };
+const AVP_Code c_AVP_Code_AAA_3GPP_E_UTRAN_Cell_Global_Identity := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_E_UTRAN_Cell_Global_Identity };
const AVP_Code c_AVP_Code_RX_3GPP_Min_Desired_Bandwidth_DL := {
vendor_id_3GPP := avp_code_RX_3GPP_Min_Desired_Bandwidth_DL };
+const AVP_Code c_AVP_Code_DCA_3GPP_Transmitter_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Transmitter_Info };
const AVP_Code c_AVP_Code_S6_3GPP_Group_Reporting_Guard_Timer := {
vendor_id_3GPP := avp_code_S6_3GPP_Group_Reporting_Guard_Timer };
+const AVP_Code c_AVP_Code_DCA_3GPP_PS_Furnish_Charging_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PS_Furnish_Charging_Information };
const AVP_Code c_AVP_Code_CxDx_3GPP_Associated_Identities := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Associated_Identities };
-const AVP_Code c_AVP_Code_BASE_NONE_Auth_Session_State := {
- vendor_id_NONE := avp_code_BASE_NONE_Auth_Session_State };
const AVP_Code c_AVP_Code_PCC_3GPP_Session_Linking_Indicator := {
vendor_id_3GPP := avp_code_PCC_3GPP_Session_Linking_Indicator };
+const AVP_Code c_AVP_Code_BASE_NONE_Auth_Session_State := {
+ vendor_id_NONE := avp_code_BASE_NONE_Auth_Session_State };
const AVP_Code c_AVP_Code_S6_3GPP_Maximum_Number_of_Reports := {
vendor_id_3GPP := avp_code_S6_3GPP_Maximum_Number_of_Reports };
const AVP_Code c_AVP_Code_PCC_3GPP_PRA_Install := {
vendor_id_3GPP := avp_code_PCC_3GPP_PRA_Install };
const AVP_Code c_AVP_Code_AAA_3GPP_V2X_Permission := {
vendor_id_3GPP := avp_code_AAA_3GPP_V2X_Permission };
-const AVP_Code c_AVP_Code_AAA_3GPP_LIPA_Permission := {
- vendor_id_3GPP := avp_code_AAA_3GPP_LIPA_Permission };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Range_Class := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Range_Class };
+const AVP_Code c_AVP_Code_DCA_3GPP_Carrier_Select_Routing_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Carrier_Select_Routing_Information };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Negotiation := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Negotiation };
+const AVP_Code c_AVP_Code_AAA_3GPP_LIPA_Permission := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_LIPA_Permission };
const AVP_Code c_AVP_Code_CxDx_3GPP_SIP_Auth_Data_Item := {
vendor_id_3GPP := avp_code_CxDx_3GPP_SIP_Auth_Data_Item };
const AVP_Code c_AVP_Code_AAA_3GPP_3GPP2_MEID := {
vendor_id_3GPP := avp_code_AAA_3GPP_3GPP2_MEID };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_FA_to_MN_MSA := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_FA_to_MN_MSA };
const AVP_Code c_AVP_Code_AAA_3GPP_Subscription_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_Subscription_Data };
const AVP_Code c_AVP_Code_CxDx_3GPP_Multiple_Registration_Indication := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Multiple_Registration_Indication };
-const AVP_Code c_AVP_Code_BASE_NONE_Vendor_Specific_Application_Id := {
- vendor_id_NONE := avp_code_BASE_NONE_Vendor_Specific_Application_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_WLAN_offloadability_UTRAN := {
vendor_id_3GPP := avp_code_AAA_3GPP_WLAN_offloadability_UTRAN };
+const AVP_Code c_AVP_Code_BASE_NONE_Vendor_Specific_Application_Id := {
+ vendor_id_NONE := avp_code_BASE_NONE_Vendor_Specific_Application_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMSI_Unauthenticated_Flag := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMSI_Unauthenticated_Flag };
+const AVP_Code c_AVP_Code_DCA_3GPP_Interface_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Interface_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_CSG_Subscription_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_CSG_Subscription_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_Diagnostics := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Diagnostics };
const AVP_Code c_AVP_Code_MIPv6_NONE_Service_Selection := {
vendor_id_NONE := avp_code_MIPv6_NONE_Service_Selection };
const AVP_Code c_AVP_Code_AAA_3GPP_TS_Code := {
vendor_id_3GPP := avp_code_AAA_3GPP_TS_Code };
const AVP_Code c_AVP_Code_DNAS_NONE_Tunnel_Client_Endpoint := {
vendor_id_NONE := avp_code_DNAS_NONE_Tunnel_Client_Endpoint };
+const AVP_Code c_AVP_Code_AAA_3GPP_AN_Trusted := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_AN_Trusted };
+const AVP_Code c_AVP_Code_DCA_3GPP_Monitoring_Event_Funtionality := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Monitoring_Event_Funtionality };
+const AVP_Code c_AVP_Code_DCA_3GPP_Aux_Applic_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Aux_Applic_Info };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Nonce := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Nonce };
const AVP_Code c_AVP_Code_S6_3GPP_IP_SM_GW_Number := {
vendor_id_3GPP := avp_code_S6_3GPP_IP_SM_GW_Number };
+const AVP_Code c_AVP_Code_AAA_3GPP_AAR_Flags := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_AAR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Client_External_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Client_External_ID };
+const AVP_Code c_AVP_Code_DCA_3GPP_VLR_Number := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_VLR_Number };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Install := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Install };
const AVP_Code c_AVP_Code_RX_3GPP_Rx_Request_Type := {
vendor_id_3GPP := avp_code_RX_3GPP_Rx_Request_Type };
const AVP_Code c_AVP_Code_S6_3GPP_NIDD_Authorization_Response := {
vendor_id_3GPP := avp_code_S6_3GPP_NIDD_Authorization_Response };
+const AVP_Code c_AVP_Code_DCA_3GPP_Outgoing_Trunk_Group_Id := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Outgoing_Trunk_Group_Id };
+const AVP_Code c_AVP_Code_AAA_3GPP_Transport_Access_Type := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Transport_Access_Type };
const AVP_Code c_AVP_Code_DCC_NONE_Subscription_Id := {
vendor_id_NONE := avp_code_DCC_NONE_Subscription_Id };
-const AVP_Code c_AVP_Code_AAA_3GPP_VPLMN_CSG_Subscription_Data := {
- vendor_id_3GPP := avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_QoS_Rule_Remove := {
vendor_id_3GPP := avp_code_PCC_3GPP_QoS_Rule_Remove };
+const AVP_Code c_AVP_Code_AAA_3GPP_VPLMN_CSG_Subscription_Data := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_VPLMN_CSG_Subscription_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_Message_Body := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Message_Body };
const AVP_Code c_AVP_Code_S6_3GPP_Communication_Duration_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Communication_Duration_Time };
const AVP_Code c_AVP_Code_PCC_3GPP_Access_Availability_Change_Reason := {
vendor_id_3GPP := avp_code_PCC_3GPP_Access_Availability_Change_Reason };
const AVP_Code c_AVP_Code_PCC_3GPP_TDF_Application_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_Application_Identifier };
+const AVP_Code c_AVP_Code_DCA_3GPP_Requested_PLMN_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Requested_PLMN_Identifier };
const AVP_Code c_AVP_Code_AAA_3GPP_Location_Area_Identity := {
vendor_id_3GPP := avp_code_AAA_3GPP_Location_Area_Identity };
const AVP_Code c_AVP_Code_RX_3GPP_Media_Component_Status := {
vendor_id_3GPP := avp_code_RX_3GPP_Media_Component_Status };
const AVP_Code c_AVP_Code_AAA_3GPP_eDRX_Cycle_Length_Value := {
vendor_id_3GPP := avp_code_AAA_3GPP_eDRX_Cycle_Length_Value };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_FA_Challenge := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_FA_Challenge };
const AVP_Code c_AVP_Code_CxDx_3GPP_Visited_Network_Identifier := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Visited_Network_Identifier };
const AVP_Code c_AVP_Code_S6_3GPP_RIR_Flags := {
vendor_id_3GPP := avp_code_S6_3GPP_RIR_Flags };
-const AVP_Code c_AVP_Code_AAA_3GPP_Collection_Period_RRM_LTE := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Collection_Period_RRM_LTE };
+const AVP_Code c_AVP_Code_DCA_3GPP_Volume_Quota_Threshold := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Volume_Quota_Threshold };
+const AVP_Code c_AVP_Code_DCA_3GPP_Incremental_Cost := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Incremental_Cost };
const AVP_Code c_AVP_Code_PCC_3GPP_Usage_Monitoring_Level := {
vendor_id_3GPP := avp_code_PCC_3GPP_Usage_Monitoring_Level };
-const AVP_Code c_AVP_Code_AAA_3GPP_Subscriber_Status := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Subscriber_Status };
+const AVP_Code c_AVP_Code_AAA_3GPP_Collection_Period_RRM_LTE := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Collection_Period_RRM_LTE };
const AVP_Code c_AVP_Code_PCC_3GPP_Extended_APN_AMBR_UL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Extended_APN_AMBR_UL };
+const AVP_Code c_AVP_Code_AAA_3GPP_Subscriber_Status := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Subscriber_Status };
const AVP_Code c_AVP_Code_CxDx_3GPP_Identity_with_Emergency_Registration := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Identity_with_Emergency_Registration };
+const AVP_Code c_AVP_Code_DCA_3GPP_Originator_Received_Address := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Originator_Received_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Service := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Service };
const AVP_Code c_AVP_Code_DCC_NONE_Tariff_Change_Usage := {
vendor_id_NONE := avp_code_DCC_NONE_Tariff_Change_Usage };
const AVP_Code c_AVP_Code_AAA_3GPP_LCS_PrivacyException := {
@@ -9190,96 +14548,158 @@ const AVP_Code c_AVP_Code_AAA_3GPP_QoS_Subscribed := {
vendor_id_3GPP := avp_code_AAA_3GPP_QoS_Subscribed };
const AVP_Code c_AVP_Code_DNAS_NONE_NAS_IP_Address := {
vendor_id_NONE := avp_code_DNAS_NONE_NAS_IP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Variable_Part_Value := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Variable_Part_Value };
+const AVP_Code c_AVP_Code_DCA_3GPP_Read_Reply_Report_Requested := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Read_Reply_Report_Requested };
+const AVP_Code c_AVP_Code_DCA_3GPP_Event_Charging_TimeStamp := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Event_Charging_TimeStamp };
const AVP_Code c_AVP_Code_RX_3GPP_RR_Bandwidth := {
vendor_id_3GPP := avp_code_RX_3GPP_RR_Bandwidth };
-const AVP_Code c_AVP_Code_DCC_NONE_Service_Context_Id := {
- vendor_id_NONE := avp_code_DCC_NONE_Service_Context_Id };
const AVP_Code c_AVP_Code_DNAS_NONE_CHAP_Auth := {
vendor_id_NONE := avp_code_DNAS_NONE_CHAP_Auth };
+const AVP_Code c_AVP_Code_DCC_NONE_Service_Context_Id := {
+ vendor_id_NONE := avp_code_DCC_NONE_Service_Context_Id };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Authenticator_Length := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Authenticator_Length };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_TimeStamps := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_TimeStamps };
+const AVP_Code c_AVP_Code_DCA_3GPP_IMS_Charging_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_IMS_Charging_Identifier };
+const AVP_Code c_AVP_Code_AAA_3GPP_MIP_FA_RK_SPI := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_MIP_FA_RK_SPI };
+const AVP_Code c_AVP_Code_DCA_3GPP_Related_Trigger := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Related_Trigger };
const AVP_Code c_AVP_Code_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL := {
vendor_id_3GPP := avp_code_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL };
const AVP_Code c_AVP_Code_S6_3GPP_SCS_Identity := {
vendor_id_3GPP := avp_code_S6_3GPP_SCS_Identity };
+const AVP_Code c_AVP_Code_DCA_3GPP_LCS_Name_String := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_LCS_Name_String };
const AVP_Code c_AVP_Code_RX_3GPP_Access_Network_Charging_Address := {
vendor_id_3GPP := avp_code_RX_3GPP_Access_Network_Charging_Address };
const AVP_Code c_AVP_Code_PCC_3GPP_Presence_Reporting_Area_Identifier := {
vendor_id_3GPP := avp_code_PCC_3GPP_Presence_Reporting_Area_Identifier };
const AVP_Code c_AVP_Code_BASE_NONE_Inband_Security_Id := {
vendor_id_NONE := avp_code_BASE_NONE_Inband_Security_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_ISUP_Cause_Value := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ISUP_Cause_Value };
const AVP_Code c_AVP_Code_PCC_3GPP_Charging_Rule_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_Charging_Rule_Name };
const AVP_Code c_AVP_Code_RX_3GPP_Ip_Domain_Id := {
vendor_id_3GPP := avp_code_RX_3GPP_Ip_Domain_Id };
-const AVP_Code c_AVP_Code_AAA_3GPP_UE_Usage_Type := {
- vendor_id_3GPP := avp_code_AAA_3GPP_UE_Usage_Type };
const AVP_Code c_AVP_Code_PCC_3GPP_TDF_IP_Address := {
vendor_id_3GPP := avp_code_PCC_3GPP_TDF_IP_Address };
+const AVP_Code c_AVP_Code_AAA_3GPP_UE_Usage_Type := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_UE_Usage_Type };
const AVP_Code c_AVP_Code_S6_3GPP_Enhanced_Coverage_Restriction := {
vendor_id_3GPP := avp_code_S6_3GPP_Enhanced_Coverage_Restriction };
+const AVP_Code c_AVP_Code_DCA_3GPP_Charged_Party := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Charged_Party };
+const AVP_Code c_AVP_Code_DCA_3GPP_PDN_Connection_Charging_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PDN_Connection_Charging_ID };
const AVP_Code c_AVP_Code_CxDx_3GPP_User_Data_Already_Available := {
vendor_id_3GPP := avp_code_CxDx_3GPP_User_Data_Already_Available };
-const AVP_Code c_AVP_Code_AAA_3GPP_MME_Number_for_MT_SMS := {
- vendor_id_3GPP := avp_code_AAA_3GPP_MME_Number_for_MT_SMS };
const AVP_Code c_AVP_Code_PCC_3GPP_Security_Parameter_Index := {
vendor_id_3GPP := avp_code_PCC_3GPP_Security_Parameter_Index };
-const AVP_Code c_AVP_Code_DCC_NONE_CC_Correlation_Id := {
- vendor_id_NONE := avp_code_DCC_NONE_CC_Correlation_Id };
+const AVP_Code c_AVP_Code_AAA_3GPP_MME_Number_for_MT_SMS := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_MME_Number_for_MT_SMS };
const AVP_Code c_AVP_Code_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL := {
vendor_id_3GPP := avp_code_PCC_3GPP_Traffic_Steering_Policy_Identifier_UL };
+const AVP_Code c_AVP_Code_DCC_NONE_CC_Correlation_Id := {
+ vendor_id_NONE := avp_code_DCC_NONE_CC_Correlation_Id };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Home_Agent_Host := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Home_Agent_Host };
const AVP_Code c_AVP_Code_BASE_NONE_Route_Record := {
vendor_id_NONE := avp_code_BASE_NONE_Route_Record };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_User_Data_Header := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_User_Data_Header };
const AVP_Code c_AVP_Code_AAA_3GPP_Carrier_Frequency := {
vendor_id_3GPP := avp_code_AAA_3GPP_Carrier_Frequency };
+const AVP_Code c_AVP_Code_DCA_3GPP_MMTel_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MMTel_Information };
const AVP_Code c_AVP_Code_CxDx_3GPP_Mandatory_Capability := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Mandatory_Capability };
const AVP_Code c_AVP_Code_AAA_3GPP_Trace_NE_Type_List := {
vendor_id_3GPP := avp_code_AAA_3GPP_Trace_NE_Type_List };
+const AVP_Code c_AVP_Code_DCA_3GPP_Charging_Characteristics_Selection_Mode := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Charging_Characteristics_Selection_Mode };
const AVP_Code c_AVP_Code_DNAS_NONE_Port_Limit := {
vendor_id_NONE := avp_code_DNAS_NONE_Port_Limit };
+const AVP_Code c_AVP_Code_MIPv6_NONE_MIP6_Feature_Vector := {
+ vendor_id_NONE := avp_code_MIPv6_NONE_MIP6_Feature_Vector };
const AVP_Code c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control := {
vendor_id_NONE := avp_code_DCC_NONE_Multiple_Services_Credit_Control };
const AVP_Code c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator := {
vendor_id_3GPP := avp_code_AAA_3GPP_All_APN_Configurations_Included_Indicator };
const AVP_Code c_AVP_Code_AAA_3GPP_NOR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_NOR_Flags };
+const AVP_Code c_AVP_Code_DCA_3GPP_Message_ID := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Message_ID };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_MS_TimeZone := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_MS_TimeZone };
const AVP_Code c_AVP_Code_AAA_3GPP_External_Client := {
vendor_id_3GPP := avp_code_AAA_3GPP_External_Client };
+const AVP_Code c_AVP_Code_DCA_3GPP_Charge_Reason_Code := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Charge_Reason_Code };
const AVP_Code c_AVP_Code_BASE_NONE_Authorization_Lifetime := {
vendor_id_NONE := avp_code_BASE_NONE_Authorization_Lifetime };
+const AVP_Code c_AVP_Code_AAA_3GPP_TWAN_PCO := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_TWAN_PCO };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Change_Conditions := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Change_Conditions };
+const AVP_Code c_AVP_Code_DCA_3GPP_Language := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Language };
+const AVP_Code c_AVP_Code_RX_3GPP_Extended_Min_Requested_BW_DL := {
+ vendor_id_3GPP := avp_code_RX_3GPP_Extended_Min_Requested_BW_DL };
const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Features := {
vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Features };
const AVP_Code c_AVP_Code_DNAS_NONE_Framed_MTU := {
vendor_id_NONE := avp_code_DNAS_NONE_Framed_MTU };
-const AVP_Code c_AVP_Code_RX_3GPP_Extended_Min_Requested_BW_DL := {
- vendor_id_3GPP := avp_code_RX_3GPP_Extended_Min_Requested_BW_DL };
+const AVP_Code c_AVP_Code_DCA_3GPP_Unit_Quota_Threshold := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Unit_Quota_Threshold };
const AVP_Code c_AVP_Code_DNAS_NONE_Accounting_Auth_Method := {
vendor_id_NONE := avp_code_DNAS_NONE_Accounting_Auth_Method };
+const AVP_Code c_AVP_Code_MIPv4_NONE_MIP_Authenticator_Offset := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_MIP_Authenticator_Offset };
+const AVP_Code c_AVP_Code_DCA_3GPP_MBMS_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MBMS_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Bearer_Capability := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Bearer_Capability };
const AVP_Code c_AVP_Code_RX_3GPP_Service_URN := {
vendor_id_3GPP := avp_code_RX_3GPP_Service_URN };
const AVP_Code c_AVP_Code_S6_3GPP_Supported_Services := {
vendor_id_3GPP := avp_code_S6_3GPP_Supported_Services };
-const AVP_Code c_AVP_Code_DNAS_NONE_Accounting_Output_Packets := {
- vendor_id_NONE := avp_code_DNAS_NONE_Accounting_Output_Packets };
-const AVP_Code c_AVP_Code_AAA_3GPP_Relay_Node_Indicator := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Relay_Node_Indicator };
+const AVP_Code c_AVP_Code_DCA_3GPP_SDP_Media_Description := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SDP_Media_Description };
+const AVP_Code c_AVP_Code_MIPv4_NONE_Accounting_Output_Packets := {
+ vendor_id_NONE := avp_code_MIPv4_NONE_Accounting_Output_Packets };
+const AVP_Code c_AVP_Code_DCA_3GPP_Radio_Parameter_Set_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Radio_Parameter_Set_Info };
const AVP_Code c_AVP_Code_PCC_3GPP_Rule_DeActivation_Time := {
vendor_id_3GPP := avp_code_PCC_3GPP_Rule_DeActivation_Time };
+const AVP_Code c_AVP_Code_AAA_3GPP_Relay_Node_Indicator := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Relay_Node_Indicator };
const AVP_Code c_AVP_Code_S6_3GPP_T4_Data := {
vendor_id_3GPP := avp_code_S6_3GPP_T4_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_Fixed_User_Location_Info := {
vendor_id_3GPP := avp_code_PCC_3GPP_Fixed_User_Location_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_Coverage_Status := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Coverage_Status };
const AVP_Code c_AVP_Code_PCC_3GPP_Online := {
vendor_id_3GPP := avp_code_PCC_3GPP_Online };
const AVP_Code c_AVP_Code_PCC_3GPP_ADC_Rule_Base_Name := {
vendor_id_3GPP := avp_code_PCC_3GPP_ADC_Rule_Base_Name };
const AVP_Code c_AVP_Code_AAA_3GPP_SCEF_Realm := {
vendor_id_3GPP := avp_code_AAA_3GPP_SCEF_Realm };
+const AVP_Code c_AVP_Code_DCA_3GPP_MBMS_Charged_Party := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_MBMS_Charged_Party };
const AVP_Code c_AVP_Code_S6_3GPP_Requested_Validity_Time := {
vendor_id_3GPP := avp_code_S6_3GPP_Requested_Validity_Time };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Request_Number := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Request_Number };
+const AVP_Code c_AVP_Code_DCA_3GPP_AoC_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_AoC_Information };
const AVP_Code c_AVP_Code_CxDx_3GPP_Supported_Features := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Supported_Features };
const AVP_Code c_AVP_Code_AAA_3GPP_Local_Time_Zone := {
@@ -9288,6 +14708,10 @@ const AVP_Code c_AVP_Code_AAA_3GPP_GERAN_Vector := {
vendor_id_3GPP := avp_code_AAA_3GPP_GERAN_Vector };
const AVP_Code c_AVP_Code_CxDx_3GPP_Call_ID_SIP_Header := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Call_ID_SIP_Header };
+const AVP_Code c_AVP_Code_DCA_3GPP_Online_Charging_Flag := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Online_Charging_Flag };
+const AVP_Code c_AVP_Code_DCA_3GPP_Number_of_Messages_Sent := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Number_of_Messages_Sent };
const AVP_Code c_AVP_Code_AAA_3GPP_EPS_Subscribed_QoS_Profile := {
vendor_id_3GPP := avp_code_AAA_3GPP_EPS_Subscribed_QoS_Profile };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Session_Stop_Indicator := {
@@ -9296,28 +14720,52 @@ const AVP_Code c_AVP_Code_AAA_3GPP_GPRS_Subscription_Data := {
vendor_id_3GPP := avp_code_AAA_3GPP_GPRS_Subscription_Data };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_GPRS_Negotiated_QoS_Profile };
+const AVP_Code c_AVP_Code_DCA_3GPP_Access_Transfer_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Access_Transfer_Type };
const AVP_Code c_AVP_Code_DNAS_NONE_Called_Station_Id := {
vendor_id_NONE := avp_code_DNAS_NONE_Called_Station_Id };
+const AVP_Code c_AVP_Code_DCA_3GPP_Inter_UE_Transfer := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Inter_UE_Transfer };
const AVP_Code c_AVP_Code_DCC_NONE_Cost_Unit := {
vendor_id_NONE := avp_code_DCC_NONE_Cost_Unit };
const AVP_Code c_AVP_Code_BASE_NONE_Accounting_Realtime_Required := {
vendor_id_NONE := avp_code_BASE_NONE_Accounting_Realtime_Required };
const AVP_Code c_AVP_Code_BASE_NONE_Termination_Cause := {
vendor_id_NONE := avp_code_BASE_NONE_Termination_Cause };
+const AVP_Code c_AVP_Code_DCA_3GPP_Received_Talk_Burst_Volume := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Received_Talk_Burst_Volume };
+const AVP_Code c_AVP_Code_DCA_3GPP_Rate_Control_Max_Rate := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Rate_Control_Max_Rate };
+const AVP_Code c_AVP_Code_DCA_3GPP_Class_Identifier := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Class_Identifier };
const AVP_Code c_AVP_Code_GI_3GPP_3GPP_Allocate_IP_Type := {
vendor_id_3GPP := avp_code_GI_3GPP_3GPP_Allocate_IP_Type };
+const AVP_Code c_AVP_Code_AAA_3GPP_SM_Back_Off_Timer := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_SM_Back_Off_Timer };
const AVP_Code c_AVP_Code_RX_3GPP_Specific_Action := {
vendor_id_3GPP := avp_code_RX_3GPP_Specific_Action };
+const AVP_Code c_AVP_Code_S6_3GPP_Maximum_Detection_Time := {
+ vendor_id_3GPP := avp_code_S6_3GPP_Maximum_Detection_Time };
const AVP_Code c_AVP_Code_DNAS_NONE_Login_TCP_Port := {
vendor_id_NONE := avp_code_DNAS_NONE_Login_TCP_Port };
const AVP_Code c_AVP_Code_DNAS_NONE_Password_Retry := {
vendor_id_NONE := avp_code_DNAS_NONE_Password_Retry };
-const AVP_Code c_AVP_Code_S6_3GPP_Maximum_Detection_Time := {
- vendor_id_3GPP := avp_code_S6_3GPP_Maximum_Detection_Time };
-const AVP_Code c_AVP_Code_AAA_3GPP_Ext_PDP_Address := {
- vendor_id_3GPP := avp_code_AAA_3GPP_Ext_PDP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_Stamps := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_Stamps };
+const AVP_Code c_AVP_Code_DCA_3GPP_Base_Time_Interval := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Base_Time_Interval };
+const AVP_Code c_AVP_Code_DCA_3GPP_UWAN_User_Location_Info := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_UWAN_User_Location_Info };
+const AVP_Code c_AVP_Code_DCA_3GPP_ProSe_Role_Of_UE := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ProSe_Role_Of_UE };
const AVP_Code c_AVP_Code_PCC_3GPP_RAT_Type := {
vendor_id_3GPP := avp_code_PCC_3GPP_RAT_Type };
+const AVP_Code c_AVP_Code_AAA_3GPP_Ext_PDP_Address := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_Ext_PDP_Address };
+const AVP_Code c_AVP_Code_DCA_3GPP_PoC_Session_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_PoC_Session_Type };
+const AVP_Code c_AVP_Code_DCA_3GPP_ISUP_Cause := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_ISUP_Cause };
const AVP_Code c_AVP_Code_RX_3GPP_AF_Signalling_Protocol := {
vendor_id_3GPP := avp_code_RX_3GPP_AF_Signalling_Protocol };
const AVP_Code c_AVP_Code_AAA_3GPP_Adjacent_PLMNs := {
@@ -9326,6 +14774,12 @@ const AVP_Code c_AVP_Code_S6_3GPP_Service_Result_Code := {
vendor_id_3GPP := avp_code_S6_3GPP_Service_Result_Code };
const AVP_Code c_AVP_Code_AAA_3GPP_SGSN_Location_Information := {
vendor_id_3GPP := avp_code_AAA_3GPP_SGSN_Location_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Authorised_QoS := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Authorised_QoS };
+const AVP_Code c_AVP_Code_DCA_3GPP_Time_First_Transmission := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Time_First_Transmission };
+const AVP_Code c_AVP_Code_DCA_3GPP_Stop_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Stop_Time };
const AVP_Code c_AVP_Code_CxDx_3GPP_Reason_Code := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Reason_Code };
const AVP_Code c_AVP_Code_PCC_3GPP_Pre_emption_Vulnerability := {
@@ -9336,20 +14790,28 @@ const AVP_Code c_AVP_Code_PCC_3GPP_Default_Access := {
vendor_id_3GPP := avp_code_PCC_3GPP_Default_Access };
const AVP_Code c_AVP_Code_CxDx_3GPP_Supported_Applications := {
vendor_id_3GPP := avp_code_CxDx_3GPP_Supported_Applications };
-const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Challenge_Response := {
- vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Challenge_Response };
const AVP_Code c_AVP_Code_BASE_NONE_Class := {
vendor_id_NONE := avp_code_BASE_NONE_Class };
+const AVP_Code c_AVP_Code_DNAS_NONE_ARAP_Challenge_Response := {
+ vendor_id_NONE := avp_code_DNAS_NONE_ARAP_Challenge_Response };
+const AVP_Code c_AVP_Code_DCA_3GPP_SM_Message_Type := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_SM_Message_Type };
const AVP_Code c_AVP_Code_DCC_NONE_CC_Sub_Session_Id := {
vendor_id_NONE := avp_code_DCC_NONE_CC_Sub_Session_Id };
const AVP_Code c_AVP_Code_AAA_3GPP_IDR_Flags := {
vendor_id_3GPP := avp_code_AAA_3GPP_IDR_Flags };
-const AVP_Code c_AVP_Code_AAA_3GPP_V2X_Subscription_Data := {
- vendor_id_3GPP := avp_code_AAA_3GPP_V2X_Subscription_Data };
const AVP_Code c_AVP_Code_PCC_3GPP_PS_to_CS_Session_Continuity := {
vendor_id_3GPP := avp_code_PCC_3GPP_PS_to_CS_Session_Continuity };
+const AVP_Code c_AVP_Code_AAA_3GPP_V2X_Subscription_Data := {
+ vendor_id_3GPP := avp_code_AAA_3GPP_V2X_Subscription_Data };
+const AVP_Code c_AVP_Code_DCA_3GPP_Refund_Information := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Refund_Information };
+const AVP_Code c_AVP_Code_DCA_3GPP_Rate_Element := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Rate_Element };
const AVP_Code c_AVP_Code_AAA_3GPP_PDP_Type := {
vendor_id_3GPP := avp_code_AAA_3GPP_PDP_Type };
const AVP_Code c_AVP_Code_AAA_3GPP_AMBR := {
vendor_id_3GPP := avp_code_AAA_3GPP_AMBR };
+const AVP_Code c_AVP_Code_DCA_3GPP_Submission_Time := {
+ vendor_id_3GPP := avp_code_DCA_3GPP_Submission_Time };
} with { encode "RAW" } // End module
diff --git a/library/DIAMETER_rfc4004_Templates.ttcn b/library/DIAMETER_rfc4004_Templates.ttcn
new file mode 100644
index 00000000..2df5573e
--- /dev/null
+++ b/library/DIAMETER_rfc4004_Templates.ttcn
@@ -0,0 +1,34 @@
+module DIAMETER_rfc4004_Templates {
+
+/* (C) 2023 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
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/* 4.2.1. MIP6-Agent-Info AVP */
+template (value) MIPv4_NONE_MIP_Home_Agent_Address ts_AVP_Home_Agent_Address(template (value) AddressType addr_type,
+ template (value) octetstring addr_data) := {
+ address_type := addr_type,
+ address_data := addr_data
+}
+
+template (value) GenericAVP ts_AVP_MIPHomeAgentAddress(template (value) MIPv4_NONE_MIP_Home_Agent_Address addr) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv4_NONE_MIP_Home_Agent_Address),
+ avp_data := {
+ avp_MIPv4_NONE_MIP_Home_Agent_Address := addr
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/library/DIAMETER_rfc5447_Templates.ttcn b/library/DIAMETER_rfc5447_Templates.ttcn
new file mode 100644
index 00000000..f62c96d7
--- /dev/null
+++ b/library/DIAMETER_rfc5447_Templates.ttcn
@@ -0,0 +1,54 @@
+module DIAMETER_rfc5447_Templates {
+
+/* (C) 2023 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
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+import from DIAMETER_rfc4004_Templates all;
+
+/* 4.2.1. MIP6-Agent-Info AVP */
+template (value) GenericAVP ts_AVP_MIP6AgentInfo(template (value) MIPv4_NONE_MIP_Home_Agent_Address addr) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv6_NONE_MIP6_Agent_Info),
+ avp_data := {
+ avp_MIPv6_NONE_MIP6_Agent_Info := {
+ ts_AVP_MIPHomeAgentAddress(addr)
+ }
+ }
+ }
+}
+
+/* 4.2.5. MIP6-Feature-Vector AVP */
+const uint64_t DIA_RFC5447_MIP6_Feature_Vector_MIP6_INTEGRATED := hex2int('0000000000000001'H);
+const uint64_t DIA_RFC5447_MIP6_Feature_Vector_LOCAL_HOME_AGENT_ASSIGNMENT := hex2int('0000000000000002'H);
+
+
+/* 4.2.5. MIP6-Feature-Vector AVP */
+template (value) GenericAVP ts_AVP_MIP6FeatureVector(template (value) MIPv6_NONE_MIP6_Feature_Vector inp) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv6_NONE_MIP6_Feature_Vector),
+ avp_data := {
+ avp_MIPv6_NONE_MIP6_Feature_Vector := inp
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_MIP6FeatureVector(template (present) MIPv6_NONE_MIP6_Feature_Vector inp := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_MIPv6_NONE_MIP6_Feature_Vector),
+ avp_data := {
+ avp_MIPv6_NONE_MIP6_Feature_Vector := inp
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/library/DIAMETER_ts29_212_Templates.ttcn b/library/DIAMETER_ts29_212_Templates.ttcn
new file mode 100644
index 00000000..209ac100
--- /dev/null
+++ b/library/DIAMETER_ts29_212_Templates.ttcn
@@ -0,0 +1,69 @@
+module DIAMETER_ts29_212_Templates {
+
+/* (C) 2023 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
+ *
+ * Templates for AVPs and messages for TS 29.212
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/*******************************
+ * S6a 3GPP TS 29.212 section 7
+ *******************************/
+
+/* 3GPP TS 29.212 Section 5.1 */
+const uint32_t c_DIAMETER_3GPP_Gx_AID := 16777238;
+
+/* 3GPP TS 29.212 5.6.2 Credit-Control-Request (CC-Request, CCR) Command */
+template (present) PDU_DIAMETER
+tr_DIA_Gx_CCR(template (present) DCC_NONE_CC_Request_Type req_type := INITIAL_REQUEST)
+:= tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost,
+ tr_AVP_OriginRealm,
+ tr_AVP_DestinationRealm,
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?)
+ ));
+
+/* 3GPP TS 29.212 5.6.3 Credit-Control-Answer (CC-Answer, CCA) Command */
+template (value) PDU_DIAMETER
+ts_DIA_Gx_CCA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) octetstring sess_id,
+ template (value) DCC_NONE_CC_Request_Type req_type,
+ template (value) AVP_Unsigned32 req_num)
+:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
+ app_id:=int2oct(c_DIAMETER_3GPP_Gx_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost("pcrf.localdomain"),
+ ts_AVP_OriginRealm("localdomain"),
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_Gx_AID, 4)),
+ ts_AVP_CcReqType(req_type),
+ ts_AVP_CcReqNum(req_num),
+ ts_AVP_PCC_3GPP_QoS_Information({
+ ts_AVP_PCC_3GPP_APN_Aggregate_Max_Bitrate_UL(33554432),
+ ts_AVP_PCC_3GPP_APN_Aggregate_Max_Bitrate_DL(52428800)
+ }),
+ ts_AVP_PCC_3GPP_Default_EPS_Bearer_QoS({
+ ts_AVP_PCC_3GPP_QoS_Class_Identifier(9),
+ ts_AVP_PCC_3GPP_AllocRetenPrio(2)
+ })
+ // supported features
+ // origin
+ });
+
+} /* module */
diff --git a/library/DIAMETER_ts29_229_Templates.ttcn b/library/DIAMETER_ts29_229_Templates.ttcn
new file mode 100644
index 00000000..bab9bd9c
--- /dev/null
+++ b/library/DIAMETER_ts29_229_Templates.ttcn
@@ -0,0 +1,78 @@
+module DIAMETER_ts29_229_Templates {
+
+/* (C) 2023 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
+ *
+ * Templates for AVPs and messages for TS 29.273
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_rfc5447_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/* 3GPP TS 29.229 section 6.2. Errors in Result-Code AVP values */
+type enumerated DIAMETER_ts29_229_ExperimentalResultcode {
+ /* Success */
+ DIAMETER_FIRST_REGISTRATION (2001),
+ DIAMETER_SUBSEQUENT_REGISTRATION (2002),
+ DIAMETER_UNREGISTERED_SERVICE (2003),
+ DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED (2004),
+ /* Permanent Failures */
+ DIAMETER_ERROR_USER_UNKNOWN (5001),
+ DIAMETER_ERROR_IDENTITIES_DONT_MATCH (5002),
+ DIAMETER_ERROR_IDENTITY_NOT_REGISTERED (5003),
+ DIAMETER_ERROR_ROAMING_NOT_ALLOWED (5004),
+ DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED (5005),
+ DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED (5006),
+ DIAMETER_ERROR_IN_ASSIGNMENT_TYPE (5007),
+ DIAMETER_ERROR_TOO_MUCH_DATA (5008),
+ DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA (5009),
+ DIAMETER_ERROR_FEATURE_UNSUPPORTED (5011),
+ DIAMETER_ERROR_SERVING_NODE_FEATURE_UNSUPPORTED (5012)
+}
+
+/* TS 29.229 6.3.16 Deregistration-Reason */
+template (value) GenericAVP ts_AVP_CxDx_3GPP_Deregistration_Reason(template (value) CxDx_3GPP_Reason_Code reason,
+ template (value) octetstring info) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Non_3GPP_User_Data),
+ avp_data := {
+ avp_CxDx_3GPP_Deregistration_Reason := {
+ ts_AVP_CxDx_3GPP_Reason_Code(reason),
+ ts_AVP_CxDx_3GPP_Reason_Info(info)
+ }
+ }
+ }
+}
+
+/* TS 29.229 6.3.17 Reason-Code AVP */
+template (value) GenericAVP ts_AVP_CxDx_3GPP_Reason_Code(template (value) CxDx_3GPP_Reason_Code reason) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Reason_Code),
+ avp_data := {
+ avp_CxDx_3GPP_Reason_Code := reason
+ }
+ }
+}
+
+
+/* 6.3.18 Reason-Info AVP */
+template (value) GenericAVP ts_AVP_CxDx_3GPP_Reason_Info(template (value) octetstring info) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_Reason_Info),
+ avp_data := {
+ avp_CxDx_3GPP_Reason_Info := info
+ }
+ }
+}
+
+}
diff --git a/library/DIAMETER_ts29_272_Templates.ttcn b/library/DIAMETER_ts29_272_Templates.ttcn
new file mode 100644
index 00000000..0aa5c642
--- /dev/null
+++ b/library/DIAMETER_ts29_272_Templates.ttcn
@@ -0,0 +1,710 @@
+module DIAMETER_ts29_272_Templates {
+
+/* (C) 2023 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
+ *
+ * Templates for AVPs and messages for TS 29.272
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/*******************************
+ * S6a 3GPP TS 29.272 section 7
+ *******************************/
+
+/* 3GPP TS 29.272 Section 7.1.8 */
+const uint32_t c_DIAMETER_3GPP_S6_AID := 16777251; /* S6a/S6d */
+const uint32_t c_DIAMETER_3GPP_S13_AID := 16777252;
+
+/* 3GPP TS 29.272 section 7.4. Errors in Experimental-Result-Code */
+type enumerated DIAMETER_ExperimentalResultcode {
+ /* transient */
+ DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE (4181),
+ DIAMETER_ERROR_CAMEL_SUBSCRIPTION_PRESENT (4182),
+ /* permanent */
+ DIAMETER_ERROR_USER_UNKNOWN (5001),
+ DIAMETER_AUTHORIZATION_REJECTED (5003),
+ DIAMETER_ERROR_ROAMING_NOT_ALLOWED (5004),
+ DIAMETER_MISSING_AVP (5005),
+ DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION (5420),
+ DIAMETER_ERROR_RAT_NOT_ALLOWED (5421),
+ DIAMETER_ERROR_EQUIPMENT_UNKNOWN (5422),
+ DIAMETER_ERROR_UNKOWN_SERVING_NODE (5423)
+}
+
+/* TS 29.272 7.3.53 RAND */
+template (value) GenericAVP ts_AVP_RAND(template (value) octetstring rand) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_RAND),
+ avp_data := {
+ avp_AAA_3GPP_RAND := rand
+ }
+ }
+}
+
+/* TS 29.272 7.3.54 XRES */
+template (value) GenericAVP ts_AVP_XRES(template (value) octetstring xres) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_XRES),
+ avp_data := {
+ avp_AAA_3GPP_XRES := xres
+ }
+ }
+}
+
+/* TS 29.272 7.3.55 XRES */
+template (value) GenericAVP ts_AVP_AUTN(template (value) octetstring autn) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AUTN),
+ avp_data := {
+ avp_AAA_3GPP_AUTN := autn
+ }
+ }
+}
+
+/* TS 29.272 7.3.56 KASME */
+template (value) GenericAVP ts_AVP_KASME(template (value) octetstring kasme) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
+ avp_data := {
+ avp_AAA_3GPP_KASME := kasme
+ }
+ }
+}
+
+/* TS 29.272 7.3.23 Item-Number */
+template (value) GenericAVP ts_AVP_ItemNumber(uint32_t num) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_KASME),
+ avp_data := {
+ avp_AAA_3GPP_Item_Number := int2oct(num, 4)
+ }
+ }
+}
+
+/* TS 29.272 7.3.18 E-UTRAN Vector */
+template (value) GenericAVP ts_AVP_EutranVec(uint32_t item_num, octetstring rand, octetstring xres,
+ octetstring autn, octetstring kasme) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_E_UTRAN_Vector),
+ avp_data := {
+ avp_AAA_3GPP_E_UTRAN_Vector := {
+ ts_AVP_ItemNumber(item_num),
+ ts_AVP_RAND(rand),
+ ts_AVP_XRES(xres),
+ ts_AVP_AUTN(autn),
+ ts_AVP_KASME(kasme)
+ }
+ }
+ }
+}
+
+/* TS 29.272 7.3.2 Subscription-Data */
+template (value) GenericAVP ts_AVP_3GPP_SubscriptionData(template (value) AVP_list content) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscription_Data),
+ avp_data := {
+ avp_AAA_3GPP_Subscription_Data := content
+ }
+ }
+}
+template (present) GenericAVP
+tr_AVP_3GPP_SubscriptionData(template (present) AVP_list content := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscription_Data),
+ avp_data := {
+ avp_AAA_3GPP_Subscription_Data := content
+ }
+ }
+}
+
+
+/* TS 29.272 7.3.17 Authentication-Info */
+template (value) GenericAVP ts_AVP_3GPP_AuthInfo(template (value) AVP_list content) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Authentication_Info),
+ avp_data := {
+ avp_AAA_3GPP_Authentication_Info := content
+ }
+ }
+}
+template (present) GenericAVP
+tr_AVP_3GPP_AuthInfo(template (present) AVP_list content := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Authentication_Info),
+ avp_data := {
+ avp_AAA_3GPP_Authentication_Info := content
+ }
+ }
+}
+
+/* TS 29.272 7.3.9 Visited-PLMN-Id */
+template (value) GenericAVP ts_AVP_3GPP_VisitedPlmnId(template (value) octetstring id) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
+ avp_data := {
+ avp_AAA_3GPP_Visited_PLMN_Id := id
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_3GPP_VisitedPlmnId(template (present) octetstring id := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Visited_PLMN_Id),
+ avp_data := {
+ avp_AAA_3GPP_Visited_PLMN_Id := id
+ }
+ }
+}
+
+/* TS 29.272 7.3.13 RAT-Type */
+template (value) GenericAVP ts_AVP_PCC_3GPP_RatType(template (value) PCC_3GPP_RAT_Type rat_type) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
+ avp_data := {
+ avp_PCC_3GPP_RAT_Type := rat_type
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_PCC_3GPP_RatType(template (present) PCC_3GPP_RAT_Type rat_type := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_PCC_3GPP_RAT_Type),
+ avp_data := {
+ avp_PCC_3GPP_RAT_Type := rat_type
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_GI_3GPP_RatType(template (present) GI_3GPP_3GPP_RAT_Type rat_type := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_GI_3GPP_3GPP_RAT_Type),
+ avp_data := {
+ avp_GI_3GPP_3GPP_RAT_Type := rat_type
+ }
+ }
+}
+
+/* TS 29.272 7.3.7 ULR-Flags */
+template (value) GenericAVP ts_AVP_3GPP_UlrFlags(template (value) UINT32 flags) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
+ avp_data := {
+ avp_AAA_3GPP_ULR_Flags := flags
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_3GPP_UlrFlags(template (present) UINT32 flags := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULR_Flags),
+ avp_data := {
+ avp_AAA_3GPP_ULR_Flags := flags
+ }
+ }
+}
+
+/* TS 29.272 7.3.8 ULA-Flags */
+template (value) GenericAVP ts_AVP_3GPP_UlaFlags(template (value) UINT32 flags) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
+ avp_data := {
+ avp_AAA_3GPP_ULA_Flags := flags
+ }
+ }
+}
+template (present) GenericAVP tr_AVP_3GPP_UlaFlags(template (present) UINT32 flags := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_ULA_Flags),
+ avp_data := {
+ avp_AAA_3GPP_ULA_Flags := flags
+ }
+ }
+}
+
+
+/* TS 29.272 7.3.27 Context-Identifier */
+template (present) GenericAVP tr_AVP_3GPP_ContextId(template (present) uint32_t ctx := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Context_Identifier),
+ avp_data := {
+ avp_AAA_3GPP_Context_Identifier := int2oct_tmpl(ctx, 4)
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_ContextId(template (value) uint32_t ctx) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Context_Identifier),
+ avp_data := {
+ avp_AAA_3GPP_Context_Identifier := int2oct(valueof(ctx), 4)
+ }
+ }
+}
+
+/* Ts 29.272 7.3.29 Subscriber-Status */
+template (present) GenericAVP tr_AVP_3GPP_SubscriberStatus(template (present) AAA_3GPP_Subscriber_Status sts) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscriber_Status),
+ avp_data := {
+ avp_AAA_3GPP_Subscriber_Status := sts
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SubscriberStatus(template (value) AAA_3GPP_Subscriber_Status sts) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Subscriber_Status),
+ avp_data := {
+ avp_AAA_3GPP_Subscriber_Status := sts
+ }
+ }
+}
+
+/* Ts 29.272 7.3.30 Operator-Determined-Barring */
+template (present) GenericAVP tr_AVP_3GPP_OperatorDeterminedBarring(template (present) uint32_t val := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Operator_Determined_Barring),
+ avp_data := {
+ avp_AAA_3GPP_Operator_Determined_Barring := int2oct_tmpl(val, 4)
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_OperatorDeterminedBarring(uint32_t val) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Operator_Determined_Barring),
+ avp_data := {
+ avp_AAA_3GPP_Operator_Determined_Barring := int2oct(val, 4)
+ }
+ }
+}
+
+/* TS 29.272 7.3.33 All-APN-Configurations-Included-Indicator */
+template (present) GenericAVP tr_AVP_3GPP_AllApnConfigsIncl(template (present) AAA_3GPP_All_APN_Configurations_Included_Indicator ind := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator),
+ avp_data := {
+ avp_AAA_3GPP_All_APN_Configurations_Included_Indicator := ind
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_AllApnConfigsIncl(template (value) AAA_3GPP_All_APN_Configurations_Included_Indicator ind := All_APN_CONFIGURATIONS_INCLUDED) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_All_APN_Configurations_Included_Indicator),
+ avp_data := {
+ avp_AAA_3GPP_All_APN_Configurations_Included_Indicator := ind
+ }
+ }
+}
+
+/* TS 29.272 7.3.24 Cancellation-Type */
+template (value) GenericAVP ts_AVP_3GPP_CancellationType(template (value) AAA_3GPP_Cancellation_Type t) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Cancellation_Type),
+ avp_data := {
+ avp_AAA_3GPP_Cancellation_Type := t
+ }
+ }
+}
+
+/* TS 29.272 7.3.34 APN-Configuration-Profile */
+template (present) GenericAVP tr_AVP_3GPP_ApnConfigProfile(template (present) AVP_list content := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
+ avp_data := {
+ avp_AAA_3GPP_APN_Configuration_Profile := content
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_ApnConfigProfile(template (value) AVP_list content) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration_Profile),
+ avp_data := {
+ avp_AAA_3GPP_APN_Configuration_Profile := content
+ }
+ }
+}
+
+/* TS 29.272 7.3.35 APN-Configuration */
+template (present) GenericAVP tr_AVP_3GPP_ApnConfig(template (present) uint32_t ctx := ?,
+ template (present) AAA_3GPP_PDN_Type pdn_type := ?,
+ template (present) charstring apn := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration),
+ avp_data := {
+ avp_AAA_3GPP_APN_Configuration := superset(
+ tr_AVP_3GPP_ContextId(ctx),
+ tr_AVP_3GPP_PdnType(pdn_type),
+ tr_AVP_ServiceSelection(apn),
+ tr_AVP_3GPP_EpsSubscrQosProfile(?, ?)
+ )
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_ApnConfig(template (value) uint32_t ctx,
+ template (value) AAA_3GPP_PDN_Type pdn_type,
+ template (value) charstring apn) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_APN_Configuration),
+ avp_data := {
+ avp_AAA_3GPP_APN_Configuration := {
+ ts_AVP_3GPP_ContextId(ctx),
+ ts_AVP_3GPP_PdnType(pdn_type),
+ ts_AVP_ServiceSelection(apn),
+ ts_AVP_3GPP_EpsSubscrQosProfile(1, 1)
+ }
+ }
+ }
+}
+
+/* Service-Selection, TS 29.272 7.3.36, TS 29.273 5.2.3.5, (RFC 5778) */
+template (present) GenericAVP tr_AVP_ServiceSelection(template (present) charstring apn := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr(c_AVP_Code_MIPv6_NONE_Service_Selection),
+ avp_data := {
+ avp_MIPv6_NONE_Service_Selection := char2oct_tmpl(apn)
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_ServiceSelection(template (value) charstring apn) := {
+ avp := {
+ avp_header := ts_DIA_Hdr(c_AVP_Code_MIPv6_NONE_Service_Selection),
+ avp_data := {
+ avp_MIPv6_NONE_Service_Selection := char2oct(valueof(apn))
+ }
+ }
+}
+
+/* TS 29.272 7.3.41 AMBR */
+template (present) GenericAVP tr_AVP_3GPP_AMBR(template (present) uint32_t ul := ?, template (present) uint32_t dl := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AMBR),
+ avp_data := {
+ avp_AAA_3GPP_AMBR := {
+ tr_AVP_3GPP_MaxReqBwUL(ul),
+ tr_AVP_3GPP_MaxReqBwDL(dl)
+ }
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_AMBR(template (value) uint32_t ul,
+ template (value) uint32_t dl) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_AMBR),
+ avp_data := {
+ avp_AAA_3GPP_AMBR := {
+ ts_AVP_3GPP_MaxReqBwUL(ul),
+ ts_AVP_3GPP_MaxReqBwDL(dl)
+ }
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_3GPP_MaxReqBwUL(template (present) uint32_t bw := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL),
+ avp_data := {
+ avp_RX_3GPP_Max_Requested_Bandwidth_UL := int2oct_tmpl(bw, 4)
+ }
+ }
+}
+
+template (value) GenericAVP ts_AVP_3GPP_MaxReqBwUL(template (value) uint32_t bw) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_UL),
+ avp_data := {
+ avp_RX_3GPP_Max_Requested_Bandwidth_UL := int2oct(valueof(bw), 4)
+ }
+ }
+}
+
+template (present) GenericAVP tr_AVP_3GPP_MaxReqBwDL(template (present) uint32_t bw := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL),
+ avp_data := {
+ avp_RX_3GPP_Max_Requested_Bandwidth_DL := int2oct_tmpl(bw, 4)
+ }
+ }
+}
+
+template (value) GenericAVP ts_AVP_3GPP_MaxReqBwDL(template (value) uint32_t bw) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_RX_3GPP_Max_Requested_Bandwidth_DL),
+ avp_data := {
+ avp_RX_3GPP_Max_Requested_Bandwidth_DL := int2oct(valueof(bw), 4)
+ }
+ }
+}
+
+/* TS 29.272 7.3.62 PDN-Type */
+template (present) GenericAVP tr_AVP_3GPP_PdnType(template (present) AAA_3GPP_PDN_Type pdn_type := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_PDN_Type),
+ avp_data := {
+ avp_AAA_3GPP_PDN_Type := pdn_type
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_PdnType(template (value) AAA_3GPP_PDN_Type pdn_type) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_PDN_Type),
+ avp_data := {
+ avp_AAA_3GPP_PDN_Type := pdn_type
+ }
+ }
+}
+
+
+/* TS 29.272 5.2.3.1 + 7.2.6 Authentication Information Answer */
+template (value) PDU_DIAMETER
+ts_DIA_AIA(template (value) AVP_list auth_info_contents,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Authentication_Information,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_3GPP_AuthInfo(auth_info_contents)
+ });
+template (present) PDU_DIAMETER
+tr_DIA_AIA(template (present) AVP_list auth_info_contents := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Authentication_Information,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ tr_AVP_3GPP_AuthInfo(auth_info_contents)
+ ));
+template (present) PDU_DIAMETER
+tr_DIA_AIA_ERR(template (present) GenericAVP err_avp := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Authentication_Information,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ err_avp
+ ));
+
+
+/* TS 29.272 7.2.3 Update Location Request */
+template (value) PDU_DIAMETER
+ts_DIA_ULR(/* template (value) */ hexstring imsi,
+ template (value) octetstring mcc_mnc := '111F11'O,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Update_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_UserNameImsi(imsi),
+ ts_AVP_3GPP_UlrFlags('00000000'O),
+ ts_AVP_3GPP_VisitedPlmnId(mcc_mnc),
+ ts_AVP_PCC_3GPP_RatType(EUTRAN),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationRealm(dest_realm)
+ });
+template (present) PDU_DIAMETER
+tr_DIA_ULR(/* template (present) */ hexstring imsi,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '11000000'B,
+ cmd_code := Update_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_AuthSessionState,
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_UserNameImsi(imsi),
+ tr_AVP_PCC_3GPP_RatType,
+ tr_AVP_3GPP_UlrFlags,
+ tr_AVP_3GPP_VisitedPlmnId
+ ));
+
+template (value) PDU_DIAMETER
+ts_DIA_ULA(template (value) AVP_list sub_data,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags:='01000000'B,
+ cmd_code := Update_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS), /* optional */
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_3GPP_UlaFlags('00000002'O),
+ ts_AVP_3GPP_SubscriptionData(sub_data)
+ });
+template (present) PDU_DIAMETER
+tr_DIA_ULA(template (present) AVP_list sub_data := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Update_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ tr_AVP_AuthSessionState,
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_3GPP_UlaFlags,
+ tr_AVP_3GPP_SubscriptionData(sub_data)
+ ));
+
+/* TS 29.272 7.2.5 Authentication-Information-Request */
+template (value) PDU_DIAMETER
+ts_DIA_AIR(/* template (value) */ hexstring imsi,
+ template (value) octetstring mcc_mnc := '111F11'O,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Authentication_Information,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_UserNameImsi(imsi),
+ /* Requested EUTRAN Auth Info */
+ ts_AVP_RequestedEutranAuthInfo,
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_3GPP_VisitedPlmnId(mcc_mnc)
+ });
+template (present) PDU_DIAMETER
+tr_DIA_AIR(/* template (present) */ hexstring imsi,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Authentication_Information,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_UserNameImsi(imsi),
+ tr_AVP_3GPP_VisitedPlmnId
+ ));
+
+/* TS 29.272 7.2.7 Cancel-Location-Request */
+template (value) PDU_DIAMETER
+ts_DIA_CLR(/* template (value) */ hexstring imsi,
+ template (value) AAA_3GPP_Cancellation_Type cancel_type,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "ttcn3.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_host := "iut.localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Cancel_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationHost(dest_host),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_UserNameImsi(imsi),
+ /* [Supported-Features ] */
+ ts_AVP_3GPP_CancellationType(cancel_type)
+ });
+
+/* TS 29.272 7.2.8 Cancel-Location-Answer */
+template (present) PDU_DIAMETER
+tr_DIA_CLA(template (present) AVP_list sub_data := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Cancel_Location,
+ app_id := int2oct(c_DIAMETER_3GPP_S6_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ tr_AVP_AuthSessionState,
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ ));
+
+} /* module */
diff --git a/library/DIAMETER_ts29_273_Templates.ttcn b/library/DIAMETER_ts29_273_Templates.ttcn
new file mode 100644
index 00000000..6ed00ffb
--- /dev/null
+++ b/library/DIAMETER_ts29_273_Templates.ttcn
@@ -0,0 +1,677 @@
+module DIAMETER_ts29_273_Templates {
+
+/* (C) 2023 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
+ *
+ * Templates for AVPs and messages for TS 29.273
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from DIAMETER_rfc5447_Templates all;
+import from DIAMETER_ts29_229_Templates all;
+import from DIAMETER_ts29_272_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/* 3GPP TS 29.273 Section 8.2 */
+const uint32_t c_DIAMETER_3GPP_SWx_AID := 16777265;
+/* 3GPP TS 29.273 Section 9 */
+const uint32_t c_DIAMETER_3GPP_S6b_AID := 16777272;
+
+/* 5.2.3.3 MIP6-Feature-Vector bits */
+const uint64_t DIA_TS29_373_MIP6_Feature_Vector_PMIP6_SUPPORTED := hex2int('0000010000000000'H);
+const uint64_t DIA_TS29_373_MIP6_Feature_Vector_ASSIGN_LOCAL_IP := hex2int('0000080000000000'H);
+const uint64_t DIA_TS29_373_MIP6_Feature_Vector_MIP4_SUPPORTED := hex2int('0000100000000000'H);
+const uint64_t DIA_TS29_373_MIP6_Feature_Vector_OPTIMIZED_IDLE_MODE_MOBILITY := hex2int('0000200000000000'H);
+const uint64_t DIA_TS29_373_MIP6_Feature_Vector_GTPv2_SUPPORTED := hex2int('0000400000000000'H);
+
+/*******************************
+ * SWx 3GPP TS 29.273 section 8
+ *******************************/
+
+/* TS 29.273 8.2.3.1 Non-3GPP-User-Data */
+template (value) GenericAVP ts_AVP_3GPP_Non_3GPP_User_Data(template (value) AAA_3GPP_PDN_Type pdn_type,
+ template (value) charstring apn,
+ template (value) uint32_t ambr_max_req_ul := 1000000000,
+ template (value) uint32_t ambr_max_req_dl := 1000000000) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Non_3GPP_User_Data),
+ avp_data := {
+ avp_AAA_3GPP_Non_3GPP_User_Data := {
+ ts_AVP_3GPP_Non_3GPP_IP_Access(NON_3GPP_SUBSCRIPTION_ALLOWED),
+ ts_AVP_3GPP_Non_3GPP_IP_Access_APN(NON_3GPP_APNS_ENABLE),
+ ts_AVP_3GPP_AMBR(ambr_max_req_ul, ambr_max_req_dl),
+ ts_AVP_3GPP_ContextId(1),
+ ts_AVP_3GPP_ApnConfig(1, pdn_type, apn)
+ }
+ }
+ }
+}
+
+/* TS 29.273 8.2.3.3 Non-3GPP-IP-Access */
+template (value) GenericAVP ts_AVP_3GPP_Non_3GPP_IP_Access(template (value) AAA_3GPP_Non_3GPP_IP_Access val := NON_3GPP_SUBSCRIPTION_ALLOWED) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Non_3GPP_IP_Access),
+ avp_data := {
+ avp_AAA_3GPP_Non_3GPP_IP_Access := val
+ }
+ }
+}
+
+
+/* TS 29.273 8.2.3.4 Non-3GPP-IP-Access-APN */
+template (value) GenericAVP ts_AVP_3GPP_Non_3GPP_IP_Access_APN(template (value) AAA_3GPP_Non_3GPP_IP_Access_APN val := NON_3GPP_APNS_ENABLE) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_AAA_3GPP_Non_3GPP_IP_Access_APN),
+ avp_data := {
+ avp_AAA_3GPP_Non_3GPP_IP_Access_APN := val
+ }
+ }
+}
+
+/* TS 29.273 8.2.3.7 APN-Configuration: The APN-Configuration AVP is of type Grouped AVP and is defined in 3GPP TS 29.272 */
+/* TS 29.273 5.2.3.8 AMBR: Please refer to 3GPP TS 29.272 [29] for the encoding of this AVP. */
+
+/* SIP-Auth-Data-Item , 3GPP TS 29.273 8.2.3.9 */
+template (present) GenericAVP tr_AVP_3GPP_SIPAuthDataItem(template (present) uint32_t num := ?) := {
+ avp := {
+ avp_header := tr_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Auth_Data_Item),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Auth_Data_Item := superset(
+ //tr_AVP_3GPP_SIPItemNumber(num), /* Optional */
+ tr_AVP_3GPP_SIPAuthScheme(?)//, /* Optional */
+ //tr_AVP_3GPP_SIPAuthenticate(?), /* Optional */
+ //tr_AVP_3GPP_SIPAuthorization(?), /* Optional */
+ //tr_AVP_3GPP_SIPAuthContext(?), /* Optional */
+ //tr_AVP_3GPP_ConfidentialityKey(?), /* Optional */
+ //tr_AVP_3GPP_IntegrityKey(?) /* Optional */
+ /* TODO:
+ [ SIP-Digest-Authenticate ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ [ Line-Identifier ]
+ *[AVP]
+ */
+ )
+ }
+ }
+}
+template (value) GenericAVP ts_AVP_3GPP_SIPAuthDataItem(uint32_t num, OCT16 rand, OCT16 ik, OCT16 ck, OCT16 autn, OCT14 auts) := {
+ avp := {
+ avp_header := ts_DIA_Hdr_3GPP(c_AVP_Code_CxDx_3GPP_SIP_Auth_Data_Item),
+ avp_data := {
+ avp_CxDx_3GPP_SIP_Auth_Data_Item := {
+ ts_AVP_3GPP_SIPItemNumber(num),
+ ts_AVP_3GPP_SIPAuthScheme(char2oct("Digest-AKAv1-MD5")),
+ ts_AVP_3GPP_SIPAuthenticate(rand & autn),
+ ts_AVP_3GPP_SIPAuthorization(rand & auts),
+ ts_AVP_3GPP_SIPAuthContext(char2oct("foobar")),
+ ts_AVP_3GPP_ConfidentialityKey(ck),
+ ts_AVP_3GPP_IntegrityKey(ik)
+ /* TODO:
+ [ SIP-Digest-Authenticate ]
+ [ Framed-IP-Address ]
+ [ Framed-IPv6-Prefix ]
+ [ Framed-Interface-Id ]
+ [ Line-Identifier ]
+ *[AVP]
+ */
+ }
+ }
+ }
+}
+
+/* Multimedia-Auth-Request, 3GPP TS 29.273 8.2.2.1 Authentication Procedure */
+template (present) PDU_DIAMETER
+tr_DIA_SWx_MAR(template (present) hexstring imsi := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Multimedia_Auth,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_VendorSpecAppId(?, ?),
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_UserNameImsi(imsi),
+ tr_AVP_3GPP_SIPAuthDataItem(?),
+ tr_AVP_3GPP_SIPNumAuthDataItems(?)
+ ));
+
+/* Multimedia-Auth-Answer, 3GPP TS 29.273 8.2.2.1 Authentication Procedure */
+template (value) PDU_DIAMETER
+ts_DIA_SWx_MAA(template (value) hexstring imsi,
+ template (value) GenericAVP sip_auth_data_item,
+ template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Multimedia_Auth,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_UserNameImsi(valueof(imsi)),
+ sip_auth_data_item,
+ ts_AVP_3GPP_SIPNumAuthDataItems(1)
+ });
+
+template (value) PDU_DIAMETER
+ts_DIA_SWx_MAA_result(template (value) hexstring imsi,
+ template (value) GenericAVP result,
+ template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Multimedia_Auth,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+ result,
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_UserNameImsi(valueof(imsi))
+ });
+
+/* Push-Profile-Request,
+ * 3GPP TS 29.273 8.1.2.3 HSS Initiated Update of User Profile
+ * 3GPP TS 29.273 8.2.2.2 HSS Initiated Update of User Profile Procedure
+ */
+template (value) PDU_DIAMETER
+ts_DIA_SWx_PPR(template (value) hexstring imsi,
+ template (value) AAA_3GPP_PDN_Type pdn_type,
+ template (value) charstring apn,
+ template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_host := "aaa.localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Push_Profile,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationHost(dest_host),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_UserNameImsi(imsi),
+ ts_AVP_3GPP_Non_3GPP_User_Data(pdn_type, apn)
+ /* Optional: PPR-Flags */
+ /* TODO:
+ * *[ Supported-Features ]
+ */
+ });
+
+/* Push-Profile-Answer,
+ * 3GPP TS 29.273 8.1.2.3 HSS Initiated Update of User Profile
+ * 3GPP TS 29.273 8.2.2.2 HSS Initiated Update of User Profile Procedure
+ */
+template (present) PDU_DIAMETER
+tr_DIA_SWx_PPA(template (present) GenericAVP tmpl_result := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_host := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Push_Profile,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_VendorSpecAppId(?, ?),
+ tmpl_result,
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ /* Optional:
+ * [ Access-Network-Info ]
+ * [ Local-Time-Zone ]
+ * *[ Supported-Features ]
+ */
+ ));
+
+/* Server-Assignment-Request,
+ * 3GPP TS 29.273 8.1.2.2.2 UE/PDN Registration/DeRegistration Notification
+ * 3GPP TS 29.273 8.2.2.3 Non-3GPP IP Access Registration Procedure */
+template (present) PDU_DIAMETER
+tr_DIA_SWx_SAR(template (present) hexstring imsi := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?,
+ template (present) CxDx_3GPP_Server_Assignment_Type server_ass_type := ?,
+ template (present) charstring service_selection := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Server_Assignment,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_VendorSpecAppId(?, ?),
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_UserNameImsi(imsi),
+ tr_AVP_3GPP_ServerAssignmentType(server_ass_type),
+ tr_AVP_ServiceSelection(service_selection)
+ ));
+
+/* Server-Assignment-Answer,
+ * 3GPP TS 29.273 8.1.2.2.2 UE/PDN Registration/DeRegistration Notification
+ * 3GPP TS 29.273 8.2.2.3 Non-3GPP IP Access Registration Procedure */
+template (value) PDU_DIAMETER
+ts_DIA_SWx_SAA(template (value) hexstring imsi,
+ template (value) AAA_3GPP_PDN_Type pdn_type,
+ template (value) charstring apn,
+ template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Server_Assignment,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_UserNameImsi(valueof(imsi)),
+ ts_AVP_3GPP_Non_3GPP_User_Data(pdn_type, apn)
+ /* TODO:
+ * [ 3GPP-AAA-Server-Name ]
+ * [ OC-Supported-Features ]
+ * [ OC-OLR ] ]
+ * *[ Load ]
+ * *[ Supported-Features ]
+ */
+ });
+
+/* Registration-Termination-Request (RTR) , 8.2.2.4 Network Initiated De-Registration by HSS Procedure */
+template (value) PDU_DIAMETER
+ts_DIA_SWx_RTR(template (value) hexstring imsi,
+ template (value) CxDx_3GPP_Reason_Code reason_code := PERMANENT_TERMINATION,
+ template (value) octetstring reason_info := ''O,
+ template (value) uint32_t vendor_app_id := c_DIAMETER_3GPP_SWx_AID,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "hss.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_host := "aaa.localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Registration_Termination,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_VendorSpecAppId(vendor_id_3GPP, valueof(vendor_app_id)),
+ ts_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationHost(dest_host),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_UserNameImsi(imsi),
+ ts_AVP_CxDx_3GPP_Deregistration_Reason(reason_code, reason_info)
+ /* TODO:
+ * *[ Supported-Features ]
+ */
+ });
+
+template (present) PDU_DIAMETER
+tr_DIA_SWx_RTA(template (present) GenericAVP tmpl_result := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_host := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Registration_Termination,
+ app_id := int2oct(c_DIAMETER_3GPP_SWx_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ tr_AVP_VendorSpecAppId(?, ?),
+ tmpl_result,
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ ));
+
+/*******************************
+ * S6b 3GPP TS 29.273 section 9
+ *******************************/
+
+ /* TS 29.273 9.2.2.5.1 AA-Request (AAR) */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_AAR(template (present) charstring username_nai := ?,
+ template (present) MIPv6_NONE_MIP6_Feature_Vector mip6_feat_vec := ?,
+ template (present) charstring apn := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Authorize_Authenticate,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_AuthRequestType(AUTHORIZE_ONLY),
+ tr_AVP_UserName(char2oct_tmpl_present(username_nai)),
+ tr_AVP_MIP6FeatureVector(mip6_feat_vec),
+ tr_AVP_ServiceSelection(apn)
+ /* TODO: Lots other optional */
+ ));
+
+template (value) PDU_DIAMETER
+ts_DIA_S6b_AAR(template (value) charstring username_nai,
+ template (value) MIPv6_NONE_MIP6_Feature_Vector mip6_feat_vec,
+ template (value) charstring apn,
+ template (value) MIPv4_NONE_MIP_Home_Agent_Address pgw_addr,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "pgw.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Authorize_Authenticate,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_AuthRequestType(AUTHORIZE_ONLY),
+ ts_AVP_UserName(char2oct(valueof(username_nai))),
+ ts_AVP_MIP6AgentInfo(pgw_addr),
+ ts_AVP_MIP6FeatureVector(mip6_feat_vec),
+ ts_AVP_ServiceSelection(valueof(apn))
+ /* TODO: Lots other optional */
+ });
+
+/* TS 29.273 9.2.2.2.2 AA-Answer (AAA) */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_AAA(template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?,
+ template (present) CxDx_3GPP_Server_Assignment_Type server_ass_type := ?,
+ template (present) charstring service_selection := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Authorize_Authenticate,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ tr_AVP_AuthRequestType(AUTHORIZE_ONLY),
+ tr_AVP_ResultCode(DIAMETER_SUCCESS),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ ));
+
+template (value) PDU_DIAMETER
+ts_DIA_S6b_AAA(template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "aaa.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Authorize_Authenticate,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ ts_AVP_AuthRequestType(AUTHORIZE_ONLY),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm)
+ });
+
+ /* TS 29.273 9.2.2.3.1 Session-Termination-Request (STR) Command,
+ * Table 9.1.2.3.1/1: S6b Session Termination Request (STR), based on RFC 6733 8.4.1 */
+template (value) PDU_DIAMETER
+ts_DIA_S6b_STR(template (value) hexstring imsi,
+ template (value) BASE_NONE_Termination_Cause term_cause := DIAMETER_LOGOUT,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "pgw.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '11000000'B,
+ cmd_code := Session_Termination,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ /* Optional: DRMP */
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm),
+ ts_AVP_DestinationRealm(dest_realm),
+ ts_AVP_TerminationCause(term_cause),
+ ts_AVP_UserNameImsi(valueof(imsi))
+ /* Optional: OC-Supported-Features */
+ });
+
+/* TS 29.273 9.2.2.3.2 Session-Termination-Answer (STA) Command,
+ * Table 9.1.2.3.1/2: S6b Session Termination Answer (STA), based on RFC 6733 8.4.2 */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_STA(template (present) DIAMETER_Resultcode res_code := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Session_Termination,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP */
+ tr_AVP_ResultCode(res_code),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ /* Lots other Optional */
+ ));
+
+
+/* TS 29.273 9.2.2.4.1 Abort-Session-Request (ASR) */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_ASR(template (present) charstring username_nai := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) charstring dest_host := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Abort_Session,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_DestinationHost(dest_host),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ tr_AVP_UserName(char2oct_tmpl_present(username_nai)),
+ tr_AVP_AuthSessionState(NO_STATE_MAINTAINED)
+ ));
+
+/* TS 29.273 9.2.2.4.2 Abort-Session-Answer (ASA) */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_ASA(template (present) DIAMETER_Resultcode res_code := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '0???????'B,
+ cmd_code := Abort_Session,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP */
+ tr_AVP_ResultCode(res_code),
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm)
+ ));
+
+template (value) PDU_DIAMETER
+ts_DIA_S6b_ASA(template (value) DIAMETER_Resultcode res_code := DIAMETER_SUCCESS,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "aaa.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Abort_Session,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ ts_AVP_ResultCode(res_code),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm)
+ });
+
+/* TS 29.273 9.2.2.6.1 Re-Auth-Request (RAR)
+ * TS 29.273 Table 9.1.2.5.1/1: S6b Re-authorization request */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_RAR(template (present) charstring username_nai := ?,
+ template (present) octetstring sess_id := ?,
+ template (present) charstring orig_host := ?,
+ template (present) charstring orig_realm := ?,
+ template (present) charstring dest_realm := ?,
+ template (present) charstring dest_host := ?,
+ template (present) UINT32 hbh_id := ?,
+ template (present) UINT32 ete_id := ?) :=
+ tr_DIAMETER(flags := '1???????'B,
+ cmd_code := Re_Auth,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id,
+ ete_id := ete_id,
+ avps := superset(
+ tr_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ tr_AVP_OriginHost(orig_host),
+ tr_AVP_OriginRealm(orig_realm),
+ tr_AVP_DestinationRealm(dest_realm),
+ tr_AVP_DestinationHost(dest_host),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+ tr_AVP_ReAuthRequestType(AUTHORIZE_ONLY),
+ tr_AVP_UserName(char2oct_tmpl_present(username_nai))
+ /* Optional: RAR-Flags, */
+ ));
+
+/* TS 29.273 9.2.2.6.2 Re-Auth-Answer (RAA)
+ * TS 29.273 Table 9.1.2.5.1/2: S6b Re-authorization response */
+template (value) PDU_DIAMETER
+ts_DIA_S6b_RAA(template (value) DIAMETER_Resultcode res_code := DIAMETER_SUCCESS,
+ template (value) octetstring sess_id := c_def_sess_id,
+ template (value) charstring orig_host := "aaa.localdomain",
+ template (value) charstring orig_realm := "localdomain",
+ template (value) charstring dest_realm := "localdomain",
+ template (value) UINT32 hbh_id := '00000000'O,
+ template (value) UINT32 ete_id := '00000000'O) :=
+ ts_DIAMETER(flags := '01000000'B,
+ cmd_code := Re_Auth,
+ app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+ hbh_id := hbh_id, ete_id := ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ /* Optional: DRMP, */
+ ts_AVP_ResultCode(res_code),
+ ts_AVP_OriginHost(orig_host),
+ ts_AVP_OriginRealm(orig_realm)
+ });
+
+}
diff --git a/library/DIAMETER_ts32_299_Templates.ttcn b/library/DIAMETER_ts32_299_Templates.ttcn
new file mode 100644
index 00000000..ffbd15f5
--- /dev/null
+++ b/library/DIAMETER_ts32_299_Templates.ttcn
@@ -0,0 +1,184 @@
+module DIAMETER_ts32_299_Templates {
+
+/* (C) 2023 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
+ *
+ * Templates for AVPs and messages for TS 32.299
+ */
+
+import from General_Types all;
+import from DIAMETER_Types all;
+import from DIAMETER_Templates all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+/*******************************
+ * Gy 3GPP TS 32.299 section 7
+ *******************************/
+
+/* Gy AID : 3GPP TS 32.299 7.1.6, RFC4006 3.1: c_DIAMETER_CREDIT_CONTROL_AID */
+
+/* 3GPP TS 32.299 7.1.11 Result-Code AVP*/
+type enumerated DIAMETER_ts32_229_Resultcode {
+ /* transient */
+ DIAMETER_END_USER_SERVICE_DENIED (4010),
+ DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE (4011),
+ DIAMETER_CREDIT_LIMIT_REACHED (4012),
+ /* permanent */
+ DIAMETER_AUTHORIZATION_REJECTED (5003),
+ DIAMETER_USER_UNKNOWN (5030),
+ DIAMETER_RATING_FAILED (5031)
+}
+
+/* 3GPP TS 32.299 6.4.2 Credit-Control-Request */
+template (present) PDU_DIAMETER
+tr_DIA_Gy_CCR(template (present) DCC_NONE_CC_Request_Type req_type := INITIAL_REQUEST)
+:= tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost,
+ tr_AVP_OriginRealm,
+ tr_AVP_DestinationRealm,
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?)
+ ));
+
+/* 3GPP TS 32.299 6.4.3 Credit-Control-Answer message */
+template (value) PDU_DIAMETER
+ts_DIA_Gy_CCA(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) octetstring sess_id,
+ template (value) DIAMETER_Resultcode res_code,
+ template (value) DCC_NONE_CC_Request_Type req_type,
+ template (value) AVP_Unsigned32 req_num)
+:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
+ app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(res_code),
+ ts_AVP_OriginHost("ocs.localdomain"),
+ ts_AVP_OriginRealm("localdomain"),
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ ts_AVP_CcReqType(req_type),
+ ts_AVP_CcReqNum(req_num)//,
+ // qos
+ // default eps bearer qos
+ // supported features
+ // origin
+ });
+/* Same as ts_DIA_Gy_CCA, but with extra AVP to grant access for limited amount of seconds */
+template (value) PDU_DIAMETER
+ts_DIA_Gy_CCA_ValidityTime(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) octetstring sess_id,
+ template (value) DCC_NONE_CC_Request_Type req_type,
+ template (value) AVP_Unsigned32 req_num,
+ uint32_t validity_time)
+:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
+ app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost("ocs.localdomain"),
+ ts_AVP_OriginRealm("localdomain"),
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ ts_AVP_CcReqType(req_type),
+ ts_AVP_CcReqNum(req_num),
+ ts_AVP_Multiple_Services_Credit_Control({
+ ts_AVP_Validity_Time(validity_time),
+ ts_AVP_Granted_Service_Unit({
+ //ts_AVP_CC_Time(validity_time*2),
+ ts_AVP_CC_Total_Octets(1000)
+ })
+ })
+ //,
+ // qos
+ // default eps bearer qos
+ // supported features
+ // origin
+ });
+/* Same as ts_DIA_Gy_CCA_ValidityTime, but with extra AVP to grant access for limited amount of octets */
+template (value) PDU_DIAMETER
+ts_DIA_Gy_CCA_ValidityTimeVolumeThreshold(template (value) UINT32 hbh_id, template (value) UINT32 ete_id,
+ template (value) octetstring sess_id,
+ template (value) DCC_NONE_CC_Request_Type req_type,
+ template (value) AVP_Unsigned32 req_num,
+ uint32_t validity_time,
+ uint32_t volume_quota,
+ uint32_t volume_threhsold := 0)
+:= ts_DIAMETER(flags:='01000000'B, cmd_code:=Credit_Control,
+ app_id:=int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4), hbh_id:=hbh_id, ete_id:=ete_id,
+ avps := {
+ ts_AVP_SessionId(sess_id),
+ ts_AVP_ResultCode(DIAMETER_SUCCESS),
+ ts_AVP_OriginHost("ocs.localdomain"),
+ ts_AVP_OriginRealm("localdomain"),
+ ts_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ ts_AVP_CcReqType(req_type),
+ ts_AVP_CcReqNum(req_num),
+ ts_AVP_Multiple_Services_Credit_Control({
+ ts_AVP_Validity_Time(validity_time),
+ ts_AVP_Granted_Service_Unit({
+ ts_AVP_CC_Total_Octets(volume_quota)
+ }),
+ ts_AVP_3GPP_VolumeQuotaThreshold(volume_threhsold)
+ })
+ //,
+ // qos
+ // default eps bearer qos
+ // supported features
+ // origin
+ });
+
+function f_validate_gy_cc_report(PDU_DIAMETER rx_dia, template (present) DCA_3GPP_Reporting_Reason repreason_exp := ?,
+ template (present) integer cc_time_exp := ?,
+ template (present) integer cc_in_oct_exp := ?,
+ template (present) integer cc_out_oct_exp := ?)
+{
+ var AVP multi_services_cc, used_service_unit;
+ var AVP_Grouped multi_services_cc_data, used_service_unit_data;
+ var template (omit) AVP repreason_tpl;
+ var AVP repreason, cc_time, cc_in_oct, cc_out_oct;
+
+ multi_services_cc := f_DIAMETER_get_avp_or_fail(rx_dia, c_AVP_Code_DCC_NONE_Multiple_Services_Credit_Control);
+ multi_services_cc_data := valueof(multi_services_cc.avp_data.avp_DCC_NONE_Multiple_Services_Credit_Control);
+
+ used_service_unit := f_AVP_Grouped_get_avp_or_fail(multi_services_cc_data, c_AVP_Code_DCC_NONE_Used_Service_Unit);
+ used_service_unit_data := valueof(used_service_unit.avp_data.avp_DCC_NONE_Used_Service_Unit);
+
+ /* Reporting-Reason can be either inside Multiple-Services-Credit-Control or inside Used-Service-Unit */
+ repreason_tpl := f_AVP_Grouped_get_avp(multi_services_cc_data, c_AVP_Code_DCA_3GPP_Reporting_Reason);
+ if (istemplatekind(repreason_tpl, "omit")) {
+ repreason := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCA_3GPP_Reporting_Reason);
+ } else {
+ repreason := valueof(repreason_tpl);
+ }
+ if (not match(repreason.avp_data.avp_DCA_3GPP_Reporting_Reason, repreason_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-Reporting-Reason mismatch ", repreason, " vs exp ", repreason_exp));
+ }
+
+ cc_time := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Time);
+ if (not match(oct2int(cc_time.avp_data.avp_DCC_NONE_CC_Time), cc_time_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Time mismatch ", cc_time, " vs exp ", cc_time_exp));
+ }
+
+ cc_in_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Input_Octets);
+ if (not match(oct2int(cc_in_oct.avp_data.avp_DCC_NONE_CC_Input_Octets), cc_in_oct_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Input-Octets mismatch ", cc_in_oct, " vs exp ", cc_in_oct_exp));
+ }
+
+ cc_out_oct := f_AVP_Grouped_get_avp_or_fail(used_service_unit_data, c_AVP_Code_DCC_NONE_CC_Output_Octets);
+ if (not match(oct2int(cc_out_oct.avp_data.avp_DCC_NONE_CC_Output_Octets), cc_out_oct_exp)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("3GPP-CC-Output-Octets mismatch ", cc_out_oct, " vs exp ", cc_out_oct_exp));
+ }
+}
+
+} /* module */
diff --git a/library/DNS_Helpers.ttcn b/library/DNS_Helpers.ttcn
index 85040fc2..a1a347c7 100644
--- a/library/DNS_Helpers.ttcn
+++ b/library/DNS_Helpers.ttcn
@@ -10,7 +10,7 @@ module DNS_Helpers {
* SPDX-License-Identifier: GPL-2.0-or-later
*/
-private function f_strchr(charstring s, char c) return integer {
+private function f_strchr(charstring s, charstring c) return integer {
var integer i;
for (i := 0; i < lengthof(s); i := i+1) {
if (s[i] == c) {
diff --git a/library/GSMTAP_Types.ttcn b/library/GSMTAP_Types.ttcn
index 32882844..76e6ea3c 100644
--- a/library/GSMTAP_Types.ttcn
+++ b/library/GSMTAP_Types.ttcn
@@ -1,5 +1,6 @@
module GSMTAP_Types {
import from Osmocom_Types all;
+ import from GSM_Types all;
const uint8_t GSMTAP_VERSION := 2;
@@ -49,7 +50,7 @@ module GSMTAP_Types {
uint8_t hdr_len,
GsmtapMsgType msg_type,
uint8_t timeslot,
- Arfcn arfcn,
+ GsmBandArfcn arfcn,
int8_t signal_dbm,
int8_t snr_db,
uint32_t frame_number,
diff --git a/library/GSM_RR_Types.ttcn b/library/GSM_RR_Types.ttcn
index c12ebd18..464d060c 100644
--- a/library/GSM_RR_Types.ttcn
+++ b/library/GSM_RR_Types.ttcn
@@ -15,8 +15,10 @@ module GSM_RR_Types {
import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
+ import from GSM_RestOctets all;
import from RLCMAC_CSN1_Types all;
import from MobileL3_CommonIE_Types all;
+ import from MobileL3_RRM_Types all;
/* Table 10.4.1 of Section 10.4 / 3GPP TS 44.018 */
type enumerated RrMessageType {
@@ -81,8 +83,16 @@ module GSM_RR_Types {
EXTENDED_MEASUREMENT_REPORT ('00110110'B),
EXTENDED_MEASUREMENT_ORDER ('00110111'B),
GPRS_SUSPENSION_REQUEST ('00110100'B),
- //MBMS_ANNOUNCEMENT ('00010110'B), duplicate?
- //SERVICE_INFORMATION ('00110110'B), duplicate?
+ //MBMS_ANNOUNCEMENT ('00010110'B), duplicate, DL only
+ //SERVICE_INFORMATION ('00110110'B), duplicate, DL only
+
+ VGCS_UPLINK_GRANT ('00001001'B),
+ UPLINK_RELEASE ('00001110'B),
+ UPLINK_BUSY ('00101010'B),
+ TALKER_INDICATION ('00010001'B),
+ PRIORITY_UPLINK_REQUEST ('01100110'B),
+ DATA_INDICATION ('01100111'B),
+ DATA_INDICATION2 ('01101000'B),
APPLICATION_INFORMATION ('00111000'B),
@@ -109,13 +119,48 @@ module GSM_RR_Types {
CDMA2000_CLASSMARK_CHANGE ('01100010'B),
INTERSYS_TO_UTRAN_HO_CMD ('01100011'B),
INTERSYS_TO_CDMA2000_HO_CMD ('01100100'B),
- GERAN_IU_MODE_CLASSMARK_CHG ('01100101'B),
- INTERSYS_TO_EUTRAN_HO_CMD ('01100110'B)
+ GERAN_IU_MODE_CLASSMARK_CHG ('01100101'B)
+ //INTERSYS_TO_EUTRAN_HO_CMD ('01100110'B) duplicate, DL only
+ } with { variant "FIELDLENGTH(8)" };
+
+ /* Table 10.4.2 of Section 10.4 / 3GPP TS 44.018 */
+ type enumerated RrShortDisc {
+ SYSTEM_INFORMATION_TYPE_10 ('00000'B),
+ NOTIFICATION_FACCH ('00001'B),
+ UPLINK_FREE ('00010'B),
+ ENHAN_MEAS_REP_UL ('00100'B),
+ MEAS_INFO_DL ('00101'B),
+ VBS_VGCS_RECON ('00110'B),
+ VBS_VGCS_RECON2 ('00111'B),
+ VGCS_ADD_INFO ('01000'B),
+ VGCS_SMS_INFO ('01001'B),
+ SYSTEM_INFORMATION_TYPE_10bis ('01010'B),
+ SYSTEM_INFORMATION_TYPE_10ter ('01011'B),
+ VGCS_NEIGH_CELL_INFO ('01100'B),
+ NOTIFY_APP_DATA ('01101'B)
+ } with { variant "FIELDLENGTH(5)" };
+
+ type enumerated RR_Cause {
+ GSM48_RR_CAUSE_NORMAL ('00'O),
+ GSM48_RR_CAUSE_ABNORMAL_UNSPEC ('01'O),
+ GSM48_RR_CAUSE_ABNORMAL_UNACCT ('02'O),
+ GSM48_RR_CAUSE_ABNORMAL_TIMER ('03'O),
+ GSM48_RR_CAUSE_ABNORMAL_NOACT ('04'O),
+ GSM48_RR_CAUSE_PREMPTIVE_REL ('05'O),
+ GSM48_RR_CAUSE_HNDOVER_IMP ('08'O),
+ GSM48_RR_CAUSE_CHAN_MODE_UNACCT ('09'O),
+ GSM48_RR_CAUSE_FREQ_NOT_IMPL ('0a'O),
+ GSM48_RR_CAUSE_CALL_CLEARED ('41'O),
+ GSM48_RR_CAUSE_SEMANT_INCORR ('5f'O),
+ GSM48_RR_CAUSE_INVALID_MAND_INF ('60'O),
+ GSM48_RR_CAUSE_MSG_TYPE_N ('61'O),
+ GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT('62'O),
+ GSM48_RR_CAUSE_COND_IE_ERROR ('64'O),
+ GSM48_RR_CAUSE_NO_CELL_ALLOC_A ('65'O),
+ GSM48_RR_CAUSE_PROT_ERROR_UNSPC ('6f'O)
} with { variant "FIELDLENGTH(8)" };
type octetstring RestOctets with { variant "PADDING(yes), PADDING_PATTERN('00101011'B)" };
- type hexstring GsmBcdString with { variant "HEXORDER(low)" };
- type GsmBcdString BcdMccMnc with { variant "FIELDLENGTH(6)" };
type record L2PseudoLength {
uint6_t l2_plen,
@@ -174,7 +219,15 @@ module GSM_RR_Types {
uint8_t actual_ta
} with { variant "FIELDORDER(msb)" };
- template (value) SacchL1Header ts_SacchL1Header(uint5_t ms_power_lvl, boolean fpc, uint8_t actual_ta) := {
+ external function enc_SacchL1Header(in SacchL1Header hdr) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+ external function dec_SacchL1Header(in octetstring stream) return SacchL1Header
+ with { extension "prototype(convert) decode(RAW)" };
+
+ template (value) SacchL1Header
+ ts_SacchL1Header(uint5_t ms_power_lvl,
+ uint8_t actual_ta,
+ boolean fpc := false) := {
reserved := 0,
fpc := fpc,
ms_power_lvl := ms_power_lvl,
@@ -198,18 +251,9 @@ module GSM_RR_Types {
hsn := hsn
};
- /* TS 24.008 10.5.1.1 */
- type uint16_t CellIdentity;
-
/* TS 24.008 10.5.1.2 */
type uint4_t CipheringKeySeqNr (0..7);
- /* 24.008 10.5.1.3 */
- type record LocationAreaIdentification {
- BcdMccMnc mcc_mnc,
- uint16_t lac
- } with { variant "" };
-
/* TS 24.008 10.5.1.4 */
type enumerated MobileIdentityType {
MI_TYPE_NONE (0),
@@ -274,14 +318,19 @@ module GSM_RR_Types {
} with { variant "" };
/* 10.5.2.21 */
- type record MobileAllocation {
+ type record MobileAllocationLV {
uint8_t len,
- bitstring ma
+ bitstring ma length (0..64)
} with {
variant (len) "LENGTHTO(ma)"
variant (ma) "BYTEORDER(first), BITORDER(msb)"
};
+ type record MobileAllocationTLV {
+ OCT1 iei ('72'O),
+ MobileAllocationLV v
+ } with { variant "" };
+
/* 10.5.2.25a */
type record PktChDesc0Ind {
uint6_t maio,
@@ -398,228 +447,6 @@ module GSM_RR_Types {
uint3_t non_drx_timer
} with { variant "" };
- /* 24.008 10.5.5.15 */
- type record RoutingAreaIdentification {
- LocationAreaIdentification lai,
- uint8_t rac
- } with { variant "" };
-
- external function enc_RoutingAreaIdentification(RoutingAreaIdentification rai) return octetstring
- with { extension "prototype(convert)" extension "encode(RAW)" }
-
- /* 44.018 10.5.2.16 */
- type record IaRestOctHL {
- uint6_t freq_par_len,
- BIT2 padding ('00'B) optional,
- uint6_t maio optional,
- octetstring mobile_allocation optional
- } with {
- variant (freq_par_len) "LENGTHTO(mobile_allocation,maio,padding)"
-/*
- variant (padding) "PRESENCE(freq_par_len != 0)"
- variant (maio) "PRESENCE(freq_par_len != 0)"
- variant (mobile_allocation) "PRESENCE(freq_par_len != 0)"
-*/
- };
- type record SecondPartAssign {
- BIT1 r99, /* L / H */
- BIT1 presence optional,
- BIT5 ext_ra optional
- } with {
- variant (r99) "CSN.1 L/H"
- variant (presence) "PRESENCE(r99 = '1'B)" /* H */
- variant (ext_ra) "PRESENCE(presence = '1'B)"
- /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
- variant (ext_ra) "BYTEORDER(last)" // FIXME: should be first
- };
- type union PacketUlDlAssignUnion {
- PacketUlAssign ul,
- PacketDlAssign dl
- };
- type record PacketUlDlAssign {
- BIT1 ass_disc,
- PacketUlDlAssignUnion ass
- } with {
- variant (ass) "CROSSTAG(dl, ass_disc = '1'B; ul, ass_disc = '0'B)"
- };
- type union PacketAssignUnion {
- SecondPartAssign spa,
- PacketUlDlAssign uldl
- };
- type record IaRestOctHH {
- /* Packet Assignment discriminator:
- * Packet Uplink / Downlink Assignment (0)
- * Second Part Packet Assignment (1) */
- BIT1 pa_disc,
- PacketAssignUnion pa
- } with {
- variant (pa) "CROSSTAG(spa, pa_disc = '1'B; uldl, pa_disc = '0'B)"
- };
- type record PacketUlAssignDyn {
- uint5_t tfi_assignment,
- BIT1 polling,
- BIT1 spare ('0'B),
- uint3_t usf,
- BIT1 usf_granularity,
- BIT1 p0_present,
- uint4_t p0 optional,
- BIT1 pr_mode optional,
- ChCodingCommand ch_coding_cmd,
- BIT1 tlli_block_chan_coding,
- BIT1 alpha_present,
- uint4_t alpha optional,
- uint5_t gamma,
- BIT1 ta_index_present,
- uint4_t ta_index optional,
- BIT1 tbf_starting_time_present,
- uint16_t tbf_starting_time optional
- } with {
- variant (p0) "PRESENCE(p0_present = '1'B)"
- variant (pr_mode) "PRESENCE(p0_present = '1'B)"
- variant (alpha) "PRESENCE(alpha_present = '1'B)"
- variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
- variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
- };
- type record PacketUlAssignSgl {
- BIT1 alpha_present,
- uint4_t alpha optional,
- uint5_t gamma,
- BIT2 padding ('01'B),
- uint16_t tbf_starting_time
- /* TODO: P0 / PR_MODE */
- } with {
- variant (alpha) "PRESENCE(alpha_present = '1'B)"
- };
- type record PacketUlAssign {
- BIT1 presence,
- PacketUlAssignDyn dynamic optional,
- PacketUlAssignSgl single optional
- /* TODO: Estended RA, PFI */
- } with {
- variant (dynamic) "PRESENCE(presence = '1'B)"
- variant (single) "PRESENCE(presence = '0'B)"
- };
- type record PacketDlAssG1 {
- uint5_t tfi_assignment,
- BIT1 rlc_mode,
- BIT1 alpha_present,
- uint4_t alpha optional,
- uint5_t gamma,
- BIT1 polling,
- BIT1 ta_valid
- } with { variant "" };
- type record PacketDlAssign {
- GprsTlli tlli,
- BIT1 group1_present,
- PacketDlAssG1 group1 optional,
- BIT1 ta_index_present,
- uint4_t ta_index optional,
- BIT1 tbf_starting_time_present,
- uint16_t tbf_starting_time optional,
- BIT1 p0_present,
- uint4_t p0 optional,
- BIT1 pr_mode optional
- /* TODO: EGPRS window size, etc. */
- } with {
- variant (group1) "PRESENCE(group1_present = '1'B)"
- variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
- variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
- variant (p0) "PRESENCE(p0_present = '1'B)"
- variant (pr_mode) "PRESENCE(p0_present = '1'B)"
- };
- type record IaRestOctLL {
- BIT1 compressed_irat_ho_info_ind
- } with {
- variant (compressed_irat_ho_info_ind) "CSN.1 L/H"
- };
- type record EgprsUlAssignDyn {
- uint5_t tfi_assignment,
- BIT1 polling,
- BIT1 spare ('0'B),
- uint3_t usf,
- BIT1 usf_granularity,
- BIT1 p0_present,
- uint4_t p0 optional,
- BIT1 pr_mode optional,
- EgprsChCodingCommand egprs_ch_coding_cmd,
- BIT1 tlli_block_chan_coding,
- BIT1 bep_period2_present,
- BIT4 bep_period2 optional,
- BIT1 resegment,
- EgprsWindowSize egprs_window_size,
- BIT1 alpha_present,
- uint4_t alpha optional,
- uint5_t gamma,
- BIT1 ta_index_present,
- uint4_t ta_index optional,
- BIT1 tbf_starting_time_present,
- uint16_t tbf_starting_time optional
- /* TODO: Additions for Rel-7 */
- } with {
- variant (p0) "PRESENCE(p0_present = '1'B)"
- variant (pr_mode) "PRESENCE(p0_present = '1'B)"
- variant (bep_period2) "PRESENCE(bep_period2_present = '1'B)"
- variant (alpha) "PRESENCE(alpha_present = '1'B)"
- variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
- variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
- };
- type record EgprsUlAssignMultiblock {
- BIT1 alpha_present,
- uint4_t alpha optional,
- uint5_t gamma,
- uint16_t tbf_starting_time,
- BIT2 nr_radio_blocks_allocated,
- BIT1 p0_present,
- uint4_t p0 optional,
- BIT1 spare ('0'B) optional,
- BIT1 pr_mode optional
- /* TDO: Additions for Rel-6 */
- } with {
- variant (alpha) "PRESENCE(alpha_present = '1'B)"
- variant (p0) "PRESENCE(p0_present = '1'B)"
- variant (spare) "PRESENCE(p0_present = '1'B)"
- variant (pr_mode) "PRESENCE(p0_present = '1'B)"
- };
- /* 3GPP TS 44.018 version 13.3.2 10.5.2.16, "EGPRS Packet Uplink Assignment" */
- type record EgprsUlAss {
- BIT5 ext_ra,
- BIT1 ats_present,
- AccessTechnologiesRequestRepetition ats optional,
- BIT1 presence,
- EgprsUlAssignDyn dynamic optional,
- EgprsUlAssignMultiblock multiblock optional
- } with {
- variant (ats) "PRESENCE(ats_present = '1'B)"
- variant (dynamic) "PRESENCE(presence = '1'B)"
- variant (multiblock) "PRESENCE(presence = '0'B)"
- /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
- variant (ext_ra) "BYTEORDER(last)" // FIXME: should be first
- };
-
- type octetstring MblkDlAss; /* TODO */
- type record IaRestOctLH {
- BIT2 presence,
- EgprsUlAss egprs_ul optional,
- MblkDlAss multiblock_dl_ass optional
- } with {
- variant (egprs_ul) "PRESENCE(presence = '00'B)"
- variant (multiblock_dl_ass) "PRESENCE(presence = '01'B)"
- };
- type record IaRestOctets {
- BIT2 presence,
- IaRestOctLL ll optional,
- IaRestOctLH lh optional,
- IaRestOctHL hl optional,
- IaRestOctHH hh optional
- } with {
- variant (presence) "CSN.1 L/H"
- variant (ll) "PRESENCE(presence = '00'B)"
- variant (lh) "PRESENCE(presence = '01'B)"
- variant (hl) "PRESENCE(presence = '10'B)"
- variant (hh) "PRESENCE(presence = '11'B)"
- variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
- };
-
type record MeasurementResults {
BIT1 ba_used,
BIT1 dtx_used,
@@ -634,8 +461,7 @@ module GSM_RR_Types {
NcellReports ncell_reports optional
} with { variant (no_ncell_m) "LENGTHTO(ncell_reports)"
variant (no_ncell_m) "UNIT(elements)"
- variant "PADDING(yes)"
- variant "FIELDLENGTH(16)"
+ /* FIXME: pad to 16 octets */
};
type record NcellReport {
@@ -646,6 +472,59 @@ module GSM_RR_Types {
type record of NcellReport NcellReports;
+ /* 3GPP TS 44.018, section 9.1.2 (minimalistic implementation) */
+ type record AssignmentCommand {
+ ChannelDescription chan_desc,
+ PowerCommand_V power_cmd,
+ FrequencyList_TLV freq_list_at optional,
+ CellChannelDescription_TV cell_chan_desc optional,
+ /* TODO: Multislot Allocation IE */
+ ChannelMode_TV chan1_mode optional,
+ ChannelMode_TV chan2_mode optional,
+ /* TODO: Mode of Channel Set 3..8 IE */
+ MobileAllocationTLV mobile_allocation optional
+ /* TODO: more optional IEs... */
+ } with {
+ variant "TAG(
+ freq_list_at, elementIdentifier = '05'O;
+ cell_chan_desc, elementIdentifier = '62'O;
+ chan1_mode, elementIdentifier = '63'O;
+ chan2_mode, elementIdentifier = '11'O;
+ mobile_allocation, iei = '72'O;
+ )"
+ };
+
+ /* 3GPP TS 44.018, section 9.1.15 (minimalistic implementation) */
+ type record HandoverCommand {
+ CellDescriptionV cell_desc,
+ ChannelDescription chan_desc,
+ OCT1 ho_ref,
+ PowerCommandAndAccesstype_V power_cmd_acc_type,
+ FrequencyList_TLV freq_list_at optional,
+ CellChannelDescription_TV cell_chan_desc optional,
+ ChannelMode_TV chan1_mode optional,
+ ChannelMode_TV chan2_mode optional,
+ /* TODO: Mode of Channel Set 3..8 IE */
+ MobileAllocationTLV mobile_allocation optional
+ /* TODO: more optional IEs... */
+ } with {
+ variant "TAG(
+ freq_list_at, elementIdentifier = '05'O;
+ cell_chan_desc, elementIdentifier = '62'O;
+ chan1_mode, elementIdentifier = '63'O;
+ chan2_mode, elementIdentifier = '11'O;
+ mobile_allocation, iei = '72'O;
+ )"
+ };
+
+ /* 10.5.2.2 Cell Description IE */
+ type record CellDescriptionV {
+ uint3_t bcc, /* PLMN colour code */
+ uint3_t ncc, /* BS colour code */
+ uint10_t bcch_arfcn
+ } with { variant "FIELDORDER(lsb)" };
+
+
/* 9.1.18 */
type record ImmediateAssignment {
DedicatedModeOrTbf ded_or_tbf,
@@ -654,7 +533,7 @@ module GSM_RR_Types {
PacketChannelDescription pkt_chan_desc optional,
RequestReference req_ref,
TimingAdvance timing_advance,
- MobileAllocation mobile_allocation,
+ MobileAllocationLV mobile_allocation,
/* TODO: starting time TLV */
IaRestOctets rest_octets
} with { variant (chan_desc) "PRESENCE(ded_or_tbf.tbf = false)"
@@ -673,34 +552,6 @@ module GSM_RR_Types {
IARRestOctets rest_octets
} with { variant "" };
- /* 10.5.2.17 IAR (Immediate Assignment Reject) Rest Octets */
- type record IARRestOctets {
- ExtRAList ext_ra_list,
- BIT1 rel13_ind, // L/H
- uint3_t rcc optional
- /* Addition in Rel-15: PEO IMM Cell Group Details struct */
- } with {
- variant (rel13_ind) "CSN.1 L/H"
- variant (rcc) "PRESENCE(rel13_ind = '1'B)"
-
- /* The TITAN's RAW encoder generates an octet-aligned octetstring,
- * so we should make sure that unused bits contain proper padding. */
- variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
- };
-
- /* Optional extended RA: 0 | 1 < Extended RA 1 : bit (5) > */
- type record ExtRAOpt {
- BIT1 presence, // L/H
- BIT5 ext_ra optional
- } with {
- variant (presence) "CSN.1 L/H"
- variant (ext_ra) "PRESENCE(presence = '1'B)"
- /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
- variant (ext_ra) "BYTEORDER(last)"
- };
-
- type record length(4) of ExtRAOpt ExtRAList;
-
/* 9.1.21 */
type record MeasurementReport {
MeasurementResults meas_res
@@ -734,6 +585,92 @@ module GSM_RR_Types {
RestOctets rest_octets
} with { variant "" };
+ /* 9.1.44 */
+ type record CipheringKeySeqNrTV {
+ HEX1 tag,
+ CipheringKeySeqNr cksn
+ }
+ type record TalkerIndication {
+ MsClassmark2LV cm2,
+ MobileIdentityLV mi,
+ CipheringKeySeqNrTV cksn optional
+ } with { variant "TAG(cksn, tag = 'B'H)" };
+
+ /* 9.1.44a */
+ type record PriorityUplinkRequest {
+ OCT1 est_cause,
+ OCT4 token,
+ OCT4 reduced_gcr,
+ MobileIdentityLV mi
+ } with { variant "" };
+
+ /* 9.1.44b */
+ type record DataIndication {
+ GsmTmsi tmsi,
+ OCT9 app_data,
+ OCT1 data_id
+ } with { variant "" };
+
+ /* 9.1.44c */
+ type record DataIndication2 {
+ GsmTmsi tmsi,
+ OCT4 reduced_gcr,
+ OCT9 app_data,
+ OCT1 data_id
+ } with { variant "" };
+
+ /* 9.1.46 */
+ type record UplinkBusy {
+ TalkerPrioEmergIndTLV prio optional,
+ TokenTV token optional,
+ TalkerIdentityTLV talker_id optional,
+ UplinkAccessIndTV ul_access_ind optional
+ } with { variant "" };
+
+ /* 9.1.48 */
+ type record UplinkRelease {
+ RR_Cause cause
+ } with { variant "" };
+
+ /* 9.1.49 */
+ type record VgcsUplinkGrant {
+ RequestReference req_ref,
+ TimingAdvance ta
+ } with { variant "" };
+
+
+ /* 10.5.2.64 */
+ type record TalkerPrioEmergIndTLV {
+ OCT1 iei ('31'O),
+ uint8_t len,
+ boolean es,
+ BIT3 spare,
+ boolean uai_rach,
+ uint3_t priority
+ } with { variant (len) "LENGTHTO(es,spare,uai_rach,priority)"
+ variant "PRESENCE(iei = '31'O)" };
+
+ /* 10.5.2.65 */
+ type record TokenTV {
+ OCT1 iei ('32'O),
+ OCT4 token
+ } with { variant "PRESENCE(iei = '32'O)" };
+
+ /* 10.5.2.66 */
+ type record TalkerIdentityTLV {
+ OCT1 iei ('33'O),
+ uint8_t len,
+ octetstring talker_id
+ } with { variant (len) "LENGTHTO(talker_id)"
+ variant "PRESENCE(iei = '33'O)" };
+
+ /* 10.5.2.74 */
+ type record UplinkAccessIndTV {
+ HEX1 iei ('8'H),
+ BIT3 spare ('000'B),
+ boolean uai_rach
+ } with { variant "PRESENCE(iei = '8'H)" };
+
type union RrUnion {
/*
SystemInformationType1 si1,
@@ -801,9 +738,18 @@ module GSM_RR_Types {
} with { variant "" };
type union RrL3Union {
- PagingResponse paging_response,
- MeasurementReport meas_rep,
- octetstring other
+ PagingResponse paging_response,
+ MeasurementReport meas_rep,
+ AssignmentCommand ass_cmd,
+ HandoverCommand ho_cmd,
+ TalkerIndication talker_ind,
+ PriorityUplinkRequest priority_ul_req,
+ UplinkBusy uplink_busy,
+ UplinkRelease uplink_release,
+ VgcsUplinkGrant vgcs_ul_grant,
+ DataIndication data_ind,
+ DataIndication2 data_ind2,
+ octetstring other
};
type record GsmRrL3Message {
@@ -812,6 +758,15 @@ module GSM_RR_Types {
} with { variant (payload) "CROSSTAG(
paging_response, header.message_type = PAGING_RESPONSE;
meas_rep, header.message_type = MEASUREMENT_REPORT;
+ ass_cmd, header.message_type = ASSIGNMENT_COMMAND;
+ ho_cmd, header.message_type = HANDOVER_COMMAND;
+ talker_ind, header.message_type = TALKER_INDICATION;
+ priority_ul_req, header.message_type = PRIORITY_UPLINK_REQUEST;
+ uplink_busy, header.message_type = UPLINK_BUSY;
+ uplink_release, header.message_type = UPLINK_RELEASE;
+ vgcs_ul_grant, header.message_type = VGCS_UPLINK_GRANT;
+ data_ind, header.message_type = DATA_INDICATION;
+ data_ind2, header.message_type = DATA_INDICATION2;
other, OTHERWISE;
)" }
@@ -821,122 +776,9 @@ module GSM_RR_Types {
with { extension "prototype(convert) decode(RAW)" };
- template PacketDlAssign tr_PacketDlAssign(template GprsTlli tlli) := {
- tlli := tlli,
- group1_present := ?,
- group1 := *,
- ta_index_present := ?,
- ta_index := *,
- tbf_starting_time_present := ?,
- tbf_starting_time := *,
- p0_present := ?,
- p0 := *,
- pr_mode := *
- };
-
- template IaRestOctets tr_IaRestOctets_DLAss(template PacketDlAssign dl_ass) := {
- presence := '11'B, /* HH */
- ll := omit, lh := omit, hl := omit,
- hh := {
- pa_disc := '0'B, /* Packet Assignment (0) */
- pa := {
- uldl := {
- ass_disc := '1'B, /* Downlink Assignment (1) */
- ass := { dl := dl_ass }
- }
- }
- }
- };
-
- template PacketUlAssign tr_PacketUlDynAssign(template uint5_t tfi := ?,
- template BIT1 polling := ?,
- template uint3_t usf := ?,
- template BIT1 usf_granularity := ?,
- template ChCodingCommand cs := ?) := {
- presence := '1'B, /* Dynamic Block Allocation */
- dynamic := {
- tfi_assignment := tfi,
- polling := polling,
- spare := '0'B, /* Dynamic Block Allocation (mandatory after Rel-4) */
- usf := usf,
- usf_granularity := usf_granularity,
- p0_present := ?,
- p0 := *,
- pr_mode := *,
- ch_coding_cmd := cs,
- tlli_block_chan_coding := ?,
- alpha_present := ?,
- alpha := *,
- gamma := ?,
- /* TODO: add to parameters */
- ta_index_present := ?,
- ta_index := *,
- tbf_starting_time_present := ?,
- tbf_starting_time := *
- },
- single := omit
- };
-
- template PacketUlAssign tr_PacketUlSglAssign := {
- presence := '0'B, /* Single Block Allocation */
- dynamic := omit,
- single := {
- alpha_present := ?,
- alpha := *,
- gamma := ?,
- padding := '01'B,
- tbf_starting_time := ?
- }
- };
-
- template IaRestOctets tr_IaRestOctets_ULAss(template PacketUlAssign ul_ass) := {
- presence := '11'B, /* HH */
- ll := omit, lh := omit, hl := omit,
- hh := {
- pa_disc := '0'B, /* Packet Assignment (0) */
- pa := {
- uldl := {
- ass_disc := '0'B, /* Uplink Assignment (0) */
- ass := { ul := ul_ass }
- }
- }
- }
- };
-
- template EgprsUlAss tr_EgprsUlAssDynamic(template (present) BIT5 ext_ra := ?,
- template EgprsUlAssignDyn dyn_ass := ?) := {
- ext_ra := ext_ra,
- ats_present := ?,
- ats := *,
- presence := '1'B,
- dynamic := dyn_ass,
- multiblock := omit
- };
- template EgprsUlAss tr_EgprsUlAssMultiblock(template (present) BIT5 ext_ra := ?,
- template EgprsUlAssignMultiblock mb_ass := ?) := {
- ext_ra := ext_ra,
- ats_present := ?,
- ats := *,
- presence := '0'B,
- dynamic := omit,
- multiblock := mb_ass
- };
-
- template IaRestOctets tr_IaRestOctets_EGPRSULAss(template EgprsUlAss ul_ass) := {
- presence := '01'B, /* LH */
- ll := omit,
- lh := {
- presence := '00'B,
- egprs_ul := ul_ass,
- multiblock_dl_ass := omit
- },
- hl := omit,
- hh := omit
- };
-
template (value) GsmRrMessage ts_IMM_ASS(uint8_t ra, GsmFrameNumber fn, TimingAdvance ta,
- ChannelDescription ch_desc, MobileAllocation ma) := {
- header := t_RrHeader(IMMEDIATE_ASSIGNMENT, 0),
+ ChannelDescription ch_desc, MobileAllocationLV ma) := {
+ header := ts_RrHeader(IMMEDIATE_ASSIGNMENT, 0),
payload := {
imm_ass := {
ded_or_tbf := {
@@ -965,7 +807,8 @@ module GSM_RR_Types {
template GsmRrMessage tr_IMM_ASS(template uint8_t ra := ?, template GsmFrameNumber fn := ?,
template TimingAdvance ta := ?,
template ChannelDescription ch_desc := ?,
- template MobileAllocation ma := ?) := {
+ template MobileAllocationLV ma := ?,
+ template PageMode page_mode := PAGE_MODE_NORMAL) := {
header := t_RrHeader(IMMEDIATE_ASSIGNMENT, ?),
payload := {
imm_ass := {
@@ -975,7 +818,7 @@ module GSM_RR_Types {
downlink := false,
tbf := false
},
- page_mode := PAGE_MODE_NORMAL,
+ page_mode := page_mode,
chan_desc := ch_desc,
pkt_chan_desc := omit,
req_ref := tr_compute_ReqRef(ra, fn),
@@ -992,7 +835,7 @@ module GSM_RR_Types {
template GsmFrameNumber fn := ?,
template TimingAdvance ta := ?,
template PacketChannelDescription ch_desc := ?,
- template MobileAllocation ma := ?,
+ template MobileAllocationLV ma := ?,
template IaRestOctets rest := ?) := {
header := t_RrHeader(IMMEDIATE_ASSIGNMENT, ?),
payload := {
@@ -1031,9 +874,33 @@ module GSM_RR_Types {
}
};
- template (value) GsmRrL3Message ts_MEAS_REP(boolean valid, uint6_t rxl_f, uint6_t rxl_s,
- uint3_t rxq_f, uint3_t rxq_s,
- template (omit) NcellReports reps) := {
+ template (value) MeasurementResults
+ ts_MeasurementResults(template (value) uint6_t rxl_f := 63,
+ template (value) uint6_t rxl_s := 63,
+ template (value) uint3_t rxq_f := 0,
+ template (value) uint3_t rxq_s := 0,
+ boolean dtx_used := false,
+ boolean valid := true,
+ template (omit) NcellReports reps := omit) := {
+ ba_used := '0'B,
+ dtx_used := bool2bit(dtx_used),
+ rxlev_full_srv_cell := rxl_f,
+ threeg_ba_used := '0'B,
+ meas_valid := bool2bit(not valid),
+ rxlev_sub_srv_cell := rxl_s,
+ si23_ba_used := '0'B,
+ rxqual_full_srv_cell := rxq_f,
+ rxqual_sub_srv_cell := rxq_s,
+ no_ncell_m := 0,
+ ncell_reports := reps
+ };
+
+ template (value) GsmRrL3Message ts_MEAS_REP(boolean valid,
+ template (value) uint6_t rxl_f,
+ template (value) uint6_t rxl_s,
+ template (value) uint3_t rxq_f := 0,
+ template (value) uint3_t rxq_s := 0,
+ template (omit) NcellReports reps := omit) := {
header := t_RrL3Header(MEASUREMENT_REPORT),
payload := {
meas_rep := {
@@ -1074,18 +941,6 @@ module GSM_RR_Types {
wait_ind := wi
};
- template IARRestOctets tr_IARRestOctets(template ExtRAList ext_ra_list := ?,
- template uint3_t rcc := ?) := {
- ext_ra_list := ext_ra_list,
- rel13_ind := ?,
- rcc := rcc ifpresent
- };
-
- template ExtRAOpt tr_ExtRAOpt(template BIT5 ext_ra := ?) := {
- presence := '1'B, // L/H
- ext_ra := ext_ra
- };
-
template (value) ChannelDescription ts_ChanDescH0(template (value) RslChannelNr chan_nr,
template (value) uint12_t arfcn,
template (value) uint3_t tsc := 7) := {
@@ -1095,6 +950,15 @@ module GSM_RR_Types {
arfcn := arfcn,
maio_hsn := omit
}
+ template ChannelDescription tr_ChanDescH0(template (present) RslChannelNr chan_nr := ?,
+ template (present) uint12_t arfcn := ?,
+ template (present) uint3_t tsc := ?) := {
+ chan_nr := chan_nr,
+ tsc := tsc,
+ h := false,
+ arfcn := arfcn,
+ maio_hsn := omit
+ }
template (value) ChannelDescription ts_ChanDescH1(template (value) RslChannelNr chan_nr,
template (value) MaioHsn maio_hsn,
@@ -1105,5 +969,121 @@ module GSM_RR_Types {
arfcn := omit,
maio_hsn := maio_hsn
}
+ template ChannelDescription tr_ChanDescH1(template (present) RslChannelNr chan_nr := ?,
+ template (present) MaioHsn maio_hsn := ?,
+ template (present) uint3_t tsc := ?) := {
+ chan_nr := chan_nr,
+ tsc := tsc,
+ h := true,
+ arfcn := omit,
+ maio_hsn := maio_hsn
+ }
+
+
+ /* Templates for the RR Channel Release message's "Cell selection indicator after release of all TCH and SDCCH" IE.
+ * See 3GPP TS 44.018 9.1.7 and 10.5.2.1e */
+
+ /* 3GPP TS 44.018 10.5.2.1e, Cell Selection Indicator after release of all TCH and SDCCH value part */
+ type record CellSelIndValue {
+ BIT3 discr,
+ CellSelIndValueEnum value_list,
+ BIT1 value_list_term ('0'B)
+ } with {
+ variant (value_list) "CROSSTAG(
+ gsm, discr='000'B;
+ utran_fdd, discr='001'B;
+ utran_tdd, discr='010'B;
+ eutran, discr='011'B;
+ )"
+ };
+
+ /* 3GPP TS 44.018 10.5.2.1e, Cell Selection Indicator after release of all TCH and SDCCH value part */
+ private type union CellSelIndValueEnum {
+ CellSelIndValue_GSM_Descrs gsm,
+ CellSelIndValue_UTRAN_Descrs utran_fdd,
+ CellSelIndValue_UTRAN_Descrs utran_tdd,
+ CellSelIndValue_EUTRAN_Descrs eutran
+ } with { variant "" };
+
+ type record of CellSelIndValue_GSM_Descr CellSelIndValue_GSM_Descrs;
+ /* 3GPP TS 44.018 10.5.2.1e, GSM Description struct */
+ type record CellSelIndValue_GSM_Descr {
+ BIT1 item_ind ('1'B),
+ BIT1 band_indicator,
+ uint10_t arfcn,
+ uint6_t bsic
+ } with {
+ variant "PRESENCE(item_ind = '1'B)"
+ };
+
+ type record of CellSelIndValue_UTRAN_Descr CellSelIndValue_UTRAN_Descrs;
+ /* 3GPP TS 44.018 10.5.2.1e, UTRAN {FDD,TDD} Description struct */
+ type record CellSelIndValue_UTRAN_Descr {
+ BIT1 item_ind ('1'B),
+ BIT1 bandwidth_presence,
+ uint3_t bandwidth optional,
+ uint14_t arfcn,
+ BIT1 cell_info_presence,
+ UTRAN_CellInfo cell_info optional
+ } with {
+ variant "PRESENCE(item_ind = '1'B)"
+ variant (bandwidth) "PRESENCE(bandwidth_presence = '1'B)"
+ variant (cell_info) "PRESENCE(cell_info_presence = '1'B)"
+ };
+ type record UTRAN_CellInfo {
+ BIT1 indic0,
+ uint5_t nr_of_cells,
+ // TODO: define cell_information_field
+ octetstring cell_information_field
+ } with { variant "" };
+
+ type record of CellSelIndValue_EUTRAN_Descr CellSelIndValue_EUTRAN_Descrs;
+ /* 3GPP TS 44.018 10.5.2.1e, E-UTRAN Description struct */
+ type record CellSelIndValue_EUTRAN_Descr {
+ BIT1 item_ind ('1'B),
+ uint16_t earfcn,
+ BIT1 meas_bw_presence,
+ uint3_t meas_bw optional,
+ BIT1 not_allowed_cells_presence,
+ // define not_allowed_cells
+ octetstring not_allowed_cells optional,
+ BIT1 target_pcid_presence,
+ uint9_t target_pcid optional
+ } with {
+ variant "PRESENCE(item_ind = '1'B)"
+ variant (meas_bw) "PRESENCE(meas_bw_presence = '1'B)"
+ variant (not_allowed_cells) "PRESENCE(not_allowed_cells_presence = '1'B)"
+ variant (target_pcid) "PRESENCE(target_pcid_presence = '1'B)"
+ };
+
+ template CellSelIndValue tr_CellSelIndValue_EUTRAN(
+ template CellSelIndValue_EUTRAN_Descrs cells := {})
+ := {
+ discr := '011'B,
+ value_list := {
+ eutran := cells
+ },
+ value_list_term := '0'B
+ };
+
+ template CellSelIndValue_EUTRAN_Descr tr_CellSelIndValue_EUTRAN_Descr(
+ template (present) uint16_t earfcn,
+ template (present) BIT1 meas_bw_presence := ?,
+ template uint3_t meas_bw := *)
+ := {
+ item_ind := '1'B,
+ earfcn := earfcn,
+ meas_bw_presence := meas_bw_presence,
+ meas_bw := meas_bw,
+ not_allowed_cells_presence := '0'B,
+ not_allowed_cells := omit,
+ target_pcid_presence := '0'B,
+ target_pcid := omit
+ };
+
+ external function enc_CellSelIndValue(in CellSelIndValue ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+ external function dec_CellSelIndValue(in octetstring stream) return CellSelIndValue
+ with { extension "prototype(convert) decode(RAW)" };
} with { encode "RAW" ; variant "FIELDORDER(msb)" }
diff --git a/library/GSM_RestOctets.ttcn b/library/GSM_RestOctets.ttcn
index d47e510f..eff95469 100644
--- a/library/GSM_RestOctets.ttcn
+++ b/library/GSM_RestOctets.ttcn
@@ -15,6 +15,408 @@ module GSM_RestOctets {
import from General_Types all;
import from Osmocom_Types all;
+import from RLCMAC_CSN1_Types all;
+import from GSM_Types all;
+
+/* 10.5.2.16 IA (Immediate Assignment) Rest Octets */
+type record IaRestOctets {
+ BIT2 presence,
+ IaRestOctLL ll optional,
+ IaRestOctLH lh optional,
+ IaRestOctHL hl optional,
+ IaRestOctHH hh optional
+} with {
+ variant (presence) "CSN.1 L/H"
+ variant (ll) "PRESENCE(presence = '00'B)"
+ variant (lh) "PRESENCE(presence = '01'B)"
+ variant (hl) "PRESENCE(presence = '10'B)"
+ variant (hh) "PRESENCE(presence = '11'B)"
+
+ /* The TITAN's RAW encoder generates an octet-aligned octetstring,
+ * so we should make sure that unused bits contain proper padding. */
+ variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
+};
+
+type record IaRestOctLL {
+ BIT1 compressed_irat_ho_info_ind
+} with {
+ variant (compressed_irat_ho_info_ind) "CSN.1 L/H"
+};
+
+type record IaRestOctLH {
+ BIT2 presence,
+ EgprsUlAss egprs_ul optional,
+ octetstring multiblock_dl_ass optional /* TODO */
+} with {
+ variant (egprs_ul) "PRESENCE(presence = '00'B)"
+ variant (multiblock_dl_ass) "PRESENCE(presence = '01'B)"
+};
+
+/* EGPRS Packet Uplink Assignment */
+type record EgprsUlAss {
+ BIT5 ext_ra,
+ BIT1 ats_present,
+ AccessTechnologiesRequestRepetition ats optional,
+ BIT1 presence,
+ EgprsUlAssignDyn dynamic optional,
+ EgprsUlAssignMultiblock multiblock optional
+} with {
+ variant (ats) "PRESENCE(ats_present = '1'B)"
+ variant (dynamic) "PRESENCE(presence = '1'B)"
+ variant (multiblock) "PRESENCE(presence = '0'B)"
+ /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
+ variant (ext_ra) "BYTEORDER(last)" // FIXME: should be first
+};
+
+type record EgprsUlAssignDyn {
+ uint5_t tfi_assignment,
+ BIT1 polling,
+ BIT1 spare ('0'B),
+ uint3_t usf,
+ BIT1 usf_granularity,
+ BIT1 p0_present,
+ uint4_t p0 optional,
+ BIT1 pr_mode optional,
+ EgprsChCodingCommand egprs_ch_coding_cmd,
+ BIT1 tlli_block_chan_coding,
+ BIT1 bep_period2_present,
+ BIT4 bep_period2 optional,
+ BIT1 resegment,
+ EgprsWindowSize egprs_window_size,
+ BIT1 alpha_present,
+ uint4_t alpha optional,
+ uint5_t gamma,
+ BIT1 ta_index_present,
+ uint4_t ta_index optional,
+ BIT1 tbf_starting_time_present,
+ TbfStartingTime tbf_starting_time optional
+ /* TODO: Additions for Rel-7 */
+} with {
+ variant (p0) "PRESENCE(p0_present = '1'B)"
+ variant (pr_mode) "PRESENCE(p0_present = '1'B)"
+ variant (bep_period2) "PRESENCE(bep_period2_present = '1'B)"
+ variant (alpha) "PRESENCE(alpha_present = '1'B)"
+ variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
+ variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
+};
+
+type record EgprsUlAssignMultiblock {
+ BIT1 alpha_present,
+ uint4_t alpha optional,
+ uint5_t gamma,
+ TbfStartingTime tbf_starting_time,
+ BIT2 nr_radio_blocks_allocated,
+ BIT1 p0_present,
+ uint4_t p0 optional,
+ BIT1 spare ('0'B) optional,
+ BIT1 pr_mode optional
+ /* TDO: Additions for Rel-6 */
+} with {
+ variant (alpha) "PRESENCE(alpha_present = '1'B)"
+ variant (p0) "PRESENCE(p0_present = '1'B)"
+ variant (spare) "PRESENCE(p0_present = '1'B)"
+ variant (pr_mode) "PRESENCE(p0_present = '1'B)"
+};
+
+type record IaRestOctHL {
+ uint6_t freq_par_len,
+ BIT2 padding ('00'B) optional,
+ uint6_t maio optional,
+ octetstring mobile_allocation optional
+} with {
+ variant (freq_par_len) "LENGTHTO(mobile_allocation,maio,padding)"
+/*
+ variant (padding) "PRESENCE(freq_par_len != 0)"
+ variant (maio) "PRESENCE(freq_par_len != 0)"
+ variant (mobile_allocation) "PRESENCE(freq_par_len != 0)"
+*/
+};
+
+type record IaRestOctHH {
+ /* Packet Assignment discriminator:
+ * Packet Uplink / Downlink Assignment (0)
+ * Second Part Packet Assignment (1) */
+ BIT1 pa_disc,
+ PacketAssignUnion pa
+} with {
+ variant (pa) "CROSSTAG(spa, pa_disc = '1'B; uldl, pa_disc = '0'B)"
+};
+
+type union PacketAssignUnion {
+ SecondPartAssign spa,
+ PacketUlDlAssign uldl
+};
+
+type record SecondPartAssign {
+ BIT1 r99, /* L / H */
+ BIT1 presence optional,
+ BIT5 ext_ra optional
+} with {
+ variant (r99) "CSN.1 L/H"
+ variant (presence) "PRESENCE(r99 = '1'B)" /* H */
+ variant (ext_ra) "PRESENCE(presence = '1'B)"
+ /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
+ variant (ext_ra) "BYTEORDER(last)" // FIXME: should be first
+};
+
+type record PacketUlDlAssign {
+ BIT1 ass_disc,
+ PacketUlDlAssignUnion ass
+} with {
+ variant (ass) "CROSSTAG(dl, ass_disc = '1'B; ul, ass_disc = '0'B)"
+};
+
+type union PacketUlDlAssignUnion {
+ PacketUlAssign ul,
+ PacketDlAssign dl
+};
+
+type record PacketUlAssign {
+ BIT1 presence,
+ PacketUlAssignDyn dynamic optional,
+ PacketUlAssignSgl single optional
+ /* TODO: Estended RA, PFI */
+} with {
+ variant (dynamic) "PRESENCE(presence = '1'B)"
+ variant (single) "PRESENCE(presence = '0'B)"
+};
+
+type record PacketUlAssignDyn {
+ uint5_t tfi_assignment,
+ BIT1 polling,
+ BIT1 spare ('0'B),
+ uint3_t usf,
+ BIT1 usf_granularity,
+ BIT1 p0_present,
+ uint4_t p0 optional,
+ BIT1 pr_mode optional,
+ ChCodingCommand ch_coding_cmd,
+ BIT1 tlli_block_chan_coding,
+ BIT1 alpha_present,
+ uint4_t alpha optional,
+ uint5_t gamma,
+ BIT1 ta_index_present,
+ uint4_t ta_index optional,
+ BIT1 tbf_starting_time_present,
+ TbfStartingTime tbf_starting_time optional
+} with {
+ variant (p0) "PRESENCE(p0_present = '1'B)"
+ variant (pr_mode) "PRESENCE(p0_present = '1'B)"
+ variant (alpha) "PRESENCE(alpha_present = '1'B)"
+ variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
+ variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
+};
+
+type record PacketUlAssignSgl {
+ BIT1 alpha_present,
+ uint4_t alpha optional,
+ uint5_t gamma,
+ BIT2 padding ('01'B),
+ TbfStartingTime tbf_starting_time
+ /* TODO: P0 / PR_MODE */
+} with {
+ variant (alpha) "PRESENCE(alpha_present = '1'B)"
+};
+
+type record PacketDlAssign {
+ GprsTlli tlli,
+ BIT1 group1_present,
+ PacketDlAssG1 group1 optional,
+ BIT1 ta_index_present,
+ uint4_t ta_index optional,
+ BIT1 tbf_starting_time_present,
+ TbfStartingTime tbf_starting_time optional,
+ BIT1 p0_present,
+ uint4_t p0 optional,
+ BIT1 pr_mode optional
+ /* TODO: EGPRS window size, etc. */
+} with {
+ variant (group1) "PRESENCE(group1_present = '1'B)"
+ variant (ta_index) "PRESENCE(ta_index_present = '1'B)"
+ variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
+ variant (p0) "PRESENCE(p0_present = '1'B)"
+ variant (pr_mode) "PRESENCE(p0_present = '1'B)"
+};
+
+type record PacketDlAssG1 {
+ uint5_t tfi_assignment,
+ BIT1 rlc_mode,
+ BIT1 alpha_present,
+ uint4_t alpha optional,
+ uint5_t gamma,
+ BIT1 polling,
+ BIT1 ta_valid
+} with { variant "" };
+
+type record TbfStartingTime {
+ uint5_t t1,
+ uint6_t t3,
+ uint5_t t2
+};
+
+/* 10.5.2.17 IAR (Immediate Assignment Reject) Rest Octets */
+type record IARRestOctets {
+ ExtRAList ext_ra_list,
+ BIT1 rel13_ind, // L/H
+ uint3_t rcc optional
+ /* Addition in Rel-15: PEO IMM Cell Group Details struct */
+} with {
+ variant (rel13_ind) "CSN.1 L/H"
+ variant (rcc) "PRESENCE(rel13_ind = '1'B)"
+
+ /* The TITAN's RAW encoder generates an octet-aligned octetstring,
+ * so we should make sure that unused bits contain proper padding. */
+ variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
+};
+
+/* Optional extended RA: 0 | 1 < Extended RA 1 : bit (5) > */
+type record length(4) of ExtRAOpt ExtRAList;
+type record ExtRAOpt {
+ BIT1 presence, // L/H
+ BIT5 ext_ra optional
+} with {
+ variant (presence) "CSN.1 L/H"
+ variant (ext_ra) "PRESENCE(presence = '1'B)"
+ /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562488 */
+ variant (ext_ra) "BYTEORDER(last)"
+};
+
+template PacketDlAssign tr_PacketDlAssign(template GprsTlli tlli) := {
+ tlli := tlli,
+ group1_present := ?,
+ group1 := *,
+ ta_index_present := ?,
+ ta_index := *,
+ tbf_starting_time_present := ?,
+ tbf_starting_time := *,
+ p0_present := ?,
+ p0 := *,
+ pr_mode := *
+};
+
+template IaRestOctets tr_IaRestOctets_DLAss(template PacketDlAssign dl_ass) := {
+ presence := '11'B, /* HH */
+ ll := omit, lh := omit, hl := omit,
+ hh := {
+ pa_disc := '0'B, /* Packet Assignment (0) */
+ pa := {
+ uldl := {
+ ass_disc := '1'B, /* Downlink Assignment (1) */
+ ass := { dl := dl_ass }
+ }
+ }
+ }
+};
+
+template PacketUlAssign tr_PacketUlDynAssign(template uint5_t tfi := ?,
+ template BIT1 polling := ?,
+ template uint3_t usf := ?,
+ template BIT1 usf_granularity := ?,
+ template ChCodingCommand cs := ?) := {
+ presence := '1'B, /* Dynamic Block Allocation */
+ dynamic := {
+ tfi_assignment := tfi,
+ polling := polling,
+ spare := '0'B, /* Dynamic Block Allocation (mandatory after Rel-4) */
+ usf := usf,
+ usf_granularity := usf_granularity,
+ p0_present := ?,
+ p0 := *,
+ pr_mode := *,
+ ch_coding_cmd := cs,
+ tlli_block_chan_coding := ?,
+ alpha_present := ?,
+ alpha := *,
+ gamma := ?,
+ /* TODO: add to parameters */
+ ta_index_present := ?,
+ ta_index := *,
+ tbf_starting_time_present := ?,
+ tbf_starting_time := *
+ },
+ single := omit
+};
+
+template PacketUlAssign tr_PacketUlSglAssign := {
+ presence := '0'B, /* Single Block Allocation */
+ dynamic := omit,
+ single := {
+ alpha_present := ?,
+ alpha := *,
+ gamma := ?,
+ padding := '01'B,
+ tbf_starting_time := ?
+ }
+};
+
+template IaRestOctets tr_IaRestOctets_ULAss(template PacketUlAssign ul_ass) := {
+ presence := '11'B, /* HH */
+ ll := omit, lh := omit, hl := omit,
+ hh := {
+ pa_disc := '0'B, /* Packet Assignment (0) */
+ pa := {
+ uldl := {
+ ass_disc := '0'B, /* Uplink Assignment (0) */
+ ass := { ul := ul_ass }
+ }
+ }
+ }
+};
+
+template EgprsUlAss tr_EgprsUlAssDynamic(template (present) BIT5 ext_ra := ?,
+ template EgprsUlAssignDyn dyn_ass := ?) := {
+ ext_ra := ext_ra,
+ ats_present := ?,
+ ats := *,
+ presence := '1'B,
+ dynamic := dyn_ass,
+ multiblock := omit
+};
+template EgprsUlAss tr_EgprsUlAssMultiblock(template (present) BIT5 ext_ra := ?,
+ template EgprsUlAssignMultiblock mb_ass := ?) := {
+ ext_ra := ext_ra,
+ ats_present := ?,
+ ats := *,
+ presence := '0'B,
+ dynamic := omit,
+ multiblock := mb_ass
+};
+
+template IaRestOctets tr_IaRestOctets_EGPRSULAss(template EgprsUlAss ul_ass) := {
+ presence := '01'B, /* LH */
+ ll := omit,
+ lh := {
+ presence := '00'B,
+ egprs_ul := ul_ass,
+ multiblock_dl_ass := omit
+ },
+ hl := omit,
+ hh := omit
+};
+
+template IARRestOctets tr_IARRestOctets(template ExtRAList ext_ra_list := ?,
+ template uint3_t rcc := ?) := {
+ ext_ra_list := ext_ra_list,
+ rel13_ind := ?,
+ rcc := rcc ifpresent
+};
+
+template ExtRAOpt tr_ExtRAOpt(template BIT5 ext_ra := ?) := {
+ presence := '1'B, // L/H
+ ext_ra := ext_ra
+};
+
+
+external function enc_IaRestOctets(in IaRestOctets ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_IaRestOctets(in octetstring stream) return IaRestOctets
+ with { extension "prototype(convert) decode(RAW)" };
+
+external function enc_IARRestOctets(in IARRestOctets ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_IARRestOctets(in octetstring stream) return IARRestOctets
+ with { extension "prototype(convert) decode(RAW)" };
+
/* 10.5.2.33b SI 2quater Rest Octets */
type record SI2quaterRestOctets {
@@ -692,6 +1094,83 @@ type record SI4RestOctets {
variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
};
+/* 10.5.2.35a SI 6 Rest Octets */
+type record SI6RestOctets {
+ PchAndNchInfoOpt pch_nch_info,
+ VbsVgcsOptionsOpt vbs_vgcs_options,
+ BIT1 dtm_support, // L/H
+ uint8_t rac optional,
+ uint3_t max_lapdm optional,
+ BIT1 band_ind // L/H (DCS/PCS)
+ /* TODO: add more fields */
+} with {
+ variant (dtm_support) "CSN.1 L/H"
+ variant (rac) "PRESENCE(dtm_support = '1'B)"
+ variant (max_lapdm) "PRESENCE(dtm_support = '1'B)"
+ variant (band_ind) "CSN.1 L/H"
+
+ /* The TITAN's RAW encoder generates an octet-aligned octetstring,
+ * so we should make sure that unused bits contain proper padding. */
+ variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
+};
+
+/* Optional PCH and NCH info: L | H < PCH and NCH info > */
+type record PchAndNchInfoOpt {
+ BIT1 presence, // L/H
+ PchAndNchInfo info optional
+} with {
+ variant (presence) "CSN.1 L/H"
+ variant (info) "PRESENCE(presence = '1'B)"
+};
+
+/* PCH and NCH info */
+type record PchAndNchInfo {
+ BIT1 pag_chan_restruct,
+ uint2_t nln_sacch,
+ BIT1 call_prio_presence,
+ uint3_t call_prio optional,
+ BIT1 nln_status_sacch
+} with {
+ variant (call_prio) "PRESENCE(call_prio_presence = '1'B)"
+};
+
+/* Optional VBS/VGCS options: L | H < VBS/VGCS options > */
+type record VbsVgcsOptionsOpt {
+ BIT1 presence, // L/H
+ BIT2 options optional
+} with {
+ variant (presence) "CSN.1 L/H"
+ variant (options) "PRESENCE(presence = '1'B)"
+};
+
+/* 10.5.2.37b SI 13 Rest Octets (O & S) */
+type record SI13RestOctets {
+ BIT1 presence, // L/H
+ uint3_t bcch_change_mark,
+ BIT4 si_change_field,
+ BIT1 presence2,
+ BIT2 si13_change_mark optional,
+ GprsMobileAllocation gprs_ma optional,
+ BIT1 zero ('0'B), /* PBCCH not present in cell */
+ uint8_t rac,
+ BIT1 spgc_ccch_sup,
+ BIT3 priority_access_thr,
+ BIT2 network_control_order,
+ GprsCellOptions gprs_cell_opts,
+ GprsPowerControlParameters gprs_pwr_ctrl_params
+ /* TODO: Additions in release 99 */
+} with {
+
+ variant (presence) "CSN.1 L/H"
+ /* TODO: for all fields after presencte: variant (<field>) "PRESENCE(presence = '1'B)" */
+ variant (si13_change_mark) "PRESENCE(presence2 = '1'B)"
+ variant (gprs_ma) "PRESENCE(presence2 = '1'B)"
+
+ /* The TITAN's RAW encoder generates an octet-aligned octetstring,
+ * so we should make sure that unused bits contain proper padding. */
+ variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
+};
+
/* Selection Parameters */
type record SelectionParams {
boolean cbq,
@@ -762,6 +1241,125 @@ type record SI21IndicatorOpt {
};
+/* 10.5.2.44 SI10 rest octets (ASCI) */
+type record SI10RestOctets {
+ BIT1 ba_ind,
+ BIT1 neigh_info_presence, // L/H
+ SI10NeighInfo neigh_info optional
+} with {
+ variant (neigh_info_presence) "CSN.1 L/H"
+ variant (neigh_info) "PRESENCE(neigh_info_presence = '1'B)"
+
+ /* The TITAN's RAW encoder generates an octet-aligned octetstring,
+ * so we should make sure that unused bits contain proper padding. */
+ variant "PADDING(yes), PADDING_PATTERN('00101011'B)"
+};
+
+private type record SI10NeighInfo {
+ uint5_t first_freq,
+ SI10CellInfo cell_info,
+ SI10InfoFieldList info_field optional,
+ BIT1 info_field_term ('0'B) // L/H
+} with {
+ variant (info_field_term) "CSN.1 L/H"
+};
+
+private type record SI10CellInfo {
+ uint6_t bsic,
+ BIT1 cell_params_presence, // L/H
+ SI10CellParams cell_params optional
+} with {
+ variant (cell_params_presence) "CSN.1 L/H"
+ variant (cell_params) "PRESENCE(cell_params_presence = '1'B)"
+};
+
+private type record SI10CellParams {
+ BIT1 cell_barred, // L/H
+ SI10FurtherCellInfo further_cell_info optional
+} with {
+ variant (cell_barred) "CSN.1 L/H"
+ variant (further_cell_info) "PRESENCE(cell_barred = '0'B)"
+};
+
+private type record SI10FurtherCellInfo {
+ BIT1 la_different, // L/H
+ uint3_t cell_resel_hyst optional,
+ uint5_t ms_txpwr_max_cch,
+ uint6_t rxlev_access_min,
+ uint6_t cell_resel_offset,
+ uint3_t temp_offset,
+ uint5_t penalty_time
+} with {
+ variant (la_different) "CSN.1 L/H"
+ variant (cell_resel_hyst) "PRESENCE(la_different = '1'B)"
+};
+
+private type record of SI10InfoField SI10InfoFieldList;
+private type record SI10InfoField {
+ BIT1 item_ind ('1'B),
+ SI10NextFreqList next_freq optional,
+ BIT1 next_freq_term ('0'B), // L/H
+ SI10DiffCellInfo diff_cell_info
+} with {
+ variant (item_ind) "CSN.1 L/H"
+ variant "PRESENCE(item_ind = '1'B)"
+ variant (next_freq_term) "CSN.1 L/H"
+};
+
+private type record of SI10NextFreq SI10NextFreqList;
+private type BIT1 SI10NextFreq with { variant "CSN.1 L/H" };
+
+private type record SI10DiffCellInfo {
+ BIT1 bcc_or_bsic, // L/H
+ uint3_t bcc optional,
+ uint6_t bsic optional,
+ BIT1 diff_cell_params_presence, // L/H
+ SI10DiffCellParams diff_cell_params optional
+} with {
+ variant (bcc_or_bsic) "CSN.1 L/H"
+ variant (bcc) "PRESENCE(bcc_or_bsic = '1'B)"
+ variant (bsic) "PRESENCE(bcc_or_bsic = '0'B)"
+ variant (diff_cell_params_presence) "CSN.1 L/H"
+ variant (diff_cell_params) "PRESENCE(diff_cell_params_presence = '1'B)"
+};
+
+private type record SI10DiffCellParams {
+ BIT1 cell_barred, // L/H
+ SI10FurtherDiffCellInfo further_diff_cell_info optional
+} with {
+ variant (cell_barred) "CSN.1 L/H"
+ variant (further_diff_cell_info) "PRESENCE(cell_barred = '0'B)"
+};
+
+private type record SI10FurtherDiffCellInfo {
+ BIT1 la_different, // L/H
+ uint3_t cell_resel_hyst optional,
+ BIT1 ms_txpwr_max_cch_presence, // L/H
+ uint5_t ms_txpwr_max_cch optional,
+ BIT1 rxlev_access_min_presence, // L/H
+ uint6_t rxlev_access_min optional,
+ BIT1 cell_resel_offset_presence, // L/H
+ uint6_t cell_resel_offset optional,
+ BIT1 temp_offset_presence, // L/H
+ uint3_t temp_offset optional,
+ BIT1 penalty_time_presence, // L/H
+ uint5_t penalty_time optional
+} with {
+ variant (la_different) "CSN.1 L/H"
+ variant (cell_resel_hyst) "PRESENCE(la_different = '1'B)"
+ variant (ms_txpwr_max_cch_presence) "CSN.1 L/H"
+ variant (ms_txpwr_max_cch) "PRESENCE(ms_txpwr_max_cch_presence = '1'B)"
+ variant (rxlev_access_min_presence) "CSN.1 L/H"
+ variant (rxlev_access_min) "PRESENCE(rxlev_access_min_presence = '1'B)"
+ variant (cell_resel_offset_presence) "CSN.1 L/H"
+ variant (cell_resel_offset) "PRESENCE(cell_resel_offset_presence = '1'B)"
+ variant (temp_offset_presence) "CSN.1 L/H"
+ variant (temp_offset) "PRESENCE(temp_offset_presence = '1'B)"
+ variant (penalty_time_presence) "CSN.1 L/H"
+ variant (penalty_time) "PRESENCE(penalty_time_presence = '1'B)"
+};
+
+
external function enc_SI2quaterRestOctets(in SI2quaterRestOctets ro) return octetstring
with { extension "prototype(convert) encode(RAW)" };
external function dec_SI2quaterRestOctets(in octetstring stream) return SI2quaterRestOctets
@@ -777,6 +1375,21 @@ external function enc_SI4RestOctets(in SI4RestOctets ro) return octetstring
external function dec_SI4RestOctets(in octetstring stream) return SI4RestOctets
with { extension "prototype(convert) decode(RAW)" };
+external function enc_SI6RestOctets(in SI4RestOctets ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_SI6RestOctets(in octetstring stream) return SI6RestOctets
+ with { extension "prototype(convert) decode(RAW)" };
+
+external function enc_SI13RestOctets(in SI13RestOctets ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_SI13RestOctets(in octetstring stream) return SI13RestOctets
+ with { extension "prototype(convert) decode(RAW)" };
+
+external function enc_SI10RestOctets(in SI10RestOctets ro) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_SI10RestOctets(in octetstring stream) return SI10RestOctets
+ with { extension "prototype(convert) decode(RAW)" };
+
/* Basic templates to be extended in place */
template (value) SI3RestOctets ts_SI3RestOctets := {
diff --git a/library/GSM_SystemInformation.ttcn b/library/GSM_SystemInformation.ttcn
index 91135839..53c36c89 100644
--- a/library/GSM_SystemInformation.ttcn
+++ b/library/GSM_SystemInformation.ttcn
@@ -86,13 +86,6 @@ module GSM_SystemInformation {
template ControlChannelDescription t_ControlChannelDescription := { ?, ?, ?, ?, ?, ?, '00'B, ?, ? };
- /* 44.018 10.5.2.21 */
- type record MobileAllocationT {
- OCT1 iei,
- uint8_t len,
- bitstring ma
- } with { variant "" };
-
/* 44.018 10.5.2.22 */
type octetstring NeighbourCellDescription with { variant "FIELDLENGTH(16)" };
@@ -167,7 +160,7 @@ module GSM_SystemInformation {
rach_control := ?,
rest_octets := ?
};
-
+
/* 44.018 9.1.36 */
type record SystemInformationType4 {
@@ -175,7 +168,7 @@ module GSM_SystemInformation {
CellSelectionParameters cell_sel_par,
RachControlParameters rach_control,
ChannelDescriptionTV cbch_chan_desc optional,
- MobileAllocationT cbch_mobile_alloc optional,
+ MobileAllocationTLV cbch_mobile_alloc optional,
SI4RestOctets rest_octets /* see 10.5.2.35 */
} with { variant "TAG(cbch_chan_desc, iei = '64'O; cbch_mobile_alloc, iei = '72'O)" };
@@ -200,7 +193,12 @@ module GSM_SystemInformation {
LocationAreaIdentification lai,
CellOptionsSacch cell_options,
BIT8 ncc_permitted,
- RestOctets rest_octets length(0..7)
+ SI6RestOctets rest_octets
+ } with { variant "" };
+
+ /* 44.018 9.1.43a */
+ type record SystemInformationType13 {
+ SI13RestOctets rest_octets
} with { variant "" };
type union SystemInformationUnion {
@@ -215,6 +213,7 @@ module GSM_SystemInformation {
SystemInformationType5bis si5bis,
SystemInformationType5ter si5ter,
SystemInformationType6 si6,
+ SystemInformationType13 si13,
octetstring other
} with { variant "" };
@@ -232,6 +231,7 @@ module GSM_SystemInformation {
si5bis, header.message_type = SYSTEM_INFORMATION_TYPE_5bis;
si5ter, header.message_type = SYSTEM_INFORMATION_TYPE_5ter;
si6, header.message_type = SYSTEM_INFORMATION_TYPE_6;
+ si13, header.message_type = SYSTEM_INFORMATION_TYPE_13;
other, OTHERWISE;
)" };
diff --git a/library/GSM_Types.ttcn b/library/GSM_Types.ttcn
index ee6d1326..54c2e98d 100644
--- a/library/GSM_Types.ttcn
+++ b/library/GSM_Types.ttcn
@@ -12,224 +12,301 @@
module GSM_Types {
- import from General_Types all;
- import from Osmocom_Types all;
-
- type integer GsmArfcn (0..1023);
- type integer UmtsArfcn (0..16383);
- type integer UmtsScramblingCode (0..511);
- const integer GsmMaxFrameNumber := 26*51*2048;
- type integer GsmFrameNumber (0..GsmMaxFrameNumber);
- type integer GsmRxLev (0..63);
- type integer GsmTsc (0..7) with { variant "FIELDLENGTH(8)" };
- type uint32_t GsmTmsi;
- type OCT4 GprsTlli;
- type hexstring GsmMcc length(3);
- type hexstring GsmMnc length(2 .. 3);
- type uint16_t GsmLac;
- type uint16_t GsmCellId;
-
- type enumerated GprsCodingScheme {
- CS1, CS2, CS3, CS4
- };
-
- function f_gprs_blocksize(GprsCodingScheme cs) return integer {
- select (cs) {
- case (CS1) { return 22 }
- case (CS2) { return 32 }
- case (CS3) { return 38 }
- case (CS3) { return 52 }
- case else {
- setverdict(fail, "Invalid GPRS CS ", cs);
- mtc.stop;
- return -1;
- }
- }
- }
+import from General_Types all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
+
+type integer GsmArfcn (0..1023);
+type integer UmtsArfcn (0..16383);
+type integer UmtsScramblingCode (0..511);
+const integer GsmMaxFrameNumber := 26*51*2048;
+type integer GsmFrameNumber (0..GsmMaxFrameNumber);
+type integer GsmRxLev (0..63);
+type integer GsmTsc (0..7) with { variant "FIELDLENGTH(8)" };
+type uint32_t GsmTmsi;
+type OCT4 GprsTlli;
+type hexstring GsmMcc length(3);
+type hexstring GsmMnc length(2 .. 3);
+type uint16_t GsmLac;
+type uint16_t GsmCellId;
+type octetstring GroupCallRef length(1 .. 5);
+
+
+/* ARFCN with explicit band discrimination */
+type record GsmBandArfcn {
+ boolean pcs,
+ boolean uplink,
+ BIT4 spare,
+ GsmArfcn arfcn
+} with {
+ variant (arfcn) "BYTEORDER(last)"
+ variant (arfcn) "FIELDLENGTH(10)"
+};
- /* 10.5.2.8 */
- type enumerated ChannelNeeded {
- CHAN_NEED_ANY (0),
- CHAN_NEED_SDCCH (1),
- CHAN_NEED_TCH_F (2),
- CHAN_NEED_TCH_H (3)
- } with { variant "FIELDLENGTH(2)" };
- type record ChannelNeeded12 {
- ChannelNeeded second,
- ChannelNeeded first
- } with { variant "" };
-
-
- /* TS 48.058 9.3.1 Channel Number IE */
- type enumerated RslChanNr0 {
- RSL_CHAN_NR_INVALID ('00000'B),
- RSL_CHAN_NR_Bm_ACCH ('00001'B),
- RSL_CHAN_NR_BCCH ('10000'B),
- RSL_CHAN_NR_RACH ('10001'B),
- RSL_CHAN_NR_PCH_AGCH ('10010'B),
- RSL_CHAN_NR_OSMO_PDCH ('11000'B),
- RSL_CHAN_NR_OSMO_CBCH4 ('11001'B),
- RSL_CHAN_NR_OSMO_CBCH8 ('11010'B)
- } with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
-
- type record RslChanNr2 {
- BIT4 tag ('0001'B),
- uint1_t sub_chan
- } with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
-
- type record RslChanNr4 {
- BIT3 tag ('001'B),
- uint2_t sub_chan
- } with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
-
- type record RslChanNr8 {
- BIT2 tag ('01'B),
- uint3_t sub_chan
- } with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
-
- type union RslChanNrU {
- RslChanNr0 ch0,
- RslChanNr2 lm,
- RslChanNr4 sdcch4,
- RslChanNr8 sdcch8
- } with {
- variant "TAG(lm, tag = '0001'B;
- sdcch4, tag = '001'B;
- sdcch8, tag = '01'B;
- ch0, OTHERWISE)"
- variant "FIELDLENGTH(5)"
- variant "FIELDORDER(msb)"
- };
-
- type record RslChannelNr {
- RslChanNrU u,
- uint3_t tn
- } with { variant "FIELDLENGTH(8)" variant "FIELDORDER(msb)" };
-
- template RslChannelNr t_RslChanNr0(template uint3_t tn, template RslChanNr0 cht) := {
- u := { ch0 := cht },
- tn := tn
- }
+template (value) GsmBandArfcn
+ts_GsmBandArfcn(template (value) GsmArfcn arfcn,
+ template (value) boolean pcs := false,
+ template (value) boolean uplink := false) := {
+ pcs := pcs,
+ uplink := uplink,
+ spare := '0000'B,
+ arfcn := arfcn
+};
+template GsmBandArfcn
+tr_GsmBandArfcn(template (present) GsmArfcn arfcn,
+ template (present) boolean pcs := ?,
+ template (present) boolean uplink := ?) := {
+ pcs := pcs,
+ uplink := uplink,
+ spare := ?,
+ arfcn := arfcn
+};
- template RslChannelNr t_RslChanNr_RACH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_RACH);
- template RslChannelNr t_RslChanNr_BCCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_BCCH);
- template RslChannelNr t_RslChanNr_PCH_AGCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_PCH_AGCH);
- template RslChannelNr t_RslChanNr_Bm(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_Bm_ACCH);
- template RslChannelNr t_RslChanNr_PDCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_PDCH);
- template RslChannelNr t_RslChanNr_CBCH4(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH4);
- template RslChannelNr t_RslChanNr_CBCH8(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH8);
- template RslChannelNr t_RslChanNr_Lm(template uint3_t tn, template uint1_t sub_slot) := {
- u := { lm := { tag := '0001'B, sub_chan := sub_slot } },
- tn := tn
- }
- template RslChannelNr t_RslChanNr_SDCCH4(template uint3_t tn, template uint2_t sub_slot) := {
- u := { sdcch4 := { tag := '001'B, sub_chan := sub_slot } },
- tn := tn
- }
- template RslChannelNr t_RslChanNr_SDCCH8(template uint3_t tn, template uint3_t sub_slot) := {
- u := { sdcch8 := { tag := '01'B, sub_chan := sub_slot } },
- tn := tn
- }
+/* see enum 'gsm_phys_chan_config' in libosmocore */
+type enumerated PchanConfig {
+ GSM_PCHAN_NONE,
+ GSM_PCHAN_CCCH,
+ GSM_PCHAN_CCCH_SDCCH4,
+ GSM_PCHAN_CCCH_SDCCH4_CBCH,
+ GSM_PCHAN_SDCCH8,
+ GSM_PCHAN_SDCCH8_CBCH,
+ GSM_PCHAN_TCHF,
+ GSM_PCHAN_TCHH,
+ GSM_PCHAN_PDCH,
+ /* IPA style dynamic TCH/F+PDCH */
+ GSM_PCHAN_TCHF_PDCH,
+ /* Osmocom style dynamic TCH/H+TCH/F+PDCH */
+ GSM_PCHAN_TCHH_TCHF_PDCH
+};
- template (value) RslChannelNr ts_RslChanNr0(uint3_t tn, RslChanNr0 cht) := {
- u := { ch0 := cht },
- tn := tn
- }
- template (value) RslChannelNr ts_RslChanNr_RACH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_RACH);
- template (value) RslChannelNr ts_RslChanNr_BCCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_BCCH);
- template (value) RslChannelNr ts_RslChanNr_PCH_AGCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_PCH_AGCH);
- template (value) RslChannelNr ts_RslChanNr_Bm(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_Bm_ACCH);
- template (value) RslChannelNr ts_RslChanNr_PDCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_PDCH);
- template (value) RslChannelNr ts_RslChanNr_CBCH4(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH4);
- template (value) RslChannelNr ts_RslChanNr_CBCH8(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH8);
- template (value) RslChannelNr ts_RslChanNr_Lm(uint3_t tn, uint1_t sub_slot) := {
- u := { lm := { tag := '0001'B, sub_chan := sub_slot } },
- tn := tn
- }
- template (value) RslChannelNr ts_RslChanNr_SDCCH4(uint3_t tn, uint2_t sub_slot) := {
- u := { sdcch4 := { tag := '001'B, sub_chan := sub_slot } },
- tn := tn
+type enumerated GprsCodingScheme {
+ CS1, CS2, CS3, CS4
+};
+
+function f_gprs_blocksize(GprsCodingScheme cs) return integer {
+ select (cs) {
+ case (CS1) { return 22 }
+ case (CS2) { return 32 }
+ case (CS3) { return 38 }
+ case (CS3) { return 52 }
}
- template (value) RslChannelNr ts_RslChanNr_SDCCH8(uint3_t tn, uint3_t sub_slot) := {
- u := { sdcch8 := { tag := '01'B, sub_chan := sub_slot } },
- tn := tn
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Invalid GPRS CS ", cs));
+ return 0;
+}
+
+const GprsTlli TLLI_UNUSED := 'FFFFFFFF'O;
+function f_gen_tlli() return GprsTlli {
+ var GprsTlli tlli := f_rnd_octstring(4);
+ if (tlli == TLLI_UNUSED) {
+ tlli := 'EEEEEEEE'O;
}
+ return tlli;
+}
+
+/* 10.5.2.8 */
+type enumerated ChannelNeeded {
+ CHAN_NEED_ANY (0),
+ CHAN_NEED_SDCCH (1),
+ CHAN_NEED_TCH_F (2),
+ CHAN_NEED_TCH_H (3)
+} with { variant "FIELDLENGTH(2)" };
+type record ChannelNeeded12 {
+ ChannelNeeded second,
+ ChannelNeeded first
+} with { variant "" };
+
+
+/* TS 48.058 9.3.1 Channel Number IE */
+type enumerated RslChanNr0 {
+ RSL_CHAN_NR_INVALID ('00000'B),
+ RSL_CHAN_NR_Bm_ACCH ('00001'B),
+ RSL_CHAN_NR_BCCH ('10000'B),
+ RSL_CHAN_NR_RACH ('10001'B),
+ RSL_CHAN_NR_PCH_AGCH ('10010'B),
+ RSL_CHAN_NR_OSMO_PDCH ('11000'B),
+ RSL_CHAN_NR_OSMO_CBCH4 ('11001'B),
+ RSL_CHAN_NR_OSMO_CBCH8 ('11010'B),
+ RSL_CHAN_NR_OSMO_VAMOS_Bm_ACCH ('11101'B)
+} with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
+
+type record RslChanNr2 {
+ BIT4 tag ('0001'B, '1111'B),
+ uint1_t sub_chan
+} with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
+
+type record RslChanNr4 {
+ BIT3 tag ('001'B),
+ uint2_t sub_chan
+} with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
+
+type record RslChanNr8 {
+ BIT2 tag ('01'B),
+ uint3_t sub_chan
+} with { variant "FIELDLENGTH(5)" variant "FIELDORDER(msb)" };
+
+type union RslChanNrU {
+ RslChanNr0 ch0,
+ RslChanNr2 lm,
+ RslChanNr4 sdcch4,
+ RslChanNr8 sdcch8
+} with {
+ variant "TAG(lm, tag = '0001'B;
+ lm, tag = '1111'B;
+ sdcch4, tag = '001'B;
+ sdcch8, tag = '01'B;
+ ch0, OTHERWISE)"
+ variant "FIELDLENGTH(5)"
+ variant "FIELDORDER(msb)"
+};
+
+type record RslChannelNr {
+ RslChanNrU u,
+ uint3_t tn
+} with { variant "FIELDLENGTH(8)" variant "FIELDORDER(msb)" };
+
+template RslChannelNr t_RslChanNr0(template uint3_t tn, template RslChanNr0 cht) := {
+ u := { ch0 := cht },
+ tn := tn
+}
+
+template RslChannelNr t_RslChanNr_RACH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_RACH);
+template RslChannelNr t_RslChanNr_BCCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_BCCH);
+template RslChannelNr t_RslChanNr_PCH_AGCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_PCH_AGCH);
+template RslChannelNr t_RslChanNr_Bm(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_Bm_ACCH);
+template RslChannelNr t_RslChanNr_PDCH(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_PDCH);
+template RslChannelNr t_RslChanNr_CBCH4(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH4);
+template RslChannelNr t_RslChanNr_CBCH8(template uint3_t tn) := t_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH8);
+template RslChannelNr t_RslChanNr_Lm(template uint3_t tn, template uint1_t sub_slot) := {
+ u := { lm := { tag := '0001'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template RslChannelNr t_RslChanNr_SDCCH4(template uint3_t tn, template uint2_t sub_slot) := {
+ u := { sdcch4 := { tag := '001'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template RslChannelNr t_RslChanNr_SDCCH8(template uint3_t tn, template uint3_t sub_slot) := {
+ u := { sdcch8 := { tag := '01'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template RslChannelNr t_RslChanNr_Osmo_VAMOS_Bm(template uint3_t tn) := {
+ u := { ch0 := RSL_CHAN_NR_OSMO_VAMOS_Bm_ACCH },
+ tn := tn
+}
+
+template RslChannelNr t_RslChanNr_Osmo_VAMOS_Lm(template uint3_t tn, template uint1_t sub_slot) := {
+ u := { lm := { tag := '1111'B, sub_chan := sub_slot } },
+ tn := tn
+}
+
+template (value) RslChannelNr ts_RslChanNr0(uint3_t tn, RslChanNr0 cht) := {
+ u := { ch0 := cht },
+ tn := tn
+}
+template (value) RslChannelNr ts_RslChanNr_RACH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_RACH);
+template (value) RslChannelNr ts_RslChanNr_BCCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_BCCH);
+template (value) RslChannelNr ts_RslChanNr_PCH_AGCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_PCH_AGCH);
+template (value) RslChannelNr ts_RslChanNr_Bm(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_Bm_ACCH);
+template (value) RslChannelNr ts_RslChanNr_PDCH(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_PDCH);
+template (value) RslChannelNr ts_RslChanNr_CBCH4(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH4);
+template (value) RslChannelNr ts_RslChanNr_CBCH8(uint3_t tn) := ts_RslChanNr0(tn, RSL_CHAN_NR_OSMO_CBCH8);
+template (value) RslChannelNr ts_RslChanNr_Lm(uint3_t tn, uint1_t sub_slot) := {
+ u := { lm := { tag := '0001'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template (value) RslChannelNr ts_RslChanNr_SDCCH4(uint3_t tn, uint2_t sub_slot) := {
+ u := { sdcch4 := { tag := '001'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template (value) RslChannelNr ts_RslChanNr_SDCCH8(uint3_t tn, uint3_t sub_slot) := {
+ u := { sdcch8 := { tag := '01'B, sub_chan := sub_slot } },
+ tn := tn
+}
+template (value) RslChannelNr ts_RslChanNr_Osmo_VAMOS_Bm(uint3_t tn) := {
+ u := { ch0 := RSL_CHAN_NR_OSMO_VAMOS_Bm_ACCH },
+ tn := tn
+}
+template (value) RslChannelNr ts_RslChanNr_Osmo_VAMOS_Lm(uint3_t tn, uint1_t sub_slot) := {
+ u := { lm := { tag := '1111'B, sub_chan := sub_slot } },
+ tn := tn
+}
+
+
+/* TS 48.058 9.3.2 Link ID */
+type enumerated RslLinkIdC {
+ FACCH_SDCCH (0),
+ SACCH (1),
+ OSMO_PTCCH (2) /* Osmocom (trxcon) specific extension */
+} with { variant "FIELDLENGTH(2)" };
+
+type enumerated RslSapi0Prio {
+ SAPI0_PRIO_NORMAL (0),
+ SAPI0_PRIO_HIGH (1),
+ SAPI0_PRIO_LOW (2)
+} with { variant "FIELDLENGTH(2)" };
+
+type uint3_t GsmSapi;
+
+type record RslLinkId {
+ RslLinkIdC c,
+ boolean na,
+ RslSapi0Prio prio,
+ GsmSapi sapi
+} with { variant "" };
+
+template RslLinkId tr_RslLinkId := {
+ c := ?,
+ na := ?,
+ prio := ?,
+ sapi := ?
+};
- /* TS 48.058 9.3.2 Link ID */
- type enumerated RslLinkIdC {
- FACCH_SDCCH (0),
- SACCH (1),
- OSMO_PTCCH (2) /* Osmocom (trxcon) specific extension */
- } with { variant "FIELDLENGTH(2)" };
-
- type enumerated RslSapi0Prio {
- SAPI0_PRIO_NORMAL (0),
- SAPI0_PRIO_HIGH (1),
- SAPI0_PRIO_LOW (2)
- } with { variant "FIELDLENGTH(2)" };
-
- type uint3_t GsmSapi;
-
- type record RslLinkId {
- RslLinkIdC c,
- boolean na,
- RslSapi0Prio prio,
- GsmSapi sapi
- } with { variant "" };
-
- template RslLinkId tr_RslLinkId := {
- c := ?,
- na := ?,
- prio := ?,
- sapi := ?
- };
-
- template RslLinkId tr_RslLinkID_DCCH(template GsmSapi sapi) modifies tr_RslLinkId := {
- c := FACCH_SDCCH,
- na := false,
- sapi := sapi
- };
-
- template RslLinkId tr_RslLinkID_SACCH(template GsmSapi sapi) modifies tr_RslLinkId := {
- c := SACCH,
- na := false,
- sapi := sapi
- };
-
- template RslLinkId tr_RslLinkID_OSMO_PTCCH(template GsmSapi sapi) modifies tr_RslLinkId := {
- c := OSMO_PTCCH,
- na := false,
- sapi := sapi
- };
-
- template (value) RslLinkId ts_RslLinkID_DCCH(GsmSapi sapi) := {
- c := FACCH_SDCCH,
- na := false,
- prio := SAPI0_PRIO_NORMAL,
- sapi := sapi
- };
-
- template (value) RslLinkId ts_RslLinkID_SACCH(GsmSapi sapi) := {
- c := SACCH,
- na := false,
- prio := SAPI0_PRIO_NORMAL,
- sapi := sapi
- };
-
- template (value) RslLinkId ts_RslLinkID_OSMO_PTCCH(GsmSapi sapi) := {
- c := OSMO_PTCCH,
- na := false,
- prio := SAPI0_PRIO_NORMAL,
- sapi := sapi
- };
-
- function f_hex_is_odd_length(hexstring digits) return bitstring {
- if (lengthof(digits) rem 2 == 1) {
- return '1'B;
- } else {
- return '0'B;
- }
+template RslLinkId tr_RslLinkID_DCCH(template GsmSapi sapi) modifies tr_RslLinkId := {
+ c := FACCH_SDCCH,
+ na := false,
+ sapi := sapi
+};
+
+template RslLinkId tr_RslLinkID_SACCH(template GsmSapi sapi) modifies tr_RslLinkId := {
+ c := SACCH,
+ na := false,
+ sapi := sapi
+};
+
+template RslLinkId tr_RslLinkID_OSMO_PTCCH(template GsmSapi sapi) modifies tr_RslLinkId := {
+ c := OSMO_PTCCH,
+ na := false,
+ sapi := sapi
+};
+
+template (value) RslLinkId ts_RslLinkID_DCCH(GsmSapi sapi) := {
+ c := FACCH_SDCCH,
+ na := false,
+ prio := SAPI0_PRIO_NORMAL,
+ sapi := sapi
+};
+
+template (value) RslLinkId ts_RslLinkID_SACCH(GsmSapi sapi) := {
+ c := SACCH,
+ na := false,
+ prio := SAPI0_PRIO_NORMAL,
+ sapi := sapi
+};
+
+template (value) RslLinkId ts_RslLinkID_OSMO_PTCCH(GsmSapi sapi) := {
+ c := OSMO_PTCCH,
+ na := false,
+ prio := SAPI0_PRIO_NORMAL,
+ sapi := sapi
+};
+
+function f_hex_is_odd_length(hexstring digits) return bitstring {
+ if (lengthof(digits) rem 2 == 1) {
+ return '1'B;
+ } else {
+ return '0'B;
}
+}
/* TS 04.12 Section 3.3.1 Block type */
@@ -357,5 +434,89 @@ function f_gsm_compute_tc(integer fn) return integer {
return (fn / 51) mod 8;
}
+type hexstring GsmBcdString with { variant "HEXORDER(low)" };
+type GsmBcdString BcdMccMnc with { variant "FIELDLENGTH(6)" };
+
+/* hex2oct()/oct2hex() do not respect the HEXORDER/FIELDLENGTH attributes,
+ * so better use the functions, employing TITAN's RAW codec, dclared below. */
+external function enc_BcdMccMnc(in BcdMccMnc str) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_BcdMccMnc(in octetstring str) return BcdMccMnc
+ with { extension "prototype(convert) decode(RAW)" };
+
+/* Compute BcdMccMnc from a pair of GsmMcc/GsmMnc values */
+function f_build_BcdMccMnc(GsmMcc mcc, GsmMnc mnc) return BcdMccMnc {
+ if (lengthof(mnc) == 2) {
+ mnc := mnc[0] & mnc[1] & 'F'H;
+ }
+ /* 3GPP TS 24.008, Figure 10.5.13
+ * | MCC digit 2 | MCC digit 1 | octet 1
+ * | MNC digit 3 | MCC digit 3 | octet 2
+ * | MNC digit 2 | MNC digit 1 | octet 3
+ *
+ * NOTE: TITAN takes care of swapping the nibbles in octets,
+ * so we use the normal (low-to-high) ordering here. */
+ return mcc[0] & mcc[1] & mcc[2] & mnc[2] & mnc[0] & mnc[1];
+}
+
+/* Compute BcdMccMnc from integer values */
+function f_build_BcdMccMnc_int(uint16_t mcc, uint16_t mnc, boolean mnc_3_digits) return BcdMccMnc {
+ var hexstring mcc_str := str2hex(int2str(mcc));
+ var hexstring mnc_str := str2hex(int2str(mnc));
+ if (mnc_3_digits == true) {
+ return f_build_BcdMccMnc(mcc_str[0] & mcc_str[1] & mcc_str[2],
+ mnc_str[0] & mnc_str[1] & mnc_str[2]);
+ } else {
+ return f_build_BcdMccMnc(mcc_str[0] & mcc_str[1] & mcc_str[2],
+ mnc_str[0] & mnc_str[1]);
+ }
+}
+
+testcase TC_selftest_BcdMccMnc() runs on Dummy_CT {
+ if (not match('62F224'O, decmatch BcdMccMnc:'262F42'H)) { setverdict(fail); }
+ if (not match('21F354'O, decmatch BcdMccMnc:'123F45'H)) { setverdict(fail); }
+ if (not match('216354'O, decmatch BcdMccMnc:'123645'H)) { setverdict(fail); }
+
+ if (not match(enc_BcdMccMnc('262F42'H), '62F224'O)) { setverdict(fail); }
+ if (not match(enc_BcdMccMnc('123F45'H), '21F354'O)) { setverdict(fail); }
+ if (not match(enc_BcdMccMnc('123645'H), '216354'O)) { setverdict(fail); }
+
+ if (not match(f_build_BcdMccMnc('262'H, '42'H), BcdMccMnc:'262F42'H)) { setverdict(fail); }
+ if (not match(f_build_BcdMccMnc('123'H, '45'H), BcdMccMnc:'123F45'H)) { setverdict(fail); }
+ if (not match(f_build_BcdMccMnc('123'H, '456'H), BcdMccMnc:'123645'H)) { setverdict(fail); }
+
+ if (not match(f_build_BcdMccMnc_int(262, 42, false), BcdMccMnc:'262F42'H)) { setverdict(fail); }
+ if (not match(f_build_BcdMccMnc_int(123, 45, false), BcdMccMnc:'123F45'H)) { setverdict(fail); }
+ if (not match(f_build_BcdMccMnc_int(123, 456, true), BcdMccMnc:'123645'H)) { setverdict(fail); }
+
+ setverdict(pass);
+}
+
+/* 24.008 10.5.1.3 */
+type record LocationAreaIdentification {
+ BcdMccMnc mcc_mnc,
+ uint16_t lac
+} with { variant "" };
+template (value) LocationAreaIdentification ts_LAI(BcdMccMnc mcc_mnc, uint16_t lac) := {
+ mcc_mnc := mcc_mnc,
+ lac := lac
+};
+
+/* 24.008 10.5.5.15 */
+type record RoutingAreaIdentification {
+ LocationAreaIdentification lai,
+ uint8_t rac
+} with { variant "" };
+template (value) RoutingAreaIdentification ts_RAI(template (value) LocationAreaIdentification lai, uint8_t rac) := {
+ lai := lai,
+ rac := rac
+};
+
+external function enc_RoutingAreaIdentification(RoutingAreaIdentification rai) return octetstring
+with { extension "prototype(convert)" extension "encode(RAW)" }
+
+/* TS 24.008 10.5.1.1 */
+type uint16_t CellIdentity;
+
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/GSUP_Emulation.ttcn b/library/GSUP_Emulation.ttcn
index 51c158a5..4f7e5d65 100644
--- a/library/GSUP_Emulation.ttcn
+++ b/library/GSUP_Emulation.ttcn
@@ -60,11 +60,10 @@ type component GSUP_Emulation_CT {
/* GSUP port to the per-connection clients */
port GSUP_Conn_PT GSUP_CLIENT;
- /* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
- var ConnectionData GsupImsiTable[16];
+ var ConnectionData GsupImsiTable[256];
/* pending expected incoming connections */
- var ExpectData GsupExpectTable[16];
+ var ExpectData GsupExpectTable[256];
/* procedure based port to register for incoming connections */
port GSUPEM_PROC_PT GSUP_PROC;
};
@@ -217,9 +216,24 @@ function main(GsupOps ops, charstring id) runs on GSUP_Emulation_CT {
/* Client -> us: procedure call to register expect */
- [] GSUP_PROC.getcall(GSUPEM_register:{?,?}) -> param(imsi, vc_hdlr) {
+ [] GSUP_PROC.getcall(GSUPEM_register_expect:{?,?}) -> param(imsi, vc_hdlr) {
f_create_expect(imsi, vc_hdlr);
- GSUP_PROC.reply(GSUPEM_register:{imsi, vc_hdlr}) to vc_hdlr;
+ GSUP_PROC.reply(GSUPEM_register_expect:{imsi, vc_hdlr}) to vc_hdlr;
+ }
+ /* Client -> us: procedure call to unregister expect */
+ [] GSUP_PROC.getcall(GSUPEM_unregister_expect:{?,?}) -> param(imsi, vc_hdlr) {
+ f_destroy_expect(imsi, vc_hdlr);
+ GSUP_PROC.reply(GSUPEM_unregister_expect:{imsi, vc_hdlr}) to vc_hdlr;
+ }
+
+ [] GSUP_PROC.getcall(GSUPEM_unregister_connhdlr:{?}) -> param(imsi) sender vc_hdlr {
+ f_imsi_table_del(imsi);
+ GSUP_PROC.reply(GSUPEM_unregister_connhdlr:{imsi}) to vc_hdlr;
+ }
+ [] GSUP_PROC.getcall(GSUPEM_change_connhdlr:{?,?}) -> param(imsi, vc_hdlr) {
+ f_imsi_table_del(imsi);
+ f_imsi_table_add(vc_hdlr, imsi);
+ GSUP_PROC.reply(GSUPEM_change_connhdlr:{imsi, vc_hdlr}) to vc_hdlr;
}
}
@@ -239,10 +253,14 @@ type record ExpectData {
}
/* procedure based port to register for incoming calls */
-signature GSUPEM_register(in charstring imsi, in GSUP_ConnHdlr hdlr);
+signature GSUPEM_register_expect(in charstring imsi, in GSUP_ConnHdlr hdlr);
+signature GSUPEM_unregister_expect(in charstring imsi, in GSUP_ConnHdlr hdlr);
+signature GSUPEM_unregister_connhdlr(in charstring imsi);
+signature GSUPEM_change_connhdlr(in charstring imsi, in GSUP_ConnHdlr hdlr);
type port GSUPEM_PROC_PT procedure {
- inout GSUPEM_register;
+ inout GSUPEM_register_expect, GSUPEM_unregister_expect,
+ GSUPEM_unregister_connhdlr, GSUPEM_change_connhdlr;
} with { extension "internal" };
/* CreateCallback that can be used as create_cb and will use the expectation table */
@@ -288,17 +306,52 @@ runs on GSUP_Emulation_CT {
testcase.stop("No space left in GsupExpectTable");
}
+/* server/emulation side function to destroy expect */
+private function f_destroy_expect(charstring imsi, GSUP_ConnHdlr hdlr)
+runs on GSUP_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(GsupExpectTable); i := i+1) {
+ if (GsupExpectTable[i].imsi == imsi and GsupExpectTable[i].vc_conn == hdlr) {
+ GsupExpectTable[i].imsi := omit;
+ GsupExpectTable[i].vc_conn := null;
+ log("Destroyed GsupExpect[", i, "] for ", imsi, " to be handled at ", hdlr);
+ return;
+ }
+ }
+ testcase.stop("No matching expect found to be destoyed");
+}
+
/* client/conn_hdlr side function to use procedure port to create expect in emulation */
function f_create_gsup_expect(charstring imsi) runs on GSUP_ConnHdlr {
- GSUP_PROC.call(GSUPEM_register:{imsi, self}) {
- [] GSUP_PROC.getreply(GSUPEM_register:{?,?}) {};
+ GSUP_PROC.call(GSUPEM_register_expect:{imsi, self}) {
+ [] GSUP_PROC.getreply(GSUPEM_register_expect:{?,?}) {};
+ }
+}
+
+function f_destroy_gsup_expect(charstring imsi) runs on GSUP_ConnHdlr {
+ GSUP_PROC.call(GSUPEM_unregister_expect:{imsi, self}) {
+ [] GSUP_PROC.getreply(GSUPEM_unregister_expect:{?,?}) {};
+ }
+}
+
+function f_unregister_gsup_imsi(charstring imsi) runs on GSUP_ConnHdlr {
+ GSUP_PROC.call(GSUPEM_unregister_connhdlr:{imsi}) {
+ [] GSUP_PROC.getreply(GSUPEM_unregister_connhdlr:{?}) {};
}
}
+
+
/* Same as f_create_gsup_expect, but with explicit addressing. Needed when connecting multiple ports to GSUP_PROC. */
function f_create_gsup_expect_explicit(charstring imsi, GSUP_Emulation_CT ct) runs on GSUP_ConnHdlr {
- GSUP_PROC.call(GSUPEM_register:{imsi, self}) to ct {
- [] GSUP_PROC.getreply(GSUPEM_register:{?,?}) {};
+ GSUP_PROC.call(GSUPEM_register_expect:{imsi, self}) to ct {
+ [] GSUP_PROC.getreply(GSUPEM_register_expect:{?,?}) {};
+ }
+}
+
+function f_gsup_change_connhdlr(charstring imsi) runs on GSUP_ConnHdlr {
+ GSUP_PROC.call(GSUPEM_change_connhdlr:{imsi, self}) {
+ [] GSUP_PROC.getreply(GSUPEM_change_connhdlr:{?,?}) {};
}
}
diff --git a/library/GSUP_Templates.ttcn b/library/GSUP_Templates.ttcn
new file mode 100644
index 00000000..403af743
--- /dev/null
+++ b/library/GSUP_Templates.ttcn
@@ -0,0 +1,1845 @@
+module GSUP_Templates {
+
+/* GSUP_Templates, defining TTCN-3 templates for the GSUP protocol.
+ *
+ * GSUP is a non-standard protocol used between OsmoMSC/OsmoSGSN and OsmoHLR
+ * in order to replace the complex TCAP/MAP protocol.
+ *
+ * (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from PCO_Types all;
+import from GSUP_Types all;
+
+function f_gsup_postprocess_decoded(inout GSUP_PDU gsup) {
+ if (gsup.ies[0].tag == OSMO_GSUP_IMSI_IE) {
+ /* if last digit is 'F', then there's an odd number of digits and we must strip the F */
+ var integer num_digits := lengthof(gsup.ies[0].val.imsi);
+ if (gsup.ies[0].val.imsi[num_digits-1] == 'F'H) {
+ gsup.ies[0].val.imsi := substr(gsup.ies[0].val.imsi, 0, num_digits-1);
+ }
+ }
+}
+
+function f_gsup_preprocess_encoded(inout GSUP_PDU gsup) {
+ if (ischosen(gsup.ies[0].val.imsi)) {
+ /* if number of digits is odd, add a 'F' as padding at the end */
+ var integer num_digits := lengthof(gsup.ies[0].val.imsi);
+ if (num_digits rem 2 == 1) {
+ gsup.ies[0].val.imsi := gsup.ies[0].val.imsi & 'F'H;
+ }
+ }
+}
+
+template (value) GSUP_MSISDN ts_GSUP_MSISDN(hexstring digits,
+ BIT3 ton := '000'B,
+ BIT4 npi := '0000'B) := {
+ len := 0, /* overwritten */
+ /* numberingPlanIdentification := npi,
+ typeOfNumber := ton,
+ ext1 := '0'B, */
+ digits := digits
+}
+
+template GSUP_MSISDN tr_GSUP_MSISDN(template hexstring digits,
+ template BIT3 ton := ?,
+ template BIT4 npi := ?) := {
+ len := ?,
+ /* numberingPlanIdentification := npi,
+ typeOfNumber := ton,
+ ext1 := '0'B, */
+ digits := digits
+}
+
+template (value) GSUP_PDP_Address ts_GSUP_PDP_Address_IPv4(template (omit) OCT4 ip_addr) := {
+ ipv4 := {
+ spare := '1111'B,
+ pdp_typeorg := '0001'B,
+ pdp_typenum := '21'O,
+ ipv4_address := ip_addr
+ }
+}
+template (value) GSUP_PDP_Address ts_EuaIPv4Dyn := ts_GSUP_PDP_Address_IPv4(omit);
+
+template (present) GSUP_PDP_Address tr_GSUP_PDP_Address_IPv4(template OCT4 ip_addr) := {
+ ipv4 := {
+ spare := ?,
+ pdp_typeorg := '0001'B,
+ pdp_typenum := '21'O,
+ ipv4_address := ip_addr
+ }
+}
+
+template GSUP_IE ts_GSUP_IE_AuthTuple2G(octetstring rand, octetstring sres,
+ octetstring kc) := {
+ tag := OSMO_GSUP_AUTH_TUPLE_IE,
+ len := 0, /* overwritten */
+ val := {
+ auth_tuple := {
+ valueof(ts_GSUP_IE_RAND(rand)),
+ valueof(ts_GSUP_IE_SRES(sres)),
+ valueof(ts_GSUP_IE_Kc(kc))
+ }
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_AuthTuple3G(
+ template (present) octetstring rand := ?,
+ template (present) octetstring ik := ?,
+ template (present) octetstring ck := ?,
+ template (present) octetstring autn := ?,
+ template (present) octetstring res := ?) := {
+ tag := OSMO_GSUP_AUTH_TUPLE_IE,
+ len := ?,
+ val := {
+ auth_tuple := {
+ tr_GSUP_IE_RAND(rand),
+ tr_GSUP_IE_IK(ik),
+ tr_GSUP_IE_CK(ck),
+ tr_GSUP_IE_AUTN(autn),
+ tr_GSUP_IE_RES(res)
+ }
+ }
+}
+
+template GSUP_IE ts_GSUP_IE_AuthTuple3G(octetstring rand, octetstring ik,
+ octetstring ck, octetstring autn,
+ octetstring res) := {
+ tag := OSMO_GSUP_AUTH_TUPLE_IE,
+ len := 0, /* overwritten */
+ val := {
+ auth_tuple := {
+ valueof(ts_GSUP_IE_RAND(rand)),
+ valueof(ts_GSUP_IE_IK(ik)),
+ valueof(ts_GSUP_IE_CK(ck)),
+ valueof(ts_GSUP_IE_AUTN(autn)),
+ valueof(ts_GSUP_IE_RES(res))
+ }
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_AuthTuple2G3G(
+ template (present) octetstring rand := ?,
+ template (present) octetstring sres := ?,
+ template (present) octetstring kc := ?,
+ template (present) octetstring ik := ?,
+ template (present) octetstring ck := ?,
+ template (present) octetstring autn := ?,
+ template (present) octetstring res := ?) := {
+ tag := OSMO_GSUP_AUTH_TUPLE_IE,
+ len := ?,
+ val := {
+ auth_tuple := {
+ tr_GSUP_IE_RAND(rand),
+ tr_GSUP_IE_SRES(sres),
+ tr_GSUP_IE_Kc(kc),
+ tr_GSUP_IE_IK(ik),
+ tr_GSUP_IE_CK(ck),
+ tr_GSUP_IE_AUTN(autn),
+ tr_GSUP_IE_RES(res)
+ }
+ }
+}
+
+template GSUP_IE ts_GSUP_IE_AuthTuple2G3G(octetstring rand, octetstring sres,
+ octetstring kc, octetstring ik,
+ octetstring ck, octetstring autn,
+ octetstring res) := {
+ tag := OSMO_GSUP_AUTH_TUPLE_IE,
+ len := 0, /* overwritten */
+ val := {
+ auth_tuple := {
+ valueof(ts_GSUP_IE_RAND(rand)),
+ valueof(ts_GSUP_IE_SRES(sres)),
+ valueof(ts_GSUP_IE_Kc(kc)),
+ valueof(ts_GSUP_IE_IK(ik)),
+ valueof(ts_GSUP_IE_CK(ck)),
+ valueof(ts_GSUP_IE_AUTN(autn)),
+ valueof(ts_GSUP_IE_RES(res))
+ }
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PdpInfoCompl := {
+ tag := OSMO_GSUP_PDP_INFO_COMPL_IE,
+ len := 0, /* overwritten */
+ val := {
+ pdp_info_compl := ''O
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PdpInfoCompl := {
+ tag := OSMO_GSUP_PDP_INFO_COMPL_IE,
+ len := 0, /* overwritten */
+ val := {
+ pdp_info_compl := ''O
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PdpInfo(template (value) OCT1 ctx_id,
+ template (value) octetstring apn,
+ template (value) GSUP_PDP_Address pdp_address,
+ template (value) octetstring pdp_qos) := {
+ tag := OSMO_GSUP_PDP_INFO_IE,
+ len := 0, /* overwritten */
+ val := {
+ pdp_info := {
+ valueof(ts_GSUP_IE_PDP_CONTEXT_ID(ctx_id)),
+ valueof(ts_GSUP_IE_PDP_ADDRESS(pdp_address)),
+ valueof(ts_GSUP_IE_APN(apn)),
+ valueof(ts_GSUP_IE_PDP_QOS(pdp_qos))
+ }
+ }
+}
+template (value) GSUP_IE ts_GSUP_IE_PdpInfo_ie(template (value) GSUP_IEs pdp_info) := {
+ tag := OSMO_GSUP_PDP_INFO_IE,
+ len := 0, /* overwritten */
+ val := {
+ pdp_info := pdp_info
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PdpInfo(template (present) OCT1 ctx_id,
+ template (present) octetstring apn,
+ template (present) GSUP_PDP_Address pdp_address) := {
+ tag := OSMO_GSUP_PDP_INFO_IE,
+ len := ?,
+ val := {
+ pdp_info := {
+ tr_GSUP_IE_PDP_CONTEXT_ID(ctx_id),
+ tr_GSUP_IE_PDP_ADDRESS(pdp_address),
+ tr_GSUP_IE_APN(apn)
+ }
+ }
+}
+template (present) GSUP_IE tr_GSUP_IE_PdpInfo_ie(template (present) GSUP_IEs pdp_info := ?) := {
+ tag := OSMO_GSUP_PDP_INFO_IE,
+ len := ?,
+ val := {
+ pdp_info := pdp_info
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PDP_CONTEXT_ID(template (value) OCT1 ctx_id) := {
+ tag := OSMO_GSUP_PDP_CONTEXT_ID_IE,
+ len := 0,
+ val := {
+ pdp_ctx_id := ctx_id
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PDP_CONTEXT_ID(template OCT1 ctx_id) := {
+ tag := OSMO_GSUP_PDP_CONTEXT_ID_IE,
+ len := ?,
+ val := {
+ pdp_ctx_id := ctx_id
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PDP_ADDRESS(template (value) GSUP_PDP_Address pdp_address) := {
+ tag := OSMO_GSUP_PDP_ADDRESS_IE,
+ len := 0,
+ val := {
+ pdp_address := pdp_address
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PDP_ADDRESS(template (present) GSUP_PDP_Address pdp_address := ?) := {
+ tag := OSMO_GSUP_PDP_ADDRESS_IE,
+ len := ?,
+ val := {
+ pdp_address := pdp_address
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PDP_QOS(template (value) octetstring pdp_qos) := {
+ tag := OSMO_GSUP_PDP_QOS_IE,
+ len := 0,
+ val := {
+ pdp_qos := pdp_qos
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PDP_QOS(template (present) octetstring pdp_qos := ?) := {
+ tag := OSMO_GSUP_PDP_QOS_IE,
+ len := ?,
+ val := {
+ pdp_qos := pdp_qos
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Charging_Characteristics(template (value) octetstring charg_char) := {
+ tag := OSMO_GSUP_CHARG_CHAR_IE,
+ len := 0,
+ val := {
+ charg_char := charg_char
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_Charging_Characteristics(template (present) octetstring charg_char := ?) := {
+ tag := OSMO_GSUP_CHARG_CHAR_IE,
+ len := ?,
+ val := {
+ charg_char := charg_char
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_PCO(template (value) PCO_DATA pco) := {
+ tag := OSMO_GSUP_PCO_IE,
+ len := 0,
+ val := {
+ pco := pco
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_PCO(template (present) PCO_DATA pco := ?) := {
+ tag := OSMO_GSUP_PCO_IE,
+ len := ?,
+ val := {
+ pco := pco
+ }
+}
+
+template GSUP_PDU tr_GSUP(template GSUP_MessageType msgt := ?, template GSUP_IEs ies := *) := {
+ msg_type := msgt,
+ ies := ies
+}
+
+template (present) GSUP_PDU tr_GSUP_IMSI(template (present) GSUP_MessageType msgt := ?, template (present) hexstring imsi := ?) := {
+ msg_type := msgt,
+ ies := { tr_GSUP_IE_IMSI(imsi), * }
+}
+
+template GSUP_PDU ts_GSUP(GSUP_MessageType msgt, GSUP_IEs ies := {}) := {
+ msg_type := msgt,
+ ies := ies
+}
+
+template (value) GSUP_IMEI ts_GSUP_IMEI(hexstring digits) := {
+ len := 0, /* overwritten */
+ digits := digits
+}
+
+template GSUP_IMEI tr_GSUP_IMEI(template hexstring digits) := {
+ len := ?,
+ digits := digits
+}
+
+
+template (value) GSUP_PDU ts_GSUP_SAI_REQ(hexstring imsi) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, { valueof(ts_GSUP_IE_IMSI(imsi)) });
+
+template (value) GSUP_PDU ts_GSUP_SAI_REQ_EPS(hexstring imsi) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_CURRENT_RAT_TYPE(RAT_TYPE_EUTRAN_SGs))
+ });
+
+template (value) GSUP_PDU ts_GSUP_SAI_REQ_NUM_AUTH(hexstring imsi, OCT1 num_auth_vectors) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_NUM_VECTORS_REQ(num_auth_vectors))
+ });
+
+template (value) GSUP_PDU ts_GSUP_SAI_REQ_PDP_INFO(hexstring imsi, template (value) GSUP_IEs pdp_info) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_PdpInfo_ie(pdp_info))
+ });
+
+template GSUP_PDU ts_GSUP_SAI_REQ_PDP_INFO_UMTS_AKA_RESYNC(
+ template (value) hexstring imsi,
+ template (value) GSUP_IEs pdp_info,
+ template (value) octetstring auts,
+ template (value) octetstring rand) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_PdpInfo_ie(pdp_info)),
+ valueof(ts_GSUP_IE_AUTS(auts)),
+ valueof(ts_GSUP_IE_RAND(rand))
+ });
+
+template GSUP_PDU tr_GSUP_SAI_REQ(template hexstring imsi) :=
+ tr_GSUP_IMSI(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, imsi);
+
+template GSUP_PDU tr_GSUP_SAI_REQ_UMTS_AKA_RESYNC(
+ template hexstring imsi,
+ template octetstring auts,
+ template octetstring rand) :=
+ tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_AUTS(auts),
+ tr_GSUP_IE_RAND(rand),
+ *
+ });
+
+template (value) GSUP_PDU ts_GSUP_SAI_RES(hexstring imsi, GSUP_IE auth_tuple) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), auth_tuple });
+
+template GSUP_PDU tr_GSUP_SAI_ERR(template hexstring imsi, template (present) integer cause := ?) :=
+ tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR, {
+ tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause), *});
+
+template (value) GSUP_PDU ts_GSUP_SAI_ERR(hexstring imsi, integer cause) :=
+ ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
+
+
+template GSUP_PDU tr_GSUP_SAI_RES(template (present) hexstring imsi,
+ template (present) GSUP_IE auth_tuple_ie := tr_GSUP_IE(OSMO_GSUP_AUTH_TUPLE_IE)) :=
+ tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT, {
+ tr_GSUP_IE_IMSI(imsi), *, auth_tuple_ie, * });
+
+template GSUP_PDU ts_GSUP_UL_REQ(hexstring imsi, GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS,
+ template octetstring source_name := omit) :=
+ ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST, f_gen_ts_ies(imsi, dom := dom,
+ source_name := source_name));
+
+template GSUP_PDU tr_GSUP_UL_REQ(template hexstring imsi) :=
+ tr_GSUP_IMSI(OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST, imsi);
+
+template (value) GSUP_PDU ts_GSUP_UL_RES(hexstring imsi, octetstring destination_name := ''O) :=
+ ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT, { valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name))});
+
+template GSUP_PDU tr_GSUP_UL_RES(template hexstring imsi, template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT, f_gen_tr_ies(imsi, destination_name := destination_name));
+
+template (value) GSUP_PDU ts_GSUP_UL_ERR(hexstring imsi, integer cause) :=
+ ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
+
+template GSUP_PDU tr_GSUP_UL_ERR(template hexstring imsi, template integer cause := ?,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR,
+ f_gen_tr_ies(imsi, cause := cause, destination_name := destination_name));
+
+template (value) GSUP_PDU ts_GSUP_ISD_REQ(hexstring imsi, hexstring msisdn, octetstring destination_name := ''O) :=
+ ts_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_MSISDN(msisdn)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name))});
+
+template GSUP_PDU tr_GSUP_ISD_REQ(template hexstring imsi, template hexstring msisdn := ?,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_REQUEST,
+ f_gen_tr_ies(imsi, msisdn := msisdn, destination_name := destination_name));
+
+template GSUP_PDU ts_GSUP_ISD_RES(hexstring imsi,
+ template octetstring source_name := omit,
+ template octetstring destination_name := omit) :=
+ ts_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_RESULT,
+ f_gen_ts_ies(imsi, source_name := source_name,
+ destination_name := destination_name));
+
+template GSUP_PDU tr_GSUP_ISD_RES(template hexstring imsi) :=
+ tr_GSUP_IMSI(OSMO_GSUP_MSGT_INSERT_DATA_RESULT, imsi);
+
+template GSUP_PDU tr_GSUP_AUTH_FAIL_IND(hexstring imsi) :=
+ tr_GSUP_IMSI(OSMO_GSUP_MSGT_AUTH_FAIL_REPORT, imsi);
+
+template (present) GSUP_PDU tr_GSUP_CL_REQ(template (present) hexstring imsi := ?,
+ template GSUP_CnDomain dom := omit,
+ template GSUP_CancelType ctype := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST,
+ f_gen_tr_ies(imsi,
+ cancel_type := ctype,
+ cn_domain := dom));
+
+template (value) GSUP_PDU ts_GSUP_CL_REQ(hexstring imsi, GSUP_CancelType ctype) :=
+ ts_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_CancelType(ctype)) });
+
+template GSUP_PDU tr_GSUP_CL_RES(template hexstring imsi) :=
+ tr_GSUP_IMSI(OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT, imsi);
+
+template (value) GSUP_PDU ts_GSUP_CL_RES(template (value) hexstring imsi) :=
+ ts_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT, {valueof(ts_GSUP_IE_IMSI(imsi))});
+
+template GSUP_PDU tr_GSUP_CL_ERR(template hexstring imsi, template integer cause := ?) :=
+ tr_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR, {
+ tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause), * });
+
+template (value) GSUP_PDU ts_GSUP_PURGE_MS_REQ(hexstring imsi, GSUP_CnDomain dom) :=
+ ts_GSUP(OSMO_GSUP_MSGT_PURGE_MS_REQUEST, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_CnDomain(dom)) });
+
+template GSUP_PDU tr_GSUP_PURGE_MS_REQ(template hexstring imsi, template GSUP_CnDomain dom := ?) :=
+ tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_REQUEST, {
+ tr_GSUP_IE_IMSI(imsi), *, tr_GSUP_IE_CnDomain(dom) });
+
+template (value) GSUP_PDU ts_GSUP_PURGE_MS_RES(hexstring imsi) :=
+ ts_GSUP(OSMO_GSUP_MSGT_PURGE_MS_RESULT, {
+ valueof(ts_GSUP_IE_IMSI(imsi)) });
+
+template GSUP_PDU tr_GSUP_PURGE_MS_RES(template hexstring imsi) :=
+ tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_RESULT, {
+ tr_GSUP_IE_IMSI(imsi), * });
+
+template GSUP_PDU tr_GSUP_PURGE_MS_ERR(template hexstring imsi, template integer cause) :=
+ tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_ERROR, {
+ tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause) });
+
+template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_REQ(hexstring imsi, hexstring imei,
+ template (omit) octetstring source_name := omit) :=
+ ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST, f_gen_ts_ies(imsi, imei := imei, source_name := source_name));
+
+template GSUP_PDU tr_GSUP_CHECK_IMEI_REQ(
+ template hexstring imsi,
+ template hexstring imei
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_IMEI(imei),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_RES(hexstring imsi, GSUP_IMEIResult result) :=
+ ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_RESULT, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_IMEI_Result(result)) });
+
+template GSUP_PDU tr_GSUP_CHECK_IMEI_RES(template hexstring imsi, template GSUP_IMEIResult result,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
+ f_gen_tr_ies(imsi, imei_result := result, destination_name := destination_name));
+
+template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_ERR(hexstring imsi, integer cause) :=
+ ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_ERROR, {
+ valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
+
+template GSUP_PDU tr_GSUP_CHECK_IMEI_ERR(template hexstring imsi, template integer cause,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_ERROR, f_gen_tr_ies(imsi, cause := cause, destination_name := destination_name));
+
+
+/* EPDG Tunnel */
+template (value) GSUP_PDU ts_GSUP_EPDGTunnel_REQ(hexstring imsi,
+ template (value) PCO_DATA pco,
+ GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG,
+ GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS,
+ template (omit) octetstring source_name := omit) :=
+ ts_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST, f_gen_ts_ies(imsi,
+ message_class := message_class,
+ pco := pco,
+ dom := dom,
+ source_name := source_name));
+
+template (present) GSUP_PDU tr_GSUP_EPDGTunnel_REQ(template (present) hexstring imsi := ?,
+ template (present) GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG) :=
+ tr_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST,
+ f_gen_tr_ies(imsi,
+ message_class := message_class));
+
+
+template (value) GSUP_PDU ts_GSUP_EPDGTunnel_RES(hexstring imsi,
+ template (value) GSUP_IEs pdp_info,
+ GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG,
+ octetstring destination_name := ''O) :=
+ ts_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_PdpInfoCompl),
+ valueof(ts_GSUP_IE_PdpInfo_ie(pdp_info)),
+ valueof(ts_GSUP_IE_Message_Class(message_class)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name))
+ });
+
+template (present) GSUP_PDU tr_GSUP_EPDGTunnel_RES(template (present) hexstring imsi,
+ template (present) GSUP_IEs pdp_info,
+ template (present) PCO_DATA pco := ?,
+ template (present) GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT,
+ f_gen_tr_ies(imsi,
+ pdp_info_compl := true,
+ pdp_info := pdp_info,
+ message_class := message_class,
+ pco := pco,
+ destination_name := destination_name));
+
+template (value) GSUP_PDU ts_GSUP_EPDGTunnel_ERR(hexstring imsi,
+ GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG,
+ integer cause := 0) :=
+ ts_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR, {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_Cause(cause)),
+ valueof(ts_GSUP_IE_Message_Class(message_class))
+ });
+
+template (present) GSUP_PDU tr_GSUP_EPDGTunnel_ERR(template (present) hexstring imsi,
+ template (present) GSUP_Message_Class message_class := OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG,
+ template (present) integer cause := ?,
+ template octetstring destination_name := omit) :=
+ tr_GSUP(OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR,
+ f_gen_tr_ies(imsi,
+ message_class := message_class,
+ cause := cause,
+ destination_name := destination_name));
+
+
+template (value) GSUP_IE ts_GSUP_IE_CancelType(GSUP_CancelType ctype) := {
+ tag := OSMO_GSUP_CANCEL_TYPE_IE,
+ len := 0, /* overwritten */
+ val := {
+ cancel_type := ctype
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_CancelType(template GSUP_CancelType ctype) :=
+ tr_GSUP_IE(OSMO_GSUP_CANCEL_TYPE_IE, GSUP_IeValue:{cancel_type:=ctype});
+
+template GSUP_IE tr_GSUP_IE_CnDomain(template GSUP_CnDomain domain) :=
+ tr_GSUP_IE(OSMO_GSUP_CN_DOMAIN_IE, GSUP_IeValue:{cn_domain:=domain});
+
+template GSUP_IE tr_GSUP_IE(template GSUP_IEI iei, template GSUP_IeValue val := ?) := {
+ tag := iei,
+ len := ?,
+ val := val
+}
+
+template (value) GSUP_IE ts_GSUP_IE_IMSI(template (value) hexstring imsi) := {
+ tag := OSMO_GSUP_IMSI_IE,
+ len := 0, /* overwritten */
+ val := {
+ imsi := imsi
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_IMSI(template (present) hexstring imsi := ?) := {
+ tag := OSMO_GSUP_IMSI_IE,
+ len := ?,
+ val := {
+ imsi := imsi
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_MSISDN(hexstring msisdn) := {
+ tag := OSMO_GSUP_MSISDN_IE,
+ len := 0, /* overwritten */
+ val := {
+ msisdn := ts_GSUP_MSISDN(msisdn)
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_MSISDN(template hexstring msisdn) := {
+ tag := OSMO_GSUP_MSISDN_IE,
+ len := ?,
+ val := {
+ msisdn := tr_GSUP_MSISDN(msisdn)
+ }
+}
+
+
+template (value) GSUP_IE ts_GSUP_IE_Cause(integer cause) := {
+ tag := OSMO_GSUP_CAUSE_IE,
+ len := 0, /* overwritten */
+ val := {
+ cause := cause
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Cause(template integer cause) := {
+ tag := OSMO_GSUP_CAUSE_IE,
+ len := ?,
+ val := {
+ cause := cause
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_AUTS(template (value) octetstring auts) := {
+ tag := OSMO_GSUP_AUTS_IE,
+ len := 0, /* overwritten */
+ val := {
+ auts := auts
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_AUTS(template octetstring auts) := {
+ tag := OSMO_GSUP_AUTS_IE,
+ len := ?,
+ val := {
+ auts := auts
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_RAND(template (value) octetstring rand) := {
+ tag := OSMO_GSUP_RAND_IE,
+ len := 0, /* overwritten */
+ val := {
+ rand := rand
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_RAND(template octetstring rand := ?) := {
+ tag := OSMO_GSUP_RAND_IE,
+ len := ?,
+ val := {
+ rand := rand
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_SRES(template (present) octetstring sres := ?) := {
+ tag := OSMO_GSUP_SRES_IE,
+ len := ?,
+ val := {
+ sres := sres
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SRES(octetstring sres) := {
+ tag := OSMO_GSUP_SRES_IE,
+ len := 0, /* overwritten */
+ val := {
+ sres := sres
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_Kc(template (present) octetstring kc := ?) := {
+ tag := OSMO_GSUP_KC_IE,
+ len := ?,
+ val := {
+ kc := kc
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Kc(octetstring kc) := {
+ tag := OSMO_GSUP_KC_IE,
+ len := 0, /* overwritten */
+ val := {
+ kc := kc
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_IK(template (present) octetstring ik := ?) := {
+ tag := OSMO_GSUP_IK_IE,
+ len := ?,
+ val := {
+ ik := ik
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_IK(octetstring ik) := {
+ tag := OSMO_GSUP_IK_IE,
+ len := 0, /* overwritten */
+ val := {
+ ik := ik
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_CK(template (present) octetstring ck := ?) := {
+ tag := OSMO_GSUP_CK_IE,
+ len := ?,
+ val := {
+ ck := ck
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_CK(octetstring ck) := {
+ tag := OSMO_GSUP_CK_IE,
+ len := 0, /* overwritten */
+ val := {
+ ck := ck
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_AUTN(template (present) octetstring autn := ?) := {
+ tag := OSMO_GSUP_AUTN_IE,
+ len := ?,
+ val := {
+ autn := autn
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_AUTN(octetstring autn) := {
+ tag := OSMO_GSUP_AUTN_IE,
+ len := 0, /* overwritten */
+ val := {
+ autn := autn
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_RES(template (present) octetstring res := ?) := {
+ tag := OSMO_GSUP_RES_IE,
+ len := ?,
+ val := {
+ res := res
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_RES(octetstring res) := {
+ tag := OSMO_GSUP_RES_IE,
+ len := 0, /* overwritten */
+ val := {
+ res := res
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_APN(template (value) octetstring apn) := {
+ tag := OSMO_GSUP_ACCESS_POINT_NAME_IE,
+ len := 0, /* overwritten */
+ val := {
+ apn := apn
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_APN(template octetstring apn) := {
+ tag := OSMO_GSUP_ACCESS_POINT_NAME_IE,
+ len := ?,
+ val := {
+ apn := apn
+ }
+}
+
+template GSUP_IE ts_GSUP_IE_CnDomain(template GSUP_CnDomain dom) := {
+ tag := OSMO_GSUP_CN_DOMAIN_IE,
+ len := 0, /* overwritten */
+ val := {
+ cn_domain := dom
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SessionId(OCT4 sid) := {
+ tag := OSMO_GSUP_SESSION_ID_IE,
+ len := 0, /* overwritten */
+ val := {
+ session_id := sid
+ }
+}
+template GSUP_IE tr_GSUP_IE_SessionId(template OCT4 sid) := {
+ tag := OSMO_GSUP_SESSION_ID_IE,
+ len := ?,
+ val := {
+ session_id := sid
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SessionState(GSUP_SessionState state) := {
+ tag := OSMO_GSUP_SESSION_STATE_IE,
+ len := 0, /* overwritten */
+ val := {
+ session_state := state
+ }
+}
+template GSUP_IE tr_GSUP_IE_SessionState(template GSUP_SessionState state) := {
+ tag := OSMO_GSUP_SESSION_STATE_IE,
+ len := ?,
+ val := {
+ session_state := state
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_MR(OCT1 ref) := {
+ tag := OSMO_GSUP_SM_RP_MR_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_mr := ref
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_MR(template OCT1 ref) := {
+ tag := OSMO_GSUP_SM_RP_MR_IE,
+ len := ?,
+ val := {
+ sm_rp_mr := ref
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_CAUSE(OCT1 cause) := {
+ tag := OSMO_GSUP_SM_RP_CAUSE_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_cause := cause
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_CAUSE(template OCT1 cause) := {
+ tag := OSMO_GSUP_SM_RP_CAUSE_IE,
+ len := ?,
+ val := {
+ sm_rp_cause := cause
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_MMS(OCT1 mms) := {
+ tag := OSMO_GSUP_SM_RP_MMS_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_mms := mms
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_MMS(template OCT1 mms) := {
+ tag := OSMO_GSUP_SM_RP_MMS_IE,
+ len := ?,
+ val := {
+ sm_rp_mms := mms
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_IMEI(hexstring imei) := {
+ tag := OSMO_GSUP_IMEI_IE,
+ len := 0, /* overwritten */
+ val := {
+ imei := ts_GSUP_IMEI(imei)
+ }
+}
+template GSUP_IE tr_GSUP_IE_IMEI(template hexstring imei) := {
+ tag := OSMO_GSUP_IMEI_IE,
+ len := ?,
+ val := {
+ imei := tr_GSUP_IMEI(imei)
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_IMEI_Result(GSUP_IMEIResult result) := {
+ tag := OSMO_GSUP_IMEI_RESULT_IE,
+ len := 0, /* overwritten */
+ val := {
+ imei_result := result
+ }
+}
+template GSUP_IE tr_GSUP_IE_IMEI_Result(template GSUP_IMEIResult result) := {
+ tag := OSMO_GSUP_IMEI_RESULT_IE,
+ len := ?,
+ val := {
+ imei_result := result
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_NUM_VECTORS_REQ(OCT1 num) := {
+ tag := OSMO_GSUP_NUM_VECTORS_REQ_IE,
+ len := 0, /* overwritten */
+ val := {
+ num_auth_vectors := num
+ }
+}
+template GSUP_IE tr_GSUP_IE_NUM_VECTORS_REQ(template OCT1 num) := {
+ tag := OSMO_GSUP_NUM_VECTORS_REQ_IE,
+ len := ?,
+ val := {
+ num_auth_vectors := num
+ }
+}
+
+/* See 3GPP TS 24.011, figures 8.5 and 8.6 */
+private function f_pad_SM_RP_Addr(template hexstring number)
+return template hexstring {
+ if (isvalue(number) and not istemplatekind(number, "omit")) {
+ return f_pad_bcd_number(valueof(number));
+ } else {
+ return number;
+ }
+}
+
+template GSUP_SM_RP_Addr t_GSUP_SM_RP_Addr(template hexstring number,
+ template BIT4 npi := '0001'B,
+ template BIT3 ton := '001'B,
+ template BIT1 ext := '1'B) := {
+ ext := ext,
+ ton := ton,
+ npi := npi,
+ /* Work around TITAN's padding problems: encoding works fine,
+ * but it does not consider 'F'H as padding in decoded data. */
+ number := f_pad_SM_RP_Addr(number)
+}
+
+/**
+ * SM-RP-DA represents the SM Destination Address, see 7.6.8.1.
+ * It can be either of the following:
+ * - IMSI
+ * - LMSI (not implemented)
+ * - MSISDN
+ * - roaming number (not implemented)
+ * - service centre address
+ */
+template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_IMSI(hexstring imsi) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_IMSI,
+ id_enc := { imsi := imsi }
+}
+template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_IMSI(template hexstring imsi) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_IMSI,
+ id_enc := { imsi := imsi }
+}
+
+template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_MSISDN(GSUP_SM_RP_Addr msisdn) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
+ id_enc := { msisdn := msisdn }
+}
+template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_MSISDN(template GSUP_SM_RP_Addr msisdn) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
+ id_enc := { msisdn := msisdn }
+}
+
+template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_SMSC_ADDR(GSUP_SM_RP_Addr smsc_addr) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
+ id_enc := { smsc_addr := smsc_addr }
+}
+template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_SMSC_ADDR(template GSUP_SM_RP_Addr smsc_addr) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
+ id_enc := { smsc_addr := smsc_addr }
+}
+
+template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_NULL := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
+ id_enc := omit
+}
+template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_NULL := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
+ id_enc := omit
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_DA(GSUP_SM_RP_DA val) := {
+ tag := OSMO_GSUP_SM_RP_DA_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_da := val
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_DA(template GSUP_SM_RP_DA val) := {
+ tag := OSMO_GSUP_SM_RP_DA_IE,
+ len := ?,
+ val := {
+ sm_rp_da := val
+ }
+}
+
+/**
+ * SM-RP-OA represents the SM Originating Address, see 7.6.8.2.
+ * It can be either of the following:
+ * - MSISDN
+ * - service centre address
+ */
+template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_MSISDN(GSUP_SM_RP_Addr msisdn) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
+ id_enc := { msisdn := msisdn }
+}
+template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_MSISDN(template GSUP_SM_RP_Addr msisdn) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
+ id_enc := { msisdn := msisdn }
+}
+
+template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_SMSC_ADDR(GSUP_SM_RP_Addr smsc_addr) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
+ id_enc := { smsc_addr := smsc_addr }
+}
+template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_SMSC_ADDR(template GSUP_SM_RP_Addr smsc_addr) := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
+ id_enc := { smsc_addr := smsc_addr }
+}
+
+template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_NULL := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
+ id_enc := omit
+}
+template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_NULL := {
+ id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
+ id_enc := omit
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_OA(GSUP_SM_RP_OA val) := {
+ tag := OSMO_GSUP_SM_RP_OA_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_oa := val
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_OA(template GSUP_SM_RP_OA val) := {
+ tag := OSMO_GSUP_SM_RP_OA_IE,
+ len := ?,
+ val := {
+ sm_rp_oa := val
+ }
+}
+
+/* SM-RP-UI represents the SM TPDU, see 7.6.8.4 */
+template (value) GSUP_IE ts_GSUP_IE_SM_RP_UI(octetstring val) := {
+ tag := OSMO_GSUP_SM_RP_UI_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_rp_ui := val
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_RP_UI(template octetstring val) := {
+ tag := OSMO_GSUP_SM_RP_UI_IE,
+ len := ?,
+ val := {
+ sm_rp_ui := val
+ }
+}
+
+/* SM Alert Reason IE (used in READY-FOR-SM), see 7.6.8.8 */
+template (value) GSUP_IE ts_GSUP_IE_SM_ALERT_RSN(GSUP_SM_ALERT_RSN_Type rsn) := {
+ tag := OSMO_GSUP_SM_ALERT_RSN_IE,
+ len := 0, /* overwritten */
+ val := {
+ sm_alert_rsn := rsn
+ }
+}
+template GSUP_IE tr_GSUP_IE_SM_ALERT_RSN(template GSUP_SM_ALERT_RSN_Type rsn) := {
+ tag := OSMO_GSUP_SM_ALERT_RSN_IE,
+ len := ?,
+ val := {
+ sm_alert_rsn := rsn
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_SSInfo(octetstring ss) := {
+ tag := OSMO_GSUP_SS_INFO_IE,
+ len := 0, /* overwritten */
+ val := {
+ ss_info := ss
+ }
+}
+template GSUP_IE tr_GSUP_IE_SSInfo(template octetstring ss) := {
+ tag := OSMO_GSUP_SS_INFO_IE,
+ len := ?,
+ val := {
+ ss_info := ss
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Message_Class(template GSUP_Message_Class val) := {
+ tag := OSMO_GSUP_MESSAGE_CLASS_IE,
+ len := ?,
+ val := {
+ message_class := val
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Message_Class(GSUP_Message_Class val) := {
+ tag := OSMO_GSUP_MESSAGE_CLASS_IE,
+ len := 0, /* overwritten */
+ val := {
+ message_class := val
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Source_Name(template octetstring name) := {
+ tag := OSMO_GSUP_SOURCE_NAME_IE,
+ len := ?,
+ val := {
+ source_name := name
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Source_Name(octetstring name) := {
+ tag := OSMO_GSUP_SOURCE_NAME_IE,
+ len := 0, /* overwritten */
+ val := {
+ source_name := name
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Destination_Name(template octetstring name) := {
+ tag := OSMO_GSUP_DESTINATION_NAME_IE,
+ len := ?,
+ val := {
+ destination_name := name
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Destination_Name(octetstring name) := {
+ tag := OSMO_GSUP_DESTINATION_NAME_IE,
+ len := 0, /* overwritten */
+ val := {
+ destination_name := name
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_AN_APDU(template GSUP_AN_APDU an_apdu) := {
+ tag := OSMO_GSUP_AN_APDU_IE,
+ len := ?,
+ val := {
+ an_apdu := an_apdu
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_AN_APDU(GSUP_AN_APDU an_apdu) := {
+ tag := OSMO_GSUP_AN_APDU_IE,
+ len := 0, /* overwritten */
+ val := {
+ an_apdu := an_apdu
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_SUPPORTED_RAT_TYPES(template (present) GSUP_RatTypes ratt) := {
+ tag := OSMO_GSUP_SUPPORTED_RAT_TYPES_IE,
+ len := ?,
+ val := {
+ supported_rat_types := ratt
+ }
+}
+template (value) GSUP_IE ts_GSUP_IE_SUPPORTED_RAT_TYPES(GSUP_RatTypes ratt) := {
+ tag := OSMO_GSUP_SUPPORTED_RAT_TYPES_IE,
+ len := 0, /* overwritten */
+ val := {
+ supported_rat_types := ratt
+ }
+}
+
+template (present) GSUP_IE tr_GSUP_IE_CURRENT_RAT_TYPE(template (present) GSUP_RatType ratt) := {
+ tag := OSMO_GSUP_CURRENT_RAT_TYPE_IE,
+ len := ?,
+ val := {
+ current_rat_type := ratt
+ }
+}
+template (value) GSUP_IE ts_GSUP_IE_CURRENT_RAT_TYPE(GSUP_RatType ratt) := {
+ tag := OSMO_GSUP_CURRENT_RAT_TYPE_IE,
+ len := 0, /* overwritten */
+ val := {
+ current_rat_type := ratt
+ }
+}
+
+private function f_gen_ts_ies(hexstring imsi,
+ template (omit) boolean pdp_info_compl := omit,
+ template (omit) GSUP_Message_Class message_class := omit,
+ template (omit) hexstring imei := omit,
+ template (omit) PCO_DATA pco := omit,
+ template (omit) GSUP_CnDomain dom := omit,
+ template (omit) octetstring source_name := omit,
+ template (omit) octetstring destination_name := omit
+ ) return GSUP_IEs {
+ var GSUP_IEs ies := {
+ valueof(ts_GSUP_IE_IMSI(imsi))
+ };
+
+ if (isvalue(dom)) {
+ ies := ies & { valueof(ts_GSUP_IE_CnDomain(dom)) };
+ }
+
+ if (isvalue(pdp_info_compl) and valueof(pdp_info_compl)) {
+ ies := ies & { valueof(ts_GSUP_IE_PdpInfoCompl) };
+ }
+
+ if (isvalue(imei)) {
+ ies := ies & { valueof(ts_GSUP_IE_IMEI(valueof(imei))) };
+ }
+
+ if (isvalue(pco)) {
+ ies := ies & { valueof(ts_GSUP_IE_PCO(valueof(pco))) };
+ }
+
+ if (isvalue(message_class)) {
+ ies := ies & { valueof(ts_GSUP_IE_Message_Class(valueof(message_class))) };
+ }
+
+ if (isvalue(source_name)) {
+ ies := ies & { valueof(ts_GSUP_IE_Source_Name(valueof(source_name))) };
+ }
+
+ if (isvalue(destination_name)) {
+ ies := ies & { valueof(ts_GSUP_IE_Destination_Name(valueof(destination_name))) };
+ }
+
+ return ies;
+}
+
+private function f_gen_tr_ies(template hexstring imsi,
+ template boolean pdp_info_compl := omit,
+ template GSUP_IEs pdp_info := omit,
+ template GSUP_Message_Class message_class := omit,
+ template integer cause := omit,
+ template GSUP_CancelType cancel_type := omit,
+ template hexstring msisdn := omit,
+ template GSUP_IMEIResult imei_result := omit,
+ template PCO_DATA pco := omit,
+ template GSUP_CnDomain cn_domain := omit,
+ template octetstring source_name := omit,
+ template octetstring destination_name := omit
+ ) return template GSUP_IEs {
+ var template GSUP_IEs ies := {
+ tr_GSUP_IE_IMSI(imsi)
+ };
+ var integer idx := 1;
+
+ if (not istemplatekind(msisdn, "omit")) {
+ ies[idx] := tr_GSUP_IE_MSISDN(msisdn);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(cause, "omit")) {
+ ies[idx] := tr_GSUP_IE_Cause(cause);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(cancel_type, "omit")) {
+ ies[idx] := tr_GSUP_IE_CancelType(cancel_type);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(pdp_info_compl, "omit")) {
+ ies[idx] := tr_GSUP_IE_PdpInfoCompl;
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(pdp_info, "omit")) {
+ ies[idx] := tr_GSUP_IE_PdpInfo_ie(pdp_info);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(cn_domain, "omit")) {
+ ies[idx] := tr_GSUP_IE_CnDomain(cn_domain);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(imei_result, "omit")) {
+ ies[idx] := tr_GSUP_IE_IMEI_Result(imei_result);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(message_class, "omit")) {
+ ies[idx] := tr_GSUP_IE_Message_Class(message_class);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(pco, "omit")) {
+ ies[idx] := tr_GSUP_IE_PCO(pco);
+ idx := idx + 1;
+ }
+
+ if (not istemplatekind(source_name, "omit")) {
+ ies[idx] := tr_GSUP_IE_Source_Name(source_name);
+ idx := idx + 1;
+ }
+
+ ies[idx] := *;
+ idx := idx + 1;
+
+ if (not istemplatekind(destination_name, "omit")) {
+ if (istemplatekind(destination_name, "*")) {
+ ies[idx] := *;
+ } else {
+ ies[idx] := tr_GSUP_IE_Destination_Name(destination_name);
+ }
+ idx := idx + 1;
+ }
+
+ return ies;
+}
+
+private function f_gen_ts_ss_ies(
+ hexstring imsi,
+ OCT4 sid,
+ GSUP_SessionState state,
+ template (omit) octetstring ss := omit,
+ template (omit) integer cause := omit,
+ template octetstring source_name := omit
+) return GSUP_IEs {
+ /* Mandatory IEs */
+ var GSUP_IEs ies := {
+ valueof(ts_GSUP_IE_IMSI(imsi))
+ };
+
+ /* Cause IE is needed for PROC_SS_ERR */
+ if (isvalue(cause)) {
+ ies := ies & { valueof(ts_GSUP_IE_Cause(valueof(cause))) };
+ }
+
+ /* Mandatory session IEs */
+ ies := ies & { valueof(ts_GSUP_IE_SessionId(sid)) };
+ ies := ies & { valueof(ts_GSUP_IE_SessionState(state)) };
+
+ /* Optional SS payload */
+ if (isvalue(ss)) {
+ ies := ies & { valueof(ts_GSUP_IE_SSInfo(valueof(ss))) };
+ }
+
+ if (isvalue(source_name)) {
+ ies := ies & { valueof(ts_GSUP_IE_Source_Name(valueof(source_name))) };
+ }
+
+ return ies;
+}
+private function f_gen_tr_ss_ies(
+ template hexstring imsi,
+ template OCT4 sid := ?,
+ template GSUP_SessionState state := ?,
+ template octetstring ss := omit,
+ template integer cause := omit,
+ template octetstring destination_name := omit
+) return template GSUP_IEs {
+ /* Mandatory IEs */
+ var template GSUP_IEs ies := {
+ tr_GSUP_IE_IMSI(imsi)
+ };
+ var integer idx := 1;
+
+ /* Cause IE is needed for PROC_SS_ERR */
+ if (istemplatekind(cause, "*")) {
+ ies[idx] := *;
+ idx := idx + 1;
+ } else if (not istemplatekind(cause, "omit")) {
+ ies[idx] := tr_GSUP_IE_Cause(cause);
+ idx := idx + 1;
+ }
+
+ /* Mandatory session IEs */
+ ies[idx] := tr_GSUP_IE_SessionId(sid);
+ ies[idx + 1] := tr_GSUP_IE_SessionState(state);
+ idx := idx + 2;
+
+ /* Optional SS payload */
+ if (istemplatekind(ss, "*")) {
+ ies[idx] := *;
+ idx := idx + 1;
+ } else if (not istemplatekind(ss, "omit")) {
+ ies[idx] := tr_GSUP_IE_SSInfo(ss);
+ idx := idx + 1;
+ }
+
+ if (isvalue(destination_name)) {
+ ies[idx] := tr_GSUP_IE_Destination_Name(destination_name);
+ idx := idx + 1;
+ }
+
+ /* the GSUP Message Class IE is optional, as old implementations don't have it yet */
+ var template GSUP_IEs ies2 := ies;
+ ies2[idx] := tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_USSD);
+ idx := idx + 1;
+
+ return (ies, ies2);
+}
+
+template (value) GSUP_PDU ts_GSUP_PROC_SS_REQ(
+ hexstring imsi,
+ OCT4 sid,
+ GSUP_SessionState state,
+ template (omit) octetstring ss := omit,
+ template (omit) octetstring source_name := omit
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_REQUEST,
+ f_gen_ts_ss_ies(imsi, sid, state, ss, source_name := source_name)
+);
+template GSUP_PDU tr_GSUP_PROC_SS_REQ(
+ template hexstring imsi,
+ template OCT4 sid := ?,
+ template GSUP_SessionState state := ?,
+ template octetstring ss := *
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_REQUEST,
+ f_gen_tr_ss_ies(imsi, sid, state, ss)
+);
+
+template (value) GSUP_PDU ts_GSUP_PROC_SS_RES(
+ hexstring imsi,
+ OCT4 sid,
+ GSUP_SessionState state,
+ template (omit) octetstring ss := omit
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_RESULT,
+ f_gen_ts_ss_ies(imsi, sid, state, ss)
+);
+template GSUP_PDU tr_GSUP_PROC_SS_RES(
+ template hexstring imsi,
+ template OCT4 sid := ?,
+ template GSUP_SessionState state := ?,
+ template octetstring ss := *,
+ template octetstring destination_name := omit
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_RESULT,
+ f_gen_tr_ss_ies(imsi, sid, state, ss, destination_name := destination_name)
+);
+
+template (value) GSUP_PDU ts_GSUP_PROC_SS_ERR(
+ hexstring imsi,
+ OCT4 sid,
+ GSUP_SessionState state,
+ integer cause
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_ERROR,
+ f_gen_ts_ss_ies(imsi, sid, state, cause := cause)
+);
+template GSUP_PDU tr_GSUP_PROC_SS_ERR(
+ template hexstring imsi,
+ template OCT4 sid := ?,
+ template GSUP_SessionState state := ?,
+ template integer cause := ?
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_PROC_SS_ERROR,
+ f_gen_tr_ss_ies(imsi, sid, state, cause := cause)
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_REQ(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
+ GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
+ octetstring sm_rp_ui /* SM TPDU, see 7.6.8.4 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_RP_DA(sm_rp_da)),
+ valueof(ts_GSUP_IE_SM_RP_OA(sm_rp_oa)),
+ valueof(ts_GSUP_IE_SM_RP_UI(sm_rp_ui)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_FORWARD_SM_REQ(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
+ template GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
+ template octetstring sm_rp_ui /* SM TPDU, see 7.6.8.4 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_RP_DA(sm_rp_da),
+ tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
+ tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_RES(
+ hexstring imsi,
+ OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_FORWARD_SM_RES(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_ERR(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_FORWARD_SM_ERR(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_REQ(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
+ GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
+ octetstring sm_rp_ui, /* SM TPDU, see 7.6.8.4 */
+ OCT1 sm_rp_mms /* MMS (More Messages to Send), see 7.6.8.7 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST,
+ {
+ /**
+ * TODO: add MT-specific fields (and IEs):
+ * - smDeliveryTimer
+ * - smDeliveryStartTime
+ */
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_RP_DA(sm_rp_da)),
+ valueof(ts_GSUP_IE_SM_RP_OA(sm_rp_oa)),
+ valueof(ts_GSUP_IE_SM_RP_UI(sm_rp_ui)),
+ valueof(ts_GSUP_IE_SM_RP_MMS(sm_rp_mms)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MT_FORWARD_SM_REQ(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
+ template GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
+ template octetstring sm_rp_ui, /* SM TPDU, see 7.6.8.4 */
+ template OCT1 sm_rp_mms /* MMS (More Messages to Send), see 7.6.8.7 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST,
+ {
+ /**
+ * TODO: add MT-specific fields (and IEs):
+ * - smDeliveryTimer
+ * - smDeliveryStartTime
+ */
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_RP_DA(sm_rp_da),
+ tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
+ tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
+ tr_GSUP_IE_SM_RP_MMS(sm_rp_mms),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_RES(
+ hexstring imsi,
+ OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MT_FORWARD_SM_RES(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_ERR(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MT_FORWARD_SM_ERR(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_REQ(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ GSUP_SM_ALERT_RSN_Type sm_alert_rsn /* SM Alert Reason, see 7.6.8.8 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_REQ(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template GSUP_SM_ALERT_RSN_Type sm_alert_rsn := ? /* SM Alert Reason, see 7.6.8.8 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_RES(
+ hexstring imsi,
+ OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_RES(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_ERR(
+ hexstring imsi,
+ OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_ERROR,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
+ valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS))
+ }
+);
+template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_ERR(
+ template hexstring imsi := ?,
+ template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
+ template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
+) := tr_GSUP(
+ OSMO_GSUP_MSGT_READY_FOR_SM_ERROR,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS),
+ tr_GSUP_IE_Source_Name(?)
+ }
+);
+
+function f_gsup_find_nested_ie_multiple(GSUP_IEs ies, GSUP_IEI iei, integer nth, out GSUP_IeValue ret) return boolean {
+ var integer current := 0;
+ for (var integer i := 0; i < sizeof(ies); i := i+1) {
+ if (ies[i].tag == iei) {
+ if (current == nth) {
+ ret := ies[i].val;
+ return true;
+ } else {
+ current := current + 1;
+ }
+ }
+ }
+ return false;
+}
+
+function f_gsup_find_nested_ie(GSUP_IEs ies, GSUP_IEI iei, out GSUP_IeValue ret) return boolean {
+ for (var integer i := 0; i < sizeof(ies); i := i+1) {
+ if (ies[i].tag == iei) {
+ ret := ies[i].val;
+ return true;
+ }
+ }
+ return false;
+}
+
+function f_gsup_find_ie(GSUP_PDU msg, GSUP_IEI iei, out GSUP_IeValue ret) return boolean {
+ return f_gsup_find_nested_ie(msg.ies, iei, ret);
+}
+
+template GSUP_AN_APDU t_GSUP_AN_APDU(
+ template GSUP_AN_PROTO an_proto := ?,
+ template octetstring pdu := ?
+) := {
+ proto := an_proto,
+ pdu := pdu
+};
+
+template GSUP_PDU tr_GSUP_E_AN_APDU(
+ template GSUP_MessageType msgt,
+ template hexstring imsi := ?,
+ template octetstring source_name := ?,
+ template octetstring destination_name := ?,
+ template GSUP_AN_APDU an_apdu := ?
+) := tr_GSUP(
+ msgt,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
+ tr_GSUP_IE_Source_Name(source_name),
+ tr_GSUP_IE_Destination_Name(destination_name),
+ tr_GSUP_IE_AN_APDU(an_apdu)
+ }
+);
+
+template GSUP_PDU tr_GSUP_E_NO_PDU(
+ template GSUP_MessageType msgt,
+ template hexstring imsi := ?,
+ template octetstring source_name := ?,
+ template octetstring destination_name := ?
+) := tr_GSUP(
+ msgt,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
+ tr_GSUP_IE_Source_Name(source_name),
+ tr_GSUP_IE_Destination_Name(destination_name)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_E_AN_APDU(
+ GSUP_MessageType msgt,
+ hexstring imsi,
+ octetstring source_name,
+ octetstring destination_name,
+ GSUP_AN_APDU an_apdu
+) := ts_GSUP(
+ msgt,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
+ valueof(ts_GSUP_IE_Source_Name(source_name)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name)),
+ valueof(ts_GSUP_IE_AN_APDU(an_apdu))
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_E_PrepareHandoverResult(
+ hexstring imsi,
+ hexstring msisdn,
+ octetstring source_name,
+ octetstring destination_name,
+ GSUP_AN_APDU an_apdu
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_MSISDN(msisdn)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
+ valueof(ts_GSUP_IE_Source_Name(source_name)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name)),
+ valueof(ts_GSUP_IE_AN_APDU(an_apdu))
+ }
+);
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/GSUP_Types.ttcn b/library/GSUP_Types.ttcn
index 41181e8a..078347e5 100644
--- a/library/GSUP_Types.ttcn
+++ b/library/GSUP_Types.ttcn
@@ -17,6 +17,7 @@ module GSUP_Types {
import from General_Types all;
import from Osmocom_Types all;
+import from PCO_Types all;
type enumerated GSUP_IEI {
OSMO_GSUP_IMSI_IE ('01'O),
@@ -29,10 +30,11 @@ type enumerated GSUP_IEI {
OSMO_GSUP_MSISDN_IE ('08'O),
OSMO_GSUP_HLR_NUMBER_IE ('09'O),
OSMO_GSUP_PDP_CONTEXT_ID_IE ('10'O),
- OSMO_GSUP_PDP_TYPE_IE ('11'O),
+ OSMO_GSUP_PDP_ADDRESS_IE ('11'O),
OSMO_GSUP_ACCESS_POINT_NAME_IE ('12'O),
OSMO_GSUP_PDP_QOS_IE ('13'O),
OSMO_GSUP_CHARG_CHAR_IE ('14'O),
+ OSMO_GSUP_PCO_IE ('15'O),
OSMO_GSUP_RAND_IE ('20'O),
OSMO_GSUP_SRES_IE ('21'O),
@@ -138,7 +140,11 @@ type enumerated GSUP_MessageType {
OSMO_GSUP_MSGT_E_CLOSE ('01000111'B),
OSMO_GSUP_MSGT_E_ABORT ('01001011'B),
- OSMO_GSUP_MSGT_E_ROUTING_ERROR ('01001110'B)
+ OSMO_GSUP_MSGT_E_ROUTING_ERROR ('01001110'B),
+
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST ('01010000'B),
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR ('01010001'B),
+ OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT ('01010010'B)
} with { variant "FIELDLENGTH(8)" };
type enumerated GSUP_CancelType {
@@ -168,7 +174,8 @@ type enumerated GSUP_Message_Class {
OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT (1),
OSMO_GSUP_MESSAGE_CLASS_SMS (2),
OSMO_GSUP_MESSAGE_CLASS_USSD (3),
- OSMO_GSUP_MESSAGE_CLASS_INTER_MSC (4)
+ OSMO_GSUP_MESSAGE_CLASS_INTER_MSC (4),
+ OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG (5)
} with { variant "FIELDLENGTH(8)" };
type record GSUP_MSISDN {
@@ -191,6 +198,45 @@ type record GSUP_AN_APDU {
octetstring pdu
};
+type union GSUP_PDP_Address {
+ GSUP_PDP_Address_IPv4 ipv4,
+ GSUP_PDP_Address_IPv6 ipv6,
+ GSUP_PDP_Address_IPv4v6 ipv4v6,
+ GSUP_PDP_Address_unknown other
+} with { variant "TAG(ipv4, pdp_typenum = '21'O;
+ ipv6, pdp_typenum = '57'O;
+ ipv4v6, pdp_typenum = '8D'O;
+ other, OTHERWISE;)" };
+
+type record GSUP_PDP_Address_IPv4 {
+ BIT4 spare,
+ BIT4 pdp_typeorg,
+ OCT1 pdp_typenum,
+ OCT4 ipv4_address optional
+};
+
+type record GSUP_PDP_Address_IPv6 {
+ BIT4 spare,
+ BIT4 pdp_typeorg,
+ OCT1 pdp_typenum,
+ OCT16 ipv6_address optional
+};
+
+type record GSUP_PDP_Address_IPv4v6 {
+ BIT4 spare,
+ BIT4 pdp_typeorg,
+ OCT1 pdp_typenum,
+ OCT4 ipv4_address optional,
+ OCT16 ipv6_address optional
+};
+
+type record GSUP_PDP_Address_unknown {
+ BIT4 spare,
+ BIT4 pdp_typeorg,
+ OCT1 pdp_typenum,
+ octetstring addr optional
+};
+
type record GSUP_IE {
GSUP_IEI tag,
uint8_t len,
@@ -200,6 +246,7 @@ type record GSUP_IE {
cause, tag = OSMO_GSUP_CAUSE_IE;
cancel_type, tag = OSMO_GSUP_CANCEL_TYPE_IE;
auth_tuple, tag = OSMO_GSUP_AUTH_TUPLE_IE;
+ pdp_info_compl, tag = OSMO_GSUP_PDP_INFO_COMPL_IE;
auts, tag = OSMO_GSUP_AUTS_IE;
rand, tag = OSMO_GSUP_RAND_IE;
sres, tag = OSMO_GSUP_SRES_IE;
@@ -212,10 +259,12 @@ type record GSUP_IE {
hlr_number, tag = OSMO_GSUP_HLR_NUMBER_IE;
cn_domain, tag = OSMO_GSUP_CN_DOMAIN_IE;
pdp_info, tag = OSMO_GSUP_PDP_INFO_IE;
+ pdp_address, tag = OSMO_GSUP_PDP_ADDRESS_IE;
apn, tag = OSMO_GSUP_ACCESS_POINT_NAME_IE;
pdp_qos, tag = OSMO_GSUP_PDP_QOS_IE;
- pdp_type, tag = OSMO_GSUP_PDP_TYPE_IE;
charg_char, tag = OSMO_GSUP_CHARG_CHAR_IE;
+ pco, tag = OSMO_GSUP_PCO_IE;
+ pdp_ctx_id, tag = OSMO_GSUP_PDP_CONTEXT_ID_IE;
session_state, tag = OSMO_GSUP_SESSION_STATE_IE;
session_id, tag = OSMO_GSUP_SESSION_ID_IE;
ss_info, tag = OSMO_GSUP_SS_INFO_IE;
@@ -256,8 +305,8 @@ type union GSUP_IeValue {
hexstring imsi,
integer cause,
GSUP_CancelType cancel_type,
- //boolean pdp_info_compl,
- //boolean freeze_ptmsi,
+ octetstring pdp_info_compl,
+ //octetstring freeze_ptmsi,
GSUP_IEs auth_tuple,
octetstring auts,
octetstring rand,
@@ -272,10 +321,12 @@ type union GSUP_IeValue {
GSUP_CnDomain cn_domain,
/* PDP context + nested IEs */
GSUP_IEs pdp_info,
+ OCT1 pdp_ctx_id,
octetstring apn,
octetstring pdp_qos,
- OCT2 pdp_type,
+ GSUP_PDP_Address pdp_address,
octetstring charg_char,
+ PCO_DATA pco,
/* Session information */
GSUP_SessionState session_state,
OCT4 session_id,
@@ -314,595 +365,15 @@ type record GSUP_PDU {
GSUP_IEs ies
};
+type record of GSUP_PDU GSUP_PDUs;
+
+
external function enc_GSUP_PDU(in GSUP_PDU msg) return octetstring
with { extension "prototype(convert) encode(RAW)" };
external function dec_GSUP_PDU(in octetstring msg) return GSUP_PDU
with { extension "prototype(convert) decode(RAW)" };
-function f_gsup_postprocess_decoded(inout GSUP_PDU gsup) {
- if (gsup.ies[0].tag == OSMO_GSUP_IMSI_IE) {
- /* if last digit is 'F', then there's an odd number of digits and we must strip the F */
- var integer num_digits := lengthof(gsup.ies[0].val.imsi);
- if (gsup.ies[0].val.imsi[num_digits-1] == 'F'H) {
- gsup.ies[0].val.imsi := substr(gsup.ies[0].val.imsi, 0, num_digits-1);
- }
- }
-}
-
-function f_gsup_preprocess_encoded(inout GSUP_PDU gsup) {
- if (ischosen(gsup.ies[0].val.imsi)) {
- /* if number of digits is odd, add a 'F' as padding at the end */
- var integer num_digits := lengthof(gsup.ies[0].val.imsi);
- if (num_digits rem 2 == 1) {
- gsup.ies[0].val.imsi := gsup.ies[0].val.imsi & 'F'H;
- }
- }
-}
-
-template (value) GSUP_MSISDN ts_GSUP_MSISDN(hexstring digits,
- BIT3 ton := '000'B,
- BIT4 npi := '0000'B) := {
- len := 0, /* overwritten */
- /* numberingPlanIdentification := npi,
- typeOfNumber := ton,
- ext1 := '0'B, */
- digits := digits
-}
-
-template GSUP_MSISDN tr_GSUP_MSISDN(template hexstring digits,
- template BIT3 ton := ?,
- template BIT4 npi := ?) := {
- len := ?,
- /* numberingPlanIdentification := npi,
- typeOfNumber := ton,
- ext1 := '0'B, */
- digits := digits
-}
-
-
-
-template GSUP_IE ts_GSUP_IE_AuthTuple2G(octetstring rand, octetstring sres,
- octetstring kc) := {
- tag := OSMO_GSUP_AUTH_TUPLE_IE,
- len := 0, /* overwritten */
- val := {
- auth_tuple := {
- valueof(ts_GSUP_IE_RAND(rand)),
- valueof(ts_GSUP_IE_SRES(sres)),
- valueof(ts_GSUP_IE_Kc(kc))
- }
- }
-}
-
-template GSUP_IE ts_GSUP_IE_AuthTuple2G3G(octetstring rand, octetstring sres,
- octetstring kc, octetstring ik,
- octetstring ck, octetstring autn,
- octetstring res) := {
- tag := OSMO_GSUP_AUTH_TUPLE_IE,
- len := 0, /* overwritten */
- val := {
- auth_tuple := {
- valueof(ts_GSUP_IE_RAND(rand)),
- valueof(ts_GSUP_IE_SRES(sres)),
- valueof(ts_GSUP_IE_Kc(kc)),
- valueof(ts_GSUP_IE_IK(ik)),
- valueof(ts_GSUP_IE_CK(ck)),
- valueof(ts_GSUP_IE_AUTN(autn)),
- valueof(ts_GSUP_IE_RES(res))
- }
- }
-}
-
-template GSUP_IE ts_GSUP_IE_PdpInfo(octetstring apn, octetstring pdp_type, octetstring pdp_qos) := {
- tag := OSMO_GSUP_PDP_INFO_IE,
- len := 0, /* overwritten */
- val := {
- pdp_info := {
- valueof(ts_GSUP_IE_APN(apn)),
- valueof(ts_GSUP_IE_PDP_TYPE(pdp_type)),
- valueof(ts_GSUP_IE_PDP_QOS(pdp_qos))
- }
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_PDP_TYPE(OCT2 pdp_type) := {
- tag := OSMO_GSUP_PDP_TYPE_IE,
- len := 0,
- val := {
- pdp_type := pdp_type
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_PDP_QOS(octetstring pdp_qos) := {
- tag := OSMO_GSUP_PDP_QOS_IE,
- len := 0,
- val := {
- pdp_qos := pdp_qos
- }
-}
-
-
-template GSUP_PDU tr_GSUP(template GSUP_MessageType msgt := ?, template GSUP_IEs ies := *) := {
- msg_type := msgt,
- ies := ies
-}
-
-template GSUP_PDU tr_GSUP_IMSI(template GSUP_MessageType msgt := ?, template hexstring imsi) := {
- msg_type := msgt,
- ies := { tr_GSUP_IE_IMSI(imsi), * }
-}
-
-template GSUP_PDU ts_GSUP(GSUP_MessageType msgt, GSUP_IEs ies := {}) := {
- msg_type := msgt,
- ies := ies
-}
-
-template (value) GSUP_IMEI ts_GSUP_IMEI(hexstring digits) := {
- len := 0, /* overwritten */
- digits := digits
-}
-
-template GSUP_IMEI tr_GSUP_IMEI(template hexstring digits) := {
- len := ?,
- digits := digits
-}
-
-
-template (value) GSUP_PDU ts_GSUP_SAI_REQ(hexstring imsi) :=
- ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, { valueof(ts_GSUP_IE_IMSI(imsi)) });
-
-template (value) GSUP_PDU ts_GSUP_SAI_REQ_EPS(hexstring imsi) :=
- ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_CURRENT_RAT_TYPE(RAT_TYPE_EUTRAN_SGs))
- });
-
-template (value) GSUP_PDU ts_GSUP_SAI_REQ_NUM_AUTH(hexstring imsi, OCT1 num_auth_vectors) :=
- ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_NUM_VECTORS_REQ(num_auth_vectors))
- });
-
-template GSUP_PDU tr_GSUP_SAI_REQ(template hexstring imsi) :=
- tr_GSUP_IMSI(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, imsi);
-
-template GSUP_PDU tr_GSUP_SAI_REQ_UMTS_AKA_RESYNC(
- template hexstring imsi,
- template octetstring auts,
- template octetstring rand) :=
- tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST, {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_AUTS(auts),
- tr_GSUP_IE_RAND(rand),
- *
- });
-
-template (value) GSUP_PDU ts_GSUP_SAI_RES(hexstring imsi, GSUP_IE auth_tuple) :=
- ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT, {
- valueof(ts_GSUP_IE_IMSI(imsi)), auth_tuple });
-
-template GSUP_PDU tr_GSUP_SAI_ERR(template hexstring imsi, template integer cause) :=
- tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR, {
- tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause) });
-
-template (value) GSUP_PDU ts_GSUP_SAI_ERR(hexstring imsi, integer cause) :=
- ts_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
-
-
-template GSUP_PDU tr_GSUP_SAI_RES(template hexstring imsi) :=
- tr_GSUP(OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT, {
- tr_GSUP_IE_IMSI(imsi), *, tr_GSUP_IE(OSMO_GSUP_AUTH_TUPLE_IE), * });
-
-template GSUP_PDU ts_GSUP_UL_REQ(hexstring imsi, GSUP_CnDomain dom := OSMO_GSUP_CN_DOMAIN_PS,
- template octetstring source_name := omit) :=
- ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST, f_gen_ts_ies(imsi, dom := dom,
- source_name := source_name));
-
-template GSUP_PDU tr_GSUP_UL_REQ(template hexstring imsi) :=
- tr_GSUP_IMSI(OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST, imsi);
-
-template (value) GSUP_PDU ts_GSUP_UL_RES(hexstring imsi, octetstring destination_name := ''O) :=
- ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT, { valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_Destination_Name(destination_name))});
-
-template GSUP_PDU tr_GSUP_UL_RES(template hexstring imsi, template octetstring destination_name := omit) :=
- tr_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT, f_gen_tr_ies(imsi, destination_name := destination_name));
-
-template (value) GSUP_PDU ts_GSUP_UL_ERR(hexstring imsi, integer cause) :=
- ts_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
-
-template GSUP_PDU tr_GSUP_UL_ERR(template hexstring imsi, template integer cause := ?,
- template octetstring destination_name := omit) :=
- tr_GSUP(OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR,
- f_gen_tr_ies(imsi, cause := cause, destination_name := destination_name));
-
-template (value) GSUP_PDU ts_GSUP_ISD_REQ(hexstring imsi, hexstring msisdn, octetstring destination_name := ''O) :=
- ts_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_REQUEST, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_MSISDN(msisdn)),
- valueof(ts_GSUP_IE_Destination_Name(destination_name))});
-
-template GSUP_PDU tr_GSUP_ISD_REQ(template hexstring imsi, template hexstring msisdn := ?,
- template octetstring destination_name := omit) :=
- tr_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_REQUEST,
- f_gen_tr_ies(imsi, msisdn := msisdn, destination_name := destination_name));
-
-template GSUP_PDU ts_GSUP_ISD_RES(hexstring imsi,
- template octetstring source_name := omit,
- template octetstring destination_name := omit) :=
- ts_GSUP(OSMO_GSUP_MSGT_INSERT_DATA_RESULT,
- f_gen_ts_ies(imsi, source_name := source_name,
- destination_name := destination_name));
-
-template GSUP_PDU tr_GSUP_ISD_RES(template hexstring imsi) :=
- tr_GSUP_IMSI(OSMO_GSUP_MSGT_INSERT_DATA_RESULT, imsi);
-
-template GSUP_PDU tr_GSUP_AUTH_FAIL_IND(hexstring imsi) :=
- tr_GSUP_IMSI(OSMO_GSUP_MSGT_AUTH_FAIL_REPORT, imsi);
-
-template (value) GSUP_PDU ts_GSUP_CL_REQ(hexstring imsi, GSUP_CancelType ctype) :=
- ts_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_CancelType(ctype)) });
-
-template GSUP_PDU tr_GSUP_CL_RES(template hexstring imsi) :=
- tr_GSUP_IMSI(OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT, imsi);
-
-template GSUP_PDU tr_GSUP_CL_ERR(template hexstring imsi, template integer cause := ?) :=
- tr_GSUP(OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR, {
- tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause), * });
-
-template (value) GSUP_PDU ts_GSUP_PURGE_MS_REQ(hexstring imsi, GSUP_CnDomain dom) :=
- ts_GSUP(OSMO_GSUP_MSGT_PURGE_MS_REQUEST, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_CnDomain(dom)) });
-
-template GSUP_PDU tr_GSUP_PURGE_MS_REQ(template hexstring imsi, template GSUP_CnDomain dom := ?) :=
- tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_REQUEST, {
- tr_GSUP_IE_IMSI(imsi), *, tr_GSUP_IE_CnDomain(dom) });
-
-template (value) GSUP_PDU ts_GSUP_PURGE_MS_RES(hexstring imsi) :=
- ts_GSUP(OSMO_GSUP_MSGT_PURGE_MS_RESULT, {
- valueof(ts_GSUP_IE_IMSI(imsi)) });
-
-template GSUP_PDU tr_GSUP_PURGE_MS_RES(template hexstring imsi) :=
- tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_RESULT, {
- tr_GSUP_IE_IMSI(imsi), * });
-
-template GSUP_PDU tr_GSUP_PURGE_MS_ERR(template hexstring imsi, template integer cause) :=
- tr_GSUP(OSMO_GSUP_MSGT_PURGE_MS_ERROR, {
- tr_GSUP_IE_IMSI(imsi), tr_GSUP_IE_Cause(cause) });
-
-template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_REQ(hexstring imsi, hexstring imei,
- template (omit) octetstring source_name := omit) :=
- ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST, f_gen_ts_ies(imsi, imei := imei, source_name := source_name));
-
-template GSUP_PDU tr_GSUP_CHECK_IMEI_REQ(
- template hexstring imsi,
- template hexstring imei
-) := tr_GSUP(
- OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_IMEI(imei),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_RES(hexstring imsi, GSUP_IMEIResult result) :=
- ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_RESULT, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_IMEI_Result(result)) });
-
-template GSUP_PDU tr_GSUP_CHECK_IMEI_RES(template hexstring imsi, template GSUP_IMEIResult result,
- template octetstring destination_name := omit) :=
- tr_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_RESULT,
- f_gen_tr_ies(imsi, imei_result := result, destination_name := destination_name));
-
-template (value) GSUP_PDU ts_GSUP_CHECK_IMEI_ERR(hexstring imsi, integer cause) :=
- ts_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_ERROR, {
- valueof(ts_GSUP_IE_IMSI(imsi)), valueof(ts_GSUP_IE_Cause(cause)) });
-
-template GSUP_PDU tr_GSUP_CHECK_IMEI_ERR(template hexstring imsi, template integer cause,
- template octetstring destination_name := omit) :=
- tr_GSUP(OSMO_GSUP_MSGT_CHECK_IMEI_ERROR, f_gen_tr_ies(imsi, cause := cause, destination_name := destination_name));
-
-
-template (value) GSUP_IE ts_GSUP_IE_CancelType(GSUP_CancelType ctype) := {
- tag := OSMO_GSUP_CANCEL_TYPE_IE,
- len := 0, /* overwritten */
- val := {
- cancel_type := ctype
- }
-}
-
-template GSUP_IE tr_GSUP_IE_CancelType(template GSUP_CancelType ctype) :=
- tr_GSUP_IE(OSMO_GSUP_CANCEL_TYPE_IE, GSUP_IeValue:{cancel_type:=ctype});
-
-template GSUP_IE tr_GSUP_IE_CnDomain(template GSUP_CnDomain domain) :=
- tr_GSUP_IE(OSMO_GSUP_CN_DOMAIN_IE, GSUP_IeValue:{cn_domain:=domain});
-
-template GSUP_IE tr_GSUP_IE(template GSUP_IEI iei, template GSUP_IeValue val := ?) := {
- tag := iei,
- len := ?,
- val := val
-}
-
-template (value) GSUP_IE ts_GSUP_IE_IMSI(hexstring imsi) := {
- tag := OSMO_GSUP_IMSI_IE,
- len := 0, /* overwritten */
- val := {
- imsi := imsi
- }
-}
-
-template GSUP_IE tr_GSUP_IE_IMSI(template hexstring imsi) := {
- tag := OSMO_GSUP_IMSI_IE,
- len := ?,
- val := {
- imsi := imsi
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_MSISDN(hexstring msisdn) := {
- tag := OSMO_GSUP_MSISDN_IE,
- len := 0, /* overwritten */
- val := {
- msisdn := ts_GSUP_MSISDN(msisdn)
- }
-}
-
-template GSUP_IE tr_GSUP_IE_MSISDN(template hexstring msisdn) := {
- tag := OSMO_GSUP_MSISDN_IE,
- len := ?,
- val := {
- msisdn := tr_GSUP_MSISDN(msisdn)
- }
-}
-
-
-template (value) GSUP_IE ts_GSUP_IE_Cause(integer cause) := {
- tag := OSMO_GSUP_CAUSE_IE,
- len := 0, /* overwritten */
- val := {
- cause := cause
- }
-}
-
-template GSUP_IE tr_GSUP_IE_Cause(template integer cause) := {
- tag := OSMO_GSUP_CAUSE_IE,
- len := ?,
- val := {
- cause := cause
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_AUTS(octetstring auts) := {
- tag := OSMO_GSUP_AUTS_IE,
- len := 0, /* overwritten */
- val := {
- auts := auts
- }
-}
-
-template GSUP_IE tr_GSUP_IE_AUTS(template octetstring auts) := {
- tag := OSMO_GSUP_AUTS_IE,
- len := ?,
- val := {
- auts := auts
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_RAND(octetstring rand) := {
- tag := OSMO_GSUP_RAND_IE,
- len := 0, /* overwritten */
- val := {
- rand := rand
- }
-}
-
-template GSUP_IE tr_GSUP_IE_RAND(template octetstring rand) := {
- tag := OSMO_GSUP_RAND_IE,
- len := ?,
- val := {
- rand := rand
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SRES(octetstring sres) := {
- tag := OSMO_GSUP_SRES_IE,
- len := 0, /* overwritten */
- val := {
- sres := sres
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_Kc(octetstring kc) := {
- tag := OSMO_GSUP_KC_IE,
- len := 0, /* overwritten */
- val := {
- kc := kc
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_IK(octetstring ik) := {
- tag := OSMO_GSUP_IK_IE,
- len := 0, /* overwritten */
- val := {
- ik := ik
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_CK(octetstring ck) := {
- tag := OSMO_GSUP_CK_IE,
- len := 0, /* overwritten */
- val := {
- ck := ck
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_AUTN(octetstring autn) := {
- tag := OSMO_GSUP_AUTN_IE,
- len := 0, /* overwritten */
- val := {
- autn := autn
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_RES(octetstring res) := {
- tag := OSMO_GSUP_RES_IE,
- len := 0, /* overwritten */
- val := {
- res := res
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_APN(octetstring apn) := {
- tag := OSMO_GSUP_ACCESS_POINT_NAME_IE,
- len := 0, /* overwritten */
- val := {
- apn := apn
- }
-}
-
-template GSUP_IE ts_GSUP_IE_CnDomain(template GSUP_CnDomain dom) := {
- tag := OSMO_GSUP_CN_DOMAIN_IE,
- len := 0, /* overwritten */
- val := {
- cn_domain := dom
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SessionId(OCT4 sid) := {
- tag := OSMO_GSUP_SESSION_ID_IE,
- len := 0, /* overwritten */
- val := {
- session_id := sid
- }
-}
-template GSUP_IE tr_GSUP_IE_SessionId(template OCT4 sid) := {
- tag := OSMO_GSUP_SESSION_ID_IE,
- len := ?,
- val := {
- session_id := sid
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SessionState(GSUP_SessionState state) := {
- tag := OSMO_GSUP_SESSION_STATE_IE,
- len := 0, /* overwritten */
- val := {
- session_state := state
- }
-}
-template GSUP_IE tr_GSUP_IE_SessionState(template GSUP_SessionState state) := {
- tag := OSMO_GSUP_SESSION_STATE_IE,
- len := ?,
- val := {
- session_state := state
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_MR(OCT1 ref) := {
- tag := OSMO_GSUP_SM_RP_MR_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_mr := ref
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_MR(template OCT1 ref) := {
- tag := OSMO_GSUP_SM_RP_MR_IE,
- len := ?,
- val := {
- sm_rp_mr := ref
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_CAUSE(OCT1 cause) := {
- tag := OSMO_GSUP_SM_RP_CAUSE_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_cause := cause
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_CAUSE(template OCT1 cause) := {
- tag := OSMO_GSUP_SM_RP_CAUSE_IE,
- len := ?,
- val := {
- sm_rp_cause := cause
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_MMS(OCT1 mms) := {
- tag := OSMO_GSUP_SM_RP_MMS_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_mms := mms
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_MMS(template OCT1 mms) := {
- tag := OSMO_GSUP_SM_RP_MMS_IE,
- len := ?,
- val := {
- sm_rp_mms := mms
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_IMEI(hexstring imei) := {
- tag := OSMO_GSUP_IMEI_IE,
- len := 0, /* overwritten */
- val := {
- imei := ts_GSUP_IMEI(imei)
- }
-}
-template GSUP_IE tr_GSUP_IE_IMEI(template hexstring imei) := {
- tag := OSMO_GSUP_IMEI_IE,
- len := ?,
- val := {
- imei := tr_GSUP_IMEI(imei)
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_IMEI_Result(GSUP_IMEIResult result) := {
- tag := OSMO_GSUP_IMEI_RESULT_IE,
- len := 0, /* overwritten */
- val := {
- imei_result := result
- }
-}
-template GSUP_IE tr_GSUP_IE_IMEI_Result(template GSUP_IMEIResult result) := {
- tag := OSMO_GSUP_IMEI_RESULT_IE,
- len := ?,
- val := {
- imei_result := result
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_NUM_VECTORS_REQ(OCT1 num) := {
- tag := OSMO_GSUP_NUM_VECTORS_REQ_IE,
- len := 0, /* overwritten */
- val := {
- num_auth_vectors := num
- }
-}
-template GSUP_IE tr_GSUP_IE_NUM_VECTORS_REQ(template OCT1 num) := {
- tag := OSMO_GSUP_NUM_VECTORS_REQ_IE,
- len := ?,
- val := {
- num_auth_vectors := num
- }
-}
-
-
-/* Possible identity types for SM-RP-{OA|DA} IEs */
-type enumerated GSUP_SM_RP_ODA_IdType {
- OSMO_GSUP_SM_RP_ODA_ID_NONE ('00'O),
- OSMO_GSUP_SM_RP_ODA_ID_IMSI ('01'O),
- OSMO_GSUP_SM_RP_ODA_ID_MSISDN ('02'O),
- OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR ('03'O),
- /* Special value for noSM-RP-DA and noSM-RP-OA */
- OSMO_GSUP_SM_RP_ODA_ID_NULL ('FF'O)
-} with { variant "FIELDLENGTH(8)" };
-
/* See 3GPP TS 24.011, figures 8.5 and 8.6 */
type record GSUP_SM_RP_Addr {
BIT1 ext, /* Extension? */
@@ -914,27 +385,6 @@ type record GSUP_SM_RP_Addr {
variant "PADDING_PATTERN('1111'B)"
};
-private function f_pad_SM_RP_Addr(template hexstring number)
-return template hexstring {
- if (isvalue(number) and not istemplatekind(number, "omit")) {
- return f_pad_bcd_number(valueof(number));
- } else {
- return number;
- }
-}
-
-template GSUP_SM_RP_Addr t_GSUP_SM_RP_Addr(template hexstring number,
- template BIT4 npi := '0001'B,
- template BIT3 ton := '001'B,
- template BIT1 ext := '1'B) := {
- ext := ext,
- ton := ton,
- npi := npi,
- /* Work around TITAN's padding problems: encoding works fine,
- * but it does not consider 'F'H as padding in decoded data. */
- number := f_pad_SM_RP_Addr(number)
-}
-
/**
* SM-RP-DA represents the SM Destination Address, see 7.6.8.1.
* It can be either of the following:
@@ -961,57 +411,6 @@ type record GSUP_SM_RP_DA {
)"
};
-template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_IMSI(hexstring imsi) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_IMSI,
- id_enc := { imsi := imsi }
-}
-template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_IMSI(template hexstring imsi) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_IMSI,
- id_enc := { imsi := imsi }
-}
-
-template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_MSISDN(GSUP_SM_RP_Addr msisdn) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
- id_enc := { msisdn := msisdn }
-}
-template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_MSISDN(template GSUP_SM_RP_Addr msisdn) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
- id_enc := { msisdn := msisdn }
-}
-
-template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_SMSC_ADDR(GSUP_SM_RP_Addr smsc_addr) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
- id_enc := { smsc_addr := smsc_addr }
-}
-template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_SMSC_ADDR(template GSUP_SM_RP_Addr smsc_addr) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
- id_enc := { smsc_addr := smsc_addr }
-}
-
-template (value) GSUP_SM_RP_DA ts_GSUP_SM_RP_DA_NULL := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
- id_enc := omit
-}
-template GSUP_SM_RP_DA tr_GSUP_SM_RP_DA_NULL := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
- id_enc := omit
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_DA(GSUP_SM_RP_DA val) := {
- tag := OSMO_GSUP_SM_RP_DA_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_da := val
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_DA(template GSUP_SM_RP_DA val) := {
- tag := OSMO_GSUP_SM_RP_DA_IE,
- len := ?,
- val := {
- sm_rp_da := val
- }
-}
-
/**
* SM-RP-OA represents the SM Originating Address, see 7.6.8.2.
* It can be either of the following:
@@ -1033,64 +432,6 @@ type record GSUP_SM_RP_OA {
)"
};
-template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_MSISDN(GSUP_SM_RP_Addr msisdn) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
- id_enc := { msisdn := msisdn }
-}
-template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_MSISDN(template GSUP_SM_RP_Addr msisdn) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_MSISDN,
- id_enc := { msisdn := msisdn }
-}
-
-template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_SMSC_ADDR(GSUP_SM_RP_Addr smsc_addr) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
- id_enc := { smsc_addr := smsc_addr }
-}
-template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_SMSC_ADDR(template GSUP_SM_RP_Addr smsc_addr) := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR,
- id_enc := { smsc_addr := smsc_addr }
-}
-
-template (value) GSUP_SM_RP_OA ts_GSUP_SM_RP_OA_NULL := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
- id_enc := omit
-}
-template GSUP_SM_RP_OA tr_GSUP_SM_RP_OA_NULL := {
- id_type := OSMO_GSUP_SM_RP_ODA_ID_NULL,
- id_enc := omit
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_OA(GSUP_SM_RP_OA val) := {
- tag := OSMO_GSUP_SM_RP_OA_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_oa := val
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_OA(template GSUP_SM_RP_OA val) := {
- tag := OSMO_GSUP_SM_RP_OA_IE,
- len := ?,
- val := {
- sm_rp_oa := val
- }
-}
-
-/* SM-RP-UI represents the SM TPDU, see 7.6.8.4 */
-template (value) GSUP_IE ts_GSUP_IE_SM_RP_UI(octetstring val) := {
- tag := OSMO_GSUP_SM_RP_UI_IE,
- len := 0, /* overwritten */
- val := {
- sm_rp_ui := val
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_RP_UI(template octetstring val) := {
- tag := OSMO_GSUP_SM_RP_UI_IE,
- len := ?,
- val := {
- sm_rp_ui := val
- }
-}
-
/* SM Alert Reason types, see 7.6.8.8 */
type enumerated GSUP_SM_ALERT_RSN_Type {
GSUP_SM_ALERT_RSN_TYPE_NONE ('00'O),
@@ -1098,684 +439,14 @@ type enumerated GSUP_SM_ALERT_RSN_Type {
GSUP_SM_ALERT_RSN_TYPE_MEM_AVAIL ('02'O)
} with { variant "FIELDLENGTH(8)" };
-/* SM Alert Reason IE (used in READY-FOR-SM), see 7.6.8.8 */
-template (value) GSUP_IE ts_GSUP_IE_SM_ALERT_RSN(GSUP_SM_ALERT_RSN_Type rsn) := {
- tag := OSMO_GSUP_SM_ALERT_RSN_IE,
- len := 0, /* overwritten */
- val := {
- sm_alert_rsn := rsn
- }
-}
-template GSUP_IE tr_GSUP_IE_SM_ALERT_RSN(template GSUP_SM_ALERT_RSN_Type rsn) := {
- tag := OSMO_GSUP_SM_ALERT_RSN_IE,
- len := ?,
- val := {
- sm_alert_rsn := rsn
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_SSInfo(octetstring ss) := {
- tag := OSMO_GSUP_SS_INFO_IE,
- len := 0, /* overwritten */
- val := {
- ss_info := ss
- }
-}
-template GSUP_IE tr_GSUP_IE_SSInfo(template octetstring ss) := {
- tag := OSMO_GSUP_SS_INFO_IE,
- len := ?,
- val := {
- ss_info := ss
- }
-}
-
-template GSUP_IE tr_GSUP_IE_Message_Class(template GSUP_Message_Class val) := {
- tag := OSMO_GSUP_MESSAGE_CLASS_IE,
- len := ?,
- val := {
- message_class := val
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_Message_Class(GSUP_Message_Class val) := {
- tag := OSMO_GSUP_MESSAGE_CLASS_IE,
- len := 0, /* overwritten */
- val := {
- message_class := val
- }
-}
-
-template GSUP_IE tr_GSUP_IE_Source_Name(template octetstring name) := {
- tag := OSMO_GSUP_SOURCE_NAME_IE,
- len := ?,
- val := {
- source_name := name
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_Source_Name(octetstring name) := {
- tag := OSMO_GSUP_SOURCE_NAME_IE,
- len := 0, /* overwritten */
- val := {
- source_name := name
- }
-}
-
-template GSUP_IE tr_GSUP_IE_Destination_Name(template octetstring name) := {
- tag := OSMO_GSUP_DESTINATION_NAME_IE,
- len := ?,
- val := {
- destination_name := name
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_Destination_Name(octetstring name) := {
- tag := OSMO_GSUP_DESTINATION_NAME_IE,
- len := 0, /* overwritten */
- val := {
- destination_name := name
- }
-}
-
-template GSUP_IE tr_GSUP_IE_AN_APDU(template GSUP_AN_APDU an_apdu) := {
- tag := OSMO_GSUP_AN_APDU_IE,
- len := ?,
- val := {
- an_apdu := an_apdu
- }
-}
-
-template (value) GSUP_IE ts_GSUP_IE_AN_APDU(GSUP_AN_APDU an_apdu) := {
- tag := OSMO_GSUP_AN_APDU_IE,
- len := 0, /* overwritten */
- val := {
- an_apdu := an_apdu
- }
-}
-
-template (present) GSUP_IE tr_GSUP_IE_SUPPORTED_RAT_TYPES(template (present) GSUP_RatTypes ratt) := {
- tag := OSMO_GSUP_SUPPORTED_RAT_TYPES_IE,
- len := ?,
- val := {
- supported_rat_types := ratt
- }
-}
-template (value) GSUP_IE ts_GSUP_IE_SUPPORTED_RAT_TYPES(GSUP_RatTypes ratt) := {
- tag := OSMO_GSUP_SUPPORTED_RAT_TYPES_IE,
- len := 0, /* overwritten */
- val := {
- supported_rat_types := ratt
- }
-}
-
-template (present) GSUP_IE tr_GSUP_IE_CURRENT_RAT_TYPE(template (present) GSUP_RatType ratt) := {
- tag := OSMO_GSUP_CURRENT_RAT_TYPE_IE,
- len := ?,
- val := {
- current_rat_type := ratt
- }
-}
-template (value) GSUP_IE ts_GSUP_IE_CURRENT_RAT_TYPE(GSUP_RatType ratt) := {
- tag := OSMO_GSUP_CURRENT_RAT_TYPE_IE,
- len := 0, /* overwritten */
- val := {
- current_rat_type := ratt
- }
-}
-
-private function f_gen_ts_ies(hexstring imsi,
- template hexstring imei := omit,
- template GSUP_CnDomain dom := omit,
- template octetstring source_name := omit,
- template octetstring destination_name := omit
- ) return GSUP_IEs {
- var GSUP_IEs ies := {
- valueof(ts_GSUP_IE_IMSI(imsi))
- };
-
- if (isvalue(dom)) {
- ies := ies & { valueof(ts_GSUP_IE_CnDomain(dom)) };
- }
-
- if (isvalue(imei)) {
- ies := ies & { valueof(ts_GSUP_IE_IMEI(valueof(imei))) };
- }
-
- if (isvalue(source_name)) {
- ies := ies & { valueof(ts_GSUP_IE_Source_Name(valueof(source_name))) };
- }
-
- if (isvalue(destination_name)) {
- ies := ies & { valueof(ts_GSUP_IE_Destination_Name(valueof(destination_name))) };
- }
-
- return ies;
-}
-
-private function f_gen_tr_ies(template hexstring imsi,
- template integer cause := omit,
- template hexstring msisdn := omit,
- template GSUP_IMEIResult imei_result := omit,
- template octetstring source_name := omit,
- template octetstring destination_name := omit
- ) return template GSUP_IEs {
- var template GSUP_IEs ies := {
- tr_GSUP_IE_IMSI(imsi)
- };
- var integer idx := 1;
-
- if (isvalue(cause)) {
- ies[idx] := tr_GSUP_IE_Cause(cause);
- idx := idx + 1;
- }
-
- if (isvalue(msisdn)) {
- ies[idx] := tr_GSUP_IE_MSISDN(msisdn);
- idx := idx + 1;
- }
-
- if (isvalue(imei_result)) {
- ies[idx] := tr_GSUP_IE_IMEI_Result(imei_result);
- idx := idx + 1;
- }
-
- if (isvalue(source_name)) {
- ies[idx] := tr_GSUP_IE_Source_Name(source_name);
- idx := idx + 1;
- }
-
- ies[idx] := *;
- idx := idx + 1;
-
- if (isvalue(destination_name)) {
- ies[idx] := tr_GSUP_IE_Destination_Name(destination_name);
- idx := idx + 1;
- }
-
- return ies;
-}
-
-private function f_gen_ts_ss_ies(
- hexstring imsi,
- OCT4 sid,
- GSUP_SessionState state,
- template (omit) octetstring ss := omit,
- template (omit) integer cause := omit,
- template octetstring source_name := omit
-) return GSUP_IEs {
- /* Mandatory IEs */
- var GSUP_IEs ies := {
- valueof(ts_GSUP_IE_IMSI(imsi))
- };
-
- /* Cause IE is needed for PROC_SS_ERR */
- if (isvalue(cause)) {
- ies := ies & { valueof(ts_GSUP_IE_Cause(valueof(cause))) };
- }
-
- /* Mandatory session IEs */
- ies := ies & { valueof(ts_GSUP_IE_SessionId(sid)) };
- ies := ies & { valueof(ts_GSUP_IE_SessionState(state)) };
-
- /* Optional SS payload */
- if (isvalue(ss)) {
- ies := ies & { valueof(ts_GSUP_IE_SSInfo(valueof(ss))) };
- }
-
- if (isvalue(source_name)) {
- ies := ies & { valueof(ts_GSUP_IE_Source_Name(valueof(source_name))) };
- }
-
- return ies;
-}
-private function f_gen_tr_ss_ies(
- template hexstring imsi,
- template OCT4 sid := ?,
- template GSUP_SessionState state := ?,
- template octetstring ss := omit,
- template integer cause := omit,
- template octetstring destination_name := omit
-) return template GSUP_IEs {
- /* Mandatory IEs */
- var template GSUP_IEs ies := {
- tr_GSUP_IE_IMSI(imsi)
- };
- var integer idx := 1;
-
- /* Cause IE is needed for PROC_SS_ERR */
- if (istemplatekind(cause, "*")) {
- ies[idx] := *;
- idx := idx + 1;
- } else if (not istemplatekind(cause, "omit")) {
- ies[idx] := tr_GSUP_IE_Cause(cause);
- idx := idx + 1;
- }
-
- /* Mandatory session IEs */
- ies[idx] := tr_GSUP_IE_SessionId(sid);
- ies[idx + 1] := tr_GSUP_IE_SessionState(state);
- idx := idx + 2;
-
- /* Optional SS payload */
- if (istemplatekind(ss, "*")) {
- ies[idx] := *;
- idx := idx + 1;
- } else if (not istemplatekind(ss, "omit")) {
- ies[idx] := tr_GSUP_IE_SSInfo(ss);
- idx := idx + 1;
- }
-
- if (isvalue(destination_name)) {
- ies[idx] := tr_GSUP_IE_Destination_Name(destination_name);
- idx := idx + 1;
- }
-
- /* the GSUP Message Class IE is optional, as old implementations don't have it yet */
- var template GSUP_IEs ies2 := ies;
- ies2[idx] := tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_USSD);
- idx := idx + 1;
-
- return (ies, ies2);
-}
-
-template (value) GSUP_PDU ts_GSUP_PROC_SS_REQ(
- hexstring imsi,
- OCT4 sid,
- GSUP_SessionState state,
- template (omit) octetstring ss := omit,
- template (omit) octetstring source_name := omit
-) := ts_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_REQUEST,
- f_gen_ts_ss_ies(imsi, sid, state, ss, source_name := source_name)
-);
-template GSUP_PDU tr_GSUP_PROC_SS_REQ(
- template hexstring imsi,
- template OCT4 sid := ?,
- template GSUP_SessionState state := ?,
- template octetstring ss := *
-) := tr_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_REQUEST,
- f_gen_tr_ss_ies(imsi, sid, state, ss)
-);
-
-template (value) GSUP_PDU ts_GSUP_PROC_SS_RES(
- hexstring imsi,
- OCT4 sid,
- GSUP_SessionState state,
- template (omit) octetstring ss := omit
-) := ts_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_RESULT,
- f_gen_ts_ss_ies(imsi, sid, state, ss)
-);
-template GSUP_PDU tr_GSUP_PROC_SS_RES(
- template hexstring imsi,
- template OCT4 sid := ?,
- template GSUP_SessionState state := ?,
- template octetstring ss := *,
- template octetstring destination_name := omit
-) := tr_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_RESULT,
- f_gen_tr_ss_ies(imsi, sid, state, ss, destination_name := destination_name)
-);
-
-template (value) GSUP_PDU ts_GSUP_PROC_SS_ERR(
- hexstring imsi,
- OCT4 sid,
- GSUP_SessionState state,
- integer cause
-) := ts_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_ERROR,
- f_gen_ts_ss_ies(imsi, sid, state, cause := cause)
-);
-template GSUP_PDU tr_GSUP_PROC_SS_ERR(
- template hexstring imsi,
- template OCT4 sid := ?,
- template GSUP_SessionState state := ?,
- template integer cause := ?
-) := tr_GSUP(
- OSMO_GSUP_MSGT_PROC_SS_ERROR,
- f_gen_tr_ss_ies(imsi, sid, state, cause := cause)
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_REQ(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
- GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
- octetstring sm_rp_ui /* SM TPDU, see 7.6.8.4 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_RP_DA(sm_rp_da)),
- valueof(ts_GSUP_IE_SM_RP_OA(sm_rp_oa)),
- valueof(ts_GSUP_IE_SM_RP_UI(sm_rp_ui))
- }
-);
-template GSUP_PDU tr_GSUP_MO_FORWARD_SM_REQ(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
- template GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
- template octetstring sm_rp_ui /* SM TPDU, see 7.6.8.4 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_DA(sm_rp_da),
- tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
- tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_RES(
- hexstring imsi,
- OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr))
- }
-);
-template GSUP_PDU tr_GSUP_MO_FORWARD_SM_RES(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_FORWARD_SM_ERR(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause))
- }
-);
-template GSUP_PDU tr_GSUP_MO_FORWARD_SM_ERR(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MO_FORWARD_SM_ERROR,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_REQ(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
- GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
- octetstring sm_rp_ui, /* SM TPDU, see 7.6.8.4 */
- OCT1 sm_rp_mms /* MMS (More Messages to Send), see 7.6.8.7 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST,
- {
- /**
- * TODO: add MT-specific fields (and IEs):
- * - smDeliveryTimer
- * - smDeliveryStartTime
- */
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_RP_DA(sm_rp_da)),
- valueof(ts_GSUP_IE_SM_RP_OA(sm_rp_oa)),
- valueof(ts_GSUP_IE_SM_RP_UI(sm_rp_ui)),
- valueof(ts_GSUP_IE_SM_RP_MMS(sm_rp_mms))
- }
-);
-template GSUP_PDU tr_GSUP_MT_FORWARD_SM_REQ(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template GSUP_SM_RP_DA sm_rp_da, /* Destination Address, see 7.6.8.1 */
- template GSUP_SM_RP_OA sm_rp_oa, /* Originating Address, see 7.6.8.2 */
- template octetstring sm_rp_ui, /* SM TPDU, see 7.6.8.4 */
- template OCT1 sm_rp_mms /* MMS (More Messages to Send), see 7.6.8.7 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST,
- {
- /**
- * TODO: add MT-specific fields (and IEs):
- * - smDeliveryTimer
- * - smDeliveryStartTime
- */
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_DA(sm_rp_da),
- tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
- tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
- tr_GSUP_IE_SM_RP_MMS(sm_rp_mms),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_RES(
- hexstring imsi,
- OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr))
- }
-);
-template GSUP_PDU tr_GSUP_MT_FORWARD_SM_RES(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MT_FORWARD_SM_ERR(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause))
- }
-);
-template GSUP_PDU tr_GSUP_MT_FORWARD_SM_ERR(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_REQ(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- GSUP_SM_ALERT_RSN_Type sm_alert_rsn /* SM Alert Reason, see 7.6.8.8 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn))
- }
-);
-template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_REQ(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template GSUP_SM_ALERT_RSN_Type sm_alert_rsn := ? /* SM Alert Reason, see 7.6.8.8 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_RES(
- hexstring imsi,
- OCT1 sm_rp_mr /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr))
- }
-);
-template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_RES(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ? /* Message Reference, see GSM TS 04.11, 8.2.3 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_MO_READY_FOR_SM_ERR(
- hexstring imsi,
- OCT1 sm_rp_mr, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- OCT1 sm_rp_cause /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := ts_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_ERROR,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_SM_RP_MR(sm_rp_mr)),
- valueof(ts_GSUP_IE_SM_RP_CAUSE(sm_rp_cause))
- }
-);
-template GSUP_PDU tr_GSUP_MO_READY_FOR_SM_ERR(
- template hexstring imsi := ?,
- template OCT1 sm_rp_mr := ?, /* Message Reference, see GSM TS 04.11, 8.2.3 */
- template OCT1 sm_rp_cause := ? /* RP-Cause value, see GSM TS 04.11, 8.2.5.4 */
-) := tr_GSUP(
- OSMO_GSUP_MSGT_READY_FOR_SM_ERROR,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
- }
-);
-
-function f_gsup_find_nested_ie(GSUP_IEs ies, GSUP_IEI iei, out GSUP_IeValue ret) return boolean {
- for (var integer i := 0; i < sizeof(ies); i := i+1) {
- if (ies[i].tag == iei) {
- ret := ies[i].val;
- return true;
- }
- }
- return false;
-}
-
-function f_gsup_find_ie(GSUP_PDU msg, GSUP_IEI iei, out GSUP_IeValue ret) return boolean {
- return f_gsup_find_nested_ie(msg.ies, iei, ret);
-}
-
-template GSUP_AN_APDU t_GSUP_AN_APDU(
- template GSUP_AN_PROTO an_proto := ?,
- template octetstring pdu := ?
-) := {
- proto := an_proto,
- pdu := pdu
-};
-
-template GSUP_PDU tr_GSUP_E_AN_APDU(
- template GSUP_MessageType msgt,
- template hexstring imsi := ?,
- template octetstring source_name := ?,
- template octetstring destination_name := ?,
- template GSUP_AN_APDU an_apdu := ?
-) := tr_GSUP(
- msgt,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
- tr_GSUP_IE_Source_Name(source_name),
- tr_GSUP_IE_Destination_Name(destination_name),
- tr_GSUP_IE_AN_APDU(an_apdu)
- }
-);
-
-template GSUP_PDU tr_GSUP_E_NO_PDU(
- template GSUP_MessageType msgt,
- template hexstring imsi := ?,
- template octetstring source_name := ?,
- template octetstring destination_name := ?
-) := tr_GSUP(
- msgt,
- {
- tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
- tr_GSUP_IE_Source_Name(source_name),
- tr_GSUP_IE_Destination_Name(destination_name)
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_E_AN_APDU(
- GSUP_MessageType msgt,
- hexstring imsi,
- octetstring source_name,
- octetstring destination_name,
- GSUP_AN_APDU an_apdu
-) := ts_GSUP(
- msgt,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
- valueof(ts_GSUP_IE_Source_Name(source_name)),
- valueof(ts_GSUP_IE_Destination_Name(destination_name)),
- valueof(ts_GSUP_IE_AN_APDU(an_apdu))
- }
-);
-
-template (value) GSUP_PDU ts_GSUP_E_PrepareHandoverResult(
- hexstring imsi,
- hexstring msisdn,
- octetstring source_name,
- octetstring destination_name,
- GSUP_AN_APDU an_apdu
-) := ts_GSUP(
- OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT,
- {
- valueof(ts_GSUP_IE_IMSI(imsi)),
- valueof(ts_GSUP_IE_MSISDN(msisdn)),
- valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
- valueof(ts_GSUP_IE_Source_Name(source_name)),
- valueof(ts_GSUP_IE_Destination_Name(destination_name)),
- valueof(ts_GSUP_IE_AN_APDU(an_apdu))
- }
-);
+/* Possible identity types for SM-RP-{OA|DA} IEs */
+type enumerated GSUP_SM_RP_ODA_IdType {
+ OSMO_GSUP_SM_RP_ODA_ID_NONE ('00'O),
+ OSMO_GSUP_SM_RP_ODA_ID_IMSI ('01'O),
+ OSMO_GSUP_SM_RP_ODA_ID_MSISDN ('02'O),
+ OSMO_GSUP_SM_RP_ODA_ID_SMSC_ADDR ('03'O),
+ /* Special value for noSM-RP-DA and noSM-RP-OA */
+ OSMO_GSUP_SM_RP_ODA_ID_NULL ('FF'O)
+} with { variant "FIELDLENGTH(8)" };
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/GTP_Emulation.ttcn b/library/GTP_Emulation.ttcn
index 43c034b8..f7c54a19 100644
--- a/library/GTP_Emulation.ttcn
+++ b/library/GTP_Emulation.ttcn
@@ -16,8 +16,10 @@ import from General_Types all;
import from Osmocom_Types all;
import from GTPC_Types all;
import from GTPU_Types all;
-import from GTP_CodecPort all;
-import from GTP_CodecPort_CtrlFunct all;
+import from GTPv1C_CodecPort all;
+import from GTPv1U_CodecPort all;
+import from GTPv1C_CodecPort_CtrlFunct all;
+import from GTPv1U_CodecPort_CtrlFunct all;
/***********************************************************************
* Main Emulation Component
@@ -30,8 +32,8 @@ const integer GTP1U_PORT := 2152;
type record GtpEmulationCfg {
HostName gtpc_bind_ip,
PortNumber gtpc_bind_port,
- HostName gtpu_bind_ip,
- PortNumber gtpu_bind_port,
+ HostName gtpu_bind_ip optional,
+ PortNumber gtpu_bind_port optional,
boolean sgsn_role
};
@@ -43,6 +45,7 @@ type component GTP_Emulation_CT {
/* Communication with Clients */
port GTPEM_PT CLIENT;
port GTPEM_PROC_PT CLIENT_PROC;
+ port GTPEM_PT CLIENT_DEFAULT;
/* Configuration by the user */
var GtpEmulationCfg g_gtp_cfg;
@@ -133,9 +136,17 @@ function f_gtpc_extract_imsi(PDU_GTPC gtp) return template (omit) hexstring {
} else if (ischosen(gtp.gtpc_pdu.identificationResponse) ){
return gtp.gtpc_pdu.identificationResponse.imsi.digits;
} else if (ischosen(gtp.gtpc_pdu.sgsn_ContextRequest)) {
- return gtp.gtpc_pdu.sgsn_ContextRequest.imsi.digits;
+ if (ispresent(gtp.gtpc_pdu.sgsn_ContextRequest.imsi.digits)) {
+ return gtp.gtpc_pdu.sgsn_ContextRequest.imsi.digits;
+ } else {
+ return omit;
+ }
} else if (ischosen(gtp.gtpc_pdu.sgsn_ContextResponse)) {
- return gtp.gtpc_pdu.sgsn_ContextResponse.imsi.digits;
+ if (ispresent(gtp.gtpc_pdu.sgsn_ContextResponse.imsi.digits)) {
+ return gtp.gtpc_pdu.sgsn_ContextResponse.imsi.digits;
+ } else {
+ return omit;
+ }
} else if (ischosen(gtp.gtpc_pdu.forwardRelocationRequest)) {
return gtp.gtpc_pdu.forwardRelocationRequest.imsi.digits;
} else if (ischosen(gtp.gtpc_pdu.relocationCancelRequest)) {
@@ -163,14 +174,16 @@ private function f_init(GtpEmulationCfg cfg) runs on GTP_Emulation_CT {
var Result res;
map(self:GTPC, system:GTPC);
- res := GTP_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, cfg.gtpc_bind_ip,
+ res := GTPv1C_CodecPort_CtrlFunct.f_IPL4_listen(GTPC, cfg.gtpc_bind_ip,
cfg.gtpc_bind_port, {udp:={}});
g_gtpc_id := res.connId;
- map(self:GTPU, system:GTPU);
- res := GTP_CodecPort_CtrlFunct.f_GTPU_listen(GTPU, cfg.gtpu_bind_ip,
- cfg.gtpu_bind_port, {udp:={}});
- g_gtpu_id := res.connId;
+ 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_gtpu_id := res.connId;
+ }
g_restart_ctr := f_rnd_octstring(1);
g_c_seq_nr := f_rnd_int(65535);
@@ -199,11 +212,16 @@ function main(GtpEmulationCfg cfg) runs on GTP_Emulation_CT {
vc_conn := f_comp_by_teid(g1c_ud.gtpc.teid);
CLIENT.send(g1c_ud) to vc_conn;
} else {
- /* Send to all clients */
- var integer i;
- for (i := 0; i < sizeof(TidTable); i := i+1) {
- if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
- CLIENT.send(g1c_ud) to TidTable[i].vc_conn;
+ /* Check if a default port is set: */
+ if (CLIENT_DEFAULT.checkstate("Connected")) {
+ CLIENT_DEFAULT.send(g1c_ud);
+ } else {
+ /* Send to all clients */
+ var integer i;
+ for (i := 0; i < sizeof(TidTable); i := i+1) {
+ if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
+ CLIENT.send(g1c_ud) to TidTable[i].vc_conn;
+ }
}
}
}
@@ -220,7 +238,9 @@ function main(GtpEmulationCfg cfg) runs on GTP_Emulation_CT {
[] CLIENT.receive(Gtp1uUnitdata:?) -> value g1u_ud sender vc_conn {
GTPU.send(g1u_ud);
}
-
+ [] CLIENT_DEFAULT.receive(Gtp1cUnitdata:?) -> value g1c_ud sender vc_conn {
+ GTPC.send(g1c_ud);
+ }
[] CLIENT_PROC.getcall(GTPEM_register_imsi:{?}) -> param(imsi) sender vc_conn {
f_imsi_tbl_add(imsi, vc_conn);
@@ -252,7 +272,7 @@ type port GTPEM_PROC_PT procedure {
} with { extension "internal" };
/***********************************************************************
- * Client Compoennt
+ * Client Component
***********************************************************************/
type component GTP_ConnHdlr {
diff --git a/library/GTP_Templates.ttcn b/library/GTP_Templates.ttcn
deleted file mode 100644
index aa427594..00000000
--- a/library/GTP_Templates.ttcn
+++ /dev/null
@@ -1,747 +0,0 @@
-/* GTP Templates in TTCN-3
- * (C) 2018 Harald Welte <laforge@gnumonks.org>
- * contributions by sysmocom - s.f.m.c. GmbH
- * 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 GTP_Templates {
-
- import from General_Types all;
- import from Osmocom_Types all;
- import from GTPC_Types all;
- import from GTPU_Types all;
- import from GTP_CodecPort all;
- import from IPCP_Types all;
-
- /* Table 38 of 3GPP TS 29.060 */
- type enumerated GTP_Cause {
- GTP_CAUSE_REQUEST_IMEI (1),
- GTP_CAUSE_REQUEST_IMSI_AND_IMEI (2),
- GTP_CAUSE_NO_IDENTITY_NEDED (3),
- GTP_CAUSE_MS_REFUSES (4),
- GTP_CAUSE_MS_IS_NOT_GPRS_RESPONDING (5),
- /* reserved */
- GTP_CAUSE_REQUEST_ACCEPTED (128)
- /* FIXME */
- };
-
- /* generalized GTP-C receive template */
- template PDU_GTPC tr_GTP1C_PDU(template OCT1 msg_type, template OCT4 teid, template GTPC_PDUs pdu := ?) := {
- /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
- * error if this flag is set to '1'. */
- pn_bit := '0'B,
- /* Sequence number flag (S) shall be set to '1'. */
- s_bit := '1'B,
- e_bit := ?,
- spare := ?,
- /* Protocol Type flag (PT) shall be set to '1'.*/
- pt := '1'B,
- /* Version shall be set to decimal 1 ('001'). */
- version := '001'B,
- messageType := msg_type,
- lengthf := ?,
- teid := teid,
- opt_part := *,
- gtpc_pdu := pdu
- }
-
- /* generalized GTP-C send template */
- template PDU_GTPC ts_GTP1C_PDU(OCT1 msg_type, OCT4 teid, GTPC_PDUs pdu, uint16_t seq_nr) := {
- /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
- * error if this flag is set to '1'. */
- pn_bit := '0'B,
- /* Sequence number flag (S) shall be set to '1'. */
- s_bit := '1'B,
- e_bit := '0'B,
- spare := '0'B,
- /* Protocol Type flag (PT) shall be set to '1'.*/
- pt := '1'B,
- /* Version shall be set to decimal 1 ('001'). */
- version := '001'B,
- messageType := msg_type,
- lengthf := 0, /* we assume encoder overwrites this */
- teid := teid,
- opt_part := {
- sequenceNumber := int2oct(seq_nr, 2),
- npduNumber := '00'O,
- nextExtHeader := '00'O,
- gTPC_extensionHeader_List := omit
- },
- gtpc_pdu := pdu
- }
-
- /* recovery IE */
- template Recovery_gtpc ts_Recovery(OCT1 restart_counter) := {
- type_gtpc := '0E'O,
- restartCounter := restart_counter
- }
-
- template Recovery_gtpc tr_Recovery(template OCT1 restart_counter) := {
- type_gtpc := '0E'O,
- restartCounter := restart_counter
- }
-
- /* template matching reception of GTP-C echo-request */
- template Gtp1cUnitdata tr_GTPC_MsgType(template GtpPeer peer, template OCT1 msg_type, template OCT4 teid, template GTPC_PDUs pdus := ?) := {
- peer := peer,
- gtpc := tr_GTP1C_PDU(msg_type, teid, pdus)
- }
-
- /* template matching reception of GTP-C echo-request */
- template Gtp1cUnitdata tr_GTPC_PING(template GtpPeer peer) := tr_GTPC_MsgType(peer, echoRequest, '00000000'O);
-
- template GTPC_PDUs tr_EchoRespPDU(template OCT1 restart_counter) := {
- echoResponse := {
- recovery := tr_Recovery(restart_counter),
- private_extension_gtpc := *
- }
- }
-
- /* template matching reception of GTP-C echo-response */
- template Gtp1cUnitdata tr_GTPC_PONG(template GtpPeer peer) := tr_GTPC_MsgType(peer, echoResponse, '00000000'O, tr_EchoRespPDU(?));
-
- template GTPC_PDUs ts_EchoRespPDU(OCT1 restart_counter) := {
- echoResponse := {
- recovery := ts_Recovery(restart_counter),
- private_extension_gtpc := omit
- }
- }
-
- /* master template for senidng a GTP-C echo response */
- template Gtp1cUnitdata ts_GTPC_PONG(GtpPeer peer, uint16_t seq, OCT1 rest_ctr) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(echoResponse, '00000000'O, valueof(ts_EchoRespPDU(rest_ctr)), seq)
- }
-
- template GTPC_PDUs ts_EchoReqPDU := {
- echoRequest := {
- private_extension_gtpc := omit
- }
- }
-
- /* master template for sending a GTP-C echo request */
- template Gtp1cUnitdata ts_GTPC_PING(GtpPeer peer, uint16_t seq) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(echoRequest, '00000000'O, valueof(ts_EchoReqPDU), seq)
- }
-
- template EndUserAddress t_EuaIPv4(template OCT4 ip_addr) := {
- type_gtpc := '80'O,
- endUserAddress := {
- endUserAddressIPv4 := {
- lengthf := 2,
- pdp_typeorg := '0001'B,
- spare := '1111'B,
- pdp_typenum := '21'O,
- ipv4_address := ip_addr
- }
- }
- }
- template EndUserAddress t_EuaIPv4Dyn := t_EuaIPv4(omit);
- template EndUserAddress tr_EuaIPv4(template OCT4 ip_addr) modifies t_EuaIPv4 := {
- endUserAddress := {
- endUserAddressIPv4 := {
- lengthf := 2+lengthof(ip_addr)
- }
- }
- }
-
- template EndUserAddress t_EuaIPv6(template OCT16 ip_addr) := {
- type_gtpc := '80'O,
- endUserAddress := {
- endUserAddressIPv6 := {
- lengthf := 2,
- pdp_typeorg := '0001'B,
- spare := '1111'B,
- pdp_typenum := '57'O,
- ipv6_address := ip_addr
- }
- }
- }
- template EndUserAddress t_EuaIPv6Dyn := t_EuaIPv6(omit);
- template EndUserAddress tr_EuaIPv6(template OCT16 ip_addr) modifies t_EuaIPv6 := {
- endUserAddress := {
- endUserAddressIPv6 := {
- lengthf := 2+lengthof(ip_addr)
- }
- }
- }
-
- /* 3GPP TS 29.060 Figure 37A: End User Address Information Element for IPv4v6 (both static) */
- template EndUserAddress t_EuaIPv4v6(template OCT4 ip_addr4, template OCT16 ip_addr6) := {
- type_gtpc := '80'O,
- endUserAddress := {
- endUserAddressIPv4andIPv6 := {
- lengthf := 2,
- pdp_typeorg := '0001'B,
- spare := '1111'B,
- pdp_typenum := '8D'O,
- ipv4_address := ip_addr4,
- ipv6_address := ip_addr6
- }
- }
- }
- template EndUserAddress t_EuaIPv4Dynv6Dyn := t_EuaIPv4v6(omit, omit);
- template EndUserAddress tr_EuaIPv4v6(template OCT4 ip_addr4, template OCT16 ip_addr6) modifies t_EuaIPv4v6 := {
- endUserAddress := {
- endUserAddressIPv4andIPv6 := {
- lengthf := 2+lengthof(ip_addr4)+lengthof(ip_addr6)
- }
- }
- }
-
- template AccessPointName ts_APN(octetstring apn) := {
- type_gtpc := '83'O,
- lengthf := lengthof(apn),
- apn_value := apn
- }
-
- template GSN_Address_GTPC ts_GsnAddr(octetstring ip_addr) := {
- type_gtpc := '85'O,
- lengthf := lengthof(ip_addr),
- addressf := ip_addr
- }
-
- template MSISDN ts_Msisdn(octetstring msisdn) := {
- type_gtpc := '86'O,
- lengthf := lengthof(msisdn),
- msisdn := msisdn
- }
-
- template QualityOfServiceProfile ts_QosDefault := {
- type_gtpc := '87'O,
- lengthf := 4,
- allocRetensionPrio := '00'O,
- qos_ProfileValue := {
- reliabilityClass := '011'B,
- delayClass := '001'B,
- spare1 := '00'B,
- precedenceClass := '010'B,
- spare2 := '0'B,
- peakThroughput := '1001'B,
- meanThroughput := '11111'B,
- spare3 := '000'B,
- deliverErroneusSDU := omit,
- deliveryOrder := omit,
- trafficClass := omit,
- maxSDUSize := omit,
- maxBitrateUplink := omit,
- maxBitrateDownlink := omit,
- sduErrorRatio := omit,
- residualBER := omit,
- trafficHandlingPriority := omit,
- transferDelay := omit,
- guaranteedBitRateUplink := omit,
- guaranteedBitRateDownlink := omit,
- sourceStatisticsDescriptor := omit,
- signallingIndication := omit,
- spare4 := omit,
- maxBitrateDownlinkExt := omit,
- guaranteedBitRateDownlinkExt := omit,
- maxBitrateUplinkExt := omit,
- guaranteedBitRateUplinkExt := omit
- }
- }
-
- template IMSI_gtpc ts_Imsi(hexstring digits) := {
- type_gtpc := '02'O,
- digits := digits,
- padding := 'F'H
- }
-
- template GTPC_PDUs ts_CreatePdpPDU(hexstring imsi, OCT1 restart_ctr, OCT4 teid_data, OCT4 teid_ctrl,
- BIT4 nsapi, EndUserAddress eua, octetstring apn,
- octetstring sgsn_ip_sign, octetstring sgsn_ip_data,
- octetstring msisdn, template ProtConfigOptions pco := omit) := {
- createPDPContextRequest := {
- imsi := ts_Imsi(imsi),
- rai := omit,
- recovery := ts_Recovery(restart_ctr),
- selectionMode := {
- type_gtpc := '0F'O,
- selectModeValue := '00'B,
- spare := '111111'B
- },
- teidDataI := {
- type_gtpc := '00'O,
- teidDataI := teid_data
- },
- teidControlPlane := {
- type_gtpc := '00'O,
- teidControlPlane := teid_ctrl
- },
- nsapi := {
- type_gtpc := '00'O,
- nsapi := nsapi,
- unused := '0000'B
- },
- linked_nsapi := omit,
- charging_char := omit,
- trace_ref := omit,
- trace_type := omit,
- endUserAddress := eua,
- accessPointName := ts_APN(apn),
- protConfigOptions := pco,
- sgsn_addr_signalling := ts_GsnAddr(sgsn_ip_sign),
- sgsn_addr_traffic := ts_GsnAddr(sgsn_ip_data),
- msisdn := ts_Msisdn(msisdn),
- qualityOfServiceProfile := ts_QosDefault,
- tft := omit,
- triggerId := omit,
- omcId := omit,
- commonFlags := omit,
- aPN_Restriction := omit,
- ratType := omit,
- userLocationInformation := omit,
- mS_TimeZone := omit,
- imeisv := omit,
- camelChargingInformationContainer := omit,
- additionalTraceInfo := omit,
- correlationID := omit,
- evolvedAllocationRetentionPriorityI := omit,
- extendedCommonFlags := omit,
- userCSGInformation := omit,
- aPN_AMBR := omit,
- signallingPriorityIndication := omit,
- cN_OperatorSelectionEntity := omit,
- private_extension_gtpc := omit
- }
- }
-
- template Gtp1cUnitdata ts_GTPC_CreatePDP(GtpPeer peer, uint16_t seq, hexstring imsi,
- OCT1 restart_ctr, OCT4 teid_data,
- OCT4 teid_ctrl, BIT4 nsapi, EndUserAddress eua,
- octetstring apn, octetstring sgsn_ip_sign,
- octetstring sgsn_ip_data, octetstring msisdn,
- template ProtConfigOptions pco := omit) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(createPDPContextRequest, '00000000'O,
- valueof(ts_CreatePdpPDU(imsi, restart_ctr, teid_data, teid_ctrl,
- nsapi, eua, apn, sgsn_ip_sign,
- sgsn_ip_data, msisdn, pco)), seq)
- }
-
-
- template NSAPI_GTPC ts_NSAPI(BIT4 nsapi) := {
- type_gtpc := '14'O,
- nsapi := nsapi,
- unused := '0000'B
- }
-
- template ReorderingRequired ts_ReorderReq(boolean req := false) := {
- type_gtpc := '08'O,
- reordreq := bool2bit(req),
- spare := '0000000'B
- }
-
- template GTPC_PDUs ts_CreatePdpRespPDU(OCT1 cause, OCT4 teid_data, OCT4 teid_ctrl, BIT4 nsapi,
- octetstring ggsn_ip_sign, octetstring ggsn_ip_data,
- OCT4 chg_id, template EndUserAddress eua := omit,
- template Recovery_gtpc recovery := omit,
- template ProtConfigOptions pco := omit) := {
- createPDPContextResponse := {
- cause := { '00'O, cause },
- reorderingRequired := ts_ReorderReq(false),
- recovery := recovery,
- teidDataI := {
- type_gtpc := '00'O,
- teidDataI := teid_data
- },
- teidControlPlane := {
- type_gtpc := '00'O,
- teidControlPlane := teid_ctrl
- },
- nsapi := ts_NSAPI(nsapi),
- chargingID := {
- type_gtpc := '7F'O,
- chargingID := chg_id
- },
- endUserAddress := eua,
- protConfigOptions := pco,
- ggsn_addr_controlPlane := ts_GsnAddr(ggsn_ip_sign),
- ggsn_addr_traffic := ts_GsnAddr(ggsn_ip_data),
- alt_ggsn_addr_controlPane := omit,
- alt_ggsn_addr_traffic := omit,
- qualityOfServiceProfile := ts_QosDefault,
- commonFlags := omit,
- aPN_Restriction := omit,
- mS_InfoChangeReportingAction := omit,
- bearerControlMode := omit,
- evolvedAllocationRetentionPriorityI := omit,
- extendedCommonFlag := omit,
- csg_information_reporting_action := omit,
- aPN_AMBR := omit,
- gGSN_BackOffTime := omit,
- private_extension_gtpc := omit
- }
- }
-
- template Gtp1cUnitdata ts_GTPC_CreatePdpResp(GtpPeer peer, uint16_t seq, OCT4 teid,
- OCT1 cause,
- OCT4 teid_ctrl, OCT4 teid_data,
- BIT4 nsapi, octetstring ggsn_ip_sign,
- octetstring ggsn_ip_data, OCT4 chg_id,
- template EndUserAddress eua := omit,
- template Recovery_gtpc recovery := omit,
- template ProtConfigOptions pco := omit) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(createPDPContextResponse, teid,
- valueof(ts_CreatePdpRespPDU(cause, teid_data, teid_ctrl, nsapi,
- ggsn_ip_sign, ggsn_ip_data, chg_id,
- eua, recovery, pco)), seq)
- }
-
- /* PCO send base template */
- template ProtConfigOptions ts_PCO := {
- type_gtpc := '84'O,
- lengthf := 0,
- configProtocol := '000'B,
- spare := '0000'B,
- extension0 := '1'B,
- protocols := {}
- }
- /* PCO receive base template */
- template ProtConfigOptions tr_PCO := {
- type_gtpc := '84'O,
- lengthf := ?,
- configProtocol := '000'B,
- spare := ?,
- extension0 := '1'B,
- protocols := {}
- }
-
- template ProtConfigOptions ts_PCO_IPv6_DNS modifies ts_PCO := {
- protocols := {
- { protocolID := '0003'O, lengthProtoID := 0, protoIDContents := ''O }
- }
- }
- template ProtConfigOptions tr_PCO_IPv6_DNS_resp(template OCT16 contents) modifies tr_PCO := {
- protocols := {
- *, { protocolID := '0003'O, lengthProtoID := 16, protoIDContents := contents }, *
- }
- }
-
- template ProtConfigOptions ts_PCO_IPv4_DNS_IPCP modifies ts_PCO := {
- protocols := {
- /* dummy PAP entry to check if our parser in the GGSN can properly iterate over
- * the list of protocols, see Change-Id Icc2e6716c33d78d3c3e000f529806228d8aa155e */
- { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
- enc_IpcpPacket(valueof(ts_IPCP_ReqDNS)) }
- }
- }
-
- template ProtConfigOptions ts_PCO_IPv4_PRI_DNS_IPCP modifies ts_PCO := {
- protocols := {
- /* dummy PAP entry to check if our parser can cope with a single primary DNS entry
- * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
- { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
- enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Primary)) }
- }
- }
- template ProtConfigOptions ts_PCO_IPv4_SEC_DNS_IPCP modifies ts_PCO := {
- protocols := {
- /* dummy PAP entry to check if our parser can cope with a single secondary DNS entry
- * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
- { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
- enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Secondary)) }
- }
- }
- template ProtConfigOptions ts_PCO_IPv4_SEPARATE_DNS_IPCP modifies ts_PCO := {
- protocols := {
- /* dummy PAP entry to check if our parser can cope with a primary and secondary DNS
- * in separate IPCP containers OS#3381 */
- { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
- enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Primary)) },
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
- enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Secondary)) }
- }
- }
-
- template ProtocolElement tr_PCO_Proto(OCT2 prot_id) := {
- protocolID := prot_id,
- lengthProtoID := ?,
- protoIDContents := ?
- }
- template ProtocolElement ts_PCOelem_PAP_broken := {
- protocolID := 'C023'O,
- lengthProtoID := 60,
- /* PPP Password Authentication Protocol containing incorrect Peer-Id-Length set to 4 (6-7 should be the valid one), see OS#3914. */
- protoIDContents := '0100003c'O & '0444435338323700bc1c08087c1508083e00790000150808fd06000001000000000000000000000000000000000000000000000000000000'O
- }
- template ProtConfigOptions ts_PCO_PAP_IPv4_DNS modifies ts_PCO := {
- protocols := {
- ts_PCOelem_PAP_broken,
- { protocolID := '8021'O, lengthProtoID := 16, protoIDContents := enc_IpcpPacket(valueof(ts_IPCP_ReqDNS)) }
- }
- }
- template ProtConfigOptions tr_PCO_Contains(OCT2 prot_id) modifies tr_PCO := {
- protocols := { *, tr_PCO_Proto(prot_id), * }
- }
-
- template ProtConfigOptions ts_PCO_IPv4_DNS_CONT modifies ts_PCO := {
- protocols := {
- { protocolID := '000d'O, lengthProtoID := 0, protoIDContents := ''O }
- }
- }
- template ProtConfigOptions tr_PCO_IPv4_DNS_CONT_resp(template OCT4 contents) modifies tr_PCO := {
- protocols := {
- *, { protocolID := '000d'O, lengthProtoID := 4, protoIDContents := contents }, *
- }
- }
-
- /* extract a given protocol payload from PCO */
- function f_PCO_extract_proto(ProtConfigOptions pco, OCT2 protocol, integer nth_match := 1) return octetstring {
- var integer i;
- var integer num_matches := 0;
- for (i := 0; i < lengthof(pco.protocols); i := i + 1) {
- if (pco.protocols[i].protocolID == protocol) {
- num_matches := num_matches + 1;
- if (num_matches == nth_match) {
- return pco.protocols[i].protoIDContents;
- }
- }
- }
- setverdict(fail, "Could not extract protocol payload from protocol ", protocol);
- mtc.stop;
- return ''O;
- }
-
- template IpcpPacket tr_IPCP(template LcpCode code, template uint8_t identifier,
- template IpcpOptionList opts) := {
- code := code,
- identifier := identifier,
- len := ?,
- options := opts
- }
- template IpcpOption tr_IPCP_PrimaryDns(template OCT4 addr) := {
- code := IPCP_OPT_PrimaryDNS,
- len := 6,
- data := addr
- }
- template IpcpOption tr_IPCP_SecondaryDns(template OCT4 addr) := {
- code := IPCP_OPT_SecondaryDNS,
- len := 6,
- data := addr
- }
- template IpcpPacket tr_IPCP_Ack_DNS(template uint8_t identifier := ?, template OCT4 dns1 := ?,
- template OCT4 dns2 := ?) :=
- tr_IPCP(LCP_Configure_Ack, identifier,
- { *, tr_IPCP_PrimaryDns(dns1), *, tr_IPCP_SecondaryDns(dns2), * });
-
- template IpcpPacket ts_IPCP(LcpCode code, uint8_t identifier, template IpcpOptionList opts) := {
- code := code,
- identifier := identifier,
- len := 0, /* overwritten */
- options := opts
- }
- template IpcpPacket ts_IPCP_ReqDNS(uint8_t identifier := 0) :=
- ts_IPCP(LCP_Configure_Request, identifier,
- { tr_IPCP_PrimaryDns('00000000'O), tr_IPCP_SecondaryDns('00000000'O) });
-
- template IpcpPacket ts_IPCP_ReqDNS_Primary(uint8_t identifier := 0) :=
- ts_IPCP(LCP_Configure_Request, identifier,
- { tr_IPCP_PrimaryDns('00000000'O) });
- template IpcpPacket ts_IPCP_ReqDNS_Secondary(uint8_t identifier := 0) :=
- ts_IPCP(LCP_Configure_Request, identifier,
- { tr_IPCP_SecondaryDns('00000000'O) });
-
- function f_teardown_ind_IE(in template (omit) BIT1 ind) return template (omit) TearDownInd {
- if (istemplatekind(ind, "omit")) {
- return omit;
- }
- var TearDownInd ret := {
- type_gtpc := '13'O,
- tdInd := valueof(ind),
- spare:= '0000000'B
- }
- return ret;
- }
-
- template GTPC_PDUs ts_DeletePdpPDU(BIT4 nsapi, template (omit) BIT1 teardown_ind) := {
- deletePDPContextRequest := {
- cause := omit,
- tearDownIndicator := f_teardown_ind_IE(teardown_ind),
- nsapi := {
- type_gtpc := '14'O,
- nsapi := nsapi,
- unused := '0000'B
- },
- protConfigOptions := omit,
- userLocationInformation := omit,
- mS_TimeZone := omit,
- extendedCommonFlags := omit,
- uLI_Timestamp := omit,
- private_extension_gtpc := omit
- }
- }
-
- template Gtp1cUnitdata ts_GTPC_DeletePDP(GtpPeer peer, uint16_t seq, OCT4 teid,
- BIT4 nsapi, template (omit) BIT1 teardown_ind) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(deletePDPContextRequest, teid,
- valueof(ts_DeletePdpPDU(nsapi, teardown_ind)), seq)
- }
-
- template GTPC_PDUs ts_DeletePdpRespPDU(OCT1 cause,
- template ProtConfigOptions pco := omit) := {
- deletePDPContextResponse := {
- cause := { '00'O, cause },
- protConfigOptions := pco,
- userLocationInformation := omit,
- mS_TimeZone := omit,
- uLI_Timestamp := omit,
- private_extension_gtpc := omit
- }
- }
-
- template Gtp1cUnitdata ts_GTPC_DeletePdpResp(GtpPeer peer, uint16_t seq, OCT4 teid,
- OCT1 cause,
- template ProtConfigOptions pco := omit) := {
- peer := peer,
- gtpc := ts_GTP1C_PDU(deletePDPContextResponse, teid,
- valueof(ts_DeletePdpRespPDU(cause, pco)), seq)
- }
-
-
-
- /* GTP-U */
-
- template PDU_GTPU tr_GTP1U_PDU(template OCT1 msg_type, template OCT4 teid, template GTPU_IEs ies := ?) := {
- pn_bit := ?,
- s_bit := ?,
- e_bit := ?,
- spare := ?,
- /* Protocol Type flag (PT) shall be set to '1' in GTP */
- pt := '1'B,
- /* Version shall be set to decimal 1 ('001'). */
- version := '001'B,
- messageType := msg_type,
- lengthf := ?,
- teid := teid,
- opt_part := *,
- gtpu_IEs := ies
- }
-
- function f_GTPU_s_bit(template (omit) uint16_t seq) return BIT1 {
- if (istemplatekind(seq, "omit")) {
- return '0'B;
- }
- return '1'B;
- }
-
- function f_GTPU_opt_part(template (omit) uint16_t seq) return template (omit) GTPU_Header_optional_part {
- if (istemplatekind(seq, "omit")) {
- return omit;
- }
- var GTPU_Header_optional_part ret := {
- sequenceNumber := int2oct(valueof(seq), 2),
- npduNumber := '00'O,
- nextExtHeader := '00'O,
- gTPU_extensionHeader_List := omit
- };
- return ret;
- }
-
- /* generalized GTP-U send template */
- template PDU_GTPU ts_GTP1U_PDU(OCT1 msg_type, template (omit) uint16_t seq, OCT4 teid, GTPU_IEs ies) := {
- /* N-PDU Number flag (PN): the GTP-U header contains a meaningful N-PDU Number field if the PN
- * flag is set to 1. */
- pn_bit := '0'B, /* we assume the encoder overwrites this if an optional part is given */
- /* If the Sequence Number flag (S) is set to '1' the sequence number field is present and
- * meaningful otherwise it is set to '0'. For GTP-U messages Echo Request, Echo Response,
- * Error Indication and Supported Extension Headers Notification, the S flag shall be set to '1'.
- *
- * Note that the caller must ensure that these conditions hold.
- * The caller can either pass a sequence number (we set s_bit to '1'B) when appropriate,
- * or may omit the sequence number (we set s_bit to '0'B). */
- s_bit := f_GTPU_s_bit(seq),
- /* Extension header presence */
- e_bit := '0'B,
- spare := '0'B,
- /* Protocol Type flag (PT) shall be set to '1' in GTP */
- pt := '1'B,
- /* Version shall be set to decimal 1 ('001'). */
- version := '001'B,
- messageType := msg_type,
- lengthf := 0, /* we assume encoder overwrites this */
- teid := teid,
- opt_part := f_GTPU_opt_part(seq),
- gtpu_IEs := ies
- }
-
- template Gtp1uUnitdata tr_GTPU_MsgType(template GtpPeer peer, template OCT1 msg_type, template OCT4 teid) := {
- peer := peer,
- gtpu := tr_GTP1U_PDU(msg_type, teid)
- }
-
-
- /* template matching reception of GTP-U echo-request */
- template Gtp1uUnitdata tr_GTPU_PING(template GtpPeer peer) := tr_GTPU_MsgType(peer, echoRequest, '00000000'O);
-
- /* template matching reception of GTP-U GPDU */
- template GTPU_IEs t_GPDU(template octetstring data) := {
- g_PDU_IEs := {
- data := data
- }
- }
- template Gtp1uUnitdata tr_GTPU_GPDU(template GtpPeer peer, template OCT4 teid, template octetstring data := ?) := {
- peer := peer,
- gtpu := tr_GTP1U_PDU('FF'O, teid, t_GPDU(data))
- }
-
- template GTPU_IEs ts_UEchoRespPDU(OCT1 restart_counter) := {
- echoResponse_IEs := {
- recovery_gtpu := {
- type_gtpu := '00'O, /* we assume encoder fixes? */
- restartCounter := restart_counter
- },
- private_extension_gtpu := omit
- }
- }
-
- /* master template for sending a GTP-U echo response */
- template Gtp1uUnitdata ts_GTPU_PONG(GtpPeer peer, uint16_t seq, OCT1 rest_ctr) := {
- peer := peer,
- gtpu := ts_GTP1U_PDU(echoResponse, seq, '00000000'O, valueof(ts_UEchoRespPDU(rest_ctr)))
- }
-
- template GSNAddress_gtpu ts_UGsnAddr(octetstring ip_addr) := {
- type_gtpu := '85'O,
- lengthf := lengthof(ip_addr),
- gSNAddressValue := ip_addr
- }
-
- template TeidDataI_gtpu ts_UteidDataI(OCT4 teid) := {
- type_gtpu := '10'O,
- teidDataI := teid
- }
-
- template GTPU_IEs ts_UErrorIndication(OCT4 teid, octetstring gsn_addr) := {
- errorIndication_IEs := {
- teidDataI_gtpu := ts_UteidDataI(teid),
- gSNAddress_gtpu := ts_UGsnAddr(gsn_addr),
- private_extension_gtpu := omit
- }
- }
-
- /* master template for sending a GTP-U Error indication */
- template Gtp1uUnitdata ts_GTPU_ErrorIndication(GtpPeer peer, uint16_t seq, OCT4 teid, octetstring gsn_addr) := {
- peer := peer,
- gtpu := ts_GTP1U_PDU('1A'O, seq, '00000000'O, valueof(ts_UErrorIndication(teid, gsn_addr)))
- }
-
- /* master template for sending a GTP-U user plane data */
- template Gtp1uUnitdata ts_GTP1U_GPDU(GtpPeer peer, template (omit) uint16_t seq, OCT4 teid, octetstring data) := {
- peer := peer,
- gtpu := ts_GTP1U_PDU('FF'O, seq, teid, { g_PDU_IEs := { data := data }})
- }
-}
diff --git a/library/GTPv1C_CodecPort.ttcn b/library/GTPv1C_CodecPort.ttcn
new file mode 100644
index 00000000..bf147234
--- /dev/null
+++ b/library/GTPv1C_CodecPort.ttcn
@@ -0,0 +1,65 @@
+/* dual-faced port sitting on top of IPL4_asp UDP to encode/decode GTPv1C
+ * (C) 2017 Harald Welte <laforge@gnumonks.org>
+ * 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 GTPv1C_CodecPort {
+ import from IPL4asp_PortType all;
+ import from IPL4asp_Types all;
+ import from GTPC_Types all;
+ import from Misc_Helpers all;
+
+ modulepar {
+ SystemUnderTest mp_pl_SystemUnderTest := SGSN;
+ }
+
+ /* identifies a remote peer (sender or receiver) */
+ type record Gtp1cPeer {
+ ConnectionId connId,
+ HostName remName,
+ PortNumber remPort
+ }
+
+ /* Decoded GTP1C (Control Plane), used in send and receive direction */
+ type record Gtp1cUnitdata {
+ Gtp1cPeer peer,
+ PDU_GTPC gtpc
+ }
+
+ /* Translation port on top of IPL4asp; ASP_Event passed through transparently */
+ type port GTPC_PT message {
+ out Gtp1cUnitdata;
+ in Gtp1cUnitdata,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+ } with { extension "user IPL4asp_PT
+ out(Gtp1cUnitdata -> ASP_SendTo: function(f_enc_Gtp1cUD))
+ in(ASP_RecvFrom -> Gtp1cUnitdata: function(f_dec_Gtp1cUD);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)" }
+
+ private function f_enc_Gtp1cUD(in Gtp1cUnitdata in_ud, out ASP_SendTo out_ud) {
+ out_ud.connId := in_ud.peer.connId;
+ out_ud.remName := in_ud.peer.remName;
+ out_ud.remPort := in_ud.peer.remPort;
+ out_ud.proto := { udp := {} };
+ out_ud.msg := enc_PDU_GTPC(in_ud.gtpc);
+ } with { extension "prototype(fast)" };
+
+ private function f_dec_Gtp1cUD(in ASP_RecvFrom in_ud, out Gtp1cUnitdata out_ud) {
+ out_ud.peer.connId := in_ud.connId;
+ out_ud.peer.remName := in_ud.remName;
+ out_ud.peer.remPort := in_ud.remPort;
+ out_ud.gtpc := dec_PDU_GTPC(in_ud.msg, pl_SystemUnderTest := mp_pl_SystemUnderTest);
+ if (lengthof(in_ud.msg) != out_ud.gtpc.lengthf + 8) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Rx GTPv1-C with field length ", out_ud.gtpc.lengthf, " + 8 != exp ", lengthof(in_ud.msg)));
+ }
+ } with { extension "prototype(fast)" };
+}
diff --git a/library/GTP_CodecPort_CtrlFunct.ttcn b/library/GTPv1C_CodecPort_CtrlFunct.ttcn
index 4f61af79..e0a5ee76 100644
--- a/library/GTP_CodecPort_CtrlFunct.ttcn
+++ b/library/GTPv1C_CodecPort_CtrlFunct.ttcn
@@ -1,6 +1,6 @@
-module GTP_CodecPort_CtrlFunct {
+module GTPv1C_CodecPort_CtrlFunct {
- import from GTP_CodecPort all;
+ import from GTPv1C_CodecPort all;
import from IPL4asp_Types all;
external function f_IPL4_listen(
@@ -39,12 +39,4 @@ module GTP_CodecPort_CtrlFunct {
in ConnectionId id,
out UserData userData
) return Result;
-
- external function f_GTPU_listen(
- inout GTPU_PT portRef,
- in HostName locName,
- in PortNumber locPort,
- in ProtoTuple proto,
- in OptionList options := {}
- ) return Result;
}
diff --git a/library/NS_CodecPort_CtrlFunctDef.cc b/library/GTPv1C_CodecPort_CtrlFunctDef.cc
index a6da7ac1..2227fe1d 100644
--- a/library/NS_CodecPort_CtrlFunctDef.cc
+++ b/library/GTPv1C_CodecPort_CtrlFunctDef.cc
@@ -1,11 +1,11 @@
#include "IPL4asp_PortType.hh"
-#include "NS_CodecPort.hh"
#include "IPL4asp_PT.hh"
+#include "GTPv1C_CodecPort.hh"
-namespace NS__CodecPort__CtrlFunct {
+namespace GTPv1C__CodecPort__CtrlFunct {
IPL4asp__Types::Result f__IPL4__listen(
- NS__CodecPort::NS__CODEC__PT& portRef,
+ GTPv1C__CodecPort::GTPC__PT& portRef,
const IPL4asp__Types::HostName& locName,
const IPL4asp__Types::PortNumber& locPort,
const IPL4asp__Types::ProtoTuple& proto,
@@ -13,9 +13,9 @@ namespace NS__CodecPort__CtrlFunct {
{
return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
}
-
+
IPL4asp__Types::Result f__IPL4__connect(
- NS__CodecPort::NS__CODEC__PT& portRef,
+ GTPv1C__CodecPort::GTPC__PT& portRef,
const IPL4asp__Types::HostName& remName,
const IPL4asp__Types::PortNumber& remPort,
const IPL4asp__Types::HostName& locName,
@@ -29,28 +29,27 @@ namespace NS__CodecPort__CtrlFunct {
}
IPL4asp__Types::Result f__IPL4__close(
- NS__CodecPort::NS__CODEC__PT& portRef,
- const IPL4asp__Types::ConnectionId& connId,
+ GTPv1C__CodecPort::GTPC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
const IPL4asp__Types::ProtoTuple& proto)
{
return f__IPL4__PROVIDER__close(portRef, connId, proto);
}
IPL4asp__Types::Result f__IPL4__setUserData(
- NS__CodecPort::NS__CODEC__PT& portRef,
+ GTPv1C__CodecPort::GTPC__PT& portRef,
const IPL4asp__Types::ConnectionId& connId,
const IPL4asp__Types::UserData& userData)
{
return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
}
-
+
IPL4asp__Types::Result f__IPL4__getUserData(
- NS__CodecPort::NS__CODEC__PT& portRef,
+ GTPv1C__CodecPort::GTPC__PT& portRef,
const IPL4asp__Types::ConnectionId& connId,
IPL4asp__Types::UserData& userData)
{
return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
}
-
-}
+}
diff --git a/library/GTPv1C_Templates.ttcn b/library/GTPv1C_Templates.ttcn
new file mode 100644
index 00000000..2eb1d7ea
--- /dev/null
+++ b/library/GTPv1C_Templates.ttcn
@@ -0,0 +1,1845 @@
+/* GTPv1-C Templates in TTCN-3
+ * (C) 2018 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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 GTPv1C_Templates {
+
+ import from General_Types all;
+ import from Osmocom_Types all;
+ import from GTPC_Types all;
+ import from GTPv1C_CodecPort all;
+ import from IPCP_Types all;
+ import from GSM_Types all; // RoutingAreaIdentification, CellIdentity
+
+ template (present) OCT1 gtp1_requests := (
+ '10'O, /* createPDPContextRequest */
+ '12'O, /* updatePDPContextRequest */
+ '14'O, /* */
+ '16'O, /* deletePDPContextRequest */
+ '1B'O, /* pdu_NotificationRequest */
+ '1D'O, /* pdu_NotificationRejectRequest */
+ '1F'O, /* supportedExtensionHeadersNotification */
+ '20'O, /* sendRouteingInformationForGPRSRequest */
+ '22'O, /* failureReportRequest */
+ '24'O, /* noteMS_GPRSPresentRequest */
+ '30'O, /* identificationRequest */
+ '32'O, /* sgsn_ContextRequest */
+ '35'O, /* forwardRelocationRequest */
+ '38'O, /* relocationCancelRequest */
+ '3A'O, /* forwardSRNSContext */
+ '3D'O, /* uERegistrationQueryRequest */
+ '46'O, /* ranInformationRelay */
+ '60'O, /* mBMSNotificationRequest */
+ '62'O, /* mBMSNotificationRejectRequest */
+ '64'O, /* createMBMSContextRequest */
+ '66'O, /* updateMBMSContextRequest */
+ '68'O, /* deleteMBMSContextRequest */
+ '70'O, /* mBMSRegistrationRequest */
+ '72'O, /* mBMSDeRegistrationRequest */
+ '74'O, /* mBMSSessionStartRequest */
+ '76'O, /* mBMSSessionStopRequest */
+ '78'O, /* mBMSSessionUpdateRequest */
+ '80'O /* mS_InfoChangeNotificationRequest */
+ );
+
+ type record GTP_CellId {
+ RoutingAreaIdentification ra_id,
+ CellIdentity cell_id
+ } with { encode "RAW" };
+
+ template (value) GTP_CellId ts_GTP_CellId(template (value) RoutingAreaIdentification rai, CellIdentity cell_id) := {
+ ra_id := rai,
+ cell_id := cell_id
+ };
+
+ /* Table 38 of 3GPP TS 29.060 */
+ type enumerated GTP_Cause {
+ GTP_CAUSE_REQUEST_IMEI (1),
+ GTP_CAUSE_REQUEST_IMSI_AND_IMEI (2),
+ GTP_CAUSE_NO_IDENTITY_NEDED (3),
+ GTP_CAUSE_MS_REFUSES (4),
+ GTP_CAUSE_MS_IS_NOT_GPRS_RESPONDING (5),
+ /* reserved */
+ GTP_CAUSE_REQUEST_ACCEPTED (128),
+ GTP_CAUSE_INVALID_MSG_FORMAT (193)
+ /* FIXME */
+ };
+
+ template (value) Cause_gtpc ts_Cause_gtpc(template (value) GTP_Cause cause) := {
+ type_gtpc := '01'O,
+ causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+ }
+ private function enum2oct1_Cause_gtpc_tmpl(template GTP_Cause inp) return template OCT1
+ {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return int2oct(enum2int(valueof(inp)), 1);
+ }
+ }
+ template (present) Cause_gtpc tr_Cause_gtpc(template (present) GTP_Cause cause) := {
+ type_gtpc := '01'O,
+ causevalue := enum2oct1_Cause_gtpc_tmpl(cause)
+ }
+ function f_tr_Cause_gtpc(template GTP_Cause cause) return
+ template Cause_gtpc {
+ if (istemplatekind(cause, "omit")) {
+ return omit;
+ } else if (istemplatekind(cause, "*")) {
+ return *;
+ } else {
+ return tr_Cause_gtpc(cause);
+ }
+ }
+
+ private function f_oct_or_wc(template integer inp, integer len) return template octetstring {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ }
+ return int2oct(valueof(inp), len);
+ }
+
+ private function f_hex_or_wc(template integer inp, integer len) return template hexstring {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ }
+ return int2hex(valueof(inp), len);
+ }
+
+ /* generalized GTP-C receive template */
+ template (present) PDU_GTPC tr_GTP1C_PDU(template (present) OCT1 msg_type, template (present) OCT4 teid, template (present) GTPC_PDUs pdu := ?) := {
+ /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
+ * error if this flag is set to '1'. */
+ pn_bit := '0'B,
+ /* Sequence number flag (S) shall be set to '1'. */
+ s_bit := '1'B,
+ e_bit := ?,
+ spare := ?,
+ /* Protocol Type flag (PT) shall be set to '1'.*/
+ pt := '1'B,
+ /* Version shall be set to decimal 1 ('001'). */
+ version := '001'B,
+ messageType := msg_type,
+ lengthf := ?,
+ teid := teid,
+ opt_part := *,
+ gtpc_pdu := pdu
+ }
+
+ /* generalized GTP-C send template */
+ template (value) PDU_GTPC ts_GTP1C_PDU(OCT1 msg_type, OCT4 teid, GTPC_PDUs pdu, uint16_t seq_nr) := {
+ /* N-PDU Number flag (PN) shall be set to '0'. A GTP-C receiver shall not return an
+ * error if this flag is set to '1'. */
+ pn_bit := '0'B,
+ /* Sequence number flag (S) shall be set to '1'. */
+ s_bit := '1'B,
+ e_bit := '0'B,
+ spare := '0'B,
+ /* Protocol Type flag (PT) shall be set to '1'.*/
+ pt := '1'B,
+ /* Version shall be set to decimal 1 ('001'). */
+ version := '001'B,
+ messageType := msg_type,
+ lengthf := 0, /* we assume encoder overwrites this */
+ teid := teid,
+ opt_part := {
+ sequenceNumber := int2oct(seq_nr, 2),
+ npduNumber := '00'O,
+ nextExtHeader := '00'O,
+ gTPC_extensionHeader_List := omit
+ },
+ gtpc_pdu := pdu
+ }
+
+ /* recovery IE */
+ template (value) Recovery_gtpc ts_Recovery(OCT1 restart_counter) := {
+ type_gtpc := '0E'O,
+ restartCounter := restart_counter
+ }
+
+ template (present) Recovery_gtpc tr_Recovery(template (present) OCT1 restart_counter) := {
+ type_gtpc := '0E'O,
+ restartCounter := restart_counter
+ }
+
+ /* Packet TMSI - 7.7.5 */
+ template (value) PacketTMSI ts_PTMSI(OCT4 ptmsi) := {
+ type_gtpc := '05'O,
+ p_tmsi := ptmsi
+ }
+
+ /* PTMSI Signature - 7.7.9 */
+ template (value) PTMSI_Signature ts_PTMSI_sig(OCT3 ptmsi_sig) := {
+ type_gtpc := '0C'O,
+ ptmsi_Signature := ptmsi_sig
+ }
+
+ /* MS Validated - 7.7.10 */
+ template (value) MS_Validated ts_MS_Validated(template (value) BIT1 msValidated) := {
+ type_gtpc := '0D'O,
+ msValidated := msValidated,
+ spare := '1111111'B
+ }
+ template (present) MS_Validated tr_MS_Validated(template (present) BIT1 msValidated := ?) := {
+ type_gtpc := '0D'O,
+ msValidated := msValidated,
+ spare := '1111111'B
+ }
+ function f_tr_MS_Validated(template BIT1 msValidated := *) return template MS_Validated {
+ if (istemplatekind(msValidated, "omit")) {
+ return omit;
+ } else if (istemplatekind(msValidated, "*")) {
+ return *;
+ } else {
+ return tr_MS_Validated(msValidated);
+ }
+ }
+ private function f_ts_MS_Validated(template (omit) BIT1 msValidated)
+ return template (omit) MS_Validated {
+ if (istemplatekind(msValidated, "omit")) {
+ return omit;
+ }
+ return ts_MS_Validated(msValidated);
+ }
+
+ /* 7.7.13 TEI Data I */
+ template (value) TeidDataI ts_TeidDataI(template (value) OCT4 teid) := {
+ type_gtpc := '10'O,
+ teidDataI := teid
+ }
+ template (present) TeidDataI tr_TeidDataI(template (present) OCT4 teid := ?) := {
+ type_gtpc := '10'O,
+ teidDataI := teid
+ }
+
+ /* 7.7.14 TEI Control Plane */
+ template (value) TeidControlPlane ts_TEIC(template (value) OCT4 teic) := {
+ type_gtpc := '11'O,
+ teidControlPlane := teic
+ }
+ template (present) TeidControlPlane tr_TEIC(template (present) OCT4 teic := ?) := {
+ type_gtpc := '11'O,
+ teidControlPlane := teic
+ }
+ private function f_ts_TEIC(template (omit) OCT4 teic)
+ return template (omit) TeidControlPlane {
+ if (istemplatekind(teic, "omit")) {
+ return omit;
+ }
+ return ts_TEIC(teic);
+ }
+
+ /* 7.7.15 Tunnel Endpoint Identifier Data II */
+ template (value) TeidDataII ts_TeidDataII(template (value) BIT4 nsapi,
+ template (value) OCT4 teid) := {
+ type_gtpc := '12'O,
+ nsapi := nsapi,
+ unused := '0000'B,
+ teidDataII := teid
+ }
+ template (present) TeidDataII tr_TeidDataII(template (present) BIT4 nsapi := ?,
+ template (present) OCT4 teid := ?) := {
+ type_gtpc := '12'O,
+ nsapi := nsapi,
+ unused := '0000'B,
+ teidDataII := teid
+ }
+
+ /* IMEI(SV) IE TS 29.060 7.7.53 */
+ template (value) IMEISV_gtpc ts_IMEISV(template (value) OCT8 imeisv) := {
+ type_gtpc := '9A'O,
+ lengthf := 8,
+ imeisv := imeisv
+ }
+ private function f_ts_IMEISV(template (omit) OCT8 imeisv)
+ return template (omit) IMEISV_gtpc {
+ if (istemplatekind(imeisv, "omit")) {
+ return omit;
+ }
+ return ts_IMEISV(imeisv);
+ }
+
+ template (present) IMEISV_gtpc tr_IMEISV(template (present) OCT8 imeisv) := {
+ type_gtpc := '9A'O,
+ lengthf := 8,
+ imeisv := imeisv
+ }
+
+ // MS Time Zone - 7.7.52
+ template (value) MS_TimeZone ts_MS_TimeZone(template (value) OCT1 timeZone := '00'O,
+ template (value) BIT2 daylightSavingTime := '00'B) := {
+ type_gtpc := '99'O,
+ lengthf := 2,
+ timeZone := timeZone,
+ daylightSavingTime := daylightSavingTime,
+ spare1 := '000'B,
+ sgsnAttempsToUpdateMS := '0'B, /* propietary, use it as spare */
+ spare2 := '00'B
+ }
+ function f_ts_MS_TimeZone(template (omit) OCT1 timeZone, template (omit) BIT2 daylightSavingTime)
+ return template (omit) MS_TimeZone {
+ if (istemplatekind(timeZone, "omit") and istemplatekind(daylightSavingTime, "omit")) {
+ return omit;
+ }
+ if (istemplatekind(timeZone, "omit")) {
+ return ts_MS_TimeZone(daylightSavingTime := daylightSavingTime);
+ }
+ if (istemplatekind(daylightSavingTime, "omit")) {
+ return ts_MS_TimeZone(timeZone);
+ }
+ return ts_MS_TimeZone(timeZone, daylightSavingTime);
+ }
+
+ template (present) MS_TimeZone tr_MS_TimeZone(template (present) OCT1 timeZone := ?,
+ template (present) BIT2 daylightSavingTime := ?) := {
+ type_gtpc := '99'O,
+ lengthf := 2,
+ timeZone := timeZone,
+ daylightSavingTime := daylightSavingTime,
+ spare1 := '000'B,
+ sgsnAttempsToUpdateMS := '0'B, /* propietary, use it as spare */
+ spare2 := '00'B
+ }
+
+ /* Charging Characteristics IE TS 29.060 7.7.23 */
+ template (value) ChargingCharacteristics_GTPC ts_ChargingCharacteristics(template (value) OCT2 chargingChar) := {
+ type_gtpc := '1A'O,
+ chargingChar := chargingChar
+ }
+ private function f_ts_ChargingCharacteristics(template (omit) OCT2 chargingChar)
+ return template (omit) ChargingCharacteristics_GTPC {
+ if (istemplatekind(chargingChar, "omit")) {
+ return omit;
+ }
+ return ts_ChargingCharacteristics(chargingChar);
+ }
+
+ template (present) ChargingCharacteristics_GTPC tr_ChargingCharacteristics(template (present) OCT2 chargingChar) := {
+ type_gtpc := '1A'O,
+ chargingChar := chargingChar
+ }
+
+ /* 7.7.28 MM Context */
+ template (value) MM_Context ts_MM_ContextGSM(template (value) OCT8 kc,
+ template (value) BIT3 cksn := '000'B,
+ template (value) BIT3 gea := '000'B,
+ template (value) octetstring triplet := ''O) := {
+ type_gtpc := '81'O,
+ context := {
+ mmcontGSM := {
+ lengthf := 0, /* overwritten */
+ cksn := cksn,
+ spare := '11111'B,
+ usedCipher := gea,
+ noofVectors := 0, /* overwritten */
+ security := '01'B, /* GSM key and triplets */
+ kc := kc,
+ triplet := triplet,
+ drx_par := '0000'O,
+ msNetW_cap_length := 0, /* overwritten */
+ msNetw_cap := omit,
+ containerLength := 0, /* overwritten */
+ container := omit,
+ access_restriction_data_length := 0,
+ access_restriction_data := omit
+ }
+ }
+ }
+ template (present) MM_Context tr_MM_ContextGSM(template (present) OCT8 kc := ?,
+ template (present) BIT3 cksn := ?,
+ template (present) BIT3 gea := ?,
+ template (present) octetstring triplet := ?) := {
+ type_gtpc := '81'O,
+ context := {
+ mmcontGSM := {
+ lengthf := ?,
+ cksn := cksn,
+ spare := ?,
+ usedCipher := gea,
+ noofVectors := ?,
+ security := '01'B, /* GSM key and triplets */
+ kc := kc,
+ triplet := triplet,
+ drx_par := ?,
+ msNetW_cap_length := ?,
+ msNetw_cap := *,
+ containerLength := ?,
+ container := *,
+ access_restriction_data_length := ?,
+ access_restriction_data := *
+ }
+ }
+ }
+
+ template (value) MM_Context ts_MM_ContextUMTS(template (value) OCT16 ck,
+ template (value) OCT16 ik) := {
+ type_gtpc := '81'O,
+ context := {
+ mmcontUMTS := {
+ lengthf := 0, /* overwritten */
+ ksi := '001'B,
+ usedGPRSIntegrityAlgorithm := '000'B,
+ ugipai := '1'B, /* Integrity Protection not required */
+ gupii := '1'B, /* Ignore "Used GPRS integrity protection algorithm" field" */
+ spare1 := '111'B,
+ noofVectors := 0, /* TODO: fill quintpuplets*/
+ security := '10'B, /* UMTS key and quintuplets */
+ ck := ck,
+ ik := ik,
+ quintupletlength := 0, /* overwritten */
+ quintuplet := ''O,
+ drx_par := '0000'O,
+ msNetW_cap_length := 0, /* overwritten */
+ msNetw_cap := omit,
+ containerLength := 0, /* overwritten */
+ container := omit,
+ access_restriction_data_length := 0, /* overwritten */
+ access_restriction_data := omit
+ }
+ }
+ }
+
+ /* 7.7.29 PDP Context */
+ template (value) PDP_Context_GTPC ts_PDP_Context_GTPC(template (value) octetstring pdp_addr,
+ template (value) octetstring ggsn_gsn_addr,
+ template (value) octetstring apn,
+ template (value) OCT4 ggsn_teic := '12345678'O,
+ template (value) OCT4 ggsn_teid := '87654321'O) := {
+ type_gtpc := '82'O,
+ lengthf := 0, /* overwritten */
+ nsapi := '0101'B,
+ order := '0'B,
+ asi := '0'B,
+ vaa := '0'B,
+ ea := '0'B,
+ sapi := '0011'B,
+ spare1 := '0000'B,
+ qos_subLength := 0, /* overwritten */
+ qos_sub := ts_QosProfileValueDefault,
+ qos_reqLength := 0, /* overwritten */
+ qos_req := ts_QosProfileValueDefault,
+ qos_negLength := 0, /* overwritten */
+ qos_neg := ts_QosProfileValueDefault,
+ snd := '0000'O,
+ snu := '0000'O,
+ sendNPDUnum := '00'O,
+ receiveNPDUnum := '00'O,
+ uteidControlPlane := ggsn_teic,
+ uteidData1 := ggsn_teid,
+ pdpcontext := '00'O,
+ pdp_typeorg := '0001'B, /* IETF */
+ spare2 := '1111'B,
+ pdp_typenum := '21'O, /* IETF IPV4 */
+ pdp_addressLength := 0, /* overwritten */
+ pdp_address := pdp_addr,
+ ggsn_addressControlPlaneLength := 0, /* overwritten */
+ ggsn_addressControlPlane := ggsn_gsn_addr,
+ ggsn_addressUserPlaneLength := 0, /* overwritten */
+ ggsn_addressUserPlane := ggsn_gsn_addr,
+ apnLength := 0, /* overwritten */
+ apn := apn,
+ transactionId := '0001'B,
+ spare3 := '0000'B,
+ transactionID_cont := '00'O,
+ pdp_typenum2 := omit,
+ pdp_addresslength2 := omit,
+ pdp_Address2 := omit
+ }
+
+
+ /* template matching reception of GTP-C unit-data */
+ template (present) Gtp1cUnitdata tr_GTPC_MsgType(template (present) Gtp1cPeer peer,
+ template (present) OCT1 msg_type,
+ template (present) OCT4 teid,
+ template (present) GTPC_PDUs pdus := ?) := {
+ peer := peer,
+ gtpc := tr_GTP1C_PDU(msg_type, teid, pdus)
+ }
+
+ /* template matching reception of GTP-C echo-request */
+ template (present) Gtp1cUnitdata tr_GTPC_PING(template (present) Gtp1cPeer peer) := tr_GTPC_MsgType(peer, echoRequest, '00000000'O);
+
+ template (present) GTPC_PDUs tr_EchoRespPDU(template (present) OCT1 restart_counter) := {
+ echoResponse := {
+ recovery := tr_Recovery(restart_counter),
+ private_extension_gtpc := *
+ }
+ }
+
+ /* template matching reception of GTP-C echo-response */
+ template (present) Gtp1cUnitdata tr_GTPC_PONG(template (present) Gtp1cPeer peer) := tr_GTPC_MsgType(peer, echoResponse, '00000000'O, tr_EchoRespPDU(?));
+
+ template (value) GTPC_PDUs ts_EchoRespPDU(OCT1 restart_counter) := {
+ echoResponse := {
+ recovery := ts_Recovery(restart_counter),
+ private_extension_gtpc := omit
+ }
+ }
+
+ /* master template for senidng a GTP-C echo response */
+ template (value) Gtp1cUnitdata ts_GTPC_PONG(Gtp1cPeer peer, uint16_t seq, OCT1 rest_ctr) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(echoResponse, '00000000'O, valueof(ts_EchoRespPDU(rest_ctr)), seq)
+ }
+
+ template (value) GTPC_PDUs ts_EchoReqPDU := {
+ echoRequest := {
+ private_extension_gtpc := omit
+ }
+ }
+
+ /* master template for sending a GTP-C echo request */
+ template (value) Gtp1cUnitdata ts_GTPC_PING(Gtp1cPeer peer, uint16_t seq) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(echoRequest, '00000000'O, valueof(ts_EchoReqPDU), seq)
+ }
+
+ private function f_eua_ipv4_len(template OCT4 ip_addr) return template (present) integer {
+ if (istemplatekind(ip_addr, "omit")) {
+ return 2;
+ } else if (istemplatekind(ip_addr, "*")) {
+ return ?;
+ } else if (istemplatekind(ip_addr, "?")) {
+ return 6;
+ }
+ return 6;
+ }
+
+ private function f_eua_ipv6_len(template OCT16 ip_addr) return template (present) integer {
+ if (istemplatekind(ip_addr, "omit")) {
+ return 2;
+ } else if (istemplatekind(ip_addr, "*")) {
+ return ?;
+ } else if (istemplatekind(ip_addr, "?")) {
+ return 18;
+ }
+ return 18;
+ }
+
+ private function f_eua_ipv4v6_len(template OCT4 ip_addr4, template OCT16 ip_addr6) return template (present) integer {
+ var integer len := 2;
+ if (istemplatekind(ip_addr4, "*") or
+ istemplatekind(ip_addr6, "*")) {
+ return ?;
+ }
+ if (not istemplatekind(ip_addr4, "omit")) {
+ len := len + 4;
+ }
+ if (not istemplatekind(ip_addr6, "omit")) {
+ len := len + 16;
+ }
+ return len;
+ }
+
+ template (present) EndUserAddress t_EuaIPv4(template OCT4 ip_addr) := {
+ type_gtpc := '80'O,
+ endUserAddress := {
+ endUserAddressIPv4 := {
+ lengthf := 2,
+ pdp_typeorg := '0001'B,
+ spare := '1111'B,
+ pdp_typenum := '21'O,
+ ipv4_address := ip_addr
+ }
+ }
+ }
+ template (present) EndUserAddress t_EuaIPv4Dyn := t_EuaIPv4(omit);
+ template (present) EndUserAddress tr_EuaIPv4(template (present) OCT4 ip_addr) modifies t_EuaIPv4 := {
+ endUserAddress := {
+ endUserAddressIPv4 := {
+ lengthf := f_eua_ipv4_len(ip_addr)
+ }
+ }
+ }
+
+ template (present) EndUserAddress t_EuaIPv6(template OCT16 ip_addr) := {
+ type_gtpc := '80'O,
+ endUserAddress := {
+ endUserAddressIPv6 := {
+ lengthf := 2,
+ pdp_typeorg := '0001'B,
+ spare := '1111'B,
+ pdp_typenum := '57'O,
+ ipv6_address := ip_addr
+ }
+ }
+ }
+ template (present) EndUserAddress t_EuaIPv6Dyn := t_EuaIPv6(omit);
+ template (present) EndUserAddress tr_EuaIPv6(template (present) OCT16 ip_addr) modifies t_EuaIPv6 := {
+ endUserAddress := {
+ endUserAddressIPv6 := {
+ lengthf := f_eua_ipv6_len(ip_addr)
+ }
+ }
+ }
+
+ /* 3GPP TS 29.060 Figure 37A: End User Address Information Element for IPv4v6 (both static) */
+ template (present) EndUserAddress t_EuaIPv4v6(template OCT4 ip_addr4, template OCT16 ip_addr6) := {
+ type_gtpc := '80'O,
+ endUserAddress := {
+ endUserAddressIPv4andIPv6 := {
+ lengthf := 2,
+ pdp_typeorg := '0001'B,
+ spare := '1111'B,
+ pdp_typenum := '8D'O,
+ ipv4_address := ip_addr4,
+ ipv6_address := ip_addr6
+ }
+ }
+ }
+ template (present) EndUserAddress t_EuaIPv4Dynv6Dyn := t_EuaIPv4v6(omit, omit);
+ template (present) EndUserAddress tr_EuaIPv4v6(template (present) OCT4 ip_addr4,
+ template (present) OCT16 ip_addr6) modifies t_EuaIPv4v6 := {
+ endUserAddress := {
+ endUserAddressIPv4andIPv6 := {
+ lengthf := f_eua_ipv4v6_len(ip_addr4, ip_addr6)
+ }
+ }
+ }
+
+ template (value) AccessPointName ts_APN(octetstring apn) := {
+ type_gtpc := '83'O,
+ lengthf := lengthof(apn),
+ apn_value := apn
+ }
+
+ template (value) GSN_Address_GTPC ts_GsnAddr(template (value) octetstring ip_addr) := {
+ type_gtpc := '85'O,
+ lengthf := lengthof(ip_addr),
+ addressf := ip_addr
+ }
+ template (present) GSN_Address_GTPC tr_GsnAddr(template (present) octetstring ip_addr := ?) := {
+ type_gtpc := '85'O,
+ lengthf := ?,
+ addressf := ip_addr
+ }
+
+ template (value) MSISDN ts_Msisdn(octetstring msisdn) := {
+ type_gtpc := '86'O,
+ lengthf := lengthof(msisdn),
+ msisdn := msisdn
+ }
+
+ template (value) QoSV_GTPC ts_QosValueDefault := {
+ reliabilityClass := '011'B,
+ delayClass := '001'B,
+ spare1 := '00'B,
+ precedenceClass := '010'B,
+ spare2 := '0'B,
+ peakThroughput := '1001'B,
+ meanThroughput := '11111'B,
+ spare3 := '000'B,
+ deliverErroneusSDU := '010'B, /* Erroneus SDU are delivered */
+ deliveryOrder := '10'B, /* Without delivery order */
+ trafficClass := '100'B, /* Background */
+ maxSDUSize := '96'O, /* 1500 octets */
+ maxBitrateUplink := 'FE'O, /* 8640, continues in extended octet */
+ maxBitrateDownlink := 'FE'O, /* 8640, continues in extended octet */
+ sduErrorRatio := '0100'B, /* 1x10^-4 */
+ residualBER := '0101'B, /* 1x10^-3 */
+ trafficHandlingPriority := '01'B, /* prio 1 */
+ transferDelay := '000001'B, /* 10 ms */
+ guaranteedBitRateUplink := 'FE'O, /* 8640, continues in extended octet */
+ guaranteedBitRateDownlink := 'FE'O, /* 8640, continues in extended octet */
+ sourceStatisticsDescriptor := '0000'B, /* unknown */
+ signallingIndication := '0'B, /* Not optimized */
+ spare4 := '000'B,
+ maxBitrateDownlinkExt := '5B'O, /* 33 mbps */
+ guaranteedBitRateDownlinkExt := '5B'O, /* 33 mbps */
+ maxBitrateUplinkExt := '6e'O, /* 52 mbps */
+ guaranteedBitRateUplinkExt := '6e'O /* 52 mbps */
+ }
+
+ template (value) QualityOfServiceProfile_Value ts_QosProfileValueDefault := {
+ allocRetensionPrio := '00'O,
+ qos_ProfileValue := ts_QosValueDefault
+ }
+
+ template (value) QualityOfServiceProfile ts_QosDefault := {
+ type_gtpc := '87'O,
+ lengthf := 17,
+ allocRetensionPrio := '00'O,
+ qos_ProfileValue := ts_QosValueDefault
+ }
+
+ template (value) IMSI_gtpc ts_Imsi(hexstring digits) := {
+ type_gtpc := '02'O,
+ digits := digits,
+ padding := 'F'H
+ }
+ function f_ts_Imsi(template (omit) hexstring digits := omit) return template (omit) IMSI_gtpc {
+ var template (omit) IMSI_gtpc imsi;
+ if (istemplatekind(digits, "omit")) {
+ imsi := omit;
+ } else {
+ imsi := ts_Imsi(valueof(digits));
+ }
+ return imsi;
+ }
+ template (present) IMSI_gtpc tr_Imsi(template (present) hexstring digits) := {
+ type_gtpc := '02'O,
+ digits := digits,
+ padding := 'F'H
+ }
+ function f_tr_Imsi(template hexstring digits := *) return template IMSI_gtpc {
+ if (istemplatekind(digits, "omit")) {
+ return omit;
+ } else if (istemplatekind(digits, "*")) {
+ return *;
+ } else {
+ return tr_Imsi(digits);
+ }
+ }
+
+ /* 7.7.50 RAT Type */
+ type enumerated GTP_RATType {
+ GTP_RAT_TYPE_RESERVED (0),
+ GTP_RAT_TYPE_UTRAN (1),
+ GTP_RAT_TYPE_GERAN (2),
+ GTP_RAT_TYPE_WLAN (3),
+ GTP_RAT_TYPE_GAN (4),
+ GTP_RAT_TYPE_HSPA_E (5),
+ GTP_RAT_TYPE_EUTRAN (6)
+ };
+ template (value) RATType ts_RATType(template (value) OCT1 rat_type) := {
+ type_gtpc := '97'O,
+ lengthf := 1,
+ ratTypeValue := rat_type
+ }
+ function f_ts_RATType(template (omit) OCT1 rat_type := omit) return template (omit) RATType {
+ if (istemplatekind(rat_type, "omit")) {
+ return omit;
+ } else {
+ return ts_RATType(rat_type);
+ }
+ }
+ template (present) RATType tr_RATType(template (present) OCT1 rat_type) := {
+ type_gtpc := '97'O,
+ lengthf := 1,
+ ratTypeValue := rat_type
+ }
+ function f_tr_RATType(template OCT1 rat_type := *) return template RATType {
+ if (istemplatekind(rat_type, "omit")) {
+ return omit;
+ } else if (istemplatekind(rat_type, "*")) {
+ return *;
+ } else {
+ return tr_RATType(rat_type);
+ }
+ }
+
+ template (value) RoutingAreaIdentity ts_RoutingAreaIdentity(template (value) hexstring mcc_digits,
+ template (value) hexstring mnc_digits,
+ template (value) OCT2 lac,
+ template (value) OCT1 rac) := {
+ type_gtpc := '03'O,
+ mcc_digits := mcc_digits,
+ mnc_digits := mnc_digits,
+ lac := lac,
+ rac := rac
+ }
+
+ template (value) GeographicLocationCGI
+ ts_GeographicLocationCGI(template (value) hexstring mcc,
+ template (value) hexstring mnc,
+ template (value) OCT2 lac,
+ template (value) OCT2 cI_value) :=
+ {
+ mccDigit1 := mcc[0],
+ mccDigit2 := mcc[1],
+ mccDigit3 := mcc[2],
+ mncDigit3 := mnc[2], /* 'F'H for 2 digit MNC */
+ mncDigit1 := mnc[0],
+ mncDigit2 := mnc[1],
+ lac := lac,
+ cI_value := cI_value
+ }
+
+ template (value) GTPC_PDUs ts_CreatePdpPDU(hexstring imsi, OCT1 restart_ctr, OCT4 teid_data, OCT4 teid_ctrl,
+ BIT4 nsapi, EndUserAddress eua, octetstring apn,
+ octetstring sgsn_ip_sign, octetstring sgsn_ip_data,
+ octetstring msisdn, template (omit) ProtConfigOptions pco := omit,
+ template (omit) OCT1 ratType := omit,
+ template (omit) UserLocationInformation uli := omit,
+ template (omit) OCT2 charging_char := omit,
+ template (omit) OCT8 imeisv := omit,
+ template (omit) MS_TimeZone ms_tz := omit) := {
+ createPDPContextRequest := {
+ imsi := ts_Imsi(imsi),
+ rai := omit,
+ recovery := ts_Recovery(restart_ctr),
+ selectionMode := {
+ type_gtpc := '0F'O,
+ selectModeValue := '00'B,
+ spare := '111111'B
+ },
+ teidDataI := {
+ type_gtpc := '00'O,
+ teidDataI := teid_data
+ },
+ teidControlPlane := {
+ type_gtpc := '00'O,
+ teidControlPlane := teid_ctrl
+ },
+ nsapi := {
+ type_gtpc := '00'O,
+ nsapi := nsapi,
+ unused := '0000'B
+ },
+ linked_nsapi := omit,
+ charging_char := f_ts_ChargingCharacteristics(charging_char),
+ trace_ref := omit,
+ trace_type := omit,
+ endUserAddress := eua,
+ accessPointName := ts_APN(apn),
+ protConfigOptions := pco,
+ sgsn_addr_signalling := ts_GsnAddr(sgsn_ip_sign),
+ sgsn_addr_traffic := ts_GsnAddr(sgsn_ip_data),
+ msisdn := ts_Msisdn(msisdn),
+ qualityOfServiceProfile := ts_QosDefault,
+ tft := omit,
+ triggerId := omit,
+ omcId := omit,
+ commonFlags := omit,
+ aPN_Restriction := omit,
+ ratType := f_ts_RATType(ratType),
+ userLocationInformation := uli,
+ mS_TimeZone := ms_tz,
+ imeisv := f_ts_IMEISV(imeisv),
+ camelChargingInformationContainer := omit,
+ additionalTraceInfo := omit,
+ correlationID := omit,
+ evolvedAllocationRetentionPriorityI := omit,
+ extendedCommonFlags := omit,
+ userCSGInformation := omit,
+ aPN_AMBR := omit,
+ signallingPriorityIndication := omit,
+ cN_OperatorSelectionEntity := omit,
+ private_extension_gtpc := omit
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_CreatePDP(Gtp1cPeer peer, uint16_t seq, hexstring imsi,
+ OCT1 restart_ctr, OCT4 teid_data,
+ OCT4 teid_ctrl, BIT4 nsapi, EndUserAddress eua,
+ octetstring apn, octetstring sgsn_ip_sign,
+ octetstring sgsn_ip_data, octetstring msisdn,
+ template (omit) ProtConfigOptions pco := omit,
+ template (omit) OCT1 ratType := omit,
+ template (omit) UserLocationInformation uli := omit,
+ template (omit) OCT2 charging_char := omit,
+ template (omit) OCT8 imeisv := omit,
+ template (omit) MS_TimeZone ms_tz := omit) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(createPDPContextRequest, '00000000'O,
+ valueof(ts_CreatePdpPDU(imsi, restart_ctr, teid_data, teid_ctrl,
+ nsapi, eua, apn, sgsn_ip_sign,
+ sgsn_ip_data, msisdn, pco, ratType, uli,
+ charging_char, imeisv, ms_tz)), seq)
+ }
+
+
+ template (value) GTPC_PDUs ts_UpdatePdpPDU(hexstring imsi, OCT1 restart_ctr, OCT4 teid_data, OCT4 teid_ctrl,
+ BIT4 nsapi,
+ octetstring sgsn_ip_sign, octetstring sgsn_ip_data,
+ template (omit) ProtConfigOptions pco := omit,
+ template (omit) OCT1 ratType := omit,
+ template (omit) UserLocationInformation uli := omit) := {
+ updatePDPContextRequest := {
+ updatePDPContextRequestSGSN := {
+ imsi := ts_Imsi(imsi),
+ rai := omit,
+ recovery := ts_Recovery(restart_ctr),
+ teidDataI := {
+ type_gtpc := '00'O,
+ teidDataI := teid_data
+ },
+ teidControlPlane := {
+ type_gtpc := '00'O,
+ teidControlPlane := teid_ctrl
+ },
+ nsapi := {
+ type_gtpc := '00'O,
+ nsapi := nsapi,
+ unused := '0000'B
+ },
+ trace_ref := omit,
+ trace_type := omit,
+ protConfigOptions := pco,
+ sgsn_addr_controlPlane := ts_GsnAddr(sgsn_ip_sign),
+ sgsn_addr_traffic := ts_GsnAddr(sgsn_ip_data),
+ alt_ggsn_addr_controlPane := omit,
+ alt_ggsn_addr_traffic := omit,
+ qualityOfServiceProfile := ts_QosDefault,
+ tft := omit,
+ triggerId := omit,
+ omcId := omit,
+ commonFlags := omit,
+ ratType := f_ts_RATType(ratType),
+ userLocationInformation := uli,
+ mS_TimeZone := omit,
+ additionalTraceInfo := omit,
+ directTunnelFlags := omit,
+ evolvedAllocationRetentionPriorityI := omit,
+ extendedCommonFlags := omit,
+ userCSGInformation := omit,
+ aPN_AMBR := omit,
+ signallingPriorityIndication := omit,
+ cN_OperatorSelectionEntity := omit,
+ private_extension_gtpc := omit
+ }
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_UpdatePDP(Gtp1cPeer peer, OCT4 teid, uint16_t seq, hexstring imsi,
+ OCT1 restart_ctr, OCT4 teid_data,
+ OCT4 teid_ctrl, BIT4 nsapi, octetstring sgsn_ip_sign,
+ octetstring sgsn_ip_data,
+ template (omit) ProtConfigOptions pco := omit,
+ template (omit) OCT1 ratType := omit,
+ template (omit) UserLocationInformation uli := omit) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(updatePDPContextRequest, teid,
+ valueof(ts_UpdatePdpPDU(imsi, restart_ctr, teid_data, teid_ctrl,
+ nsapi, sgsn_ip_sign,
+ sgsn_ip_data, pco, ratType, uli)), seq)
+ }
+
+
+ template (value) NSAPI_GTPC ts_NSAPI(BIT4 nsapi) := {
+ type_gtpc := '14'O,
+ nsapi := nsapi,
+ unused := '0000'B
+ }
+
+ template (value) ReorderingRequired ts_ReorderReq(boolean req := false) := {
+ type_gtpc := '08'O,
+ reordreq := bool2bit(req),
+ spare := '0000000'B
+ }
+
+ template (value) GTPC_PDUs ts_CreatePdpRespPDU(OCT1 cause, OCT4 teid_data, OCT4 teid_ctrl, BIT4 nsapi,
+ octetstring ggsn_ip_sign, octetstring ggsn_ip_data,
+ OCT4 chg_id, template (omit) EndUserAddress eua := omit,
+ template (omit) Recovery_gtpc recovery := omit,
+ template (omit) ProtConfigOptions pco := omit) := {
+ createPDPContextResponse := {
+ cause := { '00'O, cause },
+ reorderingRequired := ts_ReorderReq(false),
+ recovery := recovery,
+ teidDataI := {
+ type_gtpc := '00'O,
+ teidDataI := teid_data
+ },
+ teidControlPlane := {
+ type_gtpc := '00'O,
+ teidControlPlane := teid_ctrl
+ },
+ nsapi := ts_NSAPI(nsapi),
+ chargingID := {
+ type_gtpc := '7F'O,
+ chargingID := chg_id
+ },
+ endUserAddress := eua,
+ protConfigOptions := pco,
+ ggsn_addr_controlPlane := ts_GsnAddr(ggsn_ip_sign),
+ ggsn_addr_traffic := ts_GsnAddr(ggsn_ip_data),
+ alt_ggsn_addr_controlPane := omit,
+ alt_ggsn_addr_traffic := omit,
+ qualityOfServiceProfile := ts_QosDefault,
+ commonFlags := omit,
+ aPN_Restriction := omit,
+ mS_InfoChangeReportingAction := omit,
+ bearerControlMode := omit,
+ evolvedAllocationRetentionPriorityI := omit,
+ extendedCommonFlag := omit,
+ csg_information_reporting_action := omit,
+ aPN_AMBR := omit,
+ gGSN_BackOffTime := omit,
+ private_extension_gtpc := omit
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_CreatePdpResp(Gtp1cPeer peer, uint16_t seq, OCT4 teid,
+ OCT1 cause,
+ OCT4 teid_ctrl, OCT4 teid_data,
+ BIT4 nsapi, octetstring ggsn_ip_sign,
+ octetstring ggsn_ip_data, OCT4 chg_id,
+ template (omit) EndUserAddress eua := omit,
+ template (omit) Recovery_gtpc recovery := omit,
+ template (omit) ProtConfigOptions pco := omit) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(createPDPContextResponse, teid,
+ valueof(ts_CreatePdpRespPDU(cause, teid_data, teid_ctrl, nsapi,
+ ggsn_ip_sign, ggsn_ip_data, chg_id,
+ eua, recovery, pco)), seq)
+ }
+
+ /* PCO send base template */
+ template (value) ProtConfigOptions ts_PCO := {
+ type_gtpc := '84'O,
+ lengthf := 0,
+ configProtocol := '000'B,
+ spare := '0000'B,
+ extension0 := '1'B,
+ protocols := {}
+ }
+ /* PCO receive base template */
+ template (present) ProtConfigOptions tr_PCO := {
+ type_gtpc := '84'O,
+ lengthf := ?,
+ configProtocol := '000'B,
+ spare := ?,
+ extension0 := '1'B,
+ protocols := {}
+ }
+
+ template (value) ProtConfigOptions ts_PCO_IPv6_DNS modifies ts_PCO := {
+ protocols := {
+ { protocolID := '0003'O, lengthProtoID := 0, protoIDContents := ''O }
+ }
+ }
+ template (present) ProtConfigOptions tr_PCO_IPv6_DNS_resp(template (present) OCT16 contents) modifies tr_PCO := {
+ protocols := {
+ *, { protocolID := '0003'O, lengthProtoID := 16, protoIDContents := contents }, *
+ }
+ }
+
+ template (value) ProtConfigOptions ts_PCO_IPv4_DNS_IPCP(uint8_t ipcp_req_id := 0) modifies ts_PCO := {
+ protocols := {
+ /* dummy PAP entry to check if our parser in the GGSN can properly iterate over
+ * the list of protocols, see Change-Id Icc2e6716c33d78d3c3e000f529806228d8aa155e */
+ { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
+ enc_IpcpPacket(valueof(ts_IPCP_ReqDNS(ipcp_req_id))) }
+ }
+ }
+
+ template (value) ProtConfigOptions ts_PCO_IPv4_PRI_DNS_IPCP modifies ts_PCO := {
+ protocols := {
+ /* dummy PAP entry to check if our parser can cope with a single primary DNS entry
+ * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
+ { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
+ enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Primary)) }
+ }
+ }
+ template (value) ProtConfigOptions ts_PCO_IPv4_SEC_DNS_IPCP modifies ts_PCO := {
+ protocols := {
+ /* dummy PAP entry to check if our parser can cope with a single secondary DNS entry
+ * see Change-Id Icffde89f9bc5d8fcadf6e2dd6c0b4de03440edd5 and OS#3288 */
+ { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
+ enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Secondary)) }
+ }
+ }
+ template (value) ProtConfigOptions ts_PCO_IPv4_SEPARATE_DNS_IPCP modifies ts_PCO := {
+ protocols := {
+ /* dummy PAP entry to check if our parser can cope with a primary and secondary DNS
+ * in separate IPCP containers OS#3381 */
+ { protocolID := 'C023'O, lengthProtoID := 0, protoIDContents := ''O },
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
+ enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Primary)) },
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents :=
+ enc_IpcpPacket(valueof(ts_IPCP_ReqDNS_Secondary)) }
+ }
+ }
+
+ template (present) ProtocolElement tr_PCO_Proto(OCT2 prot_id) := {
+ protocolID := prot_id,
+ lengthProtoID := ?,
+ protoIDContents := ?
+ }
+ template (value) ProtocolElement ts_PCOelem_PAP_broken := {
+ protocolID := 'C023'O,
+ lengthProtoID := 60,
+ /* PPP Password Authentication Protocol containing incorrect Peer-Id-Length set to 4 (6-7 should be the valid one), see OS#3914. */
+ protoIDContents := '0100003c'O & '0444435338323700bc1c08087c1508083e00790000150808fd06000001000000000000000000000000000000000000000000000000000000'O
+ }
+ template (value) ProtConfigOptions ts_PCO_PAP_IPv4_DNS modifies ts_PCO := {
+ protocols := {
+ ts_PCOelem_PAP_broken,
+ { protocolID := '8021'O, lengthProtoID := 16, protoIDContents := enc_IpcpPacket(valueof(ts_IPCP_ReqDNS)) }
+ }
+ }
+ template (present) ProtConfigOptions tr_PCO_Contains(OCT2 prot_id) modifies tr_PCO := {
+ protocols := { *, tr_PCO_Proto(prot_id), * }
+ }
+
+ template (value) ProtConfigOptions ts_PCO_IPv4_DNS_CONT modifies ts_PCO := {
+ protocols := {
+ { protocolID := '000d'O, lengthProtoID := 0, protoIDContents := ''O }
+ }
+ }
+ template (present) ProtConfigOptions tr_PCO_IPv4_DNS_CONT_resp(template (present) OCT4 contents) modifies tr_PCO := {
+ protocols := {
+ *, { protocolID := '000d'O, lengthProtoID := 4, protoIDContents := contents }, *
+ }
+ }
+
+ /* extract a given protocol payload from PCO */
+ function f_PCO_extract_proto(ProtConfigOptions pco, OCT2 protocol, integer nth_match := 1) return octetstring {
+ var integer i;
+ var integer num_matches := 0;
+ for (i := 0; i < lengthof(pco.protocols); i := i + 1) {
+ if (pco.protocols[i].protocolID == protocol) {
+ num_matches := num_matches + 1;
+ if (num_matches == nth_match) {
+ return pco.protocols[i].protoIDContents;
+ }
+ }
+ }
+ setverdict(fail, "Could not extract protocol payload from protocol ", protocol);
+ mtc.stop;
+ return ''O;
+ }
+
+ template (present) IpcpPacket tr_IPCP(template (present) LcpCode code, template (present)uint8_t identifier,
+ template (present) IpcpOptionList opts) := {
+ code := code,
+ identifier := identifier,
+ len := ?,
+ options := opts
+ }
+ template (present) IpcpOption tr_IPCP_PrimaryDns(template (present) OCT4 addr) := {
+ code := IPCP_OPT_PrimaryDNS,
+ len := 6,
+ data := addr
+ }
+ template (present) IpcpOption tr_IPCP_SecondaryDns(template (present) OCT4 addr) := {
+ code := IPCP_OPT_SecondaryDNS,
+ len := 6,
+ data := addr
+ }
+ template (present) IpcpPacket tr_IPCP_Ack_DNS(template (present) uint8_t identifier := ?,
+ template (present) OCT4 dns1 := ?,
+ template (present) OCT4 dns2 := ?) :=
+ tr_IPCP(LCP_Configure_Ack, identifier,
+ { *, tr_IPCP_PrimaryDns(dns1), *, tr_IPCP_SecondaryDns(dns2), * });
+
+ template (value) IpcpPacket ts_IPCP(LcpCode code, uint8_t identifier, template (value) IpcpOptionList opts) := {
+ code := code,
+ identifier := identifier,
+ len := 0, /* overwritten */
+ options := opts
+ }
+ template (value) IpcpPacket ts_IPCP_ReqDNS(uint8_t identifier := 0) :=
+ ts_IPCP(LCP_Configure_Request, identifier,
+ { tr_IPCP_PrimaryDns('00000000'O), tr_IPCP_SecondaryDns('00000000'O) });
+
+ template (value) IpcpPacket ts_IPCP_ReqDNS_Primary(uint8_t identifier := 0) :=
+ ts_IPCP(LCP_Configure_Request, identifier,
+ { tr_IPCP_PrimaryDns('00000000'O) });
+ template (value) IpcpPacket ts_IPCP_ReqDNS_Secondary(uint8_t identifier := 0) :=
+ ts_IPCP(LCP_Configure_Request, identifier,
+ { tr_IPCP_SecondaryDns('00000000'O) });
+
+ function f_teardown_ind_IE(in template (omit) BIT1 ind) return template (omit) TearDownInd {
+ if (istemplatekind(ind, "omit")) {
+ return omit;
+ }
+ var TearDownInd ret := {
+ type_gtpc := '13'O,
+ tdInd := valueof(ind),
+ spare:= '0000000'B
+ }
+ return ret;
+ }
+
+ template (value) GTPC_PDUs ts_DeletePdpPDU(BIT4 nsapi, template (omit) BIT1 teardown_ind) := {
+ deletePDPContextRequest := {
+ cause := omit,
+ tearDownIndicator := f_teardown_ind_IE(teardown_ind),
+ nsapi := {
+ type_gtpc := '14'O,
+ nsapi := nsapi,
+ unused := '0000'B
+ },
+ protConfigOptions := omit,
+ userLocationInformation := omit,
+ mS_TimeZone := omit,
+ extendedCommonFlags := omit,
+ uLI_Timestamp := omit,
+ private_extension_gtpc := omit
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_DeletePDP(Gtp1cPeer peer, uint16_t seq, OCT4 teid,
+ BIT4 nsapi, template (omit) BIT1 teardown_ind) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(deletePDPContextRequest, teid,
+ valueof(ts_DeletePdpPDU(nsapi, teardown_ind)), seq)
+ }
+
+ template (value) GTPC_PDUs ts_DeletePdpRespPDU(OCT1 cause,
+ template (omit) ProtConfigOptions pco := omit) := {
+ deletePDPContextResponse := {
+ cause := { '00'O, cause },
+ protConfigOptions := pco,
+ userLocationInformation := omit,
+ mS_TimeZone := omit,
+ uLI_Timestamp := omit,
+ private_extension_gtpc := omit
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_DeletePdpResp(Gtp1cPeer peer, uint16_t seq, OCT4 teid,
+ OCT1 cause,
+ template (omit) ProtConfigOptions pco := omit) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(deletePDPContextResponse, teid,
+ valueof(ts_DeletePdpRespPDU(cause, pco)), seq)
+ }
+
+ /* SGSN Context Request - 7.5.3 */
+ template (present) GTPC_PDUs tr_SGSNContextReqPDU(template (present) RoutingAreaIdentity rai := ?,
+ template (present) OCT4 teic := ?,
+ template (present) octetstring sgsn_addr_control := ?,
+ template hexstring imsi := *,
+ template BIT1 msValidated := *,
+ template TLLI tlli := *,
+ template PacketTMSI ptmsi := *,
+ template PTMSI_Signature ptmsi_sig := *,
+ template OCT1 rat_type := *) := {
+ sgsn_ContextRequest := {
+ imsi := f_tr_Imsi(imsi),
+ routingAreaIdentity := rai,
+ tlli := tlli,
+ packetTMSI := ptmsi,
+ ptmsi_Signature := ptmsi_sig,
+ ms_Validated := f_tr_MS_Validated(msValidated),
+ teidControlPlane := {
+ type_gtpc := '11'O,
+ teidControlPlane := teic
+ },
+ sgsn_addr_controlPlane := tr_GsnAddr(sgsn_addr_control),
+ alternative_sgsn_addr_controlPlane := *,
+ sGSN_Number := *,
+ ratType := f_tr_RATType(rat_type),
+ hopCounter := *,
+ private_extension_gtpc := *
+ }
+ }
+ template (present) Gtp1cUnitdata tr_GTPC_SGSNContextReq(template (present) Gtp1cPeer peer,
+ template (present) GTPC_PDUs SGSNContextReqPDU) := {
+ peer := peer,
+ gtpc := tr_GTP1C_PDU(sgsnContextRequest, '00000000'O, SGSNContextReqPDU)
+ }
+ template (value) GTPC_PDUs ts_SGSNContextReqPDU(template (value) RoutingAreaIdentity rai,
+ template (value) OCT4 teic,
+ template (value) octetstring sgsn_addr_control,
+ template (omit) hexstring imsi := omit,
+ template (omit) BIT1 msValidated := '0'B,
+ template (omit) TLLI tlli := omit,
+ template (omit) PacketTMSI ptmsi := omit,
+ template (omit) PTMSI_Signature ptmsi_sig := omit,
+ template (omit) OCT1 rat_type := omit) := {
+ sgsn_ContextRequest := {
+ imsi := f_ts_Imsi(imsi),
+ routingAreaIdentity := rai,
+ tlli := tlli,
+ packetTMSI := ptmsi,
+ ptmsi_Signature := ptmsi_sig,
+ ms_Validated := f_ts_MS_Validated(msValidated),
+ teidControlPlane := {
+ type_gtpc := '11'O,
+ teidControlPlane := teic
+ },
+ sgsn_addr_controlPlane := ts_GsnAddr(sgsn_addr_control),
+ alternative_sgsn_addr_controlPlane := omit,
+ sGSN_Number := omit,
+ ratType := f_ts_RATType(rat_type),
+ hopCounter := omit,
+ private_extension_gtpc := omit
+ }
+ }
+ template (value) Gtp1cUnitdata ts_GTPC_SGSNContextReq(Gtp1cPeer peer, uint16_t seq,
+ template (value) GTPC_PDUs SGSNContextReqPDU) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(sgsnContextRequest, '00000000'O, valueof(SGSNContextReqPDU), seq)
+ }
+
+ /* SGSN Context Response - 7.5.4 */
+ template (present) GTPC_PDUs tr_SGSNContextRespPDU(template (present) GTP_Cause cause := ?,
+ template hexstring imsi := *) := {
+ sgsn_ContextResponse := {
+ cause := tr_Cause_gtpc(cause),
+ imsi := f_tr_Imsi(imsi),
+ teidControlPlane := *,
+ rabContext := *,
+ radioPrioritySMS := *,
+ radioPriority := *,
+ packetFlowID := *,
+ charging_char := *,
+ mm_Context := *,
+ pdp_Context := *,
+ sgsn_addr_controlPlane := *,
+ pdpContextPriorization := *,
+ radioPriority_LCS := *,
+ mBMS_UE_Context := *,
+ subscribedRFSP_Index := *,
+ rFSP_IndexInUse := *,
+ colocatedGGSN_PGW_FQDN := *,
+ evolvedAllocationRetentionPriorityII := *,
+ extendedCommonFlags := *,
+ ue_network_capability := *,
+ ue_ambr := *,
+ apn_ambr_nsapi := *,
+ signallingPriorityIndication_nsapi := *,
+ higher_bitrates_than_16mbps_flag := *,
+ selectionMode_nsapi := *,
+ localHomeNetworkID_nsapi := *,
+ uE_UsageType := *,
+ extendedCommonFlagsII := *,
+ private_extension_gtpc := *
+ }
+ }
+ template (present) Gtp1cUnitdata tr_GTPC_SGSNContextResp(template (present) Gtp1cPeer peer := ?,
+ template (present) OCT4 teid := ?,
+ template (present) GTPC_PDUs SGSNContextRespPDU := ?)
+ := tr_GTPC_MsgType(peer, sgsnContextResponse, teid, SGSNContextRespPDU);
+
+ template (value) GTPC_PDUs ts_SGSNContextRespPDU(template (value) GTP_Cause cause,
+ template (omit) hexstring imsi := omit,
+ template (omit) OCT4 teic := omit,
+ template (omit) octetstring sgsn_addr_control := omit,
+ template (omit) MM_Context mm_context := omit,
+ template (omit) PDP_Context_GTPC_List pdp_ctx_list := omit) := {
+ sgsn_ContextResponse := {
+ cause := ts_Cause_gtpc(cause),
+ imsi := f_ts_Imsi(imsi),
+ teidControlPlane := f_ts_TEIC(teic),
+ rabContext := omit,
+ radioPrioritySMS := omit,
+ radioPriority := omit,
+ packetFlowID := omit,
+ charging_char := omit,
+ mm_Context := mm_context,
+ pdp_Context := pdp_ctx_list,
+ sgsn_addr_controlPlane := ts_GsnAddr(sgsn_addr_control),
+ pdpContextPriorization := omit,
+ radioPriority_LCS := omit,
+ mBMS_UE_Context := omit,
+ subscribedRFSP_Index := omit,
+ rFSP_IndexInUse := omit,
+ colocatedGGSN_PGW_FQDN := omit,
+ evolvedAllocationRetentionPriorityII := omit,
+ extendedCommonFlags := omit,
+ ue_network_capability := omit,
+ ue_ambr := omit,
+ apn_ambr_nsapi := omit,
+ signallingPriorityIndication_nsapi := omit,
+ higher_bitrates_than_16mbps_flag := omit,
+ selectionMode_nsapi := omit,
+ localHomeNetworkID_nsapi := omit,
+ uE_UsageType := omit,
+ extendedCommonFlagsII := omit,
+ private_extension_gtpc := omit
+ }
+ }
+ template (value) Gtp1cUnitdata ts_GTPC_SGSNContextResp(Gtp1cPeer peer, OCT4 teid, uint16_t seq,
+ template (value) GTPC_PDUs SGSNContextRespPDU) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(sgsnContextResponse, teid, valueof(SGSNContextRespPDU), seq)
+ }
+
+
+ /* SGSN Context Acknowledge - 7.5.5 */
+ template (present) GTPC_PDUs tr_SGSNContextAckPDU(template (present) GTP_Cause cause := ?) := {
+ sgsn_ContextAcknowledge := {
+ cause := tr_Cause_gtpc(cause),
+ teidDataII := *,
+ sgsn_AddressForUserTraffic := *,
+ sgsn_Number := *,
+ nodeIdentifier := *,
+ private_extension_gtpc := *
+ }
+ }
+ template (present) Gtp1cUnitdata tr_GTPC_SGSNContextAck(template (present) Gtp1cPeer peer := ?,
+ template (present) OCT4 teid := ?,
+ template (present) GTPC_PDUs SGSNContextAckPDU := ?)
+ := tr_GTPC_MsgType(peer, sgsnContextAcknowledge, teid, SGSNContextAckPDU);
+ template (value) GTPC_PDUs ts_SGSNContextAckPDU(template (value) GTP_Cause cause := GTP_CAUSE_REQUEST_ACCEPTED) := {
+ sgsn_ContextAcknowledge := {
+ cause := ts_Cause_gtpc(cause),
+ teidDataII := omit,
+ sgsn_AddressForUserTraffic := omit,
+ sgsn_Number := omit,
+ nodeIdentifier := omit,
+ private_extension_gtpc := omit
+ }
+ }
+
+ template (value) Gtp1cUnitdata ts_GTPC_SGSNContextAck(Gtp1cPeer peer, OCT4 teid, uint16_t seq,
+ template (value) GTPC_PDUs SGSNContextAckPDU := ts_SGSNContextAckPDU) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(sgsnContextAcknowledge, teid, valueof(SGSNContextAckPDU), seq)
+ }
+
+ /* GTP-C RIM */
+
+ template (value) RIM_Application_Identity_GTPC ts_GTPC_RIM_Application_Identity(OCT1 app_id) := {
+ iEI := '4B'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rIMApplicationIdentity := app_id
+ }
+ /* 3GPP TS 48.018 11.3.62 */
+ template (value) RIM_Sequence_Number_GTPC ts_GTPC_RIM_Sequence_Number(integer seq) := {
+ iEI := '4C'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 4
+ },
+ rIMSequenceNumber := int2oct(seq, 4)
+ }
+ template (value) RIM_PDU_Indications_GTPC ts_GTPC_RIM_PDU_Indications(boolean ack, BIT3 type_ext) := {
+ iEI := '4F'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ ack := bool2bit(ack),
+ pDU_Type_Extension := type_ext,
+ reserved := '0000'B
+ }
+ /* 3GPP TS 48.018 11.3.67 */
+ template (value) RIM_Protocol_Version_Number_GTPC ts_GTPC_RIM_Protocol_Version_Number(integer ver) := {
+ iEI := '55'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rIMProtocolVersionNumber := int2oct(ver, 1)
+ }
+ function tr_GTPC_Cell_Identifier_V(template (present) GTP_CellId cid) return template (present) Cell_Identifier_V_GTPC {
+ var template Cell_Identifier_V_GTPC ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ lac := ?,
+ rac := ?,
+ cI_value := ?
+ }
+ if (istemplatekind(cid, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ if (isvalue(cid.ra_id.lai.lac)) {
+ ret.lac := f_oct_or_wc(cid.ra_id.lai.lac, 2);
+ }
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id)) {
+ ret.rac := f_oct_or_wc(cid.ra_id.rac, 1);
+ }
+ if (isvalue(cid)) {
+ ret.cI_value := f_oct_or_wc(cid.cell_id, 2);
+ }
+ return ret;
+ }
+ template (value) Cell_Identifier_V_GTPC ts_GTPC_Cell_Identifier_V(GTP_CellId cid) := {
+ mccDigit1 := cid.ra_id.lai.mcc_mnc[0],
+ mccDigit2 := cid.ra_id.lai.mcc_mnc[1],
+ mccDigit3 := cid.ra_id.lai.mcc_mnc[2],
+ mncDigit3 := cid.ra_id.lai.mcc_mnc[3],
+ mncDigit1 := cid.ra_id.lai.mcc_mnc[4],
+ mncDigit2 := cid.ra_id.lai.mcc_mnc[5],
+ lac := int2oct(cid.ra_id.lai.lac, 2),
+ rac := int2oct(cid.ra_id.rac, 1),
+ cI_value := int2oct(cid.cell_id, 2)
+ }
+ template (value) RIM_Routing_Address_GTPC t_GTPC_RIM_Routing_Address_cid(GTP_CellId cid) := {
+ cell_Identifier := ts_GTPC_Cell_Identifier_V(cid)
+ }
+ function tr_GTPC_ENB_Identifier(template (present) GTP_CellId cid,
+ template (present) integer tac,
+ template (present) octetstring gnbid) return template (present) ENB_Identifier {
+ var template (present) ENB_Identifier ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ tAC := ?,
+ globalENB_ID := ?
+ }
+ if (istemplatekind(cid, "?") and istemplatekind(tac, "?") and istemplatekind(gnbid, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ }
+ if (isvalue(tac)) {
+ ret.tAC := int2oct(valueof(tac), 2);
+ }
+ if (isvalue(gnbid)) {
+ ret.globalENB_ID := gnbid;
+ }
+
+ return ret;
+ }
+ template (value) ENB_Identifier ts_GTPC_ENB_Identifier(GTP_CellId cid, integer tac, octetstring gnbid) := {
+ mccDigit1 := cid.ra_id.lai.mcc_mnc[0],
+ mccDigit2 := cid.ra_id.lai.mcc_mnc[1],
+ mccDigit3 := cid.ra_id.lai.mcc_mnc[2],
+ mncDigit3 := cid.ra_id.lai.mcc_mnc[3],
+ mncDigit1 := cid.ra_id.lai.mcc_mnc[4],
+ mncDigit2 := cid.ra_id.lai.mcc_mnc[5],
+ tAC := int2oct(tac, 2),
+ globalENB_ID := gnbid
+ }
+ template (value) RIM_Routing_Address_GTPC t_GTPC_RIM_Routing_Address_enbid(GTP_CellId cid, integer tac, octetstring gnbid) := {
+ eNB_Identifier := ts_GTPC_ENB_Identifier(cid, tac, gnbid)
+ }
+ template (present) RIM_Routing_Information_GTPC
+ tr_GTPC_RIM_Routing_Information(HEX1 addr_discr, template (present) RIM_Routing_Address_GTPC addr) := {
+ iEI := '54'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIMRoutingAddressDiscriminator := addr_discr,
+ spare := '0'H,
+ rIM_Routing_Address := addr
+ }
+ template (value) RIM_Routing_Information_GTPC
+ ts_GTPC_RIM_Routing_Information(HEX1 addr_discr, template (value) RIM_Routing_Address_GTPC addr) := {
+ iEI := '54'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIMRoutingAddressDiscriminator := addr_discr,
+ spare := '0'H,
+ rIM_Routing_Address := addr
+ }
+ /* 3GPP TS 48.018 11.3.63.1.1 */
+ template (present) RAN_Information_Request_Application_Container_NACC_GTPC
+ tr_GTPC_RAN_Information_Request_Application_Container_NACC(template (present) GTP_CellId cid) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ reporting_Cell_Identifier := tr_GTPC_Cell_Identifier_V(cid)
+ }
+ template (value) RAN_Information_Request_Application_Container_NACC_GTPC
+ ts_GTPC_RAN_Information_Request_Application_Container_NACC(GTP_CellId cid) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_GTPC_Cell_Identifier_V(cid)
+ }
+ /* 3GPP TS 48.018 11.3.63.1 */
+ template (present) RAN_Information_Request_Application_Container_GTPC
+ tru_GTPC_RAN_Information_Request_Application_Container_NACC(template (present) GTP_CellId cid) := {
+ nacc := tr_GTPC_RAN_Information_Request_Application_Container_NACC(cid)
+ }
+ template (value) RAN_Information_Request_Application_Container_GTPC
+ tsu_GTPC_RAN_Information_Request_Application_Container_NACC(GTP_CellId cid) := {
+ nacc := ts_GTPC_RAN_Information_Request_Application_Container_NACC(cid)
+ }
+ /* 3GPP TS 48.018 11.3.63.2.1 */
+ template (present) RAN_Information_Application_Container_NACC_GTPC
+ tr_GTPC_RAN_Information_Application_Container_NACC(template (present) GTP_CellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ iEI := '4E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ reporting_Cell_Identifier := tr_GTPC_Cell_Identifier_V(cid),
+ typeBit := bool2bit(psi_type),
+ number_of_SI_PSI := int2bit(si_psi_num, 7),
+ sI_PSI := si_psi
+ }
+ template (value) RAN_Information_Application_Container_NACC_GTPC
+ ts_GTPC_RAN_Information_Application_Container_NACC(GTP_CellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ iEI := '4E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_GTPC_Cell_Identifier_V(cid),
+ typeBit := bool2bit(psi_type),
+ number_of_SI_PSI := int2bit(si_psi_num, 7),
+ sI_PSI := si_psi
+ }
+ external function enc_RIM_Routing_Address_GTPC(in RIM_Routing_Address_GTPC ra) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+ external function dec_RIM_Routing_Address_GTPC(in octetstring stream) return RIM_Routing_Address_GTPC
+ with { extension "prototype(convert) decode(RAW)" };
+
+ /* RAN_Information_Request */
+ template (value) RAN_Information_Request_RIM_Container_GTPC
+ ts_GTPC_RAN_Information_Request_RIM_Container(template (value) RIM_Application_Identity_GTPC app_id,
+ template (value) RIM_Sequence_Number_GTPC seq,
+ template (value) RIM_PDU_Indications_GTPC ind,
+ template (omit) RIM_Protocol_Version_Number_GTPC ver := omit,
+ template (omit) RAN_Information_Request_Application_Container_GTPC app_cont := omit,
+ template (omit) SON_TransferApplicationIdentity son_app_id := omit) := {
+ iEI := '57'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Container := app_cont,
+ sON_TransferApplicationIdentity := son_app_id
+ }
+ template (value) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC
+ ts_GTPC_RAN_Information_Request(template (value) RIM_Routing_Information_GTPC dest,
+ template (value) RIM_Routing_Information_GTPC src,
+ template (value) RAN_Information_Request_RIM_Container_GTPC cont) := {
+ bssgpPduType := '71'O,
+ destination_Cell_Identifier := dest,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ template (present) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC
+ tr_GTPC_RAN_Information_Request(template (present) RIM_Routing_Information_GTPC dest := ?,
+ template (present) RIM_Routing_Information_GTPC src := ?,
+ template (present) RAN_Information_Request_RIM_Container_GTPC cont := ?) := {
+ bssgpPduType := '71'O,
+ destination_Cell_Identifier := dest,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+
+ template (value) RANTransparentContainer ts_RANTransparentContainer_RAN_INFO_REQ(template (value) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC pdu) := {
+ type_gtpc := '90'O,
+ lengthf := 0, /* FIXME */
+ rANTransparentContainerField := {
+ pDU_BSSGP_RAN_INFORMATION_REQUEST := pdu
+ }
+ }
+ template (present) RANTransparentContainer tr_RANTransparentContainer_RAN_INFO_REQ(template (present) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC pdu := ?) := {
+ type_gtpc := '90'O,
+ lengthf := ?,
+ rANTransparentContainerField := {
+ pDU_BSSGP_RAN_INFORMATION_REQUEST := pdu
+ }
+ }
+
+ /* RAN_Information */
+ template (present) ApplContainer_or_ApplErrContainer_NACC_GTPC
+ tru_GTPC_ApplContainer_NACC(GTP_CellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ application_Container := tr_GTPC_RAN_Information_Application_Container_NACC(cid, psi_type, si_psi_num, si_psi)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_NACC_GTPC
+ tsu_GTPC_ApplContainer_NACC(GTP_CellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ application_Container := ts_GTPC_RAN_Information_Application_Container_NACC(cid, psi_type, si_psi_num, si_psi)
+ }
+ template (present) ApplContainer_or_ApplErrContainer_GTPC
+ tru_GTPC_ApplContainer_or_ApplErrContainer_NACC(template (present) ApplContainer_or_ApplErrContainer_NACC_GTPC cont) := {
+ nacc := cont
+ }
+ template (value) ApplContainer_or_ApplErrContainer_GTPC
+ tsu_GTPC_ApplContainer_or_ApplErrContainer_NACC(template (value) ApplContainer_or_ApplErrContainer_NACC_GTPC cont) := {
+ nacc := cont
+ }
+ template (present) RAN_Information_RIM_Container_GTPC
+ tr_GTPC_RAN_Information_RIM_Container(template (present) RIM_Application_Identity_GTPC app_id,
+ template (present) RIM_Sequence_Number_GTPC seq,
+ template (present) RIM_PDU_Indications_GTPC ind,
+ template RIM_Protocol_Version_Number_GTPC ver := *,
+ template ApplContainer_or_ApplErrContainer_GTPC app_cont := *,
+ template SON_TransferApplicationIdentity son_app_id := *) := {
+ iEI := '58'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ applContainer_or_ApplErrContainer := app_cont,
+ sON_TransferApplicationIdentity := son_app_id
+ }
+ template (value) RAN_Information_RIM_Container_GTPC
+ ts_GTPC_RAN_Information_RIM_Container(template (value) RIM_Application_Identity_GTPC app_id,
+ template (value) RIM_Sequence_Number_GTPC seq,
+ template (value) RIM_PDU_Indications_GTPC ind,
+ template (omit) RIM_Protocol_Version_Number_GTPC ver := omit,
+ template (omit) ApplContainer_or_ApplErrContainer_GTPC app_cont := omit,
+ template (omit) SON_TransferApplicationIdentity son_app_id := omit) := {
+ iEI := '58'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ applContainer_or_ApplErrContainer := app_cont,
+ sON_TransferApplicationIdentity := son_app_id
+ }
+ template (present) PDU_BSSGP_RAN_INFORMATION_GTPC
+ tr_GTPC_RAN_Information(template (present) RIM_Routing_Information_GTPC dest,
+ template (present) RIM_Routing_Information_GTPC src,
+ template (present) RAN_Information_RIM_Container_GTPC cont) := {
+ bssgpPduType := '70'O,
+ destination_Cell_Identifier := dest,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ template (value) PDU_BSSGP_RAN_INFORMATION_GTPC
+ ts_GTPC_RAN_Information(template (value) RIM_Routing_Information_GTPC dest,
+ template (value) RIM_Routing_Information_GTPC src,
+ template (value) RAN_Information_RIM_Container_GTPC cont) := {
+ bssgpPduType := '70'O,
+ destination_Cell_Identifier := dest,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ template (present) RANTransparentContainer tr_RANTransparentContainer_RAN_INFO(template (present) PDU_BSSGP_RAN_INFORMATION_GTPC pdu) := {
+ type_gtpc := '90'O,
+ lengthf := ?,
+ rANTransparentContainerField := {
+ pDU_BSSGP_RAN_INFORMATION := pdu
+ }
+ }
+ template (value) RANTransparentContainer ts_RANTransparentContainer_RAN_INFO(template (value) PDU_BSSGP_RAN_INFORMATION_GTPC pdu) := {
+ type_gtpc := '90'O,
+ lengthf := 0, /* overwritten */
+ rANTransparentContainerField := {
+ pDU_BSSGP_RAN_INFORMATION := pdu
+ }
+ }
+
+ template (present) RANTransparentContainer tr_RANTransparentContainer(template (present) RANTransparentContainerField rANTransparentContainerField) := {
+ type_gtpc := '90'O,
+ lengthf := ?,
+ rANTransparentContainerField := rANTransparentContainerField
+ }
+ template (value) RANTransparentContainer ts_RANTransparentContainer(template (value) RANTransparentContainerField rANTransparentContainerField) := {
+ type_gtpc := '90'O,
+ lengthf := 0, /* overwritten */
+ rANTransparentContainerField := rANTransparentContainerField
+ }
+ template (present) GTPC_PDUs tr_RANInfoRelay(template (present) RANTransparentContainer transparentContainer) := {
+ ranInformationRelay := {
+ transparentContainer := transparentContainer,
+ rIM_RoutingAddress := *,
+ rIM_RoutingAddress_Discriminator := *,
+ private_extension_gtpc := *
+ }
+ }
+ template (value) GTPC_PDUs ts_RANInfoRelay(template (value) RANTransparentContainer transparentContainer,
+ template (omit) RIM_RoutingAddress ra := omit,
+ template (omit) RIM_RoutingAddress_Discriminator ra_discr := omit) := {
+ ranInformationRelay := {
+ transparentContainer := transparentContainer,
+ rIM_RoutingAddress := ra,
+ rIM_RoutingAddress_Discriminator := ra_discr,
+ private_extension_gtpc := omit
+ }
+ }
+ template (present) Gtp1cUnitdata
+ tr_GTPC_RANInfoRelay(template (present) Gtp1cPeer peer,
+ template (present) RANTransparentContainer transparentContainer) := {
+ peer := peer,
+ gtpc := tr_GTP1C_PDU(rANInformationRelay, '00000000'O, tr_RANInfoRelay(transparentContainer))
+ }
+ template (value) Gtp1cUnitdata
+ ts_GTPC_RANInfoRelay(template (value) Gtp1cPeer peer,
+ template (value) RANTransparentContainer transparentContainer,
+ template (omit) RIM_RoutingAddress ra := omit,
+ template (omit) RIM_RoutingAddress_Discriminator ra_discr := omit) := {
+ peer := peer,
+ gtpc := ts_GTP1C_PDU(rANInformationRelay, '00000000'O, valueof(ts_RANInfoRelay(transparentContainer, ra, ra_discr)), 0)
+ }
+
+
+ template (present) RAN_Information_Request_RIM_Container_GTPC
+ tr_GTPC_RAN_Information_Request_RIM_Container(template (present) RIM_Application_Identity_GTPC app_id := ?,
+ template (present) RIM_Sequence_Number_GTPC seq := ?,
+ template (present) RIM_PDU_Indications_GTPC ind := ?,
+ template RIM_Protocol_Version_Number_GTPC ver := *,
+ template RAN_Information_Request_Application_Container_GTPC app_cont := *,
+ template SON_TransferApplicationIdentity son_app_id := *) := {
+ iEI := '57'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Container := app_cont,
+ sON_TransferApplicationIdentity := son_app_id
+ }
+
+ /* 3GPP TS 29.060, section 7.7.57 */
+ template (value) RIM_RoutingAddress ts_RIM_RoutingAddress(octetstring addr_value) := {
+ type_gtpc := '9F'O,
+ lengthf := 0, /* we assume encoder overwrites this */
+ rIM_RoutingAddressValue := addr_value
+ }
+ template (present) RIM_RoutingAddress tr_RIM_RoutingAddress(template (present) octetstring addr_value := ?) := {
+ type_gtpc := '9F'O,
+ lengthf := ?,
+ rIM_RoutingAddressValue := addr_value
+ }
+
+ /* 3GPP TS 29.060, section 7.7.77 */
+ template (value) RIM_RoutingAddress_Discriminator ts_RIM_RoutingAddress_Discriminator(bitstring addr_discr) := {
+ type_gtpc := 'B2'O,
+ lengthf := 0, /* we assume encoder overwrites this */
+ rra_discriminator := addr_discr,
+ spare := '0000'B
+ }
+ template (present) RIM_RoutingAddress_Discriminator tr_RIM_RoutingAddress_Discriminator(template (present) bitstring addr_discr := ?) := {
+ type_gtpc := 'B2'O,
+ lengthf := ?,
+ rra_discriminator := addr_discr,
+ spare := '0000'B
+ }
+}
diff --git a/library/GTP_CodecPort.ttcn b/library/GTPv1U_CodecPort.ttcn
index a8507a68..59c5ef39 100644
--- a/library/GTP_CodecPort.ttcn
+++ b/library/GTPv1U_CodecPort.ttcn
@@ -1,4 +1,4 @@
-/* dual-faced port sitting on top of IPL4_asp UDP to encode/decode GTP
+/* dual-faced port sitting on top of IPL4_asp UDP to encode/decode GTPv1-U
* (C) 2017 Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
@@ -9,59 +9,25 @@
*/
-module GTP_CodecPort {
+module GTPv1U_CodecPort {
import from IPL4asp_PortType all;
import from IPL4asp_Types all;
- import from GTPC_Types all;
import from GTPU_Types all;
+ import from Misc_Helpers all;
/* identifies a remote peer (sender or receiver) */
- type record GtpPeer {
+ type record Gtp1uPeer {
ConnectionId connId,
HostName remName,
PortNumber remPort
}
- /* Decoded GTP1C (Control Plane), used in send and receive direction */
- type record Gtp1cUnitdata {
- GtpPeer peer,
- PDU_GTPC gtpc
- }
-
/* Decoded GTP1U (User Plane), used in send and receive direction */
type record Gtp1uUnitdata {
- GtpPeer peer,
+ Gtp1uPeer peer,
PDU_GTPU gtpu
}
- /* Translation port on top of IPL4asp; ASP_Event passed through transparently */
- type port GTPC_PT message {
- out Gtp1cUnitdata;
- in Gtp1cUnitdata,
- ASP_ConnId_ReadyToRelease,
- ASP_Event;
- } with { extension "user IPL4asp_PT
- out(Gtp1cUnitdata -> ASP_SendTo: function(f_enc_Gtp1cUD))
- in(ASP_RecvFrom -> Gtp1cUnitdata: function(f_dec_Gtp1cUD);
- ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
- ASP_Event -> ASP_Event: simple)" }
-
- private function f_enc_Gtp1cUD(in Gtp1cUnitdata in_ud, out ASP_SendTo out_ud) {
- out_ud.connId := in_ud.peer.connId;
- out_ud.remName := in_ud.peer.remName;
- out_ud.remPort := in_ud.peer.remPort;
- out_ud.proto := { udp := {} };
- out_ud.msg := enc_PDU_GTPC(in_ud.gtpc);
- } with { extension "prototype(fast)" };
-
- private function f_dec_Gtp1cUD(in ASP_RecvFrom in_ud, out Gtp1cUnitdata out_ud) {
- out_ud.peer.connId := in_ud.connId;
- out_ud.peer.remName := in_ud.remName;
- out_ud.peer.remPort := in_ud.remPort;
- out_ud.gtpc := dec_PDU_GTPC(in_ud.msg);
- } with { extension "prototype(fast)" };
-
-
/* dual-faced port on top of IPL4asp; ASP_Event passed through transparently */
type port GTPU_PT message {
out Gtp1uUnitdata;
diff --git a/library/GTPv1U_CodecPort_CtrlFunct.ttcn b/library/GTPv1U_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..3a86fc9f
--- /dev/null
+++ b/library/GTPv1U_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,13 @@
+module GTPv1U_CodecPort_CtrlFunct {
+
+ import from GTPv1U_CodecPort all;
+ import from IPL4asp_Types all;
+
+ external function f_GTPU_listen(
+ inout GTPU_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+}
diff --git a/library/GTPv1U_CodecPort_CtrlFunctDef.cc b/library/GTPv1U_CodecPort_CtrlFunctDef.cc
new file mode 100644
index 00000000..49f74ce3
--- /dev/null
+++ b/library/GTPv1U_CodecPort_CtrlFunctDef.cc
@@ -0,0 +1,17 @@
+#include "IPL4asp_PortType.hh"
+#include "IPL4asp_PT.hh"
+#include "GTPv1U_CodecPort.hh"
+
+namespace GTPv1U__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__GTPU__listen(
+ GTPv1U__CodecPort::GTPU__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+}
diff --git a/library/GTPv1U_Templates.ttcn b/library/GTPv1U_Templates.ttcn
new file mode 100644
index 00000000..a31e1d2d
--- /dev/null
+++ b/library/GTPv1U_Templates.ttcn
@@ -0,0 +1,167 @@
+/* GTPv1-U Templates in TTCN-3
+ * (C) 2018 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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_Templates {
+
+ import from General_Types all;
+ import from Osmocom_Types all;
+ import from GTPU_Types all;
+ import from GTPv1U_CodecPort all;
+
+ template (present) PDU_GTPU tr_GTP1U_PDU(template (present) OCT1 msg_type,
+ template (present) OCT4 teid,
+ template (present) GTPU_IEs ies := ?) := {
+ pn_bit := ?,
+ s_bit := ?,
+ e_bit := ?,
+ spare := ?,
+ /* Protocol Type flag (PT) shall be set to '1' in GTP */
+ pt := '1'B,
+ /* Version shall be set to decimal 1 ('001'). */
+ version := '001'B,
+ messageType := msg_type,
+ lengthf := ?,
+ teid := teid,
+ opt_part := *,
+ gtpu_IEs := ies
+ }
+
+ function f_GTPU_s_bit(template (omit) uint16_t seq) return BIT1 {
+ if (istemplatekind(seq, "omit")) {
+ return '0'B;
+ }
+ return '1'B;
+ }
+
+ function f_GTPU_opt_part(template (omit) uint16_t seq) return template (omit) GTPU_Header_optional_part {
+ if (istemplatekind(seq, "omit")) {
+ return omit;
+ }
+ var GTPU_Header_optional_part ret := {
+ sequenceNumber := int2oct(valueof(seq), 2),
+ npduNumber := '00'O,
+ nextExtHeader := '00'O,
+ gTPU_extensionHeader_List := omit
+ };
+ return ret;
+ }
+
+ /* generalized GTP-U send template */
+ template (value) PDU_GTPU ts_GTP1U_PDU(OCT1 msg_type, template (omit) uint16_t seq, OCT4 teid, GTPU_IEs ies) := {
+ /* N-PDU Number flag (PN): the GTP-U header contains a meaningful N-PDU Number field if the PN
+ * flag is set to 1. */
+ pn_bit := '0'B, /* we assume the encoder overwrites this if an optional part is given */
+ /* If the Sequence Number flag (S) is set to '1' the sequence number field is present and
+ * meaningful otherwise it is set to '0'. For GTP-U messages Echo Request, Echo Response,
+ * Error Indication and Supported Extension Headers Notification, the S flag shall be set to '1'.
+ *
+ * Note that the caller must ensure that these conditions hold.
+ * The caller can either pass a sequence number (we set s_bit to '1'B) when appropriate,
+ * or may omit the sequence number (we set s_bit to '0'B). */
+ s_bit := f_GTPU_s_bit(seq),
+ /* Extension header presence */
+ e_bit := '0'B,
+ spare := '0'B,
+ /* Protocol Type flag (PT) shall be set to '1' in GTP */
+ pt := '1'B,
+ /* Version shall be set to decimal 1 ('001'). */
+ version := '001'B,
+ messageType := msg_type,
+ lengthf := 0, /* we assume encoder overwrites this */
+ teid := teid,
+ opt_part := f_GTPU_opt_part(seq),
+ gtpu_IEs := ies
+ }
+
+ template (present) Gtp1uUnitdata tr_GTPU_MsgType(template (present) Gtp1uPeer peer,
+ template (present) OCT1 msg_type,
+ template (present) OCT4 teid) := {
+ peer := peer,
+ gtpu := tr_GTP1U_PDU(msg_type, teid)
+ }
+
+
+ /* template matching reception of GTP-U echo-request/response */
+ template (present) Gtp1uUnitdata tr_GTPU_PING(template (present) Gtp1uPeer peer) := tr_GTPU_MsgType(peer, '01'O, '00000000'O);
+ template (present) Gtp1uUnitdata tr_GTPU_PONG(template (present) Gtp1uPeer peer) := tr_GTPU_MsgType(peer, '02'O, '00000000'O);
+
+ /* template matching reception of GTP-U GPDU */
+ template GTPU_IEs t_GPDU(template (present) octetstring data) := {
+ g_PDU_IEs := {
+ data := data
+ }
+ }
+ template (present) Gtp1uUnitdata tr_GTPU_GPDU(template (present) Gtp1uPeer peer,
+ template (present) OCT4 teid,
+ template (present) octetstring data := ?) := {
+ peer := peer,
+ gtpu := tr_GTP1U_PDU('FF'O, teid, t_GPDU(data))
+ }
+
+ template (present) GTPU_IEs ts_UEchoReqPDU := {
+ echoRequest_IEs := {
+ private_extension_gtpu := omit
+ }
+ }
+
+ /* master template for sending a GTP-C echo request */
+ template (value) Gtp1uUnitdata ts_GTPU_PING(Gtp1uPeer peer, uint16_t seq) := {
+ peer := peer,
+ gtpu := ts_GTP1U_PDU('01'O, seq, '00000000'O, valueof(ts_UEchoReqPDU))
+ }
+
+ template GTPU_IEs ts_UEchoRespPDU(OCT1 restart_counter) := {
+ echoResponse_IEs := {
+ recovery_gtpu := {
+ type_gtpu := '00'O, /* we assume encoder fixes? */
+ restartCounter := restart_counter
+ },
+ private_extension_gtpu := omit
+ }
+ }
+
+ /* master template for sending a GTP-U echo response */
+ template (present) Gtp1uUnitdata ts_GTPU_PONG(Gtp1uPeer peer, uint16_t seq, OCT1 rest_ctr) := {
+ peer := peer,
+ gtpu := ts_GTP1U_PDU('02'O, seq, '00000000'O, valueof(ts_UEchoRespPDU(rest_ctr)))
+ }
+
+ template (value) GSNAddress_gtpu ts_UGsnAddr(octetstring ip_addr) := {
+ type_gtpu := '85'O,
+ lengthf := lengthof(ip_addr),
+ gSNAddressValue := ip_addr
+ }
+
+ template (value) TeidDataI_gtpu ts_UteidDataI(OCT4 teid) := {
+ type_gtpu := '10'O,
+ teidDataI := teid
+ }
+
+ template (value) GTPU_IEs ts_UErrorIndication(OCT4 teid, octetstring gsn_addr) := {
+ errorIndication_IEs := {
+ teidDataI_gtpu := ts_UteidDataI(teid),
+ gSNAddress_gtpu := ts_UGsnAddr(gsn_addr),
+ private_extension_gtpu := omit
+ }
+ }
+
+ /* master template for sending a GTP-U Error indication */
+ template (value) Gtp1uUnitdata ts_GTPU_ErrorIndication(Gtp1uPeer peer, uint16_t seq, OCT4 teid, octetstring gsn_addr) := {
+ peer := peer,
+ gtpu := ts_GTP1U_PDU('1A'O, seq, '00000000'O, valueof(ts_UErrorIndication(teid, gsn_addr)))
+ }
+
+ /* master template for sending a GTP-U user plane data */
+ template (value) Gtp1uUnitdata ts_GTP1U_GPDU(Gtp1uPeer peer, template (omit) uint16_t seq, OCT4 teid, octetstring data) := {
+ peer := peer,
+ gtpu := ts_GTP1U_PDU('FF'O, seq, teid, { g_PDU_IEs := { data := data }})
+ }
+}
diff --git a/library/GTPv2_CodecPort.ttcn b/library/GTPv2_CodecPort.ttcn
index e9cf57e8..0c4e9d3b 100644
--- a/library/GTPv2_CodecPort.ttcn
+++ b/library/GTPv2_CodecPort.ttcn
@@ -15,7 +15,7 @@ module GTPv2_CodecPort {
import from GTPv2_Types all;
/* identifies a remote peer (sender or receiver) */
- type record GtpPeer {
+ type record Gtp2cPeer {
ConnectionId connId,
HostName remName,
IPL4asp_Types.PortNumber remPort
@@ -23,7 +23,7 @@ module GTPv2_CodecPort {
/* Decoded GTP2C (Control Plane), used in send and receive direction */
type record Gtp2cUnitdata {
- GtpPeer peer,
+ Gtp2cPeer peer,
PDU_GTPCv2 gtpc
}
diff --git a/library/GTPv2_Emulation.ttcn b/library/GTPv2_Emulation.ttcn
index 80742694..f3f09f80 100644
--- a/library/GTPv2_Emulation.ttcn
+++ b/library/GTPv2_Emulation.ttcn
@@ -14,6 +14,9 @@ module GTPv2_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 GTPv2_Types all;
import from GTPv2_Templates all;
import from GTPv2_CodecPort all;
@@ -40,8 +43,8 @@ type record Gtp2EmulationCfg {
IPL4asp_Types.PortNumber gtpc_bind_port,
HostName gtpc_remote_ip,
IPL4asp_Types.PortNumber gtpc_remote_port,
- //HostName gtpu_bind_ip,
- //PortNumber gtpu_bind_port,
+ HostName gtpu_bind_ip optional,
+ IPL4asp_Types.PortNumber gtpu_bind_port optional,
boolean sgw_role,
boolean use_gtpu_daemon
};
@@ -49,6 +52,7 @@ type record Gtp2EmulationCfg {
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;
@@ -62,14 +66,16 @@ type component GTPv2_Emulation_CT {
var Gtp2EmulationCfg g_gtp2_cfg;
/* State */
- var GtpPeer g_peer;
- var integer g_gtp2c_id;
+ var Gtp2cPeer g_peer;
+ var integer g_gtp2c_id, g_gtp1u_id;
var OCT1 g_restart_ctr;
var uint16_t g_c_seq_nr;
var TidTableRec TidTable[256];
var SeqTableRec SeqTable[256];
var ImsiTableRec ImsiTable[256];
+ var UdMsgTableRec UdMsgTable[256];
var PidTableRec PidTable[256];
+
var integer g_uecups_conn_id;
};
@@ -91,6 +97,12 @@ type record ImsiTableRec {
GTP2_ConnHdlr vc_conn
};
+/* Unit data message type <-> ConnHdlr mapping */
+type record UdMsgTableRec {
+ OCT1 messageType,
+ GTP2_ConnHdlr vc_conn
+};
+
/* pid <-> ConnHdlr mapping (for UECUPS process termination indication) */
type record PidTableRec {
/* process ID of the running process */
@@ -99,6 +111,16 @@ type record PidTableRec {
GTP2_ConnHdlr vc_conn
};
+private function f_teid_known(OCT4 teid) 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) {
+ return true;
+ }
+ }
+ return false;
+}
+
private function f_comp_by_teid(OCT4 teid) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr {
var integer i;
for (i := 0; i < sizeof(TidTable); i := i+1) {
@@ -131,6 +153,16 @@ private function f_comp_by_seq(OCT3 seq) runs on GTPv2_Emulation_CT return GTP2_
mtc.stop;
}
+private function f_imsi_known(hexstring imsi) runs on GTPv2_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ImsiTable); i := i+1) {
+ if (isbound(ImsiTable[i].imsi) and ImsiTable[i].imsi == imsi) {
+ return true;
+ }
+ }
+ return false;
+}
+
private function f_comp_by_imsi(hexstring imsi) runs on GTPv2_Emulation_CT return GTP2_ConnHdlr {
var integer i;
for (i := 0; i < sizeof(ImsiTable); i := i+1) {
@@ -202,6 +234,18 @@ private function f_imsi_tbl_add(hexstring imsi, GTP2_ConnHdlr vc_conn) runs on G
testcase.stop("No Space in IMSI Table for ", imsi);
}
+private function f_udmsg_tbl_add(OCT1 messageType, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(UdMsgTable); i := i+1) {
+ if (not isbound(UdMsgTable[i].messageType)) {
+ UdMsgTable[i].messageType := messageType;
+ UdMsgTable[i].vc_conn := vc_conn;
+ return;
+ }
+ }
+ testcase.stop("No Space in UdMsg Table for messateType ", messageType);
+}
+
private function f_pid_tbl_add(integer pid, GTP2_ConnHdlr vc_conn) runs on GTPv2_Emulation_CT {
var integer i;
for (i := 0; i < sizeof(PidTable); i := i+1) {
@@ -320,6 +364,73 @@ function f_gtp2c_extract_imsi(PDU_GTPCv2 gtp) return template (omit) hexstring {
return omit;
}
+private function f_gtp2c_is_initial_msg(PDU_GTPCv2 msg) return boolean
+{
+ if (ischosen(msg.gtpcv2_pdu.echoRequest) or
+ ischosen(msg.gtpcv2_pdu.versionNotSupported) or
+ ischosen(msg.gtpcv2_pdu.createSessionRequest) or
+ ischosen(msg.gtpcv2_pdu.createBearerRequest) or
+ ischosen(msg.gtpcv2_pdu.bearerResourceCommand) or
+ ischosen(msg.gtpcv2_pdu.bearerResourceFailureIndication) or
+ ischosen(msg.gtpcv2_pdu.modifyBearerRequest) or
+ ischosen(msg.gtpcv2_pdu.deleteSessionRequest) or
+ ischosen(msg.gtpcv2_pdu.deleteBearerRequest) or
+ ischosen(msg.gtpcv2_pdu.downlinkDataNotification) or
+ ischosen(msg.gtpcv2_pdu.downlinkDataNotificationAcknowledgement) or
+ ischosen(msg.gtpcv2_pdu.downlinkDataNotificationFailureIndication) or
+ ischosen(msg.gtpcv2_pdu.deleteIndirectDataForwardingTunnelRequest) or
+ ischosen(msg.gtpcv2_pdu.modifyBearerCommand) or
+ ischosen(msg.gtpcv2_pdu.modifyBearerFailureIndication) or
+ ischosen(msg.gtpcv2_pdu.updateBearerRequest) or
+ ischosen(msg.gtpcv2_pdu.deleteBearerCommand) or
+ ischosen(msg.gtpcv2_pdu.createIndirectDataForwardingTunnelRequest) or
+ ischosen(msg.gtpcv2_pdu.releaseAccessBearersRequest) or
+ ischosen(msg.gtpcv2_pdu.stopPagingIndication) or
+ ischosen(msg.gtpcv2_pdu.modifyAccessBearersRequest) or
+ ischosen(msg.gtpcv2_pdu.remoteUEReportNotification) or
+ ischosen(msg.gtpcv2_pdu.remoteUEReportAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.forwardRelocationRequest) or
+ ischosen(msg.gtpcv2_pdu.forwardRelocationCompleteNotification) or
+ ischosen(msg.gtpcv2_pdu.forwardRelocationCompleteAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.contextRequest) or
+ ischosen(msg.gtpcv2_pdu.contextAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.identificationRequest) or
+ ischosen(msg.gtpcv2_pdu.forwardAccessContextNotification) or
+ ischosen(msg.gtpcv2_pdu.forwardAccessContextAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.detachNotification) or
+ ischosen(msg.gtpcv2_pdu.detachAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.changeNotificationRequest) or
+ ischosen(msg.gtpcv2_pdu.relocationCancelRequest) or
+ ischosen(msg.gtpcv2_pdu.configurationTransferTunnel) or
+ ischosen(msg.gtpcv2_pdu.rAN_InformationRelay) or
+ ischosen(msg.gtpcv2_pdu.suspendNotification) or
+ ischosen(msg.gtpcv2_pdu.suspendAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.resumeNotification) or
+ ischosen(msg.gtpcv2_pdu.resumeAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.cSPagingIndication) or
+ ischosen(msg.gtpcv2_pdu.createForwardingTunnelRequest) or
+ ischosen(msg.gtpcv2_pdu.deletePDN_ConnectionSetRequest) or
+ ischosen(msg.gtpcv2_pdu.traceSessionActivation) or
+ ischosen(msg.gtpcv2_pdu.traceSessionDeactivation) or
+ ischosen(msg.gtpcv2_pdu.updatePDN_ConnectionSetRequest) or
+ ischosen(msg.gtpcv2_pdu.pGW_RestartNotification) or
+ ischosen(msg.gtpcv2_pdu.pGW_RestartNotificationAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.pGW_DownlinkTriggeringNotification) or
+ ischosen(msg.gtpcv2_pdu.pGW_DownlinkTriggeringAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.alertMMENotification) or
+ ischosen(msg.gtpcv2_pdu.alertMMEAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.uEActivityNotification) or
+ ischosen(msg.gtpcv2_pdu.uEActivityAcknowledge) or
+ ischosen(msg.gtpcv2_pdu.mBMSSessionStartRequest) or
+ ischosen(msg.gtpcv2_pdu.mBMSSessionUpdateRequest) or
+ ischosen(msg.gtpcv2_pdu.mBMSSessionStopRequest) or
+ ischosen(msg.gtpcv2_pdu.iSR_StatusIndication) or
+ ischosen(msg.gtpcv2_pdu.uE_RegistrationQueryRequest)) {
+ return true;
+ }
+ return false;
+}
+
private template (value) SctpTuple ts_SCTP(template (omit) integer ppid := omit) := {
sinfo_stream := omit,
sinfo_ppid := ppid,
@@ -353,12 +464,13 @@ private template PortEvent tr_SctpPeerAddrChange := {
}
private function f_uecups_xceive(template (value) PDU_UECUPS tx,
- template PDU_UECUPS rx_t := ?)
+ template PDU_UECUPS rx_t := ?, float time_out := 10.0)
runs on GTPv2_Emulation_CT return PDU_UECUPS {
- timer T := 10.0;
+ 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; }
@@ -388,6 +500,8 @@ private function f_init(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
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_SCTP) });
@@ -395,10 +509,14 @@ private function f_init(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
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:=?});
+ 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 */
@@ -417,11 +535,28 @@ var GTP2_ConnHdlr vc_conn;
}
}
+private function SendToUdMsgTable(Gtp2cUnitdata g2c_ud) runs on GTPv2_Emulation_CT {
+ var GTP2_ConnHdlr vc_conn;
+
+ for (var integer i := 0; i < sizeof(UdMsgTable); i := i + 1) {
+ if (isbound(UdMsgTable[i].messageType)) {
+ if (UdMsgTable[i].messageType == g2c_ud.gtpc.messageType) {
+ vc_conn := UdMsgTable[i].vc_conn;
+ CLIENT.send(g2c_ud.gtpc) to vc_conn;
+ }
+ }
+ }
+
+ return;
+}
+
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;
@@ -435,28 +570,26 @@ function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
/* route inbound GTP2-C based on TEID, SEQ or IMSI */
[] GTP2C.receive(Gtp2cUnitdata:?) -> value g2c_ud {
var template hexstring imsi_t := f_gtp2c_extract_imsi(g2c_ud.gtpc);
- if (not ispresent(g2c_ud.gtpc.tEID) or g2c_ud.gtpc.tEID == int2oct(0, 4)) {
- /* if this is a response, route by SEQ */
- if (match(g2c_ud.gtpc, tr_PDU_GTP2C_msgtypes(gtp2_responses))
- and f_seq_known(g2c_ud.gtpc.sequenceNumber)) {
- vc_conn := f_comp_by_seq(g2c_ud.gtpc.sequenceNumber);
- CLIENT.send(g2c_ud.gtpc) to vc_conn;
- } else {
- TEID0.send(g2c_ud.gtpc);
- }
- } else if (ispresent(g2c_ud.gtpc.tEID) and g2c_ud.gtpc.tEID != int2oct(0, 4)) {
- vc_conn := f_comp_by_teid(g2c_ud.gtpc.tEID);
+ /* if this is a response, route by SEQ: */
+ if (match(g2c_ud.gtpc, tr_PDU_GTP2C_msgtypes(gtp2_responses))
+ and f_seq_known(g2c_ud.gtpc.sequenceNumber)) {
+ vc_conn := f_comp_by_seq(g2c_ud.gtpc.sequenceNumber);
CLIENT.send(g2c_ud.gtpc) to vc_conn;
- } else if (isvalue(imsi_t)) {
+ }else if (isvalue(imsi_t) and f_imsi_known(valueof(imsi_t))) {
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);
+ 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);
+ CLIENT.send(g2c_ud.gtpc) to vc_conn;
} else {
- /* Send to all clients */
- var integer i;
- for (i := 0; i < sizeof(TidTable); i := i+1) {
- if (isbound(TidTable[i].teid) and TidTable[i].teid == teid) {
- CLIENT.send(g2c_ud.gtpc) to TidTable[i].vc_conn;
- }
+ SendToUdMsgTable(g2c_ud);
+ if (not ispresent(g2c_ud.gtpc.tEID) or g2c_ud.gtpc.tEID == '00000000'O) {
+ TEID0.send(g2c_ud.gtpc);
}
}
@@ -466,12 +599,23 @@ function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
}
}
+ [] 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 {
- /* patch in the next sequence number */
- /* FIXME: do this only for outbound requests */
- g2c.sequenceNumber := int2oct(g_c_seq_nr, 3);
- g_c_seq_nr := g_c_seq_nr + 1;
+ /* 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);
+ g_c_seq_nr := g_c_seq_nr + 1;
+ }
/* build Gtp2cUnitdata */
g2c_ud := { peer := g_peer, gtpc := g2c };
GTP2C.send(g2c_ud);
@@ -479,12 +623,16 @@ function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
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 */
- /* FIXME: do this only for outbound requests */
- g2c.sequenceNumber := int2oct(g_c_seq_nr, 3);
- g_c_seq_nr := g_c_seq_nr + 1;
+ /* 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);
+ g_c_seq_nr := g_c_seq_nr + 1;
+ }
/* build Gtp2cUnitdata */
g2c_ud := { peer := g_peer, gtpc := g2c };
GTP2C.send(g2c_ud);
@@ -492,11 +640,18 @@ function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
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);
CLIENT_PROC.reply(GTP2EM_register_imsi:{imsi}) to vc_conn;
}
+ [] CLIENT_PROC.getcall(GTP2EM_register_udmsg:{?}) -> param(messageType) sender vc_conn {
+ f_udmsg_tbl_add(messageType, vc_conn);
+ 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);
@@ -533,10 +688,11 @@ function main(Gtp2EmulationCfg cfg) runs on GTPv2_Emulation_CT {
* Interaction between Main and Client Components
***********************************************************************/
type port GTP2EM_PT message {
- inout PDU_GTPCv2, UECUPS_ProgramTermInd;
+ inout PDU_GTPCv2, Gtp1uUnitdata, UECUPS_ProgramTermInd;
} 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);
@@ -544,7 +700,7 @@ signature GTP2EM_destroy_tunnel(UECUPS_DestroyTun gtd);
signature GTP2EM_start_program(UECUPS_StartProgram sprog) return UECUPS_StartProgramRes;
type port GTP2EM_PROC_PT procedure {
- inout GTP2EM_register_imsi, GTP2EM_register_teid, GTP2EM_allocate_teid,
+ inout GTP2EM_register_imsi, GTP2EM_register_udmsg, GTP2EM_register_teid, GTP2EM_allocate_teid,
GTP2EM_create_tunnel, GTP2EM_destroy_tunnel, GTP2EM_start_program;
} with { extension "internal" };
@@ -558,11 +714,21 @@ type component GTP2_ConnHdlr {
};
function f_gtp2_register_imsi(hexstring imsi) runs on GTP2_ConnHdlr {
+ /* 15-digit IMSIs are len(imsi)=15, but decoded messages are
+ * octet-aligned, hence the hexstring in messages is len(imsi)=16, where
+ * the last hex char is a padding 'F'H */
+ imsi := f_pad_bcd_number(imsi);
GTP2_PROC.call(GTP2EM_register_imsi:{imsi}) {
[] GTP2_PROC.getreply(GTP2EM_register_imsi:{imsi});
}
}
+function f_gtp2_register_udmsg(OCT1 messageType) runs on GTP2_ConnHdlr {
+ GTP2_PROC.call(GTP2EM_register_udmsg:{messageType}) {
+ [] GTP2_PROC.getreply(GTP2EM_register_udmsg:{messageType});
+ }
+}
+
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});
diff --git a/library/GTPv2_Templates.ttcn b/library/GTPv2_Templates.ttcn
index 3d690175..752e85cd 100644
--- a/library/GTPv2_Templates.ttcn
+++ b/library/GTPv2_Templates.ttcn
@@ -106,7 +106,7 @@ template (present) PDU_GTPCv2 tr_PDU_GTP2C_msgtypes(template (present) OCT1 type
version := '010'B,
messageType := types,
lengthf := ?,
- tEID := ?,
+ tEID := *,
sequenceNumber := ?,
spare3 := '00'O,
gtpcv2_pdu := ?,
@@ -126,7 +126,7 @@ template (present) IMSI tr_GTP2C_Imsi(template (present) hexstring imsi) := {
lengthIndicator := ?,
instance := ?,
spare := '0000'B,
- iMSI_Value := imsi
+ iMSI_Value := f_pad_bcd_number_tmpl(imsi)
}
template (present) MSISDN ts_GTP2C_msisdn(template (present) hexstring msisdn) := {
@@ -145,30 +145,39 @@ template (omit) MSISDN {
}
}
-
/* 8.4-1 */
-/*
type enumerated GTP2C_Cause {
Local_Detach (2),
Complete_Detach (3),
RAT_changed_from_3GPP_to_Non_3GPP (4),
ISR_deactivation (5),
- Error_Ind_from_RNC_eNB_SGSN_MME (5),
+ Error_Ind_from_RNC_eNB_SGSN_MME (6),
IMSI_Detach_Only (7),
Reactivation_Required (8),
-}
-*/
-
-const integer c_GTP2C_Cause_LocalDetach := 1;
+ PDN_reconnection_to_APN_disallowed (9),
+ Access_changed_from_Non_3GPP_to_3GPP (10),
+ PDN_connection_inactivity_timer_expires (11),
+ PGW_not_responding (12),
+ Network_Failure (13),
+ QoS_parameter_mismatch (14),
+ EPS_to_5GS_Mobility (15),
+ Request_accepted (16),
+ Request_accepted_partially (17),
+ New_PDN_type_due_to_network_preference (18),
+ New_PDN_type_due_to_single_address_bearer_only (19),
+ /* ... */
+ Context_Not_Found (64),
+ APN_access_denied__no_subscription (93)
+} with { variant "FIELDLENGTH(8)" encode "RAW" };
/* 8.4 */
-template (value) Cause ts_GTP2C_Cause(template (value) OCT1 cause,
+template (value) Cause ts_GTP2C_Cause(template (value) GTP2C_Cause cause,
template (value) BIT1 cs) := {
elementIdentifier := '02'O,
lengthIndicator := 0, /* overwritten */
instance := '0000'B,
spare := '0000'B,
- causeValue := cause,
+ causeValue := int2oct(enum2int(valueof(cause)), 1),
cS := cs,
bCE := '0'B,
pCE := '0'B,
@@ -178,12 +187,24 @@ template (value) Cause ts_GTP2C_Cause(template (value) OCT1 cause,
instanceOfOffendingIE := omit,
spare3 := omit
}
-template (present) Cause tr_GTP2C_Cause(template (present) OCT1 cause) := {
+private function enum2int_GTP2C_Cause_tmpl(template GTP2C_Cause inp) return template integer
+{
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return enum2int(valueof(inp));
+ }
+}
+template (present) Cause tr_GTP2C_Cause(template (present) GTP2C_Cause cause) := {
elementIdentifier := '02'O,
lengthIndicator := ?,
instance := ?,
spare := '0000'B,
- causeValue := cause,
+ causeValue := int2oct_tmpl(enum2int_GTP2C_Cause_tmpl(cause), 1),
cS := ?,
bCE := ?,
pCE := ?,
@@ -193,7 +214,7 @@ template (present) Cause tr_GTP2C_Cause(template (present) OCT1 cause) := {
instanceOfOffendingIE := *,
spare3 := *
}
-private function fs_GTP2C_Cause(template (omit) OCT1 cause, template (value) BIT1 cs) return
+private function fs_GTP2C_Cause(template (omit) GTP2C_Cause cause, template (value) BIT1 cs) return
template (omit) Cause {
if (istemplatekind(cause, "omit")) {
return omit;
@@ -201,7 +222,7 @@ template (omit) Cause {
return ts_GTP2C_Cause(cause, cs);
}
}
-private function fr_GTP2C_Cause(template OCT1 cause) return
+private function fr_GTP2C_Cause(template GTP2C_Cause cause) return
template Cause {
if (istemplatekind(cause, "omit")) {
return omit;
@@ -213,16 +234,16 @@ template Cause {
}
-/* 8.5 */
+/* 8.6 */
template (value) AccessPointName ts_GTP2C_APN(template (value) octetstring apn) := {
- elementIdentifier := '48'O,
+ elementIdentifier := '47'O,
lengthIndicator := 0, /* overwritten */
instance := '0000'B,
spare := '0000'B,
aPN_Value := apn
}
template (present) AccessPointName tr_GTP2C_APN(template (present) octetstring apn) := {
- elementIdentifier := '48'O,
+ elementIdentifier := '47'O,
lengthIndicator := ?,
instance := ?,
spare := '0000'B,
@@ -262,7 +283,73 @@ tr_GTP2C_EpsBearerId(template (present) uint4_t bid) := {
additionalOctets := *
}
+/* 8.12 */
+template (present) Indication
+tr_GTP2C_Indication(template (present) BIT1 oI := ?) := {
+ elementIdentifier := '4D'O,
+ lengthIndicator := ?,
+ instance := '0000'B,
+ spare := '0000'B,
+ sGWCI := ?,
+ iSRAI := ?,
+ iSRSI := ?,
+ oI := oI,
+ dFI := ?,
+ hI := ?,
+ dTF := ?,
+ dAF := ?,
+ mSV := ?,
+ sI := ?,
+ pT := ?,
+ pBit := ?,
+ cRSI := ?,
+ cFSI := ?,
+ uIMSI := ?,
+ sQCI := ?,
+ cCRSI := *,
+ iSRAU := *,
+ mBMDT := *,
+ s4AF := *,
+ s6AF := *,
+ sRNI := *,
+ pBIC := *,
+ retLoc := *,
+ cPSR := *,
+ cLII := *,
+ cSFBI := *,
+ pPSI := *,
+ pPON_PPEI := *,
+ pPOF := *,
+ aRRL := *,
+ cPRAI := *,
+ aOPI := *,
+ aOSI := *,
+ pCRI := *,
+ pSCI := *,
+ bDWI := *,
+ dTCI := *,
+ uASI := *,
+ nSI := *,
+ wPMSI := *,
+ uNACCSI := *,
+ pNSI := *,
+ s11TF := *,
+ pMTSMI := *,
+ cPOPCI := *,
+ ePCOSI := *,
+ rOAAI := *,
+ tSPCMI := *,
+ spare_1 := *,
+ spare_2 := *,
+ spare_3 := *,
+ spare_4 := *,
+ spare_5 := *,
+ spare_6 := *,
+ spare_7 := *,
+
+ additionalOctets := *
+}
/* 8.14 */
template (value) PDN_AddressAllocation
@@ -320,8 +407,22 @@ ts_GTP2C_BearerQos(template (value) OCT1 qci,
}
/* 8.17 */
+type enumerated GTP2C_RAT_Type {
+ GTP2C_RAT_reserved ('00'O),
+ GTP2C_RAT_UTRAN ('01'O),
+ GTP2C_RAT_GERAN ('02'O),
+ GTP2C_RAT_WLAN ('03'O),
+ GTP2C_RAT_GAN ('04'O),
+ GTP2C_RAT_HSPA_EVOLUTION ('05'O),
+ GTP2C_RAT_EUTRAN ('06'O),
+ GTP2C_RAT_Virtual ('07'O),
+ GTP2C_RAT_EUTRAN_NB_IoT ('08'O),
+ GTP2C_RAT_LTE_M ('09'O),
+ GTP2C_RAT_NR ('0A'O)
+} with { variant "FIELDLENGTH(8)" encode "RAW" };
+
template (value) RAT_Type ts_GTP2C_RatType(template (value) integer rat) := {
- elementIdentifier := '53'O,
+ elementIdentifier := '52'O,
lengthIndicator := 0, /* overwritten */
instance := '0000'B,
spare := '0000'B,
@@ -329,7 +430,7 @@ template (value) RAT_Type ts_GTP2C_RatType(template (value) integer rat) := {
additionalOctets := omit
}
template (present) RAT_Type tr_GTP2C_RatType(template (present) integer rat) := {
- elementIdentifier := '53'O,
+ elementIdentifier := '52'O,
lengthIndicator := ?,
instance := ?,
spare := '0000'B,
@@ -484,6 +585,25 @@ tr_GTP2C_FTEID(template (present) integer if_type, template (present) OCT4 teid,
}
/* 8.28 */
+template (value) BearerContextIEs
+ts_GTP2C_BcContextIE(template (value) uint4_t ebi,
+ template (omit) FullyQualifiedTEID_List teid_list := omit,
+ template (omit) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0),
+ template (omit) ChargingID charging_id := omit) := {
+ ePS_Bearer_ID := ts_GTP2C_EpsBearerId(ebi),
+ cause := ts_GTP2C_Cause(Request_accepted, '0'B),
+ ePS_Bearer_TFT := omit,
+ fullyQualifiedTEID := teid_list,
+ bearerLevel_QoS := qos,
+ chargingID := charging_id,
+ bearerFlags := omit,
+ transactionIdentifier := omit,
+ protocolConfigOptions := omit,
+ rAN_NASCause := omit,
+ additionalProtocolConfigOptions := omit,
+ extendedProtocolConfigOptions := omit
+}
+
template (value) BearerContextGrouped
ts_GTP2C_BcGrouped(template (value) BearerContextIEs ies) := {
elementIdentifier := '5D'O,
@@ -501,7 +621,16 @@ tr_GTP2C_BcGrouped(template (present) BearerContextIEs ies) := {
bearerContextIEs := ies
}
-
+/* 8.29 */
+template (value) ChargingID
+ts_GTP2C_ChargingID(template (value) OCT4 chargingID_Value) := {
+ elementIdentifier := '5D'O,
+ lengthIndicator := 0, /* overwritten */
+ instance := '0000'B,
+ spare := '0000'B,
+ chargingID_Value := chargingID_Value,
+ additionalOctets := omit
+}
/* 8.30 */
template (value) ChargingCharacteristics
@@ -556,6 +685,13 @@ ts_GTP2C_ProcTransId(template (value) integer pti) := {
pTI_Value := pti,
additionalOctets := omit
}
+private function f_ts_GTP2C_ProcTransId_omit(template (omit) integer pti)
+return template (omit) ProcedureTransactionID {
+ if (istemplatekind(pti, "omit")) {
+ return omit;
+ }
+ return ts_GTP2C_ProcTransId(pti);
+}
template (present) ProcedureTransactionID
tr_GTP2C_ProcTransId(template (present) integer pti) := {
elementIdentifier := '64'O,
@@ -610,8 +746,98 @@ tr_GTP2C_SelectionMode(template (present) integer mode) := {
additionalOctets := *
}
+/* 8.62 Fully qualified PDN Connection Set Identifier (FQ-CSID) */
+template (value) NodeID ts_GTP2C_FQCSID_NodeID_IPv4(template (value) OCT4 addr) := {
+ globalUnicastIPv4 := addr
+}
+template (value) FullyQualifiedPDN_ConnectionSetID
+ts_GTP2C_FQCSID(template (value) integer nRofCSIDs,
+ template (value) integer nodeIDType,
+ template (value) NodeID nodeID,
+ template (value) PDN_CSID_List pDN_CSID_List,
+ template (value) uint4_t instance := 0) := {
+ elementIdentifier := '84'O,
+ lengthIndicator := 0, /* overwritten */
+ instance := int2bit(valueof(instance), 4),
+ spare := '0000'B,
+ nRofCSIDs := nRofCSIDs,
+ nodeIDType := nodeIDType,
+ nodeID := nodeID,
+ pDN_CSID_List := pDN_CSID_List,
+ additionalOctets := omit
+}
+template (value) FullyQualifiedPDN_ConnectionSetID
+ts_GTP2C_FQCSID_IPv4(template (value) OCT4 addr,
+ template (value) OCT2 csid,
+ template (value) uint4_t instance := 0) :=
+ts_GTP2C_FQCSID(nRofCSIDs := 1,
+ nodeIDType := 0,
+ nodeID := ts_GTP2C_FQCSID_NodeID_IPv4(addr),
+ pDN_CSID_List := {csid},
+ instance := instance);
+
+/* 8.94 Additional Protocol Configuration Options (APCO) */
+template (present) ProtocolID_or_ContainerID
+tr_GTP2C_PCO_P(template (present) OCT2 protocolID_or_ContainerID := ?,
+ template (present) octetstring protID_orContID_Contents := ?) := {
+ protocolID_or_ContainerID := protocolID_or_ContainerID,
+ lengthIndicator := ?,
+ protID_orContID_Contents := protID_orContID_Contents
+}
+template (value) ProtocolID_or_ContainerID
+ts_GTP2C_PCO_P(template (value) OCT2 protocolID_or_ContainerID,
+ template (value) octetstring protID_orContID_Contents := ''O) := {
+ protocolID_or_ContainerID := protocolID_or_ContainerID,
+ lengthIndicator := 0,
+ protID_orContID_Contents := protID_orContID_Contents
+}
-
+template (present) ProtocolID_or_ContainerID tr_GTP2C_PCO_P_DNS_IPv4(template (present) octetstring dns4 := ?) :=
+ tr_GTP2C_PCO_P('000d'O, dns4);
+template (value) ProtocolID_or_ContainerID ts_GTP2C_PCO_P_DNS_IPv4(template (value) octetstring dns4 := ''O) :=
+ ts_GTP2C_PCO_P('000d'O, dns4);
+
+template (present) ProtocolID_or_ContainerID tr_GTP2C_PCO_P_DNS_IPv6(template (present) octetstring dns6 := ?) :=
+ tr_GTP2C_PCO_P('0003'O, dns6);
+template (value) ProtocolID_or_ContainerID ts_GTP2C_PCO_P_DNS_IPv6(template (value) octetstring dns6 := ''O) :=
+ ts_GTP2C_PCO_P('0003'O, dns6);
+
+template (present) ProtocolID_or_ContainerID tr_GTP2C_PCO_P_PCSCF_IPv4(template (present) octetstring pcscf4 := ?) :=
+ tr_GTP2C_PCO_P('000C'O, pcscf4);
+template (value) ProtocolID_or_ContainerID ts_GTP2C_PCO_P_PCSCF_IPv4(template (value) octetstring pcscf4 := ''O) :=
+ ts_GTP2C_PCO_P('000C'O, pcscf4);
+
+template (present) ProtocolID_or_ContainerID tr_GTP2C_PCO_P_PCSCF_IPv6(template (present) octetstring pcscf6 := ?) :=
+ tr_GTP2C_PCO_P('0001'O, pcscf6);
+template (value) ProtocolID_or_ContainerID ts_GTP2C_PCO_P_PCSCF_IPv6(template (value) octetstring pcscf6 := ''O) :=
+ ts_GTP2C_PCO_P('0001'O, pcscf6);
+
+template (value) APCO
+ts_GTP2C_APCO(template (value) BIT4 instance := '0000'B,
+ template (value) ProtocolIDs_and_ContainerIDs protocolIDs_and_ContainerIDs := {}) := {
+ elementIdentifier := 'A3'O,
+ lengthIndicator := 0,
+ instance := instance,
+ spare := '0000'B,
+ configProtocol := '000'B,
+ spare2 := '0000'B,
+ extensionField := '1'B,
+ protocolIDs_and_ContainerIDs := protocolIDs_and_ContainerIDs,
+ additionalOctets := omit
+}
+template (present) APCO
+tr_GTP2C_APCO(template (present) BIT4 instance := ?,
+ template ProtocolIDs_and_ContainerIDs protocolIDs_and_ContainerIDs := *) := {
+ elementIdentifier := 'A3'O,
+ lengthIndicator := ?,
+ instance := instance,
+ spare := ?,
+ configProtocol := '000'B,
+ spare2 := '0000'B,
+ extensionField := '1'B,
+ protocolIDs_and_ContainerIDs := protocolIDs_and_ContainerIDs,
+ additionalOctets := *
+}
template (value) PDU_GTPCv2 ts_PDU_GTP2C(template (omit) OCT4 teid, template (value) OCT3 seq,
template (value) OCT1 msg_type,
@@ -675,13 +901,15 @@ ts_GTP2C_CreateSessionReq(template (value) hexstring imsi, template (omit) hexst
template (value) octetstring apn, template (value) BIT3 pdn_type,
template (omit) FullyQualifiedTEID_List teid_list,
template (value) OCT2 chg_car, template (value) uint4_t bearer_id,
- template (value) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0)) :=
+ template (omit) UserLocationInfo uli := omit,
+ template (value) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0),
+ template (omit) APCO apco := omit) :=
ts_PDU_GTP2C('00000000'O, '000000'O, '20'O, {
createSessionRequest := {
iMSI := ts_GTP2C_Imsi(imsi),
mSISDN := fs_GTP2C_msisdn(msisdn),
mEI := omit,
- userLocationInfo := omit,
+ userLocationInfo := uli,
servingNetwork := omit,
rAT_Type := ts_GTP2C_RatType(rat_type),
indication := omit,
@@ -721,7 +949,7 @@ ts_PDU_GTP2C('00000000'O, '000000'O, '20'O, {
signallingPriorityIndication := omit,
iP_Addr := omit,
portNumber := omit,
- aPCO := omit,
+ aPCO := apco,
trustedWLANAccessNetworkIdentifier := omit,
cNOperatorSelectionEntity := omit,
presenceReportingAreaInformation := omit,
@@ -740,38 +968,40 @@ ts_PDU_GTP2C('00000000'O, '000000'O, '20'O, {
template (present) PDU_GTPCv2
-tr_GTP2C_CreateSessionReq(template (present) hexstring imsi) :=
+tr_GTP2C_CreateSessionReq(template (present) hexstring imsi := ?,
+ template (present) octetstring apn := ?,
+ template APCO apco := *) :=
tr_PDU_GTP2C('00000000'O, ?, {
createSessionRequest := {
iMSI := tr_GTP2C_Imsi(imsi),
mSISDN := *,
mEI := *,
- userLocationInfo := ?,
- servingNetwork := ?,
- rAT_Type := tr_GTP2C_RatType(6),
+ userLocationInfo := *,
+ servingNetwork := *,
+ rAT_Type := tr_GTP2C_RatType(?),
indication := *,
fullyQualifiedTEID := ?,
- accessPointName := tr_GTP2C_APN('012a'O), // '*'
+ accessPointName := tr_GTP2C_APN(apn), // '*'
selectionMode := ?,
- pDN_Type := ?,
+ pDN_Type := *,
pDN_AddressAllocation := ?,
- maxAPN_Restriction := ?,
+ maxAPN_Restriction := *,
ambr := *,
linkedEPS_Bearer_ID := omit,
trustedWLANModeIndication := omit,
protocolConfigOptions := omit,
bearerContextGrouped := ?,
traceInformation := *,
- recovery := omit,
+ recovery := *,
csid := omit,
- uE_TimeZone := ?,
+ uE_TimeZone := *,
user_CSG_Information := omit,
- chargingCharacteristics := ?,
+ chargingCharacteristics := *,
lDN := omit,
signallingPriorityIndication := *,
iP_Addr := omit,
portNumber := omit,
- aPCO := omit,
+ aPCO := apco,
trustedWLANAccessNetworkIdentifier := omit,
cNOperatorSelectionEntity := omit,
presenceReportingAreaInformation := omit,
@@ -789,11 +1019,16 @@ tr_PDU_GTP2C('00000000'O, ?, {
}});
template (value) PDU_GTPCv2
-ts_GTP2C_CreateSessionResp(template (value) FullyQualifiedTEID_List fteids,
- template (value) PDN_AddressAllocation addr) :=
-ts_PDU_GTP2C('00000000'O, '000000'O, '21'O, {
+ts_GTP2C_CreateSessionResp(template (value) OCT4 d_teid,
+ template (value) OCT3 seq,
+ template (value) GTP2C_Cause cause := Request_accepted,
+ template (omit) FullyQualifiedTEID_List fteids := omit,
+ template (omit) PDN_AddressAllocation addr := omit,
+ template (omit) BearerContextGrouped_List bearerContextGrouped := omit,
+ template (omit) APCO apco := omit) :=
+ts_PDU_GTP2C(d_teid, seq, '21'O, {
createSessionResponse := {
- cause := ts_GTP2C_Cause(int2oct(16, 1), '0'B),
+ cause := ts_GTP2C_Cause(cause, '0'B),
changeReportingAction := omit,
cSG_InformationReportingAction := omit,
heNBInformationReporting := omit,
@@ -803,14 +1038,14 @@ ts_PDU_GTP2C('00000000'O, '000000'O, '21'O, {
ambr := omit,
linkedEPS_Bearer_ID := omit,
protocolConfigOptions := omit,
- bearerContextGrouped := omit,
+ bearerContextGrouped := bearerContextGrouped,
recovery := omit,
chargingGatewayName := omit,
chargingGatewayAddress := omit,
csid := omit,
lDN := omit,
pGW_Back_OffTime := omit,
- aPCO := omit,
+ aPCO := apco,
trustedWLANIPv4Parameters := omit,
indicationFlags := omit,
presenceReportingAreaAction := omit,
@@ -824,10 +1059,12 @@ ts_PDU_GTP2C('00000000'O, '000000'O, '21'O, {
template (present) PDU_GTPCv2
tr_GTP2C_CreateSessionResp(template (present) OCT4 d_teid := ?,
template (present) OCT3 seq := ?,
- template (present) OCT1 cause := ?,
+ template (present) GTP2C_Cause cause := ?,
template FullyQualifiedTEID_List fteids := *,
template PDN_AddressAllocation addr := *,
- template BearerContextGrouped_List bctxg := *) :=
+ template APN_Restriction apn_restriction := *,
+ template BearerContextGrouped_List bctxg := *,
+ template APCO exp_apco := *) :=
tr_PDU_GTP2C(d_teid, seq, {
createSessionResponse := {
cause := tr_GTP2C_Cause(cause),
@@ -836,7 +1073,7 @@ tr_PDU_GTP2C(d_teid, seq, {
heNBInformationReporting := *,
fullyQualifiedTEID := fteids,
pDN_AddressAllocation := addr,
- aPN_Restriction := ?,
+ aPN_Restriction := apn_restriction,
ambr := *,
linkedEPS_Bearer_ID := *,
protocolConfigOptions := *,
@@ -847,7 +1084,7 @@ tr_PDU_GTP2C(d_teid, seq, {
csid := *,
lDN := *,
pGW_Back_OffTime := *,
- aPCO := *,
+ aPCO := exp_apco,
trustedWLANIPv4Parameters := *,
indicationFlags := *,
presenceReportingAreaAction := *,
@@ -862,7 +1099,7 @@ tr_PDU_GTP2C(d_teid, seq, {
template (value) PDU_GTPCv2
ts_GTP2C_DeleteSessionReq(template (value) OCT4 d_teid,
- template (omit) OCT1 cause := omit,
+ template (omit) GTP2C_Cause cause := omit,
template (value) FullyQualifiedTEID sender_fteid,
template (omit) FullyQualifiedTEID_List teid_list := omit,
template (value) uint4_t bearer_id) :=
@@ -887,18 +1124,18 @@ ts_PDU_GTP2C(d_teid, '000000'O, '24'O, {
privateExtension := omit
}});
template (present) PDU_GTPCv2
-tr_GTP2C_DeleteSessionReq(template (present) OCT4 d_teid,
+tr_GTP2C_DeleteSessionReq(template (present) OCT4 d_teid := ?,
template (present) OCT3 seq := ?,
- template (omit) OCT1 cause,
- template (present) FullyQualifiedTEID sender_fteid,
- template FullyQualifiedTEID_List teid_list,
- template (present) uint4_t bearer_id) :=
+ template GTP2C_Cause cause := *,
+ template (present) uint4_t bearer_id := ?,
+ template Indication indicationFlags := *,
+ template FullyQualifiedTEID sender_fteid := *) :=
tr_PDU_GTP2C(d_teid, seq, {
deleteSessionRequest := {
cause := fr_GTP2C_Cause(cause),
linkedEPS_Bearer_ID := tr_GTP2C_EpsBearerId(bearer_id),
uLI := *,
- indicationFlags := *,
+ indicationFlags := indicationFlags,
protocolConfigOptions := *,
originatingNode := *,
fullyQualifiedTEID := sender_fteid,
@@ -918,8 +1155,8 @@ tr_PDU_GTP2C(d_teid, seq, {
template (value) PDU_GTPCv2
ts_GTP2C_DeleteSessionResp(template (value) OCT4 d_teid,
template (value) OCT3 seq,
- template (value) OCT1 cause) :=
-ts_PDU_GTP2C(d_teid, '000000'O, '25'O, {
+ template (value) GTP2C_Cause cause) :=
+ts_PDU_GTP2C(d_teid, seq, '25'O, {
deleteSessionResponse := {
cause := ts_GTP2C_Cause(cause, '0'B),
recovery := omit,
@@ -934,7 +1171,7 @@ ts_PDU_GTP2C(d_teid, '000000'O, '25'O, {
template (present) PDU_GTPCv2
tr_GTP2C_DeleteSessionResp(template (present) OCT4 d_teid,
template (present) OCT3 seq := ?,
- template (present) OCT1 cause := ?
+ template (present) GTP2C_Cause cause := ?
) :=
tr_PDU_GTP2C(d_teid, seq, {
deleteSessionResponse := {
@@ -950,33 +1187,19 @@ tr_PDU_GTP2C(d_teid, seq, {
template (value) PDU_GTPCv2
ts_GTP2C_CreateBearerReq(template (value) OCT4 d_teid,
- template (value) integer proc_trans_id,
+ template (omit) integer proc_trans_id,
template (value) uint4_t linked_id,
template (value) uint4_t bearer_id,
- template (omit) FullyQualifiedTEID_List teid_list,
+ template (value) BearerContextGrouped_List bearer_ctx_list,
+ template (omit) FullyQualifiedPDN_ConnectionSetID_List csid := omit,
template (value) Bearer_QoS qos := ts_GTP2C_BearerQos('09'O, 0,0,0,0)) :=
ts_PDU_GTP2C(d_teid, '000000'O, '5F'O, {
createBearerRequest := {
- procedureTransactionID := ts_GTP2C_ProcTransId(proc_trans_id),
+ procedureTransactionID := f_ts_GTP2C_ProcTransId_omit(proc_trans_id),
linkedEPS_BearerID := ts_GTP2C_EpsBearerId(linked_id),
protocolConfigOptions := omit,
- bearerContextGrouped := {
- ts_GTP2C_BcGrouped({
- ePS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
- cause := omit,
- ePS_Bearer_TFT := omit,
- fullyQualifiedTEID := teid_list,
- bearerLevel_QoS := qos,
- chargingID := omit,
- bearerFlags := omit,
- transactionIdentifier := omit,
- protocolConfigOptions := omit,
- rAN_NASCause := omit,
- additionalProtocolConfigOptions := omit,
- extendedProtocolConfigOptions := omit
- })
- },
- csid := omit,
+ bearerContextGrouped := bearer_ctx_list,
+ csid := csid,
changeReportingAction := omit,
cSG_InformationReportingAction := omit,
heNBInformationReporting := omit,
@@ -987,13 +1210,96 @@ ts_PDU_GTP2C(d_teid, '000000'O, '5F'O, {
nBIFOMContainer := omit,
privateExtension := omit
}});
+template (present) PDU_GTPCv2
+tr_GTP2C_CreateBearerResp(template (present) OCT4 d_teid,
+ template (present) OCT3 seq := ?,
+ template (present) GTP2C_Cause cause := ?
+ ) :=
+tr_PDU_GTP2C(d_teid, seq, {
+ createBearerResponse := {
+ cause := tr_GTP2C_Cause(cause),
+ bearerContextGrouped := *,
+ recovery := *,
+ csid := *,
+ protocolConfigOptions := *,
+ uE_TimeZone := *,
+ uLI := *,
+ trustedWLANAccessNetworkIdentifier := *,
+ overloadControlInformationGrouped := *,
+ presenceReportingAreaInformation := *,
+ iP_Addr := *,
+ wLANLocationTimestamp := *,
+ portNumber := *,
+ nBIFOMContainer := *,
+ extendedProtocolConfigOptions := *,
+ privateExtension:= *
+ }});
+template (present) PDU_GTPCv2
+tr_GTP2C_ModifyBearerReq(template (present) OCT4 d_teid := ?,
+ template (present) OCT3 seq := ?) :=
+tr_PDU_GTP2C(d_teid, seq, {
+ modifyBearerRequest := {
+ mEI := *,
+ userLocationInfo := *,
+ servingNetwork := *,
+ rAT_Type := *,
+ indicationFlags := *,
+ fullyQualifiedTEID := *,
+ ambr := *,
+ delayDownlinkPacketNotificationReq := *,
+ bearerContextGrouped := *,
+ recovery := *,
+ uE_TimeZone := *,
+ csid := *,
+ user_CSG_Information := *,
+ iP_Addr := *,
+ portNumber := *,
+ lDN := *,
+ //maxMBR_APN_AMBR := *,
+ cNOperatorSelectionEntity := *,
+ presenceReportingAreaInformation := *,
+ overloadControlInformationGrouped := *,
+ servingPLMNRateControl := *,
+ counter := *,
+ privateExtension := *
+ }});
+
+template (value) PDU_GTPCv2
+ts_GTP2C_ModifyBearerResp(template (value) OCT4 d_teid,
+ template (value) OCT3 seq,
+ template (value) GTP2C_Cause cause,
+ template (value) uint4_t bearer_id,
+ template (omit) BearerContextGrouped_List bearerContextGrouped := omit) :=
+ts_PDU_GTP2C(d_teid, seq, '23'O, {
+ modifyBearerResponse := {
+ cause := ts_GTP2C_Cause(cause, '0'B),
+ mSISDN := omit,
+ linkedEPS_Bearer_ID := ts_GTP2C_EpsBearerId(bearer_id),
+ aPN_Restriction := omit,
+ protocolConfigOptions := omit,
+ bearerContextGrouped := bearerContextGrouped,
+ changeReportingAction := omit,
+ cSG_InformationReportingAction := omit,
+ heNBInformationReporting := omit,
+ chargingGatewayName := omit,
+ chargingGatewayAddress := omit,
+ csid := omit,
+ recovery := omit,
+ lDN := omit,
+ indicationFlags := omit,
+ presenceReportingAreaAction := omit,
+ loadControlInformationGrouped := omit,
+ overloadControlInformationGrouped := omit,
+ pDNConnectionChargingID := omit,
+ privateExtension := omit
+ }});
template (value) PDU_GTPCv2
ts_GTP2C_DeleteBearerReq(template (value) OCT4 d_teid,
template (value) integer proc_trans_id,
template (value) uint4_t bearer_id,
- template (value) OCT1 cause) :=
+ template (value) GTP2C_Cause cause) :=
ts_PDU_GTP2C(d_teid, '000000'O, '63'O, {
deleteBearerRequest := {
epsBearerIdentity := { ts_GTP2C_EpsBearerId(bearer_id) },
@@ -1014,7 +1320,7 @@ ts_PDU_GTP2C(d_teid, '000000'O, '63'O, {
template (present) PDU_GTPCv2
tr_GTP2C_DeleteBearerResp(template (present) OCT4 d_teid,
template (present) OCT3 seq := ?,
- template (present) OCT1 cause := ?) :=
+ template (present) GTP2C_Cause cause := ?) :=
tr_PDU_GTP2C(d_teid, seq, {
deleteBearerResponse := {
cause := tr_GTP2C_Cause(cause),
@@ -1035,6 +1341,25 @@ tr_PDU_GTP2C(d_teid, seq, {
privateExtension := *
}});
+/* 8.18 */
+template (value) ServingNetwork
+ts_GTP2C_ServingNetwork(template (value) hexstring mcc,
+ template (value) hexstring mnc,
+ template (value) BIT4 instance := '0000'B) :=
+{
+ elementIdentifier := '53'O,
+ lengthIndicator := 0, /* overwritten */
+ instance := instance,
+ spare := '0000'B,
+ mccDigit1 := mcc[0],
+ mccDigit2 := mcc[1],
+ mccDigit3 := mcc[2],
+ mncDigit3 := mnc[2], /* 'F'H for 2 digit MNC */
+ mncDigit1 := mnc[0],
+ mncDigit2 := mnc[1],
+ additionalOctets := omit
+}
+
}
diff --git a/library/General_Types.ttcn b/library/General_Types.ttcn
index 40f07709..c8183130 100644
--- a/library/General_Types.ttcn
+++ b/library/General_Types.ttcn
@@ -175,6 +175,8 @@ group SimpleNativeTypes {
type hexstring HEX1_20n length(1..20) with { variant "" };
type hexstring HEX1_34n length(1..34) with { variant "" };
+ type record of hexstring Hexstrings with { variant "" };
+
//****************************************************
// Integers
//****************************************************
@@ -194,6 +196,12 @@ group SimpleNativeTypes {
type integer INT13nbp (0..8191) with { variant "" };
type integer INT15nbp (0..32767) with { variant "" };
+ //****************************************************
+ // Booleans
+ //****************************************************
+
+ type record of boolean Booleans with { variant "" };
+
} // end group NativeTypes
//****************************************************
@@ -278,6 +286,7 @@ group SimpleRAWEncodedTypes {
type integer LIN2_BO_LAST (0..65535) with { variant "FIELDLENGTH(16), COMP(nosign), BYTEORDER(last)" };
type integer LIN3_BO_LAST (0..16777215) with { variant "FIELDLENGTH(24), COMP(nosign), BYTEORDER(last)" };
type integer LIN4_BO_LAST (0..4294967295) with { variant "FIELDLENGTH(32), COMP(nosign), BYTEORDER(last)" };
+ type integer LIN8_BO_LAST (0..18446744073709551616) with { variant "FIELDLENGTH(64), COMP(nosign), BYTEORDER(last)" };
//integer with fixed bit number
type integer INT1b (0..1) with { variant "FIELDLENGTH(1)" };
@@ -328,4 +337,3 @@ group CompositeTypes {
} // end group CompositeTypes
} with { encode "RAW" } /* End of module General_Types */
-
diff --git a/library/HNBLLIF_CodecPort.ttcn b/library/HNBLLIF_CodecPort.ttcn
new file mode 100644
index 00000000..00f53fcc
--- /dev/null
+++ b/library/HNBLLIF_CodecPort.ttcn
@@ -0,0 +1,95 @@
+/* OsmoHNodeB Lower Layer Socket Interface codec port in TTCN-3
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 HNBLLIF_CodecPort {
+
+import from Osmocom_Types all;
+import from HNBLLIF_Types all;
+import from UD_PortType all;
+import from UD_Types all;
+
+type record HNBLLIF_send_data {
+ HNBLLIF_Message data,
+ integer id
+};
+
+private function HNBLLIF_to_UD(in HNBLLIF_send_data pin, out UD_send_data pout) {
+ pout.id := pin.id;
+ pout.data := enc_HNBLLIF_Message(pin.data);
+} with { extension "prototype(fast)" };
+
+private function UD_to_HNBLLIF(in UD_send_data pin, out HNBLLIF_send_data pout) {
+ pout.id := pin.id;
+ pout.data := dec_HNBLLIF_Message(pin.data);
+} with { extension "prototype(fast)" };
+
+type port HNBLLIF_CODEC_PT message {
+ out UD_close, UD_listen, UD_shutdown, UD_connect, HNBLLIF_send_data;
+ in UD_listen_result, UD_connect_result, UD_connected, HNBLLIF_send_data;
+} with { extension "user UD_PT
+ out (
+ UD_close -> UD_close:simple;
+ UD_listen -> UD_listen:simple;
+ UD_shutdown -> UD_shutdown:simple;
+ UD_connect -> UD_connect:simple;
+ HNBLLIF_send_data -> UD_send_data: function(HNBLLIF_to_UD)
+ )
+ in (
+ UD_listen_result -> UD_listen_result:simple;
+ UD_connect_result -> UD_connect_result:simple;
+ UD_send_data -> HNBLLIF_send_data: function(UD_to_HNBLLIF);
+ UD_connected -> UD_connected:simple
+ )"
+};
+
+template HNBLLIF_send_data t_SD_HNBLLIF(integer id, template HNBLLIF_Message pdu) := {
+ data := pdu,
+ id := id
+}
+template (value) HNBLLIF_send_data ts_SD_HNBLLIF(integer id, template (value) HNBLLIF_Message pdu) := {
+ data := pdu,
+ id := id
+}
+
+function f_hnbllif_connect(HNBLLIF_CODEC_PT pt, charstring sock) return integer {
+ var UD_connect_result res;
+ timer T := 5.0;
+
+ T.start;
+ pt.send(UD_connect:{sock, -1});
+ alt {
+ [] pt.receive(UD_connect_result:?) -> value res {
+ if (ispresent(res.result) and ispresent(res.result.result_code) and
+ res.result.result_code == ERROR) {
+ if (ispresent(res.result.err)) {
+ setverdict(fail, "Error connecting to HNBLL socket ", sock, ": ", res.result.err);
+ } else {
+ setverdict(fail, "Error connecting to HNBLL socket ", sock);
+ }
+ mtc.stop;
+ } else {
+ return res.id;
+ }
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout connecting to HNBLL socket ", sock);
+ mtc.stop;
+ }
+ }
+ return -23;
+}
+
+function f_hnbllif_close(HNBLLIF_CODEC_PT pt, integer id)
+{
+ pt.send(UD_close:{id := id});
+}
+
+}
diff --git a/library/HNBLLIF_Templates.ttcn b/library/HNBLLIF_Templates.ttcn
new file mode 100644
index 00000000..f56bfc90
--- /dev/null
+++ b/library/HNBLLIF_Templates.ttcn
@@ -0,0 +1,561 @@
+/* Osmocom HNBLL Interface Templates, as per osmo-hnodeb/include/osmocom/hnodeb/hnb_prim.h
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 HNBLLIF_Templates {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from HNBLLIF_Types all;
+
+/**********************
+ * CTL SAPI
+ **********************/
+template (value) HNBLLIF_Message ts_HNBLLIF_CTL_HELLO_REQ(template (value) HNBLLIF_Sapi sapi,
+ template (value) uint16_t api_version) := {
+ sapi := HNBLL_IF_SAPI_CTL,
+ u := {
+ ctl := {
+ prim := HNBLL_IF_CTL_MSG_HELLO,
+ u := {
+ hello := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ sapi := sapi,
+ api_version := api_version
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_CTL_HELLO_CNF(template (present) HNBLLIF_Sapi sapi := ?,
+ template (present) uint32_t api_version := ?) := {
+ sapi := HNBLL_IF_SAPI_CTL,
+ u := {
+ ctl := {
+ prim := HNBLL_IF_CTL_MSG_HELLO,
+ u := {
+ hello := {
+ op := HNBLL_IF_OP_CONFIRM,
+ u := {
+ cnf := {
+ sapi := sapi,
+ api_version := api_version
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**********************
+ * IUH SAPI
+ **********************/
+
+template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONFIGURE_IND(template (present) uint16_t mcc := ?,
+ template (present) uint16_t mnc := ?,
+ template (present) uint16_t cell_identity := ?,
+ template (present) uint16_t lac := ?,
+ template (present) uint8_t rac := ?,
+ template (present) uint16_t sac := ?,
+ template (present) uint16_t rnc_id := ?) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONFIGURE,
+ u := {
+ configure := {
+ op := HNBLL_IF_OP_INDICATION,
+ u := {
+ ind := {
+ mcc := mcc,
+ mnc := mnc,
+ cell_identity := cell_identity,
+ lac := lac,
+ rac := rac,
+ reserved := ?,
+ sac := sac,
+ rnc_id := rnc_id
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
+ template (value) uint8_t domain,
+ template (value) uint8_t est_cause,
+ template (value) octetstring data) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ context_id := context_id,
+ domain := domain,
+ est_cause := est_cause,
+ reserved := 0,
+ data_len := lengthof(data),
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
+ template (present) uint8_t domain := ?,
+ template (present) uint8_t est_cause := ?) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_CONFIRM,
+ u := {
+ cnf := {
+ context_id := context_id,
+ domain := domain,
+ est_cause := est_cause
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_RELEASE_REQ(template (value) uint32_t context_id,
+ template (value) uint8_t domain,
+ template (value) uint8_t cause_type,
+ template (value) uint8_t cause,
+ template (value) octetstring data) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONN_RELEASE,
+ u := {
+ conn_release := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ context_id := context_id,
+ domain := domain,
+ spare1 := 0,
+ cause_type := cause_type,
+ cause := cause,
+ data_len := lengthof(data),
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_DATA_IND(template (present) uint32_t context_id := ?,
+ template (present) uint8_t domain := ?,
+ template (present) octetstring data := ?) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_INDICATION,
+ u := {
+ ind := {
+ context_id := context_id,
+ domain := domain,
+ spare1 := ?,
+ spare2 := ?,
+ data_len := ?,
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_DATA_REQ(template (value) uint32_t context_id,
+ template (value) uint8_t domain,
+ template (value) octetstring data) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ context_id := context_id,
+ domain := domain,
+ spare1 := 0,
+ spare2 := 0,
+ data_len := lengthof(data),
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_IUH_UNITDATA_IND(template (present) octetstring data := ?) := {
+ sapi := HNBLL_IF_SAPI_IUH,
+ u := {
+ iuh := {
+ prim := HNBLL_IF_IUH_MSG_UNITDATA,
+ u := {
+ unitdata := {
+ op := HNBLL_IF_OP_INDICATION,
+ u := {
+ ind := {
+ data_len := ?,
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/**********************
+ * AUDIO SAPI
+ **********************/
+const HNBLLIF_AUDIO_IPTIs IPTIs_default := {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+private function f_subflow_sizes_default() return HNBLLIF_AUDIO_SubflowSizes
+{
+ var HNBLLIF_AUDIO_SubflowSizes ss;
+
+ for (var integer i := 0; i < HNBLLIF_MAX_RFCIS; i := i + 1) {
+ for (var integer j := 0; j < HNBLLIF_MAX_SUBFLOWS; j := j + 1) {
+ ss[i][j] := 0;
+ }
+ }
+
+ ss[0][0] := 81; ss[0][1] := 103; ss[0][2] := 60;
+ ss[1][0] := 39; ss[1][1] := 0; ss[1][2] := 0;
+ ss[2][0] := 0; ss[2][1] := 0; ss[2][2] := 0;
+
+ return ss;
+}
+
+private function f_rfcis_default() return HNBLLIF_AUDIO_RFCIs
+{
+ var HNBLLIF_AUDIO_RFCIs rfcis;
+
+ for (var integer i := 0; i < HNBLLIF_MAX_RFCIS; i := i + 1) {
+ rfcis[i] := i;
+ }
+
+ return rfcis;
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
+ template (value) uint16_t remote_rtp_port,
+ template (value) HNBLLIF_AddrType remote_rtp_address_type,
+ template (value) HNBLLIF_Addr remote_addr,
+ template (value) uint8_t transparent := 0,
+ template (value) uint8_t data_pdu_type := 0,
+ template (value) uint16_t supported_versions_mask := 3,
+ template (value) uint8_t num_rfci := 3,
+ template (value) uint8_t num_subflows := 3,
+ template (value) HNBLLIF_AUDIO_SubflowSizes subflow_sizes := f_subflow_sizes_default(),
+ template (value) uint8_t IPTIs_present := 0,
+ template (value) HNBLLIF_AUDIO_IPTIs IPTIs := IPTIs_default,
+ template (omit) HNBLLIF_AUDIO_RFCIs rfci := f_rfcis_default()) := {
+ sapi := HNBLL_IF_SAPI_AUDIO,
+ u := {
+ audio := {
+ prim := HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ context_id := context_id,
+ remote_rtp_port := remote_rtp_port,
+ reserved := 0,
+ remote_rtp_address_type := remote_rtp_address_type,
+ remote_addr := remote_addr,
+ transparent := transparent,
+ data_pdu_type := data_pdu_type,
+ supported_versions_mask := supported_versions_mask,
+ num_rfci := num_rfci,
+ num_subflows := num_subflows,
+ subflow_sizes := subflow_sizes,
+ IPTIs_present := IPTIs_present,
+ IPTIs := IPTIs,
+ rfci := rfci
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_AUDIO_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
+ template (present) uint32_t audio_conn_id := ?,
+ template (present) uint8_t error_code := ?,
+ template (present) uint16_t local_rtp_port:= ?,
+ template (present) HNBLLIF_AddrType local_rtp_address_type := ?,
+ template (present) HNBLLIF_Addr local_addr := ?) := {
+ sapi := HNBLL_IF_SAPI_AUDIO,
+ u := {
+ audio := {
+ prim := HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_CONFIRM,
+ u := {
+ cnf := {
+ context_id := context_id,
+ audio_conn_id := audio_conn_id,
+ local_rtp_port := local_rtp_port,
+ error_code := error_code,
+ local_rtp_address_type := local_rtp_address_type,
+ local_addr := local_addr
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_RELEASE_REQ(template (value) uint32_t audio_conn_id) := {
+ sapi := HNBLL_IF_SAPI_AUDIO,
+ u := {
+ audio := {
+ prim := HNBLL_IF_AUDIO_MSG_CONN_RELEASE,
+ u := {
+ conn_release := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ audio_conn_id := audio_conn_id
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_AUDIO_CONN_DATA_IND(template (present) uint32_t audio_conn_id := ?,
+ template (present) uint8_t frame_nr := ?,
+ template (present) uint8_t fqc := ?,
+ template (present) uint8_t rfci := ?,
+ template (present) octetstring data := ?) := {
+ sapi := HNBLL_IF_SAPI_AUDIO,
+ u := {
+ audio := {
+ prim := HNBLL_IF_AUDIO_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_INDICATION,
+ u := {
+ ind := {
+ audio_conn_id := audio_conn_id,
+ frame_nr := frame_nr,
+ fqc := fqc,
+ rfci := rfci,
+ spare := 0,
+ data_len := ?,
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_AUDIO_CONN_DATA_REQ(template (value) uint32_t audio_conn_id,
+ template (value) uint8_t frame_nr,
+ template (value) uint8_t fqc,
+ template (value) uint8_t rfci,
+ template (value) octetstring data) := {
+ sapi := HNBLL_IF_SAPI_AUDIO,
+ u := {
+ audio := {
+ prim := HNBLL_IF_AUDIO_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ audio_conn_id := audio_conn_id,
+ frame_nr := frame_nr,
+ fqc := fqc,
+ rfci := rfci,
+ spare := 0,
+ data_len := lengthof(data),
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**********************
+ * GTP SAPI
+ **********************/
+template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_ESTABLISH_REQ(template (value) uint32_t context_id,
+ template (value) uint32_t remote_tei,
+ template (value) HNBLLIF_AddrType remote_gtpu_address_type,
+ template (value) HNBLLIF_Addr remote_gtpu_addr) := {
+ sapi := HNBLL_IF_SAPI_GTP,
+ u := {
+ gtp := {
+ prim := HNBLL_IF_GTP_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ context_id := context_id,
+ remote_tei := remote_tei,
+ reserved := 0,
+ remote_gtpu_address_type := remote_gtpu_address_type,
+ remote_gtpu_addr := remote_gtpu_addr
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_GTP_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?,
+ template (present) uint32_t gtp_conn_id := ?,
+ template (present) uint32_t local_tei := ?,
+ template (present) uint8_t error_code := ?,
+ template (present) HNBLLIF_AddrType local_gtpu_address_type := ?,
+ template (present) HNBLLIF_Addr local_gtpu_addr := ?) := {
+ sapi := HNBLL_IF_SAPI_GTP,
+ u := {
+ gtp := {
+ prim := HNBLL_IF_GTP_MSG_CONN_ESTABLISH,
+ u := {
+ conn_establish := {
+ op := HNBLL_IF_OP_CONFIRM,
+ u := {
+ cnf := {
+ context_id := context_id,
+ gtp_conn_id := gtp_conn_id,
+ local_tei := local_tei,
+ error_code := error_code,
+ local_gtpu_address_type := local_gtpu_address_type,
+ local_gtpu_addr := local_gtpu_addr
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_RELEASE_REQ(template (value) uint32_t gtp_conn_id) := {
+ sapi := HNBLL_IF_SAPI_GTP,
+ u := {
+ gtp := {
+ prim := HNBLL_IF_GTP_MSG_CONN_RELEASE,
+ u := {
+ conn_release := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ gtp_conn_id := gtp_conn_id
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (present) HNBLLIF_Message tr_HNBLLIF_GTP_CONN_DATA_IND(template (present) uint32_t gtp_conn_id,
+ template (present) octetstring data := ?) := {
+ sapi := HNBLL_IF_SAPI_GTP,
+ u := {
+ gtp := {
+ prim := HNBLL_IF_GTP_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_INDICATION,
+ u := {
+ ind := {
+ gtp_conn_id := gtp_conn_id,
+ data_len := ?,
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+template (value) HNBLLIF_Message ts_HNBLLIF_GTP_CONN_DATA_REQ(template (value) uint32_t gtp_conn_id,
+ template (value) octetstring data) := {
+ sapi := HNBLL_IF_SAPI_GTP,
+ u := {
+ gtp := {
+ prim := HNBLL_IF_GTP_MSG_CONN_DATA,
+ u := {
+ conn_data := {
+ op := HNBLL_IF_OP_REQUEST,
+ u := {
+ req := {
+ gtp_conn_id := gtp_conn_id,
+ data_len := lengthof(data),
+ data := data
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+} with { encode "RAW" variant "BYTEORDER(first)" };
diff --git a/library/HNBLLIF_Types.ttcn b/library/HNBLLIF_Types.ttcn
new file mode 100644
index 00000000..cbbe984e
--- /dev/null
+++ b/library/HNBLLIF_Types.ttcn
@@ -0,0 +1,532 @@
+/* Osmocom HNBLL Interface Types, as per osmo-hnodeb/include/osmocom/hnodeb/hnb_prim.h
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * 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 HNBLLIF_Types {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Native_Functions all;
+
+modulepar {
+ /* HNBLLIF version supported by the IUT */
+ HNBLLIF_Version mp_hnbllif_version := 0;
+};
+
+const charstring HNBLL_SOCK_DEFAULT := "/tmp/hnb_prim_sock";
+type integer HNBLLIF_Version (0); /* supported versions */
+
+/**********************
+ * CTL SAPI
+ **********************/
+
+
+type enumerated HNBLLIF_CTL_MsgType {
+ HNBLL_IF_CTL_MSG_HELLO ('0000'O)
+} with { variant "FIELDLENGTH(16)" };
+
+type record HNBLLIF_CTL_hello_req {
+ HNBLLIF_Sapi sapi,
+ uint16_t api_version
+} with { variant "" };
+
+type record HNBLLIF_CTL_hello_cnf {
+ HNBLLIF_Sapi sapi,
+ uint16_t api_version
+} with { variant "" };
+
+type union HNBLLIF_CTL_PrimOpUnion_hello {
+ HNBLLIF_CTL_hello_req req,
+ HNBLLIF_CTL_hello_cnf cnf,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_CTL_PrimOp_hello {
+ HNBLLIF_Operation op,
+ HNBLLIF_CTL_PrimOpUnion_hello u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ cnf, op = HNBLL_IF_OP_CONFIRM;
+ other, OTHERWISE)"
+};
+
+type union HNBLLIF_CTL_PrimUnion {
+ HNBLLIF_CTL_PrimOp_hello hello,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_CTL_PrimHdr {
+ HNBLLIF_CTL_MsgType prim,
+ HNBLLIF_CTL_PrimUnion u
+} with { variant (u) "CROSSTAG( hello, prim = HNBLL_IF_CTL_MSG_HELLO;
+ other, OTHERWISE)"
+};
+
+/**********************
+ * IUH SAPI
+ **********************/
+type enumerated HNBLLIF_IUH_MsgType {
+ HNBLL_IF_IUH_MSG_CONFIGURE ('0000'O),
+ HNBLL_IF_IUH_MSG_CONN_ESTABLISH ('0001'O),
+ HNBLL_IF_IUH_MSG_CONN_RELEASE ('0002'O),
+ HNBLL_IF_IUH_MSG_CONN_DATA ('0003'O),
+ HNBLL_IF_IUH_MSG_UNITDATA ('0004'O)
+} with { variant "FIELDLENGTH(16)" };
+
+/* CONFIGURE */
+type record HNBLLIF_IUH_configure_ind {
+ uint16_t mcc,
+ uint16_t mnc,
+ uint16_t cell_identity,
+ uint16_t lac,
+ uint8_t rac,
+ uint8_t reserved,
+ uint16_t sac,
+ uint16_t rnc_id
+} with { variant "" };
+
+type union HNBLLIF_IUH_PrimOpUnion_configure {
+ HNBLLIF_IUH_configure_ind ind,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_IUH_PrimOp_configure {
+ HNBLLIF_Operation op,
+ HNBLLIF_IUH_PrimOpUnion_configure u
+} with { variant (u) "CROSSTAG( ind, op = HNBLL_IF_OP_INDICATION;
+ other, OTHERWISE)"
+};
+
+/* CONN_ESTABLISH */
+type record HNBLLIF_IUH_conn_establish_req {
+ uint32_t context_id,
+ uint8_t domain,
+ uint8_t est_cause,
+ uint16_t reserved, //uint16_t nas_node_selector_bitlen;
+ //uint8_t nas_node_selector[128]; /* TODO: check whether we can decrease this buffer size */
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type record HNBLLIF_IUH_conn_establish_cnf {
+ uint32_t context_id,
+ uint8_t domain,
+ uint8_t est_cause
+} with { variant "" };
+
+type union HNBLLIF_IUH_PrimOpUnion_conn_establish {
+ HNBLLIF_IUH_conn_establish_req req,
+ HNBLLIF_IUH_conn_establish_cnf cnf,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_IUH_PrimOp_conn_establish {
+ HNBLLIF_Operation op,
+ HNBLLIF_IUH_PrimOpUnion_conn_establish u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ cnf, op = HNBLL_IF_OP_CONFIRM;
+ other, OTHERWISE)"
+};
+
+/* CONN_RELEASE */
+type record HNBLLIF_IUH_conn_release_req {
+ uint32_t context_id,
+ uint8_t domain,
+ uint8_t spare1,
+ uint8_t cause_type,
+ uint8_t cause,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+
+type union HNBLLIF_IUH_PrimOpUnion_conn_release {
+ HNBLLIF_IUH_conn_release_req req,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_IUH_PrimOp_conn_release {
+ HNBLLIF_Operation op,
+ HNBLLIF_IUH_PrimOpUnion_conn_release u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ other, OTHERWISE)"
+};
+
+/* CONN_DATA */
+type record HNBLLIF_IUH_conn_data_ind {
+ uint32_t context_id,
+ uint8_t domain,
+ uint8_t spare1,
+ uint16_t spare2,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type record HNBLLIF_IUH_conn_data_req {
+ uint32_t context_id,
+ uint8_t domain,
+ uint8_t spare1,
+ uint16_t spare2,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type union HNBLLIF_IUH_PrimOpUnion_conn_data {
+ HNBLLIF_IUH_conn_data_req req,
+ HNBLLIF_IUH_conn_data_ind ind,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_IUH_PrimOp_conn_data {
+ HNBLLIF_Operation op,
+ HNBLLIF_IUH_PrimOpUnion_conn_data u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ ind, op = HNBLL_IF_OP_INDICATION;
+ other, OTHERWISE)"
+};
+
+/* UNITDATA */
+type record HNBLLIF_IUH_unitdata_ind {
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type record HNBLLIF_IUH_unitdata_req {
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type union HNBLLIF_IUH_PrimOpUnion_unitdata {
+ HNBLLIF_IUH_unitdata_req req,
+ HNBLLIF_IUH_unitdata_ind ind,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_IUH_PrimOp_unitdata {
+ HNBLLIF_Operation op,
+ HNBLLIF_IUH_PrimOpUnion_unitdata u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ ind, op = HNBLL_IF_OP_INDICATION;
+ other, OTHERWISE)"
+};
+
+type union HNBLLIF_IUH_PrimUnion {
+ HNBLLIF_IUH_PrimOp_configure configure,
+ HNBLLIF_IUH_PrimOp_conn_establish conn_establish,
+ HNBLLIF_IUH_PrimOp_conn_release conn_release,
+ HNBLLIF_IUH_PrimOp_conn_data conn_data,
+ HNBLLIF_IUH_PrimOp_unitdata unitdata,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_IUH_PrimHdr {
+ HNBLLIF_IUH_MsgType prim,
+ HNBLLIF_IUH_PrimUnion u
+} with { variant (u) "CROSSTAG( configure, prim = HNBLL_IF_IUH_MSG_CONFIGURE;
+ conn_establish, prim = HNBLL_IF_IUH_MSG_CONN_ESTABLISH;
+ conn_release, prim = HNBLL_IF_IUH_MSG_CONN_RELEASE;
+ conn_data, prim = HNBLL_IF_IUH_MSG_CONN_DATA;
+ unitdata, prim = HNBLL_IF_IUH_MSG_UNITDATA;
+ other, OTHERWISE)"
+};
+
+/**********************
+ * AUDIO SAPI
+ **********************/
+type enumerated HNBLLIF_AUDIO_MsgType {
+ HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH ('0000'O),
+ HNBLL_IF_AUDIO_MSG_CONN_RELEASE ('0001'O),
+ HNBLL_IF_AUDIO_MSG_CONN_DATA ('0002'O)
+} with { variant "FIELDLENGTH(16)" };
+
+const integer HNBLLIF_MAX_RFCIS := 64;
+const integer HNBLLIF_MAX_SUBFLOWS := 7;
+type record length(HNBLLIF_MAX_RFCIS) of uint8_t HNBLLIF_AUDIO_IPTIs;
+type record length(HNBLLIF_MAX_SUBFLOWS) of uint16_t HNBLLIF_AUDIO_RFCI_SubflowSizes;
+type record length(HNBLLIF_MAX_RFCIS) of HNBLLIF_AUDIO_RFCI_SubflowSizes HNBLLIF_AUDIO_SubflowSizes;
+type record length(HNBLLIF_MAX_RFCIS) of uint8_t HNBLLIF_AUDIO_RFCIs;
+
+/* CONN_ESTABLISH */
+type record HNBLLIF_AUDIO_conn_establish_req {
+ uint32_t context_id,
+ uint16_t remote_rtp_port,
+ uint8_t reserved,
+ HNBLLIF_AddrType remote_rtp_address_type,
+ HNBLLIF_Addr remote_addr,
+ uint8_t transparent, /* 1=transparent; 0=SMpSDU */
+ uint8_t data_pdu_type,
+ uint16_t supported_versions_mask, /* host byte order */
+ uint8_t num_rfci,
+ uint8_t num_subflows,
+ HNBLLIF_AUDIO_SubflowSizes subflow_sizes,
+ uint8_t IPTIs_present, /* 1=present; 0=not present */
+ HNBLLIF_AUDIO_IPTIs IPTIs, /* values range 0-15, 4 bits */
+ HNBLLIF_AUDIO_RFCIs rfci optional /* only available in audio SAPI ver >= 1 */
+} with { variant "" };
+
+type record HNBLLIF_AUDIO_conn_establish_cnf {
+ uint32_t context_id,
+ uint32_t audio_conn_id,
+ uint16_t local_rtp_port,
+ uint8_t error_code,
+ HNBLLIF_AddrType local_rtp_address_type,
+ HNBLLIF_Addr local_addr
+} with { variant "" };
+
+type union HNBLLIF_AUDIO_PrimOpUnion_conn_establish {
+ HNBLLIF_AUDIO_conn_establish_req req,
+ HNBLLIF_AUDIO_conn_establish_cnf cnf,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_AUDIO_PrimOp_conn_establish {
+ HNBLLIF_Operation op,
+ HNBLLIF_AUDIO_PrimOpUnion_conn_establish u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ cnf, op = HNBLL_IF_OP_CONFIRM;
+ other, OTHERWISE)"
+};
+
+/* CONN_RELEASE */
+type record HNBLLIF_AUDIO_conn_release_req {
+ uint32_t audio_conn_id
+} with { variant "" };
+
+
+type union HNBLLIF_AUDIO_PrimOpUnion_conn_release {
+ HNBLLIF_AUDIO_conn_release_req req,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_AUDIO_PrimOp_conn_release {
+ HNBLLIF_Operation op,
+ HNBLLIF_AUDIO_PrimOpUnion_conn_release u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ other, OTHERWISE)"
+};
+
+/* CONN_DATA */
+type record HNBLLIF_AUDIO_conn_data_ind {
+ uint32_t audio_conn_id,
+ uint8_t frame_nr,
+ uint8_t fqc, /* enumerated IuUP_FQC */
+ uint8_t rfci,
+ uint8_t spare,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type record HNBLLIF_AUDIO_conn_data_req {
+ uint32_t audio_conn_id,
+ uint8_t frame_nr,
+ uint8_t fqc, /* enumerated IuUP_FQC */
+ uint8_t rfci,
+ uint8_t spare,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type union HNBLLIF_AUDIO_PrimOpUnion_conn_data {
+ HNBLLIF_AUDIO_conn_data_req req,
+ HNBLLIF_AUDIO_conn_data_ind ind,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_AUDIO_PrimOp_conn_data {
+ HNBLLIF_Operation op,
+ HNBLLIF_AUDIO_PrimOpUnion_conn_data u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ ind, op = HNBLL_IF_OP_INDICATION;
+ other, OTHERWISE)"
+};
+
+type union HNBLLIF_AUDIO_PrimUnion {
+ HNBLLIF_AUDIO_PrimOp_conn_establish conn_establish,
+ HNBLLIF_AUDIO_PrimOp_conn_release conn_release,
+ HNBLLIF_AUDIO_PrimOp_conn_data conn_data,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_AUDIO_PrimHdr {
+ HNBLLIF_AUDIO_MsgType prim,
+ HNBLLIF_AUDIO_PrimUnion u
+} with { variant (u) "CROSSTAG( conn_establish, prim = HNBLL_IF_AUDIO_MSG_CONN_ESTABLISH;
+ conn_release, prim = HNBLL_IF_AUDIO_MSG_CONN_RELEASE;
+ conn_data, prim = HNBLL_IF_AUDIO_MSG_CONN_DATA;
+ other, OTHERWISE)"
+};
+
+/**********************
+ * GTP SAPI
+ **********************/
+type enumerated HNBLLIF_GTP_MsgType {
+ HNBLL_IF_GTP_MSG_CONN_ESTABLISH ('0000'O),
+ HNBLL_IF_GTP_MSG_CONN_RELEASE ('0001'O),
+ HNBLL_IF_GTP_MSG_CONN_DATA ('0002'O)
+} with { variant "FIELDLENGTH(16)" };
+
+/* CONN_ESTABLISH */
+type record HNBLLIF_GTP_conn_establish_req {
+ uint32_t context_id,
+ uint32_t remote_tei,
+ uint8_t reserved,
+ HNBLLIF_AddrType remote_gtpu_address_type,
+ HNBLLIF_Addr remote_gtpu_addr
+} with { variant "" };
+
+type record HNBLLIF_GTP_conn_establish_cnf {
+ uint32_t context_id,
+ uint32_t gtp_conn_id,
+ uint32_t local_tei,
+ uint8_t error_code,
+ HNBLLIF_AddrType local_gtpu_address_type,
+ HNBLLIF_Addr local_gtpu_addr
+} with { variant "" };
+
+type union HNBLLIF_GTP_PrimOpUnion_conn_establish {
+ HNBLLIF_GTP_conn_establish_req req,
+ HNBLLIF_GTP_conn_establish_cnf cnf,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_GTP_PrimOp_conn_establish {
+ HNBLLIF_Operation op,
+ HNBLLIF_GTP_PrimOpUnion_conn_establish u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ cnf, op = HNBLL_IF_OP_CONFIRM;
+ other, OTHERWISE)"
+};
+
+/* CONN_RELEASE */
+type record HNBLLIF_GTP_conn_release_req {
+ uint32_t gtp_conn_id
+} with { variant "" };
+
+type union HNBLLIF_GTP_PrimOpUnion_conn_release {
+ HNBLLIF_GTP_conn_release_req req,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_GTP_PrimOp_conn_release {
+ HNBLLIF_Operation op,
+ HNBLLIF_GTP_PrimOpUnion_conn_release u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ other, OTHERWISE)"
+};
+
+/* CONN_DATA */
+type record HNBLLIF_GTP_conn_data_req {
+ uint32_t gtp_conn_id,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type record HNBLLIF_GTP_conn_data_ind {
+ uint32_t gtp_conn_id,
+ uint32_t data_len,
+ octetstring data /* RANAP message */
+} with { variant (data_len) "LENGTHTO (data)" };
+
+type union HNBLLIF_GTP_PrimOpUnion_conn_data {
+ HNBLLIF_GTP_conn_data_req req,
+ HNBLLIF_GTP_conn_data_ind ind,
+ octetstring other
+} with { variant "" };
+type record HNBLLIF_GTP_PrimOp_conn_data {
+ HNBLLIF_Operation op,
+ HNBLLIF_GTP_PrimOpUnion_conn_data u
+} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST;
+ ind, op = HNBLL_IF_OP_INDICATION;
+ other, OTHERWISE)"
+};
+
+type union HNBLLIF_GTP_PrimUnion {
+ HNBLLIF_GTP_PrimOp_conn_establish conn_establish,
+ HNBLLIF_GTP_PrimOp_conn_release conn_release,
+ HNBLLIF_GTP_PrimOp_conn_data conn_data,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_GTP_PrimHdr {
+ HNBLLIF_GTP_MsgType prim,
+ HNBLLIF_GTP_PrimUnion u
+} with { variant (u) "CROSSTAG( conn_establish, prim = HNBLL_IF_GTP_MSG_CONN_ESTABLISH;
+ conn_release, prim = HNBLL_IF_GTP_MSG_CONN_RELEASE;
+ conn_data, prim = HNBLL_IF_GTP_MSG_CONN_DATA;
+ other, OTHERWISE)"
+};
+
+
+/**********************
+* General
+**********************/
+
+type enumerated HNBLLIF_AddrType {
+ HNBLL_IF_ADDR_TYPE_UNSPEC ('00'O),
+ HNBLL_IF_ADDR_TYPE_IPV4 ('01'O),
+ HNBLL_IF_ADDR_TYPE_IPV6 ('02'O)
+} with { variant "FIELDLENGTH(8)" };
+type octetstring HNBLLIF_Addr length(16);
+
+type enumerated HNBLLIF_Sapi {
+ HNBLL_IF_SAPI_CTL (-1),
+ HNBLL_IF_SAPI_IUH ('00000001'O),
+ HNBLL_IF_SAPI_GTP ('00000002'O),
+ HNBLL_IF_SAPI_AUDIO ('00000003'O)
+} with { variant "FIELDLENGTH(32)"
+ variant "COMP(2scompl)"
+};
+
+type enumerated HNBLLIF_Operation {
+ HNBLL_IF_OP_REQUEST ('0000'O),
+ HNBLL_IF_OP_RESPONSE ('0001'O),
+ HNBLL_IF_OP_INDICATION ('0002'O),
+ HNBLL_IF_OP_CONFIRM ('0003'O)
+} with { variant "FIELDLENGTH(16)" };
+
+type union HNBLLIF_SapiUnion {
+ HNBLLIF_CTL_PrimHdr ctl,
+ HNBLLIF_IUH_PrimHdr iuh,
+ HNBLLIF_GTP_PrimHdr gtp,
+ HNBLLIF_AUDIO_PrimHdr audio,
+ octetstring other
+} with { variant "" };
+
+type record HNBLLIF_Message {
+ HNBLLIF_Sapi sapi,
+ HNBLLIF_SapiUnion u
+} with { variant (u) "CROSSTAG( ctl, sapi = HNBLL_IF_SAPI_CTL;
+ iuh, sapi = HNBLL_IF_SAPI_IUH;
+ gtp, sapi = HNBLL_IF_SAPI_GTP;
+ audio, sapi = HNBLL_IF_SAPI_AUDIO;
+ other, OTHERWISE)"
+};
+
+external function enc_HNBLLIF_Message(in HNBLLIF_Message pdu) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_HNBLLIF_Message(in octetstring stream) return HNBLLIF_Message
+ with { extension "prototype(convert) decode(RAW)" };
+
+function f_HNBLLIF_AF2addr_type(AddressFamily address_family)
+return HNBLLIF_AddrType {
+ if (address_family == AF_INET) {
+ return HNBLL_IF_ADDR_TYPE_IPV4;
+ } else if (address_family == AF_INET6) {
+ return HNBLL_IF_ADDR_TYPE_IPV6;
+ } else {
+ return HNBLL_IF_ADDR_TYPE_UNSPEC;
+ }
+}
+
+function f_HNBLLIF_Addr(HNBLLIF_AddrType addr_type, charstring addr_str)
+return HNBLLIF_Addr {
+ var HNBLLIF_Addr addr;
+
+ if (addr_type == HNBLL_IF_ADDR_TYPE_IPV4) {
+ addr := f_inet_addr(addr_str);
+ } else {
+ addr := f_inet6_addr(addr_str);
+ }
+
+ return addr;
+}
+
+
+} with { encode "RAW" variant "BYTEORDER(first)" };
diff --git a/library/HTTP_Adapter.ttcn b/library/HTTP_Adapter.ttcn
new file mode 100644
index 00000000..0885f058
--- /dev/null
+++ b/library/HTTP_Adapter.ttcn
@@ -0,0 +1,113 @@
+module HTTP_Adapter {
+
+/* HTTP Adapter component, originally part of Integration Tests for osmo-remsim-server
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ *
+ * This test suite tests osmo-remsim-server by attaching to the external interfaces
+ * such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
+ */
+
+import from HTTPmsg_Types all;
+import from HTTPmsg_PortType all;
+
+type component http_CT {
+ port HTTPmsg_PT HTTP;
+ var charstring g_http_host;
+ var integer g_http_port;
+};
+
+function f_http_init(charstring host, integer http_port) runs on http_CT {
+ map(self:HTTP, system:HTTP);
+ g_http_host := host;
+ g_http_port := http_port;
+}
+
+template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
+ template (value) integer http_port := 80,
+ template (value) boolean use_ssl := false) := {
+ hostname := hostname,
+ portnumber := http_port,
+ use_ssl := use_ssl
+}
+template (value) Close ts_HTTP_Close := { client_id := omit };
+
+template (value) HeaderLines ts_HTTP_Header(charstring body, charstring host) := {
+ { header_name := "Host", header_value := host },
+ { header_name := "Content-Type", header_value := "application/json" },
+ { header_name := "Content-Length", header_value := int2str(lengthof(body)) }
+}
+
+template (value) HTTPMessage ts_HTTP_Req(charstring url,
+ charstring method := "GET",
+ charstring body := "",
+ integer v_maj := 1, integer v_min := 1,
+ charstring host) := {
+ request := {
+ client_id := omit,
+ method := method,
+ uri := url,
+ version_major := v_maj,
+ version_minor := v_min,
+ header := valueof(ts_HTTP_Header(body, host)),
+ body := body
+ }
+}
+
+template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
+ response := {
+ client_id := ?,
+ version_major := ?,
+ version_minor := ?,
+ statuscode := sts,
+ statustext := ?,
+ header := ?,
+ body := ?
+ }
+};
+
+template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
+
+function f_http_tx_request(charstring url, charstring method := "GET", charstring body := "")
+runs on http_CT {
+ HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
+ HTTP.receive(Connect_result:?);
+ HTTP.send(ts_HTTP_Req(url, method, body, host := g_http_host & ":" & int2str(g_http_port)));
+}
+
+function f_http_rx_response(template HTTPMessage exp := tr_HTTP_Resp2xx, float tout := 2.0)
+runs on http_CT return HTTPMessage {
+ var HTTPMessage resp;
+ timer T := tout;
+ T.start;
+ alt {
+ [] HTTP.receive(exp) -> value resp {
+ setverdict(pass);
+ }
+ [] HTTP.receive(tr_HTTP_Resp) -> value resp {
+ setverdict(fail, "Unexpected HTTP response ", resp);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for HTTP response");
+ self.stop;
+ }
+ }
+ HTTP.send(ts_HTTP_Close);
+ return resp;
+}
+
+/* run a HTTP request and return the response */
+function f_http_transact(charstring url, charstring method := "GET",
+ charstring body := "", template HTTPMessage exp := tr_HTTP_Resp2xx,
+ float tout := 2.0)
+runs on http_CT return HTTPMessage {
+ f_http_tx_request(url, method, body);
+ return f_http_rx_response(exp, tout);
+}
+
+}
diff --git a/library/HTTP_Server_Emulation.ttcn b/library/HTTP_Server_Emulation.ttcn
new file mode 100644
index 00000000..16d142d2
--- /dev/null
+++ b/library/HTTP_Server_Emulation.ttcn
@@ -0,0 +1,147 @@
+/* HTTP Emulation in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * 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
+ *
+ * This module implements a HTTP/HTTPs server based on TestPorts/HTTPmsg,
+ * (see also deps/titan.TestPorts.HTTPmsg)
+ */
+
+module HTTP_Server_Emulation {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from HTTPmsg_Types all;
+import from HTTPmsg_PortType all;
+
+/***********************************************************************
+ * Main Emulation Component
+ ***********************************************************************/
+
+type record HttpServerEmulationCfg {
+ charstring http_bind_ip,
+ integer http_bind_port,
+ boolean use_ssl
+};
+
+type component HTTP_Server_Emulation_CT {
+ /* Communication with underlying HTTP CodecPort */
+ port HTTPmsg_PT HTTP_server_port;
+
+ /* Communication with Clients */
+ port HTTP_SRV_PT CLIENT;
+ port HTTP_SRV_PROC_PT CLIENT_PROC;
+ port HTTP_SRV_PT CLIENT_DEFAULT;
+
+ /* Configuration by the user */
+ var HttpServerEmulationCfg g_http_cfg;
+
+ /* State */
+ var HTTP_ConnHdlr vc_conn_table[16];
+};
+
+private function f_init(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT {
+
+ g_http_cfg := cfg;
+
+ map(self:HTTP_server_port, system:HTTP_server_port);
+ var Listen listen := { local_hostname := g_http_cfg.http_bind_ip,
+ portnumber := g_http_cfg.http_bind_port,
+ use_ssl := g_http_cfg.use_ssl };
+
+ /* Start HTTP server */
+ HTTP_server_port.send(listen);
+}
+
+private function f_vc_conn_table_add(HTTP_ConnHdlr vc_conn) runs on HTTP_Server_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(vc_conn_table); i := i + 1) {
+ if (not isbound(vc_conn_table[i])) {
+ vc_conn_table[i] := vc_conn;
+ return;
+ }
+ }
+ testcase.stop("No Space in vc_conn_table[i] for ", vc_conn);
+}
+
+/* Forward request to all registered clients */
+private function forward_req(HTTPMessage recv_req_value) runs on HTTP_Server_Emulation_CT {
+
+ var integer i;
+ for (i := 0; i < sizeof(vc_conn_table); i := i + 1) {
+ if (isbound(vc_conn_table[i])) {
+ CLIENT.send(recv_req_value) to vc_conn_table[i];
+ }
+ }
+}
+
+function main(HttpServerEmulationCfg cfg) runs on HTTP_Server_Emulation_CT {
+
+ var HTTP_ConnHdlr vc_conn;
+ var template (value) Close close := { client_id := omit };
+ var template (present) Half_close half_close := { client_id := ? };
+ var template (present) HTTPMessage recv_req := { request := ? };
+ var template (present) HTTPMessage recv_req_bin := { request_binary := ? };
+ var HTTPMessage recv_req_value;
+ var HTTPMessage send_resp_value;
+
+ f_init(cfg);
+
+ while(true) {
+ alt {
+ [] HTTP_server_port.receive(recv_req) -> value recv_req_value {
+ forward_req(recv_req_value);
+ }
+ [] HTTP_server_port.receive(recv_req_bin) -> value recv_req_value {
+ forward_req(recv_req_value);
+ }
+ [] CLIENT.receive(HTTPMessage:?) -> value send_resp_value sender vc_conn {
+ HTTP_server_port.send(send_resp_value);
+ }
+ [] HTTP_server_port.receive(half_close) {
+ HTTP_server_port.send(close);
+ }
+ [] CLIENT_PROC.getcall(HTTPEM_register:{}) -> sender vc_conn {
+ f_vc_conn_table_add(vc_conn);
+ CLIENT_PROC.reply(HTTPEM_register:{}) to vc_conn;
+ }
+ }
+ }
+
+}
+
+
+/***********************************************************************
+ * Interaction between Main and Client Components
+ ***********************************************************************/
+type port HTTP_SRV_PT message {
+ inout HTTPMessage;
+} with { extension "internal" };
+
+signature HTTPEM_register();
+
+type port HTTP_SRV_PROC_PT procedure {
+ inout HTTPEM_register;
+} with { extension "internal" };
+
+
+/***********************************************************************
+ * Client Component
+ ***********************************************************************/
+
+type component HTTP_ConnHdlr {
+ port HTTP_SRV_PT HTTP_SRV;
+ port HTTP_SRV_PROC_PT HTTP_SRV_PROC;
+};
+
+function f_http_register() runs on HTTP_ConnHdlr {
+ HTTP_SRV_PROC.call(HTTPEM_register:{}) {
+ [] HTTP_SRV_PROC.getreply(HTTPEM_register:{});
+ }
+}
+
+}
diff --git a/library/ICMP_Templates.ttcn b/library/ICMP_Templates.ttcn
new file mode 100644
index 00000000..cf88e93d
--- /dev/null
+++ b/library/ICMP_Templates.ttcn
@@ -0,0 +1,96 @@
+/* ICMP Templates in TTCN-3
+ * (C) 2024 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 ICMP_Templates {
+
+ import from General_Types all;
+ import from IP_Types all;
+ import from ICMP_Types all;
+
+ /* template for sending an ICMPv4 echo request */
+ template (value) PDU_ICMP ts_ICMPv4_ERQ(octetstring data := ''O) := {
+ echo := {
+ type_field := 8,
+ code := 0,
+ checksum := '0000'O,
+ identifier := '0345'O,
+ sequence_number := '0001'O,
+ data := data
+ }
+ }
+
+ /* template for receiving/matching an ICMPv4 echo request */
+ template (present) PDU_ICMP tr_ICMPv4_ERQ := {
+ echo := {
+ type_field := 8,
+ code := 0,
+ checksum := ?,
+ identifier := ?,
+ sequence_number := ?,
+ data := ?
+ }
+ }
+
+ /* template for receiving/matching an ICMPv4 echo reply */
+ template (present) PDU_ICMP tr_ICMPv4_ERP(template octetstring data := *) := {
+ echo_reply := {
+ type_field := 0,
+ code := 0,
+ checksum := ?,
+ identifier := ?,
+ sequence_number := ?,
+ data := data
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 Destination Unreachable */
+ template (present) PDU_ICMP tr_ICMPv4_DU := {
+ destination_unreachable := {
+ type_field := 1,
+ code := ?,
+ checksum := ?,
+ unused := ?,
+ original_ip_msg := ?
+ }
+ }
+
+ /* template to construct IPv4_packet from input arguments, ready for use in f_IPv4_enc() */
+ template (value) IPv4_packet ts_IP4(OCT4 srcaddr, OCT4 dstaddr, LIN1 proto, LIN2_BO_LAST tlen, octetstring payload) := {
+ header := {
+ ver := 4,
+ hlen := 5,
+ tos := 0,
+ tlen := tlen,
+ id := 35902,
+ res := '0'B,
+ dfrag := '1'B,
+ mfrag := '0'B,
+ foffset := 0,
+ ttl := 64,
+ proto := proto,
+ cksum := 0,
+ srcaddr := srcaddr,
+ dstaddr := dstaddr
+ },
+ ext_headers := omit,
+ payload := payload
+ }
+
+ /* Send an ICMPv4 echo msg through GTP given pdp ctx, and ip src and dst addr */
+ function f_gen_icmpv4_echo(OCT4 saddr, OCT4 daddr, octetstring pl := ''O) return octetstring {
+ var octetstring tmp := f_enc_PDU_ICMP(valueof(ts_ICMPv4_ERQ(pl)));
+ var IPv4_packet ip4 := valueof(ts_IP4(saddr, daddr, 1, 50, tmp));
+ var octetstring data := f_IPv4_enc(ip4);
+ var OCT2 cksum := f_IPv4_checksum(data);
+ data[10] := cksum[0];
+ data[11] := cksum[1];
+ return data;
+ }
+} \ No newline at end of file
diff --git a/library/ICMPv6_Templates.ttcn b/library/ICMPv6_Templates.ttcn
new file mode 100644
index 00000000..687aad45
--- /dev/null
+++ b/library/ICMPv6_Templates.ttcn
@@ -0,0 +1,238 @@
+/* ICMPv6 Templates in TTCN-3
+ * (C) 2024 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 ICMPv6_Templates {
+
+ import from General_Types all;
+ import from IP_Types all;
+ import from ICMPv6_Types all;
+
+ /* template to generate a 'Prefix Information' ICMPv6 option */
+ template (value) OptionField ts_ICMP6_OptPrefix(OCT16 prefix, INT1 prefix_len) := {
+ prefixInformation := {
+ typeField := 3,
+ lengthIndicator := 8,
+ prefixLength := prefix_len,
+ reserved1 := '000000'B,
+ a_Bit := '0'B,
+ l_Bit := '0'B,
+ validLifetime := oct2int('FFFFFFFF'O),
+ preferredLifetime := oct2int('FFFFFFFF'O),
+ reserved2 := '00000000'O,
+ prefix := prefix
+ }
+ }
+
+ /* template for sending an ICMPv6 echo request */
+ template (value) PDU_ICMPv6 ts_ICMPv6_ERQ := {
+ echoRequest := {
+ typeField := 128,
+ code := 0,
+ checksum := '0000'O,
+ identifier := 0,
+ sequenceNr := 0,
+ data := ''O
+ }
+ }
+
+ /* template for sending an ICMPv6 router solicitation */
+ template (value) PDU_ICMPv6 ts_ICMPv6_RS := {
+ routerSolicitation := {
+ typeField := 133,
+ code := 0,
+ checksum := '0000'O,
+ reserved := '00000000'O,
+ /* TODO: do we need 'Source link-layer address' ? */
+ options := omit
+ }
+ }
+
+ /* template for sending an ICMPv6 router advertisement */
+ template (value) PDU_ICMPv6 ts_ICMPv6_RA(OCT16 prefix, INT1 prefix_len) := {
+ routerAdvertisement := {
+ typeField := 134,
+ code := 0,
+ checksum := '0000'O,
+ curHopLimit := 0,
+ reserved := '000000'B,
+ o_Bit := '0'B,
+ m_Bit := '0'B,
+ routerLifetime := oct2int('FFFF'O),
+ reachableTime := oct2int('FFFFFFFF'O),
+ retransTimer := oct2int('FFFFFFFF'O),
+ options := {
+ ts_ICMP6_OptPrefix(prefix, prefix_len)
+ }
+ }
+ }
+
+ /* template for sending an ICMPv6 neighbor solicitation */
+ template (value) PDU_ICMPv6 ts_ICMPv6_NS(OCT16 target_addr) := {
+ neighborSolicitation := {
+ typeField := 135,
+ code := 0,
+ checksum := '0000'O,
+ reserved := '00000000'O,
+ targetAddress := target_addr,
+ /* TODO: do we need 'Source link-layer address' ? */
+ options := omit
+ }
+ }
+
+ /* derive ICMPv6 link-local address from lower 64bit of link_id */
+ /* template for receiving/matching an ICMPv6 'Prefix Information' option */
+ template (present) OptionField tr_ICMP6_OptPrefix(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
+ prefixInformation := {
+ typeField := 3,
+ lengthIndicator := 4,
+ prefixLength := prefix_len,
+ reserved1 := ?,
+ a_Bit := ?,
+ l_Bit := ?,
+ validLifetime := ?,
+ preferredLifetime := ?,
+ reserved2 := ?,
+ prefix := prefix
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 'MTU' option, rfc4861 4.6.4 */
+ template (present) OptionField tr_ICMP6_OptMTU(template (present) integer mtu := ?) := {
+ mTU := {
+ typeField := 5,
+ lengthIndicator := 1,
+ reserved := ?,
+ mTU_Value := mtu
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 router advertisement */
+ template (present) PDU_ICMPv6 tr_ICMPv6_RA(template (present) OCT16 prefix, template (present) INT1 prefix_len) := {
+ routerAdvertisement := {
+ typeField := 134,
+ code := 0,
+ checksum := ?,
+ curHopLimit := ?,
+ reserved := ?,
+ o_Bit := '0'B,
+ m_Bit := '0'B,
+ routerLifetime := ?,
+ reachableTime := ?,
+ retransTimer := ?,
+ options := ({ tr_ICMP6_OptPrefix(prefix, prefix_len) },
+ { tr_ICMP6_OptPrefix(prefix, prefix_len), tr_ICMP6_OptMTU }
+ )
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 Destination Unreachable */
+ template (present) PDU_ICMPv6 tr_ICMPv6_DU := {
+ destinationUnreachable := {
+ typeField := 1,
+ code := ?,
+ checksum := ?,
+ unused := ?,
+ originalIpMsg := ?
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 echo request */
+ template (present) PDU_ICMPv6 tr_ICMPv6_ERQ := {
+ echoRequest := {
+ typeField := 128,
+ code := 0,
+ checksum := ?,
+ identifier := ?,
+ sequenceNr := ?,
+ data := ?
+ }
+ }
+
+ /* template for receiving/matching an ICMPv6 echo reply */
+ template (present) PDU_ICMPv6 tr_ICMPv6_ERP(template octetstring data := *) := {
+ echoReply := {
+ typeField := 129,
+ code := 0,
+ checksum := ?,
+ identifier := ?,
+ sequenceNr := ?,
+ data := data
+ }
+ }
+
+ /* template to construct IPv6_packet from input arguments, ready for use in f_IPv6_enc() */
+ template (value) IPv6_packet ts_IP6(OCT16 srcaddr, OCT16 dstaddr, LIN1 nexthead, octetstring payload, LIN1 hlim := 255) := {
+ header := {
+ ver := 6,
+ trclass := 0,
+ flabel := 0,
+ plen := 0,
+ nexthead := nexthead,
+ hlim := hlim,
+ srcaddr := srcaddr,
+ dstaddr := dstaddr
+ },
+ ext_headers := omit,
+ payload := payload
+ }
+
+ function f_ipv6_link_local(in OCT16 link_id) return OCT16 {
+ return 'FE80000000000000'O & substr(link_id, 8, 8);
+ }
+
+ function f_ipv6_global(in OCT16 link_id) return OCT16 {
+ return substr(link_id, 0, 8) & '1234123412341234'O;
+ }
+
+ /* Create a new different IPv6 addr from input. Starts mangling at byte prefix. */
+ function f_ipv6_mangle(in OCT16 addr, in integer prefix := 0) return OCT16 {
+ var integer i;
+ var octetstring res := substr(addr, 0, prefix);
+ for (i := prefix; i < lengthof(addr); i := i + 1) {
+ var octetstring a := addr[i] xor4b '11'O;
+ res := res & a;
+ }
+ return res;
+ }
+
+ /* Send an ICMPv6 echo msg through GTP given pdp ctx, and ip src and dst addr */
+ function f_gen_icmpv6_echo(OCT16 saddr, OCT16 daddr) return octetstring {
+ var octetstring tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_ERQ), saddr, daddr);
+ var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
+ var octetstring data := f_IPv6_enc(ip6);
+ return data;
+ }
+
+ /* Compute solicited-node multicast address as per RFC4291 2.7.1 */
+ function f_ipv6_sol_node_mcast(in OCT16 addr) return OCT16 {
+ return 'FF0200000000000000000001FF'O & substr(addr, 13, 3);
+ }
+
+ /* generate and encode ICMPv6 router solicitation */
+ function f_gen_icmpv6_router_solicitation(in OCT16 link_id) return octetstring {
+ const OCT16 c_ip6_all_router_mcast := 'FF020000000000000000000000000002'O;
+ var OCT16 saddr := f_ipv6_link_local(link_id);
+
+ var octetstring tmp;
+ tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_RS), saddr, c_ip6_all_router_mcast);
+ var IPv6_packet ip6 := valueof(ts_IP6(saddr, c_ip6_all_router_mcast, 58, tmp));
+
+ return f_IPv6_enc(ip6);
+ }
+
+ /* generate and encode ICMPv6 neighbor solicitation */
+ function f_gen_icmpv6_neigh_solicit(in OCT16 saddr, in OCT16 daddr, in OCT16 tgt_addr) return octetstring {
+ var octetstring tmp;
+ tmp := f_enc_PDU_ICMPv6(valueof(ts_ICMPv6_NS(tgt_addr)), saddr, daddr);
+ var IPv6_packet ip6 := valueof(ts_IP6(saddr, daddr, 58, tmp));
+ return f_IPv6_enc(ip6);
+ }
+
+} \ No newline at end of file
diff --git a/library/IPA_Emulation.ttcnpp b/library/IPA_Emulation.ttcnpp
index 60c6061e..07fefe55 100644
--- a/library/IPA_Emulation.ttcnpp
+++ b/library/IPA_Emulation.ttcnpp
@@ -44,6 +44,7 @@ import from MGCP_Types all;
#ifdef IPA_EMULATION_GSUP
import from GSUP_Types all;
+import from GSUP_Templates all;
#endif
#ifdef IPA_EMULATION_RSPRO
@@ -55,6 +56,10 @@ import from RSPRO_Types all;
import from Osmocom_CTRL_Types all;
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+import from PCUIF_Types all;
+#endif
+
modulepar {
/* Use Osmocom extended IPA mux header */
boolean mp_ipa_mgcp_uses_osmo_ext := true;
@@ -190,12 +195,21 @@ type port IPA_RSPRO_PT message {
} with { extension "internal" }
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+/* Client port for Osmocom PCU extension inside IPA */
+type port IPA_OSMO_PCU_PT message {
+ inout PCUIF_Message, ASP_IPA_Event;
+} with { extension "internal" }
+#endif
type component IPA_Emulation_CT {
/* down-facing port to IPA codec port */
port IPA_CODEC_PT IPA_PORT;
+ /* Down facing port to configure the component */
+ port IPA_CFG_PT CFG_PORT;
+
#ifdef IPA_EMULATION_SCCP
/* up-facing port to SCCP */
port MTP3asp_SP_PT MTP3_SP_PORT;
@@ -224,6 +238,10 @@ type component IPA_Emulation_CT {
/* up-facing port for RSPRO */
port IPA_RSPRO_PT IPA_RSPRO_PORT;
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+ /* up-facing port for RSPRO */
+ port IPA_OSMO_PCU_PT IPA_OSMO_PCU_PORT;
+#endif
/* up-facing port for other streams */
port IPA_SP_PT IPA_SP_PORT;
@@ -240,6 +258,9 @@ type component IPA_Emulation_CT {
var IpaMode g_mode;
var boolean g_ccm_enabled;
var IpaInitBehavior g_init_behavior;
+ /* Shall we stop the component once the client disconnects, or keep
+ * running to let next user in ? */
+ var boolean g_server_stop_on_ipa_ev_down := true;
var IPA_CCM_Parameters g_ccm_pars := c_IPA_default_ccm_pars;
}
@@ -269,6 +290,17 @@ const IPA_CCM_Parameters c_IPA_default_ccm_pars := {
osmo_rand := ""
};
+signature IPA_CFG_disconnect(inout IPL4asp_Types.Result res);
+type port IPA_CFG_PT procedure {
+ inout IPA_CFG_disconnect;
+} with { extension "internal" };
+
+function f_ipa_cfg_disconnect(IPA_CFG_PT pt, inout IPL4asp_Types.Result res) {
+ pt.call(IPA_CFG_disconnect:{res}) {
+ [] pt.getreply(IPA_CFG_disconnect:{?}) -> param (res) {};
+ }
+}
+
/* Function to use to connect as client to a remote IPA Server */
function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
charstring local_host, IPL4asp_Types.PortNumber local_port,
@@ -301,6 +333,25 @@ function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port,
g_is_bsc_mgw := false;
}
+private function f_close() runs on IPA_Emulation_CT return IPL4asp_Types.Result {
+ var IPL4asp_Types.Result res;
+ select (g_mode) {
+ case (IPA_MODE_CLIENT) {
+ res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_self_conn_id, {tcp := {}});
+ g_self_conn_id := -1;
+ }
+ case (IPA_MODE_SERVER) {
+ res := IPA_CodecPort_CtrlFunct.f_IPL4_close(IPA_PORT, g_last_conn_id, {tcp := {}});
+ g_last_conn_id := -1;
+ }
+ case else {
+ setverdict(fail, "Unknown mode");
+ mtc.stop;
+ }
+ }
+ return res;
+}
+
#ifdef IPA_EMULATION_SCCP
template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
sio := { '10'B, '00'B, '0011'B },
@@ -347,6 +398,11 @@ private function f_send_IPA_EVT(template (value) ASP_IPA_Event evt) runs on IPA_
IPA_RSPRO_PORT.send(evt);
}
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+ if (IPA_OSMO_PCU_PORT.checkstate("Connected")) {
+ IPA_OSMO_PCU_PORT.send(evt);
+ }
+#endif
/* FIXME: to other ports */
}
@@ -360,6 +416,11 @@ private function f_ccm_make_id_resp(PDU_IPA_CCM get) runs on IPA_Emulation_CT re
}
}
+ /* If no Tags were present in the received IPA message, .u = omit */
+ if (not ispresent(get.u)) {
+ return resp;
+ }
+
for (i := 0; i < sizeof(get.u.get); i := i + 1) {
var IpaCcmIdTag tag := get.u.get[i].tag;
var charstring foo;
@@ -549,11 +610,13 @@ function main_client(charstring remote_host, IPL4asp_Types.PortNumber remote_por
/* main function to use for a server-side IPA implementation */
function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port,
boolean ccm_enabled := true,
- IpaInitBehavior init_behavior := IPA_INIT_SEND_IPA_ID_GET)
+ IpaInitBehavior init_behavior := IPA_INIT_SEND_IPA_ID_GET,
+ boolean server_stop_on_ipa_ev_down := true)
runs on IPA_Emulation_CT {
g_mode := IPA_MODE_SERVER;
g_ccm_enabled := ccm_enabled;
g_init_behavior := init_behavior;
+ g_server_stop_on_ipa_ev_down := server_stop_on_ipa_ev_down;
f_bind(local_host, local_port);
ScanEvents();
}
@@ -580,6 +643,13 @@ private function f_rspro_to_user(octetstring msg) runs on IPA_Emulation_CT {
}
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+private function f_osmo_pcu_to_user(octetstring msg) runs on IPA_Emulation_CT {
+ var PCUIF_Message pcuif_msg := dec_PCUIF_Message(msg);
+ IPA_OSMO_PCU_PORT.send(pcuif_msg);
+}
+#endif
+
#ifdef IPA_EMULATION_MGCP
private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
var charstring msg_ch := oct2char(msg);
@@ -630,6 +700,7 @@ private function ScanEvents() runs on IPA_Emulation_CT {
var Socket_API_Definitions.PortEvent port_evt;
var octetstring payload;
var ASP_IPA_Unitdata ipa_ud;
+ var IPL4asp_Types.Result res;
#ifdef IPA_EMULATION_CTRL
var CtrlMessage ctrl_msg;
#endif
@@ -652,6 +723,9 @@ private function ScanEvents() runs on IPA_Emulation_CT {
#ifdef IPA_EMULATION_RSPRO
var RsproPDU rspro;
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+ var PCUIF_Message pcu;
+#endif
/* Set function for dissecting the binary */
var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
@@ -728,6 +802,11 @@ private function ScanEvents() runs on IPA_Emulation_CT {
f_rspro_to_user(ipa_rx.msg);
}
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+ case (IPAC_PROTO_EXT_OSMO_PCU) {
+ f_osmo_pcu_to_user(ipa_rx.msg);
+ }
+#endif
case else {
IPA_SP_PORT.send(f_to_asp(ipa_rx));
}
@@ -761,7 +840,9 @@ private function ScanEvents() runs on IPA_Emulation_CT {
log("IPA: Closed");
g_self_conn_id := -1;
f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, asp_evt.connClosed.connId));
- self.stop;
+ if (g_mode != IPA_MODE_SERVER or g_server_stop_on_ipa_ev_down) {
+ self.stop;
+ }
}
[] IPA_PORT.receive(Socket_API_Definitions.PortEvent:{result:={errorCode:=ERROR_SOCKET, connId:=?, os_error_code:=?, os_error_text:=?}}) -> value port_evt {
@@ -819,6 +900,14 @@ private function ScanEvents() runs on IPA_Emulation_CT {
}
#endif
+#ifdef IPA_EMULATION_OSMO_PCU
+ [] IPA_OSMO_PCU_PORT.receive(PCUIF_Message:?) -> value pcu {
+ payload := enc_PCUIF_Message(pcu);
+ ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_OSMO_PCU));
+ IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
+ }
+#endif
+
#ifdef IPA_EMULATION_RSL
/* Received RSL -> down into IPA */
[] IPA_RSL_PORT.receive(ASP_RSL_Unitdata:?) -> value rsl {
@@ -839,6 +928,11 @@ private function ScanEvents() runs on IPA_Emulation_CT {
IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
}
+ /* Received call to configure/operate the component */
+ [] CFG_PORT.getcall(IPA_CFG_disconnect:{?}) {
+ res := f_close();
+ CFG_PORT.reply(IPA_CFG_disconnect:{res});
+ }
}
}
diff --git a/library/IPA_Types.ttcn b/library/IPA_Types.ttcn
index 110e5b17..95623efa 100644
--- a/library/IPA_Types.ttcn
+++ b/library/IPA_Types.ttcn
@@ -35,7 +35,8 @@ type enumerated IpaExtStreamId {
IPAC_PROTO_EXT_ORC ('04'H),
IPAC_PROTO_EXT_GSUP ('05'H),
IPAC_PROTO_EXT_OAP ('06'H),
- IPAC_PROTO_EXT_RSPRO ('07'H)
+ IPAC_PROTO_EXT_RSPRO ('07'H),
+ IPAC_PROTO_EXT_OSMO_PCU ('08'H)
} with { variant "FIELDLENGTH(8)" }
external function enc_PDU_IPA(in PDU_IPA pdu) return octetstring
diff --git a/library/IuUP_Emulation.ttcn b/library/IuUP_Emulation.ttcn
index 56384ee7..3bda958b 100644
--- a/library/IuUP_Emulation.ttcn
+++ b/library/IuUP_Emulation.ttcn
@@ -26,6 +26,7 @@ type record IuUP_RabFlowCombination {
/* IPTI value in number of ITIs for the corresponding RFCI */
uint8_t ipti
};
+type record of IuUP_RabFlowCombination IuUP_RabFlowCombinationList;
template (value) IuUP_RabFlowCombination t_IuUP_RFC(IuUP_RFCI rfci, RecOfU8 subflow_bits, uint8_t ipti) := {
rfci := rfci,
@@ -34,23 +35,53 @@ template (value) IuUP_RabFlowCombination t_IuUP_RFC(IuUP_RFCI rfci, RecOfU8 subf
}
template (value) IuUP_RabFlowCombination t_IuUP_RFC_AMR_12_2(IuUP_RFCI rfci) := t_IuUP_RFC(rfci, {81, 103, 60}, 1);
-template (value) IuUP_RabFlowCombination t_IuUP_RFC_AMR_SID(IuUP_RFCI rfci) := t_IuUP_RFC(rfci, {34, 0, 0}, 7);
-
+template (value) IuUP_RabFlowCombination t_IuUP_RFC_AMR_SID(IuUP_RFCI rfci) := t_IuUP_RFC(rfci, {39, 0, 0}, 7);
+template (value) IuUP_RabFlowCombination t_IuUP_RFC_AMR_NO_DATA(IuUP_RFCI rfci) := t_IuUP_RFC(rfci, {0, 0, 0}, 1);
+
+
+const IuUP_RabFlowCombinationList c_IuUP_Config_RabFlowCombination_def := {
+ {
+ rfci := 0,
+ sub_flow_bits := {81, 103, 60},
+ ipti := 1
+ }, {
+ rfci := 1,
+ sub_flow_bits := {39, 0, 0},
+ ipti := 7
+ }, {
+ rfci := 2,
+ sub_flow_bits := {0, 0, 0},
+ ipti := 1
+ }
+};
type record IuUP_Config {
/* actively send INIT (true) or only passively respond (false) */
boolean active_init,
boolean data_pdu_type_0,
/* RAB Flow Combinations */
- record of IuUP_RabFlowCombination rab_flow_combs
+ IuUP_RabFlowCombinationList rab_flow_combs
};
+template (value) IuUP_Config t_IuUP_Config(boolean active_init := true,
+ boolean data_pdu_type_0 := true,
+ template (value) IuUP_RabFlowCombinationList rab_flow_combs :=
+ c_IuUP_Config_RabFlowCombination_def) := {
+ active_init := active_init,
+ data_pdu_type_0 := true,
+ rab_flow_combs := rab_flow_combs
+}
+
+const IuUP_Config c_IuUP_Config_def := {
+ active_init := true,
+ data_pdu_type_0 := true,
+ rab_flow_combs := c_IuUP_Config_RabFlowCombination_def
+}
+
type enumerated IuUP_Em_State {
ST_INIT,
ST_DATA_TRANSFER_READY
};
-
-
type record IuUP_Entity {
IuUP_Config cfg,
IuUP_Em_State state,
@@ -59,12 +90,8 @@ type record IuUP_Entity {
IuUP_PDU pending_tx_pdu optional
};
-template (value) IuUP_Entity t_IuUP_Entity(boolean act_init) := {
- cfg := {
- active_init := act_init,
- data_pdu_type_0 := true,
- rab_flow_combs := { t_IuUP_RFC_AMR_12_2(0), t_IuUP_RFC_AMR_SID(1) }
- },
+template (value) IuUP_Entity t_IuUP_Entity(template (value) IuUP_Config cfg) := {
+ cfg := cfg,
state := ST_INIT,
tx_next_frame_nr := 0,
rx_last_frame_nr := omit,
@@ -100,11 +127,12 @@ function f_IuUP_Em_rx_decaps(inout IuUP_Entity st, octetstring inp) return octet
} else {
/* store an INIT_ACK to be transmitted later */
st.pending_tx_pdu := valueof(ts_IuUP_INIT_ACK(pdu.type_14.frame_nr,
- pdu.type_14.iuup_version));
+ pdu.type_14.u.proc.hdr.iuup_version));
}
} else if (match(pdu, tr_IuUP_INIT_ACK)) {
if (st.cfg.active_init == true) {
log("IuUP INIT_ACK Received");
+ st.pending_tx_pdu := omit; /* Drop pending Init retrans */
st.state := ST_DATA_TRANSFER_READY;
} else {
setverdict(fail, "INIT_ACK received in PASSIVE role");
@@ -119,13 +147,59 @@ function f_IuUP_Em_rx_decaps(inout IuUP_Entity st, octetstring inp) return octet
self.stop;
}
+private function f_ts_IuUP_INIT(inout IuUP_Entity st) return IuUP_PDU
+{
+ var IuUP_PDU pdu;
+ var uint4_t data_pdu_type;
+ var template (omit) IuUP_InitRfci rfci := omit;
+ var IuUP_IPTI_List IPTIs := {};
+ var uint4_t num_rfci := lengthof(st.cfg.rab_flow_combs);
+
+ if (st.cfg.data_pdu_type_0 == true) {
+ data_pdu_type := 0;
+ } else {
+ data_pdu_type := 1;
+ }
+
+ /* Build RFCI list: */
+ for (var integer remain := num_rfci; remain > 0; remain := remain - 1) {
+ var IuUP_RabFlowCombination comb := st.cfg.rab_flow_combs[remain - 1];
+ var boolean lri := false;
+ if (remain == num_rfci) {
+ lri := true;
+ }
+ rfci := ts_IuUP_InitRfci(lri, false, comb.rfci, comb.sub_flow_bits, omit, rfci)
+ }
+
+ /* Build IPTI list: */
+ for (var integer i := 0; i < num_rfci; i := i + 1) {
+ IPTIs := IPTIs & { st.cfg.rab_flow_combs[i].ipti };
+ }
+
+ template (value) IuUP_PDU14_ProcSending_INIT tpl := ts_IuUP_PDU14_ProcSending_INIT(
+ ti := true,
+ subflows_per_rfci := num_rfci,
+ chain_ind := false,
+ rfci := rfci,
+ IPTIs := IPTIs,
+ versions_supported := '0000000000000001'B,
+ data_pdu_type := data_pdu_type
+ );
+ pdu := valueof(ts_IuUP_INIT(tpl));
+ return pdu;
+}
+
function f_IuUP_Em_tx_encap(inout IuUP_Entity st, in octetstring payload) return octetstring {
var IuUP_PDU pdu;
select (st.state) {
case (ST_INIT) {
if (st.cfg.active_init) {
- /* send INIT */
- pdu := valueof(ts_IuUP_INIT('160051673C01270000820000001710000100'O));
+ if (not isvalue(st.pending_tx_pdu)) {
+ /* send INIT */
+ pdu := f_ts_IuUP_INIT(st);
+ st.pending_tx_pdu := pdu;
+ } /* else: wait for INIT-ACK return ''O at the end */
+
} else {
/* wait for INIT */
if (isvalue(st.pending_tx_pdu)) {
@@ -143,7 +217,7 @@ function f_IuUP_Em_tx_encap(inout IuUP_Entity st, in octetstring payload) return
} else {
pdu := valueof(ts_IuUP_Type1(st.tx_next_frame_nr, 0, payload));
}
- st.tx_next_frame_nr := st.tx_next_frame_nr + 1;
+ st.tx_next_frame_nr := (st.tx_next_frame_nr + 1) mod 16;
}
}
if (isvalue(pdu)) {
diff --git a/library/IuUP_Types.ttcn b/library/IuUP_Types.ttcn
index b822ddf1..e99dfef7 100644
--- a/library/IuUP_Types.ttcn
+++ b/library/IuUP_Types.ttcn
@@ -91,6 +91,8 @@ type enumerated IuUP_ErrorCause {
/* See TS 25.415 6.6.3.18 */
type uint8_t IuUP_TimeAlignment;
+/* See TS 25.415 6.6.3.24 */
+type uint4_t IuUP_IPTI;
/* See TS 25.415 6.6.2.1 */
type record IuUP_PDU_Type_0 {
@@ -119,45 +121,57 @@ type record IuUP_PDU_Type_14 {
IuUP_PDU_Type pdu_type,
IuUP_AckNack ack_nack,
uint2_t frame_nr,
+ IuUP_PDU14_Union u
+} with { variant (u) "CROSSTAG(proc, ack_nack=IuUP_ACKNACK_CTRL;
+ ack, ack_nack=IuUP_ACKNACK_ACK;
+ nack, ack_nack=IuUP_ACKNACK_NACK)"
+};
+
+type record IuUP_PDU_Type_14_Common_Hdr {
uint4_t iuup_version,
IuUP_ProcedureIndicator procedure_ind,
uint6_t header_crc,
- uint10_t payload_crc,
- IuUP_PDU14_Union u
-} with { variant (u) "CROSSTAG( proc_sending, ack_nack=IuUP_ACKNACK_CTRL;
- ack, ack_nack=IuUP_ACKNACK_ACK;
- nack, ack_nack=IuUP_ACKNACK_NACK)"
+ uint10_t payload_crc
+};
+
+type union IuUP_PDU14_Union {
+ IuUP_PDU14_ProcSending proc,
+ IuUP_PDU14_ACK ack,
+ IuUP_PDU14_NACK nack
};
/* 6.6.2.3.1 Figure 21 */
type record IuUP_PDU14_ProcSending {
- octetstring payload
+ IuUP_PDU_Type_14_Common_Hdr hdr,
+ IuUP_PDU14_ProcSendingUnion u
+} with {
+ variant (u) "CROSSTAG(init, hdr.procedure_ind=IuUP_PRI_INITIALIZATION;
+ rate_ctrl, hdr.procedure_ind=IuUP_PRI_RATE_CONTROL;
+ time_alignment, hdr.procedure_ind=IuUP_PRI_TIME_ALIGNMENT;
+ error_event, hdr.procedure_ind=IuUP_PRI_ERROR_EVENT;
+ other, OTHERWISE)"
};
/* 6.6.2.3.2 Figure 22 */
type record IuUP_PDU14_ACK {
+ IuUP_PDU_Type_14_Common_Hdr hdr,
octetstring spare_ext optional
};
/* 6.6.2.3.3 Figure 23 */
type record IuUP_PDU14_NACK {
+ IuUP_PDU_Type_14_Common_Hdr hdr,
IuUP_ErrorCause err_cause,
BIT2 spare,
octetstring spare_ext optional
};
-type union IuUP_PDU14_Union {
- IuUP_PDU14_ProcSending proc_sending,
- IuUP_PDU14_ACK ack,
- IuUP_PDU14_NACK nack
-};
-
type union IuUP_PDU14_ProcSendingUnion {
IuUP_PDU14_ProcSending_INIT init,
IuUP_PDU14_ProcSending_RATE_CTRL rate_ctrl,
- IuUP_PDU14_ProcSending_RATE_CTRL rate_ctrl_ack,
IuUP_PDU14_ProcSending_TIME_ALIGNMENT time_alignment,
- IuUP_PDU14_ProcSending_ERROR_EVENT error_event
+ IuUP_PDU14_ProcSending_ERROR_EVENT error_event,
+ octetstring other
};
/* 6.6.2.3.4.1 Initialisation */
@@ -166,21 +180,35 @@ type record IuUP_PDU14_ProcSending_INIT {
boolean ti,
uint3_t subflows_per_rfci,
boolean chain_ind,
-
- /* FIXME: Further decode */
- octetstring payload
+ IuUP_InitRfci rfci,
+ IuUP_IPTI_List IPTIs optional,
+ BIT16 versions_supported,
+ uint4_t data_pdu_type,
+ BIT4 spare2
+} with {
+ variant (IPTIs) "PRESENCE(ti=true)"
+ variant (versions_supported) "BITORDER(lsb)"
+ variant (versions_supported) "BYTEORDER(last)"
};
type record IuUP_InitRfci {
boolean lri,
boolean li,
- IuUP_RFCI rfci,
+ IuUP_RFCI rfci_id,
RecOfU8 len8 optional,
- RecOfU16 len16 optional
-} with { variant (len8) "PRESENCE(li=false)";
- variant (len16) "PRESENCE(li=true)"
+ RecOfU16 len16 optional,
+ IuUP_InitRfci rfci optional
+} with {
+ variant (len8) "PRESENCE(li=false)";
+ variant (len16) "PRESENCE(li=true)"
+ variant (rfci) "PRESENCE(lri=false)"
};
-type record of uint8_t RecOfU8;
-type record of uint16_t RecOfU16;
+type record of IuUP_IPTI IuUP_IPTI_List with {
+ variant "FIELDLENGTH(3)"
+ variant "PADDING(yes)"
+ };
+type record of uint8_t RecOfU8 with { variant "FIELDLENGTH(3)" };
+type record of uint16_t RecOfU16 with { variant "FIELDLENGTH(3)" };
+type record of IuUP_InitRfci IuUP_InitRfciList;
/* 6.6.2.3.4.2.1 Rate Control procedure */
type record IuUP_PDU14_ProcSending_RATE_CTRL {
@@ -226,12 +254,14 @@ template IuUP_PDU ts_IuUP_INIT_ACK(uint2_t frame_nr, uint4_t version) := {
pdu_type := 14,
ack_nack := IuUP_ACKNACK_ACK,
frame_nr := frame_nr,
- iuup_version := version,
- procedure_ind := IuUP_PRI_INITIALIZATION,
- header_crc := 0,
- payload_crc := 0,
u := {
ack := {
+ hdr := {
+ iuup_version := version,
+ procedure_ind := IuUP_PRI_INITIALIZATION,
+ header_crc := 0,
+ payload_crc := 0
+ },
spare_ext := omit
}
}
@@ -243,48 +273,113 @@ template IuUP_PDU tr_IuUP_INIT_ACK(template uint2_t frame_nr := ?, template uint
pdu_type := 14,
ack_nack := IuUP_ACKNACK_ACK,
frame_nr := frame_nr,
- iuup_version := version,
- procedure_ind := IuUP_PRI_INITIALIZATION,
- header_crc := ?,
- payload_crc := ?,
u := {
ack := {
+ hdr := {
+ iuup_version := version,
+ procedure_ind := IuUP_PRI_INITIALIZATION,
+ header_crc := ?,
+ payload_crc := ?
+ },
spare_ext := omit
}
}
}
};
-template IuUP_PDU ts_IuUP_INIT(octetstring payload, uint2_t frame_nr := 0, uint4_t version := 0) := {
+template (value) IuUP_InitRfci ts_IuUP_InitRfci(
+ template (value) boolean lri,
+ template (value) boolean li,
+ template (value) IuUP_RFCI rfci_id,
+ template (omit) RecOfU8 len8,
+ template (omit) RecOfU16 len16,
+ template (omit) IuUP_InitRfci rfci := omit) := {
+ lri := lri,
+ li := li,
+ rfci_id := rfci_id,
+ len8 := len8,
+ len16 := len16,
+ rfci := rfci
+}
+
+template (value) IuUP_PDU14_ProcSending_INIT ts_IuUP_PDU14_ProcSending_INIT(
+ template (value) boolean ti := true,
+ template (value) uint3_t subflows_per_rfci := 3,
+ template (value) boolean chain_ind := false,
+ template (value) IuUP_InitRfci rfci := ts_IuUP_InitRfci(false, false, 0, {81, 103, 60}, omit,
+ ts_IuUP_InitRfci(false, false, 1, {39, 0, 0}, omit,
+ ts_IuUP_InitRfci(true, false, 2, {0, 0, 0}, omit, omit))),
+ template (omit) IuUP_IPTI_List IPTIs := {1, 7, 1},
+ template (value) BIT16 versions_supported := '0000000000000001'B,
+ template (value) uint4_t data_pdu_type := 0) := {
+ spare := '000'B,
+ ti := ti,
+ subflows_per_rfci := subflows_per_rfci,
+ chain_ind := chain_ind,
+ rfci := rfci,
+ IPTIs := IPTIs,
+ versions_supported := versions_supported,
+ data_pdu_type := data_pdu_type,
+ spare2 := '0000'B
+}
+
+template (present) IuUP_PDU14_ProcSending_INIT tr_IuUP_PDU14_ProcSending_INIT(
+ template (present) boolean ti := ?,
+ template (present) uint3_t subflows_per_rfci := ?,
+ template (present) boolean chain_ind := ?,
+ template (present) IuUP_InitRfci rfci := ?,
+ template IuUP_IPTI_List IPTIs := *,
+ template (present) BIT16 versions_supported := ?,
+ template (present) uint4_t data_pdu_type := ?) := {
+ spare := '000'B,
+ ti := ti,
+ subflows_per_rfci := subflows_per_rfci,
+ chain_ind := chain_ind,
+ rfci := rfci,
+ IPTIs := IPTIs,
+ versions_supported := versions_supported,
+ data_pdu_type := data_pdu_type,
+ spare2 := '0000'B
+}
+
+template (value) IuUP_PDU ts_IuUP_INIT(template (value) IuUP_PDU14_ProcSending_INIT init, uint2_t frame_nr := 0, uint4_t version := 0) := {
type_14 := {
pdu_type := 14,
ack_nack := IuUP_ACKNACK_CTRL,
frame_nr := frame_nr,
- iuup_version := version,
- procedure_ind := IuUP_PRI_INITIALIZATION,
- header_crc := 0,
- payload_crc := 0,
u := {
- proc_sending := {
- payload := payload
+ proc := {
+ hdr := {
+ iuup_version := version,
+ procedure_ind := IuUP_PRI_INITIALIZATION,
+ header_crc := 0,
+ payload_crc := 0
+ },
+ u := {
+ init := init
+ }
}
}
}
};
-template IuUP_PDU tr_IuUP_INIT(template octetstring payload := ?, template uint2_t frame_nr := ?,
+template IuUP_PDU tr_IuUP_INIT(template (present) IuUP_PDU14_ProcSending_INIT init := ?, template octetstring payload := ?, template uint2_t frame_nr := ?,
template uint4_t version := ?) := {
type_14 := {
pdu_type := 14,
ack_nack := IuUP_ACKNACK_CTRL,
frame_nr := frame_nr,
- iuup_version := version,
- procedure_ind := IuUP_PRI_INITIALIZATION,
- header_crc := ?,
- payload_crc := ?,
u := {
- proc_sending := {
- payload := payload
+ proc := {
+ hdr := {
+ iuup_version := version,
+ procedure_ind := IuUP_PRI_INITIALIZATION,
+ header_crc := ?,
+ payload_crc := ?
+ },
+ u := {
+ init := init
+ }
}
}
}
diff --git a/library/Iuh_CodecPort.ttcn b/library/Iuh_CodecPort.ttcn
new file mode 100644
index 00000000..75c45dda
--- /dev/null
+++ b/library/Iuh_CodecPort.ttcn
@@ -0,0 +1,137 @@
+module Iuh_CodecPort {
+
+/* Simple Iuh Codec Port, translating between raw SCTP primitives with
+ * octetstring payload towards the IPL4asp provider, and Iuh primitives
+ * which carry the decoded Iuh data types as payload.
+ *
+ * (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@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
+ */
+
+ import from IPL4asp_PortType all;
+ import from IPL4asp_Types all;
+ import from HNBAP_PDU_Descriptions all;
+ import from HNBAP_Types all;
+ import from RUA_PDU_Descriptions all;
+ import from RUA_Types all;
+ import from Iuh_Types all;
+
+ type record Iuh_RecvFrom {
+ ConnectionId connId,
+ HostName remName,
+ PortNumber remPort,
+ HostName locName,
+ PortNumber locPort,
+ Iuh_PDU msg
+ };
+
+ template Iuh_RecvFrom t_Iuh_RecvFrom(template Iuh_PDU msg) := {
+ connId := ?,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := msg
+ }
+
+ template Iuh_RecvFrom t_Iuh_RecvFrom_HNBAP(template HNBAP_PDU hnbap_msg := ?) := {
+ connId := ?,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := {
+ hnbap := hnbap_msg
+ }
+ }
+
+ template Iuh_RecvFrom t_Iuh_RecvFrom_RUA(template RUA_PDU rua_msg := ?) := {
+ connId := ?,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := {
+ rua := rua_msg
+ }
+ }
+
+ type record Iuh_Send {
+ ConnectionId connId,
+ Iuh_PDU msg
+ };
+
+ template Iuh_Send t_Iuh_Send_HNBAP(template ConnectionId connId, template HNBAP_PDU hnbap_msg) := {
+ connId := connId,
+ msg := {
+ hnbap := hnbap_msg
+ }
+ }
+
+ template Iuh_Send t_Iuh_Send_RUA(template ConnectionId connId, template RUA_PDU rua_msg) := {
+ connId := connId,
+ msg := {
+ rua := rua_msg
+ }
+ }
+
+ private function IPL4_to_Iuh_RecvFrom(in ASP_RecvFrom pin, out Iuh_RecvFrom pout) {
+ pout.connId := pin.connId;
+ pout.remName := pin.remName;
+ pout.remPort := pin.remPort;
+ pout.locName := pin.locName;
+ pout.locPort := pin.locPort;
+ select (pin.proto.sctp.sinfo_ppid) {
+ case (19) {
+ pout.msg.rua := dec_RUA_PDU(pin.msg);
+ }
+ case (20) {
+ pout.msg.hnbap := dec_HNBAP_PDU(pin.msg);
+ }
+ case else {
+ pout.msg.payload := pin.msg;
+ }
+ }
+ } with { extension "prototype(fast)" };
+
+ private function Iuh_to_IPL4_Send(in Iuh_Send pin, out ASP_Send pout) {
+ var integer sctp_ppid;
+ if (ischosen(pin.msg.rua)) {
+ sctp_ppid := 19;
+ pout.msg := enc_RUA_PDU(pin.msg.rua);
+ } else if (ischosen(pin.msg.hnbap)) {
+ sctp_ppid := 20;
+ pout.msg := enc_HNBAP_PDU(pin.msg.hnbap);
+ } else { /*TODO: abort?*/
+ sctp_ppid := 0;
+ pout.msg := pin.msg.payload;
+ }
+ pout.connId := pin.connId;
+ pout.proto := {
+ sctp := {
+ sinfo_stream := omit,
+ sinfo_ppid := sctp_ppid,
+ remSocks := omit,
+ assocId := omit
+ }
+ };
+ } with { extension "prototype(fast)" };
+
+ type port Iuh_CODEC_PT message {
+ out Iuh_Send;
+ in Iuh_RecvFrom,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+ } with { extension "user IPL4asp_PT
+ out(Iuh_Send -> ASP_Send:function(Iuh_to_IPL4_Send))
+ in(ASP_RecvFrom -> Iuh_RecvFrom: function(IPL4_to_Iuh_RecvFrom);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)"
+ }
+}
diff --git a/library/NS_CodecPort_CtrlFunct.ttcn b/library/Iuh_CodecPort_CtrlFunct.ttcn
index cc77dda1..c0c7003f 100644
--- a/library/NS_CodecPort_CtrlFunct.ttcn
+++ b/library/Iuh_CodecPort_CtrlFunct.ttcn
@@ -1,10 +1,10 @@
-module NS_CodecPort_CtrlFunct {
+module Iuh_CodecPort_CtrlFunct {
- import from NS_CodecPort all;
+ import from Iuh_CodecPort all;
import from IPL4asp_Types all;
external function f_IPL4_listen(
- inout NS_CODEC_PT portRef,
+ inout Iuh_CODEC_PT portRef,
in HostName locName,
in PortNumber locPort,
in ProtoTuple proto,
@@ -12,7 +12,7 @@ module NS_CodecPort_CtrlFunct {
) return Result;
external function f_IPL4_connect(
- inout NS_CODEC_PT portRef,
+ inout Iuh_CODEC_PT portRef,
in HostName remName,
in PortNumber remPort,
in HostName locName,
@@ -23,22 +23,21 @@ module NS_CodecPort_CtrlFunct {
) return Result;
external function f_IPL4_close(
- inout NS_CODEC_PT portRef,
+ inout Iuh_CODEC_PT portRef,
in ConnectionId id,
in ProtoTuple proto := { unspecified := {} }
) return Result;
external function f_IPL4_setUserData(
- inout NS_CODEC_PT portRef,
+ inout Iuh_CODEC_PT portRef,
in ConnectionId id,
in UserData userData
) return Result;
external function f_IPL4_getUserData(
- inout NS_CODEC_PT portRef,
+ inout Iuh_CODEC_PT portRef,
in ConnectionId id,
out UserData userData
) return Result;
}
-
diff --git a/library/Iuh_CodecPort_CtrlFunctDef.cc b/library/Iuh_CodecPort_CtrlFunctDef.cc
new file mode 100644
index 00000000..2f08deca
--- /dev/null
+++ b/library/Iuh_CodecPort_CtrlFunctDef.cc
@@ -0,0 +1,55 @@
+#include "IPL4asp_PortType.hh"
+#include "Iuh_CodecPort.hh"
+#include "IPL4asp_PT.hh"
+
+namespace Iuh__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__IPL4__listen(
+ Iuh__CodecPort::Iuh__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__connect(
+ Iuh__CodecPort::Iuh__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& remName,
+ const IPL4asp__Types::PortNumber& remPort,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+ locName, locPort, connId, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__close(
+ Iuh__CodecPort::Iuh__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto)
+ {
+ return f__IPL4__PROVIDER__close(portRef, connId, proto);
+ }
+
+ IPL4asp__Types::Result f__IPL4__setUserData(
+ Iuh__CodecPort::Iuh__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+ }
+
+ IPL4asp__Types::Result f__IPL4__getUserData(
+ Iuh__CodecPort::Iuh__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+ }
+
+}
diff --git a/library/Iuh_Emulation.ttcn b/library/Iuh_Emulation.ttcn
new file mode 100644
index 00000000..e05afe55
--- /dev/null
+++ b/library/Iuh_Emulation.ttcn
@@ -0,0 +1,225 @@
+module Iuh_Emulation {
+
+/* Iuh Emulation, runs on top of Iuh_CodecPort. It multiplexes/demultiplexes
+ * HNBAP and RUA.
+ *
+ * The Iuh_Emulation.main() function processes Iuh primitives from the Iuh
+ * socket via the Iuh_CodecPort, and dispatches them to HNBAP/RUA ports.
+ *
+ * (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@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
+ */
+
+import from Iuh_CodecPort all;
+import from Iuh_CodecPort_CtrlFunct all;
+import from HNBAP_Types all;
+import from HNBAP_Constants all;
+import from HNBAP_PDU_Contents all;
+import from HNBAP_PDU_Descriptions all;
+import from HNBAP_IEs all;
+import from HNBAP_Templates all;
+import from RUA_Types all;
+import from RUA_Constants all;
+import from RUA_PDU_Contents all;
+import from RUA_PDU_Descriptions all;
+import from RUA_IEs all;
+import from RUA_Templates all;
+import from Iuh_Types all;
+
+import from General_Types all;
+import from Misc_Helpers all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from DNS_Helpers all;
+
+/* General "base class" component definition, of which specific implementations
+ * derive themselves by means of the "extends" feature */
+type component Iuh_ConnHdlr {
+ port HNBAP_PT HNBAP;
+ port RUA_PT RUA;
+};
+
+type enumerated IUHEM_EventUpDown {
+ IUHEM_EVENT_DOWN,
+ IUHEM_EVENT_UP
+}
+
+/* an event indicating us whether or not a connection is physically up or down. */
+type union IUHEM_Event {
+ IUHEM_EventUpDown up_down
+}
+
+type port HNBAP_PT message {
+ inout HNBAP_PDU, IUHEM_Event;
+} with { extension "internal" };
+type port RUA_PT message {
+ inout RUA_PDU, IUHEM_Event;
+} with { extension "internal" };
+
+type component Iuh_Emulation_CT {
+ /* Port facing to the SCTP SUT */
+ port Iuh_CODEC_PT Iuh;
+ /* Port facing to user upper side stack: */
+ port HNBAP_PT HNBAP;
+ port RUA_PT RUA;
+
+ var Iuh_conn_parameters g_pars;
+ var charstring g_Iuh_id;
+ var integer g_self_conn_id := -1;
+ var IPL4asp_Types.ConnectionId g_last_conn_id := -1; /* server only */
+}
+
+type record Iuh_conn_parameters {
+ HostName remote_ip,
+ PortNumber remote_sctp_port,
+ HostName local_ip,
+ PortNumber local_sctp_port
+}
+
+function tr_Iuh_RecvFrom_R(template Iuh_PDU msg)
+runs on Iuh_Emulation_CT return template Iuh_RecvFrom {
+ var template Iuh_RecvFrom mrf := {
+ connId := ?,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := msg
+ }
+ return mrf;
+}
+
+private template (value) SctpTuple ts_SCTP(template (omit) integer ppid := omit) := {
+ sinfo_stream := omit,
+ sinfo_ppid := ppid,
+ remSocks := omit,
+ assocId := omit
+};
+
+private template PortEvent tr_SctpAssocChange := {
+ sctpEvent := {
+ sctpAssocChange := ?
+ }
+}
+private template PortEvent tr_SctpPeerAddrChange := {
+ sctpEvent := {
+ sctpPeerAddrChange := ?
+ }
+}
+
+private function emu_is_server() runs on Iuh_Emulation_CT return boolean {
+ return g_pars.remote_sctp_port == -1
+}
+
+/* Resolve TCP/IP connection identifier depending on server/client mode */
+private function f_iuh_conn_id() runs on Iuh_Emulation_CT
+return IPL4asp_Types.ConnectionId {
+ var IPL4asp_Types.ConnectionId conn_id;
+
+ if (not emu_is_server()) {
+ conn_id := g_self_conn_id;
+ } else {
+ conn_id := g_last_conn_id;
+ }
+
+ if (conn_id == -1) { /* Just to be sure */
+ f_shutdown(__FILE__, __LINE__, fail, "Connection is not established");
+ }
+
+ return conn_id;
+}
+
+private function f_send_IUHEM_Event(template (value) IUHEM_Event evt) runs on Iuh_Emulation_CT {
+ if (HNBAP.checkstate("Connected")) {
+ HNBAP.send(evt);
+ }
+}
+
+function main(Iuh_conn_parameters p, charstring id) runs on Iuh_Emulation_CT {
+ var Result res;
+ g_pars := p;
+ g_Iuh_id := id;
+
+ map(self:Iuh, system:Iuh_CODEC_PT);
+ if (emu_is_server()) {
+ res := Iuh_CodecPort_CtrlFunct.f_IPL4_listen(Iuh, p.local_ip, p.local_sctp_port, { sctp := valueof(ts_SCTP) });
+ } else {
+ res := Iuh_CodecPort_CtrlFunct.f_IPL4_connect(Iuh, p.remote_ip, p.remote_sctp_port,
+ p.local_ip, p.local_sctp_port, -1, { sctp := valueof(ts_SCTP) });
+ }
+ if (not ispresent(res.connId)) {
+ f_shutdown(__FILE__, __LINE__, fail, "Could not connect Iuh socket, check your configuration");
+ }
+ g_self_conn_id := res.connId;
+
+ /* notify user about SCTP establishment */
+ if (p.remote_sctp_port != -1) {
+ f_send_IUHEM_Event(IUHEM_Event:{up_down:=IUHEM_EVENT_UP});
+ }
+
+ while (true) {
+ var Iuh_RecvFrom mrf;
+ var HNBAP_PDU hnbap_msg;
+ var RUA_PDU rua_msg;
+ var ASP_Event asp_evt;
+
+ alt {
+ /* HNBAP from client: pass on transparently */
+ [] HNBAP.receive(HNBAP_PDU:?) -> value hnbap_msg {
+ /* Pass message through */
+ Iuh.send(t_Iuh_Send_HNBAP(f_iuh_conn_id(), hnbap_msg));
+ }
+ /* RUA from client: pass on transparently */
+ [] RUA.receive(RUA_PDU:?) -> value rua_msg {
+ /* Pass message through */
+ Iuh.send(t_Iuh_Send_RUA(f_iuh_conn_id(), rua_msg));
+ }
+
+ /* Iuh received from peer (HNBGW or HnodeB) */
+ [] Iuh.receive(tr_Iuh_RecvFrom_R(?)) -> value mrf {
+ if (not match(mrf.connId, f_iuh_conn_id())) {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Received message from unexpected conn_id!", mrf));
+ }
+
+ if (match(mrf, t_Iuh_RecvFrom_HNBAP(?))) {
+ HNBAP.send(mrf.msg.hnbap);
+ } else if (match(mrf, t_Iuh_RecvFrom_RUA(?))) {
+ RUA.send(mrf.msg.rua);
+ } else {
+ /* TODO: special handling, as it contains multiple HNB connection ids */
+ f_shutdown(__FILE__, __LINE__, fail, log2str("UNEXPECTED MESSAGE RECEIVED!", mrf));
+ }
+ }
+ [] Iuh.receive(tr_SctpAssocChange) { }
+ [] Iuh.receive(tr_SctpPeerAddrChange) { }
+
+ /* server only */
+ [] Iuh.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
+ if (not emu_is_server()) {
+ f_shutdown(__FILE__, __LINE__, fail, log2str("Unexpected event receiver in client mode", asp_evt));
+ }
+ g_last_conn_id := asp_evt.connOpened.connId;
+ log("Established a new Iuh connection (conn_id=", g_last_conn_id, ")");
+
+ f_send_IUHEM_Event(IUHEM_Event:{up_down:=IUHEM_EVENT_UP}); /* TODO: send g_last_conn_id */
+ }
+
+ [] Iuh.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
+ log("Iuh: Closed");
+ g_self_conn_id := -1;
+ f_send_IUHEM_Event(IUHEM_Event:{up_down:=IUHEM_EVENT_DOWN}); /* TODO: send asp_evt.connClosed.connId */
+ if (not emu_is_server()) {
+ self.stop;
+ }
+ }
+ }
+ }
+}
+
+}
diff --git a/library/Iuh_Types.ttcn b/library/Iuh_Types.ttcn
new file mode 100644
index 00000000..17f9c5f2
--- /dev/null
+++ b/library/Iuh_Types.ttcn
@@ -0,0 +1,36 @@
+/* Osmocom Iuh Interface Types
+ * (C) 2021 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@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
+ */
+
+ /* Iuh Codec Port Types
+ *
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * 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 Iuh_Types {
+
+import from HNBAP_PDU_Descriptions all;
+import from HNBAP_Types all;
+import from RUA_PDU_Descriptions all;
+import from RUA_Types all;
+
+type union Iuh_PDU {
+ HNBAP_PDU hnbap,
+ RUA_PDU rua,
+ octetstring payload
+}
+
+};
diff --git a/library/L1CTL_PortType.ttcn b/library/L1CTL_PortType.ttcn
index 94f807aa..07c536ce 100644
--- a/library/L1CTL_PortType.ttcn
+++ b/library/L1CTL_PortType.ttcn
@@ -12,11 +12,12 @@
module L1CTL_PortType {
import from L1CTL_Types all;
import from UD_PortType all;
+ import from Socket_API_Definitions all;
import from UD_Types all;
import from Osmocom_Types all;
- import from Osmocom_Types all;
import from GSM_Types all;
import from GSM_RR_Types all;
+ import from GSM_RestOctets all;
import from L1CTL_PortType_CtrlFunct all;
type record L1CTL_connect {
@@ -32,7 +33,7 @@ module L1CTL_PortType {
charstring m_l1ctl_sock_path := "/tmp/osmocom_l2";
}
- function f_L1CTL_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
+ function f_L1CTL_getMsgLen(in octetstring stream, inout Socket_API_Definitions.ro_integer args) return integer {
var integer stream_len := lengthof(stream);
var integer len;
if (stream_len < 2) {
@@ -42,10 +43,36 @@ module L1CTL_PortType {
return len;
}
- function f_L1CTL_FBSB(L1CTL_PT pt, Arfcn arfcn, L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED, integer rxlev_exp := 57) {
+ function f_L1CTL_rx_data(L1CTL_PT pt,
+ template (present) RslChannelNr chan_nr := ?,
+ template (present) RslLinkId link_id := ?)
+ return L1ctlMessage {
+ var L1ctlMessage dl;
+ timer T := 2.0;
+
+ T.start;
+ alt {
+ [] pt.receive(tr_L1CTL_DATA_IND(chan_nr, link_id)) -> value dl {
+ return dl;
+ }
+ [] pt.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for L1CTL DATA.ind");
+ mtc.stop;
+ }
+ }
+
+ /* Unreachable, make TITAN happy */
+ return dl;
+ }
+
+ function f_L1CTL_FBSB(L1CTL_PT pt, GsmBandArfcn arfcn,
+ L1ctlCcchMode ccch_mode := CCCH_MODE_COMBINED,
+ integer rxlev_exp := 57)
+ {
timer T := 15.0;
for (var integer i := 0; i < 10; i := i+1) {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
pt.send(ts_L1CTL_FBSB_REQ(arfcn, valueof(t_L1CTL_FBSB_F_ALL), 0, ccch_mode, rxlev_exp));
T.start
alt {
@@ -80,22 +107,37 @@ module L1CTL_PortType {
}
}
+ function f_L1CTL_TCH_MODE(L1CTL_PT pt,
+ template (value) L1ctlMessage tch_mode_req_tmpl := ts_L1CTL_TCH_MODE_REQ) {
+ timer T := 2.0;
+ pt.send(tch_mode_req_tmpl);
+ T.start;
+ alt {
+ [] pt.receive(tr_L1CTL_MsgType(L1CTL_TCH_MODE_CONF)) { }
+ [] pt.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for L1CTL_TCH_MODE_CONF");
+ mtc.stop;
+ }
+ }
+ }
+
function f_L1CTL_RACH(L1CTL_PT pt, uint8_t ra, uint8_t combined := 1, uint16_t offset := 0,
template (value) RslChannelNr chan_nr := ts_RslChanNr_RACH(0),
template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0))
return GsmFrameNumber {
- var L1ctlDlMessage rc;
+ var L1ctlMessage rc;
var GsmFrameNumber fn;
timer T := 2.0;
T.start
pt.send(ts_L1CTL_RACH_REQ(ra, combined, offset, chan_nr, link_id))
alt {
- [] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
- [] pt.receive { repeat; };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for L1CTL_RACH_CONF");
- mtc.stop;
- }
+ [] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
+ [] pt.receive { repeat; };
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for L1CTL_RACH_CONF");
+ mtc.stop;
+ }
}
return fn;
}
@@ -104,19 +146,19 @@ module L1CTL_PortType {
L1CTL_PT pt, uint16_t ra11, L1ctlRachSynchSeq seq,
uint8_t combined := 1, uint16_t offset := 0
) return GsmFrameNumber {
- var L1ctlDlMessage rc;
+ var L1ctlMessage rc;
var GsmFrameNumber fn;
timer T := 2.0;
T.start;
pt.send(ts_L1CTL_EXT_RACH_REQ(ra11, seq, combined, offset));
alt {
- [] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
- [] pt.receive { repeat; };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for (extended) L1CTL_RACH_CONF");
- mtc.stop;
- }
+ [] pt.receive(tr_L1CTL_RACH_CONF) -> value rc { fn := rc.dl_info.frame_nr };
+ [] pt.receive { repeat; };
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for (extended) L1CTL_RACH_CONF");
+ mtc.stop;
+ }
}
return fn;
@@ -128,7 +170,7 @@ module L1CTL_PortType {
function f_L1CTL_WAIT_IMM_ASS(L1CTL_PT pt, uint8_t ra, GsmFrameNumber rach_fn) return ImmediateAssignment {
var template GsmRrMessage rr_imm_ass;
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var GsmRrMessage rr;
timer T := 10.0;
@@ -140,20 +182,20 @@ module L1CTL_PortType {
T.start;
alt {
- [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
- rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
- log("PCH/AGCH DL RR: ", rr);
- if (match(rr, rr_imm_ass)) {
- log("Received IMM.ASS for our RACH!");
- } else {
- repeat;
- }
- };
- [] pt.receive { repeat };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for IMM ASS");
- mtc.stop;
- }
+ [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
+ rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
+ log("PCH/AGCH DL RR: ", rr);
+ if (match(rr, rr_imm_ass)) {
+ log("Received IMM.ASS for our RACH!");
+ } else {
+ repeat;
+ }
+ };
+ [] pt.receive { repeat };
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for IMM ASS");
+ mtc.stop;
+ }
}
T.stop;
return rr.payload.imm_ass;
@@ -162,46 +204,31 @@ module L1CTL_PortType {
function f_L1CTL_WAIT_IMM_ASS_TBF_DL(L1CTL_PT pt, GprsTlli tlli) return ImmediateAssignment {
var template PacketDlAssign dl_ass := tr_PacketDlAssign(tlli);
var template IaRestOctets rest := tr_IaRestOctets_DLAss(dl_ass);
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var GsmRrMessage rr;
timer T := 10.0;
T.start;
alt {
- [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
- /* TODO: use decmatch tr_IaRestOctets_DLAss(...) instead */
- rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
- log("PCH/AGCN DL RR: ", rr);
- if (match(rr, tr_IMM_TBF_ASS(dl := true, rest := rest))) {
- log("Received IMM.ASS for our TLLI!");
- } else {
- repeat;
- }
- };
- [] pt.receive { repeat };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for TBF IMM ASS");
- mtc.stop;
- }
+ [] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0))) -> value dl {
+ /* TODO: use decmatch tr_IaRestOctets_DLAss(...) instead */
+ rr := dec_GsmRrMessage(dl.payload.data_ind.payload);
+ log("PCH/AGCN DL RR: ", rr);
+ if (match(rr, tr_IMM_TBF_ASS(dl := true, rest := rest))) {
+ log("Received IMM.ASS for our TLLI!");
+ } else {
+ repeat;
+ }
+ };
+ [] pt.receive { repeat };
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for TBF IMM ASS");
+ mtc.stop;
+ }
}
T.stop;
return rr.payload.imm_ass;
}
- function f_L1CTL_TBF_CFG(L1CTL_PT pt, boolean is_uplink, TfiUsfArr tfi_usf) {
- timer T := 2.0;
- T.start;
- pt.send(ts_L1CTL_TBF_CFG_REQ(is_uplink, tfi_usf));
- alt {
- [] pt.receive(tr_L1CTL_TBF_CFG_CONF(is_uplink)) {}
- [] pt.receive { repeat };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for L1CTL_TBF_CFG_CONF");
- mtc.stop;
- };
- }
- T.stop;
- }
-
/* Send DM_EST_REQ from parameters derived from IMM ASS */
function f_L1CTL_DM_EST_REQ_IA(L1CTL_PT pt, ImmediateAssignment imm_ass, L1ctlMA ma := {}) {
/* FIXME: handle Packet Channel Description */
@@ -236,12 +263,12 @@ module L1CTL_PortType {
pt.send(t_L1ctlResetReq(res_type));
T.start;
alt {
- [] pt.receive(tr_L1CTL_MsgType(L1CTL_RESET_CONF)) { }
- [] pt.receive { repeat; }
- [] T.timeout {
- setverdict(fail, "Timeout waiting for L1CTL_RESET_CONF");
- mtc.stop;
- }
+ [] pt.receive(tr_L1CTL_MsgType(L1CTL_RESET_CONF)) { }
+ [] pt.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for L1CTL_RESET_CONF");
+ mtc.stop;
+ }
}
}
@@ -268,28 +295,28 @@ module L1CTL_PortType {
pout.err := pin.result.err;
} with { extension "prototype(fast)" }
- private function L1CTL_to_UD_ul(in L1ctlUlMessage pin, out UD_send_data pout) {
- var L1ctlUlMessageLV msg_lv := { msg := pin };
- pout.data := enc_L1ctlUlMessageLV(msg_lv);
+ private function L1CTL_to_UD(in L1ctlMessage pin, out UD_send_data pout) {
+ var L1ctlMessageLV msg_lv := { msg := pin };
+ pout.data := enc_L1ctlMessageLV(msg_lv);
pout.id := 0;
} with { extension "prototype(fast)" }
- private function UD_to_L1CTL_dl(in UD_send_data pin, out L1ctlDlMessage pout) {
- var L1ctlDlMessageLV msg_lv := dec_L1ctlDlMessageLV(pin.data);
+ private function UD_to_L1CTL(in UD_send_data pin, out L1ctlMessage pout) {
+ var L1ctlMessageLV msg_lv := dec_L1ctlMessageLV(pin.data);
pout:= msg_lv.msg;
} with { extension "prototype(fast)" }
type port L1CTL_PT message {
- out L1ctlUlMessage
+ out L1ctlMessage
out L1CTL_connect
- in L1ctlDlMessage
+ in L1ctlMessage
in L1CTL_connect_result
in UD_listen_result
in UD_connected
} with { extension "user UD_PT
- out(L1ctlUlMessage -> UD_send_data: function(L1CTL_to_UD_ul);
+ out(L1ctlMessage -> UD_send_data: function(L1CTL_to_UD);
L1CTL_connect -> UD_connect: function(L1CTL_to_UD_connect))
- in(UD_send_data -> L1ctlDlMessage: function(UD_to_L1CTL_dl);
+ in(UD_send_data -> L1ctlMessage: function(UD_to_L1CTL);
UD_connect_result -> L1CTL_connect_result: function(UD_to_L1CTL_connect_result);
UD_listen_result -> UD_listen_result: simple;
UD_connected -> UD_connected: simple
diff --git a/library/L1CTL_Types.ttcn b/library/L1CTL_Types.ttcn
index 44f04901..b977a7dd 100644
--- a/library/L1CTL_Types.ttcn
+++ b/library/L1CTL_Types.ttcn
@@ -16,8 +16,6 @@ module L1CTL_Types {
import from GSM_RR_Types all;
import from Osmocom_Types all;
- type uint32_t uint32_le with { variant "BYTEORDER(first)" };
-
type enumerated L1ctlMsgType {
L1CTL_NONE,
L1CTL_FBSB_REQ,
@@ -51,12 +49,13 @@ module L1CTL_Types {
L1CTL_TRAFFIC_CONF,
L1CTL_TRAFFIC_IND,
L1CTL_BURST_IND,
- L1CTL_TBF_CFG_REQ,
- L1CTL_TBF_CFG_CONF,
- L1CTL_DATA_TBF_REQ,
- L1CTL_DATA_TBF_CONF,
+ L1CTL_GPRS_UL_TBF_CFG_REQ,
+ L1CTL_GPRS_DL_TBF_CFG_REQ,
+ L1CTL_GPRS_UL_BLOCK_REQ,
+ L1CTL_GPRS_DL_BLOCK_IND,
L1CTL_EXT_RACH_REQ,
- L1CTL_DATA_ABS_REQ /*!< FIXME: no such message in OsmocomBB */
+ L1CTL_GPRS_RTS_IND,
+ L1CTL_GPRS_UL_BLOCK_CNF
} with { variant "FIELDLENGTH(8)" };
type enumerated L1ctlCcchMode {
@@ -72,22 +71,6 @@ module L1CTL_Types {
NEIGH_MODE_SB
} with { variant "FIELDLENGTH(8)" };
- type enumerated L1ctlGprsCs {
- L1CTL_CS1 (1),
- L1CTL_CS2,
- L1CTL_CS3,
- L1CTL_CS4,
- L1CTL_MCS1,
- L1CTL_MCS2,
- L1CTL_MCS3,
- L1CTL_MCS4,
- L1CTL_MCS5,
- L1CTL_MCS6,
- L1CTL_MCS7,
- L1CTL_MCS8,
- L1CTL_MCS9
- } with { variant "FIELDLENGTH(8)" };
-
type enumerated L1ctlResetType {
L1CTL_RES_T_BOOT (0),
L1CTL_RES_T_FULL,
@@ -105,13 +88,15 @@ module L1CTL_Types {
OCT2 padding
} with { variant "" };
- template L1ctlHeader tr_L1ctlHeader(template L1ctlMsgType msg_type) := {
+ template L1ctlHeader
+ tr_L1ctlHeader(template (present) L1ctlMsgType msg_type) := {
msg_type := msg_type,
flags := ?,
padding := ?
};
- template (value) L1ctlHeader ts_L1ctlHeader(L1ctlMsgType msg_type) := {
+ template (value) L1ctlHeader
+ ts_L1ctlHeader(template (value) L1ctlMsgType msg_type) := {
msg_type := msg_type,
flags := { padding := '0000000'B, f_done := false },
padding := '0000'O
@@ -120,7 +105,7 @@ module L1CTL_Types {
type record L1ctlDlInfo {
RslChannelNr chan_nr,
RslLinkId link_id,
- Arfcn arfcn,
+ GsmBandArfcn arfcn,
uint32_t frame_nr,
GsmRxLev rx_level,
uint8_t snr,
@@ -140,7 +125,27 @@ module L1CTL_Types {
} with { variant "" };
/* gsm48_chan_mode */
- type uint8_t L1ctlTchMode;
+ type enumerated L1ctlTchMode {
+ L1CTL_CHAN_MODE_SIGN ('00000000'B), /* Signalling */
+ L1CTL_CHAN_MODE_SPEECH_V1 ('00000001'B), /* FR or HR codec */
+ L1CTL_CHAN_MODE_SPEECH_V2 ('00100001'B), /* EFR codec */
+ L1CTL_CHAN_MODE_SPEECH_V3 ('01000001'B), /* AMR codec */
+ L1CTL_CHAN_MODE_DATA_14k5 ('00001111'B), /* CSD: TCH/F14.4 */
+ L1CTL_CHAN_MODE_DATA_12k0 ('00000011'B), /* CSD: TCH/F9.6 */
+ L1CTL_CHAN_MODE_DATA_6k0 ('00001011'B), /* CSD: TCH/{FH}4.8 */
+ L1CTL_CHAN_MODE_DATA_3k6 ('00010011'B) /* CSD: TCH/{FH}2.4 */
+ } with { variant "FIELDLENGTH(8)" };
+
+ type enumerated L1ctlLoopMode {
+ L1CTL_LOOP_MODE_OPEN ('00000000'B),
+ L1CTL_LOOP_MODE_A ('00000001'B),
+ L1CTL_LOOP_MODE_B ('00000010'B),
+ L1CTL_LOOP_MODE_C ('00000011'B),
+ L1CTL_LOOP_MODE_D ('00000100'B),
+ L1CTL_LOOP_MODE_E ('00000101'B),
+ L1CTL_LOOP_MODE_F ('00000110'B),
+ L1CTL_LOOP_MODE_I ('00000111'B)
+ } with { variant "FIELDLENGTH(8)" };
type record L1ctlAudioMode {
BIT4 padding,
@@ -152,10 +157,20 @@ module L1CTL_Types {
template (value) L1ctlAudioMode t_L1CTL_AudioModeNone := { '0000'B, false, false, false, false };
+ /* Traffic forwarding mode (see TRAFFIC.{req,cnf,ind} messages) */
+ template (value) L1ctlAudioMode t_L1CTL_AudioModeFwd
+ modifies t_L1CTL_AudioModeNone := {
+ tx_traffic_req := true,
+ rx_traffic_ind := true
+ };
+
type record L1ctlTchModeConf {
L1ctlTchMode tch_mode,
L1ctlAudioMode audio_mode,
- OCT2 padding
+ record {
+ uint8_t start_codec,
+ BIT8 codecs_bitmask
+ } amr
} with { variant "" };
type record L1ctlDataInd {
@@ -164,42 +179,6 @@ module L1CTL_Types {
variant (payload) "BYTEORDER(first)"
};
- type union L1ctlDlPayload {
- L1ctlFbsbConf fbsb_conf,
- L1ctlCcchModeConf ccch_mode_conf,
- L1ctlTchModeConf tch_mode_conf,
- L1ctlDataInd data_ind,
- L1ctlTrafficReq traffic_ind,
- L1ctlTbfCfgReq tbf_cfg_conf,
- octetstring other
- } with {
- variant (other) "BYTEORDER(first)"
- };
-
- type record L1ctlDlMessage {
- L1ctlHeader header,
- L1ctlDlInfo dl_info optional,
- L1ctlDlPayload payload optional
- } with { variant (dl_info) "PRESENCE(header.msg_type = L1CTL_FBSB_CONF,
- header.msg_type = L1CTL_RACH_CONF,
- header.msg_type = L1CTL_DATA_IND,
- header.msg_type = L1CTL_DATA_CONF,
- header.msg_type = L1CTL_TRAFFIC_IND,
- header.msg_type = L1CTL_TRAFFIC_CONF)"
- variant (payload) "CROSSTAG(fbsb_conf, header.msg_type = L1CTL_FBSB_CONF;
- ccch_mode_conf, header.msg_type = L1CTL_CCCH_MODE_CONF;
- tch_mode_conf, header.msg_type = L1CTL_TCH_MODE_CONF;
- data_ind, header.msg_type = L1CTL_DATA_IND;
- traffic_ind, header.msg_type = L1CTL_TRAFFIC_IND;
- tbf_cfg_conf, header.msg_type = L1CTL_TBF_CFG_CONF;
- other, OTHERWISE;
- )" };
-
- external function enc_L1ctlDlMessage(in L1ctlDlMessage msg) return octetstring
- with { extension "prototype(convert) encode(RAW)" };
- external function dec_L1ctlDlMessage(in octetstring stream) return L1ctlDlMessage
- with { extension "prototype(convert) decode(RAW)" };
-
type record L1ctlUlInfo {
RslChannelNr chan_nr,
@@ -207,22 +186,6 @@ module L1CTL_Types {
OCT2 padding
} with { variant "" };
- type record L1ctlUlTbfInfo {
- uint8_t tbf_nr,
- L1ctlGprsCs cs,
- OCT2 padding
- } with { variant "" };
-
- type record L1ctlUlAbsInfo {
- uint8_t tbf_nr,
- L1ctlGprsCs cs,
- uint8_t ts_nr,
- OCT1 padding,
- uint32_le fn,
- Arfcn arfcn,
- OCT2 padding2
- } with { variant "" };
-
type record L1ctlFbsbFlags {
BIT5 padding,
boolean sb,
@@ -238,7 +201,7 @@ module L1CTL_Types {
};
type record L1ctlFbsbReq {
- Arfcn arfcn,
+ GsmBandArfcn arfcn,
uint16_t timeout_tdma_frames,
uint16_t freq_err_thresh1,
uint16_t freq_err_thresh2,
@@ -257,7 +220,11 @@ module L1CTL_Types {
type record L1ctlTchModeReq {
L1ctlTchMode tch_mode,
L1ctlAudioMode audio_mode,
- OCT2 padding
+ L1ctlLoopMode loop_mode,
+ record {
+ uint8_t start_codec,
+ BIT8 codecs_bitmask
+ } amr
} with { variant "" };
type record L1ctlRachReq {
@@ -290,8 +257,15 @@ module L1CTL_Types {
octetstring l2_payload
} with { variant "" };
- type record length(0..64) of Arfcn L1ctlMA;
+ type record L1ctlH0 {
+ uint8_t h,
+ GsmBandArfcn arfcn,
+ octetstring padding length(130)
+ } with { variant "" };
+
+ type record length(0..64) of GsmBandArfcn L1ctlMA;
type record L1ctlH1 {
+ uint8_t h,
uint8_t hsn,
uint8_t maio,
uint8_t n,
@@ -308,15 +282,17 @@ module L1CTL_Types {
* variant (ma) "PADDING(128)" */
};
+ type union L1ctlH0H1 {
+ L1ctlH0 h0,
+ L1ctlH1 h1
+ } with { variant "TAG(h0, h = 0; h1, h = 1)" };
+
type record L1ctlDmEstReq {
GsmTsc tsc,
- uint8_t h,
- Arfcn arfcn optional,
- L1ctlH1 hopping optional,
+ L1ctlH0H1 h0h1,
L1ctlTchMode tch_mode,
L1ctlAudioMode audio_mode
- } with { variant (arfcn) "PRESENCE(h = 0)"
- variant (hopping) "PRESENCE(h = 1)" };
+ } with { variant "" };
type record L1ctlReset {
L1ctlResetType reset_type,
@@ -336,40 +312,106 @@ module L1CTL_Types {
variant (data) "BYTEORDER(first)"
}
- type record length(8) of uint8_t TfiUsfArr;
- type record L1ctlTbfCfgReq {
- uint8_t tbf_nr,
- boolean is_uplink,
- OCT2 padding,
- TfiUsfArr tfi_usf
- } with { variant (is_uplink) "FIELDLENGTH(8)" };
+ /* payload of L1CTL_GPRS_UL_TBF_CFG_REQ */
+ type record L1ctlGprsUlTbfCfgReq {
+ uint8_t tbf_ref,
+ BIT8 slotmask,
+ OCT2 pad ('0000'O),
+ uint32_t start_fn /* TBF Starting Time (absolute Fn) */
+ } with { variant (slotmask) "BITORDER(msb)" };
+
+ /* payload of L1CTL_GPRS_DL_TBF_CFG_REQ */
+ type record L1ctlGprsDlTbfCfgReq {
+ uint8_t tbf_ref,
+ BIT8 slotmask,
+ uint8_t dl_tfi,
+ OCT1 pad ('00'O),
+ uint32_t start_fn /* TBF Starting Time (absolute Fn) */
+ } with { variant (slotmask) "BITORDER(msb)" };
+
+ /* part of L1CTL_GPRS_{UL,DL}_BLOCK_{REQ,IND} */
+ type record L1ctlGprsBlockHdr {
+ uint32_t fn,
+ uint8_t tn,
+ OCT3 pad ('000000'O)
+ } with { variant "" };
+
+ /* payload of L1CTL_GPRS_UL_BLOCK_REQ */
+ type record L1ctlGprsUlBlockReq {
+ L1ctlGprsBlockHdr hdr,
+ octetstring data
+ } with { variant (data) "BYTEORDER(first)" };
+
+ /* payload of L1CTL_GPRS_UL_BLOCK_CNF */
+ type record L1ctlGprsUlBlockCnf {
+ uint32_t fn,
+ uint8_t tn,
+ octetstring data
+ } with { variant "" };
+
+ /* payload of L1CTL_GPRS_DL_BLOCK_IND */
+ type record L1ctlGprsDlBlockInd {
+ L1ctlGprsBlockHdr hdr,
+ record {
+ uint16_t ber10k, /* Bit Error Rate */
+ int16_t ci_cb, /* C/I in centiBels */
+ uint8_t rx_level /* RxLev 0..63 */
+ } meas,
+ uint8_t usf,
+ octetstring data
+ } with { variant (data) "BYTEORDER(first)" };
+
+ /* payload of L1CTL_GPRS_RTS_IND */
+ type record L1ctlGprsRtsInd {
+ uint32_t fn,
+ uint8_t tn,
+ uint8_t usf
+ } with { variant "" };
+
- type union L1ctlUlPayload {
+ type union L1ctlMsgPayload {
L1ctlFbsbReq fbsb_req,
- L1ctlCcchModeReq ccch_mode_req,
- L1ctlTchModeReq tch_mode_req,
+ L1ctlFbsbConf fbsb_conf,
+ L1ctlDataInd data_ind,
L1ctlRachReq rach_req,
- L1ctlExtRachReq ext_rach_req,
- L1ctlParReq par_req,
L1ctlDmEstReq dm_est_req,
+ L1ctlDataReq data_req,
+ /* TODO: L1CTL_RESET_IND */
+ /* TODO: L1CTL_PM_REQ */
+ /* TODO: L1CTL_PM_CONF */
L1ctlReset reset_req,
- //L1ctlNeighPmReq neigh_pm_req,
+ L1ctlCcchModeReq ccch_mode_req,
+ L1ctlCcchModeConf ccch_mode_conf,
+ L1ctlParReq par_req,
+ /* TODO: L1CTL_DM_FREQ_REQ */
L1CtlCryptoReq crypto_req,
+ /* TODO: L1CTL_SIM_REQ */
+ /* TODO: L1CTL_SIM_CONF */
+ L1ctlTchModeReq tch_mode_req,
+ L1ctlTchModeConf tch_mode_conf,
+ /* TODO: L1CTL_NEIGH_PM_REQ */
+ /* TODO: L1CTL_NEIGH_PM_IND */
L1ctlTrafficReq traffic_req,
- L1ctlTbfCfgReq tbf_cfg_req,
- L1ctlDataReq data_req,
+ L1ctlTrafficReq traffic_ind,
+ /* TODO: L1CTL_BURST_IND */
+ L1ctlGprsUlTbfCfgReq ul_tbf_cfg_req,
+ L1ctlGprsDlTbfCfgReq dl_tbf_cfg_req,
+ L1ctlGprsUlBlockReq ul_block_req,
+ L1ctlGprsUlBlockCnf ul_block_cnf,
+ L1ctlGprsDlBlockInd dl_block_ind,
+ L1ctlExtRachReq ext_rach_req,
+ L1ctlGprsRtsInd rts_ind,
octetstring other
} with {
variant (other) "BYTEORDER(first)"
};
- type record L1ctlUlMessage {
+ type record L1ctlMessage {
L1ctlHeader header,
L1ctlUlInfo ul_info optional,
- L1ctlUlTbfInfo ul_info_tbf optional,
- L1ctlUlAbsInfo ul_info_abs optional,
- L1ctlUlPayload payload
+ L1ctlDlInfo dl_info optional,
+ L1ctlMsgPayload payload optional
} with { variant (ul_info) "PRESENCE(header.msg_type = L1CTL_RACH_REQ,
header.msg_type = L1CTL_EXT_RACH_REQ,
header.msg_type = L1CTL_PARAM_REQ,
@@ -379,57 +421,69 @@ module L1CTL_Types {
header.msg_type = L1CTL_DM_FREQ_REQ,
header.msg_type = L1CTL_DM_REL_REQ,
header.msg_type = L1CTL_TRAFFIC_REQ)"
- variant (ul_info_tbf) "PRESENCE(header.msg_type = L1CTL_DATA_TBF_REQ)"
- variant (ul_info_abs) "PRESENCE(header.msg_type = L1CTL_DATA_ABS_REQ)"
+ variant (dl_info) "PRESENCE(header.msg_type = L1CTL_FBSB_CONF,
+ header.msg_type = L1CTL_RACH_CONF,
+ header.msg_type = L1CTL_DATA_IND,
+ header.msg_type = L1CTL_DATA_CONF,
+ header.msg_type = L1CTL_TRAFFIC_IND,
+ header.msg_type = L1CTL_TRAFFIC_CONF)"
variant (payload) "CROSSTAG(fbsb_req, header.msg_type = L1CTL_FBSB_REQ;
- ccch_mode_req, header.msg_type = L1CTL_CCCH_MODE_REQ;
- tch_mode_req, header.msg_type = L1CTL_TCH_MODE_REQ;
+ fbsb_conf, header.msg_type = L1CTL_FBSB_CONF;
+ data_ind, header.msg_type = L1CTL_DATA_IND;
rach_req, header.msg_type = L1CTL_RACH_REQ;
- ext_rach_req, header.msg_type = L1CTL_EXT_RACH_REQ;
- par_req, header.msg_type = L1CTL_PARAM_REQ;
dm_est_req, header.msg_type = L1CTL_DM_EST_REQ;
+ data_req, header.msg_type = L1CTL_DATA_REQ;
+ /* TODO: reset_ind, header.msg_type = L1CTL_RESET_IND */
+ /* TODO: pm_req, header.msg_type = L1CTL_PM_REQ */
+ /* TODO: pm_conf, header.msg_type = L1CTL_PM_CONF */
reset_req, header.msg_type = L1CTL_RESET_REQ;
+ ccch_mode_req, header.msg_type = L1CTL_CCCH_MODE_REQ;
+ ccch_mode_conf, header.msg_type = L1CTL_CCCH_MODE_CONF;
+ par_req, header.msg_type = L1CTL_PARAM_REQ;
+ /* TODO: freq_req, header.msg_type = L1CTL_DM_FREQ_REQ */
crypto_req, header.msg_type = L1CTL_CRYPTO_REQ;
+ /* TODO: sim_req, header.msg_type = L1CTL_SIM_REQ */
+ /* TODO: sim_conf, header.msg_type = L1CTL_SIM_CONF */
+ tch_mode_req, header.msg_type = L1CTL_TCH_MODE_REQ;
+ tch_mode_conf, header.msg_type = L1CTL_TCH_MODE_CONF;
+ /* TODO: neigh_pm_req, header.msg_type = L1CTL_NEIGH_PM_REQ */
+ /* TODO: neigh_pm_ind, header.msg_type = L1CTL_NEIGH_PM_IND */
traffic_req, header.msg_type = L1CTL_TRAFFIC_REQ;
- tbf_cfg_req, header.msg_type = L1CTL_TBF_CFG_REQ;
- data_req, header.msg_type = L1CTL_DATA_REQ;
+ traffic_ind, header.msg_type = L1CTL_TRAFFIC_IND;
+ /* TODO: burst_ind, header.msg_type = L1CTL_BURST_IND */
+ ul_tbf_cfg_req, header.msg_type = L1CTL_GPRS_UL_TBF_CFG_REQ;
+ dl_tbf_cfg_req, header.msg_type = L1CTL_GPRS_DL_TBF_CFG_REQ;
+ ul_block_req, header.msg_type = L1CTL_GPRS_UL_BLOCK_REQ;
+ ul_block_cnf, header.msg_type = L1CTL_GPRS_UL_BLOCK_CNF;
+ dl_block_ind, header.msg_type = L1CTL_GPRS_DL_BLOCK_IND;
+ ext_rach_req, header.msg_type = L1CTL_EXT_RACH_REQ;
+ rts_ind, header.msg_type = L1CTL_GPRS_RTS_IND;
other, OTHERWISE;
)" };
- external function enc_L1ctlUlMessage(in L1ctlUlMessage msg) return octetstring
- with { extension "prototype(convert) encode(RAW)" };
- external function dec_L1ctlUlMessage(in octetstring stream) return L1ctlUlMessage
- with { extension "prototype(convert) decode(RAW)" };
-
- type record L1ctlUlMessageLV {
- uint16_t len,
- L1ctlUlMessage msg
- } with { variant (len) "LENGTHTO(msg)" };
-
- external function enc_L1ctlUlMessageLV(in L1ctlUlMessageLV msg) return octetstring
+ external function enc_L1ctlMessage(in L1ctlMessage msg) return octetstring
with { extension "prototype(convert) encode(RAW)" };
- external function dec_L1ctlUlMessageLV(in octetstring stream) return L1ctlUlMessageLV
+ external function dec_L1ctlMessage(in octetstring stream) return L1ctlMessage
with { extension "prototype(convert) decode(RAW)" };
- type record L1ctlDlMessageLV {
+ type record L1ctlMessageLV {
uint16_t len,
- L1ctlDlMessage msg
+ L1ctlMessage msg
} with { variant (len) "LENGTHTO(msg)" };
- external function enc_L1ctlDlMessageLV(in L1ctlDlMessageLV msg) return octetstring
+ external function enc_L1ctlMessageLV(in L1ctlMessageLV msg) return octetstring
with { extension "prototype(convert) encode(RAW)" };
- external function dec_L1ctlDlMessageLV(in octetstring stream) return L1ctlDlMessageLV
+ external function dec_L1ctlMessageLV(in octetstring stream) return L1ctlMessageLV
with { extension "prototype(convert) decode(RAW)" };
-
/* for generating RESET_REQ */
- template (value) L1ctlUlMessage t_L1ctlResetReq(L1ctlResetType rst_type) := {
+ template (value) L1ctlMessage
+ t_L1ctlResetReq(template (value) L1ctlResetType rst_type) := {
header := ts_L1ctlHeader(L1CTL_RESET_REQ),
ul_info := omit,
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
reset_req := {
reset_type := rst_type,
@@ -439,14 +493,15 @@ module L1CTL_Types {
};
/* for generating FBSB_REQ */
- template (value) L1ctlUlMessage ts_L1CTL_FBSB_REQ(Arfcn arfcn, L1ctlFbsbFlags flags,
- uint8_t sync_info_idx,
- L1ctlCcchMode ccch_mode,
- GsmRxLev rxlev_exp) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_FBSB_REQ(template (value) GsmBandArfcn arfcn,
+ template (value) L1ctlFbsbFlags flags,
+ template (value) uint8_t sync_info_idx,
+ template (value) L1ctlCcchMode ccch_mode,
+ template (value) GsmRxLev rxlev_exp) := {
header := ts_L1ctlHeader(L1CTL_FBSB_REQ),
ul_info := omit,
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
fbsb_req := {
arfcn := arfcn,
@@ -463,8 +518,10 @@ module L1CTL_Types {
};
/* for matching against incoming FBSB_CONF */
- template L1ctlDlMessage tr_L1CTL_FBSB_CONF(template uint8_t result) := {
+ template L1ctlMessage
+ tr_L1CTL_FBSB_CONF(template (present) uint8_t result) := {
header := tr_L1ctlHeader(L1CTL_FBSB_CONF),
+ ul_info := omit,
dl_info := ?,
payload := {
fbsb_conf := {
@@ -475,11 +532,11 @@ module L1CTL_Types {
}
};
- template (value) L1ctlUlMessage ts_L1CTL_CCCH_MODE_REQ(L1ctlCcchMode ccch_mode) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_CCCH_MODE_REQ(template (value) L1ctlCcchMode ccch_mode) := {
header := ts_L1ctlHeader(L1CTL_CCCH_MODE_REQ),
ul_info := omit,
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
ccch_mode_req := {
ccch_mode := ccch_mode,
@@ -488,26 +545,52 @@ module L1CTL_Types {
}
};
+ template (value) L1ctlMessage
+ ts_L1CTL_TCH_MODE_REQ(template (value) L1ctlTchMode tch_mode := L1CTL_CHAN_MODE_SIGN,
+ template (value) L1ctlAudioMode audio_mode := t_L1CTL_AudioModeFwd,
+ template (value) L1ctlLoopMode loop_mode := L1CTL_LOOP_MODE_OPEN,
+ template (value) uint8_t amr_start_codec := 0,
+ template (value) BIT8 amr_codecs_bitmask := '00000000'B) := {
+ header := ts_L1ctlHeader(L1CTL_TCH_MODE_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ tch_mode_req := {
+ tch_mode := tch_mode,
+ audio_mode := audio_mode,
+ loop_mode := loop_mode,
+ amr := {
+ start_codec := amr_start_codec,
+ codecs_bitmask := amr_codecs_bitmask
+ }
+ }
+ }
+ };
+
- template L1ctlDlMessage tr_L1CTL_MsgType(template L1ctlMsgType msg_type) := {
+ template L1ctlMessage
+ tr_L1CTL_MsgType(template (present) L1ctlMsgType msg_type) := {
header := tr_L1ctlHeader(msg_type),
+ ul_info := *,
dl_info := *,
payload := *
}
- template L1ctlDlMessage tr_L1CTL_CCCH_MODE_CONF := tr_L1CTL_MsgType(L1CTL_CCCH_MODE_CONF);
+ template L1ctlMessage tr_L1CTL_CCCH_MODE_CONF := tr_L1CTL_MsgType(L1CTL_CCCH_MODE_CONF);
- template L1ctlUlMessage ts_L1CTL_RACH_REQ(uint8_t ra, uint8_t combined, uint16_t offset,
- template (value) RslChannelNr chan_nr := ts_RslChanNr_RACH(0),
- template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0)) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_RACH_REQ(template (value) uint8_t ra,
+ template (value) uint8_t combined,
+ template (value) uint16_t offset,
+ template (value) RslChannelNr chan_nr := ts_RslChanNr_RACH(0),
+ template (value) RslLinkId link_id := ts_RslLinkID_DCCH(0)) := {
header := ts_L1ctlHeader(L1CTL_RACH_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := link_id,
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
rach_req := {
ra := ra,
@@ -517,19 +600,19 @@ module L1CTL_Types {
}
}
- template L1ctlUlMessage ts_L1CTL_EXT_RACH_REQ(
- uint16_t ra11, L1ctlRachSynchSeq seq,
- uint8_t combined, uint16_t offset
- ) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_EXT_RACH_REQ(template (value) uint16_t ra11,
+ template (value) L1ctlRachSynchSeq seq,
+ template (value) uint8_t combined,
+ template (value) uint16_t offset) := {
header := ts_L1ctlHeader(L1CTL_EXT_RACH_REQ),
ul_info := {
/* FIXME: both RSL chan_nr and link_id should be configurable */
- chan_nr := t_RslChanNr_RACH(0),
+ chan_nr := ts_RslChanNr_RACH(0),
link_id := ts_RslLinkID_DCCH(0),
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
ext_rach_req := {
ra11 := ra11,
@@ -540,15 +623,16 @@ module L1CTL_Types {
}
}
- template L1ctlUlMessage ts_L1CTL_PAR_REQ(uint8_t ta, uint8_t tx_power) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_PAR_REQ(template (value) uint8_t ta,
+ template (value) uint8_t tx_power) := {
header := ts_L1ctlHeader(L1CTL_PARAM_REQ),
ul_info := {
- chan_nr := t_RslChanNr_RACH(0),
+ chan_nr := ts_RslChanNr_RACH(0),
link_id := ts_RslLinkID_DCCH(0),
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
par_req := {
ta := ta,
@@ -559,86 +643,92 @@ module L1CTL_Types {
}
/* Base template to be inherited by ts_L1CTL_DM_EST_REQ_H0 and ts_L1CTL_DM_EST_REQ_H1 */
- private template (value) L1ctlUlMessage ts_L1CTL_DM_EST_REQ(template (value) RslChannelNr chan_nr,
- template (value) GsmTsc tsc) := {
+ private template (value) L1ctlMessage
+ ts_L1CTL_DM_EST_REQ(template (value) RslChannelNr chan_nr,
+ template (value) GsmTsc tsc) := {
header := ts_L1ctlHeader(L1CTL_DM_EST_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := ts_RslLinkID_DCCH(0),
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
dm_est_req := {
tsc := tsc,
- tch_mode := 0,
- audio_mode := t_L1CTL_AudioModeNone
+ h0h1 := -,
+ tch_mode := L1CTL_CHAN_MODE_SIGN,
+ audio_mode := t_L1CTL_AudioModeFwd
}
}
}
- template (value) L1ctlUlMessage ts_L1CTL_DM_EST_REQ_H0(template (value) RslChannelNr chan_nr,
- template (value) GsmTsc tsc,
- template (value) GsmArfcn arfcn)
+ template (value) L1ctlMessage
+ ts_L1CTL_DM_EST_REQ_H0(template (value) RslChannelNr chan_nr,
+ template (value) GsmTsc tsc,
+ template (value) GsmArfcn arfcn)
modifies ts_L1CTL_DM_EST_REQ := {
payload := {
dm_est_req := {
- h := 0,
- arfcn := { false, arfcn },
- hopping := omit
+ h0h1 := {
+ h0 := {
+ h := 0,
+ arfcn := ts_GsmBandArfcn(arfcn),
+ padding := f_pad_oct(''O, 130, '00'O)
+ }
+ }
}
}
}
- template (value) L1ctlUlMessage ts_L1CTL_DM_EST_REQ_H1(template (value) RslChannelNr chan_nr,
- template (value) GsmTsc tsc,
- template (value) uint6_t hsn,
- template (value) uint6_t maio,
- template (value) L1ctlMA ma)
+ template (value) L1ctlMessage
+ ts_L1CTL_DM_EST_REQ_H1(template (value) RslChannelNr chan_nr,
+ template (value) GsmTsc tsc,
+ template (value) uint6_t hsn,
+ template (value) uint6_t maio,
+ template (value) L1ctlMA ma)
modifies ts_L1CTL_DM_EST_REQ := {
payload := {
dm_est_req := {
- h := 1,
- arfcn := omit,
- hopping := {
- hsn := hsn,
- maio := maio,
- n := sizeof(ma),
- spare := '00'O,
- ma := ma,
- /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562849 */
- padding := f_pad_oct(''O, (64 - sizeof(ma)) * 2, '00'O)
+ h0h1 := {
+ h1 := {
+ h := 1,
+ hsn := hsn,
+ maio := maio,
+ n := sizeof(ma),
+ spare := '00'O,
+ ma := ma,
+ /* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=562849 */
+ padding := f_pad_oct(''O, (64 - sizeof(ma)) * 2, '00'O)
+ }
}
}
}
}
- template L1ctlUlMessage ts_L1CTL_DM_REL_REQ(RslChannelNr chan_nr) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_DM_REL_REQ(template (value) RslChannelNr chan_nr) := {
header := ts_L1ctlHeader(L1CTL_DM_REL_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := ts_RslLinkID_DCCH(0),
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
- payload := {
- other := ''O
- }
+ dl_info := omit,
+ payload := omit
}
- template (value) L1ctlUlMessage ts_L1CTL_DATA_REQ(template (value) RslChannelNr chan_nr,
- template (value) RslLinkId link_id,
- octetstring l2_data) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_DATA_REQ(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ octetstring l2_data) := {
header := ts_L1ctlHeader(L1CTL_DATA_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := link_id,
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
data_req := {
l1header := omit,
@@ -647,18 +737,18 @@ module L1CTL_Types {
}
}
- template (value) L1ctlUlMessage ts_L1CTL_DATA_REQ_SACCH(template (value) RslChannelNr chan_nr,
- template (value) RslLinkId link_id,
- template (value) SacchL1Header l1h,
- octetstring l2_data) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_DATA_REQ_SACCH(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ template (value) SacchL1Header l1h,
+ octetstring l2_data) := {
header := ts_L1ctlHeader(L1CTL_DATA_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := link_id,
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
data_req := {
l1header := l1h,
@@ -667,17 +757,17 @@ module L1CTL_Types {
}
}
- template (value) L1ctlUlMessage ts_L1CTL_TRAFFIC_REQ(template (value) RslChannelNr chan_nr,
- template (value) RslLinkId link_id,
- octetstring frame) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_TRAFFIC_REQ(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ octetstring frame) := {
header := ts_L1ctlHeader(L1CTL_TRAFFIC_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := link_id,
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
traffic_req := {
data := frame
@@ -685,86 +775,50 @@ module L1CTL_Types {
}
};
- template (value) L1ctlUlMessage ts_L1CTL_TBF_CFG_REQ(boolean is_uplink, TfiUsfArr tfi_usf) := {
- header := ts_L1ctlHeader(L1CTL_TBF_CFG_REQ),
+ /* for matching against incoming RACH_CONF */
+ template L1ctlMessage tr_L1CTL_RACH_CONF := {
+ header := tr_L1ctlHeader(L1CTL_RACH_CONF),
ul_info := omit,
- ul_info_tbf := omit,
- ul_info_abs := omit,
- payload := {
- tbf_cfg_req := {
- tbf_nr := 0,
- is_uplink := is_uplink,
- padding := '0000'O,
- tfi_usf := tfi_usf
- }
- }
- };
-
- template L1ctlDlMessage tr_L1CTL_TBF_CFG_CONF(template boolean is_uplink) := {
- header := tr_L1ctlHeader(L1CTL_TBF_CFG_CONF),
- dl_info := omit,
- payload := {
- tbf_cfg_conf := {
- tbf_nr := 0,
- is_uplink := is_uplink,
- padding := ?,
- tfi_usf := ?
- }
- }
+ dl_info := ?,
+ payload := *
};
- template (value) L1ctlUlMessage ts_L1CTL_DATA_TBF_REQ(octetstring l2_data,
- L1ctlGprsCs cs := L1CTL_CS1,
- uint8_t tbf_nr := 0) := {
- header := ts_L1ctlHeader(L1CTL_DATA_TBF_REQ),
- ul_info := omit,
- ul_info_tbf := {
- tbf_nr := tbf_nr,
- cs := cs,
- padding := '0000'O
- },
- ul_info_abs := omit,
- payload := {
- other := l2_data
- }
- }
-
- template (value) L1ctlUlMessage ts_L1CTL_DATA_ABS_REQ(octetstring l2_data, Arfcn arfcn,
- uint8_t ts, GsmFrameNumber fn,
- L1ctlGprsCs cs := L1CTL_CS1,
- uint8_t tbf_nr := 0) := {
- header := ts_L1ctlHeader(L1CTL_DATA_ABS_REQ),
+ /* for sending and matching L1CTL_DATA_IND */
+ template (value) L1ctlMessage
+ ts_L1CTL_DATA_IND(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ template (value) octetstring l2_data,
+ template (value) GsmBandArfcn arfcn,
+ template (value) uint32_t fn := 1337,
+ template (value) GsmRxLev rx_level := 63,
+ template (value) uint8_t num_biterr := 0,
+ template (value) uint8_t fire_crc := 0) := {
+ header := ts_L1ctlHeader(L1CTL_DATA_IND),
ul_info := omit,
- ul_info_tbf := omit,
- ul_info_abs := {
- tbf_nr := tbf_nr,
- cs := cs,
- ts_nr := ts,
- padding := '00'O,
- fn := fn,
+ dl_info := {
+ chan_nr := chan_nr,
+ link_id := link_id,
arfcn := arfcn,
- padding2 := '0000'O
+ frame_nr := fn,
+ rx_level := rx_level,
+ snr := 0,
+ num_biterr := num_biterr,
+ fire_crc := fire_crc
},
payload := {
- other := l2_data
+ data_ind := {
+ payload := l2_data
+ }
}
- }
-
-
- /* for matching against incoming RACH_CONF */
- template L1ctlDlMessage tr_L1CTL_RACH_CONF := {
- header := tr_L1ctlHeader(L1CTL_RACH_CONF),
- dl_info := ?,
- payload := *
};
-
- /* for matching against incoming DATA_IND */
- template L1ctlDlMessage tr_L1CTL_DATA_IND(template RslChannelNr chan_nr,
- template RslLinkId link_id := ?,
- template octetstring l2_data := ?,
- template uint8_t num_biterr := 0,
- template uint8_t fire_crc := 0) := {
+ template L1ctlMessage
+ tr_L1CTL_DATA_IND(template (present) RslChannelNr chan_nr,
+ template (present) RslLinkId link_id := ?,
+ template (present) octetstring l2_data := ?,
+ template (present) uint8_t num_biterr := 0,
+ template (present) uint8_t fire_crc := 0) := {
header := tr_L1ctlHeader(L1CTL_DATA_IND),
+ ul_info := omit,
dl_info := {
chan_nr := chan_nr,
link_id := link_id,
@@ -773,7 +827,7 @@ module L1CTL_Types {
rx_level := ?,
snr := ?,
num_biterr := num_biterr,
- fire_crc := fire_crc
+ fire_crc := fire_crc
},
payload := {
data_ind := {
@@ -782,13 +836,73 @@ module L1CTL_Types {
}
};
+ /* for sending and matching L1CTL_DATA_CONF */
+ template (value) L1ctlMessage
+ ts_L1CTL_DATA_CONF(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ template (value) GsmBandArfcn arfcn,
+ template (value) GsmFrameNumber fn) := {
+ header := ts_L1ctlHeader(L1CTL_DATA_CONF),
+ ul_info := omit,
+ dl_info := {
+ chan_nr := chan_nr,
+ link_id := link_id,
+ arfcn := arfcn,
+ frame_nr := fn,
+ rx_level := 0,
+ snr := 0,
+ num_biterr := 0,
+ fire_crc := 0
+ },
+ payload := omit
+ };
+ template L1ctlMessage
+ tr_L1CTL_DATA_CONF(template (present) RslChannelNr chan_nr,
+ template (present) RslLinkId link_id := ?,
+ template (present) GsmBandArfcn arfcn := ?,
+ template (present) GsmFrameNumber fn := ?) := {
+ header := tr_L1ctlHeader(L1CTL_DATA_CONF),
+ ul_info := omit,
+ dl_info := {
+ chan_nr := chan_nr,
+ link_id := link_id,
+ arfcn := arfcn,
+ frame_nr := fn,
+ rx_level := ?,
+ snr := ?,
+ num_biterr := ?,
+ fire_crc := ?
+ },
+ payload := omit
+ };
+
+ /* for sending and matching L1CTL_TRAFFIC_CONF */
+ template (value) L1ctlMessage
+ ts_L1CTL_TRAFFIC_CONF(template (value) RslChannelNr chan_nr,
+ template (value) RslLinkId link_id,
+ template (value) GsmBandArfcn arfcn,
+ template (value) GsmFrameNumber fn)
+ modifies ts_L1CTL_DATA_CONF := {
+ header := ts_L1ctlHeader(L1CTL_TRAFFIC_CONF)
+ };
+ template L1ctlMessage
+ tr_L1CTL_TRAFFIC_CONF(template (present) RslChannelNr chan_nr,
+ template (present) RslLinkId link_id := ?,
+ template (present) GsmBandArfcn arfcn := ?,
+ template (present) GsmFrameNumber fn := ?)
+ modifies tr_L1CTL_DATA_CONF := {
+ header := tr_L1ctlHeader(L1CTL_TRAFFIC_CONF)
+ };
+
/* for matching against incoming TRAFFIC_IND */
- template L1ctlDlMessage tr_L1CTL_TRAFFIC_IND(template RslChannelNr chan_nr,
- template RslLinkId link_id := ?,
- template octetstring frame := ?,
- template uint8_t num_biterr := 0,
- template uint8_t fire_crc := 0) := {
+ template L1ctlMessage
+ tr_L1CTL_TRAFFIC_IND(template (present) RslChannelNr chan_nr,
+ template (present) RslLinkId link_id := ?,
+ template (present) octetstring frame := ?,
+ template (present) uint8_t num_biterr := ?,
+ template (present) uint8_t fire_crc := ?) := {
header := tr_L1ctlHeader(L1CTL_TRAFFIC_IND),
+ ul_info := omit,
dl_info := {
chan_nr := chan_nr,
link_id := link_id,
@@ -806,16 +920,17 @@ module L1CTL_Types {
}
};
- template (value) L1ctlUlMessage ts_L1CTL_CRYPTO_REQ(RslChannelNr chan_nr, uint8_t algo,
- octetstring key) := {
+ template (value) L1ctlMessage
+ ts_L1CTL_CRYPTO_REQ(template (value) RslChannelNr chan_nr,
+ template (value) uint8_t algo,
+ template (value) octetstring key) := {
header := ts_L1ctlHeader(L1CTL_CRYPTO_REQ),
ul_info := {
chan_nr := chan_nr,
link_id := ts_RslLinkID_DCCH(0),
padding := '0000'O
},
- ul_info_tbf := omit,
- ul_info_abs := omit,
+ dl_info := omit,
payload := {
crypto_req := {
algo := algo,
@@ -825,6 +940,171 @@ module L1CTL_Types {
}
};
+
+ template (value) L1ctlMessage
+ ts_L1CTL_GPRS_UL_TBF_CFG_REQ(template (value) uint8_t tbf_ref,
+ template (value) BIT8 slotmask := '00000000'B,
+ template (value) uint32_t start_fn := c_UINT32_MAX) := {
+ header := ts_L1ctlHeader(L1CTL_GPRS_UL_TBF_CFG_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ ul_tbf_cfg_req := {
+ tbf_ref := tbf_ref,
+ slotmask := slotmask,
+ pad := '0000'O,
+ start_fn := start_fn
+ }
+ }
+ };
+ template L1ctlMessage
+ tr_L1CTL_GPRS_UL_TBF_CFG_REQ(template (present) uint8_t tbf_ref := ?,
+ template (present) BIT8 slotmask := ?,
+ template (present) uint32_t start_fn := ?) := {
+ header := tr_L1ctlHeader(L1CTL_GPRS_UL_TBF_CFG_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ ul_tbf_cfg_req := {
+ tbf_ref := tbf_ref,
+ slotmask := slotmask,
+ pad := ?,
+ start_fn := start_fn
+ }
+ }
+ };
+
+ template (value) L1ctlMessage
+ ts_L1CTL_GPRS_DL_TBF_CFG_REQ(template (value) uint8_t tbf_ref,
+ template (value) BIT8 slotmask := '00000000'B,
+ template (value) uint32_t start_fn := c_UINT32_MAX,
+ template (value) uint5_t dl_tfi := 0) := {
+ header := ts_L1ctlHeader(L1CTL_GPRS_DL_TBF_CFG_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ dl_tbf_cfg_req := {
+ tbf_ref := tbf_ref,
+ slotmask := slotmask,
+ dl_tfi := dl_tfi,
+ pad := '00'O,
+ start_fn := start_fn
+ }
+ }
+ };
+ template L1ctlMessage
+ tr_L1CTL_GPRS_DL_TBF_CFG_REQ(template (present) uint8_t tbf_ref := ?,
+ template (present) BIT8 slotmask := ?,
+ template (present) uint32_t start_fn := ?,
+ template (present) uint5_t dl_tfi := ?) := {
+ header := tr_L1ctlHeader(L1CTL_GPRS_DL_TBF_CFG_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ dl_tbf_cfg_req := {
+ tbf_ref := tbf_ref,
+ slotmask := slotmask,
+ dl_tfi := dl_tfi,
+ pad := ?,
+ start_fn := start_fn
+ }
+ }
+ };
+
+ template (value) L1ctlMessage
+ ts_L1CTL_GPRS_UL_BLOCK_REQ(template (value) GsmFrameNumber fn,
+ template (value) uint3_t tn,
+ template (value) octetstring data) := {
+ header := ts_L1ctlHeader(L1CTL_GPRS_UL_BLOCK_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ ul_block_req := {
+ hdr := {
+ fn := fn,
+ tn := tn,
+ pad := '000000'O
+ },
+ data := data
+ }
+ }
+ };
+ template L1ctlMessage
+ tr_L1CTL_GPRS_UL_BLOCK_REQ(template (present) GsmFrameNumber fn := ?,
+ template (present) uint3_t tn := ?,
+ template (present) octetstring data := ?) := {
+ header := tr_L1ctlHeader(L1CTL_GPRS_UL_BLOCK_REQ),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ ul_block_req := {
+ hdr := {
+ fn := fn,
+ tn := tn,
+ pad := ?
+ },
+ data := data
+ }
+ }
+ };
+
+ template (value) L1ctlMessage
+ ts_L1CTL_GPRS_DL_BLOCK_IND(template (value) GsmFrameNumber fn,
+ template (value) uint3_t tn,
+ template (value) uint3_t usf,
+ template (value) octetstring data,
+ template (value) uint16_t ber10k := 0,
+ template (value) int16_t ci_cb := 180 /* 18 dB */,
+ template (value) GsmRxLev rx_level := 63) := {
+ header := ts_L1ctlHeader(L1CTL_GPRS_DL_BLOCK_IND),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ dl_block_ind := {
+ hdr := {
+ fn := fn,
+ tn := tn,
+ pad := '000000'O
+ },
+ meas := {
+ ber10k := ber10k,
+ ci_cb := ci_cb,
+ rx_level := rx_level
+ },
+ usf := usf,
+ data := data
+ }
+ }
+ };
+ template L1ctlMessage
+ tr_L1CTL_GPRS_DL_BLOCK_IND(template (present) GsmFrameNumber fn := ?,
+ template (present) uint3_t tn := ?,
+ template (present) uint3_t usf := ?,
+ template (present) octetstring data := ?,
+ template (present) uint16_t ber10k := ?,
+ template (present) int16_t ci_cb := ?,
+ template (present) GsmRxLev rx_level := ?) := {
+ header := tr_L1ctlHeader(L1CTL_GPRS_DL_BLOCK_IND),
+ ul_info := omit,
+ dl_info := omit,
+ payload := {
+ dl_block_ind := {
+ hdr := {
+ fn := fn,
+ tn := tn,
+ pad := ?
+ },
+ meas := {
+ ber10k := ber10k,
+ ci_cb := ci_cb,
+ rx_level := rx_level
+ },
+ usf := usf,
+ data := data
+ }
+ }
+ };
+
const octetstring c_DummyUI := '0303012B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B'O;
/* We use "BYTEORDER(last)" so we get little-endian integers. Unfortuantely, this also
diff --git a/library/L3_Common.ttcn b/library/L3_Common.ttcn
index 0a805935..a2c27bfc 100644
--- a/library/L3_Common.ttcn
+++ b/library/L3_Common.ttcn
@@ -29,72 +29,24 @@ type record AuthVector {
OCT14 auts
}
-private function f_rnd_oct(integer len) return octetstring {
- var integer i;
- var octetstring res;
- for (i := 0; i < len; i := i + 1) {
- res[i] := int2oct(float2int(rnd()*256.0), 1);
- }
- return res;
-}
-
function f_gen_auth_vec_2g() return AuthVector {
var AuthVector vec;
- vec.rand := f_rnd_oct(16);
- vec.sres := f_rnd_oct(4);
- vec.kc := f_rnd_oct(8);
+ vec.rand := f_rnd_octstring(16);
+ vec.sres := f_rnd_octstring(4);
+ vec.kc := f_rnd_octstring(8);
return vec;
}
function f_gen_auth_vec_3g() return AuthVector {
var AuthVector vec := f_gen_auth_vec_2g();
- vec.ik := f_rnd_oct(16);
- vec.ck := f_rnd_oct(16);
- vec.autn := f_rnd_oct(16);
- vec.res := f_rnd_oct(8);
- vec.auts := f_rnd_oct(14);
+ vec.ik := f_rnd_octstring(16);
+ vec.ck := f_rnd_octstring(16);
+ vec.autn := f_rnd_octstring(16);
+ vec.res := f_rnd_octstring(8);
+ vec.auts := f_rnd_octstring(14);
return vec;
}
-/* 3GPP TS 23.003 2.6 */
-type enumerated TlliType {
- TLLI_LOCAL,
- TLLI_FOREIGN,
- TLLI_RANDOM,
- TLLI_AUXILIARY,
- TLLI_RESERVED,
- TLLI_G_RNTI,
- TLLI_RAND_G_RNTI
-}
-
-/* 3GPP TS 23.003 2.6 */
-function f_gprs_tlli_type(OCT4 tlli) return TlliType {
- var bitstring tllib := oct2bit(tlli);
- if (substr(tllib, 0, 2) == '11'B) {
- return TLLI_LOCAL;
- } else if (substr(tllib, 0, 2) == '10'B) {
- return TLLI_FOREIGN;
- } else if (substr(tllib, 0, 5) == '01111'B) {
- return TLLI_RANDOM;
- } else if (substr(tllib, 0, 4) == '0110'B) {
- return TLLI_RESERVED;
- } else if (substr(tllib, 0, 3) == '010'B) {
- return TLLI_RESERVED;
- } else if (substr(tllib, 0, 4) == '0000'B) {
- return TLLI_G_RNTI;
- } else if (substr(tllib, 0, 4) == '0001'B) {
- return TLLI_RAND_G_RNTI;
- } else {
- setverdict(fail, "Unknonw TLLI Type ", tllib);
- mtc.stop;
- }
-}
-
-function f_gprs_tlli_random() return OCT4 {
- var OCT4 tlli := f_rnd_octstring(4);
- return tlli or4b 'c0000000'O;
-}
-
function f_RAI(HEX0_3n mcc, HEX0_3n mnc, OCT2 lac, OCT1 rac) return RoutingAreaIdentificationV {
if (lengthof(mnc) == 2) {
mnc := mnc & 'F'H;
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
index 1bfcec09..710b0eab 100644
--- a/library/L3_Templates.ttcn
+++ b/library/L3_Templates.ttcn
@@ -20,7 +20,6 @@ import from MobileL3_RRM_Types all;
import from MobileL3_CC_Types all;
import from MobileL3_GMM_SM_Types all;
import from MobileL3_SMS_Types all;
-import from RLCMAC_CSN1_Templates all;
/* TS 24.007 Table 11.3 TI Flag */
const BIT1 c_TIF_ORIG := '0'B;
@@ -63,6 +62,23 @@ template ML3_Cause_TLV ts_ML3_Cause(BIT7 cause, BIT4 loc := '0001'B, BIT2 std :=
diagnostics := omit
}
+template ML3_Cause_LV ts_ML3_Cause_LV(BIT7 cause, BIT4 loc := '0001'B, BIT2 std := '11'B) := {
+ lengthIndicator := 0, /* overwritten */
+ oct3 := {
+ location := loc,
+ spare1_1 := '0'B,
+ codingStandard := std,
+ ext1 := '0'B,
+ recommendation := omit,
+ ext2 := omit
+ },
+ oct4 := {
+ causeValue := cause,
+ ext3 := '1'B
+ },
+ diagnostics := omit
+}
+
/* 3GPP TS 24.008, section 10.5.1.4 "Mobile Identity" */
template (value) MobileIdentityTLV ts_MI_TLV(template (value) MobileIdentityV mi) := {
@@ -117,7 +133,7 @@ return template (present) IMSI_L3 {
return f_enc_IMSI_L3(valueof(digits))
}
}
-template MobileIdentityV tr_MI_IMSI(template hexstring imsi) := {
+template MobileIdentityV tr_MI_IMSI(template (present) hexstring imsi) := {
typeOfIdentity := '001'B,
oddEvenInd_identity := {
imsi := f_tr_MI_IMSI(imsi)
@@ -161,6 +177,9 @@ function ts_MI_TMSI_TLV(template (omit) OCT4 tmsi) return template (omit) Mobile
}
}
+template MobileIdentityLV ts_MI_TMSI_NRI_LV(integer nri_v, integer nri_bitlen := 10) :=
+ ts_MI_TMSI_LV(tmsi := f_gen_tmsi(suffix := 0, nri_v := nri_v, nri_bitlen := nri_bitlen));
+
template MobileIdentityTLV ts_MI_IMEISV_TLV(hexstring imeisv) := {
elementIdentifier := '0100011'B,
spare1 := '0'B,
@@ -297,8 +316,9 @@ template LocationUpdatingType LU_Type_IMSI_Attach := {
};
/* Send template for LOCATION UPDATING REQUEST */
-template PDU_ML3_MS_NW ts_LU_REQ(template LocationUpdatingType lu_type, MobileIdentityLV mi_lv,
- OCT3 mcc_mnc := '123456'O) := {
+template (value) PDU_ML3_MS_NW ts_LU_REQ(template (value) LocationUpdatingType lu_type,
+ template (value) MobileIdentityLV mi_lv,
+ template (value) OCT3 mcc_mnc := '123456'O) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
skipIndicator := '0000'B
@@ -373,6 +393,44 @@ template (value) PDU_ML3_MS_NW ts_CM_SERV_REQ(CmServiceType serv_type, MobileIde
}
}
+template (value) PDU_ML3_NW_MS ts_CM_SERV_REJ(OCT1 rejectCause) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ mm := {
+ cMServiceReject := {
+ messageType := '000000'B, /* overwritten */
+ nsd := '00'B,
+ rejectCause := rejectCause,
+ t3246_Value := omit
+ }
+ }
+ }
+}
+
+template (value) PDU_ML3_MS_NW ts_CM_REESTABL_REQ(MobileIdentityLV mi_lv) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ mm := {
+ cMReEstablReq := {
+ messageType := '000000'B, /* overwritten */
+ nsd := '00'B,
+ cipheringKeySequenceNumber := { '000'B, '0'B },
+ spare := '0000'B,
+ mobileStationClassmark2 := ts_CM2,
+ mobileIdentityLV := mi_lv,
+ locationAreaIdentification := omit,
+ deviceProperties := omit
+ }
+ }
+ }
+}
+
template (value) CipheringKeySequenceNumberV ts_CKSN(integer key_seq) := {
keySequence := int2bit(key_seq, 3),
spare := '0'B
@@ -512,7 +570,7 @@ template PDU_ML3_NW_MS tr_PAGING_REQ3(template TMSIP_TMSI_V mi1 := ?,
/* Send template for PAGING RESPONSE */
-template (value) PDU_ML3_MS_NW ts_PAG_RESP(MobileIdentityLV mi_lv) := {
+template (value) PDU_ML3_MS_NW ts_PAG_RESP(template (value) MobileIdentityLV mi_lv) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
skipIndicator := '0000'B
@@ -531,7 +589,51 @@ template (value) PDU_ML3_MS_NW ts_PAG_RESP(MobileIdentityLV mi_lv) := {
}
}
-template (value) PDU_ML3_MS_NW ts_RRM_ModeModifyAck(ChannelDescription2_V desc, ChannelMode_V mode) := {
+template ChannelDescription2_V tr_ChannelDescription2_V(template BIT3 timeslotNumber := ?,
+ template BIT5 channelTypeandTDMAOffset := ?) := {
+ timeslotNumber := timeslotNumber,
+ channelTypeandTDMAOffset := channelTypeandTDMAOffset,
+ octet3 := ?,
+ octet4 := ?
+}
+
+template ChannelMode_V tr_ChannelMode_V(template OCT1 mode) := {
+ mode := mode
+}
+
+template ExtendedTSCSet_TV tr_ExtendedTSCSet_TV(template BIT2 cSDomainTSCSet := ?) := {
+ elementIdentifier := '6D'O,
+ cSDomainTSCSet := cSDomainTSCSet,
+ secondPSDomainTSCAssigned := ?,
+ primaryPSDomainTSCSet := ?,
+ secondaryPSDomainTSCSet := ?,
+ secondaryPSDomainTSCValue := ?
+}
+
+template PDU_ML3_NW_MS tr_RRM_ModeModify(template ChannelDescription2_V desc := ?,
+ template ChannelMode_V mode := ?,
+ template ExtendedTSCSet_TV extendedTSCSet) := {
+ discriminator := '0110'B,
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ channelModeModify := {
+ messageType := '00010000'B,
+ channelDescription := desc,
+ channelMode := mode,
+ vGCS_TargetModeIndication := omit,
+ multiRateConfiguration := omit,
+ vGCS_Ciphering_Parameters := omit,
+ extendedTSCSet := extendedTSCSet
+ }
+ }
+ }
+}
+
+template (value) PDU_ML3_MS_NW ts_RRM_ModeModifyAck(ChannelDescription2_V desc, ChannelMode_V mode,
+ template (omit) ExtendedTSCSet_TV extendedTSCSet := omit) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
skipIndicator := '0000'B
@@ -542,7 +644,7 @@ template (value) PDU_ML3_MS_NW ts_RRM_ModeModifyAck(ChannelDescription2_V desc,
messageType := '00010111'B,
channelDescription := desc,
channelMode := mode,
- extendedTSCSet := omit
+ extendedTSCSet := extendedTSCSet
}
}
}
@@ -585,6 +687,57 @@ template (value) PDU_ML3_MS_NW ts_RRM_CiphModeCompl := {
}
}
+template ChannelMode_TV tr_ChannelMode_TV(template OCT1 mode) := {
+ elementIdentifier := '63'O,
+ mode := mode
+}
+
+template (present) PDU_ML3_NW_MS tr_RR_AssignmentCommand(
+ template ChannelDescription2_V desc := ?,
+ template ChannelMode_TV mode := ?,
+ template ExtendedTSCSet_TV extendedTSCSet := omit
+) := {
+ discriminator := '0110'B,
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ assignmentCommand := {
+ messageType := '00101110'B,
+ descrOf1stChAfterTime := desc,
+ PowerCommand := ?,
+ frequencyList_at := omit,
+ cellChannelDescr := omit,
+ descrMultislotAllocation := omit,
+ modeOf1stChannel := mode,
+ channelSet2 := omit,
+ channelSet3 := omit,
+ channelSet4 := omit,
+ channelSet5 := omit,
+ channelSet6 := omit,
+ channelSet7 := omit,
+ channelSet8 := omit,
+ descrOf2ndChAfterTime := omit,
+ modeOf2ndChannel := omit,
+ mobileAllocation_at := omit,
+ startingTime := omit,
+ frequencyList_bt := omit,
+ descrOf1stCh_bt := omit,
+ descrOf2ndCh_bt := omit,
+ frequencyChannelSequence := omit,
+ mobileAllocation_bt := omit,
+ cipherModeSetting := omit,
+ vGCS_TargetModeIndication := omit,
+ multiRateConfiguration := omit,
+ vGCS_Ciphering_Parameters := omit,
+ extendedTSCSet_afterTime := extendedTSCSet,
+ extendedTSCSet_beforeTime := omit
+ }
+ }
+ }
+}
+
template (value) PDU_ML3_MS_NW ts_RRM_AssignmentComplete(OCT1 cause) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
@@ -862,6 +1015,23 @@ template (value) PDU_ML3_MS_NW ts_RRM_UL_REL(OCT1 cause) := {
}
}
+template (value) PDU_ML3_MS_NW ts_RRM_DTM_ASS_FAIL(OCT1 cause) := {
+ discriminator := '0110'B,
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ dTM_AssignmentFailure := {
+ messageType := '01001000'B,
+ rR_Cause := {
+ valuePart := cause
+ }
+ }
+ }
+ }
+}
+
template PDU_ML3_MS_NW tr_RRM_RR_STATUS(template OCT1 cause := ?) := {
discriminator := '0110'B,
tiOrSkip := {
@@ -911,7 +1081,7 @@ template PDU_ML3_NW_MS tr_RRM_RR_RELEASE(template OCT1 cause := ?) := {
}
}
-template PDU_ML3_NW_MS tr_RRM_RR_RELEASE_CSFB(template OCT1 cause := ?) modifies tr_RRM_RR_RELEASE := {
+template PDU_ML3_NW_MS tr_RRM_RR_RELEASE_CellSelectInd(template OCT1 cause := ?) modifies tr_RRM_RR_RELEASE := {
msgs := {
rrm := {
channelRelease := {
@@ -1104,7 +1274,8 @@ template PDU_ML3_MS_NW ts_ML3_MO_CC(integer tid) := {
tiFlag := c_TIF_ORIG,
tIExtension := omit
}
- }
+ },
+ msgs := -
}
template (value) CalledPartyBCD_Number ts_Called(hexstring digits) := {
@@ -1112,7 +1283,7 @@ template (value) CalledPartyBCD_Number ts_Called(hexstring digits) := {
lengthIndicator := 0, /* overwritten */
numberingPlanIdentification := '0000'B,
typeOfNumber := '000'B, /* unknown */
- ext1 := '0'B,
+ ext1 := '1'B, /* no extension */
digits := digits
}
@@ -1121,7 +1292,7 @@ template CalledPartyBCD_Number tr_Called(template hexstring digits) := {
lengthIndicator := ?,
numberingPlanIdentification := ?,
typeOfNumber := ?,
- ext1 := ?,
+ ext1 := '1'B, /* no extension */
digits := digits
}
@@ -1154,6 +1325,7 @@ template (value) Speech_AuxiliarySpeech ts_SpeechAux(SpeechVer ver, BIT1 suffix)
template (value) Speech_AuxiliarySpeech ts_SpeechAuxFR(SpeechVer ver) := ts_SpeechAux(ver, '0'B);
template (value) Speech_AuxiliarySpeech ts_SpeechAuxHR(SpeechVer ver) := ts_SpeechAux(ver, '1'B);
+/* TS 3GPP 24.008 § 10.5.4.5 */
template (value) BearerCapability_TLV ts_Bcap_voice := {
elementIdentifier := '04'O,
lengthIndicator := 0, /* overwritten */
@@ -1177,6 +1349,86 @@ template (value) BearerCapability_TLV ts_Bcap_voice := {
octet7 := omit
}
+/* TS 3GPP 24.008 § 10.5.4.5 */
+template (value) BearerCapability_TLV ts_Bcap_csd := {
+ elementIdentifier := '04'O,
+ lengthIndicator := 0, /* overwritten */
+ octet3 := {
+ informationTransferCapability := '001'B,
+ transferMode := '0'B,
+ codingStandard := '0'B,
+ radioChannelRequirement := '11'B,
+ extension_octet_3 := '0'B,
+ speech_aux_3a_3b := omit
+ },
+ octet4 := {
+ establishment := '0'B,
+ nirr := '1'B,
+ configuration := '0'B,
+ duplexMode := '1'B,
+ structure := '00'B,
+ compression := '0'B,
+ extension_octet_4 := '1'B
+ },
+ octet5 := {
+ signallingAccessProtocol := '001'B,
+ rateAdaptation := '01'B, /* V.110 */
+ accessId := '00'B,
+ extension_octet_5 := '0'B,
+ spare2_3 := omit,
+ otherRateAdaptation := omit,
+ otherInformationTransferCapability := omit,
+ extension_octet_5a := omit,
+ spare3_1 := omit,
+ inbandNegotiation := omit,
+ assignor_assignee := omit,
+ lli := omit,
+ mode := omit,
+ multiframe := omit,
+ hdrNohdr := omit,
+ extension_octet_5b := omit
+ },
+ octet6 := {
+ synchronous_asynchronous := '1'B, /* 0: sync, 1: async */
+ userInformationLayer1Protocol := '0000'B,
+ layer1Id := '01'B,
+ extension_octet_6 := '0'B,
+ /* octet 6a */
+ userRate := '0100'B, /* 4.8 kbit/s */
+ numberDataBits := '0'B,
+ negotiation := '0'B,
+ numberStopBits := '0'B,
+ extension_octet_6a := '1'B,
+ /* octet 6b */
+ parity := '000'B,
+ nicOnRX := '0'B,
+ nicOnTX := '0'B,
+ intermediateRate := '10'B,
+ extension_octet_6b := '1'B,
+ /* octet 6c */
+ modemType := '00000'B,
+ connectionElement := '00'B, /* 00: T / 01: NT */
+ extension_octet_6c := '0'B,
+ /* octet 6d */
+ fixedNetworkUserRate := omit,
+ otherModemType := omit,
+ extension_octet_6d := omit,
+ /* octet 6e */
+ maxNumberOfTrafficChannels := omit,
+ acceptableChannelCodings := omit,
+ extension_octet_6e := omit,
+ wantedAirInterfaceUserRate := omit,
+ uimi := omit,
+ /* octet 6f */
+ extension_octet_6f := omit,
+ spare := omit,
+ asymetryIndication := omit,
+ acceptableChannelCodingsExt := omit,
+ extension_octet_6g := omit
+ },
+ octet7 := omit
+}
+
template PDU_ML3_MS_NW ts_ML3_MO_CC_SETUP(integer tid, hexstring called, template BearerCapability_TLV bcap := ts_Bcap_voice) := {
discriminator := '0011'B,
tiOrSkip := {
@@ -1450,6 +1702,29 @@ template PDU_ML3_NW_MS tr_ML3_MT_CC_DISC(integer tid) := {
}
}
+template PDU_ML3_MS_NW ts_ML3_MO_CC_DISC(integer tid, BIT1 tid_remote, BIT7 cause) := {
+ discriminator := '0011'B,
+ tiOrSkip := {
+ transactionId := {
+ tio := int2bit(tid, 3),
+ tiFlag := tid_remote,
+ tIExtension := omit
+ }
+ },
+ msgs := {
+ cc := {
+ disconnect_MS_NW := {
+ messageType := '100101'B,
+ nsd := '00'B,
+ cause := ts_ML3_Cause_LV(cause),
+ facility := omit,
+ user_user := omit,
+ ss_VersionIndicator := omit
+ }
+ }
+ }
+}
+
template PDU_ML3_NW_MS tr_ML3_MT_CC_RELEASE(integer tid) := {
discriminator := '0011'B,
tiOrSkip := {
@@ -2035,7 +2310,7 @@ template (value) MSNetworkCapabilityV ts_GMM_MsNetCapV := {
smCapabilitiesviaGPRSChannels := '0'B,
ucs2Support := '1'B,
ssScreeningIndicator := '01'B,
- solSACapability := omit,
+ solSACapability := '0'B,
revisionLevelIndicatior := omit,
pFCFeatureMode := omit,
extendedGEAbits := omit,
@@ -2094,6 +2369,58 @@ template (value) DRXParameterV ts_DrxParameterV := {
cnSpecificDRXCycleLength := '0000'B /* SI value used */
};
+private function f_presence_bit_MultislotCap_GPRS(template (omit) MultislotCap_GPRS mscap_gprs) return BIT1 {
+ if (istemplatekind(mscap_gprs, "omit")) {
+ return '0'B;
+ }
+ return '1'B;
+}
+private function f_presence_bit_MultislotCap_EGPRS(template (omit) MultislotCap_EGPRS mscap_egprs) return BIT1 {
+ if (istemplatekind(mscap_egprs, "omit")) {
+ return '0'B;
+ }
+ return '1'B;
+}
+template (value) MSRACapabilityValuesRecord ts_RaCapRec(BIT4 att := '0001'B /* E-GSM */, template (omit) MultislotCap_GPRS mscap_gprs := omit, template (omit) MultislotCap_EGPRS mscap_egprs := omit) := {
+ mSRACapabilityValues := {
+ mSRACapabilityValuesExclude1111 := {
+ accessTechnType := att, /* E-GSM */
+ accessCapabilities := {
+ lengthIndicator := 0, /* overwritten */
+ accessCapabilities := {
+ rfPowerCapability := '001'B, /* FIXME */
+ presenceBitA5 := '0'B,
+ a5bits := omit,
+ esind := '1'B,
+ psbit := '0'B,
+ vgcs := '0'B,
+ vbs := '0'B,
+ presenceBitMultislot := '1'B,
+ multislotcap := {
+ presenceBitHscsd := '0'B,
+ hscsdmultislotclass := omit,
+ presenceBitGprs := f_presence_bit_MultislotCap_GPRS(mscap_gprs),
+ gprsmultislot := mscap_gprs,
+ presenceBitSms := '0'B,
+ multislotCap_SMS := omit,
+ multislotCapAdditionsAfterRel97 := {
+ presenceBitEcsdmulti := '0'B,
+ ecsdmultislotclass := omit,
+ presenceBitEgprsmulti := f_presence_bit_MultislotCap_EGPRS(mscap_egprs),
+ multislotCap_EGPRS := mscap_egprs,
+ presenceBitDtmGprsmulti := '0'B,
+ multislotCapdtmgprsmultislotsubclass := omit
+ }
+ },
+ accessCapAdditionsAfterRel97 := omit
+ },
+ spare_bits := omit
+ }
+ }
+ },
+ presenceBitMSRACap := '0'B
+};
+
template (value) MSRadioAccessCapabilityLV ts_MS_RaCapa := {
lengthIndicator := 0, /* overwritten */
msRadioAccessCapabilityV := {
@@ -2101,11 +2428,23 @@ template (value) MSRadioAccessCapabilityLV ts_MS_RaCapa := {
}
}
+template (value) NetworkResourceIdentifierContainerTLV ts_GMM_NRI(integer nri) := {
+ elementIdentifier := '10'O,
+ networkResourceIdentifierContainerLV := {
+ lengthIndicator := 2,
+ networkResourceIdentifierContainerV := {
+ nRIContainerValue := f_bits_reversed(int2bit(nri, 10)),
+ spare := '000000'B
+ }
+ }
+}
+
template (value) PDU_L3_MS_SGSN
ts_GMM_ATTACH_REQ(MobileIdentityLV mi_lv, RoutingAreaIdentificationV old_ra,
boolean combined := false, boolean follow_on_pending := false,
- template (omit) MobileStationClassmark2_TLV cm2_tlv,
- template (omit) MobileStationClassmark3_TLV cm3_tlv
+ template (omit) MobileStationClassmark2_TLV cm2_tlv := omit,
+ template (omit) MobileStationClassmark3_TLV cm3_tlv := omit,
+ template (omit) NetworkResourceIdentifierContainerTLV nri := omit
) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
@@ -2138,7 +2477,7 @@ template (value) PDU_L3_MS_SGSN
mS_NetworkFeatureSupport := omit,
oldLocationAreaIdentification := omit,
additionalUpdateType := omit,
- tMSIBasedNRIcontainer := omit,
+ tMSIBasedNRIcontainer := nri,
t3324 := omit,
t3312_ExtendedValue := omit,
extendedDRXParameters := omit
@@ -2253,9 +2592,10 @@ template (value) PDU_L3_MS_SGSN
ts_GMM_RAU_REQ(MobileIdentityLV mi_lv, GprsUpdateType upd_type,
RoutingAreaIdentificationV old_ra,
boolean follow_on_pending := false,
- template (omit) MobileStationClassmark2_TLV cm2_tlv,
- template (omit) MobileStationClassmark3_TLV cm3_tlv,
- template (omit) OCT4 p_tmsi := omit
+ template (omit) MobileStationClassmark2_TLV cm2_tlv := omit,
+ template (omit) MobileStationClassmark3_TLV cm3_tlv := omit,
+ template (omit) OCT4 p_tmsi := omit,
+ template (omit) NetworkResourceIdentifierContainerTLV nri := omit
) := {
discriminator := '0000'B, /* overwritten */
tiOrSkip := {
@@ -2290,7 +2630,7 @@ template (value) PDU_L3_MS_SGSN
mS_NetworkFeatureSupport := omit,
oldLocationAreaIdentification := omit,
additionalUpdateType := omit,
- tMSIBasedNRIcontainer := omit,
+ tMSIBasedNRIcontainer := nri,
t3324 := omit,
t3312_ExtendedValue := omit,
extendedDRXParameters := omit
@@ -2574,6 +2914,27 @@ template (value) PDU_L3_MS_SGSN ts_GMM_DET_REQ_MO(BIT3 dtt := c_GMM_DTT_MO_GPRS,
}
}
+template (value) PDU_L3_MS_SGSN ts_GMM_DET_REQ_MO_mi(BIT3 dtt := c_GMM_DTT_MO_GPRS,
+ boolean power_off := false,
+ template (value) MobileIdentityTLV p_tmsi,
+ template (omit) OCT3 p_tmsi_sig := omit) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ gprs_mm := {
+ detachRequest_MS_SGSN := {
+ messageType := '00000000'B, /* overwritten */
+ detachType := valueof(ts_GMM_DetType(dtt, power_off)),
+ spare := '0000'B,
+ ptmsi := p_tmsi,
+ ptmsiSignature := ts_PtmsiSigTLV(p_tmsi_sig)
+ }
+ }
+ }
+}
+
template PDU_L3_SGSN_MS tr_GMM_DET_ACCEPT_MT := {
discriminator := '1000'B,
tiOrSkip := {
@@ -2916,26 +3277,6 @@ template (value) PDU_L3_MS_SGSN ts_SM_DEACT_PDP_ACCEPT_MO(BIT3 tid)
-private function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring {
- var integer suffix_len := tot_len - lengthof(prefix);
- var charstring suffix_ch := int2str(suffix);
- var integer pad_len := suffix_len - lengthof(suffix_ch);
-
- return prefix & int2hex(0, pad_len) & str2hex(suffix_ch);
-}
-
-function f_gen_imei(integer suffix) return hexstring {
- return f_concat_pad(14, '49999'H, suffix);
-}
-
-function f_gen_imsi(integer suffix) return hexstring {
- return f_concat_pad(15, '26242'H, suffix);
-}
-
-function f_gen_msisdn(integer suffix) return hexstring {
- return f_concat_pad(12, '49123'H, suffix);
-}
-
external function enc_MobileIdentityLV(in MobileIdentityLV si) return octetstring
with { extension "prototype(convert) encode(RAW)" };
@@ -3261,6 +3602,91 @@ template (value) PDU_ML3_MS_NW ts_RRM_GprsSuspReq(template (value) OCT4 tlli,
}
}
+template (value) PDU_ML3_NW_MS
+ts_RRM_PhysicalInfo(template (value) OCT1 ta := '00'O) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ physicalInformation := {
+ messageType := '00101101'B,
+ timingAdvance := ta
+ }
+ }
+ }
+}
+template PDU_ML3_NW_MS
+tr_RRM_PhysicalInfo(template (present) OCT1 ta := ?) := {
+ discriminator := '0110'B, /* RRM */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ physicalInformation := {
+ messageType := '00101101'B,
+ timingAdvance := ta
+ }
+ }
+ }
+}
+
+template (value) PDU_ML3_MS_NW ts_ML3_MO_BCC(integer tid, octetstring bcc) := {
+ discriminator := '0001'B,
+ tiOrSkip := {
+ transactionId := {
+ tio := int2bit(tid, 3),
+ tiFlag := c_TIF_ORIG,
+ tIExtension := omit
+ }
+ },
+ msgs := {
+ bcc := bcc
+ }
+}
+template PDU_ML3_NW_MS tr_ML3_MT_BCC(integer tid, template octetstring bcc := ?) := {
+ discriminator := '0001'B,
+ tiOrSkip := {
+ transactionId := {
+ tio := int2bit(tid, 3),
+ tiFlag := c_TIF_REPL,
+ tIExtension := omit
+ }
+ },
+ msgs := {
+ bcc := bcc
+ }
+}
+
+template (value) PDU_ML3_MS_NW ts_ML3_MO_GCC(integer tid, octetstring gcc) := {
+ discriminator := '0000'B,
+ tiOrSkip := {
+ transactionId := {
+ tio := int2bit(tid, 3),
+ tiFlag := c_TIF_ORIG,
+ tIExtension := omit
+ }
+ },
+ msgs := {
+ gcc := gcc
+ }
+}
+template PDU_ML3_NW_MS tr_ML3_MT_GCC(integer tid, template octetstring gcc := ?) := {
+ discriminator := '0000'B,
+ tiOrSkip := {
+ transactionId := {
+ tio := int2bit(tid, 3),
+ tiFlag := c_TIF_REPL,
+ tIExtension := omit
+ }
+ },
+ msgs := {
+ gcc := gcc
+ }
+}
+
}
diff --git a/library/LAPDm_RAW_PT.ttcn b/library/LAPDm_RAW_PT.ttcn
index 77f0452b..f7c18b58 100644
--- a/library/LAPDm_RAW_PT.ttcn
+++ b/library/LAPDm_RAW_PT.ttcn
@@ -14,15 +14,18 @@
module LAPDm_RAW_PT {
import from GSM_Types all;
import from GSM_RR_Types all;
+ import from GSM_RestOctets all;
import from Osmocom_Types all;
import from L1CTL_Types all;
import from L1CTL_PortType all;
import from LAPDm_Types all;
import from RLCMAC_Types all;
+ type record length(8) of uint8_t TfiUsfArr;
+
/* request to tune to a given ARFCN and start BCCH decoding */
type record BCCH_tune_req {
- Arfcn arfcn,
+ GsmBandArfcn arfcn,
boolean combined_ccch
}
@@ -39,7 +42,7 @@ module LAPDm_RAW_PT {
/* directly switch to a dedicated channel (without RACH/IMM.ASS */
type record DCCH_switch_req {
ChannelDescription chan_desc,
- L1ctlMA ma
+ L1ctlMA ma optional
}
type record DCCH_switch_res {
@@ -102,7 +105,7 @@ module LAPDm_RAW_PT {
GprsCodingScheme cs,
uint8_t ts_nr,
GsmFrameNumber fn,
- Arfcn arfcn,
+ GsmBandArfcn arfcn,
RlcmacUlBlock block
}
type union RLCMAC_ph_data_req {
@@ -198,7 +201,8 @@ module LAPDm_RAW_PT {
}
/* tune to given ARFCN and start BCCH/CCCH decoding */
- private function f_tune_bcch(Arfcn arfcn, boolean combined) runs on lapdm_CT {
+ private function f_tune_bcch(GsmBandArfcn arfcn, boolean combined)
+ runs on lapdm_CT {
var L1ctlCcchMode mode := CCCH_MODE_NON_COMBINED;
if (combined) {
mode := CCCH_MODE_COMBINED;
@@ -274,7 +278,8 @@ module LAPDm_RAW_PT {
}
template (value) RLCMAC_ph_data_req ts_PH_DATA_ABS(uint8_t tbf_id, GprsCodingScheme cs,
- uint8_t ts, uint32_t fn, Arfcn arfcn,
+ uint8_t ts, uint32_t fn,
+ GsmBandArfcn arfcn,
RlcmacUlBlock block) := {
abs := {
tbf_id := tbf_id,
@@ -319,7 +324,7 @@ module LAPDm_RAW_PT {
/* Important: ARFCN, TN, TSC, USF, USF_GRANULARITY, CH_CODING_CMD */
f_TfiUsfArrSet(tua, imm_ass.pkt_chan_desc.tn, pkt_ul_ass.dynamic.usf);
- f_L1CTL_TBF_CFG(L1CTL, true, tua);
+ // FIXME: f_L1CTL_TBF_CFG(L1CTL, true, tua);
return true;
/* FIXME: Single Block Allocation */
} else if (match(pkt_ul_ass, tr_PacketUlSglAssign)) {
@@ -334,8 +339,8 @@ module LAPDm_RAW_PT {
private function f_release_tbf() runs on lapdm_CT {
var TfiUsfArr tua := f_TfiUsfArrInit();
/* send "all timeslots unused" for both UL and DL */
- f_L1CTL_TBF_CFG(L1CTL, true, tua);
- f_L1CTL_TBF_CFG(L1CTL, false, tua);
+ // FIXME: f_L1CTL_TBF_CFG(L1CTL, true, tua);
+ // FIXME: f_L1CTL_TBF_CFG(L1CTL, false, tua);
/* L1 will then fall back to BCCH/CCCH */
set_ph_state(PH_STATE_BCH);
}
@@ -371,7 +376,7 @@ module LAPDm_RAW_PT {
mtc.stop;
}
g_tbf_dl[tbf_nr] := tbf_dl_req.pars;
- f_L1CTL_TBF_CFG(L1CTL, false, tbf_dl_req.pars.tfi);
+ // FIXME: f_L1CTL_TBF_CFG(L1CTL, false, tbf_dl_req.pars.tfi);
set_ph_state(PH_STATE_TBF);
log("Established DL TBF ", tbf_nr, ": ", tbf_dl_req.pars);
}
@@ -386,7 +391,7 @@ module LAPDm_RAW_PT {
}
function ScanEvents() runs on lapdm_CT {
- var L1ctlDlMessage dl;
+ var L1ctlMessage dl;
var BCCH_tune_req bt;
var LAPDm_ph_data lpd;
var RLCMAC_ph_data_ind rpdi;
@@ -492,7 +497,7 @@ module LAPDm_RAW_PT {
link_id := valueof(ts_RslLinkID_SACCH(lpd.sapi));
buf := f_pad_oct(enc_LapdmFrame(lpd.lapdm), 21, '2B'O);
var SacchL1Header l1h := valueof(ts_SacchL1Header(ms_power_lvl,
- false, timing_adv));
+ timing_adv));
L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(chan_desc.chan_nr, link_id,
l1h, buf));
} else {
@@ -534,12 +539,12 @@ module LAPDm_RAW_PT {
var octetstring buf;
if (ischosen(rpdr.dyn)) {
buf := enc_RlcmacUlBlock(rpdr.dyn.block);
- L1CTL.send(ts_L1CTL_DATA_TBF_REQ(buf, L1CTL_CS1, rpdr.dyn.tbf_id));
+ // FIXME: L1CTL.send(ts_L1CTL_DATA_TBF_REQ(buf, L1CTL_CS1, rpdr.dyn.tbf_id));
} else {
buf := enc_RlcmacUlBlock(rpdr.abs.block);
- L1CTL.send(ts_L1CTL_DATA_ABS_REQ(buf, rpdr.abs.arfcn,
- rpdr.abs.ts_nr, rpdr.abs.fn,
- L1CTL_CS1, rpdr.abs.tbf_id));
+ // FIXME: L1CTL.send(ts_L1CTL_DATA_ABS_REQ(buf, rpdr.abs.arfcn,
+ // rpdr.abs.ts_nr, rpdr.abs.fn,
+ // L1CTL_CS1, rpdr.abs.tbf_id));
}
}
diff --git a/library/LAPDm_Types.ttcn b/library/LAPDm_Types.ttcn
index caccc12b..4d028633 100644
--- a/library/LAPDm_Types.ttcn
+++ b/library/LAPDm_Types.ttcn
@@ -166,7 +166,7 @@ module LAPDm_Types {
external function dec_LapdmCtrlU(in octetstring stream) return LapdmCtrlU
with { extension "prototype(convert) decode(RAW)" };
- /* Formats B, Bter and B4 are used on DCCHs for frames containing an information field:
+ /* Formats B, Bter and B4 are used on DCCHs for frames containing an information field:
/* - format Bter is used on request of higher layers if and only if short L2 header type 1 is
* supported and a UI command is to be transmitted on SAPI 0 */
/* - format B4 is used for UI frames transmitted by the network on SACCH; */
@@ -180,7 +180,8 @@ module LAPDm_Types {
uint6_t len,
boolean m,
uint1_t el,
- octetstring payload /* zero-length in Frame A */
+ octetstring payload, /* zero-length in Frame A */
+ octetstring padding
} with { variant (len) "LENGTHTO(payload)"
variant "FIELDORDER(msb)" };
@@ -210,10 +211,20 @@ module LAPDm_Types {
external function dec_LapdmFrameBbis(in octetstring stream) return LapdmFrameBbis
with { extension "prototype(convert) decode(RAW)" };
+ type record LapdmFrameBter {
+ octetstring payload
+ } with { variant "" };
+
+ external function enc_LapdmFrameBter(in LapdmFrameBter si) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+ external function dec_LapdmFrameBter(in octetstring stream) return LapdmFrameBter
+ with { extension "prototype(convert) decode(RAW)" };
+
type union LapdmFrame {
LapdmFrameAB ab,
LapdmFrameBbis bbis,
- LapdmFrameB4 b4
+ LapdmFrameB4 b4,
+ LapdmFrameBter bter
} with { variant "" };
external function enc_LapdmFrame(in LapdmFrame si) return octetstring
@@ -230,7 +241,8 @@ module LAPDm_Types {
len := 0, /* overwritten in encoder */
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ''O
}
}
template LapdmFrame tr_LAPDm_SABM(template LapdmSapi sapi, template boolean c_r,
@@ -241,7 +253,8 @@ module LAPDm_Types {
len := ?,
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ?
}
}
@@ -253,7 +266,8 @@ module LAPDm_Types {
len := 0, /* overwritten in encoder */
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ''O
}
}
template LapdmFrame tr_LAPDm_UA(template LapdmSapi sapi, template boolean c_r,
@@ -264,7 +278,8 @@ module LAPDm_Types {
len := ?,
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ?
}
}
@@ -275,7 +290,8 @@ module LAPDm_Types {
len := 0, /* overwritten in encoder */
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ''O
}
}
template LapdmFrame tr_LAPDm_DM(template LapdmSapi sapi, template boolean c_r,
@@ -286,7 +302,8 @@ module LAPDm_Types {
len := ?,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ?
}
}
@@ -297,7 +314,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ''O
}
}
template LapdmFrame tr_LAPDm_DISC(template LapdmSapi sapi, template boolean c_r,
@@ -308,7 +326,8 @@ module LAPDm_Types {
len := ?,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ?
}
}
@@ -319,7 +338,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ''O
}
}
template LapdmFrame tr_LAPDm_UI(template LapdmSapi sapi, template boolean c_r,
@@ -330,7 +350,8 @@ module LAPDm_Types {
len := ?,
m := false,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ?
}
}
@@ -350,6 +371,17 @@ module LAPDm_Types {
}
}
+ template LapdmFrame ts_LAPDm_Bter_UI(octetstring l3) := {
+ bter := {
+ payload := l3
+ }
+ }
+ template LapdmFrame tr_LAPDm_Bter_UI(template octetstring l3) := {
+ bter := {
+ payload := l3
+ }
+ }
+
template LapdmFrame tr_LAPDm_I(template LapdmSapi sapi, template boolean c_r,
template boolean p, template uint3_t nr,
template uint3_t ns, template octetstring l3,
@@ -360,7 +392,8 @@ module LAPDm_Types {
len := ?,
m := m,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ?
}
}
template (value) LapdmFrame ts_LAPDm_I(LapdmSapi sapi, boolean c_r, boolean p, uint3_t nr,
@@ -371,7 +404,8 @@ module LAPDm_Types {
len := 0,
m := m,
el := 1,
- payload := l3
+ payload := l3,
+ padding := ''O
}
}
@@ -383,7 +417,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ?
}
}
template (value) LapdmFrame ts_LAPDm_RR(LapdmSapi sapi, boolean c_r,
@@ -394,7 +429,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ''O
}
}
@@ -406,7 +442,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ?
}
}
template (value) LapdmFrame ts_LAPDm_REJ(LapdmSapi sapi, boolean c_r,
@@ -417,7 +454,8 @@ module LAPDm_Types {
len := 0,
m := false,
el := 1,
- payload := ''O
+ payload := ''O,
+ padding := ''O
}
}
diff --git a/library/M3UA_CodecPort.ttcn b/library/M3UA_CodecPort.ttcn
index 94d16d64..e88b6a0d 100644
--- a/library/M3UA_CodecPort.ttcn
+++ b/library/M3UA_CodecPort.ttcn
@@ -15,6 +15,7 @@ module M3UA_CodecPort {
import from IPL4asp_PortType all;
import from IPL4asp_Types all;
+ import from M3UA_CodecPort_CtrlFunct all;
import from M3UA_Types all;
type record M3UA_RecvFrom {
@@ -37,7 +38,7 @@ module M3UA_CodecPort {
type record M3UA_Send {
ConnectionId connId,
- integer stream,
+ integer stream optional,
PDU_M3UA msg
}
@@ -59,14 +60,18 @@ module M3UA_CodecPort {
private function M3UA_to_IPL4_Send(in M3UA_Send pin, out ASP_Send pout) {
pout.connId := pin.connId;
- pout.proto := {
- sctp := {
- sinfo_stream := pin.stream,
- sinfo_ppid := 3,
- remSocks := omit,
- assocId := omit
- }
- };
+ if (ispresent(pin.stream)) {
+ pout.proto := {
+ sctp := {
+ sinfo_stream := pin.stream,
+ sinfo_ppid := 3,
+ remSocks := omit,
+ assocId := omit
+ }
+ };
+ } else {
+ pout.proto := { tcp := { } };
+ }
pout.msg := enc_PDU_M3UA(pin.msg);
} with { extension "prototype(fast)" };
@@ -80,5 +85,12 @@ module M3UA_CodecPort {
in(ASP_RecvFrom -> M3UA_RecvFrom: function(IPL4_to_M3UA_RecvFrom);
ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
ASP_Event -> ASP_Event: simple)"
+ };
+
+ function f_set_tcp_segmentation(M3UA_CODEC_PT pt, ConnectionId connId) {
+ /* Set function for dissecting the binary stream into packets */
+ var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
+ /* Offset: 4, size of length: 4, delta: 0, multiplier: 1, big-endian */
+ M3UA_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(pt, connId, vl_f, {4, 4, 0, 1, 0});
}
}
diff --git a/library/M3UA_CodecPort_CtrlFunct.ttcn b/library/M3UA_CodecPort_CtrlFunct.ttcn
index fc38e43f..6f06e2c4 100644
--- a/library/M3UA_CodecPort_CtrlFunct.ttcn
+++ b/library/M3UA_CodecPort_CtrlFunct.ttcn
@@ -40,5 +40,12 @@ module M3UA_CodecPort_CtrlFunct {
out UserData userData
) return Result;
+ external function f_IPL4_setGetMsgLen(
+ inout M3UA_CODEC_PT portRef,
+ in ConnectionId id,
+ inout f_IPL4_getMsgLen f,
+ in ro_integer msgLenArgs
+ )
+
}
diff --git a/library/M3UA_CodecPort_CtrlFunctDef.cc b/library/M3UA_CodecPort_CtrlFunctDef.cc
index 62533dee..7ddacdc4 100644
--- a/library/M3UA_CodecPort_CtrlFunctDef.cc
+++ b/library/M3UA_CodecPort_CtrlFunctDef.cc
@@ -51,6 +51,15 @@ namespace M3UA__CodecPort__CtrlFunct {
{
return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
}
+
+ void f__IPL4__setGetMsgLen(
+ M3UA__CodecPort::M3UA__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ Socket__API__Definitions::f__getMsgLen& f,
+ const Socket__API__Definitions::ro__integer& msgLenArgs)
+ {
+ return f__IPL4__PROVIDER__setGetMsgLen(portRef, connId, f, msgLenArgs);
+ }
}
diff --git a/library/M3UA_Templates.ttcn b/library/M3UA_Templates.ttcn
index 1063b501..3667ca0b 100644
--- a/library/M3UA_Templates.ttcn
+++ b/library/M3UA_Templates.ttcn
@@ -17,6 +17,9 @@ import from Osmocom_Types all;
const OCT1 c_M3UA_VERSION := '01'O;
+const OCT1 c_M3UA_NI_NATIONAL := '02'O;
+const OCT1 c_M3UA_NI_INTERNATIONAL := '00'O;
+
const OCT2 c_M3UA_ST_T_STATE_CHG := '0001'O;
const OCT2 c_M3UA_ST_I_RESERVED := '0001'O;
const OCT2 c_M3UA_ST_I_AS_INACTIVE := '0002'O;
@@ -379,6 +382,218 @@ template (present) PDU_M3UA tr_M3UA_ASPIA_ACK(template OCT4 rctx) := {
}
}
+/***********************************************************************
+ * SSNM Class
+ ***********************************************************************/
+
+template (value) M3UA_Point_Code ts_M3UA_PC(uint24_t pc, uint8_t mask := 0) := {
+ mask := int2oct(mask, 1),
+ affected_Point_Code := int2oct(pc, 3)
+}
+
+template (value) M3UA_Affected_Point_Codes ts_M3UA_AffPc(template (value) M3UA_Point_Codes pcs) := {
+ tag := '0012'O,
+ lengthInd := 0,
+ pointCodes := pcs
+}
+template (present) M3UA_Affected_Point_Codes tr_M3UA_AffPc(template (present) M3UA_Point_Codes pcs) := {
+ tag := '0012'O,
+ lengthInd := ?,
+ pointCodes := pcs
+}
+
+template (value) M3UA_User_Cause ts_M3UA_UserCause(template (value) OCT2 cause,
+ template (value) OCT2 user) := {
+ tag := '0204'O,
+ lengthInd := 0,
+ cause := cause,
+ user := user
+}
+template (present) M3UA_User_Cause tr_M3UA_UserCause(template (present) OCT2 cause,
+ template (present) OCT2 user) := {
+ tag := '0204'O,
+ lengthInd := ?,
+ cause := cause,
+ user := user
+}
+
+template (value) PDU_M3UA ts_M3UA_DUNA(template (value) M3UA_Point_Codes affected_pcs,
+ template (omit) OCT4 rctx := omit) := {
+ m3UA_DUNA := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0201'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := omit,
+ routing_Context := ts_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := ts_M3UA_AffPc(affected_pcs),
+ info_String := omit
+ }
+ }
+}
+template (present) PDU_M3UA tr_M3UA_DUNA(template (present) M3UA_Point_Codes affected_pcs := ?,
+ template OCT4 rctx := *):= {
+ m3UA_DUNA := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0201'O,
+ messageLength := ?,
+ messageParameters := {
+ network_Appearance := *,
+ routing_Context := tr_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := tr_M3UA_AffPc(affected_pcs),
+ info_String := *
+ }
+ }
+}
+
+template (value) PDU_M3UA ts_M3UA_DAVA(template (value) M3UA_Point_Codes affected_pcs,
+ template (omit) OCT4 rctx := omit) := {
+ m3UA_DAVA := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0202'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := omit,
+ routing_Context := ts_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := ts_M3UA_AffPc(affected_pcs),
+ info_String := omit
+ }
+ }
+}
+template (present) PDU_M3UA tr_M3UA_DAVA(template (present) M3UA_Point_Codes affected_pcs := ?,
+ template OCT4 rctx := *):= {
+ m3UA_DAVA := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0202'O,
+ messageLength := ?,
+ messageParameters := {
+ network_Appearance := *,
+ routing_Context := tr_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := tr_M3UA_AffPc(affected_pcs),
+ info_String := *
+ }
+ }
+}
+
+template (value) PDU_M3UA ts_M3UA_DAUD(template (value) M3UA_Point_Codes affected_pcs,
+ template (omit) OCT4 rctx := omit) := {
+ m3UA_DAUD := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0203'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := omit,
+ routing_Context := ts_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := ts_M3UA_AffPc(affected_pcs),
+ info_String := omit
+ }
+ }
+}
+template (present) PDU_M3UA tr_M3UA_DAUD(template (present) M3UA_Point_Codes affected_pcs := ?,
+ template OCT4 rctx := *):= {
+ m3UA_DAUD := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0203'O,
+ messageLength := ?,
+ messageParameters := {
+ network_Appearance := *,
+ routing_Context := tr_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := tr_M3UA_AffPc(affected_pcs),
+ info_String := *
+ }
+ }
+}
+
+template (value) PDU_M3UA ts_M3UA_SCON(template (value) M3UA_Point_Codes affected_pcs,
+ template (omit) OCT4 rctx := omit) := {
+ m3UA_SCON := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0204'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := omit,
+ routing_Context := ts_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := ts_M3UA_AffPc(affected_pcs),
+ concerned_Destination := omit,
+ congestion_Indicators := omit,
+ info_String := omit
+ }
+ }
+}
+template (present) PDU_M3UA tr_M3UA_SCON(template (present) M3UA_Point_Codes affected_pcs := ?,
+ template OCT4 rctx := *):= {
+ m3UA_SCON := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0204'O,
+ messageLength := ?,
+ messageParameters := {
+ network_Appearance := *,
+ routing_Context := tr_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := tr_M3UA_AffPc(affected_pcs),
+ concerned_Destination := *,
+ congestion_Indicators := *,
+ info_String := *
+ }
+ }
+}
+
+template (value) PDU_M3UA ts_M3UA_DUPU(template (value) M3UA_Point_Codes affected_pcs,
+ template (value) OCT2 cause,
+ template (value) OCT2 user,
+ template (omit) OCT4 rctx := omit) := {
+ m3UA_DUPU := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0205'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := omit,
+ routing_Context := ts_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := ts_M3UA_AffPc(affected_pcs),
+ user_Cause := ts_M3UA_UserCause(cause, user),
+ info_String := omit
+ }
+ }
+}
+template (present) PDU_M3UA tr_M3UA_DUPU(template (present) M3UA_Point_Codes affected_pcs := ?,
+ template (present) OCT2 cause := ?,
+ template (present) OCT2 user := ?,
+ template OCT4 rctx := *):= {
+ m3UA_DUPU := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0205'O,
+ messageLength := ?,
+ messageParameters := {
+ network_Appearance := *,
+ routing_Context := tr_M3UA_routing_ctx(rctx),
+ affected_Point_Codes := tr_M3UA_AffPc(affected_pcs),
+ user_Cause := tr_M3UA_UserCause(cause, user),
+ info_String := *
+ }
+ }
+}
+
+template (present) PDU_M3UA tr_M3UA_DRST := {
+ m3UA_DRST := {
+ version := c_M3UA_VERSION,
+ reserved := '00'O,
+ messageClassAndType := '0206'O,
+ messageLength := ?,
+ messageParameters := ?
+ }
+}
+
+template (present) PDU_M3UA tr_M3UA_SSNM := (tr_M3UA_DUNA, tr_M3UA_DAVA, tr_M3UA_DAUD,
+ tr_M3UA_SCON, tr_M3UA_DUPU, tr_M3UA_DRST);
/***********************************************************************
* MGMT Class
diff --git a/library/MGCP_CodecPort.ttcn b/library/MGCP_CodecPort.ttcn
index 8614eef1..8819fd8d 100644
--- a/library/MGCP_CodecPort.ttcn
+++ b/library/MGCP_CodecPort.ttcn
@@ -74,10 +74,6 @@ module MGCP_CodecPort {
pout.remPort := pin.remPort;
pout.locName := pin.locName;
pout.locPort := pin.locPort;
- /* FIXME: This should actually be the below:
- pout.msg := dec_MgcpMessage(oct2char(pin.msg)); - see
- https://www.eclipse.org/forums/index.php/t/1088893/
- */
pout.msg := dec_MgcpMessage(oct2char(pin.msg));
} with { extension "prototype(fast)" };
diff --git a/library/MGCP_Emulation.ttcn b/library/MGCP_Emulation.ttcn
index 494b1714..31675799 100644
--- a/library/MGCP_Emulation.ttcn
+++ b/library/MGCP_Emulation.ttcn
@@ -193,6 +193,19 @@ runs on MGCP_Emulation_CT {
mtc.stop;
}
+private function f_ep_table_change_connhdlr(MGCP_ConnHdlr comp_ref, MgcpEndpoint ep)
+runs on MGCP_Emulation_CT {
+ var integer i;
+ for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
+ if (MgcpEndpointTable[i].endpoint == ep) {
+ MgcpEndpointTable[i].comp_ref := comp_ref;
+ log("MGCP_Emulation_CT: MgcpEndpointTable[", i, "] now sends to ", comp_ref);
+ return;
+ }
+ }
+ setverdict(fail, "MGCP Endpoint Table: Couldn't find entry to move to ", comp_ref);
+ mtc.stop;
+}
/* Check if the given transaction ID is a pending CRCX. If yes, return true + remove */
private function f_trans_id_was_pending(MgcpTransId trans_id)
@@ -280,7 +293,7 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
msg := {
response := resp
};
- /* If this is the resposne to a pending CRCX, extract Endpoint and store in table */
+ /* If this is the response to a pending CRCX, extract Endpoint and store in table */
if (f_trans_id_was_pending(resp.line.trans_id)) {
f_ep_table_add(vc_conn, f_mgcp_ep(msg));
}
@@ -291,7 +304,7 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
/* MGCP from client in Multi Conn mode */
[p.multi_conn_mode] MGCP_CLIENT_MULTI.receive(MGCP_SendTo:?) -> value mst sender vc_conn {
- /* If this is the resposne to a pending CRCX, extract Endpoint and store in table */
+ /* If this is the response to a pending CRCX, extract Endpoint and store in table */
if (f_trans_id_was_pending(mst.msg.response.line.trans_id)) {
f_ep_table_add(vc_conn, f_mgcp_ep(mst.msg));
}
@@ -349,6 +362,10 @@ function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_E
f_ep_table_del(vc_conn, ep);
MGCP_PROC.reply(MGCPEM_delete_ep:{ep, vc_conn}) to vc_conn;
}
+ [] MGCP_PROC.getcall(MGCPEM_change_connhdlr:{?,?}) -> param(ep, vc_conn) {
+ f_ep_table_change_connhdlr(vc_conn, ep);
+ MGCP_PROC.reply(MGCPEM_change_connhdlr:{ep, vc_conn}) to vc_conn;
+ }
}
}
@@ -370,9 +387,10 @@ type record ExpectData {
signature MGCPEM_register(in ExpectCriteria cmd, in MGCP_ConnHdlr hdlr);
signature MGCPEM_delete_ep(in MgcpEndpoint ep, in MGCP_ConnHdlr hdlr);
+signature MGCPEM_change_connhdlr(in MgcpEndpoint ep, in MGCP_ConnHdlr hdlr);
type port MGCPEM_PROC_PT procedure {
- inout MGCPEM_register, MGCPEM_delete_ep;
+ inout MGCPEM_register, MGCPEM_delete_ep, MGCPEM_change_connhdlr;
} with { extension "internal" };
function f_get_mgcp_by_crit(ExpectCriteria crit)
@@ -400,7 +418,7 @@ return template MgcpCommand {
return ret;
}
-/* Function that can be used as create_cb and will usse the expect table */
+/* Function that can be used as create_cb and will use the expect table */
function ExpectedCreateCallback(MgcpCommand cmd, charstring id)
runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
var MGCP_ConnHdlr ret := null;
@@ -430,7 +448,7 @@ private function f_create_expect(ExpectCriteria crit, MGCP_ConnHdlr hdlr)
runs on MGCP_Emulation_CT {
var integer i;
- /* Check an entry like this is not already presnt */
+ /* Check an entry like this is not already present */
for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
if (crit == MgcpExpectTable[i].crit) {
setverdict(fail, "Crit already present", crit);
@@ -455,13 +473,20 @@ function f_create_mgcp_expect(ExpectCriteria dest_number) runs on MGCP_ConnHdlr
}
}
-/* client/conn_hdlr side function to use procedure port to create expect in emulation */
+/* client/conn_hdlr side function to use procedure port to delete expect in emulation */
function f_create_mgcp_delete_ep(MgcpEndpoint ep) runs on MGCP_ConnHdlr {
MGCP_PROC.call(MGCPEM_delete_ep:{ep, self}) {
[] MGCP_PROC.getreply(MGCPEM_delete_ep:{?,?}) {};
}
}
+/* Move MGCP handling for a given MGW endpoint to a different MGCP_ConnHdlr component. */
+function f_mgcp_change_connhdlr(MgcpEndpoint ep) runs on MGCP_ConnHdlr {
+ MGCP_PROC.call(MGCPEM_change_connhdlr:{ep, self}) {
+ [] MGCP_PROC.getreply(MGCPEM_change_connhdlr:{?,?}) {};
+ }
+}
+
private function f_expect_table_init()
runs on MGCP_Emulation_CT {
diff --git a/library/MGCP_Templates.ttcn b/library/MGCP_Templates.ttcn
index e03fd8e9..85129e8b 100644
--- a/library/MGCP_Templates.ttcn
+++ b/library/MGCP_Templates.ttcn
@@ -10,473 +10,430 @@ module MGCP_Templates {
*/
- import from MGCP_Types all;
- import from SDP_Types all;
+import from MGCP_Types all;
+import from SDP_Types all;
+import from SDP_Templates all;
- function f_mgcp_par_append(inout template MgcpParameterList list, template MgcpParameter par) {
- var integer len := lengthof(list);
- list[len] := par;
- }
-
- /* 3.2.2.6 Connection Mode (sendonly, recvonly, sendrecv, confrnce, inactive, loopback,
- * conttest, netwloop, netwtest) */
- template MgcpParameter t_MgcpParConnMode(template MgcpConnectionMode mode) := { "M", mode };
-
- /* 3.2.2.2 CallId: maximum 32 hex chars */
- template MgcpParameter ts_MgcpParCallId(MgcpCallId cid) := {
- code := "C",
- val := hex2str(cid)
- };
-
- /* 3.2.2.18 RequestIdentifier: Maximum 32 hex chars */
- template MgcpParameter ts_MgcpParReqId(MgcpRequestId rid) := {
- code := "X",
- val := hex2str(rid)
- };
-
- /* 3.2.1.3 SpecificEndpointId */
- template MgcpParameter ts_MgcpParSpecEP(MgcpEndpoint ep) := {
- code := "Z",
- val := ep
- };
-
- /* 3.2.2.10: LocalConnectionOptions (codec, packetization, bandwidth, ToS, eco, gain, silence, ...) */
- template MgcpParameter t_MgcpParLocConnOpt(template charstring lco) := { "L", lco };
-
- /* 3.2.2.5: ConnectionId: maximum 32 hex chars */
- template MgcpParameter ts_MgcpParConnectionId(MgcpConnectionId cid) := {
- code := "I",
- val := hex2str(cid)
- };
-
- /* Osmocom extension: X-Osmux: {*,%u} */
- template MgcpParameter ts_MgcpParOsmuxCID(MgcpOsmuxCID osmux_cid) := {
- code := "X-OSMUX",
- val := f_mgcp_osmux_cid_encode(osmux_cid)
- };
-
- /* osmo-bsc_mgcp implements L/C/M/X only, osmo-mgw adds 'I' */
- /* SDP: osmo-bsc_mgcp implements Tx of v,o,s,c,t,m,a */
-
- template MgcpResponse tr_MgcpResp_Err(template MgcpResponseCode code) := {
- line := {
- code := code,
- trans_id := ?,
- string := ?
- },
- params := {},
- sdp := omit
- }
+function f_mgcp_par_append(inout template MgcpParameterList list, template MgcpParameter par) {
+ var integer len := lengthof(list);
+ list[len] := par;
+}
- template MgcpCommandLine t_MgcpCmdLine(template charstring verb, template MgcpTransId trans_id, template charstring ep) := {
- verb := verb,
+/* 3.2.2.6 Connection Mode (sendonly, recvonly, sendrecv, confrnce, inactive, loopback,
+ * conttest, netwloop, netwtest) */
+template MgcpParameter t_MgcpParConnMode(template MgcpConnectionMode mode) := { "M", mode };
+
+/* 3.2.2.2 CallId: maximum 32 hex chars */
+template MgcpParameter ts_MgcpParCallId(MgcpCallId cid) := {
+ code := "C",
+ val := hex2str(cid)
+};
+
+/* 3.2.2.18 RequestIdentifier: Maximum 32 hex chars */
+template MgcpParameter ts_MgcpParReqId(MgcpRequestId rid) := {
+ code := "X",
+ val := hex2str(rid)
+};
+
+/* 3.2.1.3 SpecificEndpointId */
+template MgcpParameter ts_MgcpParSpecEP(MgcpEndpoint ep) := {
+ code := "Z",
+ val := ep
+};
+
+/* 3.2.2.10: LocalConnectionOptions (codec, packetization, bandwidth, ToS, eco, gain, silence, ...) */
+template MgcpParameter t_MgcpParLocConnOpt(template charstring lco) := { "L", lco };
+
+/* 3.2.2.5: ConnectionId: maximum 32 hex chars */
+template MgcpParameter ts_MgcpParConnectionId(MgcpConnectionId cid) := {
+ code := "I",
+ val := hex2str(cid)
+};
+
+/* Osmocom extension: X-Osmux: {*,%u} */
+template MgcpParameter ts_MgcpParOsmuxCID(MgcpOsmuxCID osmux_cid) := {
+ code := "X-OSMUX",
+ val := f_mgcp_osmux_cid_encode(osmux_cid)
+};
+
+/* Osmocom extension: X-Osmux: {*,%u} */
+template MgcpParameter t_MgcpParOsmoIGN(template charstring val) := {
+ code := "X-OSMO-IGN",
+ val := val
+};
+
+/* osmo-bsc_mgcp implements L/C/M/X only, osmo-mgw adds 'I' */
+/* SDP: osmo-bsc_mgcp implements Tx of v,o,s,c,t,m,a */
+
+template (value) MgcpResponse
+ts_MgcpResp_Err(template (value) MgcpTransId trans_id,
+ template (value) MgcpResponseCode code,
+ template (value) charstring string := "FAIL") := {
+ line := {
+ code := code,
trans_id := trans_id,
- ep := ep,
- ver := "1.0"
- };
-
- template MgcpCommand ts_CRCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
- line := t_MgcpCmdLine("CRCX", trans_id, ep),
- params := {
- t_MgcpParConnMode(mode),
- ts_MgcpParCallId(call_id),
- //t_MgcpParReqId(omit),
- t_MgcpParLocConnOpt("p:20, a:AMR")
- },
- sdp := sdp
- }
+ string := string
+ },
+ params := {},
+ sdp := omit
+}
+template MgcpResponse
+tr_MgcpResp_Err(template (present) MgcpResponseCode code) := {
+ line := {
+ code := code,
+ trans_id := ?,
+ string := ?
+ },
+ params := {},
+ sdp := omit
+}
- template MgcpCommand ts_CRCX_no_lco(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
- line := t_MgcpCmdLine("CRCX", trans_id, ep),
- params := {
- t_MgcpParConnMode(mode),
- ts_MgcpParCallId(call_id)
- },
- sdp := sdp
- }
+template MgcpCommandLine t_MgcpCmdLine(template charstring verb, template MgcpTransId trans_id, template charstring ep) := {
+ verb := verb,
+ trans_id := trans_id,
+ ep := ep,
+ ver := "1.0"
+};
+
+template MgcpCommand ts_AUEP(MgcpTransId trans_id, charstring ep) := {
+ line := t_MgcpCmdLine("AUEP", trans_id, ep),
+ params := omit,
+ sdp := omit
+}
- template MgcpCommand ts_CRCX_osmux(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
- line := t_MgcpCmdLine("CRCX", trans_id, ep),
- params := {
- t_MgcpParConnMode(mode),
- ts_MgcpParCallId(call_id),
- //t_MgcpParReqId(omit),
- t_MgcpParLocConnOpt("p:20, a:AMR"),
- ts_MgcpParOsmuxCID(osmux_cid)
- },
- sdp := sdp
- }
+template MgcpResponse tr_AUEP_ACK := {
+ line := {
+ code := "200",
+ trans_id := ?,
+ string := "OK"
+ },
+ params:= *,
+ sdp := omit
+}
- template MgcpCommand tr_CRCX(template MgcpEndpoint ep := ?) := {
- line := t_MgcpCmdLine("CRCX", ?, ep),
- params := *,
- sdp := *
- }
+template MgcpCommand ts_CRCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
+ line := t_MgcpCmdLine("CRCX", trans_id, ep),
+ params := {
+ t_MgcpParConnMode(mode),
+ ts_MgcpParCallId(call_id),
+ //t_MgcpParReqId(omit),
+ t_MgcpParLocConnOpt("p:20, a:AMR")
+ },
+ sdp := sdp
+}
- template MgcpResponse tr_CRCX_ACK := {
- line := {
- code := "200",
- trans_id := ?,
- string := "OK"
- },
- params:= { { "I", ? }, *},
- sdp := ?
- }
+template MgcpCommand ts_CRCX_no_lco(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, template SDP_Message sdp := omit) := {
+ line := t_MgcpCmdLine("CRCX", trans_id, ep),
+ params := {
+ t_MgcpParConnMode(mode),
+ ts_MgcpParCallId(call_id)
+ },
+ sdp := sdp
+}
- template MgcpResponse tr_CRCX_ACK_osmux := {
- line := {
- code := "200",
- trans_id := ?,
- string := "OK"
- },
- params:= { { "I", ? }, {"X-OSMUX", ?}, *},
- sdp := ?
- }
+template MgcpCommand ts_CRCX_osmux(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
+ line := t_MgcpCmdLine("CRCX", trans_id, ep),
+ params := {
+ t_MgcpParConnMode(mode),
+ ts_MgcpParCallId(call_id),
+ //t_MgcpParReqId(omit),
+ t_MgcpParLocConnOpt("p:20, a:AMR"),
+ ts_MgcpParOsmuxCID(osmux_cid)
+ },
+ sdp := sdp
+}
- template MgcpResponse ts_CRCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
- line := {
- code := "200",
- trans_id := trans_id,
- string := "OK"
- },
- params:= { ts_MgcpParConnectionId(conn_id) },
- sdp := sdp
- }
+template MgcpCommand tr_CRCX(template MgcpEndpoint ep := ?, template SDP_Message sdp := *) := {
+ line := t_MgcpCmdLine("CRCX", ?, ep),
+ params := *,
+ sdp := sdp
+}
- template MgcpResponse ts_CRCX_ACK_osmux(MgcpTransId trans_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
- line := {
- code := "200",
- trans_id := trans_id,
- string := "OK"
- },
- params:= {
- ts_MgcpParConnectionId(conn_id),
- ts_MgcpParOsmuxCID(osmux_cid)
- },
- sdp := sdp
- }
+template MgcpResponse tr_CRCX_ACK := {
+ line := {
+ code := "200",
+ trans_id := ?,
+ string := "OK"
+ },
+ params:= { { "I", ? }, *},
+ sdp := ?
+}
- template MgcpCommand ts_MDCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
- line := t_MgcpCmdLine("MDCX", trans_id, ep),
- params := {
- t_MgcpParConnMode(mode),
- ts_MgcpParCallId(call_id),
- ts_MgcpParConnectionId(conn_id),
- //t_MgcpParReqId(omit),
- t_MgcpParLocConnOpt("p:20, a:AMR")
- },
- sdp := sdp
- }
+template MgcpResponse tr_CRCX_ACK_osmux := {
+ line := {
+ code := "200",
+ trans_id := ?,
+ string := "OK"
+ },
+ params:= { { "I", ? }, {"X-OSMUX", ?}, *},
+ sdp := ?
+}
- template MgcpCommand ts_MDCX_osmux(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
- line := t_MgcpCmdLine("MDCX", trans_id, ep),
- params := {
- t_MgcpParConnMode(mode),
- ts_MgcpParCallId(call_id),
- ts_MgcpParConnectionId(conn_id),
- //t_MgcpParReqId(omit),
- t_MgcpParLocConnOpt("p:20, a:AMR"),
- ts_MgcpParOsmuxCID(osmux_cid)
- },
- sdp := sdp
- }
+template MgcpResponse ts_CRCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
+ line := {
+ code := "200",
+ trans_id := trans_id,
+ string := "OK"
+ },
+ params:= { ts_MgcpParConnectionId(conn_id) },
+ sdp := sdp
+}
- template MgcpCommand tr_MDCX := {
- line := t_MgcpCmdLine("MDCX", ?, ?),
- params := *,
- sdp := *
- }
+template MgcpResponse ts_CRCX_ACK_osmux(MgcpTransId trans_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
+ line := {
+ code := "200",
+ trans_id := trans_id,
+ string := "OK"
+ },
+ params:= {
+ ts_MgcpParConnectionId(conn_id),
+ ts_MgcpParOsmuxCID(osmux_cid)
+ },
+ sdp := sdp
+}
- template MgcpResponse tr_MDCX_ACK := {
- line := {
- code := "200",
- trans_id := ?,
- string := "OK"
- },
- params := *,
- sdp := ?
- }
+template MgcpCommand ts_MDCX(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := {
+ line := t_MgcpCmdLine("MDCX", trans_id, ep),
+ params := {
+ t_MgcpParConnMode(mode),
+ ts_MgcpParCallId(call_id),
+ ts_MgcpParConnectionId(conn_id),
+ //t_MgcpParReqId(omit),
+ t_MgcpParLocConnOpt("p:20, a:AMR")
+ },
+ sdp := sdp
+}
- template MgcpResponse ts_MDCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
- template MgcpResponse ts_MDCX_ACK_osmux(MgcpTransId trans_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := ts_CRCX_ACK_osmux(trans_id, conn_id, osmux_cid, sdp);
-
- /* have a function that generates a template, rather than a template in order to handle
- * optional parameters */
- function ts_DLCX(MgcpTransId trans_id, charstring ep, template MgcpCallId call_id := omit,
- template MgcpConnectionId conn_id := omit) return template MgcpCommand {
- var template MgcpCommand cmd;
- cmd.line := t_MgcpCmdLine("DLCX", trans_id, ep);
- cmd.params := {};
- cmd.sdp := omit;
- if (isvalue(call_id)) {
- f_mgcp_par_append(cmd.params, ts_MgcpParCallId(valueof(call_id)));
- if (isvalue(conn_id)) {
- f_mgcp_par_append(cmd.params, ts_MgcpParConnectionId(valueof(conn_id)));
- }
- }
- return cmd;
- }
+template MgcpCommand ts_MDCX_osmux(MgcpTransId trans_id, charstring ep, MgcpConnectionMode mode, MgcpCallId call_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := {
+ line := t_MgcpCmdLine("MDCX", trans_id, ep),
+ params := {
+ t_MgcpParConnMode(mode),
+ ts_MgcpParCallId(call_id),
+ ts_MgcpParConnectionId(conn_id),
+ //t_MgcpParReqId(omit),
+ t_MgcpParLocConnOpt("p:20, a:AMR"),
+ ts_MgcpParOsmuxCID(osmux_cid)
+ },
+ sdp := sdp
+}
- template MgcpCommand tr_DLCX(template MgcpEndpoint ep := ?) := {
- line := t_MgcpCmdLine("DLCX", ?, ep),
- params := *,
- sdp := *
- }
+template MgcpCommand tr_MDCX(template SDP_Message sdp := *) := {
+ line := t_MgcpCmdLine("MDCX", ?, ?),
+ params := *,
+ sdp := sdp
+}
- template MgcpResponse tr_DLCX_ACK := {
- line := {
- code := ("200", "250"),
- trans_id := ?,
- string := "OK"
- },
- params:= *,
- sdp := *
- }
+template MgcpResponse tr_MDCX_ACK := {
+ line := {
+ code := "200",
+ trans_id := ?,
+ string := "OK"
+ },
+ params := *,
+ sdp := ?
+}
- template MgcpResponse ts_DLCX_ACK2(MgcpTransId trans_id) := {
- line := {
- code := "250",
- trans_id := trans_id,
- string := "OK"
- },
- params:= { /* list of ConnectionIDs */ },
- sdp := omit
+template MgcpResponse ts_MDCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
+template MgcpResponse ts_MDCX_ACK_osmux(MgcpTransId trans_id, MgcpConnectionId conn_id, MgcpOsmuxCID osmux_cid, template SDP_Message sdp := omit) := ts_CRCX_ACK_osmux(trans_id, conn_id, osmux_cid, sdp);
+
+/* have a function that generates a template, rather than a template in order to handle
+ * optional parameters */
+function ts_DLCX(MgcpTransId trans_id, charstring ep, template MgcpCallId call_id := omit,
+ template MgcpConnectionId conn_id := omit) return template MgcpCommand {
+ var template MgcpCommand cmd;
+ cmd.line := t_MgcpCmdLine("DLCX", trans_id, ep);
+ cmd.params := {};
+ cmd.sdp := omit;
+ if (isvalue(call_id)) {
+ f_mgcp_par_append(cmd.params, ts_MgcpParCallId(valueof(call_id)));
+ if (isvalue(conn_id)) {
+ f_mgcp_par_append(cmd.params, ts_MgcpParConnectionId(valueof(conn_id)));
+ }
}
+ return cmd;
+}
+template MgcpCommand tr_DLCX(template MgcpEndpoint ep := ?) := {
+ line := t_MgcpCmdLine("DLCX", ?, ep),
+ params := *,
+ sdp := *
+}
+template MgcpResponse tr_DLCX_ACK := {
+ line := {
+ code := ("200", "250"),
+ trans_id := ?,
+ string := "OK"
+ },
+ params:= *,
+ sdp := *
+}
- template MgcpResponse ts_DLCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
-
- template MgcpCommand tr_RSIP := {
- line := t_MgcpCmdLine("RSIP", ?, ?),
- params := *,
- sdp := *
- }
-
- /* SDP Templates */
- template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
- charstring session_version := "1",
- charstring addr_type := "IP4",
- charstring user_name := "-") := {
- user_name := user_name,
- session_id := session_id,
- session_version := session_version,
- net_type := "IN",
- addr_type := addr_type,
- addr := addr
- }
+template MgcpResponse ts_DLCX_ACK2(MgcpTransId trans_id) := {
+ line := {
+ code := "250",
+ trans_id := trans_id,
+ string := "OK"
+ },
+ params:= { /* list of ConnectionIDs */ },
+ sdp := omit
+}
- template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
- template integer ttl := omit,
- template integer num_of_addr := omit) :={
- net_type := "IN",
- addr_type := addr_type,
- conn_addr := {
- addr := addr,
- ttl := ttl,
- num_of_addr := num_of_addr
- }
- }
- template SDP_time ts_SDP_time(charstring beg, charstring end) := {
- time_field := {
- start_time := beg,
- stop_time := end
- },
- time_repeat := omit
- }
- template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
- SDP_attribute_list attributes) := {
- media_field := {
- media := "audio",
- ports := {
- port_number := port_number,
- num_of_ports := omit
- },
- transport := "RTP/AVP",
- fmts := fmts
- },
- information := omit,
- connections := omit,
- bandwidth := omit,
- key := omit,
- attributes := attributes
- }
+template MgcpResponse ts_DLCX_ACK(MgcpTransId trans_id, MgcpConnectionId conn_id, template SDP_Message sdp := omit) := ts_CRCX_ACK(trans_id, conn_id, sdp);
- /* master template for generating SDP based in template arguments */
- template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
- charstring session_id, charstring session_version,
- integer rtp_port, SDP_fmt_list fmts,
- SDP_attribute_list attributes) := {
- protocol_version := 0,
- origin := ts_SDP_origin(local_addr, session_id, session_version),
- session_name := "-",
- information := omit,
- uri := omit,
- emails := omit,
- phone_numbers := omit,
- connection := ts_SDP_connection_IP(remote_addr),
- bandwidth := omit,
- times := { ts_SDP_time("0","0") },
- timezone_adjustments := omit,
- key := omit,
- attributes := omit,
- media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
- }
+template MgcpCommand tr_RSIP := {
+ line := t_MgcpCmdLine("RSIP", ?, ?),
+ params := *,
+ sdp := *
+}
- template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
- rtpmap := {
- attr_value := int2str(fmt) & " " & val
- }
- }
- template SDP_attribute ts_SDP_ptime(integer p) := {
- ptime := {
- attr_value := int2str(p)
- }
- }
- template SDP_attribute ts_SDP_fmtp(integer fmt, charstring val) := {
- fmtp := {
- attr_value := int2str(fmt) & " " & val
+function f_mgcp_addr2addrtype(charstring addr) return charstring {
+ for (var integer i := 0; i < lengthof(addr); i := i + 1) {
+ if (addr[i] == ":") {
+ return "IP6";
}
}
+ return "IP4";
+}
- /* -1 is wildcard, positive is translated as string */
- function f_mgcp_osmux_cid_encode(MgcpOsmuxCID osmux_cid) return charstring {
- if (osmux_cid == -1) {
- return "*";
- }
- return int2str(osmux_cid);
+/* -1 is wildcard, positive is translated as string */
+function f_mgcp_osmux_cid_encode(MgcpOsmuxCID osmux_cid) return charstring {
+ if (osmux_cid == -1) {
+ return "*";
}
+ return int2str(osmux_cid);
+}
- function f_mgcp_osmux_cid_decode(charstring osmux_cid) return MgcpOsmuxCID {
- if (osmux_cid == "*") {
- return -1;
- }
- return str2int(osmux_cid);
+function f_mgcp_osmux_cid_decode(charstring osmux_cid) return MgcpOsmuxCID {
+ if (osmux_cid == "*") {
+ return -1;
}
+ return str2int(osmux_cid);
+}
- function f_mgcp_contains_par(MgcpMessage msg, MgcpInfoCode code) return boolean {
- var MgcpParameterList pars;
- if (ischosen(msg.command)) {
- pars := msg.command.params;
- } else {
- pars := msg.response.params;
- }
- for (var integer i := 0; i < lengthof(pars); i := i + 1) {
- var MgcpParameter par := pars[i];
- if (par.code == code) {
- return true;
- }
+function f_mgcp_contains_par(MgcpMessage msg, MgcpInfoCode code) return boolean {
+ var MgcpParameterList pars;
+ if (ischosen(msg.command)) {
+ pars := msg.command.params;
+ } else {
+ pars := msg.response.params;
+ }
+ for (var integer i := 0; i < lengthof(pars); i := i + 1) {
+ var MgcpParameter par := pars[i];
+ if (par.code == code) {
+ return true;
}
- return false;
}
+ return false;
+}
- function f_mgcp_extract_par(MgcpMessage msg, MgcpInfoCode code) return charstring {
- var MgcpParameterList pars;
- if (ischosen(msg.command)) {
- pars := msg.command.params;
- } else {
- pars := msg.response.params;
- }
- for (var integer i := 0; i < lengthof(pars); i := i + 1) {
- var MgcpParameter par := pars[i];
- if (par.code == code) {
- return par.val;
- }
+function f_mgcp_extract_par(MgcpMessage msg, MgcpInfoCode code) return charstring {
+ var MgcpParameterList pars;
+ if (ischosen(msg.command)) {
+ pars := msg.command.params;
+ } else {
+ pars := msg.response.params;
+ }
+ for (var integer i := 0; i < lengthof(pars); i := i + 1) {
+ var MgcpParameter par := pars[i];
+ if (par.code == code) {
+ return par.val;
}
- setverdict(fail, "Could not extract parameters for code ", code);
- return "";
}
+ setverdict(fail, "Could not extract parameters for code ", code);
+ return "";
+}
- function f_MgcpResp_extract_par(MgcpResponse resp, MgcpInfoCode code) return charstring {
- var MgcpMessage msg := {
- response := resp
- }
- return f_mgcp_extract_par(msg, code);
+function f_MgcpResp_extract_par(MgcpResponse resp, MgcpInfoCode code) return charstring {
+ var MgcpMessage msg := {
+ response := resp
}
+ return f_mgcp_extract_par(msg, code);
+}
- function f_MgcpCmd_extract_par(MgcpCommand cmd, MgcpInfoCode code) return charstring {
- var MgcpMessage msg := {
- command := cmd
- }
- return f_mgcp_extract_par(msg, code);
+function f_MgcpCmd_extract_par(MgcpCommand cmd, MgcpInfoCode code) return charstring {
+ var MgcpMessage msg := {
+ command := cmd
}
+ return f_mgcp_extract_par(msg, code);
+}
- function f_MgcpCmd_contains_par(MgcpCommand cmd, MgcpInfoCode code) return boolean {
- var MgcpMessage msg := {
- command := cmd
- }
- return f_mgcp_contains_par(msg, code);
+function f_MgcpCmd_contains_par(MgcpCommand cmd, MgcpInfoCode code) return boolean {
+ var MgcpMessage msg := {
+ command := cmd
}
+ return f_mgcp_contains_par(msg, code);
+}
- function f_MgcpResp_extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
- return str2hex(f_MgcpResp_extract_par(resp, "I"));
- }
+function f_MgcpResp_extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
+ return str2hex(f_MgcpResp_extract_par(resp, "I"));
+}
- function f_MgcpCmd_extract_call_id(MgcpCommand cmd) return MgcpCallId {
- return str2hex(f_MgcpCmd_extract_par(cmd, "C"));
- }
+function f_MgcpCmd_extract_call_id(MgcpCommand cmd) return MgcpCallId {
+ return str2hex(f_MgcpCmd_extract_par(cmd, "C"));
+}
- function f_MgcpCmd_extract_conn_id(MgcpCommand cmd) return MgcpConnectionId {
- return str2hex(f_MgcpCmd_extract_par(cmd, "I"));
- }
+function f_MgcpCmd_extract_conn_id(MgcpCommand cmd) return MgcpConnectionId {
+ return str2hex(f_MgcpCmd_extract_par(cmd, "I"));
+}
- function f_MgcpCmd_extract_osmux_cid(MgcpCommand cmd) return MgcpOsmuxCID {
- return f_mgcp_osmux_cid_decode(f_MgcpCmd_extract_par(cmd, "X-OSMUX"));
- }
+function f_MgcpCmd_extract_osmux_cid(MgcpCommand cmd) return MgcpOsmuxCID {
+ return f_mgcp_osmux_cid_decode(f_MgcpCmd_extract_par(cmd, "X-OSMUX"));
+}
- function f_mgcp_alloc_tid() return MgcpTransId {
- return int2str(float2int(rnd()*2147483647.0));
- }
+function f_mgcp_alloc_tid() return MgcpTransId {
+ return int2str(float2int(rnd()*2147483647.0));
+}
- function f_mgcp_alloc_call_id() return MgcpCallId {
- return int2hex(float2int(rnd()*2147483647.0), 8);
- }
+function f_mgcp_alloc_call_id() return MgcpCallId {
+ return int2hex(float2int(rnd()*2147483647.0), 8);
+}
- function f_mgcp_alloc_conn_id() return MgcpConnectionId {
- return int2hex(float2int(rnd()*2147483647.0), 8);
- }
+function f_mgcp_alloc_conn_id() return MgcpConnectionId {
+ return int2hex(float2int(rnd()*2147483647.0), 8);
+}
- /* those verbs that related to a connection (and hence have ConnectionId) */
- template MgcpVerb tr_MgcpVerb_ConnectionOriented := ("CRCX", "MDCX", "DLCX", "AUCX");
- /* entire command template matching only connection oriented verbs */
- template MgcpCommand tr_MgcpCommand_CO := {
- line := {
- verb := tr_MgcpVerb_ConnectionOriented,
- trans_id := ?,
- ep := ?,
- ver := ?
- },
- params := *,
- sdp := *
- }
+/* those verbs that related to a connection (and hence have ConnectionId) */
+template MgcpVerb tr_MgcpVerb_ConnectionOriented := ("CRCX", "MDCX", "DLCX", "AUCX");
+/* entire command template matching only connection oriented verbs */
+template MgcpCommand tr_MgcpCommand_CO := {
+ line := {
+ verb := tr_MgcpVerb_ConnectionOriented,
+ trans_id := ?,
+ ep := ?,
+ ver := ?
+ },
+ params := *,
+ sdp := *
+}
- function f_mgcp_find_param_entry(MgcpParameterList pars, MgcpInfoCode code, out charstring ret)
- return boolean {
- for (var integer i := 0; i < sizeof(pars); i := i+1) {
- if (pars[i].code == code) {
- ret := pars[i].val;
- return true;
- }
+function f_mgcp_find_param_entry(MgcpParameterList pars, MgcpInfoCode code, out charstring ret)
+return boolean {
+ for (var integer i := 0; i < sizeof(pars); i := i+1) {
+ if (pars[i].code == code) {
+ ret := pars[i].val;
+ return true;
}
- return false;
}
+ return false;
+}
- function f_mgcp_find_param(MgcpMessage msg, MgcpInfoCode code, out charstring ret)
- return boolean {
- var MgcpParameterList pars;
- if (ischosen(msg.command)) {
- pars := msg.command.params;
- } else {
- pars := msg.response.params;
- }
- return f_mgcp_find_param_entry(pars, code, ret);
+function f_mgcp_find_param(MgcpMessage msg, MgcpInfoCode code, out charstring ret)
+return boolean {
+ var MgcpParameterList pars;
+ if (ischosen(msg.command)) {
+ pars := msg.command.params;
+ } else {
+ pars := msg.response.params;
}
+ return f_mgcp_find_param_entry(pars, code, ret);
+}
- /* template to determine if a MGCP endpoint is a wildcard endpoint */
- template charstring t_MGCP_EP_wildcard := (pattern "\*@*", pattern "rtpbridge/\*@*");
+/* template to determine if a MGCP endpoint is a wildcard endpoint */
+template charstring t_MGCP_EP_wildcard := (pattern "\*@*", pattern "rtpbridge/\*@*");
}
diff --git a/library/MGCP_Types.ttcn b/library/MGCP_Types.ttcn
index b56734cf..da1b7f63 100644
--- a/library/MGCP_Types.ttcn
+++ b/library/MGCP_Types.ttcn
@@ -30,8 +30,8 @@ module MGCP_Types {
type charstring MgcpInfoCode ("B", "C", "I", "N", "X", "L", "M", "R",
"S", "D", "O", "P", "E", "Z", "Q", "T",
"RC", "LC", "A", "ES", "RM", "RD", "PL",
- "MD", "X-OSMO-CP", "X-OSMUX") with {
- variant "TEXT_CODING(,convert=upper_case,'([BCINXLMRSDOPEZQTA])|(RC)|(LC)|(ES)|(RM)|(RD)|(PL)|(MD)|(X-OSMO-CP)|(X-OSMUX)',case_insensitive)"
+ "MD", "X-OSMO-CP", "X-OSMO-IGN", "X-OSMUX") with {
+ variant "TEXT_CODING(,convert=upper_case,'([BCINXLMRSDOPEZQTA])|(RC)|(LC)|(ES)|(RM)|(RD)|(PL)|(MD)|(X-OSMO-CP)|(X-OSMO-IGN)|(X-OSMUX)',case_insensitive)"
};
/* 3.2.2.6 */
@@ -128,7 +128,8 @@ module MGCP_Types {
PT_GSMEFR(110),
PT_GSMHR(111),
PT_AMR(112),
- PT_AMRWB(113)
+ PT_AMRWB(113),
+ PT_CSD(120)
}
} with { encode "TEXT" }
diff --git a/library/MNCC_Emulation.ttcn b/library/MNCC_Emulation.ttcn
index be087ec7..85556c1f 100644
--- a/library/MNCC_Emulation.ttcn
+++ b/library/MNCC_Emulation.ttcn
@@ -38,7 +38,7 @@ import from MNCC_Types all;
import from UD_Types all;
modulepar {
- int mp_mncc_version := 6;
+ int mp_mncc_version := 8;
}
/* General "base class" component definition, of which specific implementations
@@ -266,6 +266,11 @@ type record MnccOps {
function main(MnccOps ops, charstring id, charstring sock, boolean role_server := false)
runs on MNCC_Emulation_CT {
+ if (not set_MNCC_version(mp_mncc_version)) {
+ setverdict(fail, "Failed configuring MNCC enc/dec to version ", mp_mncc_version);
+ return;
+ }
+
if (role_server) {
f_listen(sock);
MNCC.send(t_SD_MNCC(g_mncc_ud_id, ts_MNCC_HELLO(version := mp_mncc_version)));
@@ -282,6 +287,7 @@ runs on MNCC_Emulation_CT {
var MNCC_PDU mncc;
var MNCC_ConnHdlr vc_hdlr;
var charstring dest_nr;
+ var uint32_t mncc_call_id;
alt {
/* MNCC -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
@@ -355,6 +361,11 @@ runs on MNCC_Emulation_CT {
MNCC_PROC.reply(MNCCEM_register:{dest_nr, vc_hdlr}) to vc_hdlr;
}
+ [] MNCC_PROC.getcall(MNCCEM_change_connhdlr:{?,?}) -> param(mncc_call_id, vc_hdlr) {
+ f_call_table_del(mncc_call_id);
+ f_call_table_add(vc_hdlr, mncc_call_id);
+ MNCC_PROC.reply(MNCCEM_change_connhdlr:{mncc_call_id, vc_hdlr}) to vc_hdlr;
+ }
}
}
}
@@ -379,9 +390,10 @@ type record ExpectData {
/* procedure based port to register for incoming calls */
signature MNCCEM_register(in charstring dest_nr, in MNCC_ConnHdlr hdlr);
+signature MNCCEM_change_connhdlr(in uint32_t mncc_call_id, in MNCC_ConnHdlr hdlr);
type port MNCCEM_PROC_PT procedure {
- inout MNCCEM_register;
+ inout MNCCEM_register, MNCCEM_change_connhdlr;
} with { extension "internal" };
/* CreateCallback that can be used as create_cb and will use the expectation table */
@@ -440,6 +452,13 @@ function f_create_mncc_expect(charstring dest_number) runs on MNCC_ConnHdlr {
}
}
+/* Move MNCC handling for a given call id to another MNCC_ConnHdlr test component. */
+function f_mncc_change_connhdlr(uint32_t mncc_call_id) runs on MNCC_ConnHdlr {
+ MNCC_PROC.call(MNCCEM_change_connhdlr:{mncc_call_id, self}) {
+ [] MNCC_PROC.getreply(MNCCEM_change_connhdlr:{?,?}) {};
+ }
+}
+
function DummyUnitdataCallback(MNCC_PDU mncc)
runs on MNCC_Emulation_CT return template MNCC_PDU {
log("Ignoring MNCC ", mncc);
diff --git a/library/MNCC_EncDec.cc b/library/MNCC_EncDec.cc
index f2692d7a..0119863e 100644
--- a/library/MNCC_EncDec.cc
+++ b/library/MNCC_EncDec.cc
@@ -5,6 +5,16 @@
namespace MNCC__Types {
+static int mncc_sock_version = MNCC_SOCK_VERSION;
+
+BOOLEAN set__MNCC__version(INTEGER const& version)
+{
+ if (version != 7 && version != 8)
+ return false;
+ mncc_sock_version = version;
+ return true;
+}
+
static void enc_bcap(struct gsm_mncc_bearer_cap *out, const MNCC__bearer__cap& in)
{
out->transfer = in.transfer();
@@ -76,6 +86,7 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
{
struct gsm_mncc mncc;
OCTETSTRING ret_val;
+ TTCN_Buffer ttcn_buffer;
memset(&mncc, 0, sizeof(mncc));
mncc.msg_type = in.msg__type();
@@ -173,6 +184,20 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
strncpy(mncc.imsi, in_sig.imsi(), sizeof(mncc.imsi));
mncc.lchan_type = in_sig.lchan__type();
mncc.lchan_mode = in_sig.lchan__mode();
+ if (in_sig.gcr().is_value()) {
+ const OCTETSTRING &gcr = in_sig.gcr();
+ if (mncc_sock_version < 8)
+ TTCN_error("GCR is only available since MNCCv8");
+ memcpy(&mncc.v8.gcr[0], gcr, sizeof(mncc.v8.gcr));
+ mncc.fields |= MNCC_F_GCR;
+ }
+ if (in_sig.sdp().is_value()) {
+ const CHARSTRING &sdp = in_sig.sdp();
+ if (mncc_sock_version > 7)
+ strncpy(&mncc.v8.sdp[0], sdp, sizeof(mncc.v8.sdp));
+ else
+ strncpy(&mncc.v7.sdp[0], sdp, sizeof(mncc.v7.sdp));
+ }
ret_val = OCTETSTRING(sizeof(mncc), (uint8_t *)&mncc);
}
break;
@@ -188,10 +213,26 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
memset(&rtp, 0, sizeof(rtp));
rtp.msg_type = in.msg__type();
rtp.callref = in.u().rtp().callref();
- rtp.ip = in.u().rtp().ip();
- rtp.port = in.u().rtp().rtp__port();
+ ttcn_buffer.put_string(in.u().rtp().ip());
+ if (in.u().rtp().is__ipv6()) {
+ // if(in.u().rtp().ip().lengthof() != 16) print error
+ rtp.addr.ss_family = AF_INET6;
+ memcpy(&((struct sockaddr_in6*)&rtp.addr)->sin6_addr, ttcn_buffer.get_data(),
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6*)&rtp.addr)->sin6_port = htons(in.u().rtp().rtp__port());
+ } else {
+ // if(in.u().rtp().ip().lengthof() != 4) print error
+ rtp.addr.ss_family = AF_INET;
+ memcpy(&((struct sockaddr_in*)&rtp.addr)->sin_addr, ttcn_buffer.get_data(),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&rtp.addr)->sin_port = htons(in.u().rtp().rtp__port());
+ }
rtp.payload_type = in.u().rtp().payload__type();
rtp.payload_msg_type = in.u().rtp().payload__msg__type();
+ if (in.u().rtp().sdp().is_value()) {
+ const CHARSTRING &sdp = in.u().rtp().sdp();
+ strncpy(rtp.sdp, sdp, sizeof(rtp.sdp));
+ }
ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
break;
case MNCC__MsgUnion::ALT_hello:
@@ -224,6 +265,9 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
const struct gsm_mncc_rtp *in_rtp;
MNCC__PDU__Rtp rtp;
MNCC__MsgUnion u;
+ bool is_ipv6;
+ OCTETSTRING ip;
+ uint16_t port;
in_mncc = (struct gsm_mncc *) ttcn_buffer.get_read_data();
@@ -258,7 +302,23 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
case MNCC_RTP_CONNECT:
case MNCC_RTP_FREE:
in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
- rtp = MNCC__PDU__Rtp(in_rtp->callref, in_rtp->ip, in_rtp->port, in_rtp->payload_type,
+ switch (in_rtp->addr.ss_family) {
+ case AF_INET6:
+ is_ipv6 = true;
+ port = ntohs(((struct sockaddr_in6*)&in_rtp->addr)->sin6_port);
+ ip = OCTETSTRING(sizeof(struct in6_addr),
+ (const unsigned char*)&((struct sockaddr_in6*)&in_rtp->addr)->sin6_addr);
+
+ break;
+ case AF_UNSPEC: //RTP_CREATE and RTP_FREE can contain fully zeroed addr
+ case AF_INET:
+ is_ipv6 = false;
+ port = ntohs(((struct sockaddr_in*)&in_rtp->addr)->sin_port);
+ ip = OCTETSTRING(sizeof(struct in_addr),
+ (const unsigned char*)&((struct sockaddr_in*)&in_rtp->addr)->sin_addr);
+ break;
+ }
+ rtp = MNCC__PDU__Rtp(in_rtp->callref, is_ipv6, ip, port, in_rtp->payload_type,
in_rtp->payload_msg_type, in_rtp->sdp);
u.rtp() = rtp;
break;
@@ -315,7 +375,13 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
sign.imsi() = CHARSTRING(in_mncc->imsi);
sign.lchan__type() = in_mncc->lchan_type;
sign.lchan__mode() = in_mncc->lchan_mode;
- sign.sdp() = in_mncc->sdp;
+ if (mncc_sock_version > 7) {
+ if (in_mncc->fields & MNCC_F_GCR)
+ sign.gcr() = OCTETSTRING(sizeof(in_mncc->v8.gcr), in_mncc->v8.gcr);
+ sign.sdp() = in_mncc->v8.sdp;
+ } else {
+ sign.sdp() = in_mncc->v7.sdp;
+ }
u.signal() = sign;
break;
}
diff --git a/library/MNCC_Types.ttcn b/library/MNCC_Types.ttcn
index 0a8e7d9f..74b9ca9b 100644
--- a/library/MNCC_Types.ttcn
+++ b/library/MNCC_Types.ttcn
@@ -192,6 +192,27 @@ template MNCC_bearer_cap ts_MNCC_bcap_voice := {
data := omit
};
+template MNCC_bearer_cap ts_MNCC_bcap_data := {
+ transfer := 1, /* unrestricted digital information */
+ mode := 0, /* circuit */
+ coding := 0, /* GSM standard */
+ radio := 3, /* FR/HR, FR preferred */
+ speech_ctm := 0, /* not supported */
+ speech_ver := { -1 },
+ data := {
+ rate_adaptation := GSM48_BCAP_RA_V110_X30,
+ sig_access := GSM48_BCAP_SA_NONE,
+ async := 1,
+ nr_stop_bits := 1,
+ nr_data_bits := 1,
+ user_rate := GSM48_BCAP_UR_4800,
+ parity := GSM48_BCAP_PAR_ODD,
+ interm_rate := GSM48_BCAP_IR_8k,
+ transp := GSM48_BCAP_TR_TRANSP,
+ modem_type := GSM48_BCAP_MT_V21
+ }
+};
+
type record MNCC_number {
GSM48_type_of_number number_type,
GSM48_num_plan_ind plan,
@@ -362,6 +383,7 @@ type record MNCC_PDU_Signal {
uint8_t lchan_type, /* empty in OSmoMSC */
uint8_t lchan_mode, /* empty in OsmoMSC */
+ octetstring gcr optional,
charstring sdp optional
};
@@ -373,7 +395,8 @@ type record MNCC_PDU_Data {
type record MNCC_PDU_Rtp {
uint32_t callref,
- uint32_t ip,
+ boolean is_ipv6,
+ octetstring ip,
uint16_t rtp_port,
uint32_t payload_type,
uint32_t payload_msg_type,
@@ -421,6 +444,8 @@ external function enc_MNCC_PDU(in MNCC_PDU pdu) return octetstring;
external function dec_MNCC_PDU(in octetstring stream) return MNCC_PDU;
+external function set_MNCC_version(in integer version) return boolean;
+
template (value) MNCC_PDU ts_MNCC_HELLO(uint32_t version := 5) := {
msg_type := MNCC_SOCKET_HELLO,
u := {
@@ -469,7 +494,8 @@ template MNCC_PDU ts_MNCC_SIMPLE(MNCC_MsgType msg_type, uint32_t call_id) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -500,6 +526,7 @@ template MNCC_PDU tr_MNCC_SIMPLE(template MNCC_MsgType msg_type, template uint32
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -508,12 +535,13 @@ template MNCC_PDU tr_MNCC_SIMPLE(template MNCC_MsgType msg_type, template uint32
/* MT: MSC <- MNCC: SETUP.req from ext. MNCC handler to MSC */
-template MNCC_PDU ts_MNCC_SETUP_req(uint32_t call_id, charstring called, charstring calling, charstring imsi := "") := {
+template MNCC_PDU ts_MNCC_SETUP_req(uint32_t call_id, charstring called, charstring calling, charstring imsi := "",
+ template MNCC_bearer_cap bcap := ts_MNCC_bcap_voice) := {
msg_type := MNCC_SETUP_REQ,
u := {
signal := { /* See 24.008 9.3.23.1 */
callref := call_id,
- bearer_cap := ts_MNCC_bcap_voice, /* mandatory */
+ bearer_cap := valueof(bcap), /* mandatory */
called := valueof(ts_MNCC_number(called)), /* optional */
calling := valueof(ts_MNCC_number(calling)), /* optional */
redirecting := omit, /* optional */
@@ -534,7 +562,8 @@ template MNCC_PDU ts_MNCC_SETUP_req(uint32_t call_id, charstring called, charstr
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
};
@@ -567,6 +596,7 @@ template MNCC_PDU tr_MNCC_SETUP_req(template uint32_t call_id := ?,
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -601,7 +631,8 @@ template MNCC_PDU ts_MNCC_SETUP_rsp(uint32_t call_id, charstring imsi := "",
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
};
@@ -633,6 +664,7 @@ template MNCC_PDU tr_MNCC_SETUP_rsp(template uint32_t call_id,
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -667,6 +699,7 @@ template MNCC_PDU tr_MNCC_SETUP_ind(template uint32_t call_id := ?, template MNC
imsi := imsi,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -700,7 +733,8 @@ template (value) MNCC_PDU ts_MNCC_SETUP_ind(uint32_t call_id, MNCC_number called
imsi := imsi,
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -732,7 +766,8 @@ template MNCC_PDU ts_MNCC_SETUP_CNF(uint32_t call_id, template MNCC_number conne
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -764,6 +799,7 @@ template MNCC_PDU tr_MNCC_SETUP_cnf(uint32_t call_id, template MNCC_number conne
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -806,6 +842,7 @@ template MNCC_PDU tr_MNCC_REJ_req(template uint32_t call_id, template MNCC_cause
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -838,7 +875,8 @@ template MNCC_PDU ts_MNCC_REJ_ind(uint32_t call_id, template MNCC_cause cause :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -872,6 +910,7 @@ template MNCC_PDU tr_MNCC_CALL_CONF_ind(template uint32_t call_id, template MNCC
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -905,7 +944,8 @@ template MNCC_PDU ts_MNCC_CALL_CONF_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -941,7 +981,8 @@ template MNCC_PDU ts_MNCC_CALL_PROC_req(uint32_t call_id, template MNCC_bearer_c
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -975,6 +1016,7 @@ template MNCC_PDU tr_MNCC_CALL_PROC_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1009,7 +1051,8 @@ template MNCC_PDU ts_MNCC_PROGRESS_req(uint32_t call_id, MNCC_progress prog,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1043,7 +1086,8 @@ template MNCC_PDU ts_MNCC_ALERT_req(uint32_t call_id, template MNCC_progress pro
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1076,6 +1120,7 @@ template MNCC_PDU tr_MNCC_ALERT_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1112,6 +1157,7 @@ template MNCC_PDU tr_MNCC_ALERT_ind(template uint32_t call_id, template MNCC_pro
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1145,7 +1191,8 @@ template (value) MNCC_PDU ts_MNCC_ALERT_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1178,7 +1225,8 @@ template MNCC_PDU ts_MNCC_NOTIFY_req(uint32_t call_id, MNCC_notify notify) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1210,6 +1258,7 @@ template MNCC_PDU tr_MNCC_NOTIFY_ind(template uint32_t call_id, template MNCC_no
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1245,6 +1294,7 @@ template MNCC_PDU tr_MNCC_DISC_ind(template uint32_t call_id := ?, template MNCC
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1278,7 +1328,8 @@ template (value) MNCC_PDU ts_MNCC_DISC_ind(uint32_t call_id, template (value) MN
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1313,7 +1364,8 @@ template MNCC_PDU ts_MNCC_DISC_req(uint32_t call_id, MNCC_cause cause,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1347,6 +1399,7 @@ template MNCC_PDU tr_MNCC_DISC_req(template uint32_t call_id,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1381,6 +1434,7 @@ template MNCC_PDU tr_MNCC_REL_ind(template uint32_t call_id := ?, template MNCC_
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1414,7 +1468,8 @@ template (value) MNCC_PDU ts_MNCC_REL_ind(uint32_t call_id,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1447,7 +1502,8 @@ template MNCC_PDU ts_MNCC_REL_req(uint32_t call_id, MNCC_cause cause,
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1478,6 +1534,7 @@ template MNCC_PDU tr_MNCC_REL_req(template uint32_t call_id, template MNCC_cause
imsi := ?,
lchan_type := 0,
lchan_mode := 0,
+ gcr := *,
sdp := *
}
}
@@ -1526,7 +1583,8 @@ template MNCC_PDU ts_MNCC_FACILITY_req(uint32_t call_id, charstring fac) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1558,6 +1616,7 @@ template MNCC_PDU tr_MNCC_FACILITY_ind(template uint32_t call_id := ?, template
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1590,6 +1649,7 @@ template MNCC_PDU tr_MNCC_START_DTMF_ind(template uint32_t call_id := ?, templat
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1622,7 +1682,8 @@ template MNCC_PDU ts_MNCC_START_DTMF_rsp(uint32_t call_id, MNCC_keypad keypad) :
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1654,7 +1715,8 @@ template MNCC_PDU ts_MNCC_START_DTMF_rej(uint32_t call_id, MNCC_cause cause) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1694,6 +1756,7 @@ template MNCC_PDU tr_MNCC_MODIFY_ind(template uint32_t call_id := ?, template MN
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1726,7 +1789,8 @@ template MNCC_PDU ts_MNCC_MODIFY_rsp(uint32_t call_id, MNCC_bearer_cap bcap) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1758,7 +1822,8 @@ template MNCC_PDU ts_MNCC_MODIFY_req(uint32_t call_id, MNCC_bearer_cap bcap) :=
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1791,6 +1856,7 @@ template MNCC_PDU tr_MNCC_MODIFY_cnf(template uint32_t call_id := ?,
imsi := ?,
lchan_type := ?,
lchan_mode := ?,
+ gcr := *,
sdp := *
}
}
@@ -1823,7 +1889,8 @@ template MNCC_PDU ts_MNCC_USERINFO_req(uint32_t call_id, MNCC_useruser uu, integ
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1856,6 +1923,7 @@ template MNCC_PDU tr_MNCC_USERINFO_ind(template uint32_t call_id := ?, template
imsi := "",
lchan_type := 0,
lchan_mode := 0,
+ gcr := *,
sdp := *
}
}
@@ -1896,7 +1964,8 @@ template MNCC_PDU ts_MNCC_HOLD_rej(uint32_t call_id, MNCC_cause cause) := {
imsi := "",
lchan_type := 0,
lchan_mode := 0,
- sdp := ""
+ gcr := omit,
+ sdp := omit
}
}
}
@@ -1921,11 +1990,12 @@ template MNCC_PDU ts_MNCC_SIMPLE_RTP(MNCC_MsgType msg_type, uint32_t call_id) :=
u := {
rtp := {
callref := call_id,
- ip := 0,
+ is_ipv6 := false,
+ ip := '00000000'O,
rtp_port := 0,
payload_type := 0,
payload_msg_type := 0,
- sdp := ""
+ sdp := omit
}
}
}
@@ -1935,13 +2005,14 @@ template MNCC_PDU ts_MNCC_RTP_CREATE(uint32_t call_id) := ts_MNCC_SIMPLE_RTP(MNC
/* MSC -> MNCC: RTP_CREATE.rsp; acknowledge creation of RTP (stating MSC side IP/Port) */
template MNCC_PDU tr_MNCC_RTP_CREATE(template uint32_t call_id := ?,
- template uint32_t ip := ?,
- template uint32_t rtp_port := ?,
+ template octetstring ip := ?,
+ template uint16_t rtp_port := ?,
template uint32_t payload_type := ?) := {
msg_type := MNCC_RTP_CREATE,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := ?,
ip := ip,
rtp_port := rtp_port,
payload_type := payload_type,
@@ -1952,27 +2023,29 @@ template MNCC_PDU tr_MNCC_RTP_CREATE(template uint32_t call_id := ?,
}
/* MSC <- MNCC: RTP_CONNECT.req; request connect of RTP */
-template MNCC_PDU ts_MNCC_RTP_CONNECT(uint32_t call_id, uint32_t ip, uint32_t rtp_port, uint32_t pt) := {
+template MNCC_PDU ts_MNCC_RTP_CONNECT(uint32_t call_id, boolean is_ipv6, octetstring ip, uint16_t rtp_port, uint32_t pt) := {
msg_type := MNCC_RTP_CONNECT,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := is_ipv6,
ip := ip,
rtp_port := rtp_port,
payload_type := pt,
payload_msg_type := 0,
- sdp := ""
+ sdp := omit
}
}
}
template MNCC_PDU tr_MNCC_RTP_CONNECT(template uint32_t call_id,
- template uint32_t ip := ?,
- template uint32_t rtp_port := ?,
+ template octetstring ip := ?,
+ template uint16_t rtp_port := ?,
template uint32_t pt := ?) := {
msg_type := MNCC_RTP_CONNECT,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := ?,
ip := ip,
rtp_port := rtp_port,
payload_type := pt,
diff --git a/library/Misc_Helpers.ttcn b/library/Misc_Helpers.ttcn
index 1ca64910..fd2e7bb9 100644
--- a/library/Misc_Helpers.ttcn
+++ b/library/Misc_Helpers.ttcn
@@ -1,5 +1,25 @@
module Misc_Helpers {
+import from Native_Functions all;
+import from TCCConversion_Functions all;
+
+modulepar {
+ charstring mp_osmo_repo := "nightly";
+}
+
+/* Test the Osmocom repository (nightly, latest, 2021q4, ...), from which the
+ * SUT is running (OS#4878). Usage examples:
+ * if (Misc_Helpers.f_osmo_repo_is("nightly")) {
+ * ...
+ * }
+ * if (Misc_Helpers.f_osmo_repo_is(("nightly", "2021q4"))) {
+ * ...
+ * }
+ */
+function f_osmo_repo_is(template charstring ver) return boolean {
+ return match(mp_osmo_repo, ver);
+}
+
/* Try to properly shutdown a testcase.
* The reliable method to stop a testcase without running into dynamic
* testcase errors due to unconnected ports receiving messages is to call
@@ -25,4 +45,58 @@ function f_shutdown(charstring file, integer line, verdicttype verdict := none,
mtc.stop
}
+function f_addr_is_ipv6(charstring addr) return boolean {
+ for (var integer i := 0; i < lengthof(addr); i := i + 1) {
+ if (addr[i] == ":") {
+ return true;
+ }
+ }
+ return false;
+}
+
+function f_addrstr2addr(charstring addr) return octetstring {
+ if (f_addr_is_ipv6(addr)) {
+ return f_inet6_addr(addr);
+ } else {
+ return f_inet_addr(addr);
+ }
+}
+
+/* Return a count of how many times sub_str occurs in str. */
+function f_strstr_count(in charstring str, in charstring sub_str) return integer
+{
+ var integer count := 0;
+ var integer pos := 0;
+
+ while (true) {
+ var integer at := f_strstr(str, sub_str, pos);
+ if (at < 0) {
+ break;
+ }
+ count := count + 1;
+ pos := at + 1;
+ }
+ return count;
+}
+
+type record of charstring ro_charstring;
+function f_str_split(charstring str, charstring delim := "\n") return ro_charstring
+{
+ var integer pos := 0;
+ var ro_charstring parts := {};
+ var integer delim_pos;
+ var integer end := lengthof(str);
+ while (pos < end) {
+ delim_pos := f_strstr(str, delim, pos);
+ if (delim_pos < 0) {
+ delim_pos := end;
+ }
+ if (delim_pos > pos) {
+ parts := parts & { substr(str, pos, delim_pos - pos) };
+ }
+ pos := delim_pos + 1;
+ }
+ return parts;
+}
+
}
diff --git a/library/NAS_Templates.ttcn b/library/NAS_Templates.ttcn
index f8198624..d45dc7dc 100644
--- a/library/NAS_Templates.ttcn
+++ b/library/NAS_Templates.ttcn
@@ -1,4 +1,4 @@
-/* EPC (Evolved Packet Core) NAS (Non-Access Stratum) templates in TTCN-3
+/* 3GPP TS 24.301, EPC (Evolved Packet Core) NAS (Non-Access Stratum) templates in TTCN-3
* (C) 2019 Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
@@ -44,6 +44,9 @@ tr_NAS_MM(template (present) EPS_MobilityManagement mm) := {
}
const BIT4 c_EPS_SEC_NONE := '0000'B;
+const BIT4 c_EPS_SEC_IP := '0001'B;
+const BIT4 c_EPS_SEC_IP_CIPH := '0010'B;
+
const BIT4 c_EPS_NAS_PD_EMM := '0111'B;
const BIT4 c_EPS_NAS_PD_ESM := '0010'B;
@@ -58,6 +61,16 @@ tr_NAS_EsmMsgContLVE(template (present) octetstring inp) := {
content := inp
}
+/* 9.9.3.4A - 10.5.1.2/24.008 */
+template (value) CipheringKeySequenceNumberTV
+ts_CipheringKeySequenceNumberTV(template (value) BIT3 key_seq) := {
+ keySequence := {
+ keySequence := key_seq,
+ spare := '0'B
+ },
+ elementIdentifier := '1000'B
+}
+
private template (value) MobileIdentityLV
ts_NAS_MobileIdLV(template (value) MobileIdentityV mid) := {
lengthIndicator := 0,
@@ -111,13 +124,15 @@ private function f_enc_IMEI_SV(hexstring digits) return IMEI_SV {
template (value) GUTI ts_NAS_GUTI(hexstring mcc_mnc, OCT2 mmegi, OCT1 mmec, OCT4 tmsi) := {
oddevenIndicator := '0'B,
spare := '1111'B,
- /* mcc_mnc specified in format 262f42 */
+ /* use the mcc_mnc format as specified in 3GPP TS 24.301, figure 9.9.3.12.1.
+ * Example: mcc=262, mnc=42 => 262f42.
+ * mcc=001, mnc=01 => 001f01. */
mccDigit1 := mcc_mnc[0],
mccDigit2 := mcc_mnc[1],
mccDigit3 := mcc_mnc[2],
- mncDigit3 := mcc_mnc[5],
- mncDigit1 := mcc_mnc[3],
- mncDigit2 := mcc_mnc[4],
+ mncDigit3 := mcc_mnc[3],
+ mncDigit1 := mcc_mnc[4],
+ mncDigit2 := mcc_mnc[5],
mMEGI := mmegi,
mMEC := mmec,
mTMSI := tmsi
@@ -140,13 +155,72 @@ ts_NAS_MobileId_IMEI(hexstring imei) := {
}
template (value) EPS_MobileIdentityV
-ts_NAS_MobileId_GUTI(hexstring mcc_mnc, OCT2 mmegi, OCT1 mmec, OCT4 tmsi) := {
+ts_NAS_MobileId_GUTI_fields(hexstring mcc_mnc, OCT2 mmegi, OCT1 mmec, OCT4 tmsi) := {
typeOfIdentity := '110'B,
oddEvenInd_identity := {
guti := ts_NAS_GUTI(mcc_mnc, mmegi, mmec, tmsi)
}
}
+template (value) EPS_MobileIdentityV
+ts_NAS_MobileId_GUTI(template (value) GUTI guti) := {
+ typeOfIdentity := '110'B,
+ oddEvenInd_identity := {
+ guti := guti
+ }
+}
+
+/* 9.9.3.12 EPS mobile identity */
+template (value) EPS_MobileIdentityLV
+ts_EPS_MobileId_IMSI(hexstring imsi) := {
+ ePS_MobileIdentity := ts_NAS_MobileId_IMSI(imsi)
+}
+
+template (value) EPS_MobileIdentityLV
+ts_EPS_MobileId_IMEI(hexstring imei) := {
+ ePS_MobileIdentity := ts_NAS_MobileId_IMEI(imei)
+}
+
+template (value) EPS_MobileIdentityLV
+ts_EPS_MobileId_GUTI(hexstring mcc_mnc, OCT2 mmegi, OCT1 mmec, OCT4 tmsi) := {
+ ePS_MobileIdentity := ts_NAS_MobileId_GUTI_fields(mcc_mnc, mmegi, mmec, tmsi)
+}
+
+template (value) EPS_MobileIdentityLV
+ts_EPS_MobileId_GUTI_(template (value) GUTI guti) := {
+ ePS_MobileIdentity := ts_NAS_MobileId_GUTI(guti)
+}
+
+/* 9.9.3.25 Nonce */
+template (value) NonceTV
+ts_NonceTV(template (value) OCT4 nonce) := {
+ elementIdentifier := '55'O,
+ noncevalue := nonce
+}
+function f_ts_NonceTV(template (omit) OCT4 nonce) return template (omit) NonceTV {
+ if (istemplatekind(nonce, "omit")) {
+ return omit;
+ }
+ return ts_NonceTV(nonce);
+}
+
+/* 9.9.3.26 P-TMSI signature */
+template (value) P_TMSISignatureTV
+ts_PTMSI_SignatureTV(template (value) OCT3 ptmsi_sig) := {
+ elementIdentifier := '19'O,
+ valueField := ptmsi_sig
+}
+
+/* 9.9.3.45 GUTI Type */
+const BIT1 GUTI_TYPE_NATIVE := '0'B;
+const BIT1 GUTI_TYPE_MAPPED := '1'B;
+template (value) GUTI_TypeTV
+ts_GUTI_TypeTV(template (value) BIT1 guti_type) := {
+ gUTI_Type := guti_type,
+ spare := '000'B,
+ elementIdentifier := '1110'B
+}
+
template (value) PDU_NAS_EPS
ts_NAS_EMM_SecurityProtected(BIT4 sec_hdr_t, integer seq_nr, octetstring inner_nas) := {
protocolDiscriminator := c_EPS_NAS_PD_EMM,
@@ -298,6 +372,146 @@ tr_NAS_AttachComplete(template (present) octetstring esm_enc := ?) := {
}
}
+/* 9.9.3.14 EPS update type */
+const BIT3 c_EPS_UPD_TYPE_TA_UPD := '000'B;
+const BIT3 c_EPS_UPD_TYPE_COMB_TA_LA_UPD := '001'B;
+const BIT3 c_EPS_UPD_TYPE_COMB_TA_LA_UPD_IMSI_ATTACH := '010'B;
+const BIT3 c_EPS_UPD_TYPE_TA_UPD_PERIODIC := '011'B;
+template (value) EPS_UpdateTypeV ts_EPS_UpdateTypeV(BIT3 typeOfUpdate := c_EPS_UPD_TYPE_TA_UPD, BIT1 activeFlag := '0'B) := {
+ typeOfUpdate := typeOfUpdate,
+ activeFlag := activeFlag
+}
+
+/* 9.9.3.21 NAS key set identifier */
+const BIT3 c_NAS_KEY_SET_ID_NO_KEY := '111'B;
+const BIT1 c_NAS_TSC_NATIVE_SEC_CTX := '0'B;
+const BIT1 c_NAS_TSC_MAPPED_SEC_CTX := '1'B;
+template (value) NAS_KeySetIdentifierV ts_NAS_KeySetIdentifierV(BIT3 identifier := c_NAS_KEY_SET_ID_NO_KEY, BIT1 tSC := c_NAS_TSC_NATIVE_SEC_CTX) := {
+ identifier := identifier,
+ tSC := tSC
+}
+
+/* 8.2.26 Tracking Area Update Accept */
+template (present) PDU_NAS_EPS
+tr_PDU_NAS_EPS_TrackingAreaUpdateAccept := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_TrackingAreaUpdateAccept := {
+ securityHeaderType := c_EPS_SEC_NONE,
+ messageType := '01001001'B,
+ updateResult := {
+ valueOfUpdateResult := ?,
+ spare := '0'B
+ },
+ spareHalfOctet := '0000'B,
+ t3412 := *,
+ gUTI := *,
+ tAI_List := *,
+ ePSBearerContextStatus := *,
+ locationAreaIdentification := *,
+ msIdentity := *,
+ eMMCause := *,
+ t3402 := *,
+ t3423 := *,
+ equivalentPLMNs := *,
+ emergencyNumberList := *,
+ ePS_NetworkFeatureSupport := *,
+ additionalUpdateResult := *,
+ t3412_Extended := *,
+ t3324 := *,
+ extendedDRXParameters := *,
+ headerCompressionConfigurationStatus := *,
+ dNCID := *,
+ sMS_ServiceStatus := *,
+ non3GPP_NW_ProvidedPolicies := *,
+ t3448 := *,
+ networkPolicy := *,
+ t3447 := *,
+ extendedEmergencyNumberList := *
+ }
+ }
+ }
+}
+
+/* 8.2.27 Tracking Area Update Complete */
+template (value) PDU_NAS_EPS
+ts_PDU_NAS_EPS_TrackingAreaUpdateComplete(template (value) BIT4 securityHeaderType := c_EPS_SEC_NONE) := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_TrackingAreaUpdateComplete := {
+ securityHeaderType := securityHeaderType,
+ messageType := '01001010'B
+ }
+ }
+ }
+}
+
+/* 8.2.28 Tracking Area Update Reject */
+template (present) PDU_NAS_EPS
+tr_PDU_NAS_EPS_TrackingAreaUpdateReject(template (present) EMM_CauseV cause := ?) := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_TrackingAreaUpdateReject := {
+ securityHeaderType := c_EPS_SEC_NONE,
+ messageType := '01001011'B,
+ emmCause := cause,
+ t3346 := *,
+ extendedEmmCause := *
+ }
+ }
+ }
+}
+
+/* 8.2.29 Tracking Area Update Request */
+template (value) PDU_NAS_EPS
+ts_PDU_NAS_EPS_TrackingAreaUpdateRequest(template (value) EPS_MobileIdentityLV old_guti,
+ template (omit) P_TMSISignatureTV old_ptmsi_sig := omit,
+ template (omit) GUTI_TypeTV old_guti_type := omit,
+ template (omit) NonceTV nonce_ue := omit,
+ template (omit) CipheringKeySequenceNumberTV gprs_cksn := omit) := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_TrackingAreaUpdateRequest := {
+ securityHeaderType := c_EPS_SEC_NONE,
+ messageType := '01001000'B,
+ ePSupdateType := ts_EPS_UpdateTypeV,
+ nasKeySetId := ts_NAS_KeySetIdentifierV,
+ oldGUTI := old_guti,
+ nonCurrentNative_nasKeySetId := omit,
+ gprsCipheringKeySequenceNumber := gprs_cksn,
+ old_P_TMSISignature := old_ptmsi_sig,
+ additionalGUTI := omit,
+ nonce := nonce_ue,
+ uENetworkCapability := omit,
+ lastVisitedRegisteredTAI := omit,
+ dRXParameter := omit,
+ uE_RadioCapabilityInfoUpdateNeeded := omit,
+ ePSBearerContextStatus := omit,
+ mSNetworkCapability := omit,
+ oldLocationAreaIdentification := omit,
+ tMSIStatusTV := omit,
+ mobileStationClassmark2 := omit,
+ mobileStationClassmark3 := omit,
+ supportedCodecList := omit,
+ additionalUpdateType := omit,
+ voiceDomainPrefandUEsettings := omit,
+ oldGUTI_Type := old_guti_type,
+ deviceProperties := omit,
+ mS_NetworkFeatureSupport := omit,
+ tMSIBasedNRIContainer := omit,
+ t3324 := omit,
+ t3412_Extended := omit,
+ extendedDRXParameters := omit,
+ uEAdditionalSecurityCapability := omit,
+ uEStatus := omit
+ }
+ }
+ }
+}
/* 8.2.3 Attach Reject */
template (value) PDU_NAS_EPS
@@ -590,6 +804,25 @@ tr_NAS_AuthResp(template OCT16 res := ?) := {
}
}
+/* 8.2.13 EMM information */
+template (present) PDU_NAS_EPS
+tr_NAS_EMMInformation := {
+ protocolDiscriminator := c_EPS_NAS_PD_EMM,
+ ePS_messages := {
+ ePS_MobilityManagement := {
+ pDU_NAS_EPS_EMM_Information := {
+ securityHeaderType := ?,
+ messageType := '01100001'B,
+ fullNameForNetwork := *,
+ shortNameForNetwork := *,
+ localTimeZone := *,
+ universalTimeAndLocalTimeZone := *,
+ networkDaylightSavingTime := *
+ }
+ }
+ }
+}
+
/* 8.2.18 Identity Request */
template (value) PDU_NAS_EPS
ts_NAS_IdentityReq(template (value) IdentityType2V id_type) := {
@@ -928,6 +1161,55 @@ ts_NAS_ActDefEpsBearCtxReq(template (value) BIT4 bearer_id,
}
}
}
+template (present) PDU_NAS_EPS
+tr_NAS_ActDefEpsBearCtxReq(template (present) BIT4 bearer_id := ?,
+ template (present) BIT8 proc_tid := ?,
+ template (present) EPS_QualityOfServiceV qos := ?,
+ template (present) octetstring apn := ?,
+ template (present) BIT3 addr_type := ?,
+ template (present) octetstring addr_info := ?) := {
+ protocolDiscriminator := c_EPS_NAS_PD_ESM,
+ ePS_messages := {
+ ePS_SessionManagement := {
+ pDU_NAS_EPS_ActDefEPSBearerContextRequest := {
+ ePSBearerIdentity := bearer_id,
+ procedureTransactionIdentifier := proc_tid,
+ messageType := '11000001'B,
+ ePS_QoS := {
+ lengthIndicator := ?,
+ ePS_QualityOfServiceV := qos
+ },
+ accessPointName := {
+ lengthIndicator := 0,
+ accessPointNameValue := apn
+ },
+ pDN_Address := {
+ lengthIndicator := 0,
+ typeValue := addr_type,
+ spare := '00000'B,
+ addressInformation := addr_info
+ },
+ transactionIdentifier := *,
+ negotiatedQoS := *,
+ negotiated_LLC_SAPI := *,
+ radioPriority := *,
+ packetFlowID := *,
+ aPN_AMBR := *,
+ esmCause := *,
+ protocolConfigOptions := *,
+ connectivityType := *,
+ wLANOffloadIndication := *,
+ nBIFOMContainer := *,
+ headerCompressinConfiguration := *,
+ controlPlaneOnlyIndication := *,
+ extendedProtocolConfigurationOptions := *,
+ servingPLMNRateControl := *,
+ extended_APN_AMBR := *,
+ extendedQoS := *
+ }
+ }
+ }
+}
/* 8.3.4 Activate Default EPS Bearer Context Accept */
template (value) PDU_NAS_EPS
diff --git a/library/NS_CodecPort.ttcn b/library/NS_CodecPort.ttcn
deleted file mode 100644
index 82ba55bb..00000000
--- a/library/NS_CodecPort.ttcn
+++ /dev/null
@@ -1,61 +0,0 @@
-module NS_CodecPort {
-
- import from IPL4asp_PortType all;
- import from IPL4asp_Types all;
- import from NS_Types all;
-
- type record NS_RecvFrom {
- ConnectionId connId,
- HostName remName,
- PortNumber remPort,
- HostName locName,
- PortNumber locPort,
- PDU_NS msg
- }
-
- template NS_RecvFrom t_NS_RecvFrom(template PDU_NS pdu) := {
- connId := ?,
- remName := ?,
- remPort := ?,
- locName := ?,
- locPort := ?,
- msg := pdu
- };
-
- type record NS_Send {
- ConnectionId connId,
- PDU_NS msg
- }
-
- template NS_Send t_NS_Send(template ConnectionId connId, template PDU_NS msg) := {
- connId := connId,
- msg := msg
- }
-
- private function IPL4_to_NS_RecvFrom(in ASP_RecvFrom pin, out NS_RecvFrom pout) {
- pout.connId := pin.connId;
- pout.remName := pin.remName;
- pout.remPort := pin.remPort;
- pout.locName := pin.locName;
- pout.locPort := pin.locPort;
- pout.msg := dec_PDU_NS(pin.msg);
- } with { extension "prototype(fast)" };
-
- private function NS_to_IPL4_Send(in NS_Send pin, out ASP_Send pout) {
- pout.connId := pin.connId;
- pout.proto := { udp := {} };
- pout.msg := enc_PDU_NS(pin.msg);
- } with { extension "prototype(fast)" };
-
- type port NS_CODEC_PT message {
- out NS_Send;
- in NS_RecvFrom,
- ASP_ConnId_ReadyToRelease,
- ASP_Event;
- } with { extension "user IPL4asp_PT
- out(NS_Send -> ASP_Send: function(NS_to_IPL4_Send))
- in(ASP_RecvFrom -> NS_RecvFrom: function(IPL4_to_NS_RecvFrom);
- ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
- ASP_Event -> ASP_Event: simple)"
- }
-}
diff --git a/library/NS_Emulation.ttcn b/library/NS_Emulation.ttcn
deleted file mode 100644
index 697a4821..00000000
--- a/library/NS_Emulation.ttcn
+++ /dev/null
@@ -1,339 +0,0 @@
-/* GPRS-NS Emulation in TTCN-3
- * (C) 2018 Harald Welte <laforge@gnumonks.org>
- * contributions by sysmocom - s.f.m.c. GmbH
- * 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 NS_Emulation {
- import from NS_Types all;
- import from BSSGP_Types all;
- import from Osmocom_Gb_Types all;
- import from NS_CodecPort all;
- import from NS_CodecPort_CtrlFunct all;
- import from IPL4asp_Types all;
-
- type record NsUnitdataRequest {
- BssgpBvci bvci,
- Nsei nsei,
- octetstring sdu optional,
- PDU_BSSGP bssgp optional
- }
-
- template NsUnitdataRequest t_NsUdReq(template Nsei nsei, template BssgpBvci bvci, template octetstring sdu,
- template PDU_BSSGP bssgp) := {
- bvci := bvci,
- nsei := nsei,
- sdu := sdu,
- bssgp := bssgp
- }
-
- type record NsUnitdataIndication {
- BssgpBvci bvci,
- Nsei nsei,
- octetstring sdu optional,
- PDU_BSSGP bssgp optional
- }
-
- template NsUnitdataIndication t_NsUdInd(Nsei nsei, BssgpBvci bvci, octetstring sdu) := {
- bvci := bvci,
- nsei := nsei,
- sdu := sdu,
- bssgp := dec_PDU_BSSGP(sdu)
- }
-
- type record NsStatusIndication {
- Nsei nsei,
- Nsvci nsvci,
- NseState old_state,
- NseState new_state
- }
-
- template NsStatusIndication t_NsStsInd(Nsei nsei, Nsvci nsvci, NseState old_state, NseState state) := {
- nsei := nsei,
- nsvci := nsvci,
- old_state := old_state,
- new_state := state
- }
-
- type enumerated NseState {
- NSE_S_DEAD_BLOCKED,
- NSE_S_WAIT_RESET,
- NSE_S_ALIVE_BLOCKED,
- NSE_S_ALIVE_UNBLOCKED
- }
-
- /* port from our (internal) point of view */
- type port NS_SP_PT message {
- in NsUnitdataRequest;
- out NsUnitdataIndication,
- NsStatusIndication,
- ASP_Event;
- } with { extension "internal" };
-
- /* port from the user point of view */
- type port NS_PT message {
- in ASP_Event,
- NsStatusIndication,
- NsUnitdataIndication;
- out NsUnitdataRequest;
- } with { extension "internal" };
-
- function NSStart(NSConfiguration init_config) runs on NS_CT {
- config := init_config;
- f_init();
- f_ScanEvents();
- }
-
- private function f_init() runs on NS_CT {
- var Result res;
- /* Connect the UDP socket */
- res := f_IPL4_connect(NSCP, config.remote_ip, config.remote_udp_port, config.local_ip, config.local_udp_port, 0, { udp := {}});
- if (not ispresent(res.connId)) {
- setverdict(fail, "Could not connect NS UDP socket from " &
- config.local_ip & ":" & int2str(config.local_udp_port) &
- " to " & config.remote_ip & ":" & int2str(config.remote_udp_port));
- mtc.stop;
- }
- g_conn_id := res.connId;
- f_change_state(NSE_S_DEAD_BLOCKED);
- /* Send the first NS-ALIVE to test the connection */
- if (not config.role_sgsn) {
- f_sendReset();
- }
- }
-
- type component NS_CT {
- /* UDP port towards the bottom (IUT) */
- port NS_CODEC_PT NSCP;
- /* NS-User SAP towards the user */
- port NS_SP_PT NS_SP;
-
- var NSConfiguration config;
-
- var NseState g_state := NSE_S_DEAD_BLOCKED;
- var ConnectionId g_conn_id := -1;
-
- timer Tns_alive := 3.0;
- timer Tns_test := 10.0;
- timer Tns_block := 10.0;
- }
-
- type record NSConfiguration {
- PortNumber local_udp_port,
- charstring local_ip,
- PortNumber remote_udp_port,
- charstring remote_ip,
- Nsvci nsvci,
- Nsvci nsei,
- boolean role_sgsn,
- boolean handle_sns
- }
-
- private function f_change_state(NseState new_state) runs on NS_CT {
- var NseState old_state := g_state;
- g_state := new_state;
- log("NS State Transition: ", old_state, " -> ", new_state);
- NS_SP.send(t_NsStsInd(config.nsei, config.nsvci, old_state, new_state));
- }
-
- private function f_sendReset() runs on NS_CT {
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_RESET(NS_CAUSE_OM_INTERVENTION, config.nsvci, config.nsei)));
- g_state := NSE_S_WAIT_RESET;
- }
-
- private function f_sendAlive() runs on NS_CT {
- NSCP.send(t_NS_Send(g_conn_id, t_NS_ALIVE));
- Tns_alive.start;
- }
-
- private function f_sendUnblock() runs on NS_CT {
- NSCP.send(t_NS_Send(g_conn_id, t_NS_UNBLOCK));
- Tns_block.start;
- }
-
- private function f_sendBlock(NsCause cause) runs on NS_CT {
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_BLOCK(cause, config.nsvci)));
- Tns_block.start;
- }
-
- altstep as_allstate() runs on NS_CT {
- var NS_RecvFrom rf;
- var ASP_Event evt;
-
- /* transition to DEAD if t_alive times out */
- [Tns_alive.running] Tns_alive.timeout {
- log("Tns-alive expired: changing to DEAD_BLOCKED + starting Tns-test");
- f_change_state(NSE_S_DEAD_BLOCKED);
- Tns_test.start;
- }
-
- [Tns_test.running] Tns_test.timeout {
- log("Tns-test expired: sending NS-ALIVE");
- f_sendAlive();
- }
-
- /* Stop t_alive when receiving ALIVE-ACK */
- [] NSCP.receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
- log("NS-ALIVE-ACK received: stopping Tns-alive; starting Tns-test");
- Tns_alive.stop;
- Tns_test.start;
- }
-
- /* respond to NS-ALIVE with NS-ALIVE-ACK */
- [] NSCP.receive(t_NS_RecvFrom(t_NS_ALIVE)) {
- NSCP.send(t_NS_Send(g_conn_id, t_NS_ALIVE_ACK));
- }
-
- /* Respond to BLOCK for wrong NSVCI */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_BLOCK(?, ?))) -> value rf {
- log("Rx NS-BLOCK for unknown NSVCI");
- /* FIXME */
- }
-
- /* Respond to RESET with correct NSEI/NSVCI */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_RESET(?, config.nsvci, config.nsei))) -> value rf {
- f_change_state(NSE_S_ALIVE_BLOCKED);
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_RESET_ACK(config.nsvci, config.nsei)));
- }
-
- /* Respond to RESET with wrong NSEI/NSVCI */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_RESET(?, ?, ?))) -> value rf {
- log("Rx NS-RESET for unknown NSEI/NSVCI");
- /* FIXME */
- }
-
- [config.role_sgsn and config.handle_sns] as_sns_sgsn();
-
- /* default case of handling unknown PDUs */
- [] NSCP.receive(t_NS_RecvFrom(?)) -> value rf {
- log("Rx Unexpected NS PDU ", rf.msg," in state ", g_state);
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_STATUS(NS_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, rf.msg)));
- }
- /* Forwarding of ASP_Evet to user */
- [] NSCP.receive(ASP_Event:?) -> value evt { NS_SP.send(evt); }
- }
-
- /* simple IP Sub-Network Service responder for the SGSN side. This is not a full implementation
- * of the protocol, merely sufficient to make the PCU/BSS side happy to proceed */
- altstep as_sns_sgsn() runs on NS_CT {
- var NS_RecvFrom rf;
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_SIZE(config.nsei))) -> value rf {
- /* blindly acknowledge whatever the PCU sends */
- NSCP.send(t_NS_Send(g_conn_id, ts_SNS_SIZE_ACK(config.nsei, omit)));
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_SIZE(?))) {
- setverdict(fail, "SNS-SIZE from unexpected NSEI");
- self.stop;
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG(config.nsei, true,
- {tr_SNS_IPv4(config.remote_ip, config.remote_udp_port)}))) -> value rf {
- /* blindly acknowledge whatever the PCU sends */
- NSCP.send(t_NS_Send(g_conn_id, ts_SNS_CONFIG_ACK(config.nsei, omit)));
- /* send a SNS-CONFIG in response and expect a SNS-CONFIG-ACK */
- var IP4_Elements v4 := { valueof(ts_SNS_IPv4(config.local_ip, config.local_udp_port)) };
- NSCP.send(t_NS_Send(g_conn_id, ts_SNS_CONFIG(config.nsei, true, v4)));
- alt {
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG_ACK(config.nsei, omit))) {
- /* success */
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG_ACK(config.nsei, ?))) {
- setverdict(fail, "Unexpected SNS-CONFIG-NACK");
- self.stop;
- }
- }
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG(config.nsei, false, ?))) { /* ignore */}
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG(config.nsei, true, ?))) {
- setverdict(fail, "Unexpected SNS-CONFIG content");
- self.stop;
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_SNS_CONFIG(?, ?, ?))) {
- setverdict(fail, "SNS-CONFIG from unexpected NSEI");
- self.stop;
- }
- }
-
- private function f_ScanEvents() runs on NS_CT {
- var NsUnitdataRequest ud_req;
- var NS_RecvFrom rf;
- var default d;
-
- d := activate(as_allstate());
-
- while (true) {
- if (g_state == NSE_S_DEAD_BLOCKED) {
- alt {
- [false] any timer.timeout {}
- }
- } else if (g_state == NSE_S_WAIT_RESET) {
- alt {
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_RESET_ACK(config.nsvci, config.nsei))) -> value rf {
- f_change_state(NSE_S_ALIVE_BLOCKED);
- f_sendAlive();
- f_sendUnblock();
- }
- }
- } else if (g_state == NSE_S_ALIVE_BLOCKED) {
- alt {
- /* bogus block, just respond with ACK */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_BLOCK(?, config.nsvci))) -> value rf {
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_BLOCK_ACK(config.nsvci)));
- }
- /* Respond to UNBLOCK with UNBLOCK-ACK + change state */
- [] NSCP.receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value rf {
- NSCP.send(t_NS_Send(g_conn_id, t_NS_UNBLOCK_ACK));
- Tns_block.stop;
- f_change_state(NSE_S_ALIVE_UNBLOCKED);
- }
- [] NSCP.receive(t_NS_RecvFrom(t_NS_UNBLOCK_ACK)) -> value rf {
- Tns_block.stop;
- f_change_state(NSE_S_ALIVE_UNBLOCKED);
- }
- [] Tns_block.timeout {
- /* repeat unblock transmission */
- f_sendUnblock();
- }
- }
- } else if (g_state == NSE_S_ALIVE_UNBLOCKED) {
- alt {
- /* bogus unblock, just respond with ACK */
- [] NSCP.receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value rf {
- NSCP.send(t_NS_Send(g_conn_id, t_NS_UNBLOCK_ACK));
- }
- /* Respond to BLOCK with BLOCK-ACK + change state */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_BLOCK(?, config.nsvci))) -> value rf {
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_BLOCK_ACK(config.nsvci)));
- Tns_block.stop;
- f_change_state(NSE_S_ALIVE_BLOCKED);
- }
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(config.nsvci))) -> value rf {
- Tns_block.stop;
- }
- /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
- [] NSCP.receive(t_NS_RecvFrom(tr_NS_UNITDATA(?, ?, ?))) -> value rf {
- NS_SP.send(t_NsUdInd(config.nsei,
- oct2int(rf.msg.pDU_NS_Unitdata.bVCI),
- rf.msg.pDU_NS_Unitdata.nS_SDU));
- }
- /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
- [] NS_SP.receive(t_NsUdReq(config.nsei, ?, ?, omit)) -> value ud_req {
- /* using raw octetstring PDU */
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu)));
- }
- [] NS_SP.receive(t_NsUdReq(config.nsei, ?, omit, ?)) -> value ud_req {
- /* using decoded BSSGP PDU that we need to encode first */
- var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
- NSCP.send(t_NS_Send(g_conn_id, ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc)));
- }
- }
- }
-
- } /* while */
- //deactivate(d);
- }
-}
diff --git a/library/NS_Emulation.ttcnpp b/library/NS_Emulation.ttcnpp
new file mode 100644
index 00000000..0ed022ae
--- /dev/null
+++ b/library/NS_Emulation.ttcnpp
@@ -0,0 +1,1044 @@
+/* GPRS-NS Emulation in TTCN-3
+ * (C) 2018-2021 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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 NS_Emulation {
+ import from Misc_Helpers all;
+ import from NS_Types all;
+ import from BSSGP_Types all;
+ import from Osmocom_Types all;
+ import from Osmocom_Gb_Types all;
+ import from NS_Provider_IPL4 all;
+#ifdef NS_EMULATION_FR
+ import from NS_Provider_FR all;
+#endif
+ import from IPL4asp_Types all;
+
+ type record NsUnitdataRequest {
+ BssgpBvci bvci,
+ Nsei nsei,
+ integer lsp,
+ octetstring sdu optional,
+ PDU_BSSGP bssgp optional
+ }
+
+ template NsUnitdataRequest tr_NsUdReq(template Nsei nsei, template BssgpBvci bvci, template integer lsp,
+ template octetstring sdu, template PDU_BSSGP bssgp) := {
+ bvci := bvci,
+ nsei := nsei,
+ lsp := lsp,
+ sdu := sdu,
+ bssgp := bssgp
+ }
+
+ template (value) NsUnitdataRequest ts_NsUdReq(template (value) Nsei nsei,
+ template (value) BssgpBvci bvci,
+ template (value) integer lsp,
+ template (omit) octetstring sdu,
+ template (omit) PDU_BSSGP bssgp) := {
+ bvci := bvci,
+ nsei := nsei,
+ lsp := lsp,
+ sdu := sdu,
+ bssgp := bssgp
+ }
+
+ type record NsUnitdataIndication {
+ BssgpBvci bvci,
+ Nsei nsei,
+ Nsvci nsvci,
+ octetstring sdu optional,
+ PDU_BSSGP bssgp optional
+ }
+
+ template (present) NsUnitdataIndication tr_NsUdInd(template (present) Nsei nsei,
+ template (present) BssgpBvci bvci,
+ template octetstring sdu) := {
+ bvci := bvci,
+ nsei := nsei,
+ nsvci := ?,
+ sdu := sdu,
+ bssgp := ?
+ }
+
+ template (value) NsUnitdataIndication ts_NsUdInd(Nsei nsei, Nsvci nsvci, BssgpBvci bvci, octetstring sdu) := {
+ bvci := bvci,
+ nsei := nsei,
+ nsvci := nsvci,
+ sdu := sdu,
+ bssgp := dec_PDU_BSSGP(sdu)
+ }
+
+ type record NsStatusIndication {
+ Nsei nsei,
+ Nsvci nsvci,
+ NsvcState old_state,
+ NsvcState new_state,
+ boolean first_or_last
+ }
+
+ template (present) NsStatusIndication tr_NsStsInd(template (present) Nsei nsei := ?,
+ template (present) Nsvci nsvci := ?,
+ template (present) NsvcState old_state := ?,
+ template (present) NsvcState state := ?,
+ template (present) boolean first_or_last := ?) := {
+ nsei := nsei,
+ nsvci := nsvci,
+ old_state := old_state,
+ new_state := state,
+ first_or_last := first_or_last
+ }
+
+
+ template (value) NsStatusIndication ts_NsStsInd(Nsei nsei, Nsvci nsvci, NsvcState old_state, NsvcState state,
+ boolean first_or_last := false) := {
+ nsei := nsei,
+ nsvci := nsvci,
+ old_state := old_state,
+ new_state := state,
+ first_or_last := first_or_last
+ }
+
+ type enumerated NsvcState {
+ NSVC_S_DISABLED, /* administratively disabled */
+ NSVC_S_DEAD_BLOCKED,
+ NSVC_S_WAIT_RESET,
+ NSVC_S_ALIVE_BLOCKED,
+ NSVC_S_ALIVE_UNBLOCKED
+ }
+
+ /* port from our (internal) point of view */
+ type port NS_SP_PT message {
+ in NsUnitdataRequest;
+ out NsUnitdataIndication,
+ NsStatusIndication;
+ } with { extension "internal" };
+
+ /* port from the user point of view */
+ type port NS_PT message {
+ in ASP_Event,
+ NsStatusIndication,
+ NsUnitdataIndication;
+ out NsUnitdataRequest;
+ } with { extension "internal" };
+
+ /* port from our (internal) point of view */
+ type port NS_CTRL_SP_PT message {
+ in NsDisableVcRequest,
+ NsEnableVcRequest;
+ } with { extension "internal" };
+
+ /* port from the user point of view */
+ type port NS_CTRL_PT message {
+ out NsEnableVcRequest,
+ NsDisableVcRequest;
+ } with { extension "internal" };
+
+ type record NsDisableVcRequest {
+ Nsvci nsvci
+ };
+ type record NsEnableVcRequest {
+ Nsvci nsvci
+ };
+
+ type component NS_Provider_CT {
+ /* upper port, facing to NS_Emulation:NSCP */
+ port NS_PROVIDER_PT NSE;
+ /* lower layer ports (UDP/IP, Frame Relay) are added in derived components */
+ };
+
+ type enumerated NS_Provider_LinkStatus {
+ NS_PROV_LINK_STATUS_UP,
+ NS_PROV_LINK_STATUS_DOWN
+ };
+ type union NS_Provider_Evt {
+ NS_Provider_LinkStatus link_status
+ };
+
+ /* port between NS_Provider and NS_CT */
+ type port NS_PROVIDER_PT message {
+ inout PDU_NS, NS_Provider_Evt;
+ } with { extension "internal" };
+
+ type record NSVCConfigurationIP {
+ AddressFamily address_family,
+ PortNumber local_udp_port,
+ charstring local_ip,
+ PortNumber remote_udp_port,
+ charstring remote_ip,
+ uint8_t data_weight,
+ uint8_t signalling_weight
+ };
+ type record NSVCConfigurationFR {
+ charstring netdev, /* HDLC net-device for AF_PACKET socket */
+ integer dlci
+ };
+ type union NSVCConfigurationP {
+ NSVCConfigurationIP ip,
+ NSVCConfigurationFR fr
+ };
+ type record NSVCConfiguration {
+ NSVCConfigurationP provider,
+ Nsvci nsvci
+ };
+ type record of NSVCConfiguration NSVCConfigurations;
+ type record NSConfiguration {
+ Nsvci nsei,
+ boolean role_sgsn,
+ boolean handle_sns,
+ NSVCConfigurations nsvc
+ }
+
+ /***********************************************************************
+ * per NS-VCG component. Exists once per [peer of] NSE
+ ***********************************************************************/
+
+ type component NS_CT {
+ /* NS-User SAP towards the user */
+ port NS_SP_PT NS_SP;
+
+ /* port towards the per-NSVC components */
+ port NSint_PT NSVC;
+
+ /* control port, used to manipulate at runtime */
+ port NS_CTRL_SP_PT NS_CTRL;
+
+ /* all of the NS configuration a user passes to us */
+ var NSConfiguration g_config;
+ var charstring g_id;
+
+ /* references to the endpoint provider components */
+ var IpEndpointTable g_ip_endpoints := {};
+ /* control port for NS-IP provider */
+ port NSPIP_PROC_PT NSPIP_PROC;
+
+ /* references to the per-NSVC components */
+ var NsvcTable g_nsvcs := {};
+ /* list of indexes to g_nsvcs[] of currently unblocked NSVCs */
+ var Osmocom_Types.ro_integer g_unblocked_nsvcs_sig := {};
+ var Osmocom_Types.ro_integer g_unblocked_nsvcs_data := {};
+ };
+ type record NsvcTableEntry {
+ NSVCConfiguration cfg,
+ NSVC_CT vc_conn,
+ NsvcState state
+ };
+ type record of NsvcTableEntry NsvcTable;
+ type record IpEndpointTableEntry {
+ /* configuration */
+ AddressFamily address_family,
+ PortNumber local_udp_port,
+ charstring local_ip,
+ uint8_t data_weight,
+ uint8_t signalling_weight,
+ /* state */
+ NS_Provider_IPL4_CT provider_ct
+ };
+ type record of IpEndpointTableEntry IpEndpointTable;
+
+ /* internal port from the NS-VC point of view */
+ type port NSint_SP_PT message {
+ in NsUnitdataRequest,
+ SnsRequest,
+ NsCtrlRequest;
+ out NsUnitdataIndication,
+ SnsIndication,
+ NsStatusIndication;
+ } with { extension "internal" };
+
+ /* internal port from the NS-VCG point of view */
+ type port NSint_PT message {
+ in ASP_Event,
+ NsStatusIndication,
+ SnsIndication,
+ NsUnitdataIndication;
+ out NsUnitdataRequest,
+ SnsRequest,
+ NsCtrlRequest;
+ } with { extension "internal" };
+
+ /* Used by NS-VC to report reception of a SNS PDU to NS-VCG */
+ type record SnsIndication {
+ Nsvci nsvci,
+ PDU_NS ns
+ };
+
+ /* Used by NS-VCG to request transmission of a SNS PDU via a NS-VC */
+ type record SnsRequest {
+ Nsvci nsvci,
+ PDU_NS ns
+ };
+
+ type enumerated NsCtrlRequest {
+ StartAliveProcedure (0),
+ DisableReq (1), /* administratively disable NS-VC */
+ EnableReq (2), /* administratively enable NS-VC */
+ ForceAliveState (3)
+ };
+
+ function f_ipep_find(AddressFamily af, PortNumber local_udp_port, charstring local_ip,
+ out IpEndpointTableEntry ret)
+ runs on NS_CT return boolean {
+ var integer i;
+ for (i := 0; i < lengthof(g_ip_endpoints); i := i+1) {
+ var IpEndpointTableEntry ipep := g_ip_endpoints[i];
+ if (ipep.address_family == af and ipep.local_udp_port == local_udp_port and
+ ipep.local_ip == local_ip) {
+ ret := ipep;
+ return true;
+ }
+ }
+ return false
+ }
+
+ /* find or create IP endpoint component for [local part of] nsvc_cfg */
+ function f_ipep_find_or_create(NSVCConfiguration nsvc_cfg)
+ runs on NS_CT return NS_Provider_IPL4_CT {
+ var IpEndpointTableEntry ipep;
+ if (f_ipep_find(nsvc_cfg.provider.ip.address_family,
+ nsvc_cfg.provider.ip.local_udp_port,
+ nsvc_cfg.provider.ip.local_ip, ipep)) {
+ return ipep.provider_ct;
+ } else {
+ var charstring nsvc_id := g_id & "-NSVCI" & int2str(nsvc_cfg.nsvci);
+ ipep := {
+ address_family := nsvc_cfg.provider.ip.address_family,
+ local_udp_port := nsvc_cfg.provider.ip.local_udp_port,
+ local_ip := nsvc_cfg.provider.ip.local_ip,
+ data_weight := nsvc_cfg.provider.ip.data_weight,
+ signalling_weight := nsvc_cfg.provider.ip.signalling_weight,
+ provider_ct := -
+ };
+ /* Create ipep and add it to the list */
+ log("Creating NSIP provider for ", ipep.local_ip, ":",
+ ipep.local_udp_port);
+ ipep.provider_ct := NS_Provider_IPL4_CT.create(nsvc_id & "-provIP") alive;
+ connect(self:NSPIP_PROC, ipep.provider_ct:PROC);
+ ipep.provider_ct.start(NS_Provider_IPL4.main(nsvc_cfg, g_config, nsvc_id));
+ g_ip_endpoints := g_ip_endpoints & { ipep };
+ return ipep.provider_ct;
+ }
+ }
+
+ /* add one NSVC (component and table entry */
+ function f_nsvc_add(NSVCConfiguration nsvc_cfg) runs on NS_CT {
+ var charstring nsvc_id := g_id & "-NSVCI" & int2str(nsvc_cfg.nsvci);
+ var NsvcTableEntry te;
+ var NS_Provider_IPL4_CT vc_ipep := null;
+
+ /* For the IP provider, we have one provider component per local endpoint,
+ * which we must create before adding the NSVcs (for each remote endpoint)
+ * to it */
+ if (ischosen(nsvc_cfg.provider.ip)) {
+ vc_ipep := f_ipep_find_or_create(nsvc_cfg);
+ }
+
+ /* Start the actual NSVC component */
+
+ te.cfg := nsvc_cfg;
+ te.vc_conn := NSVC_CT.create(nsvc_id) alive;
+ te.state := NSVC_S_DEAD_BLOCKED;
+
+ connect(self:NSVC, te.vc_conn:NS_SP);
+ log("Starting NSVC component for ", nsvc_cfg);
+ te.vc_conn.start(NSVCStart(nsvc_cfg, g_config, nsvc_id, vc_ipep));
+
+ g_nsvcs := g_nsvcs & { te };
+ /* no need to add to g_unblocked_nsvcs, as state is always DEAD_BLOCKED above */
+
+ /* For the IP provider, we must explicitly associate each NSVC with it */
+ if (ischosen(nsvc_cfg.provider.ip)) {
+ /* this causes NS_Provider_IPL4.f_nsvc_add() to be executed */
+ f_nspip_add_nsvc(vc_ipep, nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port, te.vc_conn);
+ }
+ }
+
+ function f_nsvc_find_idx(Nsvci nsvci) runs on NS_CT return integer {
+ var integer i;
+ for (i := 0; i < lengthof(g_nsvcs); i := i+1) {
+ if (g_nsvcs[i].cfg.nsvci == nsvci) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ function f_nsvc_find(Nsvci nsvci) runs on NS_CT return NSVC_CT {
+ var integer i := f_nsvc_find_idx(nsvci);
+ if (i < 0) {
+ return null;
+ } else {
+ return g_nsvcs[i].vc_conn;
+ }
+ }
+
+ function f_nsvc_update_state(Nsvci nsvci, NsvcState state) runs on NS_CT {
+ var integer i := f_nsvc_find_idx(nsvci);
+ if (i < 0) {
+ return;
+ }
+ if (g_nsvcs[i].state != NSVC_S_ALIVE_UNBLOCKED and state == NSVC_S_ALIVE_UNBLOCKED) {
+ /* add index to list of unblocked NSVCs */
+ if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
+ g_nsvcs[i].cfg.provider.ip.signalling_weight > 0) {
+ ro_integer_add_unique(g_unblocked_nsvcs_sig, i);
+ }
+ if (not ischosen(g_nsvcs[i].cfg.provider.ip) or
+ g_nsvcs[i].cfg.provider.ip.data_weight > 0) {
+ ro_integer_add_unique(g_unblocked_nsvcs_data, i);
+ }
+ } else if (g_nsvcs[i].state == NSVC_S_ALIVE_UNBLOCKED and state != NSVC_S_ALIVE_UNBLOCKED) {
+ /* remove index to list of unblocked NSVCs */
+ ro_integer_del(g_unblocked_nsvcs_sig, i);
+ ro_integer_del(g_unblocked_nsvcs_data, i);
+ }
+ g_nsvcs[i].state := state;
+ }
+
+ function NSStart(NSConfiguration init_config, charstring id := testcasename()) runs on NS_CT {
+ g_config := init_config;
+ g_id := id;
+
+ /* iterate over list of NS-VCs and start per-NSVC components */
+ for (var integer i := 0; i < lengthof(g_config.nsvc); i := i+1) {
+ var NSVCConfiguration nsvc_cfg := g_config.nsvc[i];
+ f_nsvc_add(nsvc_cfg);
+ }
+
+ if (g_config.handle_sns and not g_config.role_sgsn) {
+ f_sns_outbound_size_config();
+ }
+ while (true) {
+ alt {
+ [] as_ns_common() {}
+ }
+ }
+ }
+
+ function f_count_nsvcs_in_state(template NsvcState state := ?) runs on NS_CT return integer {
+ var integer i;
+ var integer res := 0;
+ for (i := 0; i < lengthof(g_nsvcs); i := i+1) {
+ if (match(g_nsvcs[i].state, state)) {
+ res := res + 1;
+ }
+ }
+ return res;
+ }
+
+ private altstep as_ns_common_status() runs on NS_CT {
+ var NsStatusIndication rx_nssi;
+ [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, NSVC_S_ALIVE_UNBLOCKED)) -> value rx_nssi {
+ /* check if this one is the first to be unblocked */
+ var integer num_nsvc_unblocked := f_count_nsvcs_in_state(NSVC_S_ALIVE_UNBLOCKED);
+ f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
+ if (num_nsvc_unblocked == 0) {
+ rx_nssi.first_or_last := true;
+ }
+ NS_SP.send(rx_nssi);
+ }
+ [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, NSVC_S_DEAD_BLOCKED)) -> value rx_nssi {
+ f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
+ /* check if this one is the last to be blocked */
+ var integer num_nsvc_unblocked := f_count_nsvcs_in_state(NSVC_S_ALIVE_UNBLOCKED);
+ if (num_nsvc_unblocked == 0) {
+ rx_nssi.first_or_last := true;
+ }
+ NS_SP.send(rx_nssi);
+ }
+ [] NSVC.receive(tr_NsStsInd(g_config.nsei, ?, ?, ?)) -> value rx_nssi {
+ f_nsvc_update_state(rx_nssi.nsvci, rx_nssi.new_state);
+ NS_SP.send(rx_nssi);
+ }
+ [] NSVC.receive(tr_NsStsInd) -> value rx_nssi {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received NsStatusInd for invalid NSEI: ", rx_nssi));
+ }
+ }
+
+ private altstep as_ns_common() runs on NS_CT {
+ var NsUnitdataIndication rx_nsudi;
+ var NsUnitdataRequest rx_nsudr;
+ var NsDisableVcRequest rx_disar;
+ var NsEnableVcRequest rx_enar;
+ /* pass from NS-VCs up to user */
+ [] as_ns_common_status();
+ [] NSVC.receive(tr_NsUdInd(g_config.nsei, ?, ?)) -> value rx_nsudi {
+ NS_SP.send(rx_nsudi);
+ }
+
+ [g_config.handle_sns and g_config.role_sgsn] as_vcg_sns_sgsn();
+ [g_config.handle_sns and not g_config.role_sgsn] as_vcg_sns_pcu();
+
+ [] NSVC.receive(tr_NsUdInd(?, ?, ?)) -> value rx_nsudi {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received UnitDataInd for invalid NSEI: ", rx_nsudi));
+ }
+ /* from user down to NS-VC */
+ [] NS_CTRL.receive(NsDisableVcRequest:?) -> value rx_disar {
+ var integer nsvc_idx := f_nsvc_find_idx(rx_disar.nsvci);
+ NSVC.send(NsCtrlRequest:DisableReq) to g_nsvcs[nsvc_idx].vc_conn;
+ }
+ [] NS_CTRL.receive(NsEnableVcRequest:?) -> value rx_enar {
+ var integer nsvc_idx := f_nsvc_find_idx(rx_enar.nsvci);
+ NSVC.send(NsCtrlRequest:EnableReq) to g_nsvcs[nsvc_idx].vc_conn;
+ }
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, *)) -> value rx_nsudr {
+ /* load distribution function */
+ var integer nsvc_idx := g_unblocked_nsvcs_sig[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_sig)];
+ NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
+ }
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, ?, *)) -> value rx_nsudr {
+ /* load distribution function */
+ var integer nsvc_idx := g_unblocked_nsvcs_data[rx_nsudr.lsp mod lengthof(g_unblocked_nsvcs_data)];
+ NSVC.send(rx_nsudr) to g_nsvcs[nsvc_idx].vc_conn;
+ }
+
+ [] NS_SP.receive(tr_NsUdReq(?, ?, ?, ?, *)) -> value rx_nsudr {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received NsUnitdataReq for invalid NSEI: ", rx_nsudr));
+ }
+ }
+
+ /* generate a list of v4 + v6 endpoints based on the IpEndpointTable */
+ private function gen_sns_ip_elems(out template (omit) IP4_Elements v4_out,
+ out template (omit) IP6_Elements v6_out) runs on NS_CT {
+ var integer i;
+ var IP4_Elements v4 := {};
+ var IP6_Elements v6 := {};
+
+ for (i := 0; i < lengthof(g_ip_endpoints); i := i + 1) {
+ var IpEndpointTableEntry ipep := g_ip_endpoints[i];
+ if (ipep.address_family == AF_INET) {
+ v4 := v4 & { valueof(ts_SNS_IPv4(ipep.local_ip,
+ ipep.local_udp_port,
+ ipep.signalling_weight,
+ ipep.data_weight)) };
+ } else if (ipep.address_family == AF_INET6) {
+ v6 := v6 & { valueof(ts_SNS_IPv6(ipep.local_ip,
+ ipep.local_udp_port,
+ ipep.signalling_weight,
+ ipep.data_weight)) };
+ }
+ }
+
+ /* we must not return empty lists, but 'omit' as otherwise we get wrong SNS IEs */
+ if (lengthof(v4) == 0) {
+ v4_out := omit;
+ } else {
+ v4_out := v4;
+ }
+ if (lengthof(v6) == 0) {
+ v6_out := omit;
+ } else {
+ v6_out := v6;
+ }
+ }
+
+ private function f_broadcast_ns_ctrl(template (value) NsCtrlRequest req) runs on NS_CT {
+ for (var integer i := 0; i < lengthof(g_nsvcs); i := i+1) {
+ NSVC.send(req) to g_nsvcs[i].vc_conn;
+ }
+ }
+
+ /* perform an outbound SNS-SIZE + SNS-CONFIG */
+ private function f_sns_outbound_size_config(integer idx := 0) runs on NS_CT {
+ var NSVCConfiguration nsvc_cfg := g_config.nsvc[idx];
+ var NSVC_CT vc;
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ NSVC.send(SnsRequest:{nsvc_cfg.nsvci, ts_SNS_SIZE(g_config.nsei, rst_flag := true,
+ max_nsvcs := 1,
+ num_v4 := 1, num_v6 := omit)});
+ } else {
+ NSVC.send(SnsRequest:{nsvc_cfg.nsvci, ts_SNS_SIZE(g_config.nsei, rst_flag := true,
+ max_nsvcs := 1,
+ num_v4 := omit, num_v6 := 1)});
+ }
+ /* expect SIZE-ACK */
+ alt {
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_SIZE_ACK(g_config.nsei, omit)}) -> sender vc;
+ [] NSVC.receive(NsStatusIndication:?) { repeat; }
+ }
+ /* send a SNS-CONFIG in response and expect a SNS-CONFIG-ACK */
+ var template (omit) IP4_Elements v4;
+ var template (omit) IP6_Elements v6;
+ gen_sns_ip_elems(v4, v6);
+ NSVC.send(SnsRequest:{nsvc_cfg.nsvci,
+ ts_SNS_CONFIG(g_config.nsei, true, v4, v6)}) to vc;
+ alt {
+ [] as_ns_common_status() {
+ repeat;
+ }
+ [] NSVC.receive(SnsIndication:{?,
+ tr_SNS_CONFIG_ACK(g_config.nsei, omit)}) from vc {
+ /* success */
+ log("Outbound SNS Config succeeded.");
+ }
+ [] NSVC.receive(SnsIndication:{?,
+ tr_SNS_CONFIG_ACK(g_config.nsei, ?)}) from vc {
+ setverdict(fail, "Unexpected SNS-CONFIG-NACK");
+ self.stop;
+ }
+ }
+ }
+
+ /* simple IP Sub-Network Service responder for the PCU/BSS side. This is not a full implementation
+ * of the protocol, merely sufficient to make the SGSN side happy to proceed */
+ private altstep as_vcg_sns_pcu() runs on NS_CT {
+ var SnsIndication sind;
+ var NSVC_CT vc;
+
+ /* FIXME: We assume our peer has only one endpoint */
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true,
+ {tr_SNS_IPv4(g_config.nsvc[0].provider.ip.remote_ip,
+ g_config.nsvc[0].provider.ip.remote_udp_port)})})
+ -> value sind sender vc {
+ /* blindly acknowledge whatever the SGSN sends */
+ NSVC.send(SnsRequest:{sind.nsvci, ts_SNS_CONFIG_ACK(g_config.nsei, omit)}) to vc;
+ log("Inbound SNS Config succeeded.");
+ /* switch to "alive" state already before sending the SNS-CONFIG, as otherwise
+ * there would be a race condition between internally performing the state change
+ * of all related NS-VCs and the first incoming NS-PDU after SNS-CONFIG-ACK */
+ f_broadcast_ns_ctrl(NsCtrlRequest:ForceAliveState);
+ /* inform all NS-VC that they are now considered alive */
+ f_broadcast_ns_ctrl(NsCtrlRequest:StartAliveProcedure);
+ }
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, false, ?)}) { /* ignore */}
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true, ?)}) {
+ setverdict(fail, "Unexpected SNS-CONFIG content");
+ self.stop;
+ }
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(?, ?, ?)}) {
+ setverdict(fail, "SNS-CONFIG from unexpected NSEI");
+ self.stop;
+ }
+
+ }
+
+ /* simple IP Sub-Network Service responder for the SGSN side. This is not a full implementation
+ * of the protocol, merely sufficient to make the PCU/BSS side happy to proceed */
+ private altstep as_vcg_sns_sgsn() runs on NS_CT {
+ var SnsIndication sind;
+ var NSVC_CT vc;
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_SIZE(g_config.nsei)}) -> value sind sender vc {
+ /* blindly acknowledge whatever the PCU sends */
+ NSVC.send(SnsRequest:{sind.nsvci, ts_SNS_SIZE_ACK(g_config.nsei, omit)}) to vc;
+ }
+ /* FIXME: We assume our peer has only one endpoint */
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true,
+ {tr_SNS_IPv4(g_config.nsvc[0].provider.ip.remote_ip,
+ g_config.nsvc[0].provider.ip.remote_udp_port)})})
+ -> value sind sender vc {
+ /* blindly acknowledge whatever the PCU sends */
+ NSVC.send(SnsRequest:{sind.nsvci, ts_SNS_CONFIG_ACK(g_config.nsei, omit)}) to vc;
+ /* switch to "alive" state already before sending the SNS-CONFIG, as otherwise
+ * there would be a race condition between internally performing the state change
+ * of all related NS-VCs and the first incoming NS-PDU after SNS-CONFIG-ACK */
+ f_broadcast_ns_ctrl(NsCtrlRequest:ForceAliveState);
+ /* send a SNS-CONFIG in response and expect a SNS-CONFIG-ACK */
+ var template (omit) IP4_Elements v4;
+ var template (omit) IP6_Elements v6;
+ gen_sns_ip_elems(v4, v6);
+ NSVC.send(SnsRequest:{sind.nsvci,
+ ts_SNS_CONFIG(g_config.nsei, true, v4, v6)}) to vc;
+ alt {
+ [] as_ns_common_status() {
+ repeat;
+ }
+ [] NSVC.receive(SnsIndication:{sind.nsvci,
+ tr_SNS_CONFIG_ACK(g_config.nsei, omit)}) from vc {
+ /* success */
+ log("SNS Config succeeded. Sending Alive");
+ /* inform all NS-VC that they are now considered alive */
+ f_broadcast_ns_ctrl(NsCtrlRequest:StartAliveProcedure);
+ }
+ [] NSVC.receive(SnsIndication:{sind.nsvci,
+ tr_SNS_CONFIG_ACK(g_config.nsei, ?)}) from vc {
+ setverdict(fail, "Unexpected SNS-CONFIG-NACK");
+ self.stop;
+ }
+ }
+ }
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, false, ?)}) { /* ignore */}
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(g_config.nsei, true, ?)}) {
+ setverdict(fail, "Unexpected SNS-CONFIG content");
+ self.stop;
+ }
+ [] NSVC.receive(SnsIndication:{?, tr_SNS_CONFIG(?, ?, ?)}) {
+ setverdict(fail, "SNS-CONFIG from unexpected NSEI");
+ self.stop;
+ }
+ }
+
+ /***********************************************************************
+ per-NSVC component. Exists once for each NS-VC in the NS-VCG
+ ***********************************************************************/
+
+ type component NSVC_CT {
+ /* UDP port towards the bottom (IUT) */
+ port NS_PROVIDER_PT NSCP;
+ var NS_Provider_IPL4_CT vc_NSP_IP;
+#ifdef NS_EMULATION_FR
+ var NS_Provider_FR_CT vc_NSP_FR;
+#endif
+
+ /* port towards the NS_CT */
+ port NSint_SP_PT NS_SP;
+
+ /* configuration passed by the user */
+ var NSVCConfiguration g_nsvc_config;
+ /* we cannot access the NS_CT.config and hence need to copy those */
+ var NSConfiguration g_config;
+
+ var NsvcState vc_state := NSVC_S_DEAD_BLOCKED;
+
+ timer Tns_alive := 3.0;
+ timer Tns_test := 10.0;
+ timer Tns_block := 10.0;
+ timer Tns_reset := 10.0;
+ }
+
+ function NSVCStart(NSVCConfiguration init_config, NSConfiguration init_g_config, charstring id :=
+testcasename(), NS_Provider_IPL4_CT nsp_ip := null) runs on NSVC_CT {
+ g_nsvc_config := init_config;
+ g_config := init_g_config;
+ f_init(id & "-NSVCemu" & int2str(g_nsvc_config.nsvci), nsp_ip);
+ f_ScanEvents();
+ }
+
+ private function f_init(charstring id, NS_Provider_IPL4_CT nsp_ip) runs on NSVC_CT {
+ if (ischosen(g_nsvc_config.provider.ip)) {
+ /* the provider already exists; we just associate with it */
+ vc_NSP_IP := nsp_ip
+#ifdef NS_EMULATION_FR
+ } else if (ischosen(g_nsvc_config.provider.fr)) {
+ vc_NSP_FR := NS_Provider_FR_CT.create(id & "-provFR") alive;
+ connect(self:NSCP, vc_NSP_FR:NSE);
+ vc_NSP_FR.start(NS_Provider_FR.main(g_nsvc_config, g_config, id));
+#endif
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unsupported NS provider");
+ }
+
+ f_change_state(NSVC_S_DEAD_BLOCKED);
+ }
+
+ private function f_change_state(NsvcState new_state) runs on NSVC_CT {
+ var NsvcState old_state := vc_state;
+ vc_state := new_state;
+ log("NSVC ", g_nsvc_config.nsvci, " State Transition: ", old_state, " -> ", new_state);
+ NS_SP.send(ts_NsStsInd(g_config.nsei, g_nsvc_config.nsvci, old_state, new_state));
+ }
+
+ private function f_sendReset() runs on NSVC_CT {
+ NSCP.send(ts_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsvc_config.nsvci, g_config.nsei));
+ Tns_reset.start;
+ vc_state := NSVC_S_WAIT_RESET;
+ }
+
+ private function f_sendAlive() runs on NSVC_CT {
+ NSCP.send(t_NS_ALIVE);
+ Tns_alive.start;
+ }
+
+ private function f_sendUnblock() runs on NSVC_CT {
+ NSCP.send(t_NS_UNBLOCK);
+ Tns_block.start;
+ }
+
+ private function f_sendBlock(NsCause cause) runs on NSVC_CT {
+ NSCP.send(ts_NS_BLOCK(cause, g_nsvc_config.nsvci));
+ Tns_block.start;
+ }
+
+ private altstep as_allstate() runs on NSVC_CT {
+ var PDU_NS rf;
+ var ASP_Event evt;
+
+ [] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_DOWN}) {
+ log("Provider Link went down");
+ Tns_test.stop;
+ Tns_alive.stop;
+ f_change_state(NSVC_S_DEAD_BLOCKED);
+ }
+
+ [] NS_SP.receive(NsCtrlRequest:DisableReq) {
+ /* To make NS-VCG remove us from list of active NS-VC */
+ f_change_state(NSVC_S_DEAD_BLOCKED);
+ log("Disabling NSVC on user request");
+ f_change_state(NSVC_S_DISABLED);
+ Tns_test.stop;
+ Tns_alive.stop;
+ }
+
+ /* transition to DEAD if t_alive times out */
+ [Tns_alive.running] Tns_alive.timeout {
+ log("Tns-alive expired: changing to DEAD_BLOCKED + starting Tns-test");
+ f_change_state(NSVC_S_DEAD_BLOCKED);
+ Tns_test.start;
+ }
+
+ [Tns_test.running] Tns_test.timeout {
+ log("Tns-test expired: sending NS-ALIVE");
+ f_sendAlive();
+ }
+
+ /* Stop t_alive when receiving ALIVE-ACK */
+ [Tns_alive.running] NSCP.receive(t_NS_ALIVE_ACK) {
+ log("Rx NS-ALIVE-ACK: stopping Tns-alive; starting Tns-test");
+ Tns_alive.stop;
+ Tns_test.start;
+ }
+
+ /* respond to NS-ALIVE with NS-ALIVE-ACK */
+ [] NSCP.receive(t_NS_ALIVE) {
+ NSCP.send(t_NS_ALIVE_ACK);
+ }
+
+ /* Respond to BLOCK for wrong NSVCI */
+ [] NSCP.receive(tr_NS_BLOCK(?, ?)) -> value rf {
+ log("Rx NS-BLOCK for unknown NSVCI");
+ /* FIXME */
+ }
+
+ [not g_config.handle_sns] as_handle_reset();
+
+ [g_config.handle_sns and ischosen(g_nsvc_config.provider.ip)] as_nsvc_sns();
+
+ /* log + ignore NS-STATUS; must not create another NS-STATUS in response */
+ [] NSCP.receive(tr_NS_STATUS(?)) -> value rf {
+ log("Rx NS-STATUS ", rf," in state ", vc_state);
+ }
+ /* default case of handling unknown PDUs */
+ [] NSCP.receive(PDU_NS: ?) -> value rf {
+ log("Rx Unexpected NS PDU ", rf," in state ", vc_state);
+ NSCP.send(ts_NS_STATUS(NS_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, rf));
+ }
+ }
+
+ private altstep as_disabled() runs on NSVC_CT {
+ [g_config.handle_sns == true] NS_SP.receive(NsCtrlRequest:EnableReq) {
+ f_change_state(NSVC_S_ALIVE_UNBLOCKED);
+ f_sendAlive();
+ Tns_test.start;
+ }
+ [g_config.handle_sns == false] NS_SP.receive(NsCtrlRequest:EnableReq) {
+ f_change_state(NSVC_S_DEAD_BLOCKED);
+ Tns_test.start;
+ }
+ /* drop any received messages while in this state */
+ [] NSCP.receive {
+ log("Dropping inbound NS mesage as NS-VC is disabled");
+ }
+ [] NS_SP.receive {
+ log("Dropping user primitive as NS-VC is disabled");
+ }
+ }
+
+ private altstep as_handle_reset() runs on NSVC_CT {
+ var PDU_NS rf;
+
+ [g_config.role_sgsn] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
+ log("Provider Link came up: waiting for NS-RESET");
+ }
+
+ [not g_config.role_sgsn] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
+ log("Provider Link came up: sending NS-RESET");
+ f_sendReset();
+ }
+
+ /* Respond to RESET with correct NSEI/NSVCI */
+ [] NSCP.receive(tr_NS_RESET(?, g_nsvc_config.nsvci, g_config.nsei)) -> value rf {
+ f_change_state(NSVC_S_ALIVE_BLOCKED);
+ NSCP.send(ts_NS_RESET_ACK(g_nsvc_config.nsvci, g_config.nsei));
+ log("Rx NS-RESET: Sending NS-ALIVE");
+ f_sendAlive();
+ Tns_test.start;
+ }
+
+ /* Respond to RESET with wrong NSEI/NSVCI */
+ [] NSCP.receive(tr_NS_RESET(?, ?, ?)) -> value rf {
+ log("Rx NS-RESET for unknown NSEI/NSVCI");
+ /* FIXME */
+ }
+ }
+
+ private altstep as_nsvc_sns() runs on NSVC_CT {
+ var PDU_NS rf;
+ var SnsRequest sreq;
+ [] NSCP.receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP}) {
+ log("Provider Link came up. Waiting for SNS Size");
+ }
+
+ /* pass up to NS-VCG */
+ [] NSCP.receive(tr_SNS(g_config.nsei)) -> value rf {
+ NS_SP.send(SnsIndication:{g_nsvc_config.nsvci, rf});
+ }
+ [] NSCP.receive(tr_SNS(?)) -> value rf {
+ setverdict(fail, "SNS from unexpected NSEI: ", rf);
+ self.stop;
+ }
+ [] NS_SP.receive(SnsRequest:{g_nsvc_config.nsvci, ?}) -> value sreq {
+ NSCP.send(sreq.ns);
+ }
+ [] NS_SP.receive(SnsRequest:?) -> value sreq {
+ setverdict(fail, "Unexpected SNS from NSVC: ", sreq);
+ self.stop;
+ }
+ [] NS_SP.receive(NsCtrlRequest:ForceAliveState) {
+ f_change_state(NSVC_S_ALIVE_UNBLOCKED);
+ }
+ [] NS_SP.receive(NsCtrlRequest:StartAliveProcedure) {
+ f_sendAlive();
+ Tns_test.start;
+ }
+ }
+
+ private altstep as_alive_blocked() runs on NSVC_CT {
+ var PDU_NS rf;
+ /* bogus block, just respond with ACK */
+ [] NSCP.receive(tr_NS_BLOCK(?, g_nsvc_config.nsvci)) -> value rf {
+ NSCP.send(ts_NS_BLOCK_ACK(g_nsvc_config.nsvci));
+ }
+ /* Respond to UNBLOCK with UNBLOCK-ACK + change state */
+ [] NSCP.receive(t_NS_UNBLOCK) -> value rf {
+ NSCP.send(t_NS_UNBLOCK_ACK);
+ Tns_block.stop;
+ f_change_state(NSVC_S_ALIVE_UNBLOCKED);
+ }
+ [] NSCP.receive(t_NS_UNBLOCK_ACK) -> value rf {
+ Tns_block.stop;
+ f_change_state(NSVC_S_ALIVE_UNBLOCKED);
+ }
+ /* tolerate a late NS-BLOCK-ACK from peer */
+ [] NSCP.receive(tr_NS_BLOCK_ACK(g_nsvc_config.nsvci)) -> value rf {
+ }
+ [] Tns_block.timeout {
+ /* repeat unblock transmission */
+ f_sendUnblock();
+ }
+ }
+
+ private altstep as_alive_unblocked() runs on NSVC_CT {
+ var NsUnitdataRequest ud_req;
+ var PDU_NS rf;
+ /* bogus unblock, just respond with ACK */
+ [] NSCP.receive(t_NS_UNBLOCK) -> value rf {
+ NSCP.send(t_NS_UNBLOCK_ACK);
+ }
+ /* Respond to BLOCK with BLOCK-ACK + change state */
+ [] NSCP.receive(tr_NS_BLOCK(?, g_nsvc_config.nsvci)) -> value rf {
+ NSCP.send(ts_NS_BLOCK_ACK(g_nsvc_config.nsvci));
+ Tns_block.stop;
+ f_change_state(NSVC_S_ALIVE_BLOCKED);
+ }
+ [] NSCP.receive(tr_NS_BLOCK_ACK(g_nsvc_config.nsvci)) -> value rf {
+ Tns_block.stop;
+ }
+ /* tolerate a late NS-UNBLOCK-ACK from peer */
+ [] NSCP.receive(t_NS_UNBLOCK_ACK) -> value rf {
+ }
+
+ [not ischosen(g_nsvc_config.provider.ip) or
+ g_nsvc_config.provider.ip.data_weight > 0] as_alive_unblocked_data();
+
+ [not ischosen(g_nsvc_config.provider.ip) or
+ g_nsvc_config.provider.ip.signalling_weight > 0] as_alive_unblocked_sig();
+
+ /* catch any violations of above rule */
+ [ischosen(g_nsvc_config.provider.ip)] NSCP.receive(tr_NS_UNITDATA(?, ?, ?)) -> value rf {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected Rx NS-UNITDATA on NSVC with data_weight=",
+ g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
+ g_nsvc_config.provider.ip.signalling_weight, ": ", rf));
+ }
+ [ischosen(g_nsvc_config.provider.ip)] NS_SP.receive(tr_NsUdReq(g_config.nsei, ?, ?, *, *)) -> value ud_req {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected Rx TX-UNITDATA on NSVC with data_weight=",
+ g_nsvc_config.provider.ip.data_weight, ", sig_weight=",
+ g_nsvc_config.provider.ip.signalling_weight, ": ", ud_req));
+ }
+ }
+
+ /* user data transfer; only permitted for some NS-VC */
+ private altstep as_alive_unblocked_data() runs on NSVC_CT {
+ var NsUnitdataRequest ud_req;
+ var PDU_NS rf;
+ /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
+ [] NSCP.receive(tr_NS_UNITDATA_User(?, ?)) -> value rf {
+ NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
+ oct2int(rf.pDU_NS_Unitdata.bVCI),
+ rf.pDU_NS_Unitdata.nS_SDU));
+ }
+ /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, ?, omit)) -> value ud_req {
+ /* using raw octetstring PDU */
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
+ }
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, t_BssgpBvciUser, ?, omit, ?)) -> value ud_req {
+ /* using decoded BSSGP PDU that we need to encode first */
+ var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
+ }
+ }
+
+ /* signalling (BVCI=0) transfer; only permitted for some NS-VC */
+ private altstep as_alive_unblocked_sig() runs on NSVC_CT {
+ var NsUnitdataRequest ud_req;
+ var PDU_NS rf;
+ /* NS-UNITDATA PDU from network to NS-UNITDATA.ind to user */
+ [] NSCP.receive(tr_NS_UNITDATA(?, 0, ?)) -> value rf {
+ NS_SP.send(ts_NsUdInd(g_config.nsei, g_nsvc_config.nsvci,
+ oct2int(rf.pDU_NS_Unitdata.bVCI),
+ rf.pDU_NS_Unitdata.nS_SDU));
+ }
+ /* NS-UNITDATA.req from user to NS-UNITDATA PDU on network */
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, ?, omit)) -> value ud_req {
+ /* using raw octetstring PDU */
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, ud_req.sdu));
+ }
+ [] NS_SP.receive(tr_NsUdReq(g_config.nsei, 0, ?, omit, ?)) -> value ud_req {
+ /* using decoded BSSGP PDU that we need to encode first */
+ var octetstring enc := enc_PDU_BSSGP(ud_req.bssgp);
+ NSCP.send(ts_NS_UNITDATA(t_SduCtrlB, ud_req.bvci, enc));
+ }
+ }
+
+ private altstep as_wait_reset() runs on NSVC_CT {
+ var PDU_NS rf;
+ [] Tns_reset.timeout {
+ /* If the sending entity of an NS-RESET PDU receives no NS-RESET-ACK PDU before timer
+ * Tns-reset expires the corresponding NS-VCs shall remain blocked and dead and the
+ * entire reset procedure shall be repeated */
+ f_sendReset();
+ }
+ [] NSCP.receive(tr_NS_RESET_ACK(g_nsvc_config.nsvci, g_config.nsei)) -> value rf {
+ Tns_reset.stop;
+ f_change_state(NSVC_S_ALIVE_BLOCKED);
+ f_sendAlive();
+ f_sendUnblock();
+ }
+ }
+
+ private function f_ScanEvents() runs on NSVC_CT {
+ var PDU_NS rf;
+ while (true) {
+ alt {
+ [vc_state == NSVC_S_WAIT_RESET] as_wait_reset();
+ [vc_state == NSVC_S_ALIVE_BLOCKED] as_alive_blocked();
+ [vc_state == NSVC_S_ALIVE_UNBLOCKED] as_alive_unblocked();
+ [vc_state == NSVC_S_DISABLED] as_disabled();
+ [vc_state != NSVC_S_DISABLED] as_allstate();
+ }
+ }
+ }
+}
diff --git a/library/NS_Provider_FR.ttcn b/library/NS_Provider_FR.ttcn
new file mode 100644
index 00000000..b664b5e5
--- /dev/null
+++ b/library/NS_Provider_FR.ttcn
@@ -0,0 +1,105 @@
+/* NS Provider for NS/FR/E1
+ * (C) 2020 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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 NS_Provider_FR {
+
+import from NS_Emulation all;
+import from NS_Types all;
+
+import from AF_PACKET_PortType all;
+import from FrameRelay_Types all;
+import from FrameRelay_Emulation all;
+
+
+type component NS_Provider_FR_CT extends NS_Provider_CT, FR_Client_CT {
+ /* component reference to Frame Relay emulation */
+ var FR_Emulation_CT vc_FREMU;
+
+ var boolean link_available := false;
+ var boolean pvc_active := false;
+};
+
+function main(NSVCConfiguration config, NSConfiguration nsconfig, charstring id) runs on NS_Provider_FR_CT system af_packet {
+
+ /* start Frame Relay Emulation */
+ vc_FREMU := FR_Emulation_CT.create(id & "-FRemu") alive;
+ var Q933em_Config q933_cfg := valueof(ts_Q933em_Config(ats_is_user := not nsconfig.role_sgsn, bidirectional := false));
+ q933_cfg.T391 := 1.0;
+ map(vc_FREMU:FR, system:AF_PACKET) param (config.provider.fr.netdev);
+ vc_FREMU.start(FrameRelay_Emulation.main(q933_cfg));
+
+ /* connect ourselves to frame relay emulation */
+ connect(self:FR, vc_FREMU:CLIENT);
+ connect(self:FR_PROC, vc_FREMU:PROC);
+
+ /* register ourselves for the specified DLCI */
+ f_fremu_register(config.provider.fr.dlci);
+
+ /* transceive between user-facing port and FR socket */
+ while (true) {
+ var FrameRelayFrame rx_fr;
+ var FRemu_Event rx_frevt;
+ var PDU_NS rx_pdu;
+ alt {
+
+ [not link_available] FR.receive(FrameRelayFrame:?) -> value rx_fr {
+ log("Dropping Rx Msg because FR link not yet available", rx_fr);
+ /* this can happen if the remote side has not yet recognized the
+ * link is dead; don' fail here */
+ }
+ [link_available and pvc_active] FR.receive(tr_FR(config.provider.fr.dlci)) -> value rx_fr {
+ var PDU_NS ns := dec_PDU_NS(rx_fr.payload);
+ NSE.send(ns);
+ }
+ [not pvc_active] FR.receive(tr_FR(config.provider.fr.dlci)) -> value rx_fr {
+ log("Dropping Rx Msg because FR DLC not yet available", rx_fr);
+ }
+ [] FR.receive(tr_FR(?)) -> value rx_fr {
+ log("Dropping Rx Msg because DLCI unknown", rx_fr);
+ setverdict(fail);
+ }
+
+ [] FR.receive(FRemu_Event:{link_status:=FR_LINK_STS_AVAILABLE}) -> value rx_frevt {
+ if (link_available == false and pvc_active == true) {
+ NSE.send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_UP});
+ }
+ link_available := true;
+ }
+ [] FR.receive(FRemu_Event:{link_status:=FR_LINK_STS_UNAVAILABLE}) -> value rx_frevt {
+ link_available := false;
+ pvc_active := false;
+ NSE.send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_DOWN});
+ }
+ [] FR.receive(tr_FRemu_PvcStatusAct(config.provider.fr.dlci, true)) -> value rx_frevt {
+ if (pvc_active == false and link_available == true) {
+ NSE.send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_UP});
+ }
+ pvc_active := true;
+ }
+ [] FR.receive(tr_FRemu_PvcStatusAct(config.provider.fr.dlci, false)) -> value rx_frevt {
+ pvc_active := false;
+ NSE.send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_DOWN});
+ }
+ [] FR.receive(FRemu_Event:?) -> value rx_frevt {
+ log("Unhandled FRemu_event: ", rx_frevt);
+ }
+ [] NSE.receive(PDU_NS:?) -> value rx_pdu {
+ FR.send(ts_FR(config.provider.fr.dlci, enc_PDU_NS(rx_pdu), true));
+ }
+
+ }
+ }
+
+} /* main */
+
+
+
+} /* module */
diff --git a/library/NS_Provider_IPL4.ttcn b/library/NS_Provider_IPL4.ttcn
new file mode 100644
index 00000000..09e7dc0e
--- /dev/null
+++ b/library/NS_Provider_IPL4.ttcn
@@ -0,0 +1,229 @@
+/* NS Provider for NS/UDP/IP
+ * (C) 2020-2021 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * 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
+ */
+
+/* This provider can be operated in two modes:
+ *
+ * 1) the "classic" mode, where - similar to the NS_Provider_FR - there is
+ * only one NSVC per provider. In this mode, the "NSE" port is used to
+ * exchange data with the next higher level component, such as a NSVC_CT
+ * or a RAW_NS_CT.
+ *
+ * 2) the new "endpoint" mode, where one provider can host a number of different
+ * NSVCs. This is needed in most non-trivial IP-SNS scenarios. The 'NSE'
+ * port of this component is no longer used. Instead, there is a NSVC port
+ * array, one of which will be used for each NSVC. The NSVCs are dynamically
+ * added and removed via the PROC procedure port, controlled by NS_CT.
+ */
+
+module NS_Provider_IPL4 {
+
+import from Misc_Helpers all;
+import from NS_Emulation all;
+import from RAW_NS all;
+import from NS_Types all;
+
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+
+/* maximum number of NS-VCs within one Provider (== IP endpoint) */
+private const integer NUM_MAX_NSVC := 16;
+
+type component NS_Provider_IPL4_CT extends NS_Provider_CT {
+ /* down-facing port towards IPL4asp to IUT */
+ port IPL4asp_PT IPL4;
+ var integer g_conn_id := -1;
+
+ /* per-NSVC ports and state */
+ port NS_PROVIDER_PT NSVC[NUM_MAX_NSVC];
+ var boolean g_nsvc_bound[NUM_MAX_NSVC];
+ var PerNsvcState g_nsvc[NUM_MAX_NSVC];
+
+ /* management port via which */
+ port NSPIP_PROC_PT PROC;
+};
+
+type record PerNsvcState {
+ charstring remote_ip,
+ PortNumber remote_port,
+ NSVC_CT vc_nsvc
+};
+
+signature NSPIP_add_nsvc(charstring remote_ip, PortNumber remote_port, NSVC_CT vc_nsvc) return integer;
+signature NSPIP_del_nsvc(charstring remote_ip, PortNumber remote_port) return integer;
+
+type port NSPIP_PROC_PT procedure {
+ inout NSPIP_add_nsvc, NSPIP_del_nsvc;
+} with { extension "internal" };
+
+/* add a new NSVC to the provider */
+private function f_nsvc_add(PerNsvcState nsvc) runs on NS_Provider_IPL4_CT return integer
+{
+ for (var integer i := 0; i < sizeof(g_nsvc); i := i+1) {
+ if (g_nsvc_bound[i] == false) {
+ g_nsvc[i] := nsvc;
+ g_nsvc_bound[i] := true;
+ if (isbound(nsvc.vc_nsvc) and nsvc.vc_nsvc != null) {
+ connect(self:NSVC[i], nsvc.vc_nsvc:NSCP);
+ NSVC[i].send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_UP});
+ }
+ return i;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Overflow of g_nsvc array"));
+ return -1;
+}
+
+private function f_nsvc_del(PerNsvcState nsvc) runs on NS_Provider_IPL4_CT return integer
+{
+ for (var integer i := 0; i < sizeof(g_nsvc); i := i+1) {
+ if (g_nsvc_bound[i] and
+ g_nsvc[i].remote_ip == nsvc.remote_ip and
+ g_nsvc[i].remote_port == nsvc.remote_port) {
+ g_nsvc[i] := {
+ remote_ip := -,
+ remote_port := -,
+ vc_nsvc := null
+ }
+ g_nsvc_bound[i] := false;
+ NSVC[i].send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_DOWN});
+ if (isbound(g_nsvc[i].vc_nsvc) and g_nsvc[i].vc_nsvc != null) {
+ disconnect(self:NSVC[i], nsvc.vc_nsvc:NSCP);
+ }
+ return i;
+ }
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("attempt to delete unknown NSVC"));
+ return -1;
+}
+
+private function f_get_nsvc_idx(charstring remote_ip, PortNumber remote_port)
+runs on NS_Provider_IPL4_CT return integer
+{
+ for (var integer i := 0; i < sizeof(g_nsvc); i := i+1) {
+ if (g_nsvc_bound[i] and
+ g_nsvc[i].remote_ip == remote_ip and g_nsvc[i].remote_port == remote_port) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+function main(NSVCConfiguration config, NSConfiguration nsconfig, charstring id) runs on NS_Provider_IPL4_CT {
+ for (var integer i := 0; i < sizeof(g_nsvc); i := i+1) {
+ g_nsvc[i].vc_nsvc := null;
+ g_nsvc_bound[i] := false;
+ }
+
+ /* in order to support any number of NSVC on this endpoiint, we only bind the socket
+ * to its local ip/port, but do not connect it to the remote peer provided in 'config'. */
+ map(self:IPL4, system:IPL4);
+ var Result res := f_IPL4_listen(IPL4, config.provider.ip.local_ip,
+ config.provider.ip.local_udp_port, { udp := {}});
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not connect NS UDP socket ", config.provider.ip);
+ mtc.stop;
+ }
+ g_conn_id := res.connId;
+
+ if (NSE.checkstate("Connected")) {
+ NSE.send(NS_Provider_Evt:{link_status := NS_PROV_LINK_STATUS_UP});
+ }
+
+ /* transceive between user-facing port and UDP socket */
+ while (true) {
+ var ASP_RecvFrom rx_rf;
+ var PDU_NS rx_pdu;
+ var integer rx_idx;
+ var charstring remote_ip;
+ var PortNumber remote_port;
+ var NSVC_CT vc_nsvc;
+ var NS_CT vc_caller;
+ alt {
+
+ [] IPL4.receive(ASP_RecvFrom:?) -> value rx_rf {
+ /* we have to resolve the NS-VC based on the remote peer */
+ var integer nsvc_idx := f_get_nsvc_idx(rx_rf.remName, rx_rf.remPort);
+ if (nsvc_idx == -1) {
+ /* backwards compatibility; if there's no NSVC, send to NSE port */
+ NSE.send(dec_PDU_NS(rx_rf.msg));
+ } else {
+ /* endpoint mode; send to the per-NSVC component via NSVC port */
+ NSVC[nsvc_idx].send(dec_PDU_NS(rx_rf.msg));
+ }
+ }
+
+ [] IPL4.receive(ASP_ConnId_ReadyToRelease:?) {
+ }
+
+ [] IPL4.receive(ASP_Event:?) {
+ }
+
+ [] any from NSVC.receive(PDU_NS:?) -> value rx_pdu @index value rx_idx {
+ /* we can use the port array index directly into the g_nsvc array in order
+ * to resolve the IP + port of the remote peer to which to send */
+ var ASP_SendTo tx := {
+ connId := g_conn_id,
+ remName := g_nsvc[rx_idx].remote_ip,
+ remPort := g_nsvc[rx_idx].remote_port,
+ proto := { udp := {} },
+ msg := enc_PDU_NS(rx_pdu)
+ };
+ IPL4.send(tx);
+ }
+ [] NSE.receive(PDU_NS:?) -> value rx_pdu {
+ /* backwards compatibility: If user uses the NSE port, use the destination
+ * provided during main() initialization */
+ var ASP_SendTo tx := {
+ connId := g_conn_id,
+ remName := config.provider.ip.remote_ip,
+ remPort := config.provider.ip.remote_udp_port,
+ proto := { udp := {} },
+ msg := enc_PDU_NS(rx_pdu)
+ };
+ IPL4.send(tx);
+ }
+
+ /* procedure port to add/remove NSVCs from this provider */
+ [] PROC.getcall(NSPIP_add_nsvc:{?,?,?}) -> param (remote_ip, remote_port, vc_nsvc) sender vc_caller {
+ var integer idx;
+ idx := f_nsvc_add(PerNsvcState:{remote_ip, remote_port, vc_nsvc});
+ PROC.reply(NSPIP_add_nsvc:{remote_ip, remote_port, vc_nsvc} value idx) to vc_caller;
+ }
+ [] PROC.getcall(NSPIP_del_nsvc:{?,?}) -> param (remote_ip, remote_port) sender vc_caller {
+ var integer idx;
+ idx := f_nsvc_del(PerNsvcState:{remote_ip, remote_port});
+ PROC.reply(NSPIP_del_nsvc:{remote_ip, remote_port} value idx) to vc_caller;
+ }
+
+ } /* alt */
+ } /* while */
+
+} /* main */
+
+function f_nspip_add_nsvc(NS_Provider_IPL4_CT vc_ipep, charstring remote_ip, PortNumber remote_port, NSVC_CT vc_nsvc)
+runs on NS_CT {
+ var integer idx := -1;
+ NSPIP_PROC.call(NSPIP_add_nsvc:{remote_ip, remote_port, vc_nsvc}) to vc_ipep {
+ [] NSPIP_PROC.getreply(NSPIP_add_nsvc:{?,?,?}) -> value idx;
+ }
+}
+
+function f_nspip_add_nsvc2(NS_Provider_IPL4_CT vc_ipep, charstring remote_ip, PortNumber remote_port)
+runs on RAW_NS_CT return integer {
+ var integer idx := -1;
+ NSPIP_PROC.call(NSPIP_add_nsvc:{remote_ip, remote_port, null}) to vc_ipep {
+ [] NSPIP_PROC.getreply(NSPIP_add_nsvc:{?,?,?}) -> value idx;
+ }
+
+ return idx;
+}
+
+} /* module */
diff --git a/library/NS_Types.ttcn b/library/NS_Types.ttcn
index 6432d6c1..63ed24d2 100644
--- a/library/NS_Types.ttcn
+++ b/library/NS_Types.ttcn
@@ -56,7 +56,7 @@ module NS_Types {
NS_CAUSE_BVCI_UNKNOWN_AT_NSE ('00000101'B),
NS_CAUSE_SEMANTICALLY_INCORRECT_PDU ('00001000'B),
NS_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE ('00001010'B),
- NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED ('00001011'B),
+ NS_CAUSE_PROTOCOL_ERROR_UNSPECIFIED ('00001011'B),
NS_CAUSE_INVALID_ESSENTIAL_IE ('00001100'B),
NS_CAUSE_MISSING_ESSENTIAL_IE ('00001101'B),
NS_CAUSE_INVALID_NR_OF_IPv4_ENDPOINTS ('00001110'B),
diff --git a/library/Native_FunctionDefs.cc b/library/Native_FunctionDefs.cc
index 78ca4d1f..7139a624 100644
--- a/library/Native_FunctionDefs.cc
+++ b/library/Native_FunctionDefs.cc
@@ -76,6 +76,19 @@ CHARSTRING f__inet__hntoa(const OCTETSTRING& in)
return CHARSTRING(str);
}
+CHARSTRING f__inet6__ntoa(const OCTETSTRING& in)
+{
+ char buf[INET6_ADDRSTRLEN] = { 0 };
+ TTCN_Buffer ttcn_buffer(in);
+
+ const void *src = (const void *)ttcn_buffer.get_data();
+ const char *str = inet_ntop(AF_INET6, src, buf, sizeof(buf));
+ if (str == NULL)
+ fprintf(stderr, "inet_ntop failed: %s\n", strerror(errno));
+
+ return CHARSTRING((const char *)buf);
+}
+
CHARSTRING f__str__tolower(const CHARSTRING& in)
{
TTCN_Buffer ttcn_buffer(in);
diff --git a/library/Native_Functions.ttcn b/library/Native_Functions.ttcn
index c43004a9..c9cc9486 100644
--- a/library/Native_Functions.ttcn
+++ b/library/Native_Functions.ttcn
@@ -11,6 +11,8 @@ module Native_Functions {
external function f_inet_ntoa(in octetstring oct) return charstring;
/* like inet_ntoa() but input is host byte order */
external function f_inet_hntoa(in octetstring oct) return charstring;
+ /* direct import of inet_ntop(AF_INET6) C function, input net byte order */
+ external function f_inet6_ntoa(in octetstring oct) return charstring;
/* convert content of charstring to lower-case using tolower(3) */
external function f_str_tolower(in charstring input) return charstring;
diff --git a/library/OPCAP_Adapter.ttcn b/library/OPCAP_Adapter.ttcn
new file mode 100644
index 00000000..8bcc3fd9
--- /dev/null
+++ b/library/OPCAP_Adapter.ttcn
@@ -0,0 +1,105 @@
+module OPCAP_Adapter {
+
+/* OPCAP Adapter layer, sitting on top of OPCAP_CodecPort.
+ * test suites can 'inherit' in order to have a OPCAP connection to the IUT which they're testing
+ *
+ * (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+
+import from Osmocom_Types all;
+import from General_Types all;
+import from OPCAP_Types all;
+import from OPCAP_Templates all;
+import from OPCAP_CodecPort all;
+import from OPCAP_CodecPort_CtrlFunct all;
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+import from Socket_API_Definitions all;
+
+const integer NUM_OPCAP := 3;
+
+type component OPCAP_Adapter_CT {
+ /* down-facing port to OPCAP Codec port */
+ port OPCAP_CODEC_PT OPCAP[NUM_OPCAP];
+ var IPL4asp_Types.ConnectionId g_opcap_conn_id[NUM_OPCAP] := { -1, -1, -1 };
+}
+
+private function f_set_tcp_segmentation(integer idx) runs on OPCAP_Adapter_CT {
+ /* Set function for dissecting the binary stream into packets */
+ var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
+ /* Offset: 2, size of length: 2, delta: 4, multiplier: 1, big-endian */
+ OPCAP_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(OPCAP[idx], g_opcap_conn_id[idx], vl_f, {2, 2, 4, 1, 0});
+}
+
+function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
+ charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on OPCAP_Adapter_CT {
+ var IPL4asp_Types.Result res;
+ map(self:OPCAP[idx], system:OPCAP);
+ if (g_opcap_conn_id[idx] != -1) {
+ OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+ g_opcap_conn_id[idx] := -1;
+ }
+ res := OPCAP_CodecPort_CtrlFunct.f_IPL4_connect(OPCAP[idx], remote_host, remote_port,
+ local_host, local_port, 0, { tcp :={} });
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not connect to OPCAP port, check your configuration ",
+ "{remote ", remote_host, ":", remote_port, " local ", local_host, ":", local_port, "}");
+ mtc.stop;
+ }
+ g_opcap_conn_id[idx] := res.connId;
+
+ f_set_tcp_segmentation(idx);
+}
+
+/* Function to use to bind to a local port as IPA server, accepting remote clients */
+function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on OPCAP_Adapter_CT {
+ var IPL4asp_Types.Result res;
+ map(self:OPCAP[idx], system:OPCAP);
+ if (g_opcap_conn_id[idx] != -1) {
+ OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+ g_opcap_conn_id[idx] := -1;
+ }
+ res := OPCAP_CodecPort_CtrlFunct.f_IPL4_listen(OPCAP[idx], local_host, local_port, { tcp:={} });
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not bind to OPCAP port, check your configuration ",
+ "{local ", local_host, ":", local_port, "}");
+ mtc.stop;
+ }
+ g_opcap_conn_id[idx] := res.connId;
+
+ f_set_tcp_segmentation(idx);
+}
+
+function f_wait_client_connect(integer idx) runs on OPCAP_Adapter_CT {
+ var IPL4asp_Types.PortEvent rx_event;
+ OPCAP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
+ log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
+ /* we want to store the client's connId, not the 'bind socket' one */
+ g_opcap_conn_id[idx] := rx_event.connOpened.connId;
+ }
+}
+
+function f_disconnect(integer idx) runs on OPCAP_Adapter_CT {
+ OPCAP_CodecPort_CtrlFunct.f_IPL4_close(OPCAP[idx], g_opcap_conn_id[idx], {tcp := {}});
+ OPCAP[idx].clear;
+};
+
+function f_opcap_send(template (value) OPCAP_PDU pdu, integer idx := 0) runs on OPCAP_Adapter_CT {
+ OPCAP[idx].send(ts_OPCAP_Send(g_opcap_conn_id[idx], pdu));
+}
+
+function f_opcap_exp(template OPCAP_PDU exp, integer idx := 0) runs on OPCAP_Adapter_CT return OPCAP_PDU {
+ var OPCAP_RecvFrom rf;
+ OPCAP[idx].receive(tr_OPCAP_Recv(g_opcap_conn_id[idx], exp)) -> value rf;
+ return rf.msg;
+}
+
+
+}
diff --git a/library/OPCAP_CodecPort.ttcn b/library/OPCAP_CodecPort.ttcn
new file mode 100644
index 00000000..f2d215db
--- /dev/null
+++ b/library/OPCAP_CodecPort.ttcn
@@ -0,0 +1,64 @@
+module OPCAP_CodecPort {
+
+/* Simple OPCAP Codec Port, translating between raw TCP octetstring payload
+ * towards the IPL4asp port provider, and OPCAP primitives
+ * which carry the decoded OPCAP data types as payload.
+ *
+ * (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+
+import from IPL4asp_PortType all;
+import from IPL4asp_Types all;
+import from OPCAP_Types all;
+
+type record OPCAP_RecvFrom {
+ ConnectionId connId,
+ OPCAP_PDU msg
+}
+
+type record OPCAP_Send {
+ ConnectionId connId,
+ OPCAP_PDU msg
+}
+
+template (value) OPCAP_Send ts_OPCAP_Send(ConnectionId conn_id, template (value) OPCAP_PDU msg) := {
+ connId := conn_id,
+ msg := msg
+}
+
+template OPCAP_RecvFrom tr_OPCAP_Recv(template ConnectionId conn_id, template OPCAP_PDU msg) := {
+ connId := conn_id,
+ msg := msg
+}
+
+private function IPL4_to_OPCAP_RecvFrom(in ASP_RecvFrom pin, out OPCAP_RecvFrom pout) {
+ pout.connId := pin.connId;
+ pout.msg := dec_OPCAP_PDU(pin.msg);
+} with { extension "prototype(fast)" }
+
+private function OPCAP_to_IPL4_Send(in OPCAP_Send pin, out ASP_Send pout) {
+ pout.connId := pin.connId;
+ pout.proto := { tcp := {} };
+ pout.msg := enc_OPCAP_PDU(pin.msg);
+} with { extension "prototype(fast)" }
+
+type port OPCAP_CODEC_PT message {
+ out OPCAP_Send;
+ in OPCAP_RecvFrom,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+} with { extension "user IPL4asp_PT
+ out(OPCAP_Send -> ASP_Send: function(OPCAP_to_IPL4_Send))
+ in(ASP_RecvFrom -> OPCAP_RecvFrom: function(IPL4_to_OPCAP_RecvFrom);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)"
+}
+
+
+
+}
diff --git a/library/OPCAP_CodecPort_CtrlFunct.ttcn b/library/OPCAP_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..99a5fe74
--- /dev/null
+++ b/library/OPCAP_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,52 @@
+module OPCAP_CodecPort_CtrlFunct {
+
+ import from OPCAP_CodecPort all;
+ import from IPL4asp_Types all;
+
+ external function f_IPL4_listen(
+ inout OPCAP_CODEC_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_connect(
+ inout OPCAP_CODEC_PT portRef,
+ in HostName remName,
+ in PortNumber remPort,
+ in HostName locName,
+ in PortNumber locPort,
+ in ConnectionId connId,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_close(
+ inout OPCAP_CODEC_PT portRef,
+ in ConnectionId id,
+ in ProtoTuple proto := { unspecified := {} }
+ ) return Result;
+
+ external function f_IPL4_setUserData(
+ inout OPCAP_CODEC_PT portRef,
+ in ConnectionId id,
+ in UserData userData
+ ) return Result;
+
+ external function f_IPL4_getUserData(
+ inout OPCAP_CODEC_PT portRef,
+ in ConnectionId id,
+ out UserData userData
+ ) return Result;
+
+ external function f_IPL4_setGetMsgLen(
+ inout OPCAP_CODEC_PT portRef,
+ in ConnectionId id,
+ inout f_IPL4_getMsgLen f,
+ in ro_integer msgLenArgs
+ );
+
+
+}
+
diff --git a/library/GTP_CodecPort_CtrlFunctDef.cc b/library/OPCAP_CodecPort_CtrlFunctdef.cc
index c0b9391f..b19138a4 100644
--- a/library/GTP_CodecPort_CtrlFunctDef.cc
+++ b/library/OPCAP_CodecPort_CtrlFunctdef.cc
@@ -1,11 +1,11 @@
#include "IPL4asp_PortType.hh"
+#include "OPCAP_CodecPort.hh"
#include "IPL4asp_PT.hh"
-#include "GTP_CodecPort.hh"
-namespace GTP__CodecPort__CtrlFunct {
+namespace OPCAP__CodecPort__CtrlFunct {
IPL4asp__Types::Result f__IPL4__listen(
- GTP__CodecPort::GTPC__PT& portRef,
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
const IPL4asp__Types::HostName& locName,
const IPL4asp__Types::PortNumber& locPort,
const IPL4asp__Types::ProtoTuple& proto,
@@ -15,7 +15,7 @@ namespace GTP__CodecPort__CtrlFunct {
}
IPL4asp__Types::Result f__IPL4__connect(
- GTP__CodecPort::GTPC__PT& portRef,
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
const IPL4asp__Types::HostName& remName,
const IPL4asp__Types::PortNumber& remPort,
const IPL4asp__Types::HostName& locName,
@@ -29,7 +29,7 @@ namespace GTP__CodecPort__CtrlFunct {
}
IPL4asp__Types::Result f__IPL4__close(
- GTP__CodecPort::GTPC__PT& portRef,
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
const IPL4asp__Types::ConnectionId& connId,
const IPL4asp__Types::ProtoTuple& proto)
{
@@ -37,7 +37,7 @@ namespace GTP__CodecPort__CtrlFunct {
}
IPL4asp__Types::Result f__IPL4__setUserData(
- GTP__CodecPort::GTPC__PT& portRef,
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
const IPL4asp__Types::ConnectionId& connId,
const IPL4asp__Types::UserData& userData)
{
@@ -45,22 +45,22 @@ namespace GTP__CodecPort__CtrlFunct {
}
IPL4asp__Types::Result f__IPL4__getUserData(
- GTP__CodecPort::GTPC__PT& portRef,
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
const IPL4asp__Types::ConnectionId& connId,
IPL4asp__Types::UserData& userData)
{
return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
}
-
- IPL4asp__Types::Result f__GTPU__listen(
- GTP__CodecPort::GTPU__PT& portRef,
- const IPL4asp__Types::HostName& locName,
- const IPL4asp__Types::PortNumber& locPort,
- const IPL4asp__Types::ProtoTuple& proto,
- const IPL4asp__Types::OptionList& options)
+ void f__IPL4__setGetMsgLen(
+ OPCAP__CodecPort::OPCAP__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ Socket__API__Definitions::f__getMsgLen& f,
+ const Socket__API__Definitions::ro__integer& msgLenArgs)
{
- return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ return f__IPL4__PROVIDER__setGetMsgLen(portRef, connId, f, msgLenArgs);
}
+
}
+
diff --git a/library/OPCAP_Templates.ttcn b/library/OPCAP_Templates.ttcn
new file mode 100644
index 00000000..0a1c884f
--- /dev/null
+++ b/library/OPCAP_Templates.ttcn
@@ -0,0 +1,54 @@
+module OPCAP_Templates {
+
+/* OPCAP_Templates, defining TTCN-3 templates for the osmo-pcap protocol.
+ *
+ * OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
+ *
+ * (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from OPCAP_Types all;
+
+
+template (present) OPCAP_PDU tr_OPCAP_FILE_HDR(template (present) uint32_t linktype := ?) := {
+ msg_type := PKT_LINK_HDR,
+ spare := ?,
+ len := 24,
+ u := {
+ file := {
+ magic := PCAP_MAGIC,
+ version_major := PCAP_VERSION_MAJOR,
+ version_minor := PCAP_VERSION_MINOR,
+ thiszone := 0,
+ sigfigs := 0,
+ snaplen := 9000,
+ linktype := linktype
+ }
+ }
+}
+
+template (present) OPCAP_PDU tr_OPCAP_PKT(template (present) octetstring payload,
+ template (present) uint32_t caplen := ?,
+ template (present) uint32_t len := ?) := {
+ msg_type := PKT_LINK_DATA,
+ spare := ?,
+ len := ?,
+ u := {
+ packet := {
+ ts_sec := ?,
+ ts_usec := ?,
+ caplen := caplen,
+ len := len,
+ payload := payload
+ }
+ }
+}
+
+
+};
diff --git a/library/OPCAP_Types.ttcn b/library/OPCAP_Types.ttcn
new file mode 100644
index 00000000..d244fefd
--- /dev/null
+++ b/library/OPCAP_Types.ttcn
@@ -0,0 +1,78 @@
+module OPCAP_Types {
+
+/* OPCAP_Types, defining abstract TTCN-3 data types for the osmo-pcap protocol.
+ *
+ * OPCAP is a non-standard protocol used between osmo-pcap-client and osmo-pcap-server.
+ *
+ * (C) 2021 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+type enumerated OpcapMsgType {
+ PKT_LINK_HDR (0),
+ PKT_LINK_DATA (1)
+} with { variant "FIELDLENGTH(8)" };
+
+type record OPCAP_PDU {
+ OpcapMsgType msg_type,
+ uint8_t spare,
+ uint16_t len,
+ OpcapBodyUnion u
+} with {
+ variant (len) "LENGTHTO(u)"
+ variant (len) "BYTEORDER(last)"
+ variant (u) "CROSSTAG(
+ file, msg_type = PKT_LINK_HDR;
+ packet, msg_type = PKT_LINK_DATA;
+ )"
+};
+
+type union OpcapBodyUnion {
+ PcapFileHeader file,
+ OpcapPacket packet
+};
+
+/* header in front of a PKT_LINK_DATA */
+type record OpcapPacket {
+ uint32_t ts_sec,
+ uint32_t ts_usec,
+ uint32_t caplen,
+ uint32_t len,
+ octetstring payload
+} with {
+ variant (caplen) "LENGTHTO(payload)"
+};
+
+/* below definitions are from pcap/pcap.h */
+const uint16_t PCAP_VERSION_MAJOR := 2;
+const uint16_t PCAP_VERSION_MINOR := 4;
+const uint32_t PCAP_MAGIC := 2712847316; //0xA1B2C3D4;
+
+type record PcapFileHeader {
+ uint32_t magic,
+ uint16_t version_major,
+ uint16_t version_minor,
+ uint32_t thiszone,
+ uint32_t sigfigs,
+ uint32_t snaplen,
+ uint32_t linktype
+};
+
+/* below definitions are from pcap/dlt.h */
+const uint32_t DLT_LINUX_SLL := 113;
+const uint32_t DLT_EN10MB := 1;
+
+
+external function enc_OPCAP_PDU(in OPCAP_PDU msg) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+
+external function dec_OPCAP_PDU(in octetstring msg) return OPCAP_PDU
+ with { extension "prototype(convert) decode(RAW)" };
+
+} with { encode "RAW"; variant "FIELDORDER(msb)"; variant "BYTEORDER(first)" };
diff --git a/library/OSMUX_Emulation.ttcn b/library/OSMUX_Emulation.ttcn
index e1275b9e..4538fdff 100644
--- a/library/OSMUX_Emulation.ttcn
+++ b/library/OSMUX_Emulation.ttcn
@@ -54,6 +54,8 @@ module OSMUX_Emulation {
import from General_Types all;
import from Osmocom_Types all;
import from IPL4asp_Types all;
+import from Misc_Helpers all;
+import from AMR_Types all;
import from OSMUX_Types all;
import from OSMUX_CodecPort all;
import from OSMUX_CodecPort_CtrlFunct all;
@@ -65,6 +67,8 @@ type component OSMUX_Emulation_CT {
/* user-facing port for controlling the binding */
port OsmuxEM_CTRL_PT CTRL;
+ /* user-facing port for sniffing Osmux frames */
+ port OsmuxEM_DATA_PT DATA;
/* configurable by user, should be fixed */
var OsmuxemConfig g_cfg := c_OsmuxemDefaultCfg;
@@ -188,6 +192,10 @@ type port OsmuxEM_CTRL_PT procedure {
OsmuxEM_stats_get, OsmuxEM_register_rxhandle, OsmuxEM_register_txhandle;
} with { extension "internal" };
+type port OsmuxEM_DATA_PT message {
+ inout OSMUX_PDU;
+} with { extension "internal" };
+
function f_osmuxem_bind(OsmuxEM_CTRL_PT pt, in HostName local_host, inout PortNumber local_port) {
pt.call(OsmuxEM_bind:{local_host, local_port}) {
[] pt.getreply(OsmuxEM_bind:{local_host, ?}) -> param (local_port) {};
@@ -289,26 +297,26 @@ function f_osmuxem_stats_err_check(OsmuxemStats s) {
/* Check if there was some activity at either on the RX or on the
* TX side, but complete silence would indicate some problem */
if (s.num_pkts_tx < 1 and s.num_pkts_rx < 1) {
- setverdict(fail, "no Osmux packet activity detected (packets)");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "no Osmux packet activity detected (packets)");
}
if (s.bytes_payload_tx < 1 and s.bytes_payload_rx < 1) {
- setverdict(fail, "no Osmux packet activity detected (bytes)");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "no Osmux packet activity detected (bytes)");
}
/* Check error counters */
if (s.num_pkts_rx_err_seq != 0) {
- setverdict(fail, "Osmux packet sequence number errors occurred");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Osmux packet sequence number errors occurred");
}
if (s.num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "Osmux packets received while RX was disabled");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Osmux packets received while RX was disabled");
}
if (s.num_pkts_rx_err_payload != 0) {
- setverdict(fail, "Osmux packets with mismatching payload received");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Osmux packets with mismatching payload received");
}
}
@@ -336,8 +344,9 @@ private function f_rxhandle_get_by_cid(OsmuxCID cid) runs on OSMUX_Emulation_CT
return RxHandleTable[i].vc_conn;
}
}
- setverdict(fail, "No Component for CID ", cid);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No Component for CID ", cid));
+ return RxHandleTable[0].vc_conn; /* make compiler happy, not reached */
}
private function f_rxhandle_cid_add(OsmuxRxHandle hdl) runs on OSMUX_Emulation_CT {
@@ -349,8 +358,8 @@ private function f_rxhandle_cid_add(OsmuxRxHandle hdl) runs on OSMUX_Emulation_C
return;
}
}
- testcase.stop("No Space in RxHandleTable for ", hdl.cid);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No Space in RxHandleTable for ", hdl.cid));
}
private function f_txhandle_cid_add(OsmuxTxHandle hdl) runs on OSMUX_Emulation_CT {
@@ -361,16 +370,24 @@ private function f_txhandle_cid_add(OsmuxTxHandle hdl) runs on OSMUX_Emulation_C
return;
}
}
- testcase.stop("No Space in TxHandleList for ", hdl.cid);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No Space in TxHandleList for ", hdl.cid));
}
+/* Generate correctly-sized AMR payload based on amr_ft, using tx_fixed_payload as a fill pattern. */
function f_osmux_gen_expected_rx_rtp_payload(INT4b amr_ft, octetstring tx_fixed_payload) return octetstring {
+ var integer payload_len_bits;
var integer payload_len;
+ var bitstring payload_truncated_bits;
var octetstring payload_truncated;
- var integer i;
+
+ /* Generate the AMR payload as a bitstring, since some formats don't end up in octet boundary: */
+ payload_len_bits := f_amrft_payload_bits_len(amr_ft);
+ payload_truncated_bits := substr(oct2bit(tx_fixed_payload), 0, payload_len_bits);
+
+ /* Now convert it as an octet string filling final padding with zeroes: */
payload_len := f_amrft_payload_len(amr_ft);
- payload_truncated := substr(tx_fixed_payload, 0, payload_len);
+ payload_truncated := bit2oct(f_pad_bit(payload_truncated_bits, payload_len*8, '0'B));
return payload_truncated;
}
@@ -420,7 +437,7 @@ function f_main() runs on OSMUX_Emulation_CT
var OsmuxRxHandle rx_hdl;
var OsmuxTxHandle tx_hdl;
var octetstring payload_truncated;
-
+ var PortEvent port_event;
timer T_transmit := int2float(g_cfg.tx_duration_ms)/1000.0;
var Osmux_RecvFrom rx_osmux;
var PDU_Osmux_AMR rx_amr;
@@ -451,11 +468,16 @@ function f_main() runs on OSMUX_Emulation_CT
[] CTRL.getcall(OsmuxEM_bind:{?,?}) -> param(g_local_host, g_local_port) {
g_tx_connected := false; /* will set it back to true upon next connect() call */
+
+ if (g_osmux_conn_id != -1) {
+ res := OSMUX_CodecPort_CtrlFunct.f_IPL4_close(OSMUX, g_osmux_conn_id, {udp := {}});
+ g_osmux_conn_id := -1;
+ }
res := OSMUX_CodecPort_CtrlFunct.f_IPL4_listen(OSMUX, g_local_host,
g_local_port, {udp:={}});
if (not ispresent(res.connId)) {
- setverdict(fail, "Could not listen on Osmux socket, check your configuration");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Could not listen on Osmux socket, check your configuration");
}
g_osmux_conn_id := res.connId;
tr_osmux_amr.connId := g_osmux_conn_id;
@@ -469,8 +491,8 @@ function f_main() runs on OSMUX_Emulation_CT
g_local_host, g_local_port,
g_osmux_conn_id, {udp:={}});
if (not ispresent(res.connId)) {
- setverdict(fail, "Could not connect to Osmux socket, check your configuration");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Could not connect to Osmux socket, check your configuration");
}
g_tx_connected := true;
CTRL.reply(OsmuxEM_connect:{g_remote_host, g_remote_port});
@@ -548,6 +570,9 @@ function f_main() runs on OSMUX_Emulation_CT
if (ispresent(g_cfg.rx_fixed_payload) and rx_osmux.msg.osmux_amr.data != payload_truncated) {
g_stat.num_pkts_rx_err_payload := g_stat.num_pkts_rx_err_payload + 1;
}
+ if (DATA.checkstate("Connected")) {
+ DATA.send(rx_osmux.msg);
+ }
}
/* process received Osmux Dummy if receiver enabled */
[g_rx_enabled] OSMUX.receive(tr_osmux_dummy) -> value rx_osmux {
@@ -562,10 +587,15 @@ function f_main() runs on OSMUX_Emulation_CT
T_transmit.start;
}
+ [] OSMUX.receive(PortEvent:?) -> value port_event {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected port event from Osmux:", port_event));
+ }
+
/* fail on any unexpected messages */
[] OSMUX.receive {
- setverdict(fail, "Received unexpected type from Osmux");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Received unexpected msg type from Osmux");
}
}
}
diff --git a/library/OSMUX_Types.ttcn b/library/OSMUX_Types.ttcn
index 091b4d70..bc592b79 100644
--- a/library/OSMUX_Types.ttcn
+++ b/library/OSMUX_Types.ttcn
@@ -11,6 +11,9 @@
module OSMUX_Types {
import from General_Types all;
+import from Misc_Helpers all;
+
+import from AMR_Types all;
external function enc_OSMUX_PDU ( in OSMUX_PDU msg ) return octetstring
with { extension "prototype(convert) encode(RAW)" };
@@ -83,28 +86,44 @@ type union OSMUX_PDU {
)"
};
+template (present) OSMUX_PDU tr_PDU_Osmux_AMR(template (present) BIT1 marker := ?,
+ template (present) INT3b ctr := ?,
+ template (present) BIT1 amr_f := ?,
+ template (present) BIT1 amr_q := ?,
+ template (present) INT1 seq := ?,
+ template (present) OsmuxCID cid := ?,
+ template (present) INT4b amr_ft := ?,
+ template (present) INT4b amr_cmr := ?,
+ template (present) octetstring payload := ?) := {
+ osmux_amr := {
+ header := {
+ marker := marker,
+ ft := 1,
+ ctr := ctr,
+ amr_f := amr_f,
+ amr_q := amr_q,
+ seq := seq,
+ cid := cid,
+ amr_ft := amr_ft,
+ amr_cmr := amr_cmr
+ },
+ data := payload
+ }
+}
-/* AMR voice frame type identifiers
- * See also 3GPP TS 26.101, Table 1a: Interpretation of Frame Type, Mode
- * Indication and Mode Request fields */
-type enumerated AMRFT {
- AMR_FT_0, /* 4.75 */
- AMR_FT_1, /* 5.15 */
- AMR_FT_2, /* 5.90 */
- AMR_FT_3, /* 6.70 */
- AMR_FT_4, /* 7.40 */
- AMR_FT_5, /* 7.95 */
- AMR_FT_6, /* 10.2 */
- AMR_FT_7, /* 12.2 */
- AMR_FT_SID /* SID */
-};
-
-/* AMR voice frame length (in bytes, rounded),
- * See also RFC 3267, chapter 3.6 */
-const integer c_AMRFT_len[9] := {12, 13, 15, 17, 19, 20, 26, 31, 5};
-
-function f_amrft_payload_len(INT4b amr_ft) return integer {
- return c_AMRFT_len[amr_ft];
+/* Get Nth AMR payload of osmux AMR frame (starting from 0) */
+function f_osmux_amr_get_nth_amr_payload(PDU_Osmux_AMR osmux_amr, integer nth) return octetstring
+{
+ var integer amr_pl_len := f_amrft_payload_len(osmux_amr.header.amr_ft);
+ if (nth > osmux_amr.header.ctr) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "nth > ctr");
+ return ''O;
+ }
+ if (amr_pl_len * (nth+1) > lengthof(osmux_amr.data)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "osmux payload too short");
+ }
+ var octetstring pl := substr(osmux_amr.data, amr_pl_len * nth, amr_pl_len);
+ return pl;
}
} with { encode "RAW"}
diff --git a/library/Osmocom_CTRL_Adapter.ttcn b/library/Osmocom_CTRL_Adapter.ttcn
index 0be3ebbf..6a9706eb 100644
--- a/library/Osmocom_CTRL_Adapter.ttcn
+++ b/library/Osmocom_CTRL_Adapter.ttcn
@@ -22,16 +22,49 @@ import from Osmocom_CTRL_Types all;
type component CTRL_Adapter_CT {
var IPA_Emulation_CT vc_CTRL_IPA;
+ var boolean ipa_is_up := false;
/* test port for the CTRL interface of the BSC */
port IPA_CTRL_PT IPA_CTRL;
}
+/* wait for IPA CTRL link to connect and send UP */
+function f_ipa_ctrl_wait_link_up()
+runs on CTRL_Adapter_CT {
+ if (ipa_is_up == true) {
+ return;
+ }
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] IPA_CTRL.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { ipa_is_up := true; }
+ [] T.timeout {
+ setverdict(fail, "Timeout CTRL waiting for ASP_IPA_EVENT_UP");
+ mtc.stop;
+ }
+ }
+}
-/*! Start the CTRL connection to the specified BSC IP+Port */
-function f_ipa_ctrl_start(charstring bsc_host, PortNumber bsc_port)
+/* wait for IPA CTRL link to connect and send DOWN */
+function f_ipa_ctrl_wait_link_down()
runs on CTRL_Adapter_CT {
- var charstring id := "IPA-CTRL"
+ if (ipa_is_up == false) {
+ return;
+ }
timer T := 10.0;
+ T.start;
+ alt {
+ [] IPA_CTRL.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) { ipa_is_up := false; }
+ [] T.timeout {
+ setverdict(fail, "Timeout CTRL waiting for ASP_IPA_EVENT_DOWN");
+ mtc.stop;
+ }
+ }
+}
+
+/*! Start the CTRL client connection to the specified CTRL IP+Port server*/
+function f_ipa_ctrl_start_client(charstring bsc_host, PortNumber bsc_port)
+runs on CTRL_Adapter_CT {
+ var charstring id := "IPA-CTRL-CLI"
vc_CTRL_IPA := IPA_Emulation_CT.create(id & "-IPA");
@@ -41,15 +74,22 @@ runs on CTRL_Adapter_CT {
vc_CTRL_IPA.start(IPA_Emulation.main_client(bsc_host, bsc_port, "", 0,
c_IPA_default_ccm_pars, false));
- /* wait for IPA CTRL link to connect and send UP */
- T.start;
- alt {
- [] IPA_CTRL.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { }
- [] T.timeout {
- setverdict(fail, "Timeout CTRL waiting for ASP_IPA_EVENT_UP");
- mtc.stop;
- }
- }
+ f_ipa_ctrl_wait_link_up();
+}
+
+/*! Start the CTRL server on the specified CTRL IP+Port */
+function f_ipa_ctrl_start_server(charstring listen_host, PortNumber listen_port)
+runs on CTRL_Adapter_CT {
+ var charstring id := "IPA-CTRL-SRV"
+ timer T := 10.0;
+
+ vc_CTRL_IPA := IPA_Emulation_CT.create(id & "-IPA");
+
+ map(vc_CTRL_IPA:IPA_PORT, system:IPA_CODEC_PT);
+ connect(vc_CTRL_IPA:IPA_CTRL_PORT, self:IPA_CTRL);
+
+ vc_CTRL_IPA.start(IPA_Emulation.main_server(listen_host, listen_port, false,
+ server_stop_on_ipa_ev_down := false));
}
function f_ipa_ctrl_stop() runs on CTRL_Adapter_CT {
@@ -79,5 +119,22 @@ function f_ctrl_get_exp_trx(IPA_CTRL_PT pt, integer bts_nr, integer trx_nr, Ctrl
f_ctrl_get_exp(pt, valueof(ts_bts_trx(bts_nr, trx_nr)) & suffix, exp);
}
+template (value) charstring ts_fsm_inst_id(charstring class_name, charstring inst_id) :=
+ "fsm." & class_name & ".id." & inst_id & ".";
+
+/* obtain the state of a specified FSM instance */
+function f_ctrl_get_fsm_inst_state(IPA_CTRL_PT pt, charstring fsm_class_name, charstring fsm_inst_id)
+return charstring {
+ return f_ctrl_get(pt, valueof(ts_fsm_inst_id(fsm_class_name, fsm_inst_id)) & "state");
+}
+
+/* expect the state of a specified FSM instance to match template */
+function f_ctrl_get_exp_inst_state(IPA_CTRL_PT pt, charstring fsm_class_name,
+ template (value) charstring fsm_inst_id,
+ template (present) CtrlValue exp)
+{
+ f_ctrl_get_exp(pt, valueof(ts_fsm_inst_id(fsm_class_name, valueof(fsm_inst_id))) & "state", exp);
+}
+
}
diff --git a/library/Osmocom_CTRL_Functions.ttcn b/library/Osmocom_CTRL_Functions.ttcn
index 60c66c0e..75f86469 100644
--- a/library/Osmocom_CTRL_Functions.ttcn
+++ b/library/Osmocom_CTRL_Functions.ttcn
@@ -23,6 +23,8 @@ module Osmocom_CTRL_Functions {
import from Osmocom_CTRL_Types all;
import from IPA_Emulation all;
+ type record of charstring charstring_list;
+
private function f_gen_rand_id() return CtrlId {
return int2str(float2int(rnd()*999999999.0));
}
@@ -61,7 +63,7 @@ module Osmocom_CTRL_Functions {
[] pt.receive(tr_CtrlMsgSetRepl(id, variable, val)) { }
[] pt.receive(tr_CtrlMsgTrap) { repeat; }
[] pt.receive(tr_CtrlMsgError) -> value rx {
- setverdict(fail, "Error in CTRL GET ", variable, ": ", rx.err.reason);
+ setverdict(fail, "Error in CTRL SET ", variable, ": ", rx.err.reason);
mtc.stop;
}
[] T.timeout {
@@ -117,6 +119,26 @@ module Osmocom_CTRL_Functions {
return rx.cmd.val;
}
+ /* Expect a matching SET, optionally answer */
+ function f_ctrl_exp_get(IPA_CTRL_PT pt, template CtrlVariable variable,
+ template (omit) CtrlValue rsp := omit,
+ float timeout_val := 2.0) {
+ timer T := timeout_val;
+ var CtrlMessage rx;
+ T.start;
+ alt {
+ [] pt.receive(tr_CtrlMsgGet(?, variable)) -> value rx {
+ if (ispresent(rsp)) {
+ pt.send(ts_CtrlMsgGetRepl(rx.cmd.id, valueof(variable), valueof(rsp)));
+ }
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for GET ", variable);
+ mtc.stop;
+ }
+ }
+ }
+
/* Expect a matching GET result */
function f_ctrl_get_exp(IPA_CTRL_PT pt, CtrlVariable variable, template CtrlValue exp) {
var charstring ctrl_resp;
@@ -166,14 +188,14 @@ module Osmocom_CTRL_Functions {
*
* // run some tests that increment rate counters in the program,
* // and increment expected counters accordingly:
- * my_counters := f_counter_name_vals_list_add(my_counters, instance_nr := 1, "mscpool:subscr:new", 7);
- * my_counters := f_counter_name_vals_list_add(my_counters, instance_nr := 2, "mscpool:subscr:attach_lost", 3);
+ * f_counter_name_vals_list_add(my_counters, instance_nr := 1, "mscpool:subscr:new", 7);
+ * f_counter_name_vals_list_add(my_counters, instance_nr := 2, "mscpool:subscr:attach_lost", 3);
*
* // verify that the program reflects the expected counters:
* f_counter_name_vals_expect_n(instance_name := "msc", my_counters);
*
* // run some more tests...
- * my_counters := f_counter_name_vals_list_add(my_counters, instance_nr := 0, "mscpool:subscr:known");
+ * f_counter_name_vals_list_add(my_counters, instance_nr := 0, "mscpool:subscr:known");
* // and verify again
* f_counter_name_vals_expect_n(instance_name := "msc", my_counters);
*/
@@ -211,10 +233,11 @@ module Osmocom_CTRL_Functions {
/* Retrieve the first N instances' rate counter values of the given names */
function f_counter_name_vals_get_n(IPA_CTRL_PT pt, charstring instance_name := "msc",
- integer instance_count, CounterNameVals counternames)
+ integer instance_count, CounterNameVals counternames,
+ integer start_idx := 0)
return CounterNameValsList {
var CounterNameValsList valslist;
- for (var integer instance_nr := 0; instance_nr < instance_count; instance_nr := instance_nr + 1) {
+ for (var integer instance_nr := start_idx; instance_nr < start_idx + instance_count; instance_nr := instance_nr + 1) {
valslist[instance_nr] := f_counter_name_vals_get(pt, instance_name, instance_nr, counternames);
}
log("retrieved rate counters: ", instance_name, ": ", valslist);
@@ -248,14 +271,14 @@ module Osmocom_CTRL_Functions {
* Set the test verdict accordingly. */
function f_counter_name_vals_expect(IPA_CTRL_PT pt, charstring instance_name, integer instance_nr,
CounterNameVals vals) {
- var CounterNameVals now := f_counter_name_vals_get(pt, instance_name, instance_nr, vals);
+ var CounterNameVals last := f_counter_name_vals_get(pt, instance_name, instance_nr, vals);
for (var integer i := 0; i < lengthof(vals); i := i + 1) {
- if (now[i].name != vals[i].name) {
+ if (last[i].name != vals[i].name) {
setverdict(fail, "Internal error");
}
- if (now[i].val != vals[i].val) {
+ if (last[i].val != vals[i].val) {
setverdict(fail, "Rate counter mismatch: ", instance_name, " ", instance_nr,
- " ", vals[i].name, " is at ", now[i].val, " but expected ", vals[i].val);
+ " ", vals[i].name, " is at ", last[i].val, " but expected ", vals[i].val);
}
}
setverdict(pass);
@@ -269,4 +292,81 @@ module Osmocom_CTRL_Functions {
}
}
+ /* For a specific instance, call f_counter_name_vals_get() and indentify counters that have changed with respect
+ * to 'vals'. Return list of the changed counter names in the order they appear in 'vals'. */
+ function f_counter_name_vals_get_changed(IPA_CTRL_PT pt, charstring instance_name, integer instance_nr,
+ CounterNameVals vals)
+ return charstring_list {
+ var charstring_list changed := {};
+ var CounterNameVals last := f_counter_name_vals_get(pt, instance_name, instance_nr, vals);
+ for (var integer i := 0; i < lengthof(vals); i := i + 1) {
+ if (last[i].name != vals[i].name) {
+ setverdict(fail, "Internal error");
+ }
+ if (last[i].val != vals[i].val) {
+ changed := changed & { instance_name & "." & int2str(instance_nr) & "." & vals[i].name };
+ }
+ }
+ return changed;
+ }
+
+ /* For N instances, call f_counter_name_vals_get() and indentify counters that have changed with respect
+ * to 'vals'. Return list of the changed counter names in the order they appear in 'vals'. */
+ function f_counter_name_vals_get_changed_n(IPA_CTRL_PT pt, charstring instance_name, CounterNameValsList valslist)
+ return charstring_list {
+ var charstring_list changed := {};
+ for (var integer instance_nr := 0; instance_nr < lengthof(valslist); instance_nr := instance_nr + 1) {
+ changed := changed & f_counter_name_vals_get_changed(pt, instance_name, instance_nr, valslist[instance_nr]);
+ }
+ return changed;
+ }
+
+ function f_counter_name_vals_expect_changed(IPA_CTRL_PT pt, charstring instance_name, CounterNameValsList valslist,
+ charstring_list expect_changed) {
+ var charstring_list changed := f_counter_name_vals_get_changed_n(pt, instance_name, valslist);
+ f_counter_name_vals_expect_changed_list(changed, expect_changed);
+ }
+
+ function f_counter_name_vals_expect_changed_list(charstring_list got_list, charstring_list expect_list) {
+ var charstring unexpected_change := "";
+ for (var integer i := 0; i < lengthof(got_list); i := i + 1) {
+ var boolean found := false;
+ for (var integer j := 0; j < lengthof(expect_list); j := j + 1) {
+ if (got_list[i] == expect_list[j]) {
+ found := true;
+ break;
+ }
+ }
+ if (not found) {
+ unexpected_change := unexpected_change & " " & got_list[i];
+ }
+ }
+ var charstring missing_change := "";
+ for (var integer i := 0; i < lengthof(expect_list); i := i + 1) {
+ var boolean found := false;
+ for (var integer j := 0; j < lengthof(got_list); j := j + 1) {
+ if (expect_list[i] == got_list[j]) {
+ found := true;
+ break;
+ }
+ }
+ if (not found) {
+ missing_change := missing_change & " " & expect_list[i];
+ }
+ }
+ var charstring diff := "";
+ if (lengthof(unexpected_change) > 0) {
+ diff := diff & " Unexpected changes in" & unexpected_change & ";";
+ }
+ if (lengthof(missing_change) > 0) {
+ diff := diff & " Missing changes in" & missing_change & ";";
+ }
+ if (lengthof(diff) > 0) {
+ log("ERROR\nExpected: ", expect_list, "\nGot: ", got_list);
+ setverdict(fail, "Rate counters did not change as expected:" & diff);
+ } else {
+ setverdict(pass);
+ }
+ }
+
}
diff --git a/library/Osmocom_CTRL_Types.ttcn b/library/Osmocom_CTRL_Types.ttcn
index 52be9566..36e67622 100644
--- a/library/Osmocom_CTRL_Types.ttcn
+++ b/library/Osmocom_CTRL_Types.ttcn
@@ -124,7 +124,7 @@ template CtrlMessage tr_CtrlMsgGet(template CtrlId id, template CtrlVariable var
verb := "GET",
id := id,
variable := variable,
- val := ?
+ val := omit
}
}
diff --git a/library/Osmocom_Gb_Types.ttcn b/library/Osmocom_Gb_Types.ttcn
index a5182686..42866ff3 100644
--- a/library/Osmocom_Gb_Types.ttcn
+++ b/library/Osmocom_Gb_Types.ttcn
@@ -5,8 +5,8 @@ module Osmocom_Gb_Types {
import from General_Types all;
import from Osmocom_Types all;
+ import from Misc_Helpers all;
import from GSM_Types all;
- import from GSM_RR_Types all;
import from BSSGP_Types all
import from NS_Types all
import from Native_Functions all;
@@ -15,6 +15,16 @@ module Osmocom_Gb_Types {
type uint16_t Nsei;
type uint16_t BssgpBvci;
+ template (present) BssgpBvci t_BssgpBvciUser := complement (0);
+
+ type enumerated OsmoNsDialect {
+ NS2_DIALECT_UNDEF ('00'H),
+ NS2_DIALECT_STATIC_ALIVE ('01'H),
+ NS2_DIALECT_STATIC_RESETBLOCK ('02'H),
+ NS2_DIALECT_IPACCESS ('03'H),
+ NS2_DIALECT_SNS ('04'H)
+ };
+
/* TS 48.016 10.3.7 */
type enumerated NsPduType {
NS_PDUT_NS_UNITDATA ('00000000'B),
@@ -56,7 +66,7 @@ module Osmocom_Gb_Types {
NS_CAUSE_BVCI_UNKNOWN_AT_NSE ('00000101'B),
NS_CAUSE_SEMANTICALLY_INCORRECT_PDU ('00001000'B),
NS_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE ('00001010'B),
- NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED ('00001011'B),
+ NS_CAUSE_PROTOCOL_ERROR_UNSPECIFIED ('00001011'B),
NS_CAUSE_INVALID_ESSENTIAL_IE ('00001100'B),
NS_CAUSE_MISSING_ESSENTIAL_IE ('00001101'B),
NS_CAUSE_INVALID_NR_OF_IPv4_ENDPOINTS ('00001110'B),
@@ -162,6 +172,17 @@ module Osmocom_Gb_Types {
return int2oct(valueof(inp), len);
}
+ private function f_hex_or_wc(template integer inp, integer len) return template hexstring {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ }
+ return int2hex(valueof(inp), len);
+ }
+
template (value) NS_VCI ts_NS_IE_NSVCI(Nsvci nsvci) := {
iEI := '01'O,
ext := '1'B,
@@ -230,6 +251,40 @@ module Osmocom_Gb_Types {
return e;
}
+ template (value) IP6_Element ts_SNS_IPv6(charstring ip, integer udp_port,
+ uint8_t sig_weight := 1, uint8_t data_weight := 1) := {
+ ipAddress := f_inet6_addr(ip),
+ uDP_Port := int2oct(udp_port, 2),
+ signallingWeight := int2oct(sig_weight, 1),
+ dataWeight := int2oct(data_weight, 1)
+ }
+ function tr_SNS_IPv6(template charstring ip, template integer udp_port,
+ template uint8_t sig_weight := ?, template uint8_t data_weight := ?)
+ return template IP6_Element {
+ var template IP6_Element e;
+ if (istemplatekind(ip, "?")) {
+ e.ipAddress := ?;
+ } else {
+ e.ipAddress := f_inet6_addr(valueof(ip));
+ }
+ if (istemplatekind(udp_port, "?")) {
+ e.uDP_Port := ?;
+ } else {
+ e.uDP_Port := int2oct(valueof(udp_port), 2);
+ }
+ if (istemplatekind(sig_weight, "?")) {
+ e.signallingWeight := ?;
+ } else {
+ e.signallingWeight := int2oct(valueof(sig_weight), 1);
+ }
+ if (istemplatekind(data_weight, "?")) {
+ e.dataWeight := ?;
+ } else {
+ e.dataWeight := int2oct(valueof(data_weight), 1);
+ }
+ return e;
+ }
+
template (value) PDU_NS ts_NS_RESET(NsCause cause, Nsvci nsvci, Nsei nsei) := {
pDU_NS_Reset := {
@@ -334,6 +389,18 @@ module Osmocom_Gb_Types {
}
}
+ template PDU_NS tr_NS_STATUS(template NsCause cause) := {
+ pDU_NS_Status := {
+ nsPduType := '08'O,
+ causeNS := tr_NS_IE_CAUSE(cause),
+ nS_VCI := *,
+ nS_PDU := *,
+ bVCI_NS := *,
+ listofIP4Elements := *,
+ listofIP6Elements := *
+ }
+ }
+
template (value) PDU_NS ts_NS_UNITDATA(template (value) NS_SDU_ControlBits bits, BssgpBvci bvci, octetstring sdu) := {
pDU_NS_Unitdata := {
nsPduType := '00'O,
@@ -351,6 +418,14 @@ octetstring sdu) := {
nS_SDU := sdu
}
}
+ template PDU_NS tr_NS_UNITDATA_User(template NS_SDU_ControlBits bits, template octetstring sdu) := {
+ pDU_NS_Unitdata := {
+ nsPduType := '00'O,
+ nS_SDU_ControlBits := bits,
+ bVCI := complement ('0000'O),
+ nS_SDU := sdu
+ }
+ }
@@ -475,6 +550,10 @@ octetstring sdu) := {
var template ListofIP4Elements r;
if (istemplatekind(elem, "omit")) {
return omit;
+ } else if (istemplatekind(elem, "*")) {
+ return *;
+ } else if (istemplatekind(elem, "?")) {
+ return ?;
} else {
r := {
iEI := '05'O,
@@ -512,6 +591,8 @@ octetstring sdu) := {
return omit;
} else if (istemplatekind(elem, "*")) {
return *;
+ } else if (istemplatekind(elem, "?")) {
+ return ?;
} else {
r := {
iEI := '06'O,
@@ -526,7 +607,7 @@ octetstring sdu) := {
}
template (value) PDU_NS ts_SNS_CONFIG(Nsei nsei, boolean end_flag,
- template (omit) IP4_Elements v4,
+ template (omit) IP4_Elements v4 := omit,
template (omit) IP6_Elements v6 := omit) := {
pDU_SNS_Config := {
nsPduType := '0F'O,
@@ -537,7 +618,7 @@ octetstring sdu) := {
}
}
template PDU_NS tr_SNS_CONFIG(template Nsei nsei, template boolean end_flag,
- template IP4_Elements v4,
+ template IP4_Elements v4 := omit,
template IP6_Elements v6 := omit) := {
pDU_SNS_Config := {
nsPduType := '0F'O,
@@ -666,6 +747,14 @@ octetstring sdu) := {
}
}
+ template PDU_NS tr_SNS(template Nsei nsei) := ( tr_SNS_SIZE(nsei),
+ tr_SNS_SIZE_ACK(nsei, *),
+ tr_SNS_CONFIG(nsei, ?, *, *),
+ tr_SNS_CONFIG_ACK(nsei, *),
+ tr_SNS_ADD(nsei, ?, *, *),
+ tr_SNS_DEL(nsei, ?, *, *),
+ tr_SNS_CHG_WEIGHT(nsei, ?, *, *),
+ tr_SNS_ACK(nsei, ?, *, *, *) )
@@ -677,6 +766,11 @@ octetstring sdu) := {
CellIdentity cell_id
} with { variant "" };
+ template (value) BssgpCellId ts_BssgpCellId(template (value) RoutingAreaIdentification rai, CellIdentity cell_id) := {
+ ra_id := rai,
+ cell_id := cell_id
+ };
+
type enumerated BssgpCause {
BSSGP_CAUSE_PROC_OVERLOAD ('00'H),
BSSGP_CAUSE_EQUIMENT_FAILURE ('01'H),
@@ -722,14 +816,161 @@ octetstring sdu) := {
BSSGP_CAUSE_NOT_ALL_REQUESTED_PFC_CREATED ('3c'H)
} with { variant "FIELDLENGTH(8)" };
+ private function tr_FLUSH_ACTION(template OCT1 act)
+ return template Flush_Action {
+ var template Flush_Action r;
+ if (istemplatekind(act, "omit")) {
+ return omit;
+ } else if (istemplatekind(act, "*")) {
+ return *;
+ } else {
+ r := {
+ iEI := '0C'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ actionValue := act
+ }
+ return r;
+ }
+ }
+ template (value) Flush_Action ts_FLUSH_ACTION(template (value) OCT1 act) := {
+ iEI := '0C'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ actionValue := act
+ }
- template BVCI t_BSSGP_BVCI(template BssgpBvci bvci) := {
+ private function tr_NO_OCT_AFF(template integer oct_aff)
+ return template Number_of_octets_affected {
+ var template Number_of_octets_affected r;
+ if (istemplatekind(oct_aff, "omit")) {
+ return omit;
+ } else if (istemplatekind(oct_aff, "*")) {
+ return *;
+ } else {
+ r := {
+ iEI := '25'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 3
+ },
+ number_of_octets_transfered_or_deleted := f_oct_or_wc(oct_aff, 3)
+ }
+ return r;
+ }
+ }
+ template (value) Number_of_octets_affected ts_NO_OCT_AFF(template (value) integer oct_aff) := {
+ iEI := '25'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 3
+ },
+ number_of_octets_transfered_or_deleted := int2oct(valueof(oct_aff), 3)
+ }
+
+ private function tr_LLC_FRAMES_DISCARDED(template integer frames_discarded)
+ return template LLC_Frames_Discarded {
+ var template LLC_Frames_Discarded r;
+ if (istemplatekind(frames_discarded, "omit")) {
+ return omit;
+ } else if (istemplatekind(frames_discarded, "*")) {
+ return *;
+ } else {
+ r := {
+ iEI := '0F'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ number_of_frames_discarded := f_hex_or_wc(frames_discarded, 2)
+ }
+ return r;
+ }
+ }
+ template (value) LLC_Frames_Discarded ts_LLC_FRAMES_DISCARDED(template (value) integer frames_discarded) := {
+ iEI := '0F'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ number_of_frames_discarded := int2hex(valueof(frames_discarded), 2)
+ }
+
+
+ private function tr_BSSGP_BVCI(template BssgpBvci bvci)
+ return template BVCI {
+ var template BVCI r;
+ if (istemplatekind(bvci, "omit")) {
+ return omit;
+ } else if (istemplatekind(bvci, "*")) {
+ return *;
+ } else {
+ r := {
+ iEI := '04'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ unstructured_value := f_oct_or_wc(bvci, 2)
+ }
+ return r;
+ }
+ }
+ template (value) BVCI ts_BSSGP_BVCI(template (value) BssgpBvci bvci) := {
iEI := '04'O,
ext := '1'B,
lengthIndicator := {
length1 := 2
},
- unstructured_value := f_oct_or_wc(bvci, 2)
+ unstructured_value := int2oct(valueof(bvci), 2)
+ }
+ private function f_ts_BSSGP_BVCI(template (omit) BssgpBvci bvci)
+ return template (omit) BVCI {
+ if (istemplatekind(bvci, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_BVCI(valueof(bvci));
+ }
+ }
+
+ private function t_BSSGP_NSEI(template Nsei nsei)
+ return template NSEI_BSSGP {
+ var template NSEI_BSSGP r;
+ if (istemplatekind(nsei, "omit")) {
+ return omit;
+ } else if (istemplatekind(nsei, "*")) {
+ return *;
+ } else {
+ r := {
+ iEI:= '3E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ nSEI := f_oct_or_wc(nsei, 2)
+ }
+ return r;
+ }
+ }
+ template (value) NSEI_BSSGP ts_BSSGP_NSEI(template (value) Nsei nsei) := {
+ iEI:= '3E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ nSEI := int2oct(valueof(nsei), 2)
+ }
+ private function f_ts_BSSGP_NSEI(template (omit) Nsei nsei)
+ return template (omit) NSEI_BSSGP {
+ if (istemplatekind(nsei, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_NSEI(valueof(nsei));
+ }
}
template (value) TLLI_BSSGP ts_BSSGP_TLLI(template (value) GprsTlli tlli) := {
@@ -740,7 +981,7 @@ octetstring sdu) := {
},
tLLI_Value := tlli
}
- template TLLI_BSSGP tr_BSSGP_TLLI(template GprsTlli tlli) := {
+ template (present) TLLI_BSSGP tr_BSSGP_TLLI(template (present) GprsTlli tlli) := {
iEI := '1F'O,
ext := '1'B,
lengthIndicator := {
@@ -748,6 +989,22 @@ octetstring sdu) := {
},
tLLI_Value := tlli
}
+ private function f_ts_BSSGP_TLLI(template (omit) GprsTlli tlli) return template (omit) TLLI_BSSGP {
+ if (istemplatekind(tlli, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_TLLI(valueof(tlli));
+ }
+ }
+ private function f_tr_BSSGP_TLLI(template GprsTlli tlli) return template TLLI_BSSGP {
+ if (istemplatekind(tlli, "omit")) {
+ return omit;
+ } else if (istemplatekind(tlli, "*")) {
+ return *;
+ } else {
+ return tr_BSSGP_TLLI(valueof(tlli));
+ }
+ }
template (value) Suspend_Reference_Number ts_BSSGP_SUSP_REF(template (value) OCT1 susp_ref) := {
iEI := '1D'O,
@@ -766,7 +1023,7 @@ octetstring sdu) := {
suspend_Reference_Number_value := susp_ref
}
- template IMSI_BSSGP tr_BSSGP_IMSI(template hexstring imsi) := {
+ template (present) IMSI_BSSGP tr_BSSGP_IMSI(template (present) hexstring imsi) := {
iEI := '0D'O,
ext := '1'B,
lengthIndicator := ?,
@@ -775,7 +1032,7 @@ octetstring sdu) := {
digits := imsi
}
- template IMSI_BSSGP ts_BSSGP_IMSI(hexstring imsi) := {
+ template (value) IMSI_BSSGP ts_BSSGP_IMSI(hexstring imsi) := {
iEI := '0D'O,
ext := '1'B,
lengthIndicator := { length1 := 0 /* overwritten */ },
@@ -783,6 +1040,29 @@ octetstring sdu) := {
oddevenIndicator := f_hex_is_odd_length(imsi),
digits := imsi
}
+ private function f_ts_BSSGP_IMSI(template (omit) hexstring imsi) return template (omit) IMSI_BSSGP {
+ if (istemplatekind(imsi, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_IMSI(valueof(imsi));
+ }
+ }
+ private function f_tr_BSSGP_IMSI(template hexstring imsi) return template IMSI_BSSGP {
+ if (istemplatekind(imsi, "omit")) {
+ return omit;
+ } else if (istemplatekind(imsi, "*")) {
+ return *;
+ } else {
+ return tr_BSSGP_IMSI(imsi);
+ }
+ }
+
+ template (present) TMSI_BSSGP tr_BSSGP_TMSI(GsmTmsi tmsi) := {
+ iEI := '20'O,
+ ext := '1'B,
+ lengthIndicator := { length1 := 4 },
+ tMSI_Value := int2oct(tmsi, 4)
+ }
template TMSI_BSSGP ts_BSSGP_TMSI(GsmTmsi tmsi) := {
iEI := '20'O,
@@ -790,6 +1070,24 @@ octetstring sdu) := {
lengthIndicator := { length1 := 4 },
tMSI_Value := int2oct(tmsi, 4)
}
+ private function f_ts_BSSGP_TMSI(template (omit) GsmTmsi tmsi) return template (omit) TMSI_BSSGP {
+ if (istemplatekind(tmsi, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_TMSI(valueof(tmsi));
+ }
+ }
+ private function f_tr_BSSGP_TMSI(template GsmTmsi tmsi) return template TMSI_BSSGP {
+ if (istemplatekind(tmsi, "omit")) {
+ return omit;
+ } else if (istemplatekind(tmsi, "*")) {
+ return *;
+ } else if (istemplatekind(tmsi, "?")) {
+ return ?;
+ } else {
+ return tr_BSSGP_TMSI(valueof(tmsi));
+ }
+ }
function f_bssgp_length_ind(integer len) return LIN2_2a {
var LIN2_2a ret;
@@ -802,7 +1100,7 @@ octetstring sdu) := {
}
template LLC_PDU ts_BSSGP_LLC_PDU(octetstring pdu) := {
- iEI := '0D'O,
+ iEI := '0E'O,
ext := '1'B,
lengthIndicator := f_bssgp_length_ind(lengthof(pdu)),
lLC_PDU := pdu
@@ -827,7 +1125,7 @@ octetstring sdu) := {
}
return ret;
}
- function t_BSSGP_CAUSE(template BssgpCause cause) return template Cause_BSSGP {
+ function tr_BSSGP_CAUSE(template BssgpCause cause) return template Cause_BSSGP {
var template Cause_BSSGP ret;
ret.iEI := '07'O;
ret.ext := '1'B;
@@ -840,7 +1138,7 @@ octetstring sdu) := {
return ret;
}
- function t_BSSGP_IE_CellId(template BssgpCellId cid) return template Cell_Identifier {
+ function tr_BSSGP_IE_CellId(template BssgpCellId cid) return template Cell_Identifier {
var template Cell_Identifier ret := {
iEI := '08'O,
ext := '1'B,
@@ -883,82 +1181,171 @@ octetstring sdu) := {
}
return ret;
}
+ template (value) Cell_Identifier ts_BSSGP_IE_CellId(template (value) BssgpCellId cid) := {
+ iEI := '08'O,
+ ext := '1'B,
+ lengthIndicator := { length1 := 8 },
+ mccDigit1 := cid.ra_id.lai.mcc_mnc[0],
+ mccDigit2 := cid.ra_id.lai.mcc_mnc[1],
+ mccDigit3 := cid.ra_id.lai.mcc_mnc[2],
+ mncDigit3 := cid.ra_id.lai.mcc_mnc[3],
+ mncDigit1 := cid.ra_id.lai.mcc_mnc[4],
+ mncDigit2 := cid.ra_id.lai.mcc_mnc[5],
+ lac := int2oct(valueof(cid.ra_id.lai.lac), 2),
+ rac := int2oct(valueof(cid.ra_id.rac), 1),
+ cI_value := int2oct(valueof(cid.cell_id), 2)
+ }
+ function f_ts_BSSGP_IE_CellId(template (omit) BssgpCellId cid) return template (omit) Cell_Identifier {
+ if (istemplatekind(cid, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_IE_CellId(valueof(cid));
+ }
+ }
+
+ template (value) Tag ts_BSSGP_IE_Tag(OCT1 tag) := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ }
+
+ template (present) Tag tr_BSSGP_IE_Tag(template (present) OCT1 tag) := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ }
+
+ template (value) RA_Cap_UPD_CAUSE ts_BSSGP_IE_RACU_Cause(template (value) OCT1 cause) := {
+ iEI := '1A'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rA_CAP_UPD_Cause_value := cause
+ }
+ template (present) RA_Cap_UPD_CAUSE tr_BSSGP_IE_RACU_Cause(template (present) OCT1 cause) := {
+ iEI := '1A'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rA_CAP_UPD_Cause_value := cause
+ }
+
+ /* 10.4.12 */
template PDU_BSSGP ts_BVC_RESET(BssgpCause cause, BssgpBvci bvci,
- template BssgpCellId cell_id) := {
+ template (omit) BssgpCellId cell_id) := {
pDU_BSSGP_BVC_RESET := {
bssgpPduType := '22'O,
- bVCI := t_BSSGP_BVCI(bvci),
+ bVCI := ts_BSSGP_BVCI(bvci),
cause := ts_BSSGP_CAUSE(cause),
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ cell_Identifier := f_ts_BSSGP_IE_CellId(cell_id),
feature_bitmap := omit,
extended_Feature_Bitmap := omit
}
}
-
template PDU_BSSGP tr_BVC_RESET(template BssgpCause cause, template BssgpBvci bvci,
template BssgpCellId cell_id) := {
pDU_BSSGP_BVC_RESET := {
bssgpPduType := '22'O,
- bVCI := t_BSSGP_BVCI(bvci),
- cause := t_BSSGP_CAUSE(cause),
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ bVCI := tr_BSSGP_BVCI(bvci),
+ cause := tr_BSSGP_CAUSE(cause),
+ cell_Identifier := tr_BSSGP_IE_CellId(cell_id),
feature_bitmap := *,
extended_Feature_Bitmap := *
}
}
- template PDU_BSSGP ts_BVC_RESET_ACK(BssgpBvci bvci, template BssgpCellId cell_id) := {
+ /* 10.4.13 */
+ template PDU_BSSGP ts_BVC_RESET_ACK(BssgpBvci bvci, template (omit) BssgpCellId cell_id) := {
pDU_BSSGP_BVC_RESET_ACK := {
bssgpPduType := '23'O,
- bVCI := t_BSSGP_BVCI(bvci),
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ bVCI := ts_BSSGP_BVCI(bvci),
+ cell_Identifier := f_ts_BSSGP_IE_CellId(cell_id),
feature_bitmap := omit,
extended_Feature_Bitmap := omit
}
}
-
template PDU_BSSGP tr_BVC_RESET_ACK(template BssgpBvci bvci, template BssgpCellId cell_id) := {
pDU_BSSGP_BVC_RESET_ACK := {
bssgpPduType := '23'O,
- bVCI := t_BSSGP_BVCI(bvci),
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ bVCI := tr_BSSGP_BVCI(bvci),
+ cell_Identifier := tr_BSSGP_IE_CellId(cell_id),
feature_bitmap := *,
extended_Feature_Bitmap := *
}
}
- template PDU_BSSGP t_BVC_UNBLOCK(template BssgpBvci bvci) := {
+ /* 10.4.10 */
+ template (present) PDU_BSSGP tr_BVC_UNBLOCK(template (present) BssgpBvci bvci) := {
pDU_BSSGP_BVC_UNBLOCK := {
bssgpPduType := '24'O,
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := tr_BSSGP_BVCI(bvci)
+ }
+ }
+ template (value) PDU_BSSGP ts_BVC_UNBLOCK(template (value) BssgpBvci bvci) := {
+ pDU_BSSGP_BVC_UNBLOCK := {
+ bssgpPduType := '24'O,
+ bVCI := ts_BSSGP_BVCI(bvci)
}
}
- template PDU_BSSGP t_BVC_UNBLOCK_ACK(template BssgpBvci bvci) := {
+ /* 10.4.11 */
+ template (present) PDU_BSSGP tr_BVC_UNBLOCK_ACK(template (present) BssgpBvci bvci) := {
pDU_BSSGP_BVC_UNBLOCK_ACK := {
bssgpPduType := '25'O,
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := tr_BSSGP_BVCI(bvci)
+ }
+ }
+ template (value) PDU_BSSGP ts_BVC_UNBLOCK_ACK(template (value) BssgpBvci bvci) := {
+ pDU_BSSGP_BVC_UNBLOCK_ACK := {
+ bssgpPduType := '25'O,
+ bVCI := ts_BSSGP_BVCI(bvci)
}
}
- template PDU_BSSGP t_BVC_BLOCK(template BssgpBvci bvci, template BssgpCause cause) := {
+ /* 10.4.8 */
+ template (present) PDU_BSSGP tr_BVC_BLOCK(template (present) BssgpBvci bvci,
+ template (present) BssgpCause cause) := {
pDU_BSSGP_BVC_BLOCK := {
bssgpPduType := '20'O,
- bVCI := t_BSSGP_BVCI(bvci),
- cause := t_BSSGP_CAUSE(cause)
+ bVCI := tr_BSSGP_BVCI(bvci),
+ cause := tr_BSSGP_CAUSE(cause)
+ }
+ }
+ template (value) PDU_BSSGP ts_BVC_BLOCK(template (value) BssgpBvci bvci,
+ template (value) BssgpCause cause) := {
+ pDU_BSSGP_BVC_BLOCK := {
+ bssgpPduType := '20'O,
+ bVCI := ts_BSSGP_BVCI(bvci),
+ cause := ts_BSSGP_CAUSE(cause)
}
}
- template PDU_BSSGP t_BVC_BLOCK_ACK(template BssgpBvci bvci) := {
+ /* 10.4.9 */
+ template (present) PDU_BSSGP tr_BVC_BLOCK_ACK(template (present) BssgpBvci bvci) := {
+ pDU_BSSGP_BVC_BLOCK_ACK := {
+ bssgpPduType := '21'O,
+ bVCI := tr_BSSGP_BVCI(bvci)
+ }
+ }
+ template (value) PDU_BSSGP ts_BVC_BLOCK_ACK(template (value) BssgpBvci bvci) := {
pDU_BSSGP_BVC_BLOCK_ACK := {
bssgpPduType := '21'O,
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
}
}
- template PDU_BSSGP t_BVC_FC_BVC(uint16_t bmax, uint16_t bucket_leak_rate,
+ /* 10.4.4 */
+ template (value) PDU_BSSGP ts_BVC_FC_BVC(uint16_t bmax, uint16_t bucket_leak_rate,
uint16_t bmax_default_ms, uint16_t r_default_ms, OCT1 tag) := {
pDU_BSSGP_FLOW_CONTROL_BVC := {
bssgpPduType := '26'O,
@@ -976,7 +1363,7 @@ octetstring sdu) := {
lengthIndicator := {
length1 := 2
},
- bmax := f_oct_or_wc(bmax, 2)
+ bmax := int2oct(bmax, 2)
},
bucket_Leak_Rate := {
iEI := '03'O,
@@ -984,7 +1371,7 @@ octetstring sdu) := {
lengthIndicator := {
length1 := 2
},
- r_Value := f_oct_or_wc(bucket_leak_rate, 2)
+ r_Value := int2oct(bucket_leak_rate, 2)
},
bmax_default_MS := {
iEI := '01'O,
@@ -992,7 +1379,7 @@ octetstring sdu) := {
lengthIndicator := {
length1 := 2
},
- bmax := f_oct_or_wc(bmax_default_ms, 2)
+ bmax := int2oct(bmax_default_ms, 2)
},
r_default_MS := {
iEI := '1C'O,
@@ -1000,7 +1387,7 @@ octetstring sdu) := {
lengthIndicator := {
length1 := 2
},
- r_default_MS_value := f_oct_or_wc(r_default_ms, 2)
+ r_default_MS_value := int2oct(r_default_ms, 2)
},
bucket_Full_Ratio := omit,
bVC_Measurement := omit,
@@ -1060,26 +1447,146 @@ octetstring sdu) := {
}
}
- template PDU_BSSGP t_BVC_FC_BVC_ACK(template OCT1 tag) := {
+ /* 10.4.5 */
+ template (present) PDU_BSSGP tr_BVC_FC_BVC_ACK(template (present) OCT1 tag) := {
+ pDU_BSSGP_FLOW_CONTROL_BVC_ACK := {
+ bssgpPduType := '27'O,
+ tag := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ }
+ }
+ }
+ template (value) PDU_BSSGP ts_BVC_FC_BVC_ACK(template (value) OCT1 tag) := {
pDU_BSSGP_FLOW_CONTROL_BVC_ACK := {
bssgpPduType := '27'O,
tag := {
iEI := '1E'O,
ext := '1'B,
lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ }
+ }
+ }
+
+ /* 10.4.6 */
+ template (value) PDU_BSSGP ts_BVC_FC_MS(GprsTlli tlli, uint16_t bmax, uint16_t bucket_leak_rate,
+ OCT1 tag) := {
+ pDU_BSSGP_FLOW_CONTROL_MS := {
+ bssgpPduType := '28'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ tag := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ },
+ mS_Bucket_Size := {
+ iEI := '12'O,
+ ext := '1'B,
+ lengthIndicator := {
length1 := 2
},
+ bmax := int2oct(bmax, 2)
+ },
+ bucket_Leak_Rate := {
+ iEI := '03'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ r_Value := int2oct(bucket_leak_rate, 2)
+ },
+ bucket_Full_Ratio := omit,
+ flow_Control_Granularity := omit
+ }
+ }
+ template (present) PDU_BSSGP tr_BVC_FC_MS(template (present) GprsTlli tlli := ?,
+ template (present) uint16_t bmax := ?,
+ template (present) uint16_t bucket_leak_rate := ?,
+ template (present) OCT1 tag := ?) := {
+ pDU_BSSGP_FLOW_CONTROL_MS := {
+ bssgpPduType := '28'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ tag := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ },
+ mS_Bucket_Size := {
+ iEI := '12'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ bmax := f_oct_or_wc(bmax, 2)
+ },
+ bucket_Leak_Rate := {
+ iEI := '03'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ r_Value := f_oct_or_wc(bucket_leak_rate, 2)
+ },
+ bucket_Full_Ratio := *,
+ flow_Control_Granularity := *
+ }
+ }
+
+ /* 10.4.7 */
+ template (value) PDU_BSSGP ts_BVC_FC_MS_ACK(template (value) GprsTlli tlli,
+ template (value) OCT1 tag) := {
+
+ pDU_BSSGP_FLOW_CONTROL_MS_ACK := {
+ bssgpPduType := '29'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ tag := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ unstructured_Value := tag
+ }
+ }
+ }
+ template (present) PDU_BSSGP tr_BVC_FC_MS_ACK(template (present) GprsTlli tlli,
+ template (present) OCT1 tag := ?) := {
+
+ pDU_BSSGP_FLOW_CONTROL_MS_ACK := {
+ bssgpPduType := '29'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ tag := {
+ iEI := '1E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
unstructured_Value := tag
}
}
}
- template PDU_BSSGP ts_BSSGP_STATUS(template BssgpBvci bvci, template BssgpCause cause,
- PDU_BSSGP pdu) := {
+ /* 10.4.14 */
+ template (value) PDU_BSSGP ts_BSSGP_STATUS(template (omit) BssgpBvci bvci,
+ template (value) BssgpCause cause,
+ PDU_BSSGP pdu) := {
pDU_BSSGP_STATUS := {
- bssgpPduType := '0A'O,
- cause := t_BSSGP_CAUSE(cause),
- bVCI := t_BSSGP_BVCI(bvci),
+ bssgpPduType := '41'O,
+ cause := ts_BSSGP_CAUSE(cause),
+ bVCI := f_ts_BSSGP_BVCI(bvci),
pDU_in_Error := {
iEI := '15'O,
ext := '1'B,
@@ -1090,6 +1597,22 @@ octetstring sdu) := {
}
}
}
+ template PDU_BSSGP tr_BSSGP_STATUS(template BssgpBvci bvci := ?, template BssgpCause cause := ?,
+ template octetstring pdu := ?) := {
+ pDU_BSSGP_STATUS := {
+ bssgpPduType := '41'O,
+ cause := tr_BSSGP_CAUSE(cause),
+ bVCI := tr_BSSGP_BVCI(bvci),
+ pDU_in_Error := {
+ iEI := '15'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ erroneous_BSSGP_PDU := pdu
+ }
+ }
+ }
private function f_presence_bit_MultislotCap_GPRS_BSSGP(template (omit) MultislotCap_GPRS_BSSGP mscap_gprs) return BIT1 {
if (istemplatekind(mscap_gprs, "omit")) {
@@ -1142,6 +1665,48 @@ octetstring sdu) := {
},
presenceBitMSRACap := '0'B
};
+ template (present) MSRACapabilityValuesRecord_BSSGP
+ tr_RaCapRec_BSSGP(template (present) BIT4 att := '0001'B /* E-GSM */, template MultislotCap_GPRS_BSSGP mscap_gprs := *,
+ template MultislotCap_EGPRS_BSSGP mscap_egprs := *) := {
+ mSRACapabilityValues := {
+ mSRACapabilityValuesExclude1111 := {
+ accessTechnType := att, /* E-GSM */
+ accessCapabilities := {
+ lengthIndicator := ?, /* overwritten */
+ accessCapabilities := {
+ rfPowerCapability := '001'B, /* FIXME */
+ presenceBitA5 := ?,
+ a5bits := *,
+ esind := '1'B,
+ psbit := '0'B,
+ vgcs := '0'B,
+ vbs := '0'B,
+ presenceBitMultislot := '1'B,
+ multislotcap := {
+ presenceBitHscsd := '0'B,
+ hscsdmultislotclass := omit,
+ presenceBitGprs := ?,
+ gprsmultislot := mscap_gprs,
+ presenceBitSms := '0'B,
+ multislotCap_SMS := omit,
+ multislotCapAdditionsAfterRel97 := {
+ presenceBitEcsdmulti := '0'B,
+ ecsdmultislotclass := *,
+ presenceBitEgprsmulti := ?,
+ multislotCap_EGPRS := mscap_egprs,
+ presenceBitDtmGprsmulti := ?,
+ multislotCapdtmgprsmultislotsubclass := *
+ }
+ },
+ accessCapAdditionsAfterRel97 := *
+ },
+ spare_bits := *
+ }
+ }
+ },
+ presenceBitMSRACap := '0'B
+ };
+
template QoS_Profile_V t_defaultQos := {
peak_Bit_Rate := int2oct(80, 2),
@@ -1152,7 +1717,7 @@ octetstring sdu) := {
peakBitRateGranularity := '00'B
}
- template QoS_Profile ts_QoS_TLV(template QoS_Profile_V qos) := {
+ template (value) QoS_Profile ts_QoS_TLV(template (value) QoS_Profile_V qos) := {
iEI := '18'O,
ext := '1'B,
lengthIndicator := { length1 := 3 },
@@ -1164,13 +1729,13 @@ octetstring sdu) := {
peakBitRateGranularity := qos.peakBitRateGranularity
}
- template PDU_Lifetime t_DefaultLifetime(uint16_t delay := 65535) := {
+ template (value) PDU_Lifetime t_DefaultLifetime(uint16_t delay := 65535) := {
iEI := '16'O,
ext := '1'B,
lengthIndicator := {
length1 := 2
},
- delay_Value := f_oct_or_wc(delay, 2)
+ delay_Value := int2oct(delay, 2)
}
template DRX_Parameters t_defaultDRXparam := {
@@ -1191,7 +1756,7 @@ octetstring sdu) := {
return omit;
} else {
ret := {
- iEI := '00'O,
+ iEI := '13'O,
ext := '1'B,
lengthIndicator := {
length1 := 1
@@ -1202,7 +1767,25 @@ octetstring sdu) := {
}
}
- template PDU_BSSGP ts_BSSGP_DL_UD(GprsTlli tlli, octetstring pdu, template (omit) MSRadioAccessCapabilityV_BSSGP racap := omit) := {
+ function tr_BSSGP_IE_MSRAcap(template MSRadioAccessCapabilityV_BSSGP racap) return template MS_Radio_Access_Capability {
+ var template MS_Radio_Access_Capability ret;
+ if (istemplatekind(racap, "omit")) {
+ return omit;
+ } else {
+ ret := {
+ iEI := '13'O,
+ ext := ?,
+ lengthIndicator := ?,
+ mSRadioAccessCapabilityV_BSSGP := racap
+ }
+ return ret;
+ }
+ }
+
+ /* 10.2.1 */
+ template (value) PDU_BSSGP ts_BSSGP_DL_UD(GprsTlli tlli, octetstring pdu,
+ template (omit) MSRadioAccessCapabilityV_BSSGP racap := omit,
+ template (omit) IMSI_BSSGP imsi := omit) := {
pDU_BSSGP_DL_UNITDATA := {
bssgpPduType := '00'O,
tLLI_current := tlli,
@@ -1211,7 +1794,7 @@ octetstring sdu) := {
mS_Radio_Access_Capability := ts_BSSGP_IE_MSRAcap_omit(racap),
priority := omit,
dRX_Parameters := omit,
- iMSI := omit,
+ iMSI := imsi,
tLLI_old := omit,
pFI := omit,
lSA_Information := omit,
@@ -1231,17 +1814,17 @@ octetstring sdu) := {
initialLLC_PDU := omit
}
}
-
- template PDU_BSSGP tr_BSSGP_DL_UD := {
+ template (present) PDU_BSSGP tr_BSSGP_DL_UD(template (present) GprsTlli tlli, template (present) octetstring pdu,
+ template IMSI_BSSGP imsi := omit) := {
pDU_BSSGP_DL_UNITDATA := {
bssgpPduType := '00'O,
- tLLI_current := ?,
+ tLLI_current := tlli,
qoS_Profile := ?,
pDU_Lifetime := ?,
mS_Radio_Access_Capability := *,
priority := *,
dRX_Parameters := *,
- iMSI := *,
+ iMSI := imsi,
tLLI_old := *,
pFI := *,
lSA_Information := *,
@@ -1257,17 +1840,18 @@ octetstring sdu) := {
old_Routing_Area_Identification := *,
attach_Indicator := *,
alignment_octets := *,
- lLC_PDU := tr_BSSGP_LLC_PDU,
+ lLC_PDU := tr_BSSGP_LLC_PDU(pdu),
initialLLC_PDU := *
}
}
- template PDU_BSSGP ts_BSSGP_UL_UD(GprsTlli tlli, BssgpCellId cell_id, octetstring payload) := {
+ /* 10.2.2 */
+ template (value) PDU_BSSGP ts_BSSGP_UL_UD(GprsTlli tlli, BssgpCellId cell_id, octetstring payload) := {
pDU_BSSGP_UL_UNITDATA := {
bssgpPduType := '01'O,
tLLI := tlli,
qoS_Profile := t_defaultQos,
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ cell_Identifier := ts_BSSGP_IE_CellId(cell_id),
pFI := omit,
lSA_Identifier_List := omit,
redirect_Attempt_Flag := omit,
@@ -1280,14 +1864,13 @@ octetstring sdu) := {
lLC_PDU := ts_BSSGP_LLC_PDU(payload)
}
}
-
template PDU_BSSGP tr_BSSGP_UL_UD(template GprsTlli tlli := ?, template BssgpCellId cell_id := ?,
template octetstring payload := ?) := {
pDU_BSSGP_UL_UNITDATA := {
bssgpPduType := '01'O,
tLLI := tlli,
qoS_Profile := ?,
- cell_Identifier := t_BSSGP_IE_CellId(cell_id),
+ cell_Identifier := tr_BSSGP_IE_CellId(cell_id),
pFI := *,
lSA_Identifier_List := *,
redirect_Attempt_Flag := *,
@@ -1301,13 +1884,14 @@ octetstring sdu) := {
}
}
+ /* 10.3.2 */
template PDU_BSSGP tr_BSSGP_CS_PAGING(BssgpBvci bvci) := {
pDU_BSSGP_PAGING_CS := {
bssgpPduType := '07'O,
iMSI := ?,
dRX_Parameters := ?,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
},
tLLI := *,
channel_needed := *,
@@ -1316,14 +1900,13 @@ octetstring sdu) := {
global_CN_Id := *
}
}
-
- template PDU_BSSGP ts_BSSGP_CS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := {
+ template (value) PDU_BSSGP ts_BSSGP_CS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := {
pDU_BSSGP_PAGING_CS := {
bssgpPduType := '07'O,
iMSI := ts_BSSGP_IMSI(imsi),
dRX_Parameters := t_defaultDRXparam,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
},
tLLI := omit,
channel_needed := omit,
@@ -1332,14 +1915,13 @@ octetstring sdu) := {
global_CN_Id := omit
}
}
-
- template PDU_BSSGP ts_BSSGP_CS_PAGING_PTMSI(BssgpBvci bvci, hexstring imsi, GsmTmsi tmsi) := {
+ template (value) PDU_BSSGP ts_BSSGP_CS_PAGING_PTMSI(BssgpBvci bvci, hexstring imsi, GsmTmsi tmsi) := {
pDU_BSSGP_PAGING_CS := {
bssgpPduType := '07'O,
iMSI := ts_BSSGP_IMSI(imsi),
dRX_Parameters := t_defaultDRXparam,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
},
tLLI := omit,
channel_needed := omit,
@@ -1349,13 +1931,14 @@ octetstring sdu) := {
}
}
+ /* 10.3.1 */
template PDU_BSSGP tr_BSSGP_PS_PAGING(template BssgpBvci bvci) := {
pDU_BSSGP_PAGING_PS := {
bssgpPduType := '06'O,
iMSI := ?,
dRX_Parameters := *,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := tr_BSSGP_BVCI(bvci)
},
pFI := *,
aBQP := *,
@@ -1364,14 +1947,13 @@ octetstring sdu) := {
eDRX_Paremeters := *
}
}
-
- template PDU_BSSGP ts_BSSGP_PS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := {
+ template (value) PDU_BSSGP ts_BSSGP_PS_PAGING_IMSI(BssgpBvci bvci, hexstring imsi) := {
pDU_BSSGP_PAGING_PS := {
bssgpPduType := '06'O,
iMSI := ts_BSSGP_IMSI(imsi),
dRX_Parameters := omit,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
},
pFI := omit,
aBQP := omit,
@@ -1380,14 +1962,13 @@ octetstring sdu) := {
eDRX_Paremeters := omit
}
}
-
- template PDU_BSSGP ts_BSSGP_PS_PAGING_PTMSI(BssgpBvci bvci, hexstring imsi, GsmTmsi tmsi) := {
+ template (value) PDU_BSSGP ts_BSSGP_PS_PAGING_PTMSI(BssgpBvci bvci, hexstring imsi, GsmTmsi tmsi) := {
pDU_BSSGP_PAGING_PS := {
bssgpPduType := '06'O,
iMSI := ts_BSSGP_IMSI(imsi),
dRX_Parameters := omit,
paging_Field4 := {
- bVCI := t_BSSGP_BVCI(bvci)
+ bVCI := ts_BSSGP_BVCI(bvci)
},
pFI := omit,
aBQP := omit,
@@ -1397,7 +1978,45 @@ octetstring sdu) := {
}
}
- template (value) Routeing_Area ts_BSSGP_RA_ID(RoutingAreaIdentification input) := {
+ template (value) Paging_Field4 ts_BssgpP4BssArea := {
+ bSS_Area_Indication := {
+ iEI := '02'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ bSS_indicator := '00'O
+ }
+ }
+
+ template (value) Paging_Field4 ts_BssgpP4LAC(GSM_Types.LocationAreaIdentification lai) := {
+ location_Area := ts_BSSGP_LA_ID(lai)
+ }
+
+ template (value) Paging_Field4 ts_BssgpP4RAC(GSM_Types.RoutingAreaIdentification rai) := {
+ routeing_Area := ts_BSSGP_RA_ID(rai)
+ }
+
+ template (value) Paging_Field4 ts_BssgpP4Bvci(BssgpBvci bvci) := {
+ bVCI := ts_BSSGP_BVCI(bvci)
+ }
+
+ template (value) Location_Area ts_BSSGP_LA_ID(GSM_Types.LocationAreaIdentification input) := {
+ iEI := '10'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 5
+ },
+ mccDigit1 := input.mcc_mnc[0],
+ mccDigit2 := input.mcc_mnc[1],
+ mccDigit3 := input.mcc_mnc[2],
+ mncDigit3 := input.mcc_mnc[3],
+ mncDigit1 := input.mcc_mnc[4],
+ mncDigit2 := input.mcc_mnc[5],
+ lac := int2oct(input.lac, 2)
+ }
+
+ template (value) Routeing_Area ts_BSSGP_RA_ID(GSM_Types.RoutingAreaIdentification input) := {
iEI := '1B'O,
ext := '1'B,
lengthIndicator := {
@@ -1413,6 +2032,29 @@ octetstring sdu) := {
rac := int2oct(input.rac, 1)
}
+ private function f_ts_BSSGP_RA_ID(template (omit) GSM_Types.RoutingAreaIdentification input)
+ return template (omit) Routeing_Area {
+ if (istemplatekind(input, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_RA_ID(valueof(input));
+ }
+ }
+
+ private function f_tr_BSSGP_RA_ID(template GSM_Types.RoutingAreaIdentification input)
+ return template Routeing_Area {
+ if (istemplatekind(input, "omit")) {
+ return omit;
+ } else if (istemplatekind(input, "*")) {
+ return *;
+ } else if (istemplatekind(input, "?")) {
+ return ?;
+ } else {
+ return ts_BSSGP_RA_ID(valueof(input));
+ }
+ }
+
+ /* 10.3.6 */
template (value) PDU_BSSGP ts_BSSGP_SUSPEND(GprsTlli tlli, RoutingAreaIdentification ra_id) := {
pDU_BSSGP_SUSPEND := {
bssgpPduType := '0B'O,
@@ -1420,7 +2062,7 @@ octetstring sdu) := {
routeing_Area := ts_BSSGP_RA_ID(ra_id)
}
}
- template PDU_BSSGP tr_BSSGP_SUSPEND(template GprsTlli tlli, RoutingAreaIdentification ra_id) := {
+ template PDU_BSSGP tr_BSSGP_SUSPEND(template (present) GprsTlli tlli, RoutingAreaIdentification ra_id) := {
pDU_BSSGP_SUSPEND := {
bssgpPduType := '0B'O,
tLLI := tr_BSSGP_TLLI(tlli),
@@ -1428,6 +2070,7 @@ octetstring sdu) := {
}
}
+ /* 10.3.7 */
template (value) PDU_BSSGP ts_BSSGP_SUSPEND_ACK(GprsTlli tlli, RoutingAreaIdentification ra_id,
template (value) OCT1 susp_ref) := {
pDU_BSSGP_SUSPEND_ACK := {
@@ -1447,6 +2090,7 @@ octetstring sdu) := {
}
}
+ /* 10.3.8 */
template (value) PDU_BSSGP ts_BSSGP_SUSPEND_NACK(GprsTlli tlli, RoutingAreaIdentification ra_id,
template (omit) BssgpCause cause) := {
pDU_BSSGP_SUSPEND_NACK := {
@@ -1462,12 +2106,12 @@ octetstring sdu) := {
bssgpPduType := '0D'O,
tLLI := tr_BSSGP_TLLI(tlli),
routeing_Area := ts_BSSGP_RA_ID(ra_id),
- cause := t_BSSGP_CAUSE(cause)
+ cause := tr_BSSGP_CAUSE(cause)
}
}
-
+ /* 10.3.9 */
template (value) PDU_BSSGP ts_BSSGP_RESUME(GprsTlli tlli, RoutingAreaIdentification ra_id,
OCT1 susp_ref) := {
pDU_BSSGP_RESUME := {
@@ -1477,7 +2121,7 @@ octetstring sdu) := {
suspend_Reference_Number := ts_BSSGP_SUSP_REF(susp_ref)
}
}
- template PDU_BSSGP tr_BSSGP_RESUME(template GprsTlli tlli, RoutingAreaIdentification ra_id,
+ template PDU_BSSGP tr_BSSGP_RESUME(template (present) GprsTlli tlli, RoutingAreaIdentification ra_id,
template OCT1 susp_ref) := {
pDU_BSSGP_RESUME := {
bssgpPduType := '0E'O,
@@ -1487,6 +2131,7 @@ octetstring sdu) := {
}
}
+ /* 10.3.10 */
template (value) PDU_BSSGP ts_BSSGP_RESUME_ACK(GprsTlli tlli, RoutingAreaIdentification ra_id)
:= {
pDU_BSSGP_RESUME_ACK := {
@@ -1495,7 +2140,7 @@ octetstring sdu) := {
routeing_Area := ts_BSSGP_RA_ID(ra_id)
}
}
- template PDU_BSSGP tr_BSSGP_RESUME_ACK(template GprsTlli tlli,
+ template PDU_BSSGP tr_BSSGP_RESUME_ACK(template (present) GprsTlli tlli,
RoutingAreaIdentification ra_id) := {
pDU_BSSGP_RESUME_ACK := {
bssgpPduType := '0F'O,
@@ -1504,6 +2149,7 @@ octetstring sdu) := {
}
}
+ /* 10.3.11 */
template (value) PDU_BSSGP ts_BSSGP_RESUME_NACK(GprsTlli tlli, RoutingAreaIdentification ra_id,
template (omit) BssgpCause cause) := {
pDU_BSSGP_RESUME_NACK := {
@@ -1513,18 +2159,1741 @@ octetstring sdu) := {
cause := ts_BSSGP_CAUSE(cause)
}
}
- template PDU_BSSGP tr_BSSGP_RESUME_NACK(template GprsTlli tlli,
+ template PDU_BSSGP tr_BSSGP_RESUME_NACK(template (present) GprsTlli tlli,
RoutingAreaIdentification ra_id,
template BssgpCause cause) := {
pDU_BSSGP_RESUME_NACK := {
bssgpPduType := '10'O,
tLLI := tr_BSSGP_TLLI(tlli),
routeing_Area := ts_BSSGP_RA_ID(ra_id),
- cause := t_BSSGP_CAUSE(cause)
+ cause := tr_BSSGP_CAUSE(cause)
+ }
+ }
+
+ /* 10.3.12 */
+ template (value) PDU_BSSGP ts_BSSGP_DUMMY_PAGING_PS(hexstring imsi,
+ template (omit) RoutingAreaIdentification ra) := {
+ pDU_BSSGP_DUMMY_PAGING_PS := {
+ bssgpPduType := '12'O,
+ iMSI := ts_BSSGP_IMSI(imsi),
+ routeing_Area := f_ts_BSSGP_RA_ID(ra),
+ eDRX_Paremeters := omit
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_DUMMY_PAGING_PS(hexstring imsi,
+ template RoutingAreaIdentification ra) := {
+ pDU_BSSGP_DUMMY_PAGING_PS := {
+ bssgpPduType := '12'O,
+ iMSI := tr_BSSGP_IMSI(imsi),
+ routeing_Area := f_tr_BSSGP_RA_ID(ra),
+ eDRX_Paremeters := omit
+ }
+ }
+
+ template (value) Time_Until_Next_Paging_Occasion ts_TimeNextPag(uint8_t mins, uint8_t secs) := {
+ iEI := '93'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ minutes := mins,
+ spare := '00'B,
+ seconds := secs,
+ spare2 := '00'B
+ }
+ template (present) Time_Until_Next_Paging_Occasion tr_TimeNextPag(template (present) uint8_t mins,
+ template (present) uint8_t secs) := {
+ iEI := '93'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ minutes := mins,
+ spare := ?,
+ seconds := secs,
+ spare2 := ?
+ }
+
+ /* 10.3.13 */
+ template (value) PDU_BSSGP ts_BSSGP_DUMMY_PAGING_PS_RESP(hexstring imsi, uint8_t mins, uint8_t secs) := {
+ pDU_BSSGP_DUMMY_PAGING_PS_RESPONSE := {
+ bssgpPduType := '13'O,
+ iMSI := ts_BSSGP_IMSI(imsi),
+ time_Until_Next_Paging_Occasion := ts_TimeNextPag(mins, secs)
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_DUMMY_PAGING_PS_RESP(hexstring imsi,
+ template (present) uint8_t mins,
+ template (present) uint8_t secs) := {
+ pDU_BSSGP_DUMMY_PAGING_PS_RESPONSE := {
+ bssgpPduType := '13'O,
+ iMSI := tr_BSSGP_IMSI(imsi),
+ time_Until_Next_Paging_Occasion := tr_TimeNextPag(mins, secs)
+ }
+ }
+
+ /* 10.3.14 */
+ template (value) PDU_BSSGP ts_BSSGP_PAGING_PS_REJ(hexstring imsi, uint8_t mins, uint8_t secs,
+ template (omit) GsmTmsi tmsi) := {
+ pDU_BSSGP_PAGING_PS_REJECT := {
+ bssgpPduType := '11'O,
+ iMSI := ts_BSSGP_IMSI(imsi),
+ pTMSI := f_ts_BSSGP_TMSI(tmsi),
+ time_Until_Next_Paging_Occasion := ts_TimeNextPag(mins, secs)
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_PAGING_PS_REJ(hexstring imsi,
+ template (present) uint8_t mins,
+ template (present) uint8_t secs,
+ template GsmTmsi tmsi) := {
+ pDU_BSSGP_PAGING_PS_REJECT := {
+ bssgpPduType := '11'O,
+ iMSI := tr_BSSGP_IMSI(imsi),
+ pTMSI := f_tr_BSSGP_TMSI(tmsi),
+ time_Until_Next_Paging_Occasion := tr_TimeNextPag(mins, secs)
+ }
+ }
+
+ /* 10.3.15 */
+ template (value) PDU_BSSGP ts_BSSGP_MS_REG_ENQ(hexstring imsi) := {
+ pDU_BSSGP_MS_REGISTRATION_ENQUIRY := {
+ bssgpPduType := '14'O,
+ iMSI := ts_BSSGP_IMSI(imsi),
+ mME_Query := omit
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_MS_REG_ENQ(hexstring imsi) := {
+ pDU_BSSGP_MS_REGISTRATION_ENQUIRY := {
+ bssgpPduType := '14'O,
+ iMSI := tr_BSSGP_IMSI(imsi),
+ mME_Query := *
+ }
+ }
+
+ /* 11.3.126 */
+ template (value) PLMN_Identity ts_BSSGP_PlmnId(template (value) BcdMccMnc mccmnc) := {
+ iEI := '96'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 3
+ },
+ mccDigit1 := mccmnc[0],
+ mccDigit2 := mccmnc[1],
+ mccDigit3 := mccmnc[2],
+ mncDigit3 := mccmnc[5],
+ mncDigit1 := mccmnc[3],
+ mncDigit2 := mccmnc[4]
+ }
+ template (present) PLMN_Identity tr_BSSGP_PlmnId(template (present) BcdMccMnc mccmnc) := {
+ iEI := '96'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 3
+ },
+ mccDigit1 := mccmnc[0],
+ mccDigit2 := mccmnc[1],
+ mccDigit3 := mccmnc[2],
+ mncDigit3 := mccmnc[5],
+ mncDigit1 := mccmnc[3],
+ mncDigit2 := mccmnc[4]
+ }
+ private function f_ts_BSSGP_PlmnId(template (omit) BcdMccMnc mccmnc)
+ return template (omit) PLMN_Identity {
+ if (istemplatekind(mccmnc, "omit")) {
+ return omit;
+ } else {
+ return ts_BSSGP_PlmnId(valueof(mccmnc));
+ }
+ }
+ private function f_tr_BSSGP_PlmnId(template BcdMccMnc mccmnc)
+ return template PLMN_Identity {
+ if (istemplatekind(mccmnc, "omit")) {
+ return omit;
+ } else if (istemplatekind(mccmnc, "*")) {
+ return *;
+ } else if (istemplatekind(mccmnc, "?")) {
+ return ?;
+ } else {
+ return ts_BSSGP_PlmnId(valueof(mccmnc));
+ }
+ }
+
+ /* 10.3.16 */
+ template (value) PDU_BSSGP ts_BSSGP_MS_REW_ENQ_RESP(hexstring imsi, template (omit) BcdMccMnc mccmnc) := {
+ pDU_BSSGP_MS_REGISTRATION_ENQUIRY_RESPONSE := {
+ bssgpPduType := '15'O,
+ iMSI := ts_BSSGP_IMSI(imsi),
+ pS_Registered_Operator := f_ts_BSSGP_PlmnId(mccmnc)
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_MS_REW_ENQ_RESP(hexstring imsi, template BcdMccMnc mccmnc) := {
+ pDU_BSSGP_MS_REGISTRATION_ENQUIRY_RESPONSE := {
+ bssgpPduType := '15'O,
+ iMSI := tr_BSSGP_IMSI(imsi),
+ pS_Registered_Operator := f_tr_BSSGP_PlmnId(mccmnc)
+ }
+ }
+
+ /* 10.4.1 */
+ template (value) PDU_BSSGP ts_BSSGP_FLUSH_LL(GprsTlli tlli, template (value) BssgpBvci bvci_old,
+ template (omit) BssgpBvci bvci_new := omit,
+ template (omit) Nsei nsei := omit) := {
+ pDU_BSSGP_FLUSH_LL := {
+ bssgpPduType := '2A'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ bVCI_old := ts_BSSGP_BVCI(bvci_old),
+ bVCI_new := f_ts_BSSGP_BVCI(bvci_new),
+ nSEI := f_ts_BSSGP_NSEI(nsei)
+ }
+ }
+ template PDU_BSSGP tr_BSSGP_FLUSH_LL(template (present) GprsTlli tlli, template BssgpBvci bvci_old,
+ template (omit) BssgpBvci bvci_new := omit,
+ template (omit) Nsei nsei := omit) := {
+ pDU_BSSGP_FLUSH_LL := {
+ bssgpPduType := '2A'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ bVCI_old := tr_BSSGP_BVCI(bvci_old),
+ bVCI_new := f_ts_BSSGP_BVCI(bvci_new),
+ nSEI := f_ts_BSSGP_NSEI(nsei)
+ }
+ }
+
+ /* 10.4.2 */
+ template (value) PDU_BSSGP ts_BSSGP_FLUSH_LL_ACK(GprsTlli tlli, template (value) OCT1 act,
+ template (value) integer oct_affected,
+ template (omit) BssgpBvci bvci_new := omit,
+ template (omit) Nsei nsei := omit) := {
+ pDU_BSSGP_FLUSH_LL_ACK := {
+ bssgpPduType := '2B'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ flush_Action := ts_FLUSH_ACTION(act),
+ bVCI_new := f_ts_BSSGP_BVCI(bvci_new),
+ number_of_octets_affected := ts_NO_OCT_AFF(oct_affected),
+ nSEI := f_ts_BSSGP_NSEI(nsei)
+ }
+ }
+ template PDU_BSSGP tr_BSSGP_FLUSH_LL_ACK(template (present) GprsTlli tlli, template OCT1 act,
+ template integer oct_affected,
+ template (omit) BssgpBvci bvci_new := omit,
+ template (omit) Nsei nsei := omit) := {
+ pDU_BSSGP_FLUSH_LL_ACK := {
+ bssgpPduType := '2B'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ flush_Action := tr_FLUSH_ACTION(act),
+ bVCI_new := f_ts_BSSGP_BVCI(bvci_new),
+ number_of_octets_affected := tr_NO_OCT_AFF(oct_affected),
+ nSEI := f_ts_BSSGP_NSEI(nsei)
+ }
+ }
+
+ /* 10.4.3 */
+ template (value) PDU_BSSGP ts_BSSGP_LLC_DISCARDED(GprsTlli tlli, template (value) integer frames_discarded,
+ template (value) BssgpBvci bvci,
+ template (value) integer oct_deleted) := {
+ pDU_BSSGP_LLC_DISCARDED := {
+ bssgpPduType := '2C'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ lLC_Frames_Discarded := ts_LLC_FRAMES_DISCARDED(frames_discarded),
+ bVCI := ts_BSSGP_BVCI(bvci),
+ number_of_octets_deleted := ts_NO_OCT_AFF(oct_deleted),
+ pFI := omit
+ }
+ }
+ template PDU_BSSGP tr_BSSGP_LLC_DISCARDED(template (present) GprsTlli tlli, template integer frames_discarded,
+ template BssgpBvci bvci,
+ template integer oct_deleted) := {
+ pDU_BSSGP_LLC_DISCARDED := {
+ bssgpPduType := '2C'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ lLC_Frames_Discarded := tr_LLC_FRAMES_DISCARDED(frames_discarded),
+ bVCI := tr_BSSGP_BVCI(bvci),
+ number_of_octets_deleted := tr_NO_OCT_AFF(oct_deleted),
+ pFI := *
+ }
+ }
+
+ /* 10.2.3 */
+ template (value) PDU_BSSGP ts_BSSGP_RA_CAP(GprsTlli tlli,
+ template (omit) MSRadioAccessCapabilityV_BSSGP racap := omit) := {
+ pDU_BSSGP_RA_CAPABILITY := {
+ bssgpPduType := '02'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ mS_Radio_Access_Capability := ts_BSSGP_IE_MSRAcap_omit(racap)
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_RA_CAP(template (present) GprsTlli tlli,
+ template MSRadioAccessCapabilityV_BSSGP racap) := {
+ pDU_BSSGP_RA_CAPABILITY := {
+ bssgpPduType := '02'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ mS_Radio_Access_Capability := tr_BSSGP_IE_MSRAcap(racap)
+ }
+ }
+
+
+ /* 10.3.3 */
+ template (value) PDU_BSSGP ts_BSSGP_RA_CAP_UPD(GprsTlli tlli, OCT1 tag) := {
+ pDU_BSSGP_RA_CAPABILITY_UPDATE := {
+ bssgpPduType := '08'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ tag := ts_BSSGP_IE_Tag(tag)
+ }
+ }
+ template (present) PDU_BSSGP tr_BSSGP_RA_CAP_UPD(template (present) GprsTlli tlli,
+ template (present) OCT1 tag) := {
+ pDU_BSSGP_RA_CAPABILITY_UPDATE := {
+ bssgpPduType := '08'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ tag := tr_BSSGP_IE_Tag(tag)
+ }
+ }
+
+
+ /* 10.3.4 */
+ template (value) PDU_BSSGP
+ ts_BSSGP_RA_CAP_UPD_ACK(GprsTlli tlli, OCT1 tag, template (value) OCT1 cause,
+ template (omit) MSRadioAccessCapabilityV_BSSGP racap := omit) := {
+ pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK := {
+ bssgpPduType := '09'O,
+ tLLI := ts_BSSGP_TLLI(tlli),
+ tag := ts_BSSGP_IE_Tag(tag),
+ iMSI := omit,
+ rA_Cap_UPDATE_CAUSE := ts_BSSGP_IE_RACU_Cause(cause),
+ mS_Radio_Access_Capability := ts_BSSGP_IE_MSRAcap_omit(racap)
+ }
+ }
+ template (present) PDU_BSSGP
+ tr_BSSGP_RA_CAP_UPD_ACK(template (present) GprsTlli tlli, template (present) OCT1 tag, template (present) OCT1 cause,
+ template MSRadioAccessCapabilityV_BSSGP racap := omit) := {
+ pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK := {
+ bssgpPduType := '09'O,
+ tLLI := tr_BSSGP_TLLI(tlli),
+ tag := tr_BSSGP_IE_Tag(tag),
+ iMSI := omit,
+ rA_Cap_UPDATE_CAUSE := tr_BSSGP_IE_RACU_Cause(cause),
+ mS_Radio_Access_Capability := tr_BSSGP_IE_MSRAcap(racap)
+ }
+ }
+
+ type enumerated BssgpRadioCause {
+ BSSGP_RADIO_CAUSE_CONTACT_LOST ('00'H),
+ BSSGP_RADIO_CAUSE_LINK_QUAL_INSUFF ('01'H),
+ BSSGP_RADIO_CAUSE_CELL_RESEL_ORDERED ('02'H),
+ BSSGP_RADIO_CAUSE_CELL_RESEL_PREPARE ('03'H),
+ BSSGP_RADIO_CAUSE_CELL_RESEL_FAILURE ('04'H)
+ } with { variant "FIELDLENGTH(8)" };
+
+ function ts_BSSGP_RADIO_CAUSE(template (omit) BssgpRadioCause cause) return template (omit) Radio_Cause {
+ var template (omit) Radio_Cause ret;
+ if (istemplatekind(cause, "omit")) {
+ ret := omit;
+ } else {
+ ret.iEI := '19'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := 1 };
+ ret.radio_Cause_Value := int2oct(enum2int(valueof(cause)), 1);
+ }
+ return ret;
+ }
+ function tr_BSSGP_RADIO_CAUSE(template BssgpRadioCause cause) return template (present) Radio_Cause {
+ var template (present) Radio_Cause ret;
+ ret.iEI := '19'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := 1 };
+ if (isvalue(cause)) {
+ ret.radio_Cause_Value := int2oct(enum2int(valueof(cause)), 1);
+ } else {
+ ret.radio_Cause_Value := ?
+ }
+ return ret;
+ }
+
+ /* 10.3.5 */
+ template (value) PDU_BSSGP
+ ts_BSSGP_RADIO_STATUS(template (omit) GprsTlli tlli, template (value) BssgpRadioCause cause,
+ template (omit) GsmTmsi tmsi := omit,
+ template (omit) hexstring imsi := omit) := {
+ pDU_BSSGP_RADIO_STATUS := {
+ bssgpPduType := '0a'O,
+ tLLI := f_ts_BSSGP_TLLI(tlli),
+ tMSI := f_ts_BSSGP_TMSI(tmsi),
+ iMSI := f_ts_BSSGP_IMSI(imsi),
+ radio_Cause := ts_BSSGP_RADIO_CAUSE(cause)
+ }
+ }
+ template (present) PDU_BSSGP
+ tr_BSSGP_RADIO_STATUS(template GprsTlli tlli, template (present) BssgpRadioCause cause,
+ template GsmTmsi tmsi := *, template hexstring imsi := *) := {
+ pDU_BSSGP_RADIO_STATUS := {
+ bssgpPduType := '0a'O,
+ tLLI := f_tr_BSSGP_TLLI(tlli),
+ tMSI := f_tr_BSSGP_TMSI(tmsi),
+ iMSI := f_tr_BSSGP_IMSI(imsi),
+ radio_Cause := tr_BSSGP_RADIO_CAUSE(cause)
+ }
+ }
+
+ /* 10.4.15 */
+ template (value) PDU_BSSGP
+ ts_BSSGP_INVOKE_TRACE(OCT1 eq_trace, OCT2 ref) := {
+ pDU_BSSGP_SGSN_INVOKE_TRACE := {
+ bssgpPduType := '40'O,
+ traceType := {
+ iEI := '22'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ equipment_Trace := eq_trace
+ },
+ traceReference := {
+ iEI := '21'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ trace_Reference := ref
+ },
+ triggerId := omit,
+ mobileId := omit,
+ omcId := omit,
+ transactionId := omit
+ }
+ }
+ template (present) PDU_BSSGP
+ tr_BSSGP_INVOKE_TRACE(template (present) OCT1 eq_trace, template (present) OCT2 ref) := {
+ pDU_BSSGP_SGSN_INVOKE_TRACE := {
+ bssgpPduType := '40'O,
+ traceType := {
+ iEI := '22'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ equipment_Trace := eq_trace
+ },
+ traceReference := {
+ iEI := '21'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ trace_Reference := ref
+ },
+ triggerId := *,
+ mobileId := *,
+ omcId := *,
+ transactionId := *
+ }
+ }
+
+ /* 10.4.36 */
+ template (value) PDU_BSSGP
+ ts_OVERLOAD(template (value) BIT1 priority_class) := {
+ pDU_BSSGP_OVERLOAD := {
+ bssgpPduType := '42'O,
+ priority_Class_Indicator := {
+ iEI := '8f'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ priority_Class_Indicator_Value := priority_class,
+ spare := '0000000'B
+ }
+ }
+ }
+ template (present) PDU_BSSGP
+ tr_OVERLOAD(template (present) BIT1 priority_class) := {
+ pDU_BSSGP_OVERLOAD := {
+ bssgpPduType := '42'O,
+ priority_Class_Indicator := {
+ iEI := '8f'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ priority_Class_Indicator_Value := priority_class,
+ spare := '0000000'B
+ }
}
}
+ /* 3GPP TS 48.018 11.3.61 */
+ const OCT1 RIM_APP_ID_NACC := '01'O;
+ const OCT1 RIM_APP_ID_SI3 := '02'O;
+ const OCT1 RIM_APP_ID_MBMS_DATA_CH := '03'O;
+ const OCT1 RIM_APP_ID_SON_TRANSF := '04'O;
+ const OCT1 RIM_APP_ID_UTRA_SI := '05'O;
+ template (value) RIM_Application_Identity ts_RIM_Application_Identity(OCT1 app_id) := {
+ iEI := '4B'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rIMApplicationIdentity := app_id
+ }
+ template RIM_Application_Identity tr_RIM_Application_Identity(template OCT1 app_id := ?) := {
+ iEI := '4B'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rIMApplicationIdentity := app_id
+ }
+
+ /* 3GPP TS 48.018 11.3.62 */
+ template (value) RIM_Sequence_Number ts_RIM_Sequence_Number(integer seq) := {
+ iEI := '4C'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 4
+ },
+ rIMSequenceNumber := int2oct(seq, 4)
+ }
+ function tr_RIM_Sequence_Number(template integer seq := ?) return template RIM_Sequence_Number {
+ var template RIM_Sequence_Number ret;
+ ret.iEI := '4C'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := 4 };
+ if (istemplatekind(seq, "*")) {
+ ret.rIMSequenceNumber := *;
+ } else if (istemplatekind(seq, "?")) {
+ ret.rIMSequenceNumber := ?;
+ } else {
+ ret.rIMSequenceNumber := int2oct(valueof(seq), 4);
+ }
+ return ret;
+ }
+
+ /* 3GPP TS 48.018 11.3.62a.1 */
+ template (value) RAN_Information_Request_RIM_Container
+ ts_RAN_Information_Request_RIM_Container(template (value) RIM_Application_Identity app_id,
+ template (value) RIM_Sequence_Number seq,
+ template (value) RIM_PDU_Indications ind,
+ template (omit) RIM_Protocol_Version_Number ver := omit,
+ template (omit) RAN_Information_Request_Application_Container app_cont := omit,
+ template (omit) SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '57'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Container := app_cont,
+ sON_Transfer_Application_Identity_TLV := son_app_id
+ }
+ template RAN_Information_Request_RIM_Container
+ tr_RAN_Information_Request_RIM_Container(template RIM_Application_Identity app_id := ?,
+ template RIM_Sequence_Number seq := ?,
+ template RIM_PDU_Indications ind := ?,
+ template RIM_Protocol_Version_Number ver := *,
+ template RAN_Information_Request_Application_Container app_cont := *,
+ template SON_Transfer_Application_Identity_TLV son_app_id := *) := {
+ iEI := '57'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Container := app_cont,
+ sON_Transfer_Application_Identity_TLV := son_app_id
+ }
+
+
+ /* 3GPP TS 48.018 11.3.62a.2 */
+ template (value) RAN_Information_RIM_Container
+ ts_RAN_Information_RIM_Container(template (value) RIM_Application_Identity app_id,
+ template (value) RIM_Sequence_Number seq,
+ template (value) RIM_PDU_Indications ind,
+ template (omit) RIM_Protocol_Version_Number ver := omit,
+ template (omit) ApplContainer_or_ApplErrContainer app_cont_or_app_err := omit,
+ template (omit) SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+
+ iEI := '58'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ applContainer_or_ApplErrContainer := app_cont_or_app_err,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+ template RAN_Information_RIM_Container
+ tr_RAN_Information_RIM_Container(template RIM_Application_Identity app_id := ?,
+ template RIM_Sequence_Number seq := ?,
+ template RIM_PDU_Indications ind := ?,
+ template RIM_Protocol_Version_Number ver := omit,
+ template ApplContainer_or_ApplErrContainer app_cont_or_app_err := omit,
+ template SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+
+ iEI := '58'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ applContainer_or_ApplErrContainer := app_cont_or_app_err,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+ template (value) ApplContainer_or_ApplErrContainer
+ tsu_ApplContainer_or_ApplErrContainer_NACC(template (value) ApplContainer_or_ApplErrContainer_NACC cont) := {
+ nacc := cont
+ }
+ template ApplContainer_or_ApplErrContainer
+ tru_ApplContainer_or_ApplErrContainer_NACC(template ApplContainer_or_ApplErrContainer_NACC cont := ?) := {
+ nacc := cont
+ }
+ template (value) ApplContainer_or_ApplErrContainer
+ tsu_ApplContainer_or_ApplErrContainer_SI3(template (value) ApplContainer_or_ApplErrContainer_SI3 cont) := {
+ si3 := cont
+ }
+ template (value) ApplContainer_or_ApplErrContainer
+ tsu_ApplContainer_or_ApplErrContainer_MBMS_data_channel(template (value) ApplContainer_or_ApplErrContainer_MBMS_data_channel cont) := {
+ mBMS_data_channel := cont
+ }
+ template (value) ApplContainer_or_ApplErrContainer_NACC
+ tsu_ApplContainer_NACC(template (value) BssgpCellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ application_Container := ts_RAN_Information_Application_Container_NACC(cid, psi_type, si_psi_num, si_psi)
+ }
+ template ApplContainer_or_ApplErrContainer_NACC
+ tru_ApplContainer_NACC(template BssgpCellId cid := ?, template boolean psi_type := ?, template integer si_psi_num := ?, template octetstring si_psi := ?) := {
+ application_Container := tr_RAN_Information_Application_Container_NACC(cid, psi_type, si_psi_num, si_psi)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_NACC
+ tsu_ApplErrContainer_NACC(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_NACC app_cont) := {
+ application_Error_Container := ts_Application_Error_Container_NACC(cid, cause, app_cont)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_SI3
+ tsu_ApplContainer_SI3(template (value) BssgpCellId cid, template (value) SI3 si3) := {
+ application_Container := ts_RAN_Information_Application_Container_SI3(cid, si3)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_SI3
+ tsu_ApplErrContainer_SI3(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_SI3 app_cont) := {
+ application_Error_Container := ts_Application_Error_Container_SI3(cid, cause, app_cont)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_MBMS_data_channel
+ tsu_ApplContainer_MBMS_data_channel(template (value) BssgpCellId cid, octetstring data_ch_report) := {
+ application_Container := ts_RAN_Information_Application_Container_MBMS_data_channel(cid, data_ch_report)
+ }
+ template (value) ApplContainer_or_ApplErrContainer_MBMS_data_channel
+ tsu_ApplErrContainer_MBMS_data_channel(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_MBMS_data_channel app_cont) := {
+ application_Error_Container := ts_Application_Error_Container_MBMS_data_channel(cid, cause, app_cont)
+ }
+
+ /* 3GPP TS 48.018 11.3.62a.3 */
+ template (value) RAN_Information_Ack_RIM_Container
+ ts_RAN_Information_Ack_RIM_Container(template (value) RIM_Application_Identity app_id,
+ template (value) RIM_Sequence_Number seq,
+ template (omit) RIM_Protocol_Version_Number ver := omit,
+ template (omit) SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '5A'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_Protocol_Version_Number := ver,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+ template RAN_Information_Ack_RIM_Container
+ tr_RAN_Information_Ack_RIM_Container(template RIM_Application_Identity app_id := ?,
+ template RIM_Sequence_Number seq := ?,
+ template RIM_Protocol_Version_Number ver := omit,
+ template SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '5A'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_Protocol_Version_Number := ver,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+
+ /* 3GPP TS 48.018 11.3.62a.4 */
+ template (value) RAN_Information_Error_RIM_Container
+ ts_RAN_Information_Error_RIM_Container(template (value) RIM_Application_Identity app_id,
+ template (value) Cause_BSSGP cause,
+ template (omit) RIM_Protocol_Version_Number ver := omit,
+ PDU_BSSGP pdu,
+ template (omit) SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '5B'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_cause := cause,
+ rIM_Protocol_Version_Number := ver,
+ pDU_in_Error:= {
+ iEI := '15'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ erroneous_BSSGP_PDU := enc_PDU_BSSGP(pdu)
+ },
+ sON_Transfer_Application_Identity := son_app_id
+ }
+ template RAN_Information_Error_RIM_Container
+ tr_RAN_Information_Error_RIM_Container(template RIM_Application_Identity app_id := ?,
+ template Cause_BSSGP cause := ?,
+ template RIM_Protocol_Version_Number ver := omit,
+ template octetstring pdu := ?,
+ template SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '5B'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_cause := cause,
+ rIM_Protocol_Version_Number := ver,
+ pDU_in_Error:= {
+ iEI := '15'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ erroneous_BSSGP_PDU := pdu
+ },
+ sON_Transfer_Application_Identity := son_app_id
+ }
+
+ /* 3GPP TS 48.018 11.3.62a.5 */
+ template (value) RAN_Information_Application_Error_RIM_Container
+ ts_RAN_Information_Application_Error_RIM_Container(template (value) RIM_Application_Identity app_id,
+ template (value) RIM_Sequence_Number seq,
+ template (value) RIM_PDU_Indications ind,
+ template (omit) RIM_Protocol_Version_Number ver := omit,
+ template (value) Application_Error_Container cont,
+ template (omit) SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '59'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Error_Container := cont,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+ template RAN_Information_Application_Error_RIM_Container
+ tr_RAN_Information_Application_Error_RIM_Container(template RIM_Application_Identity app_id := ?,
+ template RIM_Sequence_Number seq := ?,
+ template RIM_PDU_Indications ind := ?,
+ template RIM_Protocol_Version_Number ver := omit,
+ template Application_Error_Container cont := ?,
+ template SON_Transfer_Application_Identity_TLV son_app_id := omit) := {
+ iEI := '59'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIM_Application_Identity := app_id,
+ rIM_Sequence_Number := seq,
+ rIM_PDU_Indications := ind,
+ rIM_Protocol_Version_Number := ver,
+ application_Error_Container := cont,
+ sON_Transfer_Application_Identity := son_app_id
+ }
+
+
+ /* 3GPP TS 48.018 11.3.63.1 */
+ template (value) RAN_Information_Request_Application_Container
+ tsu_RAN_Information_Request_Application_Container_NACC(template (value) BssgpCellId cid) := {
+ nacc := ts_RAN_Information_Request_Application_Container_NACC(cid)
+ }
+ template (value) RAN_Information_Request_Application_Container
+ tsu_RAN_Information_Request_Application_Container_SI3(template (value) BssgpCellId cid) := {
+ si3 := ts_RAN_Information_Request_Application_Container_SI3(cid)
+ }
+ template (value) RAN_Information_Request_Application_Container
+ tsu_RAN_Information_Request_Application_Container_MBMS_data_channel(template (value) BssgpCellId cid) := {
+ mBMS_data_channel := ts_RAN_Information_Request_Application_Container_MBMS_data_channel(cid)
+ }
+
+ /* NOTE: The type description of reporting_Cell_Identifier in chapter 11.3.63.1, version V10.6.0 (2012-07) of
+ * 3GPP TS 48.018 clearly states: "Reporting Cell Identifier: This field is encoded as the Cell Identifier
+ * defined in sub-clause 11.3.9". However this seems to be an error in the specification, because the
+ * specifiction in Table 11.3.63.1.1 already has a length field an an IEI defined. Keeping the IEI and lenght
+ * of the BSSGP cell identifier in addition would no make sense. Also in the chapters below the specifiction
+ * of the IEs are similar and there it says "Reporting Cell Identifier: This field is encoded as the value
+ * part of the Cell Identifier IE defined in sub-clause 11.3.9, not including IEI and Length Indicator.",
+ * which actually makes sense. */
+
+ /* 3GPP TS 48.018 11.3.63.1.1 */
+ template (value) RAN_Information_Request_Application_Container_NACC
+ ts_RAN_Information_Request_Application_Container_NACC(template (value) BssgpCellId cid) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid)
+ }
+ template RAN_Information_Request_Application_Container_NACC
+ tr_RAN_Information_Request_Application_Container_NACC(template BssgpCellId cid := ?) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ reporting_Cell_Identifier := tr_Cell_Identifier_V(cid)
+ }
+
+ /* 3GPP TS 48.018 11.3.63.1.2 */
+ template (value) RAN_Information_Request_Application_Container_SI3
+ ts_RAN_Information_Request_Application_Container_SI3(template (value) BssgpCellId cid) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid)
+ }
+
+ /* 3GPP TS 48.018 11.3.63.1.3 */
+ template (value) RAN_Information_Request_Application_Container_MBMS_data_channel
+ ts_RAN_Information_Request_Application_Container_MBMS_data_channel(template (value) BssgpCellId cid) := {
+ iEI := '4D'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid)
+ }
+
+ /* 3GPP TS 48.018 11.3.63.2.1 */
+ template (value) RAN_Information_Application_Container_NACC
+ ts_RAN_Information_Application_Container_NACC(template (value) BssgpCellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ iEI := '4E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid),
+ typeBit := bool2bit(psi_type),
+ number_of_SI_PSI := int2bit(si_psi_num, 7),
+ sI_PSI := si_psi
+ }
+ function tr_RAN_Information_Application_Container_NACC(template BssgpCellId cid := ?, template boolean psi_type := ?,
+ template integer si_psi_num := ?, template octetstring si_psi := ?)
+ return template RAN_Information_Application_Container_NACC {
+ var template RAN_Information_Application_Container_NACC ret;
+ ret.iEI := '4E'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := ? };
+ ret.reporting_Cell_Identifier := tr_Cell_Identifier_V(cid);
+ if (istemplatekind(psi_type, "*")) {
+ ret.typeBit := *;
+ } else if (istemplatekind(psi_type, "?")) {
+ ret.typeBit := ?;
+ } else {
+ ret.typeBit := bool2bit(valueof(psi_type));
+ }
+ if (istemplatekind(si_psi_num, "*")) {
+ ret.number_of_SI_PSI := *;
+ } else if (istemplatekind(si_psi_num, "?")) {
+ ret.number_of_SI_PSI := ?;
+ } else {
+ ret.number_of_SI_PSI := int2bit(valueof(si_psi_num), 7);
+ }
+ ret.sI_PSI := si_psi;
+ return ret;
+ }
+
+ /* 3GPP TS 48.018 11.3.63.2.2 */
+ template (value) RAN_Information_Application_Container_SI3
+ ts_RAN_Information_Application_Container_SI3(template (value) BssgpCellId cid, template (value) SI3 si3) := {
+ iEI := '4E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid),
+ sI3 := si3
+ }
+
+ /* 3GPP TS 48.018 11.3.63.2.3 */
+ template (value) RAN_Information_Application_Container_MBMS_data_channel
+ ts_RAN_Information_Application_Container_MBMS_data_channel(template (value) BssgpCellId cid, octetstring data_ch_report) := {
+ iEI := '4E'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ reporting_Cell_Identifier := ts_Cell_Identifier_V(cid),
+ mBMS_data_channel_report := data_ch_report
+ }
+
+
+ /* 3GPP TS 48.018 11.3.64 */
+ template (value) Application_Error_Container
+ tsu_Application_Error_Container_NACC(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_NACC app_cont) := {
+ nacc := ts_Application_Error_Container_NACC(cid, cause, app_cont)
+ }
+ template Application_Error_Container
+ rsu_Application_Error_Container_NACC(template BssgpCellId cid := ?,
+ template integer cause := ?,
+ template Application_Container_IE_NACC app_cont := ?) := {
+ nacc := tr_Application_Error_Container_NACC(cid, cause, app_cont)
+ }
+ template (value) Application_Error_Container
+ tsu_Application_Error_Container_SI3(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_SI3 app_cont) := {
+ si3 := ts_Application_Error_Container_SI3(cid, cause, app_cont)
+ }
+ template (value) Application_Error_Container
+ tsu_Application_Error_Container_MBMS_data_channel(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_MBMS_data_channel app_cont) := {
+ mBMS_data_channel := ts_Application_Error_Container_MBMS_data_channel(cid, cause, app_cont)
+ }
+
+ /* 3GPP TS 48.018 11.3.64.1 */
+ template (value) Application_Error_Container_NACC
+ ts_Application_Error_Container_NACC(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_NACC app_cont) := {
+ iEI := '56'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ nACC_cause := int2oct(cause, 1),
+ erroneousApplicationContainer := app_cont
+ }
+ function tr_Application_Error_Container_NACC(template BssgpCellId cid := ?,
+ template integer cause := ?,
+ template Application_Container_IE_NACC app_cont := ?)
+ return template Application_Error_Container_NACC {
+ var template Application_Error_Container_NACC ret;
+ ret.iEI := '56'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := ? };
+ ret.erroneousApplicationContainer := app_cont;
+ if (istemplatekind(cause, "*")) {
+ ret.nACC_cause := *;
+ } else if (istemplatekind(cause, "?")) {
+ ret.nACC_cause := ?;
+ } else {
+ ret.nACC_cause := int2oct(valueof(cause), 1);
+ }
+ return ret;
+ }
+
+ template (value) Application_Container_IE_NACC
+ tsu_Application_Container_IE_NACC_req(template (value) BssgpCellId cid) := {
+ rAN_Information_Request_Application_Container := ts_RAN_Information_Request_Application_Container_NACC(cid)
+ }
+ template Application_Container_IE_NACC
+ rsu_Application_Container_IE_NACC_req(template BssgpCellId cid := ?) := {
+ rAN_Information_Request_Application_Container := tr_RAN_Information_Request_Application_Container_NACC(cid)
+ }
+ template (value) Application_Container_IE_NACC
+ tsu_Application_Container_IE_NACC(template (value) BssgpCellId cid, boolean psi_type, integer si_psi_num, octetstring si_psi) := {
+ rAN_Information_Application_Container := ts_RAN_Information_Application_Container_NACC(cid, psi_type, si_psi_num, si_psi)
+ }
+
+ /* 3GPP TS 48.018 11.3.64.2 */
+ template (value) Application_Error_Container_SI3
+ ts_Application_Error_Container_SI3(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_SI3 app_cont) := {
+ iEI := '56'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ sI3_cause := int2oct(cause, 1),
+ erroneousApplicationContainer := app_cont
+ }
+ template (value) Application_Container_IE_SI3
+ tsu_Application_Container_IE_SI3_req(template (value) BssgpCellId cid) := {
+ rAN_Information_Request_Application_Container := ts_RAN_Information_Request_Application_Container_SI3(cid)
+ }
+ template (value) Application_Container_IE_SI3
+ tsu_Application_Container_IE_SI3(template (value) BssgpCellId cid, template (value) SI3 si3) := {
+ rAN_Information_Application_Container := ts_RAN_Information_Application_Container_SI3(cid, si3)
+ }
+
+ /* 3GPP TS 48.018 11.3.64.3 */
+ template (value) Application_Error_Container_MBMS_data_channel
+ ts_Application_Error_Container_MBMS_data_channel(template (value) BssgpCellId cid,
+ integer cause,
+ template (value) Application_Container_IE_MBMS_data_channel app_cont) := {
+ iEI := '56'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ mBMS_data_channel_cause := int2oct(cause, 1),
+ erroneousApplicationContainer := app_cont
+ }
+ template (value) Application_Container_IE_MBMS_data_channel
+ tsu_Application_Container_IE_MBMS_data_channel_req(template (value) BssgpCellId cid) := {
+ rAN_Information_Request_Application_Container := ts_RAN_Information_Request_Application_Container_MBMS_data_channel(cid)
+ }
+ template (value) Application_Container_IE_MBMS_data_channel
+ tsu_Application_Container_IE_MBMS_data_channel(template (value) BssgpCellId cid, octetstring data_ch_report) := {
+ rAN_Information_Application_Container := ts_RAN_Information_Application_Container_MBMS_data_channel(cid, data_ch_report)
+ }
+
+
+ /* 3GPP TS 44.018 10.5.1.3 -> 3GPP TS 24.008 10.5.1.3 */
+ function t_LocationAreaIdentification(template BssgpCellId cid) return template BSSGP_Types.LocationAreaIdentification {
+ var template BSSGP_Types.LocationAreaIdentification ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ lac := ?
+ }
+ if (istemplatekind(cid, "omit")) {
+ return omit;
+ } else if (istemplatekind(cid, "*")) {
+ return *;
+ } else if (istemplatekind(cid, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ if (isvalue(cid.ra_id.lai.lac)) {
+ ret.lac := f_oct_or_wc(cid.ra_id.lai.lac, 2);
+ }
+ }
+ return ret;
+ }
+ /* 3GPP TS 44.018 10.5.2.11 */
+ template (value) ControlChannelDescription ts_ControlChannelDescription(integer ccch_conf,
+ integer bs_ag_blks_res,
+ boolean att,
+ boolean mscr,
+ integer bs_pa_mfrms,
+ BIT2 cbq3,
+ integer t3212) := {
+ cCCH_Conf := int2bit(ccch_conf, 3),
+ bS_AG_BLKS_RES := int2bit(bs_ag_blks_res, 3),
+ aTT := bool2bit(att),
+ mSCR := bool2bit(mscr),
+ bS_PA_MFRMS := int2bit(bs_pa_mfrms, 3),
+ spare1 := '00'B,
+ cBQ3 := cbq3,
+ spare2 := '0'B,
+ t3212 := int2oct(t3212, 1)
+ }
+
+ /* 3GPP TS 44.018 10.5.2.3 */
+ template (value) CellOptions ts_CellOptions(integer radio_link_timeout,
+ BIT3 dtx,
+ boolean pwrc) := {
+ radioLinkTimeout := int2bit(radio_link_timeout, 4),
+ dTX1 := dtx[0] & dtx[1],
+ pWRC := bool2bit(pwrc),
+ dtx2 := dtx[2]
+ }
+
+ /* 3GPP TS 44.018 10.5.2.4 */
+ template (value) CellSelectionParameters ts_CellSelectionParameters(integer ms_txpwr_max_cch,
+ integer cell_reselection_hysteresis,
+ integer rxlev_access_min,
+ boolean neci,
+ boolean acs) := {
+ mS_TXPWR_MAX_CCH := int2bit(ms_txpwr_max_cch, 5),
+ cellReselectHysterisis := int2bit(cell_reselection_hysteresis, 3),
+ rXLEV_Access_Min := int2bit(rxlev_access_min, 6),
+ nECI := bool2bit(neci),
+ aCS := bool2bit(acs)
+ }
+
+ /* 3GPP TS 44.018 10.5.2.29 */
+ template (value) RACHControlParameters ts_RACHControlParameters(boolean re,
+ boolean cell_barr_access,
+ integer tx_integer,
+ integer max_retrans,
+ integer ac_15_to_8,
+ integer ac_7_to_0) := {
+ rE := bool2bit(re),
+ cellBarrAccess := bool2bit(cell_barr_access),
+ tX_Integer := int2bit(tx_integer, 4),
+ maxRetrans := int2bit(max_retrans, 2),
+ aC_15_to_8 := int2oct(ac_15_to_8, 1),
+ aC_7_to_0 := int2oct(ac_7_to_0, 1)
+ }
+
+ /* 3GPP TS 44.018 9.1.35 */
+ template (value) SI3 ts_SI3(integer cell_id,
+ template (value) BSSGP_Types.LocationAreaIdentification lai,
+ template (value) ControlChannelDescription cch_descr,
+ template (value) CellOptions cell_opt,
+ template (value) CellSelectionParameters cell_sel_par,
+ template (value) RACHControlParameters rach_ctrl_par,
+ OCT4 rest_octets) := {
+ sI3MessageType := '1B'O,
+ cellIdentity := int2oct(cell_id, 2),
+ locationAreaIdentification := lai,
+ controlChannelDescription := cch_descr,
+ cellOptions := cell_opt,
+ cellSelectionParameters := cell_sel_par,
+ rACHControlParameters := rach_ctrl_par,
+ sI3RestOctets := rest_octets
+ }
+
+
+ /* 3GPP TS 48.018 11.3.65 */
+ const BIT3 RIM_PDU_TYPE_STOP := '000'B;
+ const BIT3 RIM_PDU_TYPE_SING_REP := '001'B;
+ const BIT3 RIM_PDU_TYPE_MULT_REP := '010'B;
+ template (value) RIM_PDU_Indications ts_RIM_PDU_Indications(boolean ack, BIT3 type_ext) := {
+ iEI := '4F'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ ack := bool2bit(ack),
+ pDU_Type_Extension := type_ext,
+ reserved := '0000'B
+ }
+ function tr_RIM_PDU_Indications(template boolean ack := ?, template BIT3 type_ext := ?) return template RIM_PDU_Indications {
+ var template RIM_PDU_Indications ret;
+ ret.iEI := '4F'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := 1 };
+ if (istemplatekind(ack, "*")) {
+ ret.ack := *;
+ } else if (istemplatekind(ack, "?")) {
+ ret.ack := ?;
+ } else {
+ ret.ack := bool2bit(valueof(ack));
+ }
+ if (istemplatekind(type_ext, "*")) {
+ ret.pDU_Type_Extension := *;
+ } else if (istemplatekind(type_ext, "?")) {
+ ret.pDU_Type_Extension := ?;
+ } else {
+ ret.pDU_Type_Extension := valueof(type_ext);
+ }
+ ret.reserved := '0000'B;
+ return ret;
+ }
+
+ /* 3GPP TS 48.018 11.3.67 */
+ template (value) RIM_Protocol_Version_Number ts_RIM_Protocol_Version_Number(integer ver) := {
+ iEI := '55'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 1
+ },
+ rIMProtocolVersionNumber := int2oct(ver, 1)
+ }
+ function tr_RIM_Protocol_Version_Number(template integer ver := ?) return template RIM_Protocol_Version_Number {
+ var template RIM_Protocol_Version_Number ret;
+ ret.iEI := '55'O;
+ ret.ext := '1'B;
+ ret.lengthIndicator := { length1 := 1 };
+ if (istemplatekind(ver, "*")) {
+ ret.rIMProtocolVersionNumber := *;
+ } else if (istemplatekind(ver, "?")) {
+ ret.rIMProtocolVersionNumber := ?;
+ } else {
+ ret.rIMProtocolVersionNumber := int2oct(valueof(ver), 1);
+ }
+ return ret;
+ }
+
+ /* 3GPP TS 48.018 11.3.70 */
+ const HEX1 RIM_ADDR_GERAN_CELL_ID := '0'H;
+ const HEX1 RIM_ADDR_UTRAN_RNC_ID := '1'H;
+ const HEX1 RIM_ADDR_EUTRAN_NODEB_ID := '2'H;
+ const HEX1 RIM_ADDR_EHRPD_SECTOR_ID := '3'H;
+ template (value) RIM_Routing_Information ts_RIM_Routing_Information(HEX1 addr_discr, template (value) RIM_Routing_Address addr) := {
+ iEI := '54'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ rIMRoutingAddressDiscriminator := addr_discr,
+ spare := '0'H,
+ rIM_Routing_Address := addr
+ }
+ template RIM_Routing_Information tr_RIM_Routing_Information(template HEX1 addr_discr := ?, template RIM_Routing_Address addr := ?) := {
+ iEI := '54'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := ?
+ },
+ rIMRoutingAddressDiscriminator := addr_discr,
+ spare := '0'H,
+ rIM_Routing_Address := addr
+ }
+
+ template RIM_Routing_Address t_RIM_Routing_Address_cid(template BssgpCellId cid := ?) := {
+ cell_Identifier := tr_Cell_Identifier_V(cid)
+ }
+ template RIM_Routing_Address t_RIM_Routing_Address_rncid(template BssgpCellId cid := ?, template integer rnc_id := ?) := {
+ globalRNCID := t_GlobalRNC_ID_BSSGP(cid, rnc_id)
+ }
+ template RIM_Routing_Address t_RIM_Routing_Address_enbid(template BssgpCellId cid := ?, template integer tac := ?, template octetstring gnbid := ?) := {
+ eNB_Identifier := t_ENB_Identifier_V(cid, tac, gnbid)
+ }
+ template RIM_Routing_Address t_RIM_Routing_Address_sector(template octetstring sector := ?) := {
+ eHRPD_SectorID := sector
+ }
+
+ function tr_Cell_Identifier_V(template BssgpCellId cid) return template Cell_Identifier_V {
+ var template Cell_Identifier_V ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ lac := ?,
+ rac := ?,
+ cI_value := ?
+ }
+ if (istemplatekind(cid, "omit")) {
+ return omit;
+ } else if (istemplatekind(cid, "*")) {
+ return *;
+ } else if (istemplatekind(cid, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ if (isvalue(cid.ra_id.lai.lac)) {
+ ret.lac := f_oct_or_wc(cid.ra_id.lai.lac, 2);
+ }
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id)) {
+ ret.rac := f_oct_or_wc(cid.ra_id.rac, 1);
+ }
+ if (isvalue(cid)) {
+ ret.cI_value := f_oct_or_wc(cid.cell_id, 2);
+ }
+ return ret;
+ }
+ template (value) Cell_Identifier_V ts_Cell_Identifier_V(template (value) BssgpCellId cid) := {
+ mccDigit1 := cid.ra_id.lai.mcc_mnc[0],
+ mccDigit2 := cid.ra_id.lai.mcc_mnc[1],
+ mccDigit3 := cid.ra_id.lai.mcc_mnc[2],
+ mncDigit3 := cid.ra_id.lai.mcc_mnc[3],
+ mncDigit1 := cid.ra_id.lai.mcc_mnc[4],
+ mncDigit2 := cid.ra_id.lai.mcc_mnc[5],
+ lac := int2oct(valueof(cid.ra_id.lai.lac), 2),
+ rac := int2oct(valueof(cid.ra_id.rac), 1),
+ cI_value := int2oct(valueof(cid.cell_id), 2)
+ }
+ function t_GlobalRNC_ID_BSSGP(template BssgpCellId cid, template integer rnc_id) return template GlobalRNC_ID_BSSGP {
+ var template GlobalRNC_ID_BSSGP ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ lac := ?,
+ rac := ?,
+ spare := ?,
+ rNC_ID := ?
+ }
+ if (istemplatekind(cid, "omit") and istemplatekind(rnc_id, "omit")) {
+ return omit;
+ } else if (istemplatekind(cid, "*") and istemplatekind(rnc_id, "*")) {
+ return *;
+ } else if (istemplatekind(cid, "?") and istemplatekind(rnc_id, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ if (isvalue(cid.ra_id.lai.lac)) {
+ ret.lac := f_oct_or_wc(cid.ra_id.lai.lac, 2);
+ }
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id)) {
+ ret.rac := f_oct_or_wc(cid.ra_id.rac, 1);
+ }
+ if (isvalue(rnc_id)) {
+ ret.spare := '0'H;
+ ret.rNC_ID := rnc_id;
+ }
+
+ return ret;
+ }
+
+ function t_ENB_Identifier_V(template BssgpCellId cid, template integer tac, template octetstring gnbid) return template ENB_Identifier_V {
+ var template ENB_Identifier_V ret := {
+ mccDigit1 := ?,
+ mccDigit2 := ?,
+ mccDigit3 := ?,
+ mncDigit3 := ?,
+ mncDigit1 := ?,
+ mncDigit2 := ?,
+ tac := ?,
+ globaleNBID := ?
+ }
+ if (istemplatekind(cid, "omit") and istemplatekind(tac, "omit") and istemplatekind(gnbid, "omit")) {
+ return omit;
+ } else if (istemplatekind(cid, "*") and istemplatekind(tac, "*") and istemplatekind(gnbid, "*")) {
+ return *;
+ } else if (istemplatekind(cid, "?") and istemplatekind(tac, "?") and istemplatekind(gnbid, "?")) {
+ return ?;
+ }
+ if (isvalue(cid) and isvalue(cid.ra_id) and isvalue(cid.ra_id.lai)) {
+ if (isvalue(cid.ra_id.lai.mcc_mnc)) {
+ ret.mccDigit1 := cid.ra_id.lai.mcc_mnc[0];
+ ret.mccDigit2 := cid.ra_id.lai.mcc_mnc[1];
+ ret.mccDigit3 := cid.ra_id.lai.mcc_mnc[2];
+ ret.mncDigit3 := cid.ra_id.lai.mcc_mnc[3];
+ ret.mncDigit1 := cid.ra_id.lai.mcc_mnc[4];
+ ret.mncDigit2 := cid.ra_id.lai.mcc_mnc[5];
+ }
+ }
+ if (isvalue(tac)) {
+ ret.tac := int2oct(valueof(tac), 2);
+ }
+ if (isvalue(gnbid)) {
+ ret.globaleNBID := gnbid;
+ }
+
+ return ret;
+ }
+
+ /* 3GPP TS 48.018 11.3.108 */
+ template (value) SON_Transfer_Application_Identity_TLV ts_SON_Transfer_Application_Identity_TLV(template (value) octetstring app_id) := {
+ iEI := '84'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 0 /* overwritten */
+ },
+ sON_Transfer_Application_Identity := app_id
+ }
+
+
+ /* 3GPP TS 48.018 10.6.1 */
+ template (value) PDU_BSSGP
+ ts_RAN_INFORMATION_REQUEST(template (value) RIM_Routing_Information dst,
+ template (value) RIM_Routing_Information src,
+ template (value) RAN_Information_Request_RIM_Container cont) := {
+ pDU_BSSGP_RAN_INFORMATION_REQUEST := {
+ bssgpPduType := '71'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+ template PDU_BSSGP
+ tr_RAN_INFORMATION_REQUEST(template RIM_Routing_Information dst := ?,
+ template RIM_Routing_Information src := ?,
+ template RAN_Information_Request_RIM_Container cont := ?) := {
+ pDU_BSSGP_RAN_INFORMATION_REQUEST := {
+ bssgpPduType := '71'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+
+ /* 3GPP TS 48.018 10.6.2 */
+ template (value) PDU_BSSGP
+ ts_PDU_BSSGP_RAN_INFORMATION(template (value) RIM_Routing_Information dst,
+ template (value) RIM_Routing_Information src,
+ template (value) RAN_Information_RIM_Container cont) := {
+ pDU_BSSGP_RAN_INFORMATION := {
+ bssgpPduType := '70'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+ template PDU_BSSGP
+ tr_PDU_BSSGP_RAN_INFORMATION(template RIM_Routing_Information dst := ?,
+ template RIM_Routing_Information src := ?,
+ template RAN_Information_RIM_Container cont := ?) := {
+ pDU_BSSGP_RAN_INFORMATION := {
+ bssgpPduType := '70'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+
+ /* 3GPP TS 48.018 10.6.3 */
+ template (value) PDU_BSSGP
+ ts_PDU_BSSGP_RAN_INFORMATION_ACK(template (value) RIM_Routing_Information dst,
+ template (value) RIM_Routing_Information src,
+ template (value) RAN_Information_Ack_RIM_Container cont) := {
+ pDU_BSSGP_RAN_INFORMATION_ACK := {
+ bssgpPduType := '72'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+ template PDU_BSSGP
+ tr_PDU_BSSGP_RAN_INFORMATION_ACK(template RIM_Routing_Information dst := ?,
+ template RIM_Routing_Information src := ?,
+ template RAN_Information_Ack_RIM_Container cont := ?) := {
+ pDU_BSSGP_RAN_INFORMATION_ACK := {
+ bssgpPduType := '72'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+
+ /* 3GPP TS 48.018 10.6.4 */
+ template (value) PDU_BSSGP
+ ts_PDU_BSSGP_RAN_INFORMATION_ERROR(template (value) RIM_Routing_Information dst,
+ template (value) RIM_Routing_Information src,
+ template (value) RAN_Information_Error_RIM_Container cont) := {
+ pDU_BSSGP_RAN_INFORMATION_ERROR := {
+ bssgpPduType := '73'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+ template PDU_BSSGP
+ tr_PDU_BSSGP_RAN_INFORMATION_ERROR(template RIM_Routing_Information dst := ?,
+ template RIM_Routing_Information src := ?,
+ template RAN_Information_Error_RIM_Container cont := ?) := {
+ pDU_BSSGP_RAN_INFORMATION_ERROR := {
+ bssgpPduType := '73'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+
+ /* 3GPP TS 48.018 10.6.5 */
+ template (value) PDU_BSSGP
+ ts_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(template (value) RIM_Routing_Information dst,
+ template (value) RIM_Routing_Information src,
+ template (value) RAN_Information_Application_Error_RIM_Container cont) := {
+ pDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR := {
+ bssgpPduType := '74'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+ template PDU_BSSGP
+ tr_PDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR(template RIM_Routing_Information dst := ?,
+ template RIM_Routing_Information src := ?,
+ template RAN_Information_Application_Error_RIM_Container cont := ?) := {
+ pDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR := {
+ bssgpPduType := '74'O,
+ destination_Cell_Identifier := dst,
+ source_Cell_Identifier := src,
+ rIM_Container := cont
+ }
+ }
+
+ /* PDU permitted on PTP BVC only (TS 48.018 Section 5.4.1) */
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_PTP_ONLY := (
+ {pDU_BSSGP_DL_UNITDATA := ?},
+ {pDU_BSSGP_UL_UNITDATA := ?},
+ {pDU_BSSGP_RA_CAPABILITY := ?},
+ {pDU_BSSGP_RA_CAPABILITY_UPDATE := ?},
+ {pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK := ?},
+ {pDU_BSSGP_RADIO_STATUS := ?},
+ {pDU_BSSGP_FLOW_CONTROL_BVC := ?},
+ {pDU_BSSGP_FLOW_CONTROL_BVC_ACK := ?},
+ {pDU_BSSGP_FLOW_CONTROL_MS := ?},
+ {pDU_BSSGP_FLOW_CONTROL_MS_ACK := ?},
+ {pDU_BSSGP_FLOW_CONTROL_PFC := ?},
+ {pDU_BSSGP_FLOW_CONTROL_PFC_ACK := ?},
+ {pDU_BSSGP_DOWNLOAD_BSS_PFC := ?},
+ {pDU_BSSGP_CREATE_BSS_PFC := ?},
+ {pDU_BSSGP_CREATE_BSS_PFC_ACK := ?},
+ {pDU_BSSGP_CREATE_BSS_PFC_NACK := ?},
+ {pDU_BSSGP_MODIFY_BSS_PFC := ?},
+ {pDU_BSSGP_MODIFY_BSS_PFC_ACK := ?},
+ {pDU_BSSGP_DELETE_BSS_PFC := ?},
+ {pDU_BSSGP_DELETE_BSS_PFC_ACK := ?},
+ {pDU_BSSGP_DELETE_BSS_PFC_REQ := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUIRED := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUIRED_ACK := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUIRED_NACK := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUEST := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUEST_ACK := ?},
+ {pDU_BSSGP_PS_HANDOVER_REQUEST_NACK := ?},
+ {pDU_BSSGP_PS_HANDOVER_COMPLETE := ?},
+ {pDU_BSSGP_PS_HANDOVER_COMPLETE_ACK := ?},
+ {pDU_BSSGP_PS_HANDOVER_CANCEL := ?}
+ );
+
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_PTP := (
+ tr_BSSGP_PERMITTED_PTP_ONLY,
+ {pDU_BSSGP_PAGING_PS := ?},
+ {pDU_BSSGP_PAGING_CS := ?},
+ {pDU_BSSGP_STATUS := ?}
+ );
+
+ /* PDU permitted on Signaling BVC only (TS 48.018 Section 5.4.1) */
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_SIGN_ONLY := (
+ {pDU_BSSGP_SUSPEND := ?},
+ {pDU_BSSGP_SUSPEND_ACK := ?},
+ {pDU_BSSGP_SUSPEND_NACK := ?},
+ {pDU_BSSGP_RESUME := ?},
+ {pDU_BSSGP_RESUME_ACK := ?},
+ {pDU_BSSGP_RESUME_NACK := ?},
+ {pDU_BSSGP_FLUSH_LL := ?},
+ {pDU_BSSGP_FLUSH_LL_ACK := ?},
+ {pDU_BSSGP_LLC_DISCARDED := ?},
+ {pDU_BSSGP_BVC_BLOCK := ?},
+ {pDU_BSSGP_BVC_BLOCK_ACK := ?},
+ {pDU_BSSGP_BVC_UNBLOCK := ?},
+ {pDU_BSSGP_BVC_UNBLOCK_ACK := ?},
+ {pDU_BSSGP_BVC_RESET := ?},
+ {pDU_BSSGP_BVC_RESET_ACK := ?},
+ {pDU_BSSGP_SGSN_INVOKE_TRACE := ?},
+ {pDU_BSSGP_PERFORM_LOCATION_REQUEST := ?},
+ {pDU_BSSGP_PERFORM_LOCATION_RESPONSE := ?},
+ {pDU_BSSGP_PERFORM_LOCATION_ABORT := ?},
+ {pDU_BSSGP_POSITION_COMMAND := ?},
+ {pDU_BSSGP_POSITION_RESPONSE := ?},
+ {pDU_BSSGP_RAN_INFORMATION := ?},
+ {pDU_BSSGP_RAN_INFORMATION_REQUEST := ?},
+ {pDU_BSSGP_RAN_INFORMATION_ACK := ?},
+ {pDU_BSSGP_RAN_INFORMATION_ERROR := ?},
+ {pDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR := ?},
+ {pDU_BSSGP_MBMS_SESSION_START_REQUEST := ?},
+ {pDU_BSSGP_MBMS_SESSION_START_RESPONSE := ?},
+ {pDU_BSSGP_MBMS_SESSION_STOP_REQUEST := ?},
+ {pDU_BSSGP_MBMS_STOP_RESPONSE := ?},
+ {pDU_BSSGP_SESSION_UPDATE_REQUEST := ?},
+ {pDU_BSSGP_SESSION_UPDATE_RESPONSE := ?}
+ );
+
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_SIGN := (
+ tr_BSSGP_PERMITTED_SIGN_ONLY,
+ {pDU_BSSGP_PAGING_PS := ?},
+ {pDU_BSSGP_PAGING_CS := ?},
+ {pDU_BSSGP_SUSPEND := ?},
+ {pDU_BSSGP_STATUS := ?}
+ );
+
+ /* PDU permitted on PTM BVC only (TS 48.018 Section 5.4.1) */
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_PTM_ONLY := (
+ {pDU_BSSGP_DL_MBMS_UNITDATA := ?},
+ {pDU_BSSGP_UL_MBMS_UNITDATA := ?}
+ );
+
+ template (present) PDU_BSSGP tr_BSSGP_PERMITTED_PTM := (
+ tr_BSSGP_PERMITTED_PTM_ONLY,
+ {pDU_BSSGP_STATUS := ?}
+ );
+
+
+ /* Template for any PTP BVCI IE */
+ template (present) BVCI tr_BSSGP_IE_PtpBvci := {
+ iEI := '04'O,
+ ext := '1'B,
+ lengthIndicator := {
+ length1 := 2
+ },
+ unstructured_value := complement ('0000'O, '0001'O)
+ }
+
+ /* message on signaling PTP but containing a ptp BVC */
+ /*
+ template PDU_BSSGP tr_BSSGP_SIG_FOR_PTP(template Bvci bvci) := (
+ {pDU_BSSGP_FLUSH_LL:{?,?,tr_BSSGP_IE_PtpBvci, *, *}},
+ {pDU_BSSGP_FLUSH_LL_ACK:{?,?,?,tr_BSSGP_IE_PtpBvci, ?, *}},
+ {pDU_BSSGP_LLC_DISCARDED:{?,?,?,tr_BSSGP_IE_PtpBvci, ?, *}},
+ {pDU_BSSGP_BVC_BLOCK:{?,tr_BSSGP_IE_PtpBvci, ?}},
+ {pDU_BSSGP_BVC_BLOCK_ACK:{?,tr_BSSGP_IE_PtpBvci}},
+ {pDU_BSSGP_BVC_UNBLOCK:{?,tr_BSSGP_IE_PtpBvci}},
+ {pDU_BSSGP_BVC_UNBLOCK_ACK:{?,tr_BSSGP_IE_PtpBvci}},
+ {pDU_BSSGP_BVC_RESET:{?,tr_BSSGP_IE_PtpBvci,?,*,*,*}},
+ {pDU_BSSGP_BVC_RESET_ACK:{?,tr_BSSGP_IE_PtpBvci,*,*,*}},
+ {pDU_BSSGP_STATUS:{?,?,tr_BSSGP_IE_PtpBvci,*}},
+ {pDU_BSSGP_PERFORM_LOCATION_REQUEST:{?,?,?,*,tr_BSSGP_IE_PtpBvci,?,?,?,*,*,*,*,*,*,*,*,*}},
+ {pDU_BSSGP_PERFORM_LOCATION_RESPONSE:{?,?,tr_BSSGP_IE_PtpBvci,*,*,*,*,*,*}},
+ {pDU_BSSGP_PERFORM_LOCATION_ABORT:{?,?,tr_BSSGP_IE_PtpBvci,?}},
+ {pDU_BSSGP_POSITION_COMMAND:{
+ );
+ */
+
+ /* extract the BVCI IE of given PDU + return it */
+ function f_BSSGP_BVCI_IE_get(PDU_BSSGP pdu) return template (omit) BVCI {
+ select (pdu) {
+ case (PDU_BSSGP:{pDU_BSSGP_FLUSH_LL:=?}) {
+ return pdu.pDU_BSSGP_FLUSH_LL.bVCI_old;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_FLUSH_LL_ACK:=?}) {
+ return pdu.pDU_BSSGP_FLUSH_LL_ACK.bVCI_new;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_LLC_DISCARDED:=?}) {
+ return pdu.pDU_BSSGP_LLC_DISCARDED.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_BLOCK:=?}) {
+ return pdu.pDU_BSSGP_BVC_BLOCK.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_BLOCK_ACK:=?}) {
+ return pdu.pDU_BSSGP_BVC_BLOCK_ACK.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_UNBLOCK:=?}) {
+ return pdu.pDU_BSSGP_BVC_UNBLOCK.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_UNBLOCK_ACK:=?}) {
+ return pdu.pDU_BSSGP_BVC_UNBLOCK_ACK.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_RESET:=?}) {
+ return pdu.pDU_BSSGP_BVC_RESET.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_BVC_RESET_ACK:=?}) {
+ return pdu.pDU_BSSGP_BVC_RESET_ACK.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_STATUS:=?}) {
+ return pdu.pDU_BSSGP_STATUS.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_PERFORM_LOCATION_REQUEST:=?}) {
+ return pdu.pDU_BSSGP_PERFORM_LOCATION_REQUEST.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_PERFORM_LOCATION_RESPONSE:=?}) {
+ return pdu.pDU_BSSGP_PERFORM_LOCATION_RESPONSE.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_PERFORM_LOCATION_ABORT:=?}) {
+ return pdu.pDU_BSSGP_PERFORM_LOCATION_ABORT.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_POSITION_COMMAND:=?}) {
+ return pdu.pDU_BSSGP_POSITION_COMMAND.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_POSITION_RESPONSE:=?}) {
+ return pdu.pDU_BSSGP_POSITION_RESPONSE.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_PAGING_PS:={?,?,*,{bVCI:=?},*,*,?,*,*}}) {
+ return pdu.pDU_BSSGP_PAGING_PS.paging_Field4.bVCI;
+ }
+ case (PDU_BSSGP:{pDU_BSSGP_PAGING_CS:={?,?,?,{bVCI:=?},*,*,*,*,*}}) {
+ return pdu.pDU_BSSGP_PAGING_CS.paging_Field4.bVCI;
+ }
+ }
+ return omit;
+ }
+
+ /* extract the BVCI IE of given PDU + convert it to integer value */
+ function f_BSSGP_BVCI_get(PDU_BSSGP pdu) return template (omit) BssgpBvci {
+ var template (omit) BVCI bvci_raw := f_BSSGP_BVCI_IE_get(pdu);
+ if (istemplatekind(bvci_raw, "omit")) {
+ return omit;
+ }
+ return oct2int(valueof(bvci_raw.unstructured_value));
+ }
+
+ /* 3GPP TS 23.003 2.6 */
+ type enumerated TlliType {
+ TLLI_LOCAL,
+ TLLI_FOREIGN,
+ TLLI_RANDOM,
+ TLLI_AUXILIARY,
+ TLLI_RESERVED,
+ TLLI_G_RNTI,
+ TLLI_RAND_G_RNTI
+ }
+
+ /* 3GPP TS 23.003 2.6 */
+ function f_gprs_tlli_type(OCT4 tlli) return TlliType {
+ var bitstring tllib := oct2bit(tlli);
+ if (substr(tllib, 0, 2) == '11'B) {
+ return TLLI_LOCAL;
+ } else if (substr(tllib, 0, 2) == '10'B) {
+ return TLLI_FOREIGN;
+ } else if (substr(tllib, 0, 5) == '01111'B) {
+ return TLLI_RANDOM;
+ } else if (substr(tllib, 0, 4) == '0110'B) {
+ return TLLI_RESERVED;
+ } else if (substr(tllib, 0, 3) == '010'B) {
+ return TLLI_RESERVED;
+ } else if (substr(tllib, 0, 4) == '0000'B) {
+ return TLLI_G_RNTI;
+ } else if (substr(tllib, 0, 4) == '0001'B) {
+ return TLLI_RAND_G_RNTI;
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unknonw TLLI Type ", tllib));
+ return TLLI_LOCAL;
+ }
+ }
+
+ /* build a TLLI of specified type from the given (P)TMSI */
+ function f_gprs_tlli_from_tmsi(OCT4 tmsi, TlliType tlli_type) return OCT4 {
+ var bitstring tmsi_bits := oct2bit(tmsi);
+ var bitstring prefix;
+ select (tlli_type) {
+ case (TLLI_LOCAL) { prefix := '11'B }
+ case (TLLI_FOREIGN) { prefix := '01111'B }
+ case (TLLI_RANDOM) { prefix := '0110'B }
+ case (TLLI_RESERVED) { prefix := '010'B }
+ case (TLLI_G_RNTI) { prefix := '0000'B }
+ case (TLLI_RAND_G_RNTI) { prefix := '0001'B }
+ case else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unknonw TLLI Type ", tlli_type));
+ return '00000000'O;
+ }
+ }
+ return bit2oct(prefix & substr(tmsi_bits, lengthof(prefix), 32-lengthof(prefix)));
+ }
+
+ function f_gprs_tlli_random() return OCT4 {
+ var OCT4 tlli := f_rnd_octstring(4);
+ return tlli or4b 'c0000000'O;
+ }
} with { encode "RAW" };
diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn
index e55f1d6c..66534086 100644
--- a/library/Osmocom_Types.ttcn
+++ b/library/Osmocom_Types.ttcn
@@ -10,89 +10,114 @@
module Osmocom_Types {
- import from General_Types all;
-
- type integer uint8_t (0..255) with { variant "unsigned 8 bit" };
- type integer uint16_t (0..65535) with { variant "unsigned 16 bit" };
- type integer uint24_t (0..16777215) with { variant "unsigned 24 bit" };
- type integer uint32_t (0..4294967295) with { variant "unsigned 32 bit" };
-
- type integer int8_t (-128..127) with { variant "8 bit" };
- type integer int16_t (-32768..32767) with { variant "16 bit" };
-
- type integer uint1_t (0..1) with { variant "unsigned 1 bit" };
- type integer uint2_t (0..3) with { variant "unsigned 2 bit" };
- type integer uint3_t (0..7) with { variant "unsigned 3 bit" };
- type integer uint4_t (0..15) with { variant "unsigned 4 bit" };
- type integer uint5_t (0..31) with { variant "unsigned 5 bit" };
- type integer uint6_t (0..63) with { variant "unsigned 6 bit" };
- type integer uint7_t (0..127) with { variant "unsigned 7 bit" };
- type integer uint9_t (0..511) with { variant "unsigned 9 bit" };
- type integer uint10_t (0..1023) with { variant "unsigned 10 bit" };
- type integer uint11_t (0..2047) with { variant "unsigned 11 bit" };
- type integer uint12_t (0..4095) with { variant "unsigned 12 bit" };
- type integer uint13_t (0..8191) with { variant "unsigned 13 bit" };
- type integer uint14_t (0..16383) with { variant "unsigned 14 bit" };
- type integer uint15_t (0..32767) with { variant "unsigned 15 bit" };
- type integer uint40_t (0..1099511627776) with { variant "unsigned 40 bit" };
-
-
- const uint16_t c_UINT16_MAX := 65535;
- const uint32_t c_UINT32_MAX := 4294967295;
-
- /* CSN.1 L/H placeholders */
- const BIT1 CSN1_L := '0'B;
- const BIT1 CSN1_H := '1'B;
-
- type record Arfcn {
- boolean pcs,
- uint15_t arfcn
- } with { variant "" };
-
- /* return random integer between 0 and max */
- function f_rnd_int(integer max) return integer {
- return float2int(rnd()*int2float(max));
- }
-
- /* return hexstring composed of random digits */
- function f_rnd_hexstring(in integer len, in integer max := 15) return hexstring {
- var integer i;
- var hexstring ret := ''H;
- for (i := 0; i < len; i := i + 1) {
- ret := ret & int2hex(f_rnd_int(max), 1);
- }
- return ret;
- }
+import from General_Types all;
- /* return octetstring composed of random bytes */
- function f_rnd_octstring(in integer len) return octetstring {
- var integer i;
- var octetstring ret := ''O;
- for (i := 0; i < len; i := i + 1) {
- ret := ret & int2oct(f_rnd_int(255), 1);
- }
- return ret;
- }
+type integer uint8_t (0..255) with { variant "unsigned 8 bit" };
+type integer uint16_t (0..65535) with { variant "unsigned 16 bit" };
+type integer uint24_t (0..16777215) with { variant "unsigned 24 bit" };
+type integer uint32_t (0..4294967295) with { variant "unsigned 32 bit" };
+type integer uint64_t (0..18446744073709551615) with { variant "unsigned 64 bit" };
- /* return bitstring composed of random bits */
- function f_rnd_bitstring(in integer len) return bitstring {
- var octetstring oct := f_rnd_octstring(len / 8 + 1);
- return substr(oct2bit(oct), 0, len);
- }
+type integer int8_t (-128..127) with { variant "8 bit" };
+type integer int16_t (-32768..32767) with { variant "16 bit" };
- function f_rnd_imsi(in hexstring prefix) return hexstring {
- return prefix & f_rnd_hexstring(15 - lengthof(prefix), 9);
- }
+type integer uint1_t (0..1) with { variant "unsigned 1 bit" };
+type integer uint2_t (0..3) with { variant "unsigned 2 bit" };
+type integer uint3_t (0..7) with { variant "unsigned 3 bit" };
+type integer uint4_t (0..15) with { variant "unsigned 4 bit" };
+type integer uint5_t (0..31) with { variant "unsigned 5 bit" };
+type integer uint6_t (0..63) with { variant "unsigned 6 bit" };
+type integer uint7_t (0..127) with { variant "unsigned 7 bit" };
+type integer uint9_t (0..511) with { variant "unsigned 9 bit" };
+type integer uint10_t (0..1023) with { variant "unsigned 10 bit" };
+type integer uint11_t (0..2047) with { variant "unsigned 11 bit" };
+type integer uint12_t (0..4095) with { variant "unsigned 12 bit" };
+type integer uint13_t (0..8191) with { variant "unsigned 13 bit" };
+type integer uint14_t (0..16383) with { variant "unsigned 14 bit" };
+type integer uint15_t (0..32767) with { variant "unsigned 15 bit" };
+type integer uint40_t (0..1099511627776) with { variant "unsigned 40 bit" };
+
+
+const uint16_t c_UINT16_MAX := 65535;
+const uint32_t c_UINT32_MAX := 4294967295;
+
+/* CSN.1 L/H placeholders */
+const BIT1 CSN1_L := '0'B;
+const BIT1 CSN1_H := '1'B;
+
+/* based on Linux */
+type enumerated AddressFamily {
+ AF_UNSPEC ('00'O),
+ AF_INET ('02'O),
+ AF_INET6 ('0a'O)
+}
+
+/* like TTCN-3 int2str() but with padding of leading zeroes */
+function f_int2str(integer i, integer total_digits) return charstring {
+ var charstring istr := int2str(i);
+ var charstring padstr := hex2str(int2hex(0, total_digits - lengthof(istr)));
+ return padstr & istr;
+}
+
+/* return random integer 0 <= ret < max. According to ETSI ES 201 873 C.6.1, rnd() returns *less* than 1, so
+ * the returned int will always be ret < max, or ret <= (max-1). */
+function f_rnd_int(integer max) return integer {
+ return float2int(rnd()*int2float(max));
+}
+
+/* return random integer 1 <= ret < max */
+function f_rnd_int_nonzero(integer max) return integer {
+ return float2int(1.0 + rnd()*int2float(max-1));
+}
- function f_rnd_msisdn(in octetstring prefix, integer len := 6) return octetstring {
- return prefix & f_rnd_octstring(len - lengthof(prefix));
+/* return hexstring composed of random digits */
+function f_rnd_hexstring(in integer len, in integer max := 16) return hexstring {
+ var integer i;
+ var hexstring ret := ''H;
+ for (i := 0; i < len; i := i + 1) {
+ ret := ret & int2hex(f_rnd_int(max), 1);
}
+ return ret;
+}
- function f_sleep(float seconds) {
- timer T := seconds;
- T.start;
- T.timeout;
+/* return octetstring composed of random bytes */
+function f_rnd_octstring(in integer len) return octetstring {
+ var integer i;
+ var octetstring ret := ''O;
+ for (i := 0; i < len; i := i + 1) {
+ ret := ret & int2oct(f_rnd_int(256), 1);
}
+ return ret;
+}
+
+/* return ocetstring composed of random bytes, at least 1, maximum 'maxlen' bytes long */
+function f_rnd_octstring_rnd_len(in integer maxlen) return octetstring {
+ return f_rnd_octstring(f_rnd_int_nonzero(maxlen));
+}
+
+/* return bitstring composed of random bits */
+function f_rnd_bitstring(in integer len) return bitstring {
+ var octetstring oct := f_rnd_octstring(len / 8 + 1);
+ return substr(oct2bit(oct), 0, len);
+}
+
+function f_rnd_imsi(in hexstring prefix) return hexstring {
+ return prefix & f_rnd_hexstring(15 - lengthof(prefix), 10);
+}
+
+function f_rnd_imei(in hexstring prefix) return hexstring {
+ return prefix & f_rnd_hexstring(14 - lengthof(prefix), 10);
+}
+
+function f_rnd_msisdn(in octetstring prefix, integer len := 6) return octetstring {
+ return prefix & f_rnd_octstring(len - lengthof(prefix));
+}
+
+function f_sleep(float seconds) {
+ timer T := seconds;
+ T.start;
+ T.timeout;
+}
function bool2bit(boolean inp) return BIT1 {
if (inp) {
@@ -128,6 +153,54 @@ function int2bool(integer int) return boolean {
}
}
+function int2oct_tmpl(template integer inp, integer num_oct) return template octetstring
+{
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return int2oct(valueof(inp), num_oct);
+ }
+}
+
+function char2oct_tmpl(template charstring inp) return template octetstring
+{
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return char2oct(valueof(inp));
+ }
+}
+
+function char2oct_tmpl_present(template (present) charstring inp) return template (present) octetstring
+{
+ if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return char2oct(valueof(inp));
+ }
+}
+
+function hex2str_tmpl(template hexstring inp) return template charstring
+{
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return hex2str(valueof(inp));
+ }
+}
+
function f_array_contains(IntegerRecord arr, integer key) return boolean {
for (var integer i:= 0; i< sizeof(arr); i := i + 1) {
if (arr[i] == key) {
@@ -197,5 +270,153 @@ function f_pad_bcd_number(hexstring number) return hexstring {
}
}
+function f_pad_bcd_number_tmpl(template hexstring inp) return template hexstring {
+ if (istemplatekind(inp, "omit")) {
+ return omit;
+ } else if (istemplatekind(inp, "*")) {
+ return *;
+ } else if (istemplatekind(inp, "?")) {
+ return ?;
+ } else {
+ return f_pad_bcd_number(valueof(inp));
+ }
+}
+
+/* like L1SAP_IS_PACKET_RACH */
+function ra_is_ps(OCT1 ra) return boolean {
+ if ((ra and4b 'F0'O == '70'O) and (ra and4b '0F'O != '0F'O)) {
+ return true;
+ }
+ return false;
+}
+
+function ra_is_emerg(OCT1 ra) return boolean {
+ /* See also: 3GPP TS 04.08, Table 9.9, ra=101xxxxx */
+ return (ra and4b 'E0'O == 'A0'O);
+}
+
+/* generate a random RACH for circuit-switched */
+function f_rnd_ra_cs() return OCT1 {
+ var OCT1 ra;
+ do {
+ ra := f_rnd_octstring(1);
+ } while (ra_is_ps(ra) or ra_is_emerg(ra));
+ return ra;
+}
+
+/* generate a random RACH for emergency */
+function f_rnd_ra_emerg() return OCT1 {
+ var OCT1 ra;
+ do {
+ ra := f_rnd_octstring(1);
+ } while (not ra_is_emerg(ra));
+ return ra;
+}
+
+/* generate a random RACH for packet-switched */
+function f_rnd_ra_ps() return OCT1 {
+ var OCT1 ra;
+ do {
+ ra := f_rnd_octstring(1);
+ } while (not ra_is_ps(ra));
+ return ra;
+}
+
+/* generate a random 11-bit RA (packet-switched only) */
+function f_rnd_ra11_ps() return BIT11 {
+ return f_rnd_bitstring(11);
+}
+
+
+private function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring {
+ var integer suffix_len := tot_len - lengthof(prefix);
+ var charstring suffix_ch := int2str(suffix);
+ var integer pad_len := suffix_len - lengthof(suffix_ch);
+
+ return prefix & int2hex(0, pad_len) & str2hex(suffix_ch);
+}
+
+function f_gen_imei(integer suffix) return hexstring {
+ return f_concat_pad(14, '49999'H, suffix);
+}
+
+function f_gen_imsi(integer suffix) return hexstring {
+ return f_concat_pad(15, '26242'H, suffix);
+}
+
+function f_gen_msisdn(integer suffix) return hexstring {
+ return f_concat_pad(12, '49123'H, suffix);
+}
+
+function f_gen_tmsi(integer suffix, integer nri_v := 0, integer nri_bitlen := 10,
+ OCT4 base_tmsi := '42000023'O) return OCT4 {
+ var integer tmsi_int := oct2int(base_tmsi) + suffix;
+ var bitstring base_tmsi_bits := int2bit(tmsi_int, 32);
+ var bitstring prefix_bits := substr(base_tmsi_bits, 0, 8);
+ var bitstring suffix_bits := substr(base_tmsi_bits, 8 + nri_bitlen, 24 - nri_bitlen);
+ var bitstring total_bits := prefix_bits & int2bit(nri_v, nri_bitlen) & suffix_bits;
+ var OCT4 tmsi := bit2oct(total_bits);
+
+ log("f_gen_tmsi(suffix:=", suffix, ", nri_v:=", nri_v, ", nri_bitlen:=", nri_bitlen,
+ ", base_tmsi:=", base_tmsi, ") -> prefix:=", prefix_bits, ", suffix:=", suffix_bits,
+ ", total_bits:=", total_bits, " == ", tmsi);
+
+ return tmsi;
+}
+
+type record of integer ro_integer;
+
+function ro_integer_contains(ro_integer r, integer x) return boolean {
+ for (var integer j := 0; j < lengthof(r); j := j+1) {
+ if (r[j] == x) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function ro_integer_add_unique(inout ro_integer roi, integer new_entry)
+{
+ if (ro_integer_contains(roi, new_entry)) {
+ return;
+ }
+ roi := roi & {new_entry};
+}
+
+function ro_integer_del(inout ro_integer roi, integer del_entry)
+{
+ var ro_integer tmp := {};
+ for (var integer j := 0; j < lengthof(roi); j := j+1) {
+ if (roi[j] != del_entry) {
+ tmp := tmp & { roi[j] };
+ }
+ }
+ roi := tmp;
+}
+
+type record of ro_integer roro_integer;
+
+function f_bool2str(boolean val) return charstring {
+ if (val) {
+ return "true";
+ } else {
+ return "false";
+ }
+}
+
+/* Return a reversed bitstring */
+function f_bits_reversed(in bitstring bits) return bitstring {
+ for (var integer i := 0; i < lengthof(bits) / 2; i := i + 1) {
+ var integer reverse_i := lengthof(bits) - 1 - i;
+ if (i >= reverse_i) {
+ break;
+ }
+ var bitstring tmp;
+ tmp[0] := bits[i];
+ bits[i] := bits[reverse_i];
+ bits[reverse_i] := tmp[0];
+ }
+ return bits;
+}
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/Osmocom_VTY_Functions.ttcn b/library/Osmocom_VTY_Functions.ttcn
index 823d79fb..b982a8ff 100644
--- a/library/Osmocom_VTY_Functions.ttcn
+++ b/library/Osmocom_VTY_Functions.ttcn
@@ -10,11 +10,16 @@
*/
module Osmocom_VTY_Functions {
+
+ import from Misc_Helpers all;
import from TELNETasp_PortType all;
import from Osmocom_Types all;
+ import from TCCConversion_Functions all;
+ import from Socket_API_Definitions all;
modulepar {
charstring mp_prompt_prefix := "OpenBSC";
+ float mp_prompt_timeout := 2.0;
}
const charstring VTY_VIEW_SUFFIX := "> ";
@@ -56,46 +61,54 @@ module Osmocom_VTY_Functions {
}
/* wait for any of the permitted prompts; buffer + return all intermediate output */
- function f_vty_wait_for_prompt(TELNETasp_PT pt) return charstring {
+ function f_vty_wait_for_prompt(TELNETasp_PT pt, boolean strict := true, charstring log_label := "(?)")
+ return charstring {
var charstring rx, buf := "";
var integer fd;
- timer T := 2.0;
+ timer T;
- T.start;
+ T.start(mp_prompt_timeout);
alt {
- [] pt.receive(pattern "[\w-]+" & VTY_VIEW_SUFFIX) { };
- [] pt.receive(pattern "[\w-]+\# ") { };
- [] pt.receive(pattern "[\w-]+\(*\)\# ") { };
- [] pt.receive(t_vty_unknown) {
- testcase.stop(fail, "VTY: Unknown Command");
- };
- [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
- [] pt.receive(integer:?) -> value fd {
- if (fd == -1) {
- setverdict(fail, "VTY Telnet Connection Failure");
- mtc.stop;
- } else {
- repeat; /* telnet connection succeeded */
- }
+ [] pt.receive(pattern "[\w-]+" & VTY_VIEW_SUFFIX) { };
+ [] pt.receive(pattern "[\w-]+\# ") { };
+ [] pt.receive(pattern "[\w-]+\(*\)\# ") { };
+ [] pt.receive(t_vty_unknown) -> value rx {
+ if (strict) {
+ setverdict(fail, "VTY: Unknown Command: " & log_label);
+ mtc.stop;
+ } else {
+ log("VTY: Unknown Command (ignored): " & log_label);
+ buf := buf & rx;
+ repeat;
}
- [] T.timeout {
- setverdict(fail, "VTY Timeout for prompt");
+ };
+ [] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
+ [] pt.receive(integer:?) -> value fd {
+ if (fd == -1) {
+ setverdict(fail, "VTY Telnet Connection Failure: " & log_label);
mtc.stop;
- };
+ } else {
+ repeat; /* telnet connection succeeded */
+ }
+ }
+ [] T.timeout {
+ setverdict(fail, "VTY Timeout for prompt: " & log_label);
+ mtc.stop;
+ };
}
T.stop;
return buf;
}
/* send a VTY command and obtain response until prompt is received */
- function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx) return charstring {
+ function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx, boolean strict := true) return charstring {
pt.send(tx);
- return f_vty_wait_for_prompt(pt);
+ return f_vty_wait_for_prompt(pt, strict, tx);
}
/* send a VTY command and obtain response until prompt is received */
- function f_vty_transceive(TELNETasp_PT pt, charstring tx) {
- var charstring unused := f_vty_transceive_ret(pt, tx);
+ function f_vty_transceive(TELNETasp_PT pt, charstring tx, boolean strict := true) {
+ var charstring unused := f_vty_transceive_ret(pt, tx, strict);
}
type integer BtsNr (0..255);
@@ -142,25 +155,39 @@ module Osmocom_VTY_Functions {
}
type record of charstring rof_charstring;
-function f_vty_config2(TELNETasp_PT pt, rof_charstring config_nodes, charstring cmd)
+function f_vty_config3(TELNETasp_PT pt, rof_charstring config_nodes, rof_charstring cmds)
{
/* enter config mode; enter node */
f_vty_enter_config(pt);
for (var integer i := 0; i < sizeof(config_nodes); i := i+1) {
f_vty_transceive(pt, config_nodes[i]);
}
- /* execute command */
- f_vty_transceive(pt, cmd);
+ /* execute commands */
+ for (var integer i := 0; i < sizeof(cmds); i := i+1) {
+ f_vty_transceive(pt, cmds[i]);
+ }
/* leave config mode */
f_vty_transceive(pt, "end");
}
+function f_vty_config2(TELNETasp_PT pt, rof_charstring config_nodes, charstring cmd)
+{
+ f_vty_config3(pt, config_nodes, { cmd });
+}
function f_vty_config(TELNETasp_PT pt, charstring config_node, charstring cmd)
{
f_vty_config2(pt, {config_node}, cmd);
}
+function f_vty_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0, rof_charstring cmds) {
+ f_vty_config3(pt, {"network", "bts " & int2str(bts)}, cmds);
+}
+
+function f_vty_cfg_msc(TELNETasp_PT pt, MscNr msc := 0, rof_charstring cmds) {
+ f_vty_config3(pt, {"msc " & int2str(msc)}, cmds);
+}
+
function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
var charstring ret := f_vty_transceive_ret(pt, cmd);
if (not match(ret, exp_ret)) {
@@ -195,9 +222,119 @@ function f_vty_transceive_match_regexp_retry(TELNETasp_PT pt, charstring cmd, ch
num_attempts := num_attempts - 1;
}
- setverdict(fail, "No matching VTY response for regular expression '", regex,
- "' after ", num_attempts, " attempts." );
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No matching VTY response for regular expression '",
+ regex, "' after ", num_attempts, " attempts." ));
+ return "";
+}
+
+private type record of charstring StrList;
+
+/* Perform a 'show talloc-context' to get a count of the given object_strs that are still allocated.
+ * Retry 'attempts' times until the actual talloc object count matches 'expect_count'.
+ * Useful to ensure that no mem leaks remain after running a test. */
+function f_verify_talloc_count(TELNETasp_PT pt, StrList object_strs, integer expect_count := 0,
+ integer attempts := 5, float wait_time := 3.0)
+{
+ var charstring show_cmd := "show talloc-context application full filter ";
+ for (var integer i := 0; i < lengthof(object_strs); i := i + 1) {
+ var charstring obj_str := object_strs[i];
+ /* spaces confuse the VTY command */
+ obj_str := f_replaceEveryOccurenceOfSubstring(obj_str, " ", ".");
+ /* In the regexp, expect word start and word end to bound the obj name */
+ obj_str := "\\<" & obj_str & "\\>";
+ if (i > 0) {
+ show_cmd := show_cmd & "\\|";
+ }
+ show_cmd := show_cmd & obj_str;
+ }
+
+ while (attempts > 0) {
+ attempts := attempts - 1;
+ var charstring ret := f_vty_transceive_ret(pt, show_cmd);
+
+ var boolean ok := true;
+ for (var integer i := 0; i < lengthof(object_strs); i := i + 1) {
+ var charstring object_str := object_strs[i];
+ var integer count := f_strstr_count(ret, object_str);
+ log("talloc reports ", object_str, " x ", count, ", expecting ", expect_count);
+ if (count != expect_count) {
+ ok := false;
+ }
+ }
+ if (ok) {
+ return;
+ }
+ if (attempts == 0) {
+ break;
+ }
+ log("count mismatch, retrying in ", wait_time);
+ f_sleep(wait_time);
+ }
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "talloc count mismatch");
+}
+
+public function f_verify_talloc_bytes(TELNETasp_PT pt, Misc_Helpers.ro_charstring object_strs, integer expect_bytes := 0,
+ integer attempts := 5, float wait_time := 3.0)
+{
+ var charstring show_cmd := "show talloc-context application brief";
+
+ while (attempts > 0) {
+ attempts := attempts - 1;
+ var charstring ret := f_vty_transceive_ret(pt, show_cmd);
+
+ var Misc_Helpers.ro_charstring lines := f_str_split(ret);
+
+ var boolean ok := true;
+ for (var integer i := 0; i < lengthof(object_strs); i := i + 1) {
+ var charstring object_str := object_strs[i];
+
+ var integer bytes := 0;
+
+ for (var integer j := 0; j < lengthof(lines); j := j + 1) {
+ var charstring line := lines[j];
+ if (f_strstr(line, object_str) < 0) {
+ continue;
+ }
+ var Misc_Helpers.ro_charstring tokens := f_str_split(line, " ");
+ if (lengthof(tokens) < 4) {
+ continue;
+ }
+ if (tokens[3] != "bytes") {
+ continue;
+ }
+ bytes := f_str2int(tokens[2]);
+ }
+
+ if (bytes != expect_bytes) {
+ ok := false;
+ log("ERROR: talloc reports ", object_str, " = ", bytes, " bytes, expecting ", expect_bytes,
+ " from VTY response ", lines);
+ } else {
+ log("ok: talloc reports ", object_str, " = ", bytes, " bytes");
+ }
+ }
+ if (ok) {
+ return;
+ }
+ if (attempts == 0) {
+ break;
+ }
+ log("bytes count mismatch, retrying in ", wait_time);
+ f_sleep(wait_time);
+ }
+ setverdict(fail, "talloc bytes count mismatch");
mtc.stop;
}
+public function f_logp(TELNETasp_PT pt, charstring log_msg)
+{
+ // log on TTCN3 log output
+ log(log_msg);
+ // log in stderr log
+ if (pt.checkstate("Mapped")) {
+ f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg);
+ }
+}
+
}
diff --git a/library/PCO_Types.ttcn b/library/PCO_Types.ttcn
new file mode 100644
index 00000000..0eaa45e4
--- /dev/null
+++ b/library/PCO_Types.ttcn
@@ -0,0 +1,151 @@
+module PCO_Types {
+
+/* PCO_Types, defining abstract TTCN-3 data types for the Protocol Configuration Options (PCO).
+ *
+ * (C) 2024 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
+ */
+
+/* 3GPP TS 24.008 10.5.6.3, 3GPP TS 29.060 7.7.31 */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+type enumerated PCO_P {
+ PCO_P_LCP ('C021'O),
+ PCO_P_PAP ('C023'O),
+ PCO_P_CHAP ('C223'O),
+ PCO_P_IPCP ('8021'O),
+ PCO_P_PCSCF_ADDR ('0001'O),
+ PCO_P_IM_CN_SS_F ('0002'O),
+ PCO_P_DNS_IPv6_ADDR ('0003'O),
+ PCO_P_POLICY_CTRL_REJ ('0004'O), /* only in Network->MS */
+ PCO_P_MS_SUP_NETREQ_BCI ('0005'O),
+ /* reserved */
+ PCO_P_DSMIPv6_HA_ADDR ('0007'O),
+ PCO_P_DSMIPv6_HN_PREF ('0008'O),
+ PCO_P_DSMIPv6_v4_HA_ADDR ('0009'O),
+ PCO_P_IP_ADDR_VIA_NAS ('000a'O), /* only MS->Network */
+ PCO_P_IPv4_ADDR_VIA_DHCP ('000b'O), /* only MS->Netowrk */
+ PCO_P_PCSCF_IPv4_ADDR ('000c'O),
+ PCO_P_DNS_IPv4_ADDR ('000d'O),
+ PCO_P_MSISDN ('000e'O),
+ PCO_P_IFOM_SUPPORT ('000f'O),
+ PCO_P_IPv4_LINK_MTU ('0010'O),
+ PCO_P_MS_SUPP_LOC_A_TFT ('0011'O),
+ PCO_P_PCSCF_RESEL_SUP ('0012'O), /* only MS->Network */
+ PCO_P_NBIFOM_REQ ('0013'O),
+ PCO_P_NBIFOM_MODE ('0014'O),
+ PCO_P_NONIP_LINK_MTU ('0015'O),
+ PCO_P_APN_RATE_CTRL_SUP ('0016'O),
+ PCO_P_PS_DATA_OFF_UE ('0017'O),
+ PCO_P_REL_DATA_SVC ('0018'O)
+} with { variant "FIELDLENGTH(16)";
+ variant "BYTEORDER(last)" };
+
+function PCO_P_to_OCT2(PCO_P p) return OCT2 {
+ return int2oct(enum2int(p), 2);
+}
+
+/* RFC 1332 IP Control Protocol options, extensions in RFC 1877 */
+type enumerated IPCP_OPT {
+ IPCP_OPT_IPADDR (3), /* RFC 1332 3.3 */
+ IPCP_OPT_PRIMARY_DNS (129), /* RFC 1877 1.1 */
+ IPCP_OPT_SECONDARY_DNS (131) /* RFC 1877 1.2 */
+} with { variant "FIELDLENGTH(8)" };
+
+/* RFC 1334, section 3.2. Packet Format */
+type enumerated PAP_CODE_ {
+ PAP_CODE__IPADDR (1),
+ PAP_CODE__PRIMARY_DNS (2),
+ PAP_CODE__SECONDARY_DNS (3)
+} with { variant "FIELDLENGTH(8)" };
+
+type set of ProtocolElement ProtocolIDList;
+
+type record ProtocolElement {
+ PCO_P protocolID,
+ uint8_t lengthProtoID,
+ octetstring protoIDContents
+} with { variant (lengthProtoID) "LENGTHTO(protoIDContents)" };
+
+type record PCO_DATA {
+ BIT1 extension0,
+ BIT4 spare,
+ BIT3 configProtocol,
+ ProtocolIDList protocols
+};
+
+external function enc_PCO_DATA(in PCO_DATA pco_data) return octetstring
+with { extension "prototype(convert)" extension "encode(RAW)" }
+
+external function dec_PCO_DATA(in octetstring pco_payload) return PCO_DATA
+with { extension "prototype(convert) decode(RAW)" };
+
+/**********************
+ * PCO_Templates:
+ **********************/
+
+template (value) ProtocolElement ts_PCO_P_OCTSTR(template (value) PCO_P protocolID,
+ template (value) uint8_t lengthProtoID := 0,
+ template (value) octetstring protoIDContents := ''O)
+:= {
+ protocolID := protocolID,
+ lengthProtoID := lengthProtoID,
+ protoIDContents := protoIDContents
+}
+
+template (present) ProtocolElement tr_PCO_P_OCTSTR(template (present) PCO_P protocolID := ?,
+ template (present) uint8_t lengthProtoID := ?,
+ template (present) octetstring protoIDContents := ?)
+:= {
+ protocolID := protocolID,
+ lengthProtoID := lengthProtoID,
+ protoIDContents := protoIDContents
+}
+
+
+template (value) ProtocolElement ts_PCO_P_DNS_IPv4(template (value) octetstring dns4 := ''O) :=
+ ts_PCO_P_OCTSTR(PCO_P_DNS_IPv4_ADDR, protoIDContents := dns4);
+template (present) ProtocolElement tr_PCO_P_DNS_IPv4(template (present) octetstring dns4 := ?) :=
+ tr_PCO_P_OCTSTR(PCO_P_DNS_IPv4_ADDR, protoIDContents := dns4);
+
+template (value) ProtocolElement ts_PCO_P_DNS_IPv6(template (value) octetstring dns6 := ''O) :=
+ ts_PCO_P_OCTSTR(PCO_P_DNS_IPv6_ADDR, protoIDContents := dns6);
+template (present) ProtocolElement tr_PCO_P_DNS_IPv6(template (present) octetstring dns6 := ?) :=
+ tr_PCO_P_OCTSTR(PCO_P_DNS_IPv6_ADDR, protoIDContents := dns6);
+
+template (value) ProtocolElement ts_PCO_P_PCSCF_IPv4(template (value) octetstring pcscf4 := ''O) :=
+ ts_PCO_P_OCTSTR(PCO_P_PCSCF_IPv4_ADDR, protoIDContents := pcscf4);
+template (present) ProtocolElement tr_PCO_P_PCSCF_IPv4(template (present) octetstring pcscf4 := ?) :=
+ tr_PCO_P_OCTSTR(PCO_P_PCSCF_IPv4_ADDR, protoIDContents := pcscf4);
+
+template (value) ProtocolElement ts_PCO_P_PCSCF_IPv6(template (value) octetstring pcscf6 := ''O) :=
+ ts_PCO_P_OCTSTR(PCO_P_PCSCF_ADDR, protoIDContents := pcscf6);
+template (present) ProtocolElement tr_PCO_P_PCSCF_IPv6(template (present) octetstring pcscf6 := ?) :=
+ tr_PCO_P_OCTSTR(PCO_P_PCSCF_ADDR, protoIDContents := pcscf6);
+
+/* PCO send base template */
+template (value) PCO_DATA ts_PCO(template (value) ProtocolIDList protocols := {}) := {
+ extension0 := '1'B,
+ spare := '0000'B,
+ configProtocol := '000'B,
+ protocols := protocols
+}
+/* PCO receive base template */
+template (present) PCO_DATA tr_PCO(template (present) ProtocolIDList protocols := ?) := {
+ extension0 := '1'B,
+ spare := ?,
+ configProtocol := '000'B,
+ protocols := protocols
+}
+
+template (value) PCO_DATA ts_PCO_IPv4_DNS(template (value) octetstring dns4 := ''O) :=
+ ts_PCO({ ts_PCO_P_DNS_IPv4(dns4) });
+
+} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/PCUIF_CodecPort.ttcn b/library/PCUIF_CodecPort.ttcn
index 4b2a8ce9..55d2ee7c 100644
--- a/library/PCUIF_CodecPort.ttcn
+++ b/library/PCUIF_CodecPort.ttcn
@@ -15,6 +15,7 @@ import from Osmocom_Types all;
import from PCUIF_Types all;
import from UD_PortType all;
import from UD_Types all;
+import from General_Types all;
type record PCUIF_send_data {
PCUIF_Message data,
@@ -37,7 +38,6 @@ private function UD_to_PCUIF(in UD_send_data pin, out PCUIF_send_data pout) {
/* HACK: fix padding in decoded message. Due to a bug in TITAN, we
* cannot just use its 'PADDING' attribute because it breaks decoding. */
if (ischosen(pout.data.u.data_req)) { fix_padding(pout.data.u.data_req); }
- if (ischosen(pout.data.u.data_cnf)) { fix_padding(pout.data.u.data_cnf); }
if (ischosen(pout.data.u.data_ind)) { fix_padding(pout.data.u.data_ind); }
} with { extension "prototype(fast)" };
@@ -139,34 +139,66 @@ function f_pcuif_listen(PCUIF_CODEC_PT pt, charstring sock) return integer {
}
function f_PCUIF_tx_imm_ass_pch(PCUIF_CODEC_PT pt, integer conn_id, octetstring imm_ass, hexstring imsi,
- uint8_t bts_nr := 0) return uint32_t {
- var PCUIF_send_data sd;
+ uint8_t bts_nr := 0, boolean wait_for_cnf := true, OCT4 msg_id := '01020304'O) {
timer T := 3.0;
- /* append 3 last imsi digits so BTS can compute pagng group */
- var hexstring last_digits := substr(imsi, lengthof(imsi)-3, 3);
- var octetstring prefix := ''O;
- log("3 last imsi digits: ", last_digits);
- for (var integer i := 0; i < 3; i := i+1) {
- prefix := prefix & int2oct(hex2int('30'H) + hex2int(last_digits[i]), 1);
+
+ var PCUIF_pch pch := {
+ msg_id := msg_id,
+ imsi := hex2str(imsi),
+ data := imm_ass,
+ confirm := true
+ };
+ pt.send(t_SD_PCUIF(conn_id, ts_PCUIF_DATA_REQ(bts_nr, 0, 0, 0, 0, PCU_IF_SAPI_PCH_2, enc_PCUIF_pch(pch))));
+
+ /* Exit early when the caller is not interested in the confirmation message */
+ if (wait_for_cnf == false) {
+ return;
}
- pt.send(t_SD_PCUIF(conn_id,
- ts_PCUIF_DATA_REQ(bts_nr, 0, 0, 0, 0, PCU_IF_SAPI_PCH, prefix & imm_ass)));
+
T.start;
alt {
- [] pt.receive(t_SD_PCUIF(conn_id,
- tr_PCUIF_DATA_CNF(bts_nr, 0, 0, PCU_IF_SAPI_PCH))) -> value sd {
- log("IMM.ASS was sent on fn ", sd.data.u.data_cnf.fn);
- return sd.data.u.data_cnf.fn;
+ [] pt.receive(t_SD_PCUIF(conn_id, tr_PCUIF_DATA_CNF_2(bts_nr, PCU_IF_SAPI_PCH_2))) {
+ log("IMM.ASS was sent on PCH");
}
[] pt.receive { repeat; }
[] T.timeout {
- setverdict(fail, "Timeout waiting for PCU DATA.cnf");
+ setverdict(fail, "Timeout waiting for PCU DATA.cnf (PCH)");
mtc.stop;
}
}
- return 0;
}
+/* This function can be used to transmit arbitrary GSM MAC blocks via the AGCH. The BTS will only confirm those MAC
+ * blocks that contain actually a valid immediate assignment message. Otherweise no confirmation is sent back */
+function f_PCUIF_tx_mac_block_agch(PCUIF_CODEC_PT pt, integer conn_id, octetstring mac_block, boolean confirm := true,
+ uint8_t bts_nr := 0, boolean wait_for_cnf := true, OCT4 msg_id := '01020304'O) {
+ timer T := 3.0;
+
+ var PCUIF_agch agch := {
+ msg_id := msg_id,
+ data := mac_block,
+ confirm := confirm
+ };
+ pt.send(t_SD_PCUIF(conn_id, ts_PCUIF_DATA_REQ(bts_nr, 0, 0, 0, 0, PCU_IF_SAPI_AGCH_2, enc_PCUIF_agch(agch))));
+
+ /* Exit early when the caller is not interested in the confirmation message */
+ if (wait_for_cnf == false) {
+ return;
+ }
+
+ T.start;
+ alt {
+ [] pt.receive(t_SD_PCUIF(conn_id, tr_PCUIF_DATA_CNF_2(bts_nr, PCU_IF_SAPI_AGCH_2))) {
+ log("IMM.ASS was sent on AGCH");
+ }
+ [] pt.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for PCU DATA.cnf (AGCH)");
+ mtc.stop;
+ }
+ }
+ return;
+}
diff --git a/library/PCUIF_Types.ttcn b/library/PCUIF_Types.ttcn
index 089403c7..70838845 100644
--- a/library/PCUIF_Types.ttcn
+++ b/library/PCUIF_Types.ttcn
@@ -13,46 +13,54 @@ module PCUIF_Types {
import from General_Types all;
import from Osmocom_Types all;
+import from Native_Functions all;
modulepar {
/* PCUIF version supported by the IUT */
- PCUIF_Version mp_pcuif_version := 9;
+ PCUIF_Version mp_pcuif_version := 12;
};
const charstring PCU_SOCK_DEFAULT := "/tmp/pcu_bts";
-type integer PCUIF_Version (9); /* supported versions */
+type integer PCUIF_Version (11..12); /* supported versions */
type enumerated PCUIF_MsgType {
PCU_IF_MSG_DATA_REQ ('00'O),
- PCU_IF_MSG_DATA_CNF ('01'O),
+ /* RFU, removed in PCUIFv11 ('01'O), */
PCU_IF_MSG_DATA_IND ('02'O),
PCU_IF_MSG_SUSP_REQ ('03'O),
PCU_IF_MSG_APP_INFO_REQ ('04'O),
PCU_IF_MSG_RTS_REQ ('10'O),
- PCU_IF_MSG_DATA_CNF_DT ('11'O),
+ PCU_IF_MSG_DATA_CNF_2 ('11'O),
PCU_IF_MSG_RACH_IND ('22'O),
PCU_IF_MSG_INFO_IND ('32'O),
+ PCU_IF_MSG_E1_CCU_IND ('33'O),
PCU_IF_MSG_ACT_REQ ('40'O),
PCU_IF_MSG_TIME_IND ('52'O),
+ PCU_IF_MSG_INTERF_IND ('53'O),
PCU_IF_MSG_PAG_REQ ('60'O),
- PCU_IF_MSG_TXT_IND ('70'O)
+ PCU_IF_MSG_TXT_IND ('70'O),
+ PCU_IF_MSG_CONTAINER ('80'O),
+ /* Container payload message types: */
+ PCU_IF_MSG_NEIGH_ADDR_REQ ('81'O),
+ PCU_IF_MSG_NEIGH_ADDR_CNF ('82'O)
} with { variant "FIELDLENGTH(8)" };
type enumerated PCUIF_Sapi {
PCU_IF_SAPI_UNKNOWN ('00'O),
PCU_IF_SAPI_RACH ('01'O),
- PCU_IF_SAPI_AGCH ('02'O),
- PCU_IF_SAPI_PCH ('03'O),
+ /* RFU, removed in PCUIFv11 ('02'O), */
+ /* RFU, removed in PCUIFv11 ('03'O), */
PCU_IF_SAPI_BCCH ('04'O),
PCU_IF_SAPI_PDTCH ('05'O),
PCU_IF_SAPI_PRACH ('06'O),
PCU_IF_SAPI_PTCCH ('07'O),
- PCU_IF_SAPI_AGCH_DT ('08'O)
+ PCU_IF_SAPI_PCH_2 ('08'O),
+ PCU_IF_SAPI_AGCH_2 ('09'O)
} with { variant "FIELDLENGTH(8)" };
type record PCUIF_Flags {
boolean bts_active,
- boolean sysmo_direct_dsp,
+ boolean direct_phy,
BIT14 spare,
boolean cs1,
boolean cs2,
@@ -70,6 +78,16 @@ type record PCUIF_Flags {
BIT3 spare2
} with { variant "" };
+type enumerated PCUIF_bts_model {
+ PCU_IF_BTS_MODEL_UNSPEC ('00'O),
+ PCU_IF_BTS_MODEL_LC15 ('01'O),
+ PCU_IF_BTS_MODEL_OC2G ('02'O),
+ PCU_IF_BTS_MODEL_OCTPHY ('03'O),
+ PCU_IF_BTS_MODEL_SYSMO ('04'O),
+ PCU_IF_BTS_MODEL_TRX ('05'O),
+ PCU_IF_BTS_MODEL_RBS ('06'O)
+} with { variant "FIELDLENGTH(8)" };
+
type enumerated PCUIF_TextType {
PCU_VERSION (0),
PCU_OML_ALERT (1)
@@ -95,21 +113,17 @@ type record PCUIF_data {
uint16_t ber10k,
int16_t ta_offs_qbits,
int16_t lqual_cb
-} with { variant (data) "FIELDLENGTH(162), ALIGN(left)" };
+} with {
+ variant (data) "FIELDLENGTH(162), ALIGN(left)"
+ variant (lqual_cb) "COMP(2scompl)"
+};
-type record PCUIF_data_cnf_dt {
+type record PCUIF_data_cnf {
PCUIF_Sapi sapi,
- OCT4 tlli,
- uint32_t fn,
- uint16_t arfcn,
- uint8_t trx_nr,
- uint8_t ts_nr,
- uint8_t block_nr,
- int8_t rssi,
- uint16_t ber10k,
- int16_t ta_offs_qbits,
- int16_t lqual_cb
-} with { variant "" };
+ OCT4 msg_id
+} with {
+ variant (msg_id) "BYTEORDER(last)"
+};
type record PCUIF_rts_req {
PCUIF_Sapi sapi,
@@ -140,12 +154,22 @@ type record PCUIF_rach_ind {
uint8_t ts_nr
} with { variant "" };
-type record PCUIF_InfoTrx {
- uint16_t arfcn,
- BIT8 pdch_mask,
- OCT1 spare,
- OCT8 tsc,
- uint32_t hLayer1
+type record PCUIF_InfoTrxTs {
+ uint8_t tsc,
+ uint8_t hopping,
+ uint8_t hsn,
+ uint8_t maio,
+ uint8_t ma_bit_len,
+ bitstring ma length(64)
+} with { variant (ma) "BYTEORDER(first), BITORDER(msb)" };
+private type record length(8) of PCUIF_InfoTrxTs PCUIF_InfoTrxTsList;
+
+private type record PCUIF_InfoTrx {
+ uint16_t arfcn,
+ BIT8 pdch_mask,
+ OCT1 spare,
+ uint32_t hLayer1,
+ PCUIF_InfoTrxTsList ts
} with { variant (pdch_mask) "BITORDER(msb)" };
type record length(8) of PCUIF_InfoTrx PCUIF_InfoTrxs;
@@ -174,9 +198,9 @@ type record PCUIF_info_ind {
uint8_t t3191,
uint8_t t3193_10ms,
uint8_t t3195,
- uint8_t t3101,
- uint8_t t3103,
- uint8_t t3105,
+ uint8_t n3101,
+ uint8_t n3103,
+ uint8_t n3105,
uint8_t cv_countdown,
uint16_t dl_tbf_ext,
uint16_t ul_tbf_ext,
@@ -184,10 +208,38 @@ type record PCUIF_info_ind {
uint8_t initial_mcs,
record length(2) of uint16_t nsvci,
- record length(2) of uint16_t local_pprt,
+ record length(2) of uint16_t local_port,
record length(2) of uint16_t remote_port,
- record length(2) of OCT4 remote_ip
-} with { variant "" }
+ PCUIF_RemoteAddr remote_addr,
+
+ /* The bts_model field was introduced with PCUIF v12 as a new mandatory field. This also means that when we
+ * use the testsuite to test against latest builds (still uses PCUIF v11) this field is not included in
+ * the PCUIF_info_ind message. Since the testsuite does not check on this field we decided to declare the
+ * field as an optional field until PCUIF v12 is also used in the latest builds.*/
+ PCUIF_bts_model bts_model optional
+} with { variant "" };
+
+type enumerated PCUIF_AddrType {
+ PCUIF_ADDR_TYPE_UNSPEC ('00'O),
+ PCUIF_ADDR_TYPE_IPV4 ('04'O),
+ PCUIF_ADDR_TYPE_IPV6 ('29'O)
+} with { variant "FIELDLENGTH(8)" };
+
+type record PCUIF_RemoteAddr {
+ record length(2) of PCUIF_AddrType addr_type,
+ record length(2) of octetstring addr length(16)
+} with { variant "" };
+
+/* E1 CCU connection parameters */
+type record PCUIF_e1_ccu_ind {
+ /* GSM/GPRS air interface */
+ uint8_t trx_nr,
+ uint8_t ts_nr,
+ /* E1 line interface */
+ uint8_t e1_nr,
+ uint8_t e1_ts,
+ uint8_t e1_ts_ss
+} with { variant "" };
type record PCUIF_act_req {
uint8_t is_activate,
@@ -200,6 +252,14 @@ type record PCUIF_time_ind {
uint32_t fn
} with { variant "" };
+type record length(8) of uint8_t PCUIF_interf;
+type record PCUIF_interf_ind {
+ uint8_t trx_nr,
+ OCT3 spare,
+ uint32_t fn,
+ PCUIF_interf interf
+} with { variant "" };
+
type record PCUIF_pag_req {
PCUIF_Sapi sapi,
uint8_t chan_needed,
@@ -222,21 +282,99 @@ type record PCUIF_susp_req {
variant (tlli) "BYTEORDER(last)"
};
+type record PCUIF_neigh_addr_req {
+ uint16_t local_lac,
+ uint16_t local_ci,
+ uint16_t tgt_arfcn,
+ uint8_t tgt_bsic
+} with { variant (local_lac) "BYTEORDER(last)"
+ variant (local_ci) "BYTEORDER(last)"
+ variant (tgt_arfcn) "BYTEORDER(last)" };
+
+type record PCUIF_neigh_addr_cnf {
+ PCUIF_neigh_addr_req orig_req,
+ uint8_t error_code,
+ uint16_t mcc,
+ uint16_t mnc,
+ uint8_t mnc_3_digits,
+ uint16_t lac,
+ uint8_t rac,
+ uint16_t cell_identity
+} with { variant (mcc) "BYTEORDER(last)"
+ variant (mnc) "BYTEORDER(last)"
+ variant (lac) "BYTEORDER(last)"
+ variant (cell_identity) "BYTEORDER(last)" };
+
+type union PCUIF_ContainerMsgUnion {
+ PCUIF_neigh_addr_req neigh_addr_req,
+ PCUIF_neigh_addr_cnf neigh_addr_cnf,
+ octetstring other
+} with { variant "" };
+
+type record PCUIF_container {
+ PCUIF_MsgType msg_type,
+ OCT1 spare,
+ uint16_t len, /* network byte order */
+ PCUIF_ContainerMsgUnion u
+} with {
+ variant (len) "BYTEORDER(last)"
+ variant (len) "LENGTHTO(u)"
+ variant (u) "CROSSTAG(
+ neigh_addr_req, msg_type = PCU_IF_MSG_NEIGH_ADDR_REQ;
+ neigh_addr_cnf, msg_type = PCU_IF_MSG_NEIGH_ADDR_CNF;
+ other, OTHERWISE)"
+};
+
+/* Record to send a (confirmed) IMMEDIATE ASSIGNMENT message via PCH. The record is sent by the PCU to the BTS as a
+ * data request (data_req) under SAPI PCU_IF_SAPI_PCH_2. */
+type record PCUIF_pch {
+ OCT4 msg_id,
+ charstring imsi length(17),
+ octetstring data length(23),
+ boolean confirm
+} with {
+ variant (msg_id) "BYTEORDER(last)"
+ variant (imsi) "FIELDLENGTH(17)"
+ variant (data) "FIELDLENGTH(23)"
+};
+
+external function enc_PCUIF_pch(in PCUIF_pch pdu) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_PCUIF_pch(in octetstring stream) return PCUIF_pch
+ with { extension "prototype(convert) decode(RAW)" };
+
+/* Record to send a (confirmed) IMMEDIATE ASSIGNMENT message via AGCH. The record is sent by the PCU to the BTS as a
+ * data request (data_req) under SAPI PCU_IF_SAPI_AGCH_2. */
+type record PCUIF_agch {
+ OCT4 msg_id,
+ octetstring data length(23),
+ boolean confirm
+} with {
+ variant (msg_id) "BYTEORDER(last)"
+ variant (data) "FIELDLENGTH(23)"
+};
+
+external function enc_PCUIF_agch(in PCUIF_agch pdu) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_PCUIF_agch(in octetstring stream) return PCUIF_agch
+ with { extension "prototype(convert) decode(RAW)" };
type union PCUIF_MsgUnion {
PCUIF_data data_req,
- PCUIF_data data_cnf,
- PCUIF_data_cnf_dt data_cnf_dt,
+ PCUIF_data_cnf data_cnf2,
PCUIF_data data_ind,
PCUIF_susp_req susp_req,
PCUIF_rts_req rts_req,
PCUIF_rach_ind rach_ind,
PCUIF_txt_ind txt_ind,
PCUIF_info_ind info_ind,
+ PCUIF_e1_ccu_ind e1_ccu_ind,
PCUIF_act_req act_req,
PCUIF_time_ind time_ind,
+ PCUIF_interf_ind interf_ind,
PCUIF_pag_req pag_req,
- PCUIF_app_info_req app_info_req
+ PCUIF_app_info_req app_info_req,
+ PCUIF_container container
} with { variant "" };
type record PCUIF_Message {
@@ -246,19 +384,22 @@ type record PCUIF_Message {
PCUIF_MsgUnion u
} with { variant (u) "CROSSTAG(
data_req, msg_type = PCU_IF_MSG_DATA_REQ;
- data_cnf, msg_type = PCU_IF_MSG_DATA_CNF;
- data_cnf_dt, msg_type = PCU_IF_MSG_DATA_CNF_DT;
+ data_cnf2, msg_type = PCU_IF_MSG_DATA_CNF_2;
data_ind, msg_type = PCU_IF_MSG_DATA_IND;
susp_req, msg_type = PCU_IF_MSG_SUSP_REQ;
rts_req, msg_type = PCU_IF_MSG_RTS_REQ;
rach_ind, msg_type = PCU_IF_MSG_RACH_IND;
txt_ind, msg_type = PCU_IF_MSG_TXT_IND;
info_ind, msg_type = PCU_IF_MSG_INFO_IND;
+ e1_ccu_ind, msg_type = PCU_IF_MSG_E1_CCU_IND;
act_req, msg_type = PCU_IF_MSG_ACT_REQ;
time_ind, msg_type = PCU_IF_MSG_TIME_IND;
+ interf_ind, msg_type = PCU_IF_MSG_INTERF_IND;
pag_req, msg_type = PCU_IF_MSG_PAG_REQ;
- app_info_req, msg_type = PCU_IF_MSG_APP_INFO_REQ)"
- variant "PADDING(1696)" /* 212 * 8 */
+ app_info_req, msg_type = PCU_IF_MSG_APP_INFO_REQ;
+ container, msg_type = PCU_IF_MSG_CONTAINER)"
+ /* PCUIFv12: 1007 * 8 = 8056 bits */
+ variant "PADDING(8056)"
};
external function enc_PCUIF_Message(in PCUIF_Message pdu) return octetstring
@@ -266,7 +407,6 @@ external function enc_PCUIF_Message(in PCUIF_Message pdu) return octetstring
external function dec_PCUIF_Message(in octetstring stream) return PCUIF_Message
with { extension "prototype(convert) decode(RAW)" };
-
/* Generic template for matching messages by type and/or the BTS number */
template PCUIF_Message tr_PCUIF_MSG(template PCUIF_MsgType msg_type := ?,
template uint8_t bts_nr := ?) := {
@@ -415,7 +555,7 @@ template (value) PCUIF_Message ts_PCUIF_DATA_IND(template (value) uint8_t bts_nr
template (value) int8_t rssi := -80,
template (value) uint16_t ber10k := 0,
template (value) int16_t ta_offs_qbits := 0,
- template (value) uint16_t lqual_cb := 10) := {
+ template (value) int16_t lqual_cb := 10) := {
msg_type := PCU_IF_MSG_DATA_IND,
bts_nr := bts_nr,
spare := '0000'O,
@@ -463,6 +603,28 @@ template PCUIF_Message tr_PCUIF_DATA_IND(template uint8_t bts_nr := ?,
}
}
+template PCUIF_data tr_PCUIF_DATA(template uint8_t trx_nr,
+ template uint8_t ts_nr,
+ template uint8_t block_nr := ?,
+ template uint32_t fn := ?,
+ template PCUIF_Sapi sapi := ?,
+ template octetstring data := ?) := {
+ sapi := sapi,
+ len := ?,
+ data := data,
+ fn := fn,
+ arfcn := ?, /* unused in BTS */
+ trx_nr := trx_nr,
+ ts_nr := ts_nr,
+ block_nr := block_nr,
+ /* measurement parameters below unused on Tx */
+ rssi := 0,
+ ber10k := 0,
+ ta_offs_qbits := 0,
+ lqual_cb := 0
+
+}
+
template (value) PCUIF_Message ts_PCUIF_DATA_REQ(uint8_t bts_nr, uint8_t trx_nr,
uint8_t ts_nr, uint8_t block_nr,
uint32_t fn, PCUIF_Sapi sapi,
@@ -499,74 +661,33 @@ template PCUIF_Message tr_PCUIF_DATA_REQ(template uint8_t bts_nr,
bts_nr := bts_nr,
spare := '0000'O,
u := {
- data_req := {
- sapi := sapi,
- len := ?,
- data := data,
- fn := fn,
- arfcn := ?, /* unused in BTS */
- trx_nr := trx_nr,
- ts_nr := ts_nr,
- block_nr := block_nr,
- /* measurement parameters below unused on Tx */
- rssi := 0,
- ber10k := 0,
- ta_offs_qbits := 0,
- lqual_cb := 0
- }
+ data_req := tr_PCUIF_DATA(trx_nr, ts_nr, block_nr, fn, sapi, data)
}
}
-template (value) PCUIF_Message ts_PCUIF_DATA_CNF(template (value) uint8_t bts_nr,
- template (value) uint8_t trx_nr,
- template (value) uint8_t ts_nr,
- template (value) uint8_t block_nr,
- template (value) uint32_t fn,
- template (value) uint16_t arfcn,
- template (value) PCUIF_Sapi sapi,
- template (value) octetstring data) := {
- msg_type := PCU_IF_MSG_DATA_CNF,
+template (value) PCUIF_Message ts_PCUIF_DATA_CNF_2(template (value) uint8_t bts_nr,
+ template (value) PCUIF_Sapi sapi,
+ template (value) OCT4 msg_id) := {
+ msg_type := PCU_IF_MSG_DATA_CNF_2,
bts_nr := bts_nr,
spare := '0000'O,
u := {
- data_cnf := {
+ data_cnf2 := {
sapi := sapi,
- len := 0, /* overwritten */
- data := data,
- fn := fn,
- arfcn := arfcn,
- trx_nr := trx_nr,
- ts_nr := ts_nr,
- block_nr := block_nr,
- rssi := 0,
- ber10k := 0,
- ta_offs_qbits := 0,
- lqual_cb := 0
+ msg_id := msg_id
}
}
}
-template PCUIF_Message tr_PCUIF_DATA_CNF(template uint8_t bts_nr := ?,
- template uint8_t trx_nr := ?,
- template uint8_t ts_nr := ?,
- template PCUIF_Sapi sapi := ?,
- template octetstring data := ?) := {
- msg_type := PCU_IF_MSG_DATA_CNF,
+template PCUIF_Message tr_PCUIF_DATA_CNF_2(template uint8_t bts_nr,
+ template PCUIF_Sapi sapi := ?,
+ template OCT4 msg_id := ?) := {
+ msg_type := PCU_IF_MSG_DATA_CNF_2,
bts_nr := bts_nr,
spare := ?,
u := {
- data_cnf := {
+ data_cnf2 := {
sapi := sapi,
- len := ?,
- data := data,
- fn := ?,
- arfcn := ?,
- trx_nr := trx_nr,
- ts_nr := ts_nr,
- block_nr := ?,
- rssi := ?,
- ber10k := ?,
- ta_offs_qbits := ?,
- lqual_cb := ?
+ msg_id := msg_id
}
}
}
@@ -658,7 +779,7 @@ template PCUIF_Message tr_PCUIF_PAG_REQ(template uint8_t bts_nr := ?,
const PCUIF_Flags c_PCUIF_Flags_default := {
bts_active := true,
- sysmo_direct_dsp := false,
+ direct_phy := false,
spare := '00000000000000'B,
cs1 := true,
cs2 := true,
@@ -676,21 +797,98 @@ const PCUIF_Flags c_PCUIF_Flags_default := {
spare2 := '000'B
};
-template (value) PCUIF_InfoTrx ts_PCUIF_InfoTrx(template (value) uint16_t arfcn := 871,
- template (value) BIT8 pdch_mask := '00000001'B,
- OCT1 tsc := '07'O) := {
+const PCUIF_Flags c_PCUIF_Flags_noMCS := {
+ bts_active := true,
+ direct_phy := false,
+ spare := '00000000000000'B,
+ cs1 := true,
+ cs2 := true,
+ cs3 := true,
+ cs4 := true,
+ mcs1 := false,
+ mcs2 := false,
+ mcs3 := false,
+ mcs4 := false,
+ mcs5 := false,
+ mcs6 := false,
+ mcs7 := false,
+ mcs8 := false,
+ mcs9 := false,
+ spare2 := '000'B
+};
+
+function f_pcuif_ind_flags_egprs_enabled(PCUIF_Flags flags) return boolean {
+ return flags.mcs1 or flags.mcs2 or flags.mcs3 or flags.mcs4 or
+ flags.mcs5 or flags.mcs6 or flags.mcs7 or flags.mcs8 or
+ flags.mcs9;
+}
+
+template (value) PCUIF_InfoTrxTs ts_PCUIF_InfoTrxTsH0(template (value) uint3_t tsc := 7) := {
+ tsc := tsc,
+ hopping := 0,
+ hsn := 0, maio := 0,
+ ma_bit_len := 0,
+ ma := f_pad_bit(''B, 64, '0'B)
+};
+template PCUIF_InfoTrxTs tr_PCUIF_InfoTrxTsH0(template uint3_t tsc := ?) := {
+ tsc := tsc,
+ hopping := 0,
+ hsn := ?, maio := ?,
+ ma_bit_len := ?,
+ ma := ?
+};
+
+template (value) PCUIF_InfoTrxTs ts_PCUIF_InfoTrxTsH1(template (value) uint3_t tsc := 7,
+ template (value) uint6_t hsn := 0,
+ template (value) uint6_t maio := 0,
+ template (value) bitstring ma := ''B) := {
+ tsc := tsc,
+ hopping := 1,
+ hsn := hsn,
+ maio := maio,
+ ma_bit_len := lengthof(valueof(ma)),
+ ma := f_pad_bit(valueof(ma), 64, '0'B)
+};
+template PCUIF_InfoTrxTs tr_PCUIF_InfoTrxTsH1(template uint3_t tsc := ?,
+ template uint6_t hsn := ?,
+ template uint6_t maio := ?,
+ template bitstring ma := ?,
+ template uint8_t ma_bit_len := ?) := {
+ tsc := tsc,
+ hopping := 1,
+ hsn := hsn,
+ maio := maio,
+ ma_bit_len := ma_bit_len,
+ ma := ma
+};
+
+template (value) PCUIF_InfoTrx
+ts_PCUIF_InfoTrx(template (value) uint16_t arfcn := 871,
+ template (value) BIT8 pdch_mask := '00000001'B,
+ template (value) uint3_t tsc := 7) := {
arfcn := arfcn,
pdch_mask := pdch_mask,
spare := '00'O,
- tsc := tsc & tsc & tsc & tsc & tsc & tsc & tsc & tsc,
- hLayer1 := 0
-}
-
-template (value) PCUIF_InfoTrx ts_PCUIF_InfoTrxNULL := ts_PCUIF_InfoTrx(0, '00000000'B, '00'O);
+ hLayer1 := 0,
+ ts := {
+ ts_PCUIF_InfoTrxTsH0(tsc), ts_PCUIF_InfoTrxTsH0(tsc),
+ ts_PCUIF_InfoTrxTsH0(tsc), ts_PCUIF_InfoTrxTsH0(tsc),
+ ts_PCUIF_InfoTrxTsH0(tsc), ts_PCUIF_InfoTrxTsH0(tsc),
+ ts_PCUIF_InfoTrxTsH0(tsc), ts_PCUIF_InfoTrxTsH0(tsc)
+ }
+};
-template (value) PCUIF_InfoTrxs ts_PCUIF_InfoTrxs_def := {
- ts_PCUIF_InfoTrx, ts_PCUIF_InfoTrxNULL, ts_PCUIF_InfoTrxNULL, ts_PCUIF_InfoTrxNULL,
- ts_PCUIF_InfoTrxNULL, ts_PCUIF_InfoTrxNULL, ts_PCUIF_InfoTrxNULL, ts_PCUIF_InfoTrxNULL };
+template (value) PCUIF_InfoTrxs
+ts_PCUIF_InfoTrxs_def(uint16_t base_arfcn) := {
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 0),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 1),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 2),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 3),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 4),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 5),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 6),
+ ts_PCUIF_InfoTrx(arfcn := base_arfcn + 7)
+};
template (value) PCUIF_Message ts_PCUIF_INFO_IND(template (value) uint8_t bts_nr,
template (value) PCUIF_info_ind info_ind) := {
@@ -730,18 +928,20 @@ template PCUIF_Message tr_PCUIF_INFO_IND(template uint8_t bts_nr := ?,
t3191 := ?,
t3193_10ms := ?,
t3195 := ?,
- t3101 := ?,
- t3103 := ?,
- t3105 := ?,
+ n3101 := ?,
+ n3103 := ?,
+ n3105 := ?,
cv_countdown := ?,
dl_tbf_ext := ?,
ul_tbf_ext := ?,
initial_cs := ?,
initial_mcs := ?,
nsvci := ?,
- local_pprt := ?,
+ local_port := ?,
remote_port := ?,
- remote_ip := ?
+ remote_addr := ?,
+ /* See note in record PCUIF_info_ind */
+ bts_model := *
}
}
}
@@ -769,6 +969,41 @@ template PCUIF_Message tr_PCUIF_TIME_IND(template uint8_t bts_nr,
}
}
+template (value) PCUIF_Message
+ts_PCUIF_INTERF_IND(template (value) uint8_t bts_nr,
+ template (value) uint8_t trx_nr,
+ template (value) uint32_t fn,
+ template (value) PCUIF_interf interf) := {
+ msg_type := PCU_IF_MSG_INTERF_IND,
+ bts_nr := bts_nr,
+ spare := '0000'O,
+ u := {
+ interf_ind := {
+ trx_nr := trx_nr,
+ spare := '000000'O,
+ fn := fn,
+ interf := interf
+ }
+ }
+}
+template PCUIF_Message
+tr_PCUIF_INTERF_IND(template (present) uint8_t bts_nr := ?,
+ template (present) uint8_t trx_nr := ?,
+ template (present) uint32_t fn := ?,
+ template (present) PCUIF_interf interf := ?) := {
+ msg_type := PCU_IF_MSG_INTERF_IND,
+ bts_nr := bts_nr,
+ spare := ?,
+ u := {
+ interf_ind := {
+ trx_nr := trx_nr,
+ spare := ?,
+ fn := fn,
+ interf := interf
+ }
+ }
+}
+
template (value) PCUIF_Message ts_PCUIF_SUSP_REQ(template (value) uint8_t bts_nr,
template (value) OCT4 tlli,
template (value) OCT6 ra_id,
@@ -830,4 +1065,153 @@ template (present) PCUIF_Message tr_PCUIF_APP_INFO_REQ(template (present) uint8_
}
+template (value) PCUIF_Message ts_PCUIF_CONTAINER(template (value) uint8_t bts_nr,
+ template (value) PCUIF_container container) := {
+ msg_type := PCU_IF_MSG_CONTAINER,
+ bts_nr := bts_nr,
+ spare := '0000'O,
+ u := {
+ container := container
+ }
+}
+template (present) PCUIF_Message tr_PCUIF_CONTAINER(template (present) uint8_t bts_nr,
+ template (present) PCUIF_container container) := {
+ msg_type := PCU_IF_MSG_CONTAINER,
+ bts_nr := bts_nr,
+ spare := '0000'O,
+ u := {
+ container := container
+ }
+}
+
+template (value) PCUIF_container ts_PCUIF_CONT_OTHER(PCUIF_MsgType msg_type, template (value) octetstring payload) := {
+ msg_type := msg_type,
+ spare := '00'O,
+ len := lengthof(payload),
+ u := {
+ other := payload
+ }
+}
+template (present) PCUIF_container tr_PCUIF_CONT_OTHER(template (present) PCUIF_MsgType msg_type,
+ template (present) octetstring payload) := {
+ msg_type := msg_type,
+ spare := '00'O,
+ len := ?,
+ u := {
+ other := payload
+ }
+}
+
+template (present) PCUIF_container tr_PCUIF_CONT_NEIGH_ADDR_REQ(template (present) uint16_t local_lac := ?,
+ template (present) uint16_t local_ci := ?,
+ template (present) uint16_t tgt_arfcn := ?,
+ template (present) uint8_t tgt_bsic := ?) := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_REQ,
+ spare := '00'O,
+ len := ?,
+ u := {
+ neigh_addr_req := {
+ local_lac := local_lac,
+ local_ci := local_ci,
+ tgt_arfcn := tgt_arfcn,
+ tgt_bsic := tgt_bsic
+ }
+ }
+}
+template (present) PCUIF_Message tr_PCUIF_NEIGH_ADDR_REQ(template (present) uint8_t bts_nr,
+ template (present) uint16_t local_lac := ?,
+ template (present) uint16_t local_ci := ?,
+ template (present) uint16_t tgt_arfcn := ?,
+ template (present) uint8_t tgt_bsic := ?) := {
+ msg_type := PCU_IF_MSG_CONTAINER,
+ bts_nr := bts_nr,
+ spare := '0000'O,
+ u := {
+ container := tr_PCUIF_CONT_NEIGH_ADDR_REQ(local_lac, local_ci, tgt_arfcn, tgt_bsic)
+ }
+}
+
+template (value) PCUIF_container ts_PCUIF_CONT_NEIGH_ADDR_CNF(template (value) PCUIF_neigh_addr_req orig_req,
+ template (value) uint8_t error_code := 0,
+ template (value) uint16_t mcc := 0,
+ template (value) uint16_t mnc := 0,
+ template (value) uint8_t mnc_3_digits := 0,
+ template (value) uint16_t lac := 0,
+ template (value) uint8_t rac := 0,
+ template (value) uint16_t cell_identity := 0) := {
+ msg_type := PCU_IF_MSG_NEIGH_ADDR_CNF,
+ spare := '00'O,
+ len := 0, /* overwritten */
+ u := {
+ neigh_addr_cnf := {
+ orig_req := orig_req,
+ error_code := error_code,
+ mcc := mcc,
+ mnc := mnc,
+ mnc_3_digits := mnc_3_digits,
+ lac := lac,
+ rac := rac,
+ cell_identity := cell_identity
+ }
+ }
+}
+template (value) PCUIF_Message ts_PCUIF_NEIGH_ADDR_CNF(template (value) uint8_t bts_nr,
+ template (value) PCUIF_neigh_addr_req orig_req,
+ template (value) uint8_t error_code := 0,
+ template (value) uint16_t mcc := 0,
+ template (value) uint16_t mnc := 0,
+ template (value) uint8_t mnc_3_digits := 0,
+ template (value) uint16_t lac := 0,
+ template (value) uint8_t rac := 0,
+ template (value) uint16_t cell_identity := 0) := {
+ msg_type := PCU_IF_MSG_CONTAINER,
+ bts_nr := bts_nr,
+ spare := '0000'O,
+ u := {
+ container := ts_PCUIF_CONT_NEIGH_ADDR_CNF(orig_req, error_code, mcc, mnc, mnc_3_digits,
+ lac, rac, cell_identity)
+ }
+}
+
+function f_PCUIF_PDCHMask_set(inout PCUIF_info_ind info, BIT8 pdch_mask,
+ template (present) uint8_t trx_nr := ?)
+{
+ for (var integer nr := 0; nr < lengthof(info.trx); nr := nr + 1) {
+ if (match(nr, trx_nr)) {
+ info.trx[nr].pdch_mask := pdch_mask;
+ }
+ }
+}
+
+function f_PCUIF_AF2addr_type(AddressFamily address_family)
+return PCUIF_AddrType {
+ if (address_family == AF_INET) {
+ return PCUIF_ADDR_TYPE_IPV4;
+ } else if (address_family == AF_INET6) {
+ return PCUIF_ADDR_TYPE_IPV6;
+ } else {
+ return PCUIF_ADDR_TYPE_UNSPEC;
+ }
+}
+
+/* TODO: second (redundant) NSVC connection is not (yet) supported */
+function f_PCUIF_RemoteAddr(PCUIF_AddrType addr_type,
+ charstring addr_str)
+return PCUIF_RemoteAddr {
+ var PCUIF_RemoteAddr remote_addr;
+
+ remote_addr.addr_type[0] := addr_type;
+ if (addr_type == PCUIF_ADDR_TYPE_IPV4) {
+ remote_addr.addr[0] := f_inet_addr(addr_str);
+ } else {
+ remote_addr.addr[0] := f_inet6_addr(addr_str);
+ }
+
+ remote_addr.addr_type[1] := PCUIF_ADDR_TYPE_UNSPEC;
+ remote_addr.addr[1] := f_pad_oct(''O, 16, '00'O);
+
+ return remote_addr;
+}
+
+
} with { encode "RAW" variant "BYTEORDER(first)" };
diff --git a/library/PFCP_CodecPort.ttcn b/library/PFCP_CodecPort.ttcn
new file mode 100644
index 00000000..8d4078dd
--- /dev/null
+++ b/library/PFCP_CodecPort.ttcn
@@ -0,0 +1,56 @@
+/* dual-faced port sitting on top of IPL4_asp UDP to encode/decode PFCP
+ *
+ * (C) 2022 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 PFCP_CodecPort {
+
+import from IPL4asp_PortType all;
+import from IPL4asp_Types all;
+import from PFCP_Types all;
+
+/* identifies a remote peer (sender or receiver) */
+type record PFCP_Peer {
+ ConnectionId conn_id,
+ HostName remote_name,
+ PortNumber remote_port
+}
+
+type record PFCP_Unitdata {
+ PFCP_Peer peer,
+ PDU_PFCP pdu
+}
+
+/* Translation port on top of IPL4asp; ASP_Event passed through transparently */
+type port PFCP_PT message {
+ out PFCP_Unitdata;
+ in PFCP_Unitdata,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+} with { extension "user IPL4asp_PT
+ out(PFCP_Unitdata -> ASP_SendTo: function(f_enc_pfcp_unitdata))
+ in(ASP_RecvFrom -> PFCP_Unitdata: function(f_dec_pfcp_unitdata);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)" }
+
+private function f_enc_pfcp_unitdata(in PFCP_Unitdata in_ud, out ASP_SendTo out_ud) {
+ out_ud.connId := in_ud.peer.conn_id;
+ out_ud.remName := in_ud.peer.remote_name;
+ out_ud.remPort := in_ud.peer.remote_port;
+ out_ud.proto := { udp := {} };
+ out_ud.msg := enc_PDU_PFCP(in_ud.pdu);
+} with { extension "prototype(fast)" };
+
+private function f_dec_pfcp_unitdata(in ASP_RecvFrom in_ud, out PFCP_Unitdata out_ud) {
+ out_ud.peer.conn_id := in_ud.connId;
+ out_ud.peer.remote_name := in_ud.remName;
+ out_ud.peer.remote_port := in_ud.remPort;
+ out_ud.pdu := dec_PDU_PFCP(in_ud.msg);
+} with { extension "prototype(fast)" };
+
+}
diff --git a/library/PFCP_CodecPort_CtrlFunct.ttcn b/library/PFCP_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..bd6af4ba
--- /dev/null
+++ b/library/PFCP_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,43 @@
+module PFCP_CodecPort_CtrlFunct {
+
+import from PFCP_CodecPort all;
+import from IPL4asp_Types all;
+
+external function f_IPL4_listen(
+ inout PFCP_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+external function f_IPL4_connect(
+ inout PFCP_PT portRef,
+ in HostName remName,
+ in PortNumber remPort,
+ in HostName locName,
+ in PortNumber locPort,
+ in ConnectionId connId,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+external function f_IPL4_close(
+ inout PFCP_PT portRef,
+ in ConnectionId id,
+ in ProtoTuple proto := { unspecified := {} }
+ ) return Result;
+
+external function f_IPL4_setUserData(
+ inout PFCP_PT portRef,
+ in ConnectionId id,
+ in UserData userData
+ ) return Result;
+
+external function f_IPL4_getUserData(
+ inout PFCP_PT portRef,
+ in ConnectionId id,
+ out UserData userData
+ ) return Result;
+
+}
diff --git a/library/PFCP_CodecPort_CtrlFunctDef.cc b/library/PFCP_CodecPort_CtrlFunctDef.cc
new file mode 100644
index 00000000..1b51633f
--- /dev/null
+++ b/library/PFCP_CodecPort_CtrlFunctDef.cc
@@ -0,0 +1,55 @@
+#include "IPL4asp_PortType.hh"
+#include "IPL4asp_PT.hh"
+#include "PFCP_CodecPort.hh"
+
+namespace PFCP__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__IPL4__listen(
+ PFCP__CodecPort::PFCP__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__connect(
+ PFCP__CodecPort::PFCP__PT& portRef,
+ const IPL4asp__Types::HostName& remName,
+ const IPL4asp__Types::PortNumber& remPort,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+ locName, locPort, connId, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__close(
+ PFCP__CodecPort::PFCP__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto)
+ {
+ return f__IPL4__PROVIDER__close(portRef, connId, proto);
+ }
+
+ IPL4asp__Types::Result f__IPL4__setUserData(
+ PFCP__CodecPort::PFCP__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+ }
+
+ IPL4asp__Types::Result f__IPL4__getUserData(
+ PFCP__CodecPort::PFCP__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+ }
+
+}
diff --git a/library/PFCP_Emulation.ttcn b/library/PFCP_Emulation.ttcn
new file mode 100644
index 00000000..d5a15a2a
--- /dev/null
+++ b/library/PFCP_Emulation.ttcn
@@ -0,0 +1,202 @@
+/* PFCP Emulation in TTCN-3
+ *
+ * (C) 2022 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 PFCP_Emulation {
+
+import from IPL4asp_Types all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from PFCP_Types all;
+import from PFCP_CodecPort all;
+import from PFCP_CodecPort_CtrlFunct all;
+
+/***********************************************************************
+ * Main Emulation Component
+ ***********************************************************************/
+
+const integer PFCP_PORT := 8805;
+
+type enumerated PFCP_Role {
+ CPF,
+ UPF
+};
+
+type record PFCP_Emulation_Cfg {
+ HostName pfcp_bind_ip,
+ PortNumber pfcp_bind_port,
+ HostName pfcp_remote_ip,
+ PortNumber pfcp_remote_port,
+ PFCP_Role role
+};
+
+type component PFCP_Emulation_CT {
+ /* Communication with underlying PFCP CodecPort */
+ port PFCP_PT PFCP;
+
+ /* Communication with Clients */
+ port PFCPEM_PT CLIENT;
+ port PFCPEM_PROC_PT CLIENT_PROC;
+
+ /* Configuration by the user */
+ var PFCP_Emulation_Cfg g_pfcp_cfg;
+
+ /* State */
+ var integer g_pfcp_conn_id;
+ var integer g_recovery_timestamp;
+
+ var PFCPEM_conns g_conns;
+
+ var integer g_next_sequence_nr_state;
+};
+
+private function f_PFCPEM_next_sequence_nr() runs on PFCP_Emulation_CT return integer {
+ g_next_sequence_nr_state := g_next_sequence_nr_state + 1;
+ if (g_next_sequence_nr_state > 16777215) {
+ g_next_sequence_nr_state := 1;
+ }
+ return g_next_sequence_nr_state;
+}
+
+type record PFCPEM_conn {
+ PFCP_ConnHdlr vc_conn,
+ OCT8 seid optional,
+ LIN3_BO_LAST pfcp_msg_sequence_number optional
+};
+
+type record of PFCPEM_conn PFCPEM_conns;
+
+private function f_PFCPEM_conn_by_seid_or_seqnr(OCT8 seid, LIN3_BO_LAST seqnr) runs on PFCP_Emulation_CT return PFCP_ConnHdlr {
+ log("looking for seid ", seid, " seqnr ", seqnr, " in conns ", g_conns);
+ for (var integer i := 0; i < lengthof(g_conns); i := i + 1) {
+ if (isbound(g_conns[i].pfcp_msg_sequence_number)
+ and seqnr == g_conns[i].pfcp_msg_sequence_number) {
+ return g_conns[i].vc_conn;
+ }
+ if (isbound(g_conns[i].seid)
+ and seid == g_conns[i].seid) {
+ return g_conns[i].vc_conn;
+ }
+ }
+ return null;
+};
+
+private function f_PFCPEM_add_conn(PFCP_ConnHdlr vc_conn) runs on PFCP_Emulation_CT {
+ for (var integer i := 0; i < lengthof(g_conns); i := i + 1) {
+ if (g_conns[i].vc_conn == vc_conn) {
+ return;
+ }
+ }
+ /* Not in the list yet, add. */
+ var PFCPEM_conn conn := { vc_conn := vc_conn };
+ g_conns := g_conns & { conn };
+}
+
+private function f_init(PFCP_Emulation_Cfg cfg) runs on PFCP_Emulation_CT {
+ var Result res;
+
+ map(self:PFCP, system:PFCP);
+ res := PFCP_CodecPort_CtrlFunct.f_IPL4_listen(PFCP, cfg.pfcp_bind_ip, cfg.pfcp_bind_port, {udp:={}});
+ g_pfcp_conn_id := res.connId;
+
+ g_recovery_timestamp := f_rnd_int(4294967296);
+ g_pfcp_cfg := cfg;
+
+ g_conns := {};
+
+ g_next_sequence_nr_state := (1 + f_rnd_int(1000)) * 10000;
+}
+
+function main(PFCP_Emulation_Cfg cfg) runs on PFCP_Emulation_CT {
+ var PFCP_ConnHdlr vc_conn;
+ var PFCP_Unitdata ud;
+ var PDU_PFCP pdu;
+
+ f_init(cfg);
+
+ while (true) {
+ alt {
+ [] PFCP.receive(PFCP_Unitdata:?) -> value ud {
+ log("PFCP_Emulation main() PFCP.receive: ", ud);
+ vc_conn := null;
+ if (ud.pdu.s_flag == '1'B) {
+ /* There is a SEID */
+ vc_conn := f_PFCPEM_conn_by_seid_or_seqnr(ud.pdu.seid, ud.pdu.sequence_number);
+ }
+ if (vc_conn != null) {
+ log("found destination ", vc_conn);
+ CLIENT.send(ud.pdu) to vc_conn;
+ } else {
+ log("sending to all conns: ", g_conns);
+ for (var integer i := 0; i < lengthof(g_conns); i := i + 1) {
+ CLIENT.send(ud.pdu) to g_conns[i].vc_conn;
+ }
+ }
+ }
+
+ [] CLIENT.receive(PDU_PFCP:?) -> value pdu sender vc_conn {
+ log("PFCP_Emulation main() CLIENT.receive from ", vc_conn, ": ", pdu);
+ if (pdu.sequence_number == 0) {
+ pdu.sequence_number := f_PFCPEM_next_sequence_nr();
+ }
+ ud := {
+ peer := {
+ conn_id := g_pfcp_conn_id,
+ remote_name := g_pfcp_cfg.pfcp_remote_ip,
+ remote_port := g_pfcp_cfg.pfcp_remote_port
+ },
+ pdu := pdu
+ };
+
+ f_PFCPEM_add_conn(vc_conn);
+
+ PFCP.send(ud);
+ }
+
+ [] CLIENT_PROC.getcall(PFCPEM_register:{}) -> sender vc_conn {
+ log("PFCP_Emulation main() CLIENT_PROC.getcall(PFCPEM_register)");
+ f_PFCPEM_add_conn(vc_conn);
+ CLIENT_PROC.reply(PFCPEM_register:{}) to vc_conn;
+ }
+ }
+ }
+}
+
+
+/***********************************************************************
+ * Interaction between Main and Client Components
+ ***********************************************************************/
+type port PFCPEM_PT message {
+ inout PDU_PFCP;
+} with { extension "internal" };
+
+signature PFCPEM_register();
+
+type port PFCPEM_PROC_PT procedure {
+ inout PFCPEM_register;
+} with { extension "internal" };
+
+/***********************************************************************
+ * Client Component
+ ***********************************************************************/
+
+type component PFCP_ConnHdlr {
+ port PFCPEM_PT PFCP;
+ port PFCPEM_PROC_PT PFCP_PROC;
+ var PFCP_Emulation_CT vc_PFCP;
+};
+
+function f_pfcp_register() runs on PFCP_ConnHdlr {
+ PFCP_PROC.call(PFCPEM_register:{}) {
+ [] PFCP_PROC.getreply(PFCPEM_register:{});
+ }
+}
+
+}
diff --git a/library/PFCP_Templates.ttcn b/library/PFCP_Templates.ttcn
new file mode 100644
index 00000000..3acc287c
--- /dev/null
+++ b/library/PFCP_Templates.ttcn
@@ -0,0 +1,664 @@
+/* PFCP Templates in TTCN-3
+ * (C) 2022 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 PFCP_Templates {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from PFCP_Types all;
+
+type enumerated e_PFCP_Cause {
+ RESERVED (0),
+ REQUEST_ACCEPTED (1),
+ MORE_USAGE_REPORT_TO_SEND (2),
+ REQUEST_REJECTED (64),
+ SESSION_CTX_NOT_FOUND (65),
+ MANDATORY_IE_MISSING (66),
+ CONDITIONAL_IE_MISSING (67),
+ INVALID_LENGTH (68),
+ MANDATORY_IE_INCORRECT (69),
+ INVALID_FORW_POLICY (70),
+ INVALID_F_TEID_ALLOC_OPTION (71),
+ NO_ESTABLISHED_PFCP_ASSOC (72),
+ RULE_CREATION_MOD_FAILURE (73),
+ PFCP_ENTITY_IN_CONGESTION (74),
+ NO_RESOURCES_AVAILABLE (75),
+ SERVICE_NOT_SUPPORTED (76),
+ SYSTEM_FAILURE (77),
+ REDIRECTION_REQUESTED (78),
+ ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED (79)
+};
+
+template (value) Cause ts_PFCP_Cause(e_PFCP_Cause cause) := {
+ elementIdentifier := 19,
+ lengthIndicator := 0,
+ causeValue := int2oct(enum2int(cause), 1)
+};
+
+template (present) Cause tr_PFCP_Cause(e_PFCP_Cause cause) := {
+ elementIdentifier := 19,
+ lengthIndicator := ?,
+ causeValue := int2oct(enum2int(cause), 1)
+};
+
+const INT4b PFCP_Node_ID_IPv4 := 0;
+const INT4b PFCP_Node_ID_IPv6 := 1;
+const INT4b PFCP_Node_ID_FQDN := 2;
+
+template (value) Node_ID ts_PFCP_Node_ID(INT4b id_type, octetstring id_value) := {
+ elementIdentifier := 60,
+ lengthIndicator := 0,
+ node_id_type := id_type,
+ spare := '0000'B,
+ node_id_value := id_value
+};
+
+template (present) Node_ID tr_PFCP_Node_ID(template (present) INT4b id_type := ?,
+ template (present) octetstring id_value := ?) := {
+ elementIdentifier := 60,
+ lengthIndicator := ?,
+ node_id_type := id_type,
+ spare := ?,
+ node_id_value := id_value
+};
+
+/* t_PFCP_Node_ID_IPv4(f_inet_addr("127.0.0.1")) */
+template (value) Node_ID ts_PFCP_Node_ID_ipv4(OCT4 ip_value) := ts_PFCP_Node_ID(PFCP_Node_ID_IPv4, ip_value);
+template (value) Node_ID ts_PFCP_Node_ID_fqdn(charstring fqdn) := ts_PFCP_Node_ID(PFCP_Node_ID_FQDN, char2oct(fqdn));
+
+template (value) Recovery_Time_Stamp ts_PFCP_Recovery_Timestamp(LIN4_BO_LAST time_value) := {
+ elementIdentifier := 96,
+ lengthIndicator := 0,
+ time_value := time_value
+};
+
+template (present) Recovery_Time_Stamp tr_PFCP_Recovery_Timestamp(template (present) LIN4_BO_LAST time_value := ?) := {
+ elementIdentifier := 96,
+ lengthIndicator := ?,
+ time_value := time_value
+};
+
+template (value) PDU_PFCP ts_PDU_PFCP_ := {
+ s_flag := '0'B,
+ mp := '0'B,
+ spare := '000'B,
+ version := 1,
+ message_type := 0,
+ lengthIndicator := 0,
+ seid := omit,
+ sequence_number := 0,
+ spare2 := '0000'B,
+ mp_or_spare := '0000'B,
+ message_body := -
+};
+
+template (present) PDU_PFCP tr_PDU_PFCP_ := {
+ s_flag := ?,
+ mp := ?,
+ spare := ?,
+ version := 1,
+ message_type := ?,
+ lengthIndicator := ?,
+ seid := *,
+ sequence_number := ?,
+ spare2 := ?,
+ mp_or_spare := ?,
+ message_body := ?
+};
+
+template (value) PDU_PFCP ts_PDU_PFCP(LIN3_BO_LAST sequence_number := 0, template (omit) OCT8 seid := omit)
+modifies ts_PDU_PFCP_ := {
+ seid := seid,
+ sequence_number := sequence_number
+};
+
+template (present) PDU_PFCP tr_PDU_PFCP(template OCT8 seid := *)
+modifies tr_PDU_PFCP_ := {
+ seid := seid
+};
+
+template (value) PDU_PFCP ts_PFCP_Assoc_Setup_Req(template (value) Node_ID node_id, LIN4_BO_LAST recovery_timestamp)
+modifies ts_PDU_PFCP_ := {
+ message_body := {
+ pfcp_association_setup_request := {
+ node_id := node_id,
+ time_stamp := ts_PFCP_Recovery_Timestamp(recovery_timestamp),
+ up_function_features := omit,
+ cp_function_features := omit,
+ UP_IP_resource_list := omit
+ }
+ }
+};
+
+function tr_PFCP_Assoc_Setup_Req(template (present) Node_ID node_id := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP();
+ t.message_body := {
+ pfcp_association_setup_request := {
+ node_id := node_id,
+ time_stamp := ?,
+ up_function_features := *,
+ cp_function_features := *,
+ UP_IP_resource_list := *
+ }
+ };
+ return t;
+};
+
+template (value) PDU_PFCP ts_PFCP_Assoc_Setup_Resp(LIN3_BO_LAST sequence_number,
+ template (value) Node_ID node_id,
+ template (value) Cause cause,
+ LIN4_BO_LAST recovery_timestamp)
+modifies ts_PDU_PFCP_ := {
+ sequence_number := sequence_number,
+ message_body := {
+ pfcp_association_setup_response := {
+ node_id := node_id,
+ cause := cause,
+ time_stamp := ts_PFCP_Recovery_Timestamp(recovery_timestamp),
+ up_function_features := omit,
+ cp_function_features := omit,
+ UP_IP_resource_list := omit
+ }
+ }
+};
+
+function tr_PFCP_Assoc_Setup_Resp(template (present) Node_ID node_id := ?,
+ template (present) Cause cause := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP();
+ t.message_body := {
+ pfcp_association_setup_response := {
+ node_id := node_id,
+ cause := cause,
+ time_stamp := ?,
+ up_function_features := *,
+ cp_function_features := *,
+ UP_IP_resource_list := *
+ }
+ };
+ return t;
+};
+
+function ts_PFCP_Assoc_Release_Req(template (value) Node_ID node_id) return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP();
+
+ t.message_body := {
+ pfcp_association_release_request := {
+ node_id := node_id
+ }
+ };
+ return t;
+};
+
+function tr_PFCP_Assoc_Release_Resp(template (present) Node_ID node_id := ?, template (present) Cause cause := ?)
+ return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP();
+ t.message_body := {
+ pfcp_association_release_response := {
+ node_id := node_id,
+ cause := cause
+ }
+ };
+ return t;
+};
+
+template (value) F_SEID ts_PFCP_F_SEID_ipv4(OCT4 addr_v4, OCT8 seid) := {
+ elementIdentifier := 57,
+ lengthIndicator := 0,
+ v6 := '0'B,
+ v4 := '1'B,
+ spare := '000000'B,
+ seid := seid,
+ ipv4_address := addr_v4,
+ ipv6_address := omit
+}
+
+type enumerated e_PFCP_Src_Iface {
+ ACCESS (0),
+ CORE (1),
+ SGI_LAN_N6_LAN (2),
+ CP_FUNCTION (3),
+ x_5G_VN_INTERNAL (4)
+};
+
+template (value) Source_Interface ts_PFCP_Src_Iface(e_PFCP_Src_Iface iface) := {
+ elementIdentifier := 20,
+ lengthIndicator := 0,
+ interfacevalue := enum2int(iface),
+ spare := '0000'B
+}
+
+template (value) UE_IP_Address ts_PFCP_UE_IP_Address_v4(OCT4 addr_v4, boolean is_destination := true) := {
+ elementIdentifier := 93,
+ lengthIndicator := 0,
+ v6 := '0'B,
+ v4 := '1'B,
+ sd := bool2bit(is_destination),
+ spare := '00000'B,
+ ipv4_address := addr_v4,
+ ipv6_address := omit
+}
+
+template (value) F_TEID ts_PFCP_F_TEID_ipv4(OCT4 teid, OCT4 addr_v4) := {
+ elementIdentifier := 21,
+ lengthIndicator := 0,
+ v4 := '1'B,
+ v6 := '0'B,
+ ch := '0'B,
+ chid := '0'B,
+ spare := '0000'B,
+ teid := teid,
+ ipv4_address := addr_v4,
+ ipv6_address := omit,
+ choose_id := omit
+}
+
+template (value) F_TEID ts_PFCP_F_TEID_choose_v4(template (omit) OCT1 choose_id := omit) := {
+ elementIdentifier := 21,
+ lengthIndicator := 0,
+ v4 := '1'B,
+ v6 := '0'B,
+ ch := '1'B,
+ chid := '0'B,
+ spare := '0000'B,
+ teid := omit,
+ ipv4_address := omit,
+ ipv6_address := omit,
+ choose_id := choose_id
+}
+
+/* Convert plain Network Instance name to encoded (length-byte + "name") format.
+ * Works only for single-label names, i.e. no dots in the name. */
+private function f_netinst_str_to_qname(charstring name) return octetstring
+{
+ var octetstring qname := int2oct(lengthof(name), 1) & char2oct(name);
+ return qname;
+}
+
+function ts_PFCP_Network_Instance(charstring netinst_name) return Network_Instance
+{
+ var Network_Instance netinst := {
+ elementIdentifier := 22,
+ lengthIndicator := 0,
+ pdn_instance := f_netinst_str_to_qname(netinst_name)
+ }
+ return netinst;
+}
+
+template (value) PDI_IE ts_PFCP_PDI(e_PFCP_Src_Iface src_iface,
+ template (omit) F_TEID local_F_TEID := omit,
+ template (omit) UE_IP_Address ue_addr_v4 := omit,
+ template (omit) Network_Instance network_instance := omit) := {
+ elementIdentifier := 2,
+ lengthIndicator := 0,
+ grouped_ie := {
+ source_interface := ts_PFCP_Src_Iface(src_iface),
+ local_F_TEID := local_F_TEID,
+ pdn_instance := network_instance,
+ ue_ip_address := ue_addr_v4,
+ traffic_endpoint_id := omit,
+ sdf_filter_list := omit,
+ application_id := omit,
+ ethernet_packet_filter_list := omit,
+ qfi_list := omit
+ }
+}
+
+template (value) Apply_Action ts_PFCP_Apply_Action(BIT1 forw := '0'B, BIT1 drop := '0'B, BIT1 buff := '0'B) := {
+ elementIdentifier := 44,
+ lengthIndicator := 0,
+ drop := drop,
+ forw := forw,
+ buff := buff,
+ nocp := '0'B,
+ dupl := '0'B,
+ spare := '000'B
+}
+
+function ts_PFCP_Apply_Action_FORW() return template (value) Apply_Action {
+ return ts_PFCP_Apply_Action(forw := '1'B);
+}
+template (value) Apply_Action ts_PFCP_Apply_Action_DROP := ts_PFCP_Apply_Action(drop := '1'B);
+template (value) Apply_Action ts_PFCP_Apply_Action_BUFF := ts_PFCP_Apply_Action(buff := '1'B);
+
+type enumerated e_PFCP_Dest_Iface {
+ ACCESS (0),
+ CORE (1),
+ SGI_LAN_N6_LAN (2),
+ CP_FUNCTION (3),
+ LI_FUNCTION (4),
+ x_5G_VN_INTERNAL (5)
+};
+
+template (value) Destination_Interface ts_PFCP_Destination_Interface(e_PFCP_Dest_Iface di) := {
+ elementIdentifier := 42,
+ lengthIndicator := 0,
+ interface_value := enum2int(di),
+ spare := '0000'B
+}
+
+template (value) Outer_Header_Creation ts_PFCP_Outer_Header_Creation_GTP_ipv4(OCT4 remote_teid, OCT4 remote_addr_v4) := {
+ elementIdentifier := 84,
+ lengthIndicator := 0,
+ ohc_description_oct5 := '00000001'B,
+ ohc_description_oct6 := '00000000'B,
+ teid := remote_teid,
+ ipv4 := remote_addr_v4,
+ ipv6 := omit,
+ udp_port := omit
+}
+
+type enumerated e_PFCP_Outer_Header_Removal {
+ GTP_U_UDP_IPV4 (0),
+ GTP_U_UDP_IPV6 (1),
+ UDP_IPV4 (2),
+ UDP_IPV6 (3),
+ IPV4 (4),
+ IPV6 (5),
+ GTP_U_UDP_IP (6),
+ VLAN_S_TAG (7),
+ S_TAG_AND_C_TAG (8)
+};
+
+template (value) Outer_Header_Removal ts_PFCP_Outer_Header_Removal(e_PFCP_Outer_Header_Removal ohr) := {
+ elementIdentifier := 95,
+ lengthIndicator := 0,
+ ohc_description := enum2int(ohr)
+}
+
+template (value) Forwarding_Parameters ts_PFCP_Forwarding_Parameters(
+ e_PFCP_Dest_Iface dest_iface,
+ template (omit) Outer_Header_Creation outer_header_creation := omit,
+ template (omit) Network_Instance network_instance := omit
+ ) := {
+ elementIdentifier := 4,
+ lengthIndicator := 0,
+ grouped_ie := {
+ destination_interface := ts_PFCP_Destination_Interface(dest_iface),
+ pdn_Instance := network_instance,
+ redirect_information := omit,
+ outer_header_creation := outer_header_creation,
+ transport_level_marking := omit,
+ forwarding_policy := omit,
+ header_enrichment := omit,
+ traffic_endpoint_ID := omit
+ }
+}
+
+template (value) Update_Forwarding_Parameters ts_PFCP_Update_Forwarding_Parameters(
+ e_PFCP_Dest_Iface dest_iface,
+ template (omit) Outer_Header_Creation outer_header_creation := omit
+ ) := {
+ elementIdentifier := 11,
+ lengthIndicator := 0,
+ grouped_ie := {
+ destination_interface := ts_PFCP_Destination_Interface(dest_iface),
+ pdn_Instance := omit,
+ redirect_information := omit,
+ outer_header_creation := outer_header_creation,
+ transport_level_marking := omit,
+ forwarding_policy := omit,
+ header_enrichment := omit,
+ pfcpSMReq_flags := omit,
+ traffic_endpoint_id := omit
+ }
+}
+
+template (value) FAR_ID ts_PFCP_FAR_ID(LIN4_BO_LAST far_id) := {
+ elementIdentifier := 108,
+ lengthIndicator := 0,
+ id_value := far_id
+}
+
+template (value) Create_FAR ts_PFCP_Create_FAR(LIN4_BO_LAST far_id, template (value) Apply_Action aa,
+ template (omit) Forwarding_Parameters fp) := {
+ elementIdentifier := 3,
+ lengthIndicator := 0,
+ grouped_ie := {
+ far_id := ts_PFCP_FAR_ID(far_id),
+ apply_action := aa,
+ forwarding_parameters := fp,
+ duplicating_parameters := omit,
+ bar_id := omit
+ }
+}
+
+template (value) Update_FAR ts_PFCP_Update_FAR(LIN4_BO_LAST far_id, template (value) Apply_Action aa,
+ template (omit) Update_Forwarding_Parameters fp) := {
+ elementIdentifier := 10,
+ lengthIndicator := 0,
+ grouped_ie := {
+ far_id := ts_PFCP_FAR_ID(far_id),
+ apply_action := aa,
+ forwarding_parameters := fp,
+ duplicating_parameters := omit,
+ bar_id := omit
+ }
+}
+
+template (value) PDR_ID ts_PFCP_PDR_ID(OCT2 pdr_id) := {
+ elementIdentifier := 56,
+ lengthIndicator := 0,
+ rule_id := pdr_id
+}
+
+template (value) Precedence ts_PFCP_Precedence(LIN4_BO_LAST val) := {
+ elementIdentifier := 29,
+ lengthIndicator := 0,
+ precedence_value := val
+}
+
+template (value) Create_PDR ts_PFCP_Create_PDR(integer pdr_id, template (value) PDI_IE pdi,
+ template (omit) Outer_Header_Removal outer_header_removal := omit,
+ LIN4_BO_LAST far_id) := {
+ elementIdentifier := 1,
+ lengthIndicator := 0,
+ grouped_ie := {
+ pdr_id := ts_PFCP_PDR_ID(int2oct(pdr_id, 2)),
+ precedence := ts_PFCP_Precedence(0),
+ pdi := pdi,
+ outer_header_removal := outer_header_removal,
+ FAR_ID_list := { ts_PFCP_FAR_ID(far_id) },
+ uRR_ID_list := omit,
+ qER_ID_list := omit,
+ activate_predefined_rules := omit
+ }
+}
+
+function ts_PFCP_Session_Est_Req(template (value) Node_ID node_id,
+ template (value) F_SEID cp_f_seid,
+ Create_PDR_list create_pdr,
+ Create_FAR_list create_far)
+ return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP();
+ t.message_body := {
+ pfcp_session_establishment_request := {
+ node_id := node_id,
+ CP_F_SEID := cp_f_seid,
+ create_PDR_list := create_pdr,
+ create_FAR_list := create_far,
+ create_URR_list := omit,
+ create_QER_list := omit,
+ create_BAR := omit,
+ create_traffic_endpoint_list := omit,
+ pdn_type := omit,
+ node_list := omit,
+ up_inactivity_timer := omit
+ }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Est_Req() return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(?);
+ t.message_body := {
+ pfcp_session_establishment_request := {
+ node_id := ?
+ }
+ };
+ return t;
+}
+
+template (value) Created_PDR ts_PFCP_Created_PDR(PDR_ID pdr_id, template (value) F_TEID local_F_TEID) := {
+ elementIdentifier := 8,
+ lengthIndicator := 0,
+ grouped_ie := {
+ pdr_id := pdr_id,
+ local_F_TEID := local_F_TEID
+ }
+}
+
+function ts_PFCP_Session_Est_Resp(LIN3_BO_LAST seq_nr, template (value) Node_ID node_id, OCT8 seid)
+ return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP(seq_nr, seid);
+ t.sequence_number := seq_nr;
+ t.message_body := {
+ pfcp_session_establishment_response := {
+ node_id := node_id,
+ cause := ts_PFCP_Cause(REQUEST_ACCEPTED)
+ }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Est_Resp(template (present) OCT8 hdr_seid := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(hdr_seid);
+ t.message_body := {
+ pfcp_session_establishment_response := {
+ node_id := ?,
+ cause := tr_PFCP_Cause(REQUEST_ACCEPTED),
+ offending_ie := *,
+ UP_F_SEID := ?,
+ created_PDR_list := ?,
+ load_control_information := *,
+ overload_control_information := *,
+ node_list := *,
+ failed_rule_id := *,
+ created_traffic_endpoint_list := *
+ }
+ };
+ return t;
+}
+
+function ts_PFCP_Session_Mod_Req(OCT8 up_seid, Update_FAR update_far)
+ return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP(seid := up_seid);
+ t.message_body := {
+ pfcp_session_modification_request := {
+ f_seid := omit,
+ remove_PDR_list := omit,
+ remove_FAR_list := omit,
+ remove_URR_list := omit,
+ remove_QER_list := omit,
+ remove_BAR := omit,
+ remove_traffic_endpoint := omit,
+ create_PDR_list := omit,
+ create_FAR_list := omit,
+ create_URR_list := omit,
+ create_QER_list := omit,
+ create_BAR := omit,
+ create_traffic_endpoint := omit,
+ update_PDR_list := omit,
+ update_FAR_list := { update_far },
+ update_URR_list := omit,
+ update_QER_list := omit,
+ update_BAR := omit,
+ update_traffic_endpoint := omit,
+ pfcpSMReq_flags := omit,
+ query_URR_list := omit,
+ node_list := omit,
+ up_inactivity_timer := omit,
+ querry_urr_reference := omit
+ }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Mod_Req(template (present) OCT8 seid := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(seid);
+ t.message_body := {
+ pfcp_session_modification_request := ?
+ };
+ return t;
+}
+
+function ts_PFCP_Session_Mod_Resp(LIN3_BO_LAST seq_nr, OCT8 seid) return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP(seq_nr, seid);
+ t.message_body := {
+ pfcp_session_modification_response := {
+ cause := ts_PFCP_Cause(REQUEST_ACCEPTED),
+ offending_IE := omit,
+ created_PDR := omit,
+ load_control_information := omit,
+ overload_control_information := omit,
+ usage_report := omit,
+ failed_rule_id := omit,
+ additional_usage_reports_information := omit,
+ created_updated_traffic_endpoint := omit
+ }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Mod_Resp(template (present) OCT8 seid := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(seid);
+ t.message_body := {
+ pfcp_session_modification_response := ?
+ };
+ return t;
+}
+
+function ts_PFCP_Session_Del_Req(OCT8 seid) return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP(seid := seid);
+ t.message_body := {
+ pfcp_session_deletion_request := { }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Del_Req(template (present) OCT8 seid := ?) return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(seid);
+ t.message_body := {
+ pfcp_session_deletion_request := ?
+ };
+ return t;
+}
+
+function ts_PFCP_Session_Del_Resp(LIN3_BO_LAST seq_nr, OCT8 seid, e_PFCP_Cause cause := REQUEST_ACCEPTED)
+ return template (value) PDU_PFCP {
+ var template (value) PDU_PFCP t := ts_PDU_PFCP(seq_nr, seid);
+ t.message_body := {
+ pfcp_session_deletion_response := {
+ cause := ts_PFCP_Cause(cause),
+ offending_IE := omit,
+ load_control_information := omit,
+ overload_control_information := omit,
+ usage_report := omit
+ }
+ };
+ return t;
+}
+
+function tr_PFCP_Session_Del_Resp(template (present) OCT8 seid := ?,
+ template (present) Cause cause := tr_PFCP_Cause(REQUEST_ACCEPTED))
+ return template (present) PDU_PFCP {
+ var template PDU_PFCP t := tr_PDU_PFCP(seid);
+ t.message_body := {
+ pfcp_session_deletion_response := {
+ cause := cause,
+ offending_IE := *,
+ load_control_information := *,
+ overload_control_information := *,
+ usage_report := *
+ }
+ };
+ return t;
+}
+
+}
diff --git a/library/RAN_Adapter.ttcnpp b/library/RAN_Adapter.ttcnpp
index 68e1e603..c90ffce4 100644
--- a/library/RAN_Adapter.ttcnpp
+++ b/library/RAN_Adapter.ttcnpp
@@ -100,11 +100,17 @@ function f_ran_adapter_init(inout RAN_Adapter ba, in RAN_Configuration cfg, char
}
select (cfg.transport) {
case (BSSAP_TRANSPORT_AoIP, RANAP_TRANSPORT_IuCS) {
+ var template (omit) integer rctx;
+ if (not ispresent(cfg.rctx)) {
+ rctx := omit;
+ } else {
+ rctx := cfg.rctx;
+ }
ba.vc_M3UA := M3UA_CT.create(id & "-M3UA");
map(ba.vc_M3UA:SCTP_PORT, system:sctp);
/* connect MTP3 service provider (M3UA) to lower side of SCCP */
connect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
- ba.vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr, cfg.rctx));
+ ba.vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr, rctx));
}
#ifdef IPA_EMULATION_SCCP
case (BSSAP_TRANSPORT_SCCPlite_SERVER) {
diff --git a/library/RAN_Emulation.ttcnpp b/library/RAN_Emulation.ttcnpp
index a400dcda..fbe921d6 100644
--- a/library/RAN_Emulation.ttcnpp
+++ b/library/RAN_Emulation.ttcnpp
@@ -168,6 +168,7 @@ type port RAN_Conn_PT message {
#endif
#ifdef RAN_EMULATION_RANAP
RANAP_PDU,
+ RANAP_N_UNITDATA_req,
/* Client requests us to create SCCP Connection */
RANAP_Conn_Req,
#endif
@@ -406,7 +407,8 @@ runs on RAN_Emulation_CT {
return;
}
}
- testcase.stop("RAN Connection table full!");
+ setverdict(fail, "RAN Connection table full!");
+ mtc.stop;
}
private function f_conn_table_del(integer sccp_conn_id)
@@ -439,9 +441,9 @@ runs on RAN_Emulation_CT return RAN_ConnHdlr {
type record BSSAP_Conn_Req {
SCCP_PAR_Address addr_peer,
SCCP_PAR_Address addr_own,
- PDU_BSSAP bssap
+ PDU_BSSAP bssap optional
}
-template BSSAP_Conn_Req ts_BSSAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, PDU_BSSAP bssap) := {
+template BSSAP_Conn_Req ts_BSSAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, template (omit) PDU_BSSAP bssap) := {
addr_peer := peer,
addr_own := own,
bssap := bssap
@@ -502,8 +504,11 @@ private function CommonBssmapUnitdataCallback(PDU_BSSAP bssap)
runs on RAN_Emulation_CT return template PDU_BSSAP {
if (match(bssap, tr_BSSMAP_Paging)) {
var RAN_ConnHdlr client := null;
- client := f_imsi_table_find(bssap.pdu.bssmap.paging.iMSI.digits,
- bssap.pdu.bssmap.paging.tMSI.tmsiOctets);
+ var template OCT4 tmsi := omit;
+ if (ispresent(bssap.pdu.bssmap.paging.tMSI)) {
+ tmsi := bssap.pdu.bssmap.paging.tMSI.tmsiOctets;
+ }
+ client := f_imsi_table_find(bssap.pdu.bssmap.paging.iMSI.digits, tmsi);
if (client != null) {
log("CommonBssmapUnitdataCallback: IMSI/TMSI found in table, dispatching to ",
client);
@@ -515,26 +520,37 @@ runs on RAN_Emulation_CT return template PDU_BSSAP {
log("CommonBssmapUnitdataCallback: Not a paging message");
}
/* ELSE: handle in user callback */
+ if (not ispresent(g_ran_ops.unitdata_cb)) {
+ return omit;
+ }
return g_ran_ops.unitdata_cb.apply(bssap);
}
function f_bssap_reset(SCCP_PAR_Address peer, SCCP_PAR_Address own) runs on RAN_Emulation_CT {
timer T := 5.0;
var boolean append_osmux_support := append_osmux_ie();
+ var integer attempts := g_ran_ops.bssap_reset_retries;
- BSSAP.send(ts_BSSAP_UNITDATA_req(peer, own, ts_BSSMAP_Reset(0, append_osmux_support)));
- T.start;
- alt {
- [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(own, peer, tr_BSSMAP_ResetAck(append_osmux_support))) {
- log("Received RESET-ACK in response to RESET, we're ready to go!");
- }
- [] as_reset_ack(append_osmux_support);
- [] BSSAP.receive { repeat };
- [] T.timeout {
- setverdict(fail, "Timeout waiting for RESET-ACK after sending RESET");
- mtc.stop;
+ while (attempts > 0) {
+ attempts := attempts - 1;
+
+ BSSAP.send(ts_BSSAP_UNITDATA_req(peer, own, ts_BSSMAP_Reset(0, append_osmux_support)));
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_BSSAP_UNITDATA_ind(own, peer, tr_BSSMAP_ResetAck(append_osmux_support))) {
+ log("BSSMAP: Received RESET-ACK in response to RESET, we're ready to go!");
+ return;
+ }
+ [] as_reset_ack(append_osmux_support);
+ [] BSSAP.receive { repeat };
+ [] T.timeout {
+ continue;
+ }
}
}
+
+ setverdict(fail, "BSSMAP: Timeout waiting for RESET-ACK after sending RESET");
+ mtc.stop;
}
private function f_bssap_l3_is_rr(PDU_BSSAP bssap) return boolean {
@@ -547,9 +563,18 @@ private function f_bssap_l3_is_rr(PDU_BSSAP bssap) return boolean {
type record RANAP_Conn_Req {
SCCP_PAR_Address addr_peer,
SCCP_PAR_Address addr_own,
- RANAP_PDU ranap
+ RANAP_PDU ranap optional
}
-template (value) RANAP_Conn_Req ts_RANAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, RANAP_PDU ranap) := {
+template (value) RANAP_Conn_Req ts_RANAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own,
+ template (omit) RANAP_PDU ranap) := {
+ addr_peer := peer,
+ addr_own := own,
+ ranap := ranap
+};
+
+template RANAP_Conn_Req tr_RANAP_Conn_Req(template SCCP_PAR_Address peer := ?,
+ template SCCP_PAR_Address own := ?,
+ template (omit) RANAP_PDU ranap := omit) := {
addr_peer := peer,
addr_own := own,
ranap := ranap
@@ -569,7 +594,7 @@ private function f_handle_userData_RANAP(RAN_ConnHdlr client, RANAP_PDU ranap)
runs on RAN_Emulation_CT {
/* decode + send decoded RANAP to client */
var template (omit) octetstring l3 := f_ranap_extract_l3(ranap);
- if (istemplatekind(l3, "omit")) {
+ if (istemplatekind(l3, "omit") or not g_ran_ops.decode_dtap) {
CLIENT.send(ranap) to client;
} else {
var template (omit) SAPI sapi := f_ranap_extract_sapi(ranap);
@@ -658,6 +683,9 @@ runs on RAN_Emulation_CT return template RANAP_PDU {
}
/* ELSE: handle in user callback */
+ if (not ispresent(g_ran_ops.ranap_unitdata_cb)) {
+ return omit;
+ }
return g_ran_ops.ranap_unitdata_cb.apply(ranap);
}
@@ -680,12 +708,12 @@ function f_ranap_reset(SCCP_PAR_Address peer, SCCP_PAR_Address own) runs on RAN_
T.start;
alt {
[] RANAP.receive(tr_RANAP_UNITDATA_ind(own, peer, tr_RANAP_ResetAck)) {
- log("Received RESET-ACK in response to RESET, we're ready to go!");
+ log("RANAP: Received RESET-ACK in response to RESET, we're ready to go!");
}
[] as_reset_ack();
[] RANAP.receive { repeat };
[] T.timeout {
- setverdict(fail, "Timeout waiting for RESET-ACK after sending RESET");
+ setverdict(fail, "RANAP: Timeout waiting for RESET-ACK after sending RESET");
mtc.stop;
}
}
@@ -713,6 +741,7 @@ type record RanOps {
RanProtocol protocol,
RAN_Transport transport,
boolean use_osmux,
+ integer bssap_reset_retries,
/* needed for performing BSSMAP RESET */
SCCP_PAR_Address sccp_addr_local optional,
SCCP_PAR_Address sccp_addr_peer optional
@@ -720,7 +749,7 @@ type record RanOps {
template BIT4 t_ML3_DISC_CC_MM_SS := ('0011'B, '0101'B, '1011'B);
-private function f_L3_is_rr(template octetstring l3) return boolean {
+function f_L3_is_rr(template octetstring l3) return boolean {
if (not isvalue(l3)) {
return false;
}
@@ -773,7 +802,7 @@ function f_ML3_n_sd_idx(in PDU_ML3_MS_NW dtap) return integer {
}
/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
-function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+private function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
var integer n_sd_idx := f_ML3_n_sd_idx(dtap);
if (n_sd_idx < 0) {
return;
@@ -791,7 +820,7 @@ private altstep as_reset_ack(boolean append_osmux_support := false) runs on RAN_
#endif
#ifdef RAN_EMULATION_BSSAP
[] BSSAP.receive(tr_BSSAP_UNITDATA_ind(?, ?, tr_BSSMAP_Reset(append_osmux_support))) -> value ud_ind {
- log("Respoding to inbound RESET with RESET-ACK");
+ log("BSSMAP: Responding to inbound RESET with RESET-ACK");
BSSAP.send(ts_BSSAP_UNITDATA_req(ud_ind.callingAddress, ud_ind.calledAddress,
ts_BSSMAP_ResetAck(append_osmux_support)));
repeat;
@@ -799,7 +828,7 @@ private altstep as_reset_ack(boolean append_osmux_support := false) runs on RAN_
#endif
#ifdef RAN_EMULATION_RANAP
[] RANAP.receive(tr_RANAP_UNITDATA_ind(?, ?, tr_RANAP_Reset)) -> value rud_ind {
- log("Respoding to inbound IuRESET with IuRESET-ACK");
+ log("RANAP: Responding to inbound IuRESET with IuRESET-ACK");
var CN_DomainIndicator dom;
dom := rud_ind.userData.initiatingMessage.value_.Reset.protocolIEs[1].value_.cN_DomainIndicator;
RANAP.send(ts_RANAP_UNITDATA_req(rud_ind.callingAddress, rud_ind.calledAddress,
@@ -944,6 +973,7 @@ private altstep as_main_ranap() runs on RAN_Emulation_CT {
var RANAP_N_DISCONNECT_ind rdisc_ind;
var RANAP_Conn_Req creq;
var RANAP_PDU ranap;
+ var RANAP_N_UNITDATA_req ranap_ud;
var RAN_ConnHdlr vc_conn;
var PDU_DTAP_PS_MO ps_mo;
var PDU_DTAP_PS_MT ps_mt;
@@ -964,7 +994,12 @@ private altstep as_main_ranap() runs on RAN_Emulation_CT {
/* store mapping between client components and SCCP connectionId */
f_conn_table_add(vc_conn, rconn_ind.connectionId);
/* handle user payload */
- f_handle_userData_RANAP(vc_conn, rconn_ind.userData);
+ if (ispresent(rconn_ind.userData)) {
+ f_handle_userData_RANAP(vc_conn, rconn_ind.userData);
+ } else {
+ /* Notify client that we received an SCCP CR without user data */
+ CLIENT.send(ts_RANAP_Conn_Req(rconn_ind.callingAddress, rconn_ind.calledAddress, omit));
+ }
/* confirm connection establishment */
RANAP.send(ts_RANAP_CONNECT_res(rconn_ind.connectionId, omit));
}
@@ -1004,6 +1039,11 @@ private altstep as_main_ranap() runs on RAN_Emulation_CT {
RANAP.send(ts_RANAP_DATA_req(conn_id, ranap));
}
+ /* e.g. for Paging from virtual MSC/SGSN to SUT osmo-hnbgw */
+ [] CLIENT.receive(RANAP_N_UNITDATA_req:?) -> value ranap_ud sender vc_conn {
+ RANAP.send(ranap_ud);
+ }
+
/* Disconnect request client -> SCCP */
[] CLIENT.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_REQ) -> sender vc_conn {
var integer conn_id := f_conn_id_by_comp(vc_conn);
@@ -1236,16 +1276,24 @@ function main(RanOps ops, charstring id) runs on RAN_Emulation_CT {
PROC.reply(RAN_register:{l3_info, vc_hdlr}) to vc_hdlr;
}
- [] PROC.getcall(RAN_register_handoverRequest:{?,?}) -> param(targetPointCode, vc_hdlr) {
+ [] PROC.getcall(RAN_register_n_connect:{?,?}) -> param(targetPointCode, vc_hdlr) {
f_create_expect(omit, vc_hdlr, targetPointCode);
- PROC.reply(RAN_register_handoverRequest:{targetPointCode, vc_hdlr}) to vc_hdlr;
+ PROC.reply(RAN_register_n_connect:{targetPointCode, vc_hdlr}) to vc_hdlr;
+ }
+
+ [] PROC.getcall(RAN_register_sccp_cr_without_payload:{?}) -> param(vc_hdlr) {
+ f_create_expect(omit, vc_hdlr);
+ PROC.reply(RAN_register_sccp_cr_without_payload:{vc_hdlr}) to vc_hdlr;
}
[] PROC.getcall(RAN_register_imsi:{?,?,?}) -> param(imsi, tmsi, vc_hdlr) {
f_create_imsi(imsi, tmsi, vc_hdlr);
PROC.reply(RAN_register_imsi:{imsi, tmsi, vc_hdlr}) to vc_hdlr;
}
-
+ [] PROC.getcall(RAN_unregister_imsi:{?,?}) -> param(imsi, vc_hdlr) {
+ f_destroy_imsi(imsi, vc_hdlr);
+ PROC.reply(RAN_unregister_imsi:{imsi, vc_hdlr}) to vc_hdlr;
+ }
}
}
@@ -1267,17 +1315,20 @@ private function f_mgcp_ep_extract_cic(charstring inp) return integer {
type record ExpectData {
/* L3 payload based on which we can match it */
octetstring l3_payload optional,
- integer handoverRequestPointCode optional,
+ integer n_connectPointCode optional,
+ boolean sccp_cr_without_payload,
/* component reference for this connection */
RAN_ConnHdlr vc_conn
}
/* procedure based port to register for incoming connections */
signature RAN_register(in octetstring l3, in RAN_ConnHdlr hdlr);
-signature RAN_register_handoverRequest(in integer targetPointCode, in RAN_ConnHdlr hdlr);
+signature RAN_register_n_connect(in integer targetPointCode, in RAN_ConnHdlr hdlr);
+signature RAN_register_sccp_cr_without_payload(in RAN_ConnHdlr hdlr);
/* procedure based port to register for incoming IMSI/TMSI */
signature RAN_register_imsi(in hexstring imsi, in OCT4 tmsi, in RAN_ConnHdlr hdlr);
+signature RAN_unregister_imsi(in hexstring imsi, in RAN_ConnHdlr hdlr);
/* If DTAP happens across other channels (e.g. GSUP), provide manual advancing of the n_sd sequence number */
signature RAN_last_n_sd(in RAN_ConnHdlr hdlr, out N_Sd_Array last_n_sd);
@@ -1286,7 +1337,8 @@ signature RAN_last_n_sd(in RAN_ConnHdlr hdlr, out N_Sd_Array last_n_sd);
signature RAN_continue_after_n_sd(N_Sd_Array last_n_sd, in RAN_ConnHdlr hdlr);
type port RAN_PROC_PT procedure {
- inout RAN_register, RAN_register_imsi, RAN_register_handoverRequest, RAN_last_n_sd, RAN_continue_after_n_sd;
+ inout RAN_register, RAN_register_imsi, RAN_unregister_imsi, RAN_register_n_connect,
+ RAN_register_sccp_cr_without_payload, RAN_last_n_sd, RAN_continue_after_n_sd;
} with { extension "internal" };
#ifdef RAN_EMULATION_BSSAP
@@ -1295,30 +1347,40 @@ function ExpectedCreateCallback(BSSAP_N_CONNECT_ind conn_ind, charstring id)
runs on RAN_Emulation_CT return RAN_ConnHdlr {
var RAN_ConnHdlr ret := null;
var octetstring l3_info;
- var boolean handoverRequest := false;
- var integer handoverRequestPointCode;
+ var boolean n_connect := false;
+ var integer n_connectPointCode;
var integer i;
if (ischosen(conn_ind.userData.pdu.bssmap.completeLayer3Information)) {
l3_info := conn_ind.userData.pdu.bssmap.completeLayer3Information.layer3Information.layer3info;
log("ExpectedCreateCallback completeLayer3Information");
} else if (ischosen(conn_ind.userData.pdu.bssmap.handoverRequest)) {
- handoverRequest := true;
- handoverRequestPointCode := bit2int(conn_ind.calledAddress.signPointCode);
- log("ExpectedCreateCallback handoverRequest ", handoverRequestPointCode);
+ n_connect := true;
+ n_connectPointCode := bit2int(conn_ind.calledAddress.signPointCode);
+ log("ExpectedCreateCallback handoverRequest ", n_connectPointCode);
+ } else if (ischosen(conn_ind.userData.pdu.bssmap.vGCS_VBSSetup)) {
+ n_connect := true;
+ n_connectPointCode := bit2int(conn_ind.calledAddress.signPointCode);
+ log("ExpectedCreateCallback VGCS/VBS Setup ", n_connectPointCode);
+ } else if (ischosen(conn_ind.userData.pdu.bssmap.vGCS_VBSAssignmentRequest)) {
+ n_connect := true;
+ n_connectPointCode := bit2int(conn_ind.calledAddress.signPointCode);
+ log("ExpectedCreateCallback VGCS/VBS Assignment ", n_connectPointCode);
} else {
- setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3 nor a Handover Request");
+ setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3 nor a new BSS connection");
mtc.stop;
- return ret;
}
for (i := 0; i < sizeof(ExpectTable); i:= i+1) {
- if (handoverRequest) {
- log("ExpectTable[", i, "].handoverRequestPointCode = ", ExpectTable[i].handoverRequestPointCode,
- " ==? ", handoverRequestPointCode);
- if (ExpectTable[i].handoverRequestPointCode == handoverRequestPointCode) {
+ if (n_connect) {
+ log("ExpectTable[", i, "].n_connectPointCode = ", ExpectTable[i].n_connectPointCode,
+ " ==? ", n_connectPointCode);
+ if (ExpectTable[i].n_connectPointCode == n_connectPointCode) {
ret := ExpectTable[i].vc_conn;
- log("Found Expect[", i, "] for handoverRequest handled at ", ret);
+ /* release this entry to be used again */
+ ExpectTable[i].n_connectPointCode := omit;
+ ExpectTable[i].vc_conn := null;
+ log("Found Expect[", i, "] for N-CONNECT handled at ", ret);
return ret;
} else {
continue;
@@ -1339,7 +1401,6 @@ runs on RAN_Emulation_CT return RAN_ConnHdlr {
}
setverdict(fail, "Couldn't find Expect for incoming connection ", conn_ind);
mtc.stop;
- return ret;
}
#endif
@@ -1349,25 +1410,31 @@ function RanapExpectedCreateCallback(RANAP_N_CONNECT_ind conn_ind, charstring id
runs on RAN_Emulation_CT return RAN_ConnHdlr {
var RAN_ConnHdlr ret := null;
var template (omit) octetstring l3_info;
+ var boolean rx_sccp_cr_without_payload;
var integer i;
- l3_info := f_ranap_extract_l3(conn_ind.userData);
- if (istemplatekind(l3_info, "omit")) {
- setverdict(fail, "N-CONNECT.ind without NAS payload");
- mtc.stop;
- return ret;
+ if (ispresent(conn_ind.userData)) {
+ l3_info := f_ranap_extract_l3(conn_ind.userData);
+ rx_sccp_cr_without_payload := false;
+ if (istemplatekind(l3_info, "omit") and not rx_sccp_cr_without_payload) {
+ setverdict(fail, "N-CONNECT.ind without NAS payload");
+ mtc.stop;
+ return ret;
+ }
+ } else {
+ l3_info := omit;
+ rx_sccp_cr_without_payload := true;
}
for (i := 0; i < sizeof(ExpectTable); i:= i+1) {
- if (not ispresent(ExpectTable[i].l3_payload)) {
- continue;
- }
- if (valueof(l3_info) == ExpectTable[i].l3_payload) {
+ if ((rx_sccp_cr_without_payload and ExpectTable[i].sccp_cr_without_payload)
+ or (ispresent(ExpectTable[i].l3_payload) and valueof(l3_info) == ExpectTable[i].l3_payload)) {
ret := ExpectTable[i].vc_conn;
/* release this entry to be used again */
+ ExpectTable[i].sccp_cr_without_payload := false;
ExpectTable[i].l3_payload := omit;
ExpectTable[i].vc_conn := null;
- log("Found Expect[", i, "] for ", l3_info, " handled at ", ret);
+ log("Found Expect[", i, "] for l3=", l3_info, " handled at ", ret);
/* return the component reference */
return ret;
}
@@ -1379,29 +1446,33 @@ runs on RAN_Emulation_CT return RAN_ConnHdlr {
#endif
private function f_create_expect(template octetstring l3, RAN_ConnHdlr hdlr,
- template integer handoverRequestPointCode := omit)
+ template integer n_connectPointCode := omit)
runs on RAN_Emulation_CT {
var integer i;
- log("f_create_expect(l3 := ", l3, ", handoverRequest := ", handoverRequestPointCode);
+ log("f_create_expect(l3 := ", l3, ", n_connectPointCode := ", n_connectPointCode);
for (i := 0; i < sizeof(ExpectTable); i := i+1) {
if (not ispresent(ExpectTable[i].l3_payload)
- and not ispresent(ExpectTable[i].handoverRequestPointCode)) {
+ and not ExpectTable[i].sccp_cr_without_payload
+ and not ispresent(ExpectTable[i].n_connectPointCode)) {
if (ispresent(l3)) {
ExpectTable[i].l3_payload := valueof(l3);
+ } else {
+ ExpectTable[i].sccp_cr_without_payload := true;
}
- if (ispresent(handoverRequestPointCode)) {
- ExpectTable[i].handoverRequestPointCode := valueof(handoverRequestPointCode);
+ if (ispresent(n_connectPointCode)) {
+ ExpectTable[i].n_connectPointCode := valueof(n_connectPointCode);
}
ExpectTable[i].vc_conn := hdlr;
- if (ispresent(handoverRequestPointCode)) {
- log("Created Expect[", i, "] for handoverRequest to be handled at ", hdlr);
+ if (ispresent(n_connectPointCode)) {
+ log("Created Expect[", i, "] for N-CONNECT to be handled at ", hdlr);
} else {
log("Created Expect[", i, "] for ", l3, " to be handled at ", hdlr);
}
return;
}
}
- testcase.stop("No space left in ExpectTable");
+ setverdict(fail, "No space left in ExpectTable");
+ mtc.stop;
}
private function f_create_imsi(hexstring imsi, OCT4 tmsi, RAN_ConnHdlr hdlr)
@@ -1415,15 +1486,31 @@ runs on RAN_Emulation_CT {
return;
}
}
- testcase.stop("No space left in ImsiTable");
+ setverdict(fail, "No space left in ImsiTable");
+ mtc.stop;
}
+private function f_destroy_imsi(hexstring imsi, RAN_ConnHdlr hdlr)
+runs on RAN_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ImsiTable); i := i+1) {
+ if (ImsiTable[i].imsi == imsi and ImsiTable[i].comp_ref == hdlr) {
+ ImsiTable[i].comp_ref := null;
+ ImsiTable[i].imsi := omit;
+ ImsiTable[i].tmsi := 'FFFFFFFF'O;
+ log("Removed IMSI[", i, "] for ", imsi, " to be handled at ", hdlr);
+ return;
+ }
+ }
+ setverdict(fail, "Unable to find to-be-destroyed IMSI in ImsiTable");
+ mtc.stop;
+}
private function f_expect_table_init()
runs on RAN_Emulation_CT {
for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) {
ExpectTable[i].l3_payload := omit;
- ExpectTable[i].handoverRequestPointCode := omit;
+ ExpectTable[i].n_connectPointCode := omit;
+ ExpectTable[i].sccp_cr_without_payload := false;
}
}
@@ -1444,9 +1531,31 @@ runs on RAN_ConnHdlr {
}
}
+/* helper function for clients to register their IMSI/TMSI */
+function f_ran_unregister_imsi(hexstring imsi)
+runs on RAN_ConnHdlr {
+
+ BSSAP_PROC.call(RAN_unregister_imsi:{imsi, self}) {
+ [] BSSAP_PROC.getreply(RAN_unregister_imsi:{?,?}) {};
+ }
+}
+
+/* register an expect with the BSSMAP core */
+function f_ran_register_exp(octetstring l3_enc) runs on RAN_ConnHdlr {
+ BSSAP_PROC.call(RAN_register:{l3_enc, self}) {
+ [] BSSAP_PROC.getreply(RAN_register:{?, ?}) {};
+ }
+}
+
+function f_ran_register_sccp_cr_without_payload() runs on RAN_ConnHdlr {
+ BSSAP_PROC.call(RAN_register_sccp_cr_without_payload:{self}) {
+ [] BSSAP_PROC.getreply(RAN_register_sccp_cr_without_payload:{?}) {};
+ }
+}
+
#ifdef RAN_EMULATION_RANAP
/* expect a IuReleaseCommand; Confirm that; expect SCCP-level N-DISCONNET.ind */
-altstep as_iu_release_compl_disc(float t := 5.0) runs on RAN_ConnHdlr {
+altstep as_iu_release_compl_disc() runs on RAN_ConnHdlr {
var RANAP_PDU ranap;
[] BSSAP.receive(tr_RANAP_IuReleaseCommand(?)) {
BSSAP.send(ts_RANAP_IuReleaseComplete);
diff --git a/library/RAW_NS.ttcnpp b/library/RAW_NS.ttcnpp
new file mode 100644
index 00000000..da1a0ccc
--- /dev/null
+++ b/library/RAW_NS.ttcnpp
@@ -0,0 +1,583 @@
+module RAW_NS {
+
+/* Osmocom NS test suite for NS in TTCN-3
+ * (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
+ * 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
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+import from NS_Emulation all;
+import from NS_Types all;
+import from BSSGP_Types all;
+import from NS_Emulation all;
+import from Native_Functions all;
+import from IPL4asp_Types all;
+import from NS_Provider_IPL4 all;
+#ifdef NS_EMULATION_FR
+import from NS_Provider_FR all;
+#endif
+
+type record PerIPProvider {
+ NS_Provider_IPL4_CT vc_NSP_IP,
+ charstring local_ip,
+ PortNumber local_udp_port
+}
+
+public type component RAW_NS_CT {
+ /* UDP port towards the bottom (IUT) */
+ port NS_PROVIDER_PT NSCP[4];
+ var PerIPProvider ip_prov[4];
+ port NSPIP_PROC_PT NSPIP_PROC;
+#ifdef NS_EMULATION_FR
+ var NS_Provider_FR_CT vc_NSP_FR[4];
+#endif
+ var NSConfiguration g_nsconfig;
+ timer g_T_guard;
+ var boolean g_handle_rx_alive := false;
+ var boolean rawns_initialized := false;
+}
+
+public altstep as_Tguard() runs on RAW_NS_CT {
+ [] g_T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+function f_find_ip_provider(NSVCConfigurationIP nsip_config)
+runs on RAW_NS_CT return integer {
+ for (var integer idx := 0; idx < sizeof(ip_prov); idx := idx+1) {
+ if (ip_prov[idx].vc_NSP_IP == null) {
+ continue;
+ }
+
+ if (ip_prov[idx].local_ip == nsip_config.local_ip and
+ ip_prov[idx].local_udp_port == nsip_config.local_udp_port) {
+ return idx;
+ }
+ }
+ return -1;
+}
+
+function f_init_ns_codec(NSConfiguration ns_config, integer idx := 0, float guard_secs := 60.0, charstring id := testcasename()) runs on RAW_NS_CT {
+ var Result res;
+
+ if (not g_T_guard.running) {
+ g_T_guard.start(guard_secs);
+ activate(as_Tguard());
+ }
+
+ if (not rawns_initialized) {
+ for (var integer i := 0; i < sizeof(ip_prov); i := i+1) {
+ ip_prov[i].vc_NSP_IP := null;
+ }
+ rawns_initialized := true;
+ }
+
+ if (not isbound(g_nsconfig)) {
+ g_nsconfig := ns_config;
+ }
+
+ if (ischosen(ns_config.nsvc[idx].provider.ip)) {
+ var integer prov_idx := f_find_ip_provider(ns_config.nsvc[idx].provider.ip);
+ /* Connect the UDP socket
+ * check if NS_Provider_IPL4_CT is already created
+ * add list of vc_NSP_IP with entries of source ip/port
+ * add a NSVC to it */
+ if (prov_idx == -1) {
+ for (prov_idx := 0; prov_idx < sizeof(ip_prov); prov_idx := prov_idx+1) {
+ if (ip_prov[prov_idx].vc_NSP_IP == null) {
+ break;
+ }
+ }
+ if (prov_idx > sizeof(ip_prov)) {
+ /* TODO: error !! */
+ }
+ ip_prov[prov_idx].local_ip := ns_config.nsvc[idx].provider.ip.local_ip;
+ ip_prov[prov_idx].local_udp_port := ns_config.nsvc[idx].provider.ip.local_udp_port;
+ ip_prov[prov_idx].vc_NSP_IP := NS_Provider_IPL4_CT.create(id & "-provIP" & int2str(prov_idx)) alive;
+ connect(self:NSPIP_PROC, ip_prov[prov_idx].vc_NSP_IP:PROC);
+ ip_prov[prov_idx].vc_NSP_IP.start(NS_Provider_IPL4.main(ns_config.nsvc[idx], ns_config, id));
+ }
+ var integer port_idx := f_nspip_add_nsvc2(ip_prov[prov_idx].vc_NSP_IP, ns_config.nsvc[idx].provider.ip.remote_ip, ns_config.nsvc[idx].provider.ip.remote_udp_port);
+ connect(self:NSCP[idx], ip_prov[prov_idx].vc_NSP_IP:NSVC[port_idx]);
+ /* the NS_PROV_LINK_STATUS_UP is not sent by the NS_Provider_IPL4 because we connect the port manual */
+#ifdef NS_EMULATION_FR
+ } else if (ischosen(ns_config.nsvc[idx].provider.fr)) {
+ vc_NSP_FR[idx] := NS_Provider_FR_CT.create(id & "-provFR") alive;
+ connect(self:NSCP[idx], vc_NSP_FR[idx]:NSE);
+ vc_NSP_FR[idx].start(NS_Provider_FR.main(ns_config.nsvc[idx], ns_config, id));
+ NSCP[idx].receive(NS_Provider_Evt:{link_status:=NS_PROV_LINK_STATUS_UP});
+#endif
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Unsupported NS provider");
+ }
+}
+
+function f_clean_ns_codec() runs on RAW_NS_CT {
+ for (var integer i := 0; i < lengthof(ip_prov); i := i + 1) {
+ if (ip_prov[i].vc_NSP_IP != null) {
+ ip_prov[i].vc_NSP_IP.stop;
+ }
+ }
+#ifdef NS_EMULATION_FR
+ for (var integer i := 0; i < lengthof(vc_NSP_FR); i := i + 1) {
+ vc_NSP_FR[i].stop;
+ }
+#endif NS_EMULATION_FR
+}
+
+public altstep ax_rx_fail_on_any_ns(integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS nrf;
+ [] NSCP[idx].receive(PDU_NS: ?) -> value nrf {
+ setverdict(fail, "Received unexpected NS: ", nrf);
+ mtc.stop;
+ }
+}
+
+function f_ns_exp(template PDU_NS exp_rx, integer idx := 0) runs on RAW_NS_CT return PDU_NS {
+ var PDU_NS nrf;
+ log("f_ns_exp() expecting ", exp_rx);
+ /* last activated altstep has the lowest priority */
+ var default d := activate(ax_rx_fail_on_any_ns());
+ alt {
+ [] NSCP[idx].receive(PDU_NS: exp_rx) -> value nrf { }
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ }
+ deactivate(d);
+ return nrf;
+}
+
+/* perform outbound NS-ALIVE procedure */
+function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
+ NSCP[idx].send(t_NS_ALIVE);
+ alt {
+ [] NSCP[idx].receive(t_NS_ALIVE_ACK);
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ }
+}
+
+/* perform outbound NS-ALIVE procedure */
+function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
+ timer T := tout;
+ NSCP[idx].send(t_NS_ALIVE);
+ T.start;
+ alt {
+ [] NSCP[idx].receive(t_NS_ALIVE_ACK) {
+ setverdict(fail, "Received unexpected NS-ALIVE ACK");
+ }
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+}
+
+function f_outgoing_ns_reset(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
+ timer T := tout;
+ var template PDU_NS reset := ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig.nsvc[idx].nsvci, g_nsconfig.nsei)
+ NSCP[idx].send(reset);
+ T.start;
+ alt {
+ [] NSCP[idx].receive(ts_NS_RESET_ACK(g_nsconfig.nsvc[idx].nsvci, g_nsconfig.nsei)) {
+ setverdict(pass);
+ }
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Failed to receive a RESET ACK");
+ }
+ }
+}
+
+/* perform outbound NS-BLOCK procedure */
+function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
+ NSCP[idx].send(ts_NS_BLOCK(cause, g_nsconfig.nsvc[idx].nsvci));
+ alt {
+ [] NSCP[idx].receive(tr_NS_BLOCK_ACK(g_nsconfig.nsvc[idx].nsvci));
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ }
+}
+
+/* perform outbound NS-UNBLOCK procedure */
+function f_outgoing_ns_unblock(integer idx := 0) runs on RAW_NS_CT {
+ NSCP[idx].send(t_NS_UNBLOCK);
+ alt {
+ [] NSCP[idx].receive(t_NS_UNBLOCK_ACK);
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ }
+}
+
+/* receive NS-ALIVE and ACK it */
+altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ [] NSCP[idx].receive(t_NS_ALIVE) {
+ NSCP[idx].send(t_NS_ALIVE_ACK);
+ if (not oneshot) { repeat; }
+ }
+ /* in oneshot mode, ignore any NS-UNITDATA we receive meanwhile. This is
+ * particularly useful when waiting for the first NS-ALIVE after SNS-CONFIG,
+ * where there is a high chance of UNITDATA during the first Tns-test cycle
+ * before the peer sends its first NS-ALIVE after Tns-test expiration */
+ [oneshot] NSCP[idx].receive(tr_NS_UNITDATA(?,?,?)) {
+ repeat;
+ }
+}
+
+/* Transmit BSSGP RESET for given BVCI and expect ACK */
+function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, template (omit) BssgpCellId tx_cell_id, template BssgpCellId rx_cell_id,
+ integer idx := 0, boolean exp_ack := true)
+runs on RAW_NS_CT {
+ var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
+ tx_cell_id));
+ timer T := 5.0;
+ NSCP[idx].send(ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx)));
+ T.start;
+ alt {
+ [exp_ack] NSCP[idx].receive(tr_NS_UNITDATA(t_SduCtrlB, 0,
+ decmatch tr_BVC_RESET_ACK(bvci, rx_cell_id))) {
+ setverdict(pass);
+ }
+ [exp_ack] T.timeout {
+ setverdict(fail, "No response to BVC-RESET");
+ }
+ [not exp_ack] T.timeout {
+ setverdict(pass);
+ }
+ [g_handle_rx_alive] as_rx_alive_tx_ack(idx := idx);
+ [] NSCP[idx].receive { repeat; }
+ }
+}
+
+/* Receive a BSSGP RESET for given BVCI and ACK it */
+altstep as_rx_bvc_reset_tx_ack(BssgpBvci bvci, template BssgpCellId rx_cell_id, template (omit) BssgpCellId tx_cell_id,
+ boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(tr_NS_UNITDATA(t_SduCtrlB, 0,
+ decmatch tr_BVC_RESET(?, bvci, rx_cell_id)))
+ -> value ns_rf {
+ var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.pDU_NS_Unitdata.nS_SDU);
+ var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, tx_cell_id));
+ NSCP[idx].send(ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx)));
+ if (not oneshot) { repeat; }
+ }
+}
+
+
+/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
+altstep as_rx_bvc_unblock_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_UNBLOCK(bvci))) -> value ns_rf {
+ var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.pDU_NS_Unitdata.nS_SDU);
+ var PDU_BSSGP bssgp_tx := valueof(ts_BVC_UNBLOCK_ACK(bvci));
+ NSCP[idx].send(ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx)));
+ if (not oneshot) { repeat; }
+ }
+}
+
+/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
+altstep as_rx_bvc_fc_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(tr_NS_UNITDATA(t_SduCtrlB, bvci,
+ decmatch tr_BVC_FC_BVC))
+ -> value ns_rf {
+ var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.pDU_NS_Unitdata.nS_SDU);
+ var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
+ var PDU_BSSGP bssgp_tx := valueof(ts_BVC_FC_BVC_ACK(tag));
+ NSCP[idx].send(ts_NS_UNITDATA(t_SduCtrlB, bvci, enc_PDU_BSSGP(bssgp_tx)));
+ if (not oneshot) { repeat; }
+ }
+}
+
+/**********************************************************************************
+ * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
+ **********************************************************************************/
+
+/* Receive a NS-RESET and ACK it */
+public altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig.nsvc[idx].nsvci,
+ g_nsconfig.nsei)) -> value ns_rf {
+ NSCP[idx].send(ts_NS_RESET_ACK(g_nsconfig.nsvc[idx].nsvci, g_nsconfig.nsei));
+ if (not oneshot) { repeat; }
+ }
+}
+/* Receive a NS-UNBLOCK and ACK it */
+public altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(t_NS_UNBLOCK) -> value ns_rf {
+ NSCP[idx].send(t_NS_UNBLOCK_ACK);
+ if (not oneshot) { repeat; }
+ }
+}
+
+/* Receive a NS-BLOCK and ACK it */
+public altstep as_rx_ns_block_ack(boolean oneshot := false, integer idx := 0, template NsCause cause := *, template Nsvci nsvci := *) runs on RAW_NS_CT {
+ var PDU_NS ns_rf;
+ [] NSCP[idx].receive(tr_NS_BLOCK(cause, nsvci)) -> value ns_rf {
+ NSCP[idx].send(ts_NS_BLOCK_ACK(oct2int(ns_rf.pDU_NS_Block.nS_VCI.nS_VCI)));
+ if (not oneshot) { repeat; }
+ }
+}
+
+/**********************************************************************************
+ * IP Sub-Network Service (SNS)
+ **********************************************************************************/
+
+/* perform inbound SNS-SIZE procedure */
+function f_incoming_sns_size(template (omit) NsCause cause := omit, integer idx := 0,
+ template integer num_max_nsvcs := ?, template integer num_ep := ?)
+runs on RAW_NS_CT {
+ log("f_incoming_sns_size(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ /* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */
+ rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := num_max_nsvcs,
+ num_v4 := num_ep, num_v6 := omit), idx);
+ } else {
+ /* expect one single SNS-SIZE with RESET flag; no v4 EP; 4x v6 EP */
+ rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := num_max_nsvcs,
+ num_v4 := omit, num_v6 := num_ep), idx);
+ }
+ NSCP[idx].send(ts_SNS_SIZE_ACK(g_nsconfig.nsei, cause));
+}
+
+/* perform outbound SNS-SIZE procedure */
+function f_outgoing_sns_size(template (omit) NsCause cause := omit, integer max_nsvcs := 1,
+ integer num_ip := 1, integer idx:= 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_size(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ NSCP[idx].send(ts_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := max_nsvcs,
+ num_v4 := num_ip, num_v6 := omit)
+ );
+ } else {
+ NSCP[idx].send(ts_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := max_nsvcs,
+ num_v4 := omit, num_v6 := num_ip)
+ );
+ }
+ /* expect one single SNS-SIZE */
+ rx := f_ns_exp(tr_SNS_SIZE_ACK(g_nsconfig.nsei, cause), idx);
+}
+
+/* perform inbound SNS-CONFIG procedure */
+function f_incoming_sns_config(template (omit) NsCause cause := omit, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_incoming_sns_config(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template IP4_Elements v4_elem := { tr_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+ rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig.nsei, end_flag := true, v4 := v4_elem), idx);
+ } else {
+ var template IP6_Elements v6_elem := { tr_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+ rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig.nsei, end_flag := true, v6 := v6_elem), idx);
+ }
+ NSCP[idx].send(ts_SNS_CONFIG_ACK(g_nsconfig.nsei, cause));
+}
+
+/* perform outbound SNS-CONFIG procedure */
+function f_outgoing_sns_config(template (omit) NsCause cause := omit, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_config(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port) }
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port) }
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
+ }
+ rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
+}
+
+/* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
+function f_outgoing_sns_config_1c1u(template (omit) NsCause cause := omit, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_config_1c1u(idx=", idx, ")");
+ var PDU_NS rx;
+
+ if (g_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig.nsvc[0].provider.ip.local_ip,
+ g_nsconfig.nsvc[0].provider.ip.local_udp_port, 1, 0),
+ ts_SNS_IPv4(g_nsconfig.nsvc[1].provider.ip.local_ip,
+ g_nsconfig.nsvc[1].provider.ip.local_udp_port, 0, 1) };
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig.nsvc[0].provider.ip.local_ip,
+ g_nsconfig.nsvc[0].provider.ip.local_udp_port, 1, 0),
+ ts_SNS_IPv6(g_nsconfig.nsvc[1].provider.ip.local_ip,
+ g_nsconfig.nsvc[1].provider.ip.local_udp_port, 0, 1) };
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
+ }
+ rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
+}
+
+/* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
+function f_outgoing_sns_config_1c1u_separate(template (omit) NsCause cause := omit, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_config_1c1u_separate(idx=", idx, ")");
+ var PDU_NS rx;
+ if (g_nsconfig.nsvc[0].provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig.nsvc[1].provider.ip.local_ip,
+ g_nsconfig.nsvc[1].provider.ip.local_udp_port, 1, 0),
+ ts_SNS_IPv4(g_nsconfig.nsvc[2].provider.ip.local_ip,
+ g_nsconfig.nsvc[2].provider.ip.local_udp_port, 0, 1) };
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(g_nsconfig.nsvc[1].provider.ip.local_ip,
+ g_nsconfig.nsvc[1].provider.ip.local_udp_port, 1, 0),
+ ts_SNS_IPv6(g_nsconfig.nsvc[2].provider.ip.local_ip,
+ g_nsconfig.nsvc[2].provider.ip.local_udp_port, 0, 1) };
+ NSCP[idx].send(ts_SNS_CONFIG(g_nsconfig.nsei, true, omit, v6));
+ }
+ rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig.nsei, cause), idx);
+}
+
+/* perform inbound SNS-CHANGE-WEIGHT procedure */
+function f_incoming_sns_chg_weight(integer idx_chg := 0, template (omit) NsCause cause := omit, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_incoming_sns_chg_weight(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_chg];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template IP4_Elements v4_elem := { tr_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+ rx := f_ns_exp(tr_SNS_CHG_WEIGHT(g_nsconfig.nsei, ?, v4 := v4_elem), idx);
+ } else {
+ var template IP6_Elements v6_elem := { tr_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+ rx := f_ns_exp(tr_SNS_CHG_WEIGHT(g_nsconfig.nsei, ?, v4 := omit, v6 := v6_elem), idx);
+ }
+ NSCP[idx].send(ts_SNS_ACK(g_nsconfig.nsei, rx.pDU_SNS_ChangeWeight.transactionID));
+}
+
+
+/* perform inbound SNS-ADD procedure */
+function f_incoming_sns_add(integer idx_add, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0, template (omit) NsCause cause := omit)
+runs on RAW_NS_CT {
+ log("f_incoming_sns_add(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_add];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4_elem := { ts_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ w_sig, w_user) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, v4 := v4_elem), idx);
+ } else {
+ var template (omit) IP6_Elements v6_elem := { ts_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ w_sig, w_user) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, omit, v6_elem), idx);
+ }
+ NSCP[idx].send(ts_SNS_ACK(g_nsconfig.nsei, rx.pDU_SNS_Add.transactionID));
+}
+
+function f_outgoing_sns_add(integer idx_add, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0, template (omit) NsCause cause := omit)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_add(idx_add=", idx_add, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_add];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_ADD(g_nsconfig.nsei, 23, v4));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 23, cause, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_ADD(g_nsconfig.nsei, 23, omit, v6));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 23, cause, omit, v6));
+ }
+}
+
+/* perform inbound SNS-DELETE procedure */
+function f_incoming_sns_del(integer idx_del, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0, template (omit) NsCause cause := omit)
+runs on RAW_NS_CT {
+ log("f_incoming_sns_del(idx=", idx, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_del];
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4_elem := { ts_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ w_sig, w_user) };
+ rx := f_ns_exp(tr_SNS_DEL(g_nsconfig.nsei, ?, omit, v4 := v4_elem), idx);
+ } else {
+ var template (omit) IP6_Elements v6_elem := { ts_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ w_sig, w_user) };
+ rx := f_ns_exp(tr_SNS_DEL(g_nsconfig.nsei, ?, omit, omit, v6_elem), idx);
+ }
+ NSCP[idx].send(ts_SNS_ACK(g_nsconfig.nsei, rx.pDU_SNS_Delete.transactionID));
+}
+
+
+function f_outgoing_sns_del(integer idx_del, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_del(idx_del=", idx_del, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_del];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_DEL(g_nsconfig.nsei, 24, omit, v4));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 24, omit, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_DEL(g_nsconfig.nsei, 24, omit, omit, v6));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 24, omit, omit, v6));
+ }
+}
+
+function f_outgoing_sns_chg_weight(integer idx_chg, uint8_t w_sig, uint8_t w_user, integer idx := 0)
+runs on RAW_NS_CT {
+ log("f_outgoing_sns_chg_weight(idx_chg=", idx_chg, ")");
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg := g_nsconfig.nsvc[idx_chg];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_CHG_WEIGHT(g_nsconfig.nsei, 25, v4));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 25, omit, v4));
+ } else {
+ var template (omit) IP6_Elements v6 := { ts_SNS_IPv6(nsvc_cfg.provider.ip.local_ip,
+ nsvc_cfg.provider.ip.local_udp_port,
+ w_sig, w_user) };
+ NSCP[idx].send(ts_SNS_CHG_WEIGHT(g_nsconfig.nsei, 25, omit, v6));
+ rx := f_ns_exp(tr_SNS_ACK(g_nsconfig.nsei, 25, omit, omit, v6));
+ }
+}
+
+}
diff --git a/library/RLCMAC_CSN1_Templates.ttcn b/library/RLCMAC_CSN1_Templates.ttcn
index 0d7de991..a4f59f08 100644
--- a/library/RLCMAC_CSN1_Templates.ttcn
+++ b/library/RLCMAC_CSN1_Templates.ttcn
@@ -19,6 +19,28 @@ module RLCMAC_CSN1_Templates {
import from MobileL3_GMM_SM_Types all;
import from RLCMAC_CSN1_Types all;
+ /* 11.2.1 Packet Access Reject */
+ template PacketAccessRejectStruct tr_PacketAccessRejectStruct_TLLI(template GprsTlli tlli := ?,
+ template uint8_t wait_ind := *,
+ template BIT1 wait_ind_size := *) := {
+ id_type := '0'B,
+ id := {
+ tlli := tlli
+ },
+ wait_ind_presence := ?,
+ wait_ind := wait_ind,
+ wait_ind_size := wait_ind_size
+ }
+ template RlcmacDlCtrlMsg tr_RlcMacDlCtrl_PKT_ACC_REJ(template PacketAccessRejectStruct rej := ?) := {
+ msg_type := PACKET_ACCESS_REJECT,
+ u := {
+ access_reject := {
+ page_mode := ?,
+ reject_struct := rej
+ }
+ }
+ }
+
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CTRL_ACK(GprsTlli tlli,
CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
msg_type := PACKET_CONTROL_ACK,
@@ -55,58 +77,6 @@ module RLCMAC_CSN1_Templates {
}
}
- private function f_presence_bit_MultislotCap_GPRS(template (omit) MultislotCap_GPRS mscap_gprs) return BIT1 {
- if (istemplatekind(mscap_gprs, "omit")) {
- return '0'B;
- }
- return '1'B;
- }
- private function f_presence_bit_MultislotCap_EGPRS(template (omit) MultislotCap_EGPRS mscap_egprs) return BIT1 {
- if (istemplatekind(mscap_egprs, "omit")) {
- return '0'B;
- }
- return '1'B;
- }
- template (value) MSRACapabilityValuesRecord ts_RaCapRec(BIT4 att := '0001'B /* E-GSM */, template (omit) MultislotCap_GPRS mscap_gprs := omit, template (omit) MultislotCap_EGPRS mscap_egprs := omit) := {
- mSRACapabilityValues := {
- mSRACapabilityValuesExclude1111 := {
- accessTechnType := att, /* E-GSM */
- accessCapabilities := {
- lengthIndicator := 0, /* overwritten */
- accessCapabilities := {
- rfPowerCapability := '001'B, /* FIXME */
- presenceBitA5 := '0'B,
- a5bits := omit,
- esind := '1'B,
- psbit := '0'B,
- vgcs := '0'B,
- vbs := '0'B,
- presenceBitMultislot := '1'B,
- multislotcap := {
- presenceBitHscsd := '0'B,
- hscsdmultislotclass := omit,
- presenceBitGprs := f_presence_bit_MultislotCap_GPRS(mscap_gprs),
- gprsmultislot := mscap_gprs,
- presenceBitSms := '0'B,
- multislotCap_SMS := omit,
- multislotCapAdditionsAfterRel97 := {
- presenceBitEcsdmulti := '0'B,
- ecsdmultislotclass := omit,
- presenceBitEgprsmulti := f_presence_bit_MultislotCap_EGPRS(mscap_egprs),
- multislotCap_EGPRS := mscap_egprs,
- presenceBitDtmGprsmulti := '0'B,
- multislotCapdtmgprsmultislotsubclass := omit
- }
- },
- accessCapAdditionsAfterRel97 := omit
- },
- spare_bits := omit
- }
- }
- },
- presenceBitMSRACap := '0'B
- };
-
private function f_presence_bit_MSRadioAccessCapabilityV(template (omit) MSRadioAccessCapabilityV ms_rac) return BIT1 {
if (istemplatekind(ms_rac, "omit")) {
return '0'B;
@@ -131,6 +101,18 @@ module RLCMAC_CSN1_Templates {
RlcOctetCount := 0
}
+ template (value) ChannelReqDescription ts_ChannelReqDescription(uint4_t peak_tput_class := 0,
+ uint2_t priority := 0,
+ RlcMode rlc_mode := RLC_MODE_ACKNOWLEDGED,
+ LlcPduType llc_pdu_type := LLC_PDU_IS_NOT_SACK_OR_ACK,
+ uint16_t RlcOctetCount := 0) := {
+ peak_tput_class := peak_tput_class,
+ priority := priority,
+ rlc_mode := rlc_mode,
+ llc_pdu_type := llc_pdu_type,
+ RlcOctetCount := RlcOctetCount
+ };
+
/* TS 44.060 sec 11.2.16 */
template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_RES_REQ(GprsTlli tlli,
template (omit) MSRadioAccessCapabilityV ms_rac,
@@ -160,6 +142,275 @@ module RLCMAC_CSN1_Templates {
}
};
+ const CCNMeasReport ccn_meas_rep_def := {
+ rxlev_servig_cell := 0,
+ zero := '0'B,
+ num_meas := 0,
+ meas := { }
+ }
+
+ /* TS 44.060 sec 11.2.3a */
+ template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(uint5_t tfi,
+ GsmArfcn arfcn,
+ uint6_t bsic,
+ template (value) CCNMeasReport ccn_meas_rep := ccn_meas_rep_def)
+ := {
+ msg_type := PACKET_CELL_CHANGE_NOTIFICATION,
+ u := {
+ cell_chg_notif := {
+ gtfi := {
+ is_dl_tfi := false,
+ tfi := tfi
+ },
+ u := {
+ u0 := {
+ tag := '0'B,
+ arfcn := arfcn,
+ bsic := bsic
+ }
+ },
+ ba_psi3_presence := '0'B,
+ ba_used := '0'B,
+ psi3_change_mark := omit,
+ pmo_used := '0'B,
+ pccn_sending := '0'B,
+ ccn_meas_rep := ccn_meas_rep,
+ rel_additions := omit
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.3a */
+ template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF_UTRAN(uint5_t tfi,
+ uint14_t uarfcn,
+ uint10_t scrambling_code,
+ template (value) CCNMeasReport ccn_meas_rep := ccn_meas_rep_def)
+ := {
+ msg_type := PACKET_CELL_CHANGE_NOTIFICATION,
+ u := {
+ cell_chg_notif := {
+ gtfi := {
+ is_dl_tfi := false,
+ tfi := tfi
+ },
+ u := {
+ u10 := {
+ tag := '10'B,
+ utran_target_cell := {
+ fdd_presence := '1'B,
+ fdd := {
+ arfcn := uarfcn,
+ bandwidth_presence := '0'B,
+ bandwidth := omit,
+ scrambling_code := scrambling_code
+ },
+ tdd_presence := '0'B,
+ tdd := omit,
+ reporting_quantity := 1
+ }
+ }
+ },
+ ba_psi3_presence := '0'B,
+ ba_used := '0'B,
+ psi3_change_mark := omit,
+ pmo_used := '0'B,
+ pccn_sending := '0'B,
+ ccn_meas_rep := ccn_meas_rep,
+ rel_additions := omit
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.3a */
+ template (value) RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF_EUTRAN(uint5_t tfi,
+ uint16_t earfcn,
+ uint9_t phys_layer_cell_id,
+ template (value) CCNMeasReport ccn_meas_rep := ccn_meas_rep_def)
+ := {
+ msg_type := PACKET_CELL_CHANGE_NOTIFICATION,
+ u := {
+ cell_chg_notif := {
+ gtfi := {
+ is_dl_tfi := false,
+ tfi := tfi
+ },
+ u := {
+ u110 := {
+ tag := '110'B,
+ arfcn_bsic_presence := '0'B,
+ arfcn := omit,
+ bsic := omit,
+
+ utran_target_cell_presence := '0'B,
+ utran_target_cell := omit,
+
+ eutran_target_cell_presence := '1'B,
+ eutran_target_cell := {
+ earfcn := earfcn,
+ meas_bandwidth_presence := '0'B,
+ meas_bandwidth := omit,
+ phys_layer_cell_id := phys_layer_cell_id,
+ reporting_quantity := 1
+ },
+ eutran_ccn_meas_rep_presence := '1'B,
+ eutran_ccn_meas_rep := {
+ utran_ba_used := 0,
+ n_eutran := 1,
+ cells := {{frequency_list_index := 1,
+ cell_identity := phys_layer_cell_id,
+ reporting_quantity := 1}}
+ }
+ }
+ },
+ ba_psi3_presence := '0'B,
+ ba_used := '0'B,
+ psi3_change_mark := omit,
+ pmo_used := '0'B,
+ pccn_sending := '0'B,
+ ccn_meas_rep := ccn_meas_rep,
+ rel_additions := omit
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.2a */
+ template RlcmacDlCtrlMsg tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE(template GlobalTfi tfi := ?)
+ := {
+ msg_type := PACKET_CELL_CHANGE_CONTINUE,
+ u := {
+ cell_chg_continue := {
+ page_mode := ?,
+ zero := '0'B,
+ gtfi := tfi,
+ arfcn_bsic_presence := ?,
+ arfcn := *,
+ bsic := *,
+ container_id := *
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.9 */
+ template (value) NCMeasurement ts_NCMeasurement(uint6_t frequency_n, BIT6 bsic, uint6_t rxlev)
+ := {
+ frequency_n := frequency_n,
+ bsic_n_presence := '1'B,
+ bsic_n := bsic,
+ rxlev_n := rxlev
+ };
+ template (value) NCMeasurementReport ts_NCMeasurementReport(BIT1 nc_mode,
+ uint6_t rxlev_serving_cell,
+ template (value) NCMeasurementList nc_meas_list := {})
+ := {
+ nc_mode := nc_mode,
+ rxlev_serving_cell := rxlev_serving_cell,
+ zero := '0'B,
+ num_nc_measurements := 0, /* automatically updated */
+ nm_measurements := nc_meas_list
+ };
+ template RlcmacUlCtrlMsg ts_RlcMacUlCtrl_PKT_MEAS_REPORT(template (value) GprsTlli tlli,
+ template (value) NCMeasurementReport nc_meas_rep)
+ := {
+ msg_type := PACKET_MEASUREMENT_REPORT,
+ u := {
+ meas_report := {
+ tlli := tlli,
+ psi5_change_mark_presence := '0'B,
+ psi5_change_mark := omit,
+ additions_99 := '0'B,
+ nc_meas_report := nc_meas_rep
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.9b */
+ template RepeatedAddFrequencyItem tr_RepeatedAddFrequencyItem(template (present) uint10_t start_frequency := ?,
+ template (present) uint6_t bsic := ?)
+ := {
+ presence := '1'B,
+ item := {
+ start_frequency := start_frequency,
+ bsic := bsic,
+ cell_sel_par_present := ?,
+ cell_sel_par := *,
+ nr_of_frequencies := 0,
+ freq_diff_length := ?
+ /* TODO: support Frequency diff list */
+ }
+ };
+ template NCFrequencyList tr_NCFrequencyList(template FreqIndexList removed_freq_index := *, template RepeatedAddFrequencyItemList repeated_add_frequency := *)
+ := {
+ removed_freq_present := ?,
+ nr_of_removed_freq := *,
+ removed_freq_index := removed_freq_index,
+ repeated_add_frequency := repeated_add_frequency,
+ repeated_add_frequency_term := '0'B
+ };
+ template NCMeasurementParameters tr_NCMeasurementParameters(template (present) NetworkControlOrder nco := ?,
+ template uint3_t nc_non_drx_period := *,
+ template uint3_t nc_reporting_period_i := *,
+ template uint3_t nc_reporting_period_t := *,
+ template NCFrequencyList nc_freq_list := *)
+ := {
+ nco := nco,
+ nc_period_present := ?,
+ nc_non_drx_period := nc_non_drx_period,
+ nc_reporting_period_i := nc_reporting_period_i,
+ nc_reporting_period_t := nc_reporting_period_t,
+ nc_freq_list_present := ?,
+ nc_freq_list := nc_freq_list
+ };
+ /* This template is used by osmo-pcu to reset the GSM Neighbour Cell List of the MS */
+ template (value) NCMeasurementParameters ts_NCMeasurementParametersRESET
+ := {
+ nco := NC_RESET,
+ nc_period_present := '0'B,
+ nc_non_drx_period := omit,
+ nc_reporting_period_i := omit,
+ nc_reporting_period_t := omit,
+ nc_freq_list_present := '0'B,
+ nc_freq_list := omit
+ };
+ template RlcmacDlCtrlMsg tr_RlcMacDlCtrl_PKT_MEAS_ORDER(template (present) GlobalTfiOrTlli tfi_or_tlli := ?,
+ template (present) uint3_t pmo_index := ?,
+ template (present) uint3_t pmo_count := ?,
+ template (present) NCMeasurementParameters nc_meas_param := ?)
+ := {
+ msg_type := PACKET_MEASUREMENT_ORDER,
+ u := {
+ meas_order := {
+ page_mode := ?,
+ tfi_or_tlli := tfi_or_tlli,
+ pmo_index := pmo_index,
+ pmo_count := pmo_count,
+ nc_meas_param_present := '1'B,
+ nc_meas_param := nc_meas_param,
+ zero := '0'B
+ }
+ }
+ };
+
+ /* TS 44.060 sec 11.2.9e */
+ template RlcmacDlCtrlMsg tr_RlcMacDlCtrl_PKT_NEIGH_CELL_DATA(template (present) GlobalTfi tfi := ?,
+ template (present) uint5_t container_index := ?)
+ := {
+ msg_type := PACKET_NEIGHBOUR_CELL_DATA,
+ u := {
+ neighbour_cell_data := {
+ page_mode := ?,
+ zero := '0'B,
+ gtfi := tfi,
+ container_id := ?,
+ spare := '0'B,
+ container_index := container_index,
+ arfcn_bsic_presence := ?,
+ arfcn := *,
+ bsic := *,
+ container_list := ?
+ }
+ }
+ };
+
private function f_presence_bit_tfi(template uint5_t tfi) return BIT1 {
if (istemplatekind(tfi, "omit")) {
return '0'B;
@@ -248,6 +499,7 @@ module RLCMAC_CSN1_Templates {
};
template UlAckNackEgprs tr_UlAckNackEgprs(template GprsTlli tlli := *) := {
+ msg_excape := '00'B,
ch_coding_cmd := ?,
resegment := ?,
preemptive_tx := ?,
@@ -264,4 +516,10 @@ module RLCMAC_CSN1_Templates {
pwr_ctrl := *
};
+ template (value) EgprsAckNackDescriptionIE ts_EgprsAckNackDescriptionIE(template (value) EgprsAckNackDescription andesc) := {
+ len_present := '1'B,
+ len := 0, /* Overwritten by RAW encoder */
+ acknack_desc := andesc
+ }
+
} with { encode "RAW"; variant "FIELDORDER(msb)" variant "BYTEORDER(last)" };
diff --git a/library/RLCMAC_CSN1_Types.ttcn b/library/RLCMAC_CSN1_Types.ttcn
index cc1ae22a..a4ed3076 100644
--- a/library/RLCMAC_CSN1_Types.ttcn
+++ b/library/RLCMAC_CSN1_Types.ttcn
@@ -32,6 +32,8 @@ module RLCMAC_CSN1_Types {
PACKET_TBF_RELEASE ('001000'B),
PACKET_UL_ACK_NACK ('001001'B),
PACKET_UL_ASSIGNMENT ('001010'B),
+ PACKET_CELL_CHANGE_CONTINUE ('001011'B),
+ PACKET_NEIGHBOUR_CELL_DATA ('001100'B),
PACKET_DL_DUMMY_CTRL ('100101'B)
} with { variant "FIELDLENGTH(6)" };
@@ -49,7 +51,7 @@ module RLCMAC_CSN1_Types {
PACKET_EGPRS_DL_ACK_NACK ('001000'B),
PACKET_PAUSE ('001001'B),
ADDITIONAL_MS_RA_CAPABILITIES ('001011'B),
- PACKET_CELL_CANGE_NOTIFICATION ('001100'B),
+ PACKET_CELL_CHANGE_NOTIFICATION ('001100'B),
PACKET_SI_STATUS ('001101'B),
PACKET_CS_REQUEST ('001110'B),
MBMS_SERVICE_REQUEST ('001111'B),
@@ -161,6 +163,80 @@ module RLCMAC_CSN1_Types {
variant (tbf_starting_time) "PRESENCE(tbf_starting_time_present = '1'B)"
};
+ /* 11.2.9b Packet Measurement Order */
+ type enumerated NetworkControlOrder {
+ NC_0 ('00'B),
+ NC_1 ('01'B),
+ NC_2 ('10'B),
+ NC_RESET ('11'B)
+ } with { variant "FIELDLENGTH(2)" };
+ type record CellSelection {
+ BIT1 cell_barr_access_2,
+ BIT1 exc_acc,
+ BIT1 same_ra_as_serving_cell,
+ BIT1 gprs_rxlev_access_min_present ('0'B),
+ BIT1 gprs_temporary_offset_present ('0'B),
+ BIT1 gprs_reselct_offset_present ('0'B),
+ BIT1 hcs_params_present ('0'B),
+ BIT1 si13_pbcch_location_present ('0'B)
+ /* TODO: add optional parameters above^ */
+ };
+ type record AddFrequency {
+ uint10_t start_frequency,
+ uint6_t bsic,
+ BIT1 cell_sel_par_present,
+ CellSelection cell_sel_par optional,
+ uint5_t nr_of_frequencies,
+ uint3_t freq_diff_length
+ /* TODO: support Frequency diff list */
+ } with {
+ variant (cell_sel_par) "PRESENCE(cell_sel_par_present = '1'B)"
+ };
+ type record RepeatedAddFrequencyItem {
+ BIT1 presence,
+ AddFrequency item
+ } with { variant "PRESENCE(presence = '1'B)" };
+ type record of uint6_t FreqIndexList;
+ type record of RepeatedAddFrequencyItem RepeatedAddFrequencyItemList;
+ type record NCFrequencyList {
+ BIT1 removed_freq_present,
+ uint5_t nr_of_removed_freq optional,
+ FreqIndexList removed_freq_index optional,
+ RepeatedAddFrequencyItemList repeated_add_frequency optional,
+ BIT1 repeated_add_frequency_term ('0'B)
+ } with {
+ variant (nr_of_removed_freq) "PRESENCE(removed_freq_present = '1'B)"
+ variant (removed_freq_index) "PRESENCE(removed_freq_present = '1'B)"
+ variant (nr_of_removed_freq) "LENGTHTO(removed_freq_index)-1"
+ variant (nr_of_removed_freq) "UNIT(elements)"
+ };
+ type record NCMeasurementParameters {
+ NetworkControlOrder nco,
+ BIT1 nc_period_present,
+ uint3_t nc_non_drx_period optional,
+ uint3_t nc_reporting_period_i optional,
+ uint3_t nc_reporting_period_t optional,
+ BIT1 nc_freq_list_present,
+ NCFrequencyList nc_freq_list optional
+ } with {
+ variant (nc_non_drx_period) "PRESENCE(nc_period_present = '1'B)"
+ variant (nc_reporting_period_i) "PRESENCE(nc_period_present = '1'B)"
+ variant (nc_reporting_period_t) "PRESENCE(nc_period_present = '1'B)"
+ variant (nc_freq_list) "PRESENCE(nc_freq_list_present = '1'B)"
+ };
+ type record PacketMeasOrder {
+ PageMode page_mode,
+ GlobalTfiOrTlli tfi_or_tlli,
+ uint3_t pmo_index,
+ uint3_t pmo_count,
+ BIT1 nc_meas_param_present,
+ NCMeasurementParameters nc_meas_param optional,
+ BIT1 zero('0'B) /* The value '1' was allocated in an earlier version of the protocol and shall not be used. */
+ /* TODO: support Additions 98 onwards */
+ } with {
+ variant (nc_meas_param) "PRESENCE(nc_meas_param_present = '1'B)"
+ };
+
private type record PktDlAssRelAdditions {
BIT1 rel99_presence, // 0/1
PktDlAssR99Additions rel99 optional
@@ -416,18 +492,22 @@ module RLCMAC_CSN1_Types {
} with {
variant "TAG(ps, presence = '0'B; cs, presence = '1'B)"
};
+ type record RepeatedPageInfoItem {
+ BIT1 presence,
+ PageInfo item
+ } with { variant "PRESENCE(presence = '1'B)" };
+ type record of RepeatedPageInfoItem RepeatedPageInfo;
type record PacketPagingReq {
PageMode page_mode,
BIT1 persistence_levels_present,
PersistenceLevels persistence_levels optional,
BIT1 nln_present,
uint2_t nln optional,
- BIT1 repeated_pageinfo_present,
- PageInfo repeated_pageinfo optional
+ RepeatedPageInfo repeated_pageinfo optional,
+ BIT1 repeated_pageinfo_term ('0'B)
} with {
variant (persistence_levels) "PRESENCE(persistence_levels_present = '1'B)"
variant (nln) "PRESENCE(nln_present = '1'B)"
- variant (repeated_pageinfo) "PRESENCE(repeated_pageinfo_present = '1'B)"
};
/* 12.26 Extension Bits IE */
@@ -478,6 +558,7 @@ module RLCMAC_CSN1_Types {
variant (cont_res_tlli) "BYTEORDER(first)"
};
type record UlAckNackEgprs {
+ BIT2 msg_excape ('00'B),
EgprsChCodingCommand ch_coding_cmd,
BIT1 resegment,
BIT1 preemptive_tx,
@@ -581,14 +662,59 @@ module RLCMAC_CSN1_Types {
variant (msg) "PRESENCE(msg_escape = '0'B)"
};
+ /* 11.2.2a Packet Cell Change Continue */
+ type record PacketCellChangeContinue {
+ PageMode page_mode,
+ BIT1 zero ('0'B),
+ GlobalTfi gtfi,
+ BIT1 arfcn_bsic_presence,
+ uint10_t arfcn optional,
+ uint6_t bsic optional,
+ uint2_t container_id optional
+ } with {
+ variant (arfcn) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ variant (bsic) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ variant (container_id) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ };
+
+ /* 11.2.9e Packet Neighbour Cell Data */
+ type record PacketNeighbourCellDataContainer {
+ BIT3 pd,
+ uint5_t cd_length,
+ octetstring container_data
+ } with {
+ variant (cd_length) "LENGTHTO (container_data)"
+ variant (container_data) "BYTEORDER(first)"
+ };
+ type record of PacketNeighbourCellDataContainer PacketNeighbourCellDataContainerList
+ type record PacketNeighbourCellData {
+ PageMode page_mode,
+ BIT1 zero ('0'B),
+ GlobalTfi gtfi,
+ uint2_t container_id,
+ BIT1 spare ('0'B),
+ uint5_t container_index,
+ BIT1 arfcn_bsic_presence,
+ uint10_t arfcn optional,
+ uint6_t bsic optional,
+ PacketNeighbourCellDataContainerList container_list
+ } with {
+ variant (arfcn) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ variant (bsic) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ };
+
/* 11.2.0.1 */
type union RlcmacDlCtrlUnion {
+ PacketAccessReject access_reject,
PacketDlAssignment dl_assignment,
+ PacketMeasOrder meas_order,
PacketUlAssignment ul_assignment,
PacketPagingReq paging,
PacketUlAckNack ul_ack_nack,
PacketDlDummy dl_dummy,
PacketPwrControlTA pwr_ta,
+ PacketCellChangeContinue cell_chg_continue,
+ PacketNeighbourCellData neighbour_cell_data,
octetstring other
} with { variant "" };
@@ -596,12 +722,16 @@ module RLCMAC_CSN1_Types {
RlcmacDlCtrlMsgType msg_type,
RlcmacDlCtrlUnion u
} with {
- variant (u) "CROSSTAG(dl_assignment, msg_type = PACKET_DL_ASSIGNMENT;
+ variant (u) "CROSSTAG(access_reject, msg_type = PACKET_ACCESS_REJECT;
+ dl_assignment, msg_type = PACKET_DL_ASSIGNMENT;
+ meas_order, msg_type = PACKET_MEASUREMENT_ORDER;
ul_assignment, msg_type = PACKET_UL_ASSIGNMENT;
paging, msg_type = PACKET_PAGING_REQUEST;
ul_ack_nack, msg_type = PACKET_UL_ACK_NACK;
dl_dummy, msg_type = PACKET_DL_DUMMY_CTRL;
pwr_ta, msg_type = PACKET_PWR_CONTROL_TA;
+ cell_chg_continue,msg_type = PACKET_CELL_CHANGE_CONTINUE;
+ neighbour_cell_data,msg_type = PACKET_NEIGHBOUR_CELL_DATA;
other, OTHERWISE
)"
};
@@ -611,8 +741,37 @@ module RLCMAC_CSN1_Types {
external function dec_RlcmacDlCtrlMsg(in octetstring stream) return RlcmacDlCtrlMsg
with { extension "prototype(convert) decode(RAW)" };
+ /* 11.2.1 Packet Access Reject */
+ type record PacketAccessRejectIDSub {
+ BIT1 id_type,
+ PacketRequestReference req_ref optional,
+ GlobalTfi gtfi optional
+ } with { variant (req_ref) "PRESENCE(id_type = '0'B)"
+ variant (gtfi) "PRESENCE(id_type = '1'B)"
+ };
+ type union PacketAccessRejectID {
+ GprsTlli tlli,
+ PacketAccessRejectIDSub id_sub
+ } with { variant (tlli) "BYTEORDER(first)" };
+ type record PacketAccessRejectStruct {
+ BIT1 id_type,
+ PacketAccessRejectID id,
+ BIT1 wait_ind_presence,
+ uint8_t wait_ind optional,
+ BIT1 wait_ind_size optional
+ } with { variant (id) "CROSSTAG(tlli, id_type = '0'B; id_sub, id_type = '1'B)"
+ variant (wait_ind) "PRESENCE(wait_ind_presence = '1'B)"
+ variant (wait_ind_size) "PRESENCE(wait_ind_presence = '1'B)"
+ };
+ type record PacketAccessReject {
+ PageMode page_mode,
+ PacketAccessRejectStruct reject_struct
+ /* TODO: Additional Reject */
+ /* TODO: Rel5 additions */
+ } with { variant "" };
+
- /* 11.2.6 Packet Downlikn Ack/Nack */
+ /* 11.2.6 Packet Downlink Ack/Nack */
type record ILevel {
BIT1 presence,
uint4_t i_level optional
@@ -630,7 +789,60 @@ module RLCMAC_CSN1_Types {
BIT1 chreq_desc_presence,
ChannelReqDescription chreq_desc optional,
ChannelQualityReport ch_qual_rep
+ } with { variant (chreq_desc) "PRESENCE(chreq_desc_presence = '1'B)" };
+
+ /* 11.2.6a Egprs Packet Downlink Ack/Nack */
+ type record EgprsBEPLinkQualityMeasurements {
+ BIT1 gmsk_presence,
+ BIT5 gmsk_mean_bep optional,
+ BIT3 gmsk_cv_bep optional,
+ BIT1 psk8_presence,
+ BIT5 psk8_mean_bep optional,
+ BIT3 psk8_cv_bep optional
+ } with { variant (gmsk_mean_bep) "PRESENCE(gmsk_presence = '1'B)"
+ variant (gmsk_cv_bep) "PRESENCE(gmsk_presence = '1'B)"
+ variant (psk8_mean_bep) "PRESENCE(psk8_presence = '1'B)"
+ variant (psk8_cv_bep) "PRESENCE(psk8_presence = '1'B)"
+ };
+ /* 12.5.4 EGPRS Timeslot Link Quality Measurements IE */
+ type record BEPMeas {
+ BIT1 presence,
+ BIT1 is_8psk optional,
+ uint4_t bep_meas optional
+ } with { variant (is_8psk) "PRESENCE(presence = '1'B)"
+ variant (bep_meas) "PRESENCE(presence = '1'B)"
+ };
+ type record length(8) of BEPMeas BEPMeasLi;
+ type record EgprsTimeslotLinkQualityMeasurements {
+ BIT1 bep_measurements_presence,
+ BEPMeasLi bep_meas optional,
+ BIT1 i_measurements_presence,
+ ILevels i_meas optional
+ } with { variant (bep_meas) "PRESENCE(bep_measurements_presence = '1'B)"
+ variant (i_meas) "PRESENCE(i_measurements_presence = '1'B)"
+ };
+ /* Table 12.5.1.1 : EGPRS Channel Quality Report Information elements */
+ type record EgprsChannelQualityReport {
+ EgprsBEPLinkQualityMeasurements bep_link_qual_meas,
+ uint6_t c_value,
+ EgprsTimeslotLinkQualityMeasurements ts_link_qual_meas
} with { variant "" };
+ type record EgprsPacketDlAckNack {
+ uint5_t dl_tfi,
+ BIT1 ms_oom,
+ BIT1 egprs_ch_qual_rep_presence,
+ EgprsChannelQualityReport egprs_ch_qual_rep optional,
+ BIT1 chreq_desc_presence,
+ ChannelReqDescription chreq_desc optional,
+ BIT1 pfi_presence,
+ BIT7 pfi optional,
+ BIT1 epdan_presence('0'B),
+ /* TODO: Implement EPD A/N */
+ EgprsAckNackDescriptionIE ack_nack_desc_ie
+ } with { variant (chreq_desc) "PRESENCE(chreq_desc_presence = '1'B)"
+ variant (egprs_ch_qual_rep) "PRESENCE(egprs_ch_qual_rep_presence = '1'B)"
+ variant (pfi) "PRESENCE(pfi_presence = '1'B)"
+ };
/* 11.2.2 Packet Control Acknowledgement */
type enumerated CtrlAck {
@@ -654,6 +866,38 @@ module RLCMAC_CSN1_Types {
variant (tlli) "BYTEORDER(first)"
};
+ /* 11.2.9 Packet Measurement Report */
+ type record NCMeasurement {
+ uint6_t frequency_n,
+ BIT1 bsic_n_presence,
+ BIT6 bsic_n optional,
+ uint6_t rxlev_n
+ } with {
+ variant (bsic_n) "PRESENCE(bsic_n_presence = '1'B)"
+ };
+ type record of NCMeasurement NCMeasurementList;
+ type record NCMeasurementReport {
+ BIT1 nc_mode,
+ uint6_t rxlev_serving_cell,
+ BIT1 zero ('0'B), /*The value '1' was allocated in an earlier version of the protocol and shall not be used.*/
+ uint3_t num_nc_measurements,
+ NCMeasurementList nm_measurements
+ } with {
+ variant (num_nc_measurements) "LENGTHTO(nm_measurements)"
+ variant (num_nc_measurements) "UNIT(elements)"
+ };
+ type record PacketMeasReport {
+ GprsTlli tlli,
+ BIT1 psi5_change_mark_presence,
+ BIT2 psi5_change_mark optional,
+ BIT1 additions_99 ('0'B), /* TODO: 1 -> support Additions 99 onwards */
+ NCMeasurementReport nc_meas_report optional
+ } with {
+ variant (tlli) "BYTEORDER(first)"
+ variant (psi5_change_mark) "PRESENCE(psi5_change_mark_presence = '1'B)"
+ variant (nc_meas_report) "PRESENCE(additions_99 = '0'B)"
+ };
+
/* TS 44.060 sec 12.30 MS Radio Access Capability 2
* (for value part, see 3GPP TS 24.008 sec 10.5.5.12a and table 10.5.146) */
type union MSRadioAccCap2 {
@@ -697,13 +941,173 @@ module RLCMAC_CSN1_Types {
variant (sign_var) "PRESENCE(sign_var_presence = '1'B)"
};
+ /* 11.2.3a Packet Cell Change Notification, 3G Target Cell Struct (Rel-6 extension) */
+ type record UtranTargetCellFdd {
+ uint14_t arfcn,
+ BIT1 bandwidth_presence,
+ uint3_t bandwidth optional,
+ uint10_t scrambling_code
+ } with {
+ variant (bandwidth) "PRESENCE(bandwidth_presence = '1'B)"
+ };
+ type record UtranTargetCellTdd {
+ uint14_t arfcn,
+ BIT1 bandwidth_presence,
+ uint3_t bandwidth optional,
+ uint7_t cell_parameter,
+ BIT1 sync_case
+ } with {
+ variant (bandwidth) "PRESENCE(bandwidth_presence = '1'B)"
+ };
+ type record UtranTargetCell {
+ BIT1 fdd_presence,
+ UtranTargetCellFdd fdd optional,
+ BIT1 tdd_presence,
+ UtranTargetCellTdd tdd optional,
+ uint6_t reporting_quantity
+ } with {
+ variant (fdd) "PRESENCE(fdd_presence = '1'B)"
+ variant (tdd) "PRESENCE(tdd_presence = '1'B)"
+ };
+
+ /* 11.2.3a Packet Cell Change Notification, Eutran Target Cell Struct (Rel-8 extension) */
+ type record EutranTargetCell {
+ uint16_t earfcn,
+ BIT1 meas_bandwidth_presence,
+ uint3_t meas_bandwidth optional,
+ uint9_t phys_layer_cell_id,
+ uint6_t reporting_quantity
+ } with {
+ variant (meas_bandwidth) "PRESENCE(meas_bandwidth_presence = '1'B)"
+ };
+
+ /* 11.2.3a Packet Cell Change Notification, 3G CCN Measurement Report Struct (Rel-6 extension) */
+ type record of UtranCCNMeasReportItem UtranReportingQuantityList;
+ type record UtranCCNMeasReportItem {
+ uint7_t cell_list_index,
+ uint6_t reporting_quantity
+ } with { variant "" };
+ type record UtranCCNMeasReport {
+ uint3_t n_3g,
+ UtranReportingQuantityList cells
+ } with {
+ variant (n_3g) "LENGTHTO(cells) - 1"
+ variant (n_3g) "UNIT(elements)"
+ };
+
+ /* 11.2.3a Packet Cell Change Notification, E-UTRAN CCN Measurement Report Struct (Rel-8 extension) */
+ type record length(1..4) of EutranCCNMeasReportItem EutranReportingQuantityList;
+ type record EutranCCNMeasReportItem {
+ uint3_t frequency_list_index,
+ uint9_t cell_identity,
+ uint6_t reporting_quantity
+ } with { variant "" };
+ type record EutranCCNMeasReport {
+ uint1_t utran_ba_used,
+ uint2_t n_eutran,
+ EutranReportingQuantityList cells
+ } with {
+ variant (n_eutran) "LENGTHTO(cells) - 1"
+ variant (n_eutran) "UNIT(elements)"
+ };
+
+ type record NCMeasurementItem {
+ uint6_t freq,
+ BIT1 bsic_presence,
+ uint6_t bsic optional,
+ uint6_t rxlev
+ } with {
+ variant (bsic) "PRESENCE(bsic_presence = '1'B)"
+ };
+ type record of NCMeasurementItem NCMeasurements;
+ type record CCNMeasReport {
+ uint6_t rxlev_servig_cell,
+ BIT1 zero ('0'B),
+ uint3_t num_meas,
+ NCMeasurements meas
+ } with { variant "" };
+
+ /* 11.2.3a Packet Cell Change Notification, Rel-Additions (Matrioshka) */
+ private type record PktCellChgNotifAdditions {
+ BIT1 rel6_presence,
+ PktCellChgNotifR6Additions rel6 optional
+ } with {
+ variant (rel6) "PRESENCE(rel6_presence = '1'B)"
+ };
+ private type record PktCellChgNotifR6Additions {
+ BIT1 utran_ba_used_presence,
+ uint1_t utran_ba_used optional,
+ UtranCCNMeasReport utran_ccn_meas_rep
+ } with {
+ variant (utran_ba_used) "PRESENCE(utran_ba_used_presence = '1'B)"
+ };
+
+ private type record PktCellChgNotifyU0 {
+ BIT1 tag ('0'B),
+ uint10_t arfcn,
+ uint6_t bsic
+ } with { variant "" };
+ private type record PktCellChgNotifyU10 {
+ BIT2 tag ('10'B),
+ UtranTargetCell utran_target_cell
+ } with { variant "" };
+ private type record PktCellChgNotifyU110 {
+ BIT3 tag ('110'B),
+ BIT1 arfcn_bsic_presence,
+ uint10_t arfcn optional,
+ uint6_t bsic optional,
+ BIT1 utran_target_cell_presence,
+ UtranTargetCell utran_target_cell optional,
+ BIT1 eutran_target_cell_presence,
+ EutranTargetCell eutran_target_cell optional,
+ BIT1 eutran_ccn_meas_rep_presence,
+ EutranCCNMeasReport eutran_ccn_meas_rep optional
+ } with {
+ variant (arfcn) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ variant (bsic) "PRESENCE(arfcn_bsic_presence = '1'B)"
+ variant (utran_target_cell) "PRESENCE(utran_target_cell_presence = '1'B)"
+ variant (eutran_target_cell) "PRESENCE(eutran_target_cell_presence = '1'B)"
+ variant (eutran_ccn_meas_rep) "PRESENCE(eutran_ccn_meas_rep_presence = '1'B)"
+ };
+ private type union PktCellChgNotifyUnion {
+ PktCellChgNotifyU0 u0,
+ PktCellChgNotifyU10 u10, /* Rel-6 additions */
+ PktCellChgNotifyU110 u110 /* Rel-8 additions */
+ /* TODO: PktCellChgNotifyU1110 Rel-9 additions */
+ /* TODO: Message escape : { 1111 } bit (*) = <no string> > */
+ } with {
+ variant "TAG(u0, tag = '0'B;
+ u10, tag = '10'B;
+ u110, tag = '110'B)"
+ };
+
+ /* 11.2.3a Packet Cell Change Notification, message body */
+ type record PacketCellChangeNotification {
+ GlobalTfi gtfi,
+ PktCellChgNotifyUnion u,
+ BIT1 ba_psi3_presence,
+ BIT1 ba_used optional,
+ BIT2 psi3_change_mark optional,
+ BIT1 pmo_used,
+ BIT1 pccn_sending,
+ CCNMeasReport ccn_meas_rep,
+ /* Rel-Additions (Matrioshka) */
+ PktCellChgNotifAdditions rel_additions optional
+ } with {
+ variant (ba_used) "PRESENCE(ba_psi3_presence = '0'B)"
+ variant (psi3_change_mark) "PRESENCE(ba_psi3_presence = '1'B)"
+ };
+
/* 11.2.0.2 */
type union RlcmacUlCtrlUnion {
- PacketCtrlAck ctrl_ack,
- PacketDlAckNack dl_ack_nack,
- PacketUlDummy ul_dummy,
- PacketResourceReq resource_req,
- octetstring other
+ PacketCtrlAck ctrl_ack,
+ PacketDlAckNack dl_ack_nack,
+ EgprsPacketDlAckNack dl_ack_nack_egprs,
+ PacketUlDummy ul_dummy,
+ PacketMeasReport meas_report,
+ PacketResourceReq resource_req,
+ PacketCellChangeNotification cell_chg_notif,
+ octetstring other
} with { variant "" };
type record RlcmacUlCtrlMsg {
@@ -712,8 +1116,11 @@ module RLCMAC_CSN1_Types {
} with {
variant (u) "CROSSTAG(ctrl_ack, msg_type = PACKET_CONTROL_ACK;
dl_ack_nack, msg_type = PACKET_DL_ACK_NACK;
+ dl_ack_nack_egprs, msg_type = PACKET_EGPRS_DL_ACK_NACK;
ul_dummy, msg_type = PACKET_UL_DUMMY_CTRL;
+ meas_report, msg_type = PACKET_MEASUREMENT_REPORT;
resource_req, msg_type = PACKET_RESOURCE_REQUEST;
+ cell_chg_notif, msg_type = PACKET_CELL_CHANGE_NOTIFICATION;
other, OTHERWISE
)"
};
@@ -732,6 +1139,27 @@ module RLCMAC_CSN1_Types {
ReceivedBlockBitmap receive_block_bitmap
} with { variant "" };
+ /* 12.3.1 Egprs Ack/Nack Description */
+ type bitstring UncompressedReceivedBlockBitmap length(64) with { variant "BYTEORDER(last)" };
+ type record EgprsAckNackDescription {
+ BIT1 final_ack,
+ BIT1 begin_window,
+ BIT1 end_window,
+ uint11_t starting_seq_nr,
+ BIT1 compressed,
+ /* TODO: CompressedReceivedBlockBitmap urbb optional, */
+ UncompressedReceivedBlockBitmap urbb optional
+ } with { variant (urbb) "PRESENCE(compressed = '0'B)" };
+ type record EgprsAckNackDescriptionIE {
+ BIT1 len_present,
+ uint8_t len optional,
+ EgprsAckNackDescription acknack_desc
+ } with { variant (len) "PRESENCE(len_present = '1'B)"
+ variant (len) "LENGTHTO(acknack_desc)"
+ variant (len) "UNIT(bits)"
+ };
+
+
/* 12.7 Channel Request Description */
type enumerated RlcMode {
RLC_MODE_ACKNOWLEDGED (0),
@@ -763,7 +1191,7 @@ module RLCMAC_CSN1_Types {
};
type record FreqDirect1 {
uint6_t maio,
- GprsMobileAllication mobile_allocation
+ GprsMobileAllocation mobile_allocation
}
type record FreqDirect2 {
uint6_t maio,
@@ -787,6 +1215,15 @@ module RLCMAC_CSN1_Types {
variant (direct2) "PRESENCE(presence = '11'B)"
};
+ /* 12.9a GPRS Power Control Parameters */
+ type record GprsPowerControlParameters {
+ uint4_t alpha,
+ BIT5 t_avg_w,
+ BIT5 t_avg_t,
+ BIT1 pc_meas_chan,
+ BIT4 n_avg_i
+ };
+
/* 12.10 Global TFI */
type record GlobalTfi {
boolean is_dl_tfi,
@@ -801,7 +1238,7 @@ module RLCMAC_CSN1_Types {
} with {
variant (rfl_number_list) "PRESENCE(presence = '1'B)"
};
- type record GprsMobileAllication {
+ type record GprsMobileAllocation {
uint6_t hsn,
BIT1 rfl_number_list_present,
RflNumberList rfl_number_list optional,
@@ -870,6 +1307,48 @@ module RLCMAC_CSN1_Types {
variant (relative_k) "PRESENCE(presence = '1'B)"
};
+ /* 12.24 GPRS Cell Options */
+ type record ExtensionInformation {
+ BIT1 egprs_supported,
+ BIT1 egprs_pkt_channel_req optional,
+ BIT4 bep_period optional,
+ BIT1 pfc_feature_mode,
+ BIT1 dtm_support,
+ BIT1 bss_paging_coordination,
+ /* REL-4 extension */
+ BIT1 ccn_active optional,
+ BIT1 nw_ext_utbf optional
+ /* TODO: REL-6 extension */
+ /* TODO: REL-7 extension */
+ /* TODO: REL-10 extension */
+ } with {
+ variant (egprs_pkt_channel_req) "PRESENCE(egprs_supported = '1'B)"
+ variant (bep_period) "PRESENCE(egprs_supported = '1'B)"
+ };
+ type record GprsCellOptions {
+ BIT2 nmo,
+ BIT3 t3168,
+ BIT3 t3192,
+ BIT3 drx_timer_max,
+ BIT1 access_burst_type,
+ BIT1 control_ack_type,
+ uint4_t bs_cv_max,
+ BIT1 pan_presence,
+ uint3_t pan_dec optional,
+ uint3_t pan_inc optional,
+ BIT3 pan_max optional,
+ BIT1 ext_info_presence,
+ BIT6 ext_info_length optional,
+ ExtensionInformation ext_info optional
+ } with {
+ variant (pan_dec) "PRESENCE(pan_presence = '1'B)"
+ variant (pan_inc) "PRESENCE(pan_presence = '1'B)"
+ variant (pan_max) "PRESENCE(pan_presence = '1'B)"
+ variant (ext_info_length) "PRESENCE(ext_info_presence = '1'B)"
+ variant (ext_info) "PRESENCE(ext_info_presence = '1'B)"
+ /* TODO: mark REL-4 and upwards in ext_info as omit based on ext_info_length ? */
+ };
+
/* 3GPP TS 44.060, table 11.2.5a.2 "EGPRS PACKET CHANNEL REQUEST" */
type union EGPRSPktChRequest {
EGPRSPktChRequest_MC5P2RB3 one_phase,
diff --git a/library/RLCMAC_EncDec.cc b/library/RLCMAC_EncDec.cc
index d25a7e07..dd32d8f8 100644
--- a/library/RLCMAC_EncDec.cc
+++ b/library/RLCMAC_EncDec.cc
@@ -207,17 +207,23 @@ static CodingScheme::enum_type payload_len_2_coding_scheme(size_t payload_len) {
return CodingScheme::MCS__3;
case 49:
return CodingScheme::MCS__4;
+ case 60: /* fall through */
case 61:
return CodingScheme::MCS__5;
+ case 78: /* fall through */
case 79:
return CodingScheme::MCS__6;
+ case 118: /* fall through */
case 119:
return CodingScheme::MCS__7;
- case 142:
+ case 142: /* fall through */
+ case 143:
return CodingScheme::MCS__8;
+ case 154: /* fall through */
case 155:
return CodingScheme::MCS__9;
default:
+ fprintf(stderr, "ERROR: Unknown CodingSCheme for payload_len=%zu\n", payload_len);
return CodingScheme::CS__1;
}
}
@@ -438,6 +444,29 @@ static void put_egprs_data_block(const TTCN_Buffer& aligned_data_block_buffer, u
dst_ttcn_buffer.increase_length(length_bytes);
}
+/* Append padding bytes and spare bits at the end of ttcn_buffer, based on requested CS */
+static void encode_trailing_padding_spb(TTCN_Buffer& ttcn_buffer, CodingScheme cs)
+{
+ uint8_t buf[256]; /* enough to fit any RLCMAC buffer*/
+ uint32_t blk_len = RLCMAC__Templates::f__rlcmac__cs__mcs2block__len(cs);
+ uint32_t blk_len_no_spb = RLCMAC__Templates::f__rlcmac__cs__mcs2block__len__no__spare__bits(cs);
+ uint32_t data_len = ttcn_buffer.get_len();
+
+ if (data_len > blk_len_no_spb) {
+ fprintf(stderr, "Buffer too large for requested CS! %s (%s:%u)\n", __func__, __FILE__, __LINE__);
+ // TODO: throw exception?
+ return;
+ }
+
+ for (int i = 0; i < blk_len_no_spb - data_len; i++)
+ buf[i] = 0x2b; /* Padding bits if needed */
+ for (int i = blk_len_no_spb - data_len; i < blk_len - data_len; i++)
+ buf[i] = 0x00; /* Spare bits if needed */
+
+ const OCTETSTRING& pad_octstr = OCTETSTRING(blk_len - data_len, buf);
+ ttcn_buffer.put_string(pad_octstr);
+}
+
/////////////////////
// DECODE
/////////////////////
@@ -450,6 +479,8 @@ RlcmacDlDataBlock dec__RlcmacDlDataBlock(const OCTETSTRING& stream)
TTCN_Buffer ttcn_buffer(stream);
int num_llc_blocks = 0;
+ ret_val.cs() = payload_len_2_coding_scheme(stream.lengthof());
+
/* use automatic/generated decoder for header */
ret_val.mac__hdr().decode(DlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
@@ -475,6 +506,7 @@ RlcmacDlDataBlock dec__RlcmacDlDataBlock(const OCTETSTRING& stream)
/* LI not present: The Upper Layer PDU that starts with the current RLC data block either
* fills the current RLC data block precisely or continues in the following in-sequence RLC
* data block */
+ lb.hdr() = OMIT_VALUE;
lb.payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
ttcn_buffer.increase_pos(length);
ret_val.blocks()[0] = lb;
@@ -482,8 +514,17 @@ RlcmacDlDataBlock dec__RlcmacDlDataBlock(const OCTETSTRING& stream)
if (ret_val.blocks().is_bound()) {
for (int i = 0; i < ret_val.blocks().size_of(); i++) {
unsigned int length = ret_val.blocks()[i].hdr()().length__ind();
+
+ /* LI[0]=0 indicates: The current LLC PDU would fit within
+ current RLC data block but the addition of the length
+ indicator octet (to indicate the LLC PDU boundary) causes the
+ LLC PDU to extend into another RLC data block */
+ if (i == 0 && length == 0)
+ length = ttcn_buffer.get_read_len();
+
if (length > ttcn_buffer.get_read_len())
length = ttcn_buffer.get_read_len();
+
ret_val.blocks()[i].payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
ttcn_buffer.increase_pos(length);
}
@@ -496,20 +537,54 @@ RlcmacDlDataBlock dec__RlcmacDlDataBlock(const OCTETSTRING& stream)
static
EgprsDlMacDataHeader dec__EgprsDlMacDataHeader_type1(const OCTETSTRING& stream)
{
+ TTCN_Buffer ttcn_buffer(stream);
EgprsDlMacDataHeader ret_val;
+ const struct gprs_rlc_dl_header_egprs_1 *egprs1;
+ uint8_t tmp;
- fprintf(stderr, "FIXME: Not implemented! %s (%s:%u)\n", __func__, __FILE__, __LINE__);
+ egprs1 = static_cast<const struct gprs_rlc_dl_header_egprs_1 *>
+ ((const void *)ttcn_buffer.get_data());
+ ret_val.header__type() = EgprsHeaderType::RLCMAC__HDR__TYPE__1;
+ ret_val.tfi() = egprs1->tfi_lo << 1 | egprs1->tfi_hi << 0;
+ ret_val.rrbp() = egprs1->rrbp;
+ tmp = egprs1->es_p;
+ ret_val.esp() = BITSTRING(2, &tmp);
+ ret_val.usf() = egprs1->usf;
+ ret_val.bsn1() = egprs1->bsn1_lo << 10 | egprs1->bsn1_mid << 2 | egprs1->bsn1_hi;
+ ret_val.bsn2__offset() = egprs1->bsn2_lo << 7 | egprs1->bsn2_hi;
+ ret_val.pr() = egprs1->pr;
+ ret_val.cps() = egprs1->cps;
+ ret_val.spb() = OMIT_VALUE;
+
+ ttcn_buffer.increase_pos(sizeof(*egprs1));
return ret_val;
}
static
EgprsDlMacDataHeader dec__EgprsDlMacDataHeader_type2(const OCTETSTRING& stream)
{
+ TTCN_Buffer ttcn_buffer(stream);
EgprsDlMacDataHeader ret_val;
+ const struct gprs_rlc_dl_header_egprs_2 *egprs2;
+ uint8_t tmp;
- fprintf(stderr, "FIXME: Not implemented! %s (%s:%u)\n", __func__, __FILE__, __LINE__);
+ egprs2 = static_cast<const struct gprs_rlc_dl_header_egprs_2 *>
+ ((const void *)ttcn_buffer.get_data());
+ ret_val.header__type() = EgprsHeaderType::RLCMAC__HDR__TYPE__2;
+ ret_val.tfi() = egprs2->tfi_lo << 1 | egprs2->tfi_hi << 0;
+ ret_val.rrbp() = egprs2->rrbp;
+ tmp = egprs2->es_p;
+ ret_val.esp() = BITSTRING(2, &tmp);
+ ret_val.usf() = egprs2->usf;
+ ret_val.bsn1() = egprs2->bsn1_lo << 10 | egprs2->bsn1_mid << 2 | egprs2->bsn1_hi;
+ ret_val.bsn2__offset() = 0; /*TODO: mark optional and not set ? */
+ ret_val.pr() = egprs2->pr;
+ ret_val.cps() = egprs2->cps;
+ ret_val.spb() = OMIT_VALUE;
+
+ ttcn_buffer.increase_pos(sizeof(*egprs2));
return ret_val;
}
@@ -541,7 +616,7 @@ EgprsDlMacDataHeader dec__EgprsDlMacDataHeader_type3(const OCTETSTRING& stream)
}
static
-RlcmacDlEgprsDataBlock dec__RlcmacDlEgprsDataBlock(const OCTETSTRING& stream, CodingScheme::enum_type mcs)
+RlcmacDlEgprsDataBlock dec__RlcmacDlEgprsDataBlock(const OCTETSTRING& stream)
{
RlcmacDlEgprsDataBlock ret_val;
TTCN_Buffer ttcn_buffer(stream);
@@ -551,7 +626,8 @@ RlcmacDlEgprsDataBlock dec__RlcmacDlEgprsDataBlock(const OCTETSTRING& stream, Co
unsigned int num_calls;
const uint8_t *ti_e;
- switch (mcs) {
+ ret_val.mcs() = payload_len_2_coding_scheme(stream.lengthof());
+ switch (ret_val.mcs()) {
case CodingScheme::MCS__0:
case CodingScheme::MCS__1:
case CodingScheme::MCS__2:
@@ -569,7 +645,7 @@ RlcmacDlEgprsDataBlock dec__RlcmacDlEgprsDataBlock(const OCTETSTRING& stream, Co
ret_val.mac__hdr() = dec__EgprsDlMacDataHeader_type1(stream);
break;
}
- setup_rlc_mac_priv(mcs, ret_val.mac__hdr().header__type(), false,
+ setup_rlc_mac_priv(ret_val.mcs(), ret_val.mac__hdr().header__type(), false,
&num_calls, &data_block_bits, data_block_offsets);
get_egprs_data_block(ttcn_buffer, data_block_offsets[0], data_block_bits, aligned_buffer);
@@ -594,13 +670,26 @@ RlcmacDlEgprsDataBlock dec__RlcmacDlEgprsDataBlock(const OCTETSTRING& stream, Co
}
/* RLC blocks at end */
- if (ret_val.blocks().is_bound()) {
- for (int i = 0; i < ret_val.blocks().size_of(); i++) {
- unsigned int length = ret_val.blocks()[i].hdr()().length__ind();
- if (length > aligned_buffer.get_read_len())
- length = aligned_buffer.get_read_len();
- ret_val.blocks()[i].payload() = OCTETSTRING(length, aligned_buffer.get_read_data());
- aligned_buffer.increase_pos(length);
+ if (ret_val.e() == true) {
+ EgprsLlcBlock lb;
+ unsigned int length = aligned_buffer.get_read_len();
+ /* LI not present: The Upper Layer PDU that starts with the current RLC data block either
+ * fills the current RLC data block precisely or continues in the following in-sequence RLC
+ * data block */
+ lb.hdr() = OMIT_VALUE;
+ lb.payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
+ aligned_buffer.increase_pos(length);
+ ret_val.blocks()[0] = lb;
+ } else {
+ /* RLC blocks at end */
+ if (ret_val.blocks().is_bound()) {
+ for (int i = 0; i < ret_val.blocks().size_of(); i++) {
+ unsigned int length = ret_val.blocks()[i].hdr()().length__ind();
+ if (length > aligned_buffer.get_read_len())
+ length = aligned_buffer.get_read_len();
+ ret_val.blocks()[i].payload() = OCTETSTRING(length, aligned_buffer.get_read_data());
+ aligned_buffer.increase_pos(length);
+ }
}
}
@@ -611,10 +700,10 @@ RlcmacDlBlock dec__RlcmacDlBlock(const OCTETSTRING& stream)
{
RlcmacDlBlock ret_val;
size_t stream_len = stream.lengthof();
- CodingScheme::enum_type mcs = payload_len_2_coding_scheme(stream_len);
+ CodingScheme::enum_type cs_mcs = payload_len_2_coding_scheme(stream_len);
unsigned char pt;
- switch (mcs) {
+ switch (cs_mcs) {
case CodingScheme::CS__1:
case CodingScheme::CS__2:
case CodingScheme::CS__3:
@@ -635,7 +724,7 @@ RlcmacDlBlock dec__RlcmacDlBlock(const OCTETSTRING& stream)
case CodingScheme::MCS__7:
case CodingScheme::MCS__8:
case CodingScheme::MCS__9:
- ret_val.data__egprs() = dec__RlcmacDlEgprsDataBlock(stream, mcs);
+ ret_val.data__egprs() = dec__RlcmacDlEgprsDataBlock(stream);
break;
}
return ret_val;
@@ -655,6 +744,8 @@ RlcmacUlDataBlock dec__RlcmacUlDataBlock(const OCTETSTRING& stream)
stream.log();
TTCN_Logger::end_event();
+ ret_val.cs() = payload_len_2_coding_scheme(stream.lengthof());
+
/* use automatic/generated decoder for header */
ret_val.mac__hdr().decode(UlMacDataHeader_descr_, ttcn_buffer, TTCN_EncDec::CT_RAW);
@@ -715,6 +806,7 @@ RlcmacUlDataBlock dec__RlcmacUlDataBlock(const OCTETSTRING& stream)
/* LI not present: The Upper Layer PDU that starts with the current RLC data block either
* fills the current RLC data block precisely or continues in the following in-sequence RLC
* data block */
+ lb.hdr() = OMIT_VALUE;
lb.payload() = OCTETSTRING(length, ttcn_buffer.get_read_data());
ttcn_buffer.increase_pos(length);
ret_val.blocks()[0] = lb;
@@ -792,7 +884,7 @@ EgprsUlMacDataHeader dec__EgprsUlMacDataHeader_type3(const OCTETSTRING& stream)
return ret_val;
}
-RlcmacUlEgprsDataBlock dec__RlcmacUlEgprsDataBlock(const OCTETSTRING& stream, CodingScheme::enum_type mcs)
+RlcmacUlEgprsDataBlock dec__RlcmacUlEgprsDataBlock(const OCTETSTRING& stream)
{
RlcmacUlEgprsDataBlock ret_val;
TTCN_Buffer ttcn_buffer(stream);
@@ -802,7 +894,8 @@ RlcmacUlEgprsDataBlock dec__RlcmacUlEgprsDataBlock(const OCTETSTRING& stream, Co
unsigned int num_calls;
const uint8_t *ti_e;
- switch (mcs) {
+ ret_val.mcs() = payload_len_2_coding_scheme(stream.lengthof());
+ switch (ret_val.mcs()) {
case CodingScheme::MCS__1:
case CodingScheme::MCS__2:
case CodingScheme::MCS__3:
@@ -819,7 +912,7 @@ RlcmacUlEgprsDataBlock dec__RlcmacUlEgprsDataBlock(const OCTETSTRING& stream, Co
ret_val.mac__hdr() = dec__EgprsUlMacDataHeader_type1(stream);
break;
}
- setup_rlc_mac_priv(mcs, ret_val.mac__hdr().header__type(), true,
+ setup_rlc_mac_priv(ret_val.mcs(), ret_val.mac__hdr().header__type(), true,
&num_calls, &data_block_bits, data_block_offsets);
get_egprs_data_block(ttcn_buffer, data_block_offsets[0], data_block_bits, aligned_buffer);
@@ -867,6 +960,7 @@ RlcmacUlEgprsDataBlock dec__RlcmacUlEgprsDataBlock(const OCTETSTRING& stream, Co
/* LI not present: The Upper Layer PDU that starts with the current RLC data block either
* fills the current RLC data block precisely or continues in the following in-sequence RLC
* data block */
+ lb.hdr() = OMIT_VALUE;
lb.payload() = OCTETSTRING(length, aligned_buffer.get_read_data());
aligned_buffer.increase_pos(length);
ret_val.blocks()[0] = lb;
@@ -889,10 +983,10 @@ RlcmacUlBlock dec__RlcmacUlBlock(const OCTETSTRING& stream)
{
RlcmacUlBlock ret_val;
size_t stream_len = stream.lengthof();
- CodingScheme::enum_type mcs = payload_len_2_coding_scheme(stream_len);
+ CodingScheme::enum_type cs_mcs = payload_len_2_coding_scheme(stream_len);
unsigned char pt;
- switch (mcs) {
+ switch (cs_mcs) {
case CodingScheme::CS__1:
case CodingScheme::CS__2:
case CodingScheme::CS__3:
@@ -912,7 +1006,7 @@ RlcmacUlBlock dec__RlcmacUlBlock(const OCTETSTRING& stream)
case CodingScheme::MCS__7:
case CodingScheme::MCS__8:
case CodingScheme::MCS__9:
- ret_val.data__egprs() = dec__RlcmacUlEgprsDataBlock(stream, mcs);
+ ret_val.data__egprs() = dec__RlcmacUlEgprsDataBlock(stream);
break;
}
@@ -964,6 +1058,8 @@ OCTETSTRING enc__RlcmacDlDataBlock(const RlcmacDlDataBlock& si)
}
}
+ encode_trailing_padding_spb(ttcn_buffer, in.cs());
+
ttcn_buffer.get_string(ret_val);
return ret_val;
}
@@ -1034,6 +1130,8 @@ OCTETSTRING enc__RlcmacDlEgprsDataBlock(const RlcmacDlEgprsDataBlock& si)
}
}
+ encode_trailing_padding_spb(ttcn_buffer, in.mcs());
+
ttcn_buffer.get_string(ret_val);
return ret_val;
}
@@ -1127,6 +1225,8 @@ OCTETSTRING enc__RlcmacUlDataBlock(const RlcmacUlDataBlock& si)
}
}
+ encode_trailing_padding_spb(ttcn_buffer, in.cs());
+
ttcn_buffer.get_string(ret_val);
return ret_val;
}
@@ -1134,13 +1234,48 @@ OCTETSTRING enc__RlcmacUlDataBlock(const RlcmacUlDataBlock& si)
static
void enc__RlcmacUlEgprsDataHeader_type1(const EgprsUlMacDataHeader& si, TTCN_Buffer& ttcn_buffer)
{
- fprintf(stderr, "FIXME: Not implemented! %s (%s:%u)\n", __func__, __FILE__, __LINE__);
+ struct gprs_rlc_ul_header_egprs_1 egprs1;
+
+ egprs1.r = bs2uint8(si.r__ri());
+ egprs1.si = bs2uint8(si.foi__si());
+ egprs1.cv = si.countdown();
+ egprs1.tfi_hi = si.tfi() >> 0;
+ egprs1.tfi_lo = si.tfi() >> 2;
+ egprs1.bsn1_hi = si.bsn1() >> 0;
+ egprs1.bsn1_lo = si.bsn1() >> 5;
+ egprs1.bsn2_hi = si.bsn2__offset() >> 0;
+ egprs1.bsn2_lo = si.bsn2__offset() >> 2;
+ egprs1.cps = si.cps();
+ egprs1.rsb = bs2uint8(si.rsb());
+ egprs1.pi = si.pfi__ind();
+ egprs1.spare_hi = 0;
+ egprs1.spare_lo = 0;
+ egprs1.dummy = 0;
+
+ ttcn_buffer.put_s(sizeof(egprs1), (const unsigned char *)&egprs1);
}
static
void enc__RlcmacUlEgprsDataHeader_type2(const EgprsUlMacDataHeader& si, TTCN_Buffer& ttcn_buffer)
{
- fprintf(stderr, "FIXME: Not implemented! %s (%s:%u)\n", __func__, __FILE__, __LINE__);
+ struct gprs_rlc_ul_header_egprs_2 egprs2;
+
+ egprs2.r = bs2uint8(si.r__ri());
+ egprs2.si = bs2uint8(si.foi__si());
+ egprs2.cv = si.countdown();
+ egprs2.tfi_hi = si.tfi() >> 0;
+ egprs2.tfi_lo = si.tfi() >> 2;
+ egprs2.bsn1_hi = si.bsn1() >> 0;
+ egprs2.bsn1_lo = si.bsn1() >> 5;
+ egprs2.cps_hi = si.cps() >> 0;
+ egprs2.cps_lo = si.cps() >> 2;
+ egprs2.rsb = bs2uint8(si.rsb());
+ egprs2.pi = si.pfi__ind();
+ egprs2.spare_hi = 0;
+ egprs2.spare_lo = 0;
+ egprs2.dummy = 0;
+
+ ttcn_buffer.put_s(sizeof(egprs2), (const unsigned char *)&egprs2);
}
static
@@ -1175,7 +1310,6 @@ OCTETSTRING enc__RlcmacUlEgprsDataBlock(const RlcmacUlEgprsDataBlock& si)
unsigned int data_block_bits, data_block_offsets[2];
unsigned int num_calls;
CodingScheme mcs;
- boolean tlli_ind, e;
mcs = RLCMAC__Templates::f__rlcmac__cps__htype__to__mcs(in.mac__hdr().cps(), in.mac__hdr().header__type());
//fprintf(stderr, "RLCMAC: infered MCS %s (%d)\n", mcs.enum_to_str(static_cast<CodingScheme::enum_type>(mcs.as_int())), mcs.as_int());
@@ -1209,7 +1343,7 @@ OCTETSTRING enc__RlcmacUlEgprsDataBlock(const RlcmacUlEgprsDataBlock& si)
}
/* Put first TI + E byte */
- aligned_buffer.put_c(tlli_ind << 1 | e << 0); /* M=0, E=1 LEN=0 */
+ aligned_buffer.put_c((in.tlli__ind() & 0x01) << 1 | (in.e() & 0x01) << 0);
//printbuffer("After encoding first byte", aligned_buffer);
if (in.e() == false) {
@@ -1251,7 +1385,13 @@ OCTETSTRING enc__RlcmacUlEgprsDataBlock(const RlcmacUlEgprsDataBlock& si)
if (in.tlli__ind()) {
- aligned_buffer.put_string(in.tlli());
+ /* The TLLI is encoded in little endian for EGPRS (see
+ * TS 44.060, figure 10.3a.2.1, note 2) */
+ OCTETSTRING tlli = in.tlli();
+ aligned_buffer.put_c(tlli[3].get_octet());
+ aligned_buffer.put_c(tlli[2].get_octet());
+ aligned_buffer.put_c(tlli[1].get_octet());
+ aligned_buffer.put_c(tlli[0].get_octet());
}
if (in.mac__hdr().pfi__ind()) {
@@ -1274,6 +1414,8 @@ OCTETSTRING enc__RlcmacUlEgprsDataBlock(const RlcmacUlEgprsDataBlock& si)
put_egprs_data_block(aligned_buffer, data_block_offsets[0], data_block_bits, ttcn_buffer);
//printbuffer("after merging data block", ttcn_buffer);
+ encode_trailing_padding_spb(ttcn_buffer, in.mcs());
+
ttcn_buffer.get_string(ret_val);
return ret_val;
}
diff --git a/library/RLCMAC_Templates.ttcn b/library/RLCMAC_Templates.ttcn
index 5bdc17d4..5e273413 100644
--- a/library/RLCMAC_Templates.ttcn
+++ b/library/RLCMAC_Templates.ttcn
@@ -18,6 +18,10 @@ module RLCMAC_Templates {
import from RLCMAC_CSN1_Templates all;
import from RLCMAC_Types all;
+ template CodingScheme cs_gprs_any := (CS_1, CS_2, CS_3, CS_4);
+ template CodingScheme mcs_egprs_any := (MCS_1, MCS_2, MCS_3, MCS_4, MCS_5,
+ MCS_6, MCS_7, MCS_8, MCS_9);
+
/* TS 44.060 10.4.5 */
function f_rrbp_fn_delay(MacRrbp rrbp) return uint32_t {
select (rrbp) {
@@ -34,6 +38,13 @@ module RLCMAC_Templates {
return (current_fn + f_rrbp_fn_delay(rrbp)) mod 2715648;
}
+ function f_rlcmac_cs_mcs_is_mcs(CodingScheme cs_mcs) return boolean {
+ if (cs_mcs >= MCS_0) {
+ return true;
+ }
+ return false;
+ }
+
function f_rlcmac_mcs2headertype(CodingScheme mcs) return EgprsHeaderType {
select (mcs) {
case (MCS_0) { return RLCMAC_HDR_TYPE_3; }
@@ -93,7 +104,27 @@ module RLCMAC_Templates {
return CS_1;
}
- /* Minimum CodingScheme required to fit RLCMAC block */
+ function f_rlcmac_cs_mcs2block_len_no_spare_bits(CodingScheme cs_mcs) return uint32_t {
+ select (cs_mcs) {
+ /* 3GPP TS 44.060 Table 10.2.1: RLC data block size, discounting padding in octet */
+ case (CS_1) { return 23; }
+ case (CS_2) { return 33; }
+ case (CS_3) { return 39; }
+ case (CS_4) { return 53; }
+ case (MCS_1) { return 27; }
+ case (MCS_2) { return 33; }
+ case (MCS_3) { return 42; }
+ case (MCS_4) { return 49; }
+ case (MCS_5) { return 61; }
+ case (MCS_6) { return 79; }
+ case (MCS_7) { return 119; }
+ case (MCS_8) { return 143; }
+ case (MCS_9) { return 155; }
+ }
+ return 0;
+ }
+
+ /* Minimum CodingScheme required to fit RLCMAC block. Spare bits not counted. */
function f_rlcmac_block_len_required_cs_mcs(uint32_t len, boolean is_mcs) return CodingScheme {
if (is_mcs) {
if (len <= 27) { return MCS_1; }
@@ -330,8 +361,16 @@ module RLCMAC_Templates {
}
}
+ private function f_presence_bit_chreq_desc(template (omit) ChannelReqDescription chreq_desc) return BIT1 {
+ if (istemplatekind(chreq_desc, "omit")) {
+ return '0'B;
+ }
+ return '1'B;
+ }
+
/* Send Template for Downlink ACK/NACK */
- template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template uint5_t tfi, AckNackDescription andesc, boolean retry := false) := {
+ template (value) RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK(template (value) uint5_t tfi, AckNackDescription andesc, boolean retry := false,
+ template (omit) ChannelReqDescription chreq_desc := omit) := {
ctrl := {
mac_hdr := {
payload_type := MAC_PT_RLCMAC_NO_OPT,
@@ -344,8 +383,8 @@ module RLCMAC_Templates {
dl_ack_nack := {
dl_tfi := tfi,
ack_nack_desc := andesc,
- chreq_desc_presence := '0'B,
- chreq_desc := omit,
+ chreq_desc_presence := f_presence_bit_chreq_desc(chreq_desc),
+ chreq_desc := chreq_desc,
ch_qual_rep := c_ChQualRep_default
}
}
@@ -353,17 +392,31 @@ module RLCMAC_Templates {
}
}
- template RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK_CHREQ(template uint5_t tfi,
- AckNackDescription andesc,
- boolean retry := false,
- template ChannelReqDescription chreq_desc := c_ChReqDesc_default)
- modifies ts_RLCMAC_DL_ACK_NACK := {
+ /* Send Template for Egprs Downlink ACK/NACK */
+ template (value) RlcmacUlBlock ts_RLCMAC_DL_ACK_NACK_EGPRS(template (value) uint5_t tfi,
+ EgprsAckNackDescription andesc,
+ boolean retry := false,
+ template (omit) ChannelReqDescription chreq_desc := omit) := {
ctrl := {
+ mac_hdr := {
+ payload_type := MAC_PT_RLCMAC_NO_OPT,
+ spare := '00000'B,
+ retry := retry
+ },
payload := {
+ msg_type := PACKET_EGPRS_DL_ACK_NACK,
u := {
- dl_ack_nack := {
- chreq_desc_presence := '1'B,
- chreq_desc := chreq_desc
+ dl_ack_nack_egprs := {
+ dl_tfi := tfi,
+ ms_oom := '0'B,
+ egprs_ch_qual_rep_presence := '0'B,
+ egprs_ch_qual_rep := omit,
+ chreq_desc_presence := f_presence_bit_chreq_desc(chreq_desc),
+ chreq_desc := chreq_desc,
+ pfi_presence := '0'B,
+ pfi := omit,
+ epdan_presence := '0'B,
+ ack_nack_desc_ie := ts_EgprsAckNackDescriptionIE(andesc)
}
}
}
@@ -371,13 +424,18 @@ module RLCMAC_Templates {
}
/* Template for uplink Data block */
- template RlcmacUlBlock t_RLCMAC_UL_DATA(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
- template LlcBlocks blocks := {}, template boolean stall := false) := {
+ template (value) RlcmacUlBlock t_RLCMAC_UL_DATA(template (value) CodingScheme cs,
+ template (value) uint5_t tfi,
+ template (value) uint4_t cv,
+ template (value) uint7_t bsn,
+ template (value) LlcBlocks blocks := {},
+ template (value) boolean stall := false) := {
data := {
+ cs := cs,
mac_hdr := {
payload_type := MAC_PT_RLC_DATA,
countdown := cv,
- stall_ind := false,
+ stall_ind := stall,
retry := false,
spare := '0'B,
pfi_ind := false,
@@ -391,13 +449,19 @@ module RLCMAC_Templates {
blocks := blocks
}
}
- template RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template uint5_t tfi, template uint4_t cv, template uint7_t bsn,
- template LlcBlocks blocks := {}, template boolean stall := false, template GprsTlli tlli) := {
+ template (value) RlcmacUlBlock t_RLCMAC_UL_DATA_TLLI(template (value) CodingScheme cs,
+ template (value) uint5_t tfi,
+ template (value) uint4_t cv,
+ template (value) uint7_t bsn,
+ template (value) LlcBlocks blocks := {},
+ template (value) boolean stall := false,
+ template (value) GprsTlli tlli) := {
data := {
+ cs := cs,
mac_hdr := {
payload_type := MAC_PT_RLC_DATA,
countdown := cv,
- stall_ind := false,
+ stall_ind := stall,
retry := false,
spare := '0'B,
pfi_ind := false,
@@ -413,10 +477,14 @@ module RLCMAC_Templates {
}
/* Template for uplink Data block */
- template RlcmacUlBlock t_RLCMAC_UL_EGPRS_DATA(CodingScheme mcs,
- template uint5_t tfi, template uint4_t cv,
- template uint11_t bsn1, template EgprsLlcBlocks blocks := {}) := {
+ template (value) RlcmacUlBlock t_RLCMAC_UL_EGPRS_DATA(CodingScheme mcs,
+ template (value) uint5_t tfi,
+ template (value) uint4_t cv,
+ template (value) uint11_t bsn1,
+ template (value) uint8_t bsn2_offset := 0,
+ template (value) EgprsLlcBlocks blocks := {}) := {
data_egprs := {
+ mcs := mcs,
mac_hdr := {
header_type := f_rlcmac_mcs2headertype(mcs),
tfi := tfi,
@@ -424,6 +492,7 @@ module RLCMAC_Templates {
foi_si := '0'B,
r_ri := '0'B,
bsn1 := bsn1,
+ bsn2_offset := bsn2_offset,
cps := f_rlcmac_mcs_to_cps(mcs, 1, false),
pfi_ind := false,
rsb := '0'B,
@@ -437,17 +506,59 @@ module RLCMAC_Templates {
}
}
- template DlMacHeader t_RLCMAC_DlMacH(template (present) MacPayloadType pt,
- template (present) boolean rrbp_valid,
- template (present) MacRrbp rrbp,
- template (present) uint3_t usf) := {
+ template (value) DlMacHeader
+ ts_RLCMAC_DlMacH(template (value) MacPayloadType pt := MAC_PT_RLCMAC_NO_OPT,
+ template (value) boolean rrbp_valid := false,
+ template (value) MacRrbp rrbp := RRBP_Nplus13_mod_2715648,
+ template (value) uint3_t usf := 7) := {
+ payload_type := pt,
+ rrbp := rrbp,
+ rrbp_valid := rrbp_valid,
+ usf := usf
+ }
+ template DlMacHeader
+ t_RLCMAC_DlMacH(template (present) MacPayloadType pt,
+ template (present) boolean rrbp_valid,
+ template (present) MacRrbp rrbp,
+ template (present) uint3_t usf) := {
payload_type := pt,
rrbp := rrbp,
rrbp_valid := rrbp_valid,
usf := usf
}
- template RlcmacDlBlock tr_RLCMAC_DUMMY_CTRL(template uint3_t usf := ?, template PageMode page_mode := ?) := {
+ template RlcmacDlBlock tr_RLCMAC_DL_CTRL(template uint3_t usf := ?, template RlcmacDlCtrlMsg dl_ctrl := ?) := {
+ ctrl := {
+ mac_hdr := {
+ payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
+ rrbp:= ?,
+ rrbp_valid := ?,
+ usf := usf
+ },
+ opt := *,
+ payload := dl_ctrl
+ }
+ }
+
+ template (value) RlcmacDlBlock
+ ts_RLCMAC_DL_DUMMY_CTRL(template (value) DlMacHeader mac_hdr := ts_RLCMAC_DlMacH,
+ template (value) PageMode page_mode := PAGE_MODE_NORMAL) := {
+ ctrl := {
+ mac_hdr := mac_hdr,
+ opt := omit,
+ payload := {
+ msg_type := PACKET_DL_DUMMY_CTRL,
+ u := {
+ dl_dummy := {
+ page_mode := page_mode,
+ persistence_levels_present := '0'B,
+ persistence_levels := omit
+ }
+ }
+ }
+ }
+ }
+ template RlcmacDlBlock tr_RLCMAC_DL_DUMMY_CTRL(template uint3_t usf := ?, template PageMode page_mode := ?) := {
ctrl := {
mac_hdr := {
payload_type := (MAC_PT_RLCMAC_NO_OPT, MAC_PT_RLCMAC_OPT),
@@ -594,7 +705,7 @@ module RLCMAC_Templates {
}
};
- template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK_GPRS(template uint5_t ul_tfi, template UlAckNackGprs gprs := tr_UlAckNackGprs(*))
+ template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK_GPRS(template uint5_t ul_tfi := ?, template UlAckNackGprs gprs := tr_UlAckNackGprs(*))
modifies tr_RLCMAC_UL_ACK_NACK := {
ctrl := {
payload := {
@@ -609,7 +720,7 @@ module RLCMAC_Templates {
}
};
- template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK_EGPRS(template uint5_t ul_tfi, template UlAckNackEgprs egprs := tr_UlAckNackEgprs(*))
+ template RlcmacDlBlock tr_RLCMAC_UL_ACK_NACK_EGPRS(template uint5_t ul_tfi := ?, template UlAckNackEgprs egprs := tr_UlAckNackEgprs(*))
modifies tr_RLCMAC_UL_ACK_NACK := {
ctrl := {
payload := {
@@ -642,8 +753,8 @@ module RLCMAC_Templates {
persistence_levels := *,
nln_present := ?,
nln := *,
- repeated_pageinfo_present := ?,
- repeated_pageinfo := *
+ repeated_pageinfo := *,
+ repeated_pageinfo_term := '0'B
}
}
}
@@ -657,6 +768,7 @@ module RLCMAC_Templates {
template (present) MacRrbp rrbp := ?,
template (present) uint3_t usf := ?) := {
data := {
+ cs := ?,
mac_hdr := {
mac_hdr := {
payload_type := MAC_PT_RLC_DATA,
@@ -672,6 +784,7 @@ module RLCMAC_Templates {
template RlcmacDlBlock tr_RLCMAC_DATA_EGPRS := {
data_egprs := {
+ mcs := ?,
mac_hdr := ?,
fbi := ?,
e := ?,
@@ -680,14 +793,16 @@ module RLCMAC_Templates {
}
/* Template for Uplink MAC Control Header */
- template UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template MacPayloadType pt, template boolean retry := false) := {
+ template (value) UlMacCtrlHeader t_RLCMAC_UlMacCtrlH(template (value) MacPayloadType pt,
+ template (value) boolean retry := false) := {
payload_type := pt,
spare := '00000'B,
retry := retry
}
/* Template for Uplink Control ACK */
- template RlcmacUlBlock ts_RLCMAC_CTRL_ACK(GprsTlli tlli, CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
+ template (value) RlcmacUlBlock
+ ts_RLCMAC_CTRL_ACK(GprsTlli tlli, CtrlAck ack := MS_RCVD_TWO_RLC_SAME_RTI_DIFF_RBSN) := {
ctrl := {
mac_hdr := t_RLCMAC_UlMacCtrlH(MAC_PT_RLCMAC_NO_OPT),
payload := {
@@ -702,6 +817,21 @@ module RLCMAC_Templates {
}
}
+ template (value) RlcmacUlBlock
+ ts_RLCMAC_UL_DUMMY_CTRL(template (value) GprsTlli tlli) := {
+ ctrl := {
+ mac_hdr := t_RLCMAC_UlMacCtrlH(MAC_PT_RLCMAC_NO_OPT),
+ payload := {
+ msg_type := PACKET_UL_DUMMY_CTRL,
+ u := {
+ ul_dummy := {
+ tlli := tlli
+ }
+ }
+ }
+ }
+ }
+
template LlcBlockHdr t_RLCMAC_LLCBLOCK_HDR(uint16_t length_ind, boolean more, boolean e) := {
length_ind := length_ind,
more := more, /* 1 = new LLC PDU starts */
@@ -726,4 +856,79 @@ module RLCMAC_Templates {
payload := data
}
+ template (value) PTCCHDownlinkMsg
+ ts_PTCCHDownlinkMsg(template (value) uint7_t tai0_ta := 0,
+ template (value) uint7_t tai1_ta := 0,
+ template (value) uint7_t tai2_ta := 0,
+ template (value) uint7_t tai3_ta := 0,
+ template (value) uint7_t tai4_ta := 0,
+ template (value) uint7_t tai5_ta := 0,
+ template (value) uint7_t tai6_ta := 0,
+ template (value) uint7_t tai7_ta := 0,
+ template (value) uint7_t tai8_ta := 0,
+ template (value) uint7_t tai9_ta := 0,
+ template (value) uint7_t tai10_ta := 0,
+ template (value) uint7_t tai11_ta := 0,
+ template (value) uint7_t tai12_ta := 0,
+ template (value) uint7_t tai13_ta := 0,
+ template (value) uint7_t tai14_ta := 0,
+ template (value) uint7_t tai15_ta := 0) := {
+ ta_idx := {
+ { spare := '0'B, ta_val := tai0_ta },
+ { spare := '0'B, ta_val := tai1_ta },
+ { spare := '0'B, ta_val := tai2_ta },
+ { spare := '0'B, ta_val := tai3_ta },
+ { spare := '0'B, ta_val := tai4_ta },
+ { spare := '0'B, ta_val := tai5_ta },
+ { spare := '0'B, ta_val := tai6_ta },
+ { spare := '0'B, ta_val := tai7_ta },
+ { spare := '0'B, ta_val := tai8_ta },
+ { spare := '0'B, ta_val := tai9_ta },
+ { spare := '0'B, ta_val := tai10_ta },
+ { spare := '0'B, ta_val := tai11_ta },
+ { spare := '0'B, ta_val := tai12_ta },
+ { spare := '0'B, ta_val := tai13_ta },
+ { spare := '0'B, ta_val := tai14_ta },
+ { spare := '0'B, ta_val := tai15_ta }
+ },
+ padding := '2B2B2B2B2B2B2B'O
+ }
+ template PTCCHDownlinkMsg
+ tr_PTCCHDownlinkMsg(template (present) uint7_t tai0_ta := ?,
+ template (present) uint7_t tai1_ta := ?,
+ template (present) uint7_t tai2_ta := ?,
+ template (present) uint7_t tai3_ta := ?,
+ template (present) uint7_t tai4_ta := ?,
+ template (present) uint7_t tai5_ta := ?,
+ template (present) uint7_t tai6_ta := ?,
+ template (present) uint7_t tai7_ta := ?,
+ template (present) uint7_t tai8_ta := ?,
+ template (present) uint7_t tai9_ta := ?,
+ template (present) uint7_t tai10_ta := ?,
+ template (present) uint7_t tai11_ta := ?,
+ template (present) uint7_t tai12_ta := ?,
+ template (present) uint7_t tai13_ta := ?,
+ template (present) uint7_t tai14_ta := ?,
+ template (present) uint7_t tai15_ta := ?) := {
+ ta_idx := {
+ { spare := '0'B, ta_val := tai0_ta },
+ { spare := '0'B, ta_val := tai1_ta },
+ { spare := '0'B, ta_val := tai2_ta },
+ { spare := '0'B, ta_val := tai3_ta },
+ { spare := '0'B, ta_val := tai4_ta },
+ { spare := '0'B, ta_val := tai5_ta },
+ { spare := '0'B, ta_val := tai6_ta },
+ { spare := '0'B, ta_val := tai7_ta },
+ { spare := '0'B, ta_val := tai8_ta },
+ { spare := '0'B, ta_val := tai9_ta },
+ { spare := '0'B, ta_val := tai10_ta },
+ { spare := '0'B, ta_val := tai11_ta },
+ { spare := '0'B, ta_val := tai12_ta },
+ { spare := '0'B, ta_val := tai13_ta },
+ { spare := '0'B, ta_val := tai14_ta },
+ { spare := '0'B, ta_val := tai15_ta }
+ },
+ padding := '2B2B2B2B2B2B2B'O
+ }
+
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/RLCMAC_Types.ttcn b/library/RLCMAC_Types.ttcn
index 96b8a647..76aeb22e 100644
--- a/library/RLCMAC_Types.ttcn
+++ b/library/RLCMAC_Types.ttcn
@@ -115,6 +115,11 @@ module RLCMAC_Types {
DlCtrlOptOctets opt optional,
RlcmacDlCtrlMsg payload
} with {
+ /* Automatic padding by RAW encoder seems to causing problems
+ * due to padding sequence 2b inserted shifted from octet
+ * boundary on some messags. See UL CTRL blocks in TC_t3193.
+ * See 3GPP TS 44.060 Figure 11.1 (below)
+ * variant "PADDING(184), PADDING_PATTERN('00101011'B)" */
variant (opt) "PRESENCE(mac_hdr.payload_type = MAC_PT_RLCMAC_OPT)"
};
@@ -133,7 +138,14 @@ module RLCMAC_Types {
type record RlcmacUlCtrlBlock {
UlMacCtrlHeader mac_hdr,
RlcmacUlCtrlMsg payload
- } with { variant "" };
+ } with {
+ /* Automatic padding by RAW encoder seems to causing problems
+ * due to padding sequence 2b inserted shifted from octet
+ * boundary on some messags. See UL CTRL blocks in TC_t3193.
+ * See 3GPP TS 44.060 Figure 11.1 (below)
+ * variant "PADDING(184), PADDING_PATTERN('00101011'B)" */
+ variant ""
+ };
external function enc_RlcmacUlCtrlBlock(in RlcmacUlCtrlBlock si) return octetstring
with { extension "prototype(convert) encode(RAW)" };
@@ -182,6 +194,7 @@ module RLCMAC_Types {
DlMacHdrDataExt hdr_ext
} with { variant "" };
type record RlcmacDlDataBlock {
+ CodingScheme cs, /* Provided by C++ Decoder */
DlMacDataHeader mac_hdr,
/* Octet 3..M / N: manual C++ Decoder */
LlcBlocks blocks
@@ -222,14 +235,15 @@ module RLCMAC_Types {
MacRrbp rrbp,
BIT2 esp,
uint3_t usf,
- uint14_t bsn1,
+ uint11_t bsn1,
uint8_t bsn2_offset,
uint2_t pr, /* power reduction */
- uint2_t spb,
+ uint2_t spb optional,
uint4_t cps
- } with { variant "" };
+ } with { variant (spb) "PRESENCE(header_type=RLCMAC_HDR_TYPE_3)" };
/* Manual C++ Decoder: */
type record RlcmacDlEgprsDataBlock {
+ CodingScheme mcs, /* Provided by C++ Decoder */
EgprsDlMacDataHeader mac_hdr,
boolean fbi,
boolean e,
@@ -277,15 +291,18 @@ module RLCMAC_Types {
BIT1 foi_si,
BIT1 r_ri,
uint11_t bsn1,
+ uint8_t bsn2_offset,
uint4_t cps,
boolean pfi_ind,
BIT1 rsb,
- BIT2 spb
+ BIT2 spb optional
} with {
variant (pfi_ind) "FIELDLENGTH(1)"
+ variant (spb) "PRESENCE(header_type=RLCMAC_HDR_TYPE_3)"
};
/* Manual C++ Decoder: 10.3a.2.1 EGPRS Uplink RLC data block */
type record RlcmacUlEgprsDataBlock {
+ CodingScheme mcs, /* Provided by C++ Decoder */
EgprsUlMacDataHeader mac_hdr,
boolean tlli_ind,
boolean e,
@@ -300,6 +317,7 @@ module RLCMAC_Types {
/* TS 44.060 10.2.2 */
type record RlcmacUlDataBlock {
+ CodingScheme cs, /* Provided by C++ Decoder */
/* MAC header */
UlMacDataHeader mac_hdr,
/* Octet 3 ... M (optional): manual C++ Decoder */
@@ -354,10 +372,8 @@ module RLCMAC_Types {
external function enc_RlcmacDlBlock(in RlcmacDlBlock si) return octetstring;
external function dec_RlcmacDlBlock(in octetstring stream) return RlcmacDlBlock;
-/************************
- * PTCCH/D (Packet Timing Advance Control Channel) message.
- * TODO: add a spec. reference to the message format definition.
- *************************/
+ /* PTCCH (Packet Timing Advance Control Channel) downlink block format.
+ * See 3GPP TS 44.004, section 7.8. */
type record PTCCHTimingAdvanceIE {
BIT1 spare ('0'B),
uint7_t ta_val
@@ -373,44 +389,4 @@ module RLCMAC_Types {
external function dec_PTCCHDownlinkMsg(in octetstring stream) return PTCCHDownlinkMsg
with { extension "prototype(convert) decode(RAW)" };
- template PTCCHDownlinkMsg tr_PTCCHDownlinkMsg(
- template (present) uint7_t tai0_ta := ?,
- template (present) uint7_t tai1_ta := ?,
- template (present) uint7_t tai2_ta := ?,
- template (present) uint7_t tai3_ta := ?,
- template (present) uint7_t tai4_ta := ?,
- template (present) uint7_t tai5_ta := ?,
- template (present) uint7_t tai6_ta := ?,
- template (present) uint7_t tai7_ta := ?,
- template (present) uint7_t tai8_ta := ?,
- template (present) uint7_t tai9_ta := ?,
- template (present) uint7_t tai10_ta := ?,
- template (present) uint7_t tai11_ta := ?,
- template (present) uint7_t tai12_ta := ?,
- template (present) uint7_t tai13_ta := ?,
- template (present) uint7_t tai14_ta := ?,
- template (present) uint7_t tai15_ta := ?
- ) := {
- ta_idx := {
- { spare := '0'B, ta_val := tai0_ta },
- { spare := '0'B, ta_val := tai1_ta },
- { spare := '0'B, ta_val := tai2_ta },
- { spare := '0'B, ta_val := tai3_ta },
- { spare := '0'B, ta_val := tai4_ta },
- { spare := '0'B, ta_val := tai5_ta },
- { spare := '0'B, ta_val := tai6_ta },
- { spare := '0'B, ta_val := tai7_ta },
- { spare := '0'B, ta_val := tai8_ta },
- { spare := '0'B, ta_val := tai9_ta },
- { spare := '0'B, ta_val := tai10_ta },
- { spare := '0'B, ta_val := tai11_ta },
- { spare := '0'B, ta_val := tai12_ta },
- { spare := '0'B, ta_val := tai13_ta },
- { spare := '0'B, ta_val := tai14_ta },
- { spare := '0'B, ta_val := tai15_ta }
- },
- padding := '2B2B2B2B2B2B2B'O
- }
-
-
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/RSL_Emulation.ttcn b/library/RSL_Emulation.ttcn
index 2fcb96ca..891e5654 100644
--- a/library/RSL_Emulation.ttcn
+++ b/library/RSL_Emulation.ttcn
@@ -34,13 +34,6 @@ import from RSL_Types all;
import from IPA_Types all;
import from IPA_Emulation all;
-
-modulepar {
- /* Work around switch for ttcn3-bts-test-latest, enables patching of IPA
- * stream ID in the "BSC" mode. See I5927f59a49724170a63e87be604973f7c9d5d8be. */
- boolean mp_rslem_patch_ipa_cid := false;
-};
-
/* General "base class" component definition, of which specific implementations
* derive themselves by means of the "extends" feature */
type component RSL_DchanHdlr {
@@ -92,7 +85,7 @@ template RSLEm_Event tr_RSLEm_EV(template RSLEm_EventType ev_type,
};
type port RSL_DCHAN_PT message {
- inout RSLDC_ChanRqd, RSL_Message;
+ inout RSLDC_ChanRqd, RSL_Message, ASP_RSL_Unitdata;
} with { extension "internal" };
type port RSL_CCHAN_PT message {
@@ -105,18 +98,20 @@ signature RSLEM_unregister(uint8_t trx_nr, RslChannelNr chan_nr, RSL_DchanHdlr h
signature RSLEM_suspend(boolean suspend);
signature RSLEM_wait_queue(boolean enable);
signature RSLEM_get_last_act(in uint8_t trx_nr, in RslChannelNr chan_nr, out RSL_Message chan_act);
+signature RSLEM_set_auto_chan_act_ack(boolean enable);
type port RSLEM_PROC_PT procedure {
inout RSLEM_register, RSLEM_unregister,
RSLEM_suspend, RSLEM_wait_queue,
- RSLEM_get_last_act;
+ RSLEM_get_last_act,
+ RSLEM_set_auto_chan_act_ack;
} with { extension "internal" };
/***********************************************************************
* Client Component for a single dedicated channel
***********************************************************************/
-private function f_rx_or_fail(template RSL_Message exp_rx) runs on RSL_DchanHdlr return RSL_Message
+private function f_rx_or_fail(template RSL_Message exp_rx, RSL_DCHAN_PT rsl_pt := RSL) runs on RSL_DchanHdlr return RSL_Message
{
var RSL_Message rx_rsl;
timer T := 10.0;
@@ -124,11 +119,11 @@ private function f_rx_or_fail(template RSL_Message exp_rx) runs on RSL_DchanHdlr
/* request a channel to be established */
T.start;
alt {
- [] RSL.receive(exp_rx) -> value rx_rsl {
+ [] rsl_pt.receive(exp_rx) -> value rx_rsl {
T.stop;
return rx_rsl;
}
- [] RSL.receive {
+ [] rsl_pt.receive {
setverdict(fail, "Unexpected RSL message on DCHAN");
mtc.stop;
}
@@ -141,19 +136,41 @@ private function f_rx_or_fail(template RSL_Message exp_rx) runs on RSL_DchanHdlr
return rx_rsl;
}
+function f_chan_act_verify_tsc(RSL_Message chan_act, template uint3_t tsc) {
+ var RSL_IE_Body ie;
+ if (f_rsl_find_ie(chan_act, RSL_IE_CHAN_IDENT, ie)) {
+ var uint3_t got_tsc := ie.chan_ident.ch_desc.v.tsc;
+ if (not match(got_tsc, tsc)) {
+ setverdict(fail, "RSL CHANnel ACTIVation: unexpected TSC in Channel Description: expected ",
+ tsc, " got ", got_tsc);
+ mtc.stop;
+ }
+ }
+}
+
/* establish a dedicated channel using 'ra' */
-function f_chan_est(OCT1 ra, octetstring est_l3, template RslLinkId link_id, GsmFrameNumber fn := 23)
+function f_chan_est(OCT1 ra, octetstring est_l3, template RslLinkId link_id, GsmFrameNumber fn := 23,
+ template uint3_t tsc := ?, RSL_DCHAN_PT rsl_pt := RSL, RSLEM_PROC_PT rsl_proc_pt := RSL_PROC)
runs on RSL_DchanHdlr {
var RSL_Message rx_rsl;
var GsmRrMessage rr;
/* request a channel to be established */
- RSL.send(ts_RSLDC_ChanRqd(ra, fn));
+ rsl_pt.send(ts_RSLDC_ChanRqd(ra, fn));
+ /* At this point the BSC sends a CHAN ACTIV which we always ACK. Checking it below. */
/* expect immediate assignment */
- rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
+ rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN, rsl_pt := rsl_pt);
rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
+ if (not match(rr.payload.imm_ass.chan_desc.tsc, tsc)) {
+ setverdict(fail, "Immediate Assignment: unexpected TSC in Channel Description: expected ", tsc, " got ",
+ rr.payload.imm_ass.chan_desc.tsc);
+ mtc.stop;
+ }
g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
- RSL.send(ts_RSL_EST_IND(g_chan_nr, valueof(link_id), est_l3));
+ rsl_pt.send(ts_RSL_EST_IND(g_chan_nr, valueof(link_id), est_l3));
+
+ /* Check above CHAN ACTIV */
+ f_chan_act_verify_tsc(f_rslem_get_last_act(rsl_proc_pt, 0, g_chan_nr), tsc);
}
function f_deact_chan(RSL_Cause cause) runs on RSL_DchanHdlr
@@ -419,19 +436,6 @@ runs on RSL_Emulation_CT return integer {
return TrxConnMap[trx_nr];
}
-/* Work around for a bug in osmo-bts when all transceivers use IPAC_PROTO_RSL_TRX0 */
-private function f_trx_conn_map_patch_ud(inout ASP_RSL_Unitdata ud)
-runs on RSL_Emulation_CT {
- for (var integer i := 0; i < sizeof(TrxConnMap); i := i + 1) {
- if (ud.conn_id == TrxConnMap[i]) {
- ud.streamId := f_streamId_by_trx(i);
- return; /* We're done */
- }
- }
-
- testcase.stop("Failed to patch IPA stream ID in ASP RSL UD: ", ud);
-}
-
private type record of ASP_RSL_Unitdata ASP_RSL_UDList;
type component RSL_Emulation_CT {
@@ -492,6 +496,7 @@ function main(boolean bts_role := true) runs on RSL_Emulation_CT {
* in a queue. These messages will remain in the queue until the appropriate
* connection handler is registered. */
var boolean wait_queue_enabled := false;
+ var boolean auto_chan_act_ack := true;
f_conn_table_init();
f_trx_conn_map_init();
@@ -587,26 +592,25 @@ function main(boolean bts_role := true) runs on RSL_Emulation_CT {
/* Forward common channel management to the special port for it */
[] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeT(?), sid := ?)) -> value rx_rsl {
- if (not bts_role and mp_rslem_patch_ipa_cid) {
- f_trx_conn_map_patch_ud(rx_rsl);
- }
CCHAN_PT.send(rx_rsl);
}
/* Forward common channel management to the special port for it */
[] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeC(?), sid := ?)) -> value rx_rsl {
- if (not bts_role and mp_rslem_patch_ipa_cid) {
- f_trx_conn_map_patch_ud(rx_rsl);
- }
CCHAN_PT.send(rx_rsl);
}
- /* blindly acknowledge all channel activations */
+ /* Channel Activation: store in LastActTable, possibly ACK. */
[bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl {
chan_nr := rx_rsl.rsl.ies[0].body.chan_nr;
trx_nr := f_trx_by_streamId(rx_rsl.streamId);
f_store_last_act_data(trx_nr, chan_nr, rx_rsl.rsl);
- IPA_PT.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl.streamId));
+ if (auto_chan_act_ack) {
+ /* blindly acknowledge all channel activations */
+ IPA_PT.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl.streamId));
+ } else {
+ CLIENT_PT.send(rx_rsl);
+ }
}
[not dchan_suspended] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeDR(?), sid := ?)) -> value rx_rsl {
@@ -619,6 +623,8 @@ function main(boolean bts_role := true) runs on RSL_Emulation_CT {
log("Storing an RSL message in the waiting queue");
WaitingQueue := WaitingQueue & { rx_rsl };
} else {
+ log("Error: RSL for unknown Dchan (streamId ", rx_rsl.streamId, ", chan_nr ",
+ rx_rsl.rsl.ies[0].body.chan_nr, "): ", rx_rsl);
setverdict(fail, "RSL for unknown Dchan");
mtc.stop;
}
@@ -651,6 +657,16 @@ function main(boolean bts_role := true) runs on RSL_Emulation_CT {
IPA_PT.send(ts_ASP_RSL_UD(rx_rsl_msg, ConnectionTable[cid].stream_id, conn_id));
}
+ /* allow the RSL_DchanHdlr components to "escape the sandbox" by sending RSL messages
+ * to other transceivers than they're bound to (determined by rx_rsl.streamId) */
+ [bts_role] CLIENT_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {
+ IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId));
+ }
+ [not bts_role] CLIENT_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {
+ conn_id := f_trx_conn_map_resolve(rx_rsl.streamId);
+ IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId, conn_id));
+ }
+
/* RSL message from MTC */
[bts_role] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {
IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId));
@@ -708,6 +724,10 @@ function main(boolean bts_role := true) runs on RSL_Emulation_CT {
var RSL_Message last_chan_act := f_lookup_last_act(trx_nr, chan_nr);
RSL_PROC.reply(RSLEM_get_last_act:{trx_nr, chan_nr, last_chan_act}) to vc_conn;
}
+
+ [] RSL_PROC.getcall(RSLEM_set_auto_chan_act_ack:{?}) -> param(auto_chan_act_ack) sender vc_conn {
+ RSL_PROC.reply(RSLEM_set_auto_chan_act_ack:{auto_chan_act_ack}) to vc_conn;
+ }
}
}
}
@@ -732,7 +752,6 @@ runs on RSL_Emulation_CT {
if (cid == -1) {
setverdict(fail, "No Dchan handler found for: ", WaitingQueue[i]);
mtc.stop;
- break;
}
/* Dispatch a stalled message to the appropriate handler */
@@ -803,7 +822,11 @@ runs on RSL_DchanHdlr return RSL_Message {
return chan_act;
}
-
-
+function f_rslem_set_auto_chan_act_ack(RSLEM_PROC_PT PT, boolean enable)
+runs on RSL_DchanHdlr {
+ PT.call(RSLEM_set_auto_chan_act_ack:{enable}) {
+ [] PT.getreply(RSLEM_set_auto_chan_act_ack:{enable}) {};
+ }
+}
}
diff --git a/library/RSL_Types.ttcn b/library/RSL_Types.ttcn
index af01c5d4..fa1d9285 100644
--- a/library/RSL_Types.ttcn
+++ b/library/RSL_Types.ttcn
@@ -4,7 +4,7 @@ module RSL_Types {
*
* RSL is a 3GPP standard protocol used between BTS and BSC in a GSM network.
*
- * (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2017-2023 by Harald Welte <laforge@gnumonks.org>
* All rights reserved.
*
* Released under the terms of GNU General Public License, Version 2 or
@@ -15,6 +15,7 @@ module RSL_Types {
import from General_Types all;
import from Osmocom_Types all;
+ import from GSM_RR_Types all;
import from GSM_Types all;
import from MobileL3_CommonIE_Types all;
import from L3_Templates all;
@@ -205,7 +206,7 @@ module RSL_Types {
RSL_IE_CBCH_LOAD_INFO ('00101101'B),
RSL_IE_SMSCB_CHAN_INDICATOR ('00101110'B),
RSL_IE_GROUP_CALL_REF ('00101111'B),
- RSL_IE_CHAN_DESC ('00110000'B),
+ RSL_IE_GROUP_CHAN_DESC ('00110000'B),
RSL_IE_NCH_DRX_INFO ('00110001'B),
RSL_IE_CMD_INDICATOR ('00110010'B),
RSL_IE_EMLPP_PRIO ('00110011'B),
@@ -219,6 +220,12 @@ module RSL_Types {
RSL_IE_TFO_STATUS ('00111011'B),
RSL_IE_LLP_APDU ('00111100'B),
+ /* Osmocom extensions */
+ RSL_IE_OSMO_REP_ACCH_CAP ('01100000'B),
+ RSL_IE_OSMO_TRAINING_SEQUENCE ('01100001'B),
+ RSL_IE_OSMO_TOP_ACCH_CAP ('01100010'B),
+ RSL_IE_OSMO_OSMUX_CID ('01100011'B),
+
/* ip.access */
RSL_IE_IPAC_SRTP_CONFIG ('11100000'B),
RSL_IE_IPAC_PROXY_UDP ('11100001'B),
@@ -313,12 +320,53 @@ module RSL_Types {
}
/* osmocom-style dynamic PDCH */
- const RSL_IE_ActivationType t_RSL_IE_ActType_PDCH := {
+ const RSL_IE_ActivationType c_RSL_IE_ActType_PDCH := {
reactivation := false,
reserved := 1,
a_bits := ACT_REL_TO_OSMO_PDCH
}
+ /* 9.3.5 */
+ type record RSL_IE_ChannelIdent {
+ uint8_t len,
+ /* 3GPP TS 44.018 Channel Description IE (TV) */
+ ChannelDescriptionTV ch_desc,
+ /* 3GPP TS 44.018 Mobile Allocation IE (shall be empty) */
+ MobileAllocationTLV ma
+ } with { variant (len) "LENGTHTO(ch_desc,ma)" };
+
+ template (value) RSL_IE_ChannelIdent
+ ts_RSL_ChannelIdent(template (value) ChannelDescription ch_desc) := {
+ len := 0, /* overwritten */
+ ch_desc := {
+ iei := '64'O,
+ v := ch_desc
+ },
+ /* Shall be included but empty */
+ ma := {
+ iei := '72'O,
+ v := {
+ len := 0,
+ ma := ''B
+ }
+ }
+ };
+
+ template RSL_IE_ChannelIdent
+ tr_RSL_ChannelIdent(template (present) ChannelDescription ch_desc := ?,
+ template (present) MobileAllocationLV ma := ?) := {
+ len := ?,
+ ch_desc := {
+ iei := '64'O,
+ v := ch_desc
+ },
+ /* Shall be included but empty */
+ ma := {
+ iei := '72'O,
+ v := ma
+ }
+ };
+
/* 9.3.6 */
type enumerated RSL_SpeechDataInd {
RSL_SPDI_SPEECH ('00000001'B),
@@ -334,10 +382,14 @@ module RSL_Types {
RSL_CHRT_TCH_F_GROUP ('00011000'B),
RSL_CHRT_TCH_H_GROUP ('00011001'B),
RSL_CHRT_TCH_F_BCAST ('00101000'B),
- RSL_CHRT_TCH_H_BCAST ('00101001'B)
+ RSL_CHRT_TCH_H_BCAST ('00101001'B),
+ RSL_CHRT_OSMO_TCH_F_VAMOS ('10001000'B),
+ RSL_CHRT_OSMO_TCH_H_VAMOS ('10001001'B)
+ } with { variant "FIELDLENGTH(8)" };
+ type enumerated RSL_ChanModeOct6Signalling {
+ RSL_CMOD_NO_RESOURCE ('00000000'B)
} with { variant "FIELDLENGTH(8)" };
- type enumerated RSL_SpeechAlgo {
- RSL_CMOD_NO_RESOURCE ('00000000'B),
+ type enumerated RSL_ChanModeOct6SpeechAlgo {
RSL_CMOD_SP_GSM1 ('00000001'B),
RSL_CMOD_SP_GSM2 ('00010001'B),
RSL_CMOD_SP_GSM3 ('00100001'B),
@@ -345,6 +397,33 @@ module RSL_Types {
RSL_CMOD_SP_GSM5 ('00001001'B),
RSL_CMOD_SP_GSM6 ('00001101'B)
} with { variant "FIELDLENGTH(8)" };
+ type enumerated RSL_ChanModeOct6DataRate {
+ RSL_CMOD_CSD_NTA_43k5_14k5 ('01100001'B),
+ RSL_CMOD_CSD_NTA_29k0_14k5 ('01100010'B),
+ RSL_CMOD_CSD_NTA_43k5_29k0 ('01100011'B),
+ RSL_CMOD_CSD_NTA_14k5_43k5 ('01101001'B),
+ RSL_CMOD_CSD_NTA_14k5_29k0 ('01101010'B),
+ RSL_CMOD_CSD_NTA_29k0_43k5 ('01101011'B),
+ RSL_CMOD_CSD_NT_43k5 ('01110100'B),
+ RSL_CMOD_CSD_NT_28k8 ('01110001'B),
+ RSL_CMOD_CSD_NT_14k5 ('01011000'B),
+ RSL_CMOD_CSD_NT_12k0 ('01010000'B),
+ RSL_CMOD_CSD_NT_6k0 ('01010001'B),
+ RSL_CMOD_CSD_T_32k0 ('00111000'B),
+ RSL_CMOD_CSD_T_29k0 ('00111001'B),
+ RSL_CMOD_CSD_T_14k4 ('00011000'B),
+ RSL_CMOD_CSD_T_9k6 ('00010000'B),
+ RSL_CMOD_CSD_T_4k8 ('00010001'B),
+ RSL_CMOD_CSD_T_2k4 ('00010010'B),
+ RSL_CMOD_CSD_T_1k2 ('00010011'B),
+ RSL_CMOD_CSD_T_600 ('00010100'B),
+ RSL_CMOD_CSD_T_1200_75 ('00010101'B)
+ } with { variant "FIELDLENGTH(8)" };
+ type union RSL_ChanModeOct6 {
+ RSL_ChanModeOct6Signalling sign,
+ RSL_ChanModeOct6SpeechAlgo speech,
+ RSL_ChanModeOct6DataRate data
+ };
type record RSL_IE_ChannelMode {
uint8_t len,
BIT6 reserved,
@@ -352,20 +431,67 @@ module RSL_Types {
boolean dtx_u,
RSL_SpeechDataInd spd_ind,
RSL_ChanRateType ch_rate_type,
- RSL_SpeechAlgo coding_alg_rate
- } with { variant (len) "LENGTHTO(reserved,dtx_d,dtx_u,spd_ind,ch_rate_type,coding_alg_rate)" }
-
- template (value) RSL_IE_ChannelMode ts_RSL_ChanMode_SIGN(boolean dtx_downlink := false) := {
+ RSL_ChanModeOct6 u
+ } with { variant (len) "LENGTHTO(reserved,dtx_d,dtx_u,spd_ind,ch_rate_type,u)"
+ variant (u) "CROSSTAG(
+ sign, spd_ind = RSL_SPDI_SIGN;
+ speech, spd_ind = RSL_SPDI_SPEECH;
+ data, spd_ind = RSL_SPDI_DATA;
+ )"}
+
+ template (value) RSL_IE_ChannelMode
+ ts_RSL_ChanMode_SIGN(template (value) RSL_ChanRateType t := RSL_CHRT_SDCCH,
+ template (value) boolean dtxd := false,
+ template (value) boolean dtxu := false) := {
len := 0, /* overwritten */
reserved := '000000'B,
- dtx_d := dtx_downlink,
- dtx_u := false,
+ dtx_d := dtxd,
+ dtx_u := dtxu,
+ spd_ind := RSL_SPDI_SIGN,
+ ch_rate_type := t,
+ u := { sign := RSL_CMOD_NO_RESOURCE }
+ }
+ template RSL_IE_ChannelMode
+ tr_RSL_ChanMode_SIGN(template (present) RSL_ChanRateType t := ?,
+ template (present) boolean dtxd := ?,
+ template (present) boolean dtxu := ?) := {
+ len := ?,
+ reserved := ?,
+ dtx_d := dtxd,
+ dtx_u := dtxu,
spd_ind := RSL_SPDI_SIGN,
- ch_rate_type := RSL_CHRT_SDCCH,
- coding_alg_rate := RSL_CMOD_NO_RESOURCE
+ ch_rate_type := t,
+ u := { sign := RSL_CMOD_NO_RESOURCE }
+ }
+
+ template (value) RSL_IE_ChannelMode
+ ts_RSL_ChanMode_DATA(template (value) RSL_ChanRateType t,
+ template (value) RSL_ChanModeOct6DataRate r,
+ template (value) boolean dtxd := false,
+ template (value) boolean dtxu := false) := {
+ len := 0, /* overwritten */
+ reserved := '000000'B,
+ dtx_d := dtxd,
+ dtx_u := dtxu,
+ spd_ind := RSL_SPDI_DATA,
+ ch_rate_type := t,
+ u := { data := r }
+ }
+ template RSL_IE_ChannelMode
+ tr_RSL_ChanMode_DATA(template (present) RSL_ChanRateType t := ?,
+ template (present) RSL_ChanModeOct6DataRate r := ?,
+ template (present) boolean dtxd := ?,
+ template (present) boolean dtxu := ?) := {
+ len := ?,
+ reserved := ?,
+ dtx_d := dtxd,
+ dtx_u := dtxu,
+ spd_ind := RSL_SPDI_DATA,
+ ch_rate_type := t,
+ u := { data := r }
}
- template (value) RSL_IE_ChannelMode ts_RSL_ChanMode(RSL_ChanRateType t, RSL_SpeechAlgo alg,
+ template (value) RSL_IE_ChannelMode ts_RSL_ChanMode(RSL_ChanRateType t, RSL_ChanModeOct6SpeechAlgo alg,
boolean dtx_downlink := false) := {
len := 0, /* overwritten */
reserved := '000000'B,
@@ -373,17 +499,17 @@ module RSL_Types {
dtx_u := false,
spd_ind := RSL_SPDI_SPEECH,
ch_rate_type := t,
- coding_alg_rate := alg
+ u := { speech := alg }
}
template RSL_IE_ChannelMode tr_RSL_ChanMode(template RSL_ChanRateType t,
- template RSL_SpeechAlgo alg) := {
+ template RSL_ChanModeOct6SpeechAlgo alg) := {
len := ?,
reserved := '000000'B,
dtx_d := ?,
dtx_u := ?,
spd_ind := RSL_SPDI_SPEECH,
ch_rate_type := t,
- coding_alg_rate := alg
+ u := { speech := alg }
}
/* 9.3.4 BS Power IE */
@@ -401,6 +527,15 @@ module RSL_Types {
fpc := fpc,
power_level := power_level
}
+ template RSL_IE_BS_Power
+ tr_RSL_IE_BS_Power(template (present) uint4_t power_level,
+ template (present) boolean epc := ?,
+ template (present) boolean fpc := ?) := {
+ reserved := ?,
+ epc := epc,
+ fpc := fpc,
+ power_level := power_level
+ }
/* 9.3.7 */
type enumerated RSL_AlgId {
@@ -450,6 +585,13 @@ module RSL_Types {
uint8_t actual_ta
}
+ template (value) RSL_IE_L1Info ts_RSL_IE_L1Info := {
+ ms_power_lvl := 0,
+ fpc := false,
+ reserved := 0,
+ actual_ta := 0
+ };
+
/* 9.3.13 */
type record RSL_IE_MS_Power {
uint2_t reserved,
@@ -524,6 +666,34 @@ module RSL_Types {
frame_nr := tr_RSL_IE_FrameNumber(frame_nr)
}
+ /* 9.3.21 Resource Information */
+ type record RSL_IE_ResourceInfo {
+ uint8_t len,
+ RSL_ResourceInfo info
+ } with { variant (len) "LENGTHTO(info)" };
+
+ type record of RSL_ResourceInfoItem RSL_ResourceInfo;
+ type record RSL_ResourceInfoItem {
+ RslChannelNr chan_nr,
+ uint3_t interf_band,
+ BIT5 rfu ('00000'B)
+ };
+
+ template (value) RSL_ResourceInfoItem
+ ts_RSL_ResourceInfoItem(template (value) RslChannelNr chan_nr,
+ template (value) uint3_t interf_band := 0) := {
+ chan_nr := chan_nr,
+ interf_band := interf_band,
+ rfu := '00000'B
+ }
+ template RSL_ResourceInfoItem
+ tr_RSL_ResourceInfoItem(template (present) RslChannelNr chan_nr := ?,
+ template (present) uint3_t interf_band := ?) := {
+ chan_nr := chan_nr,
+ interf_band := interf_band,
+ rfu := ? /* Tolerate unknown values */
+ }
+
/* Osmocom Extension */
type record RSL_IE_UplinkMeasSuppMeasInfo {
int16_t toa256_mean,
@@ -546,6 +716,19 @@ module RSL_Types {
RSL_IE_UplinkMeasSuppMeasInfo supp_meas_info optional
} with { variant (len) "LENGTHTO(rfu,dtx_d,rxlev_f_u,reserved1,rxlev_s_u,reserved2,rxq_f_u,rxq_s_u,supp_meas_info)" };
+ template (value) RSL_IE_UplinkMeas ts_RSL_IE_UplinkMeas(uint6_t rxlev := 12, uint3_t rxqual := 0) := {
+ len := 0, /* overwritten */
+ rfu := '0'B,
+ dtx_d := false,
+ rxlev_f_u := rxlev,
+ reserved1 := '00'B,
+ rxlev_s_u := rxlev,
+ reserved2 := '00'B,
+ rxq_f_u := rxqual,
+ rxq_s_u := rxqual,
+ supp_meas_info := omit
+ };
+
/* 9.3.26 */
type enumerated RSL_Cause {
/* normal event */
@@ -708,6 +891,104 @@ module RSL_Types {
slot_count := slot_count
}
+ /* 9.3.45 Group Call Reference */
+ type record RSL_IE_GroupCallReference {
+ uint8_t len,
+ GroupCallRef group_or_bcast_call_ref
+ } with {
+ variant (len) "LENGTHTO(group_or_bcast_call_ref)"
+ };
+ template (value) RSL_IE_GroupCallReference ts_GroupCallRef(template (value) GroupCallRef gcr) := {
+ len := 0, // overwritten
+ group_or_bcast_call_ref := gcr
+ }
+ template (present) RSL_IE_GroupCallReference tr_GroupCallRef(template (present) GroupCallRef gcr := ?) := {
+ len := ?,
+ group_or_bcast_call_ref := gcr
+ }
+
+ /* 9.3.46 Channel description */
+ type record RSL_IE_GroupChannelDescription {
+ uint8_t len,
+ octetstring chan_desc
+ } with {
+ variant (len) "LENGTHTO(chan_desc)"
+ };
+ template (value) RSL_IE_GroupChannelDescription ts_GroupChanDesc(template (value) octetstring cd) := {
+ len := 0, // overwritten
+ chan_desc := cd
+ }
+ template (present) RSL_IE_GroupChannelDescription tr_GroupChanDesc(template (present) octetstring cd) := {
+ len := ?,
+ chan_desc := cd
+ }
+
+ /* 9.3.47 NCH DRX Information */
+ type record RSL_IE_NchDrxInformation {
+ uint8_t len,
+ BIT2 spare,
+ BIT1 nln_status,
+ BIT3 emlpp_priority,
+ BIT2 nln
+ } with {
+ variant (len) "LENGTHTO(spare,nln_status,emlpp_priority,nln)"
+ };
+
+ /* 9.3.48 Command Indicator */
+ type enumerated RSL_CommandIndicator {
+ CMD_IND_START (0),
+ CMD_IND_STOP (1)
+ } with { variant "FIELDLENGTH(8)" };
+ type record RSL_IE_CommandIndicator {
+ uint8_t len,
+ RSL_CommandIndicator command_value
+ } with {
+ variant (len) "LENGTHTO(command_value)"
+ };
+ template (value) RSL_IE_CommandIndicator ts_CommandInd(template (value) RSL_CommandIndicator ci) := {
+ len := 0, // overwritten
+ command_value := ci
+ }
+ template (present) RSL_IE_CommandIndicator tr_CommandInd(template (present) RSL_CommandIndicator ci) := {
+ len := ?,
+ command_value := ci
+ }
+
+ /* 9.3.50 UIC */
+ type record RSL_IE_Uic {
+ uint8_t len,
+ BIT2 spare,
+ uint6_t uic
+ } with {
+ variant (len) "LENGTHTO(spare,uic)"
+ };
+
+ /* 9.3.52, 3GPP TS 44.018 10.5.2.21aa */
+ type record RSL_IE_MultirateCfg {
+ uint8_t len,
+ uint3_t mr_speech_ver,
+ boolean nscb,
+ boolean icmi,
+ BIT1 spare,
+ uint2_t start_mode,
+ BIT8 codec_modes,
+ octetstring parameters
+ } with {
+ variant (len) "LENGTHTO(mr_speech_ver,nscb,icmi,spare,start_mode,codec_modes,parameters)"
+ };
+ template (value) RSL_IE_MultirateCfg ts_RSL_MultirateCfg(boolean icmi := true, uint2_t start_mode := 0,
+ BIT8 codec_modes := '00000100'B /* 5,90k */,
+ octetstring params := ''O) := {
+ len := 2 + lengthof(params),
+ mr_speech_ver := 1,
+ nscb := false,
+ icmi := icmi,
+ spare := '0'B,
+ start_mode := start_mode,
+ codec_modes := codec_modes,
+ parameters := params
+ }
+
/* 9.3.53 */
type record RSL_IE_MultirateCtrl {
uint3_t spare,
@@ -777,11 +1058,102 @@ module RSL_Types {
RSL_IPA_Codec codec
}
+ type enumerated RSL_IPA_RTP_CSD_FMT_D {
+ RSL_IPA_RTP_CSD_EXT_TRAU ('0000'B),
+ RSL_IPA_RTP_CSD_NON_TRAU ('0001'B),
+ RSL_IPA_RTP_CSD_TRAU_BTS ('0010'B),
+ RSL_IPA_RTP_CSD_IWF_FREE ('0011'B)
+ } with { variant "FIELDLENGTH(4)" }
+
+ type enumerated RSL_IPA_RTP_CSD_FMT_IR {
+ RSL_IPA_RTP_CSD_8k ('0000'B),
+ RSL_IPA_RTP_CSD_16k ('0001'B),
+ RSL_IPA_RTP_CSD_32k ('0010'B),
+ RSL_IPA_RTP_CSD_64 ('0011'B)
+ } with { variant "FIELDLENGTH(4)" }
+
+ type record RSL_IE_IPA_RTP_CSD_FMT {
+ RSL_IPA_RTP_CSD_FMT_IR ir,
+ RSL_IPA_RTP_CSD_FMT_D d
+ }
+
/* 9.3.20 */
type enumerated RSL_IE_ReleaseMode {
RSL_REL_MODE_NORMAL ('00'B),
- REL_REL_MODE_LOCAL ('01'B)
+ RSL_REL_MODE_LOCAL ('01'B)
+ }
+
+ type record RSL_IE_OSMO_TrainingSequence {
+ uint8_t len,
+ uint8_t tsc_set,
+ uint8_t tsc
+ } with { variant (len) "LENGTHTO(tsc_set,tsc)" }
+
+ type record RSL_IE_OSMO_RepAcchCap {
+ uint8_t len,
+ BIT1 rfu ('0'B),
+ uint3_t rxqual,
+ boolean ul_sacch,
+ boolean dl_sacch,
+ boolean dl_facch_all,
+ boolean dl_facch_cmd
+ } with { variant (len) "LENGTHTO(rfu,rxqual,ul_sacch,dl_sacch,dl_facch_all,dl_facch_cmd)" }
+
+ type record RSL_IE_OSMO_TopAcchCap {
+ uint8_t len,
+ boolean sacch_enable,
+ boolean facch_enable,
+ uint3_t rxqual,
+ uint3_t overpower_db
+ } with { variant (len) "LENGTHTO(sacch_enable,facch_enable,rxqual,overpower_db)" }
+
+ template (value) RSL_IE_OSMO_TopAcchCap
+ ts_RSL_IE_OSMO_TopAcchCap(template (value) uint3_t overpower := 2,
+ template (value) uint3_t rxqual := 4,
+ boolean facch_enable := true,
+ boolean sacch_enable := true) := {
+ len := 0, /* overwritten */
+ sacch_enable := sacch_enable,
+ facch_enable := facch_enable,
+ rxqual := rxqual,
+ overpower_db := overpower
+ };
+ template RSL_IE_OSMO_TopAcchCap
+ tr_RSL_IE_OSMO_TopAcchCap(template (present) uint3_t overpower := ?,
+ template (present) uint3_t rxqual := ?,
+ template (present) boolean facch_enable := ?,
+ template (present) boolean sacch_enable := ?) := {
+ len := ?, /* overwritten */
+ sacch_enable := sacch_enable,
+ facch_enable := facch_enable,
+ rxqual := rxqual,
+ overpower_db := overpower
+ };
+
+ type record RSL_IE_OSMO_Osmux_CID {
+ uint8_t len,
+ uint8_t cid
+ } with { variant (len) "LENGTHTO(cid)" }
+
+ template (present) RSL_IE_OSMO_Osmux_CID
+ tr_RSL_IE_OSMO_Osmux_CID(template (present) uint8_t osmux_cid := ?) := {
+ len := ?, /* overwritten */
+ cid := osmux_cid
+ };
+ function f_tr_RSL_IE_OSMO_Osmux_CID(template uint8_t osmux_cid := *)
+ return template RSL_IE_OSMO_Osmux_CID {
+ var template RSL_IE_OSMO_Osmux_CID ie := omit;
+ if (not istemplatekind(osmux_cid, "omit")) {
+ ie := tr_RSL_IE_OSMO_Osmux_CID(osmux_cid);
+ }
+ return ie;
}
+ template (value) RSL_IE_OSMO_Osmux_CID
+ ts_RSL_IE_OSMO_Osmux_CID(template (value) uint8_t osmux_cid) := {
+ len := 0, /* overwritten */
+ cid := osmux_cid
+ };
+
/* union of all IE bodies */
type union RSL_IE_Body {
@@ -791,12 +1163,15 @@ module RSL_Types {
RSL_LV rlm_cause,
RSL_IE_ReleaseMode release_mode,
RSL_IE_ActivationType act_type,
+ RSL_IE_ChannelIdent chan_ident,
RSL_IE_ChannelMode chan_mode,
uint8_t handover_ref,
RSL_IE_BS_Power bs_power,
+ RSL_LV bs_power_params,
RSL_IE_MS_Power ms_power,
RSL_IE_MS_Power_Parameters ms_power_params,
uint8_t timing_adv,
+ RSL_IE_MultirateCfg multirate_cfg,
RSL_IE_MultirateCtrl multirate_ctrl,
uint8_t msg_id,
RSL_IE_FrameNumber frame_nr,
@@ -814,6 +1189,7 @@ module RSL_Types {
RSL_IE_CbCommandType cb_cmd_type,
RSL_LV smscb_message,
RSL_IE_CbchLoadInfo cbch_load_info,
+ RSL_IE_ResourceInfo resource_info,
RSL_SacchInfo sacch_info,
RSL_IE_StartingTime starting_time,
@@ -823,15 +1199,27 @@ module RSL_Types {
RSL_LV full_imm_ass_info,
MobileIdentityLV ms_identity,
+ RSL_IE_GroupCallReference group_call_ref,
+ RSL_IE_GroupChannelDescription group_chan_desc,
+ RSL_IE_NchDrxInformation nch_drx_info,
+ RSL_IE_CommandIndicator cmd_indicator,
+ RSL_IE_Uic uic,
+
uint16_t ipa_conn_id,
uint16_t ipa_local_port,
uint16_t ipa_remote_port,
- uint32_t ipa_local_ip,
- uint32_t ipa_remote_ip,
+ OCT4 ipa_local_ip,
+ OCT4 ipa_remote_ip,
uint8_t ipa_rtp_pt,
uint8_t ipa_rtp_pt2,
RSL_IE_IPA_ConnectionStats ipa_stats,
RSL_IE_IPA_SpeechMode ipa_speech_mode,
+ RSL_IE_IPA_RTP_CSD_FMT ipa_rtp_csd_fmt,
+
+ RSL_IE_OSMO_TrainingSequence osmo_training_sequence,
+ RSL_IE_OSMO_RepAcchCap rep_acch_cap,
+ RSL_IE_OSMO_TopAcchCap top_acch_cap,
+ RSL_IE_OSMO_Osmux_CID osmux_cid,
RSL_LV other
}
@@ -846,12 +1234,15 @@ module RSL_Types {
rlm_cause, iei = RSL_IE_RLM_CAUSE;
release_mode, iei = RSL_IE_RELEASE_MODE;
act_type, iei = RSL_IE_ACT_TYPE;
+ chan_ident, iei = RSL_IE_CHAN_IDENT;
chan_mode, iei = RSL_IE_CHAN_MODE;
handover_ref, iei = RSL_IE_HANDO_REF;
bs_power, iei = RSL_IE_BS_POWER;
+ bs_power_params, iei = RSL_IE_BS_POWER_PARAM;
ms_power, iei = RSL_IE_MS_POWER;
ms_power_params, iei = RSL_IE_MS_POWER_PARAM;
timing_adv, iei = RSL_IE_TIMING_ADVANCE;
+ multirate_cfg, iei = RSL_IE_MR_CONFIG;
multirate_ctrl, iei = RSL_IE_MR_CONTROL;
msg_id, iei = RSL_IE_MSG_ID;
@@ -870,6 +1261,7 @@ module RSL_Types {
cb_cmd_type, iei = RSL_IE_CB_CMD_TYPE;
smscb_message, iei = RSL_IE_SMSCB_MSG;
cbch_load_info, iei = RSL_IE_CBCH_LOAD_INFO;
+ resource_info, iei = RSL_IE_RESOURCE_INFO;
sacch_info, iei = RSL_IE_SACCH_INFO;
starting_time, iei = RSL_IE_STARTNG_TIME;
encr_info, iei = RSL_IE_ENCR_INFO;
@@ -880,6 +1272,12 @@ module RSL_Types {
ms_identity, iei = RSL_IE_MS_IDENTITY;
other, iei = RSL_IE_FULL_BCCH_INFO;
+ group_call_ref, iei = RSL_IE_GROUP_CALL_REF;
+ group_chan_desc, iei = RSL_IE_GROUP_CHAN_DESC;
+ nch_drx_info, iei = RSL_IE_NCH_DRX_INFO;
+ cmd_indicator, iei = RSL_IE_CMD_INDICATOR;
+ uic, iei = RSL_IE_UIC;
+
ipa_conn_id, iei = RSL_IE_IPAC_CONN_ID;
ipa_remote_ip, iei = RSL_IE_IPAC_REMOTE_IP;
ipa_remote_port, iei = RSL_IE_IPAC_REMOTE_PORT;
@@ -889,6 +1287,12 @@ module RSL_Types {
ipa_rtp_pt2, iei = RSL_IE_IPAC_RTP_PAYLOAD2;
ipa_stats, iei = RSL_IE_IPAC_CONN_STAT;
ipa_speech_mode, iei = RSL_IE_IPAC_SPEECH_MODE;
+ ipa_rtp_csd_fmt, iei = RSL_IE_IPAC_RTP_CSD_FMT;
+
+ osmo_training_sequence, iei = RSL_IE_OSMO_TRAINING_SEQUENCE;
+ rep_acch_cap, iei = RSL_IE_OSMO_REP_ACCH_CAP;
+ top_acch_cap, iei = RSL_IE_OSMO_TOP_ACCH_CAP;
+ osmux_cid, iei = RSL_IE_OSMO_OSMUX_CID;
other, OTHERWISE;
)" };
@@ -956,7 +1360,7 @@ template RSL_Message tr_RSL_MsgTypeD(template RSL_MessageType msg_type) modifies
msg_disc := { RSL_MDISC_DCHAN, ? }
}
-/* Dedicated Channel Management */
+/* TRX Management */
template RSL_Message tr_RSL_MsgTypeT(template RSL_MessageType msg_type) modifies tr_RSL_MsgType := {
msg_disc := { RSL_MDISC_TRX_MGMT, ? }
}
@@ -1233,13 +1637,23 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
*
}
}
- template RSL_Message tr_RSL_CHAN_ACT_PDCH(template RslChannelNr chan_nr,
- template RSL_IE_ChannelMode mode) := {
+
+ template (value) RSL_Message
+ ts_RSL_CHAN_ACT_PDCH(template (value) RslChannelNr chan_nr) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_CHAN_ACTIV,
+ ies :={
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ t_RSL_IE(RSL_IE_ACT_TYPE, RSL_IE_Body:{act_type := c_RSL_IE_ActType_PDCH})
+ }
+ }
+ template RSL_Message
+ tr_RSL_CHAN_ACT_PDCH(template (present) RslChannelNr chan_nr) := {
msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
msg_type := RSL_MT_CHAN_ACTIV,
ies :={
tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
- tr_RSL_IE(RSL_IE_Body:{act_type := t_RSL_IE_ActType_PDCH}),
+ tr_RSL_IE(RSL_IE_Body:{act_type := c_RSL_IE_ActType_PDCH}),
/* lots of optional IEs */
*
}
@@ -1365,12 +1779,27 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
- /* Receive template for a measurement report that lacks the measurement report
+ /* Templates for a measurement report that lacks the measurement report
* from the MS (l1_info, l3_info and ms timing offset */
- template RSL_Message tr_RSL_MEAS_RES_EMPTY(template RslChannelNr chan_nr,
- template uint8_t meas_res_nr := ?,
- template RSL_IE_UplinkMeas ul_meas := ?,
- template RSL_IE_BS_Power bs_power := ?) := {
+ template (value) RSL_Message
+ ts_RSL_MEAS_RES_EMPTY(template (value) RslChannelNr chan_nr,
+ template (value) uint8_t meas_res_nr,
+ template (value) RSL_IE_UplinkMeas ul_meas,
+ template (value) RSL_IE_BS_Power bs_power) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_MEAS_RES,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ t_RSL_IE(RSL_IE_MEAS_RES_NR, RSL_IE_Body:{meas_res_nr := meas_res_nr}),
+ t_RSL_IE(RSL_IE_UPLINK_MEAS, RSL_IE_Body:{uplink_meas := ul_meas}),
+ t_RSL_IE(RSL_IE_BS_POWER, RSL_IE_Body:{bs_power := bs_power})
+ }
+ }
+ template RSL_Message
+ tr_RSL_MEAS_RES_EMPTY(template (present) RslChannelNr chan_nr,
+ template uint8_t meas_res_nr := ?,
+ template RSL_IE_UplinkMeas ul_meas := ?,
+ template RSL_IE_BS_Power bs_power := ?) := {
msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
msg_type := RSL_MT_MEAS_RES,
ies := {
@@ -1402,6 +1831,26 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
+ template (value) RSL_Message ts_RSL_MEAS_RES(template (value) RslChannelNr chan_nr,
+ uint8_t meas_res_nr,
+ template (value) RSL_IE_UplinkMeas ul_meas,
+ template (value) RSL_IE_BS_Power bs_power,
+ template (value) RSL_IE_L1Info l1_info,
+ octetstring l3_info,
+ uint8_t ms_to) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_MEAS_RES,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ t_RSL_IE(RSL_IE_MEAS_RES_NR, RSL_IE_Body:{meas_res_nr := meas_res_nr}),
+ t_RSL_IE(RSL_IE_UPLINK_MEAS, RSL_IE_Body:{uplink_meas := ul_meas}),
+ t_RSL_IE(RSL_IE_BS_POWER, RSL_IE_Body:{bs_power := bs_power}),
+ t_RSL_IE(RSL_IE_L1_INFO, RSL_IE_Body:{l1_info := l1_info}),
+ t_RSL_IE(RSL_IE_L3_INFO, RSL_IE_Body:{l3_info := ts_RSL_L16V(l3_info)}),
+ t_RSL_IE(RSL_IE_MS_TIMING_OFFSET, RSL_IE_Body:{ms_timing_offset := ms_to})
+ }
+ }
+
/* 8.4.9 BSC -> BTS */
template (value) RSL_Message ts_RSL_MODE_MODIFY_REQ(template (value) RslChannelNr chan_nr,
template (value) RSL_IE_ChannelMode mode) := {
@@ -1424,7 +1873,25 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
*
}
}
-
+
+ template RSL_Message tr_RSL_MODE_MODIFY_REQ_with_OSMO_TSC(template RslChannelNr chan_nr,
+ template RSL_IE_ChannelMode mode,
+ template uint8_t tsc_set := ?,
+ template uint8_t tsc := ?) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_MODE_MODIFY_REQ,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ tr_RSL_IE(RSL_IE_Body:{chan_mode := mode}),
+ tr_RSL_IE(RSL_IE_Body:{osmo_training_sequence := {
+ len := ?,
+ tsc_set := tsc_set,
+ tsc := tsc
+ }
+ })
+ }
+ };
+
/* 8.4.10 BTS -> BSC */
template (value) RSL_Message ts_RSL_MODE_MODIFY_ACK(template (value) RslChannelNr chan_nr) := {
msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
@@ -1513,6 +1980,16 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
/* One optional IE: BS POWER PARAMETERS */
}
}
+ template RSL_Message tr_RSL_BS_PWR_CTRL(template (present) RslChannelNr chan_nr,
+ template (present) RSL_IE_BS_Power bs_power) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_BS_POWER_CONTROL,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ tr_RSL_IE(RSL_IE_Body:{bs_power := bs_power})
+ /* One optional IE: BS POWER PARAMETERS */
+ }
+ }
/* 8.4.19 BTS -> BSC */
template (value) RSL_Message ts_RSL_RF_CHAN_REL_ACK(template (value) RslChannelNr chan_nr) :=
@@ -1559,6 +2036,42 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
+ /* 8.4.21 BTS -> BSC */
+ template (value) RSL_Message ts_RSL_TALKER_DET(template (value) RslChannelNr chan_nr) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_TALKER_DET,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr})
+ }
+ }
+ template RSL_Message tr_RSL_TALKER_DET(template RslChannelNr chan_nr,
+ template uint8_t acc_delay := ?) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_TALKER_DET,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ tr_RSL_IE(RSL_IE_Body:{access_delay := acc_delay})
+ }
+ }
+
+ /* 8.4.22 BTS -> BSC */
+ template (value) RSL_Message ts_RSL_LISTENER_DET(template (value) RslChannelNr chan_nr) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_LISTENER_DET,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr})
+ }
+ }
+ template RSL_Message tr_RSL_LISTENER_DET(template RslChannelNr chan_nr,
+ template uint8_t acc_delay := ?) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+ msg_type := RSL_MT_LISTENER_DET,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ tr_RSL_IE(RSL_IE_Body:{access_delay := acc_delay})
+ }
+ }
+
/* COMMON CHANNEL MANAGEMENT MESSAGES */
@@ -1717,12 +2230,6 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
- template RSL_Message tr_RSL_RF_RES_IND := {
- msg_disc := tr_RSL_MsgDisc(RSL_MDISC_TRX_MGMT, false),
- msg_type := RSL_MT_RF_RES_IND,
- ies := *
- }
-
/* 8.5.8 BTS <- BSC SMS BROADCAST COMMAND */
template RSL_Message tr_RSL_SMSCB_CMD(template RSL_IE_CbCommandType cb_cmd := ?,
template octetstring msg := ?,
@@ -1795,6 +2302,35 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
+ /* 8.6.1 BTS -> BSC */
+ template (value) RSL_Message
+ ts_RSL_RF_RES_IND(template (value) RSL_ResourceInfo info) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_TRX_MGMT, false),
+ msg_type := RSL_MT_RF_RES_IND,
+ ies := {
+ t_RSL_IE(RSL_IE_RESOURCE_INFO, RSL_IE_Body:{
+ resource_info := {
+ len := 0, /* overwritten */
+ info := info
+ }
+ })
+ }
+ }
+ template RSL_Message
+ tr_RSL_RF_RES_IND(template (present) RSL_ResourceInfo info := ?) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_TRX_MGMT, false),
+ msg_type := RSL_MT_RF_RES_IND,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{
+ resource_info := {
+ len := ?,
+ info := info
+ }
+ })
+ }
+ }
+
+
/* 8.6.2 BTS <- BSC */
template (value) RSL_Message ts_RSL_SACCH_FILL(RSL_IE_SysinfoType si_type, octetstring l3_info) := {
msg_disc := ts_RSL_MsgDisc(RSL_MDISC_TRX_MGMT, false),
@@ -1844,6 +2380,49 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
/* Abis/IP specific messages */
+ private function f_ts_RSL_IPA_CRCX_IEs(template (value) RslChannelNr chan_nr,
+ template (omit) OCT4 remote_ip,
+ template (omit) uint16_t remote_port,
+ template (omit) uint8_t osmux_cid)
+ return RSL_IE_List {
+ var RSL_IE_List ies;
+
+ /* Channel Number is a mandatory IE */
+ ies := {
+ valueof(RSL_IE:{
+ iei := RSL_IE_CHAN_NR,
+ body := { chan_nr := chan_nr }
+ })
+ };
+ /* Remote IP / Port are optional IEs */
+ if (not istemplatekind(remote_ip, "omit")) {
+ ies := ies & {
+ valueof(RSL_IE:{
+ iei := RSL_IE_IPAC_REMOTE_IP,
+ body := { ipa_remote_ip := remote_ip }
+ })
+ };
+ }
+ if (not istemplatekind(remote_port, "omit")) {
+ ies := ies & {
+ valueof(RSL_IE:{
+ iei := RSL_IE_IPAC_REMOTE_PORT,
+ body := { ipa_remote_port := remote_port }
+ })
+ };
+ }
+ /* Osmux CID extension IE is optional: */
+ if (not istemplatekind(osmux_cid, "omit")) {
+ ies := ies & {
+ valueof(RSL_IE:{
+ iei := RSL_IE_OSMO_OSMUX_CID,
+ body := { osmux_cid := ts_RSL_IE_OSMO_Osmux_CID(osmux_cid) }
+ })
+ };
+ }
+
+ return ies;
+ }
template RSL_Message tr_RSL_IPA_CRCX(template RslChannelNr chan_nr) := {
msg_disc := tr_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
msg_type := RSL_MT_IPAC_CRCX,
@@ -1852,41 +2431,59 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
*
}
}
- template (value) RSL_Message ts_RSL_IPA_CRCX(template (value) RslChannelNr chan_nr) := {
+ template (value) RSL_Message
+ ts_RSL_IPA_CRCX(template (value) RslChannelNr chan_nr,
+ template (omit) OCT4 remote_ip := omit,
+ template (omit) uint16_t remote_port := omit,
+ template (omit) uint8_t osmux_cid := omit) := {
msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
msg_type := RSL_MT_IPAC_CRCX,
- ies := {
- t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr})
+ ies := f_ts_RSL_IPA_CRCX_IEs(chan_nr, remote_ip, remote_port, osmux_cid)
+ }
+
+ function ts_RSL_IPA_CRCX_ACK(template (value) RslChannelNr chan_nr,
+ uint16_t ipa_conn_id, OCT4 local_ip,
+ uint16_t local_port, uint7_t rtp_pt2,
+ template (omit) uint8_t osmux_cid := omit)
+ return template (value) RSL_Message {
+ var template (value) RSL_Message msg := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
+ msg_type := RSL_MT_IPAC_CRCX_ACK,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
+ t_RSL_IE(RSL_IE_IPAC_LOCAL_IP, RSL_IE_Body:{ipa_local_ip := local_ip}),
+ t_RSL_IE(RSL_IE_IPAC_LOCAL_PORT, RSL_IE_Body:{ipa_local_port := local_port}),
+ t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ }
}
- }
-
-
- template (value) RSL_Message ts_RSL_IPA_CRCX_ACK(template (value) RslChannelNr chan_nr,
- uint16_t ipa_conn_id, uint32_t local_ip,
- uint16_t local_port, uint7_t rtp_pt2) := {
- msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
- msg_type := RSL_MT_IPAC_CRCX_ACK,
- ies := {
- t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
- t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
- t_RSL_IE(RSL_IE_IPAC_LOCAL_IP, RSL_IE_Body:{ipa_local_ip := local_ip}),
- t_RSL_IE(RSL_IE_IPAC_LOCAL_PORT, RSL_IE_Body:{ipa_local_port := local_port}),
- t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ if (not istemplatekind(osmux_cid, "omit")) {
+ msg.ies[lengthof(msg.ies)] := t_RSL_IE(RSL_IE_OSMO_OSMUX_CID, RSL_IE_Body:{osmux_cid := ts_RSL_IE_OSMO_Osmux_CID(osmux_cid)});
+ }
+ return msg;
+ }
+
+ function tr_RSL_IPA_CRCX_ACK(template RslChannelNr chan_nr,
+ template uint16_t ipa_conn_id,
+ template OCT4 local_ip,
+ template uint16_t local_port,
+ template uint8_t osmux_cid := omit)
+ return template RSL_Message {
+ var template RSL_Message msg := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
+ msg_type := RSL_MT_IPAC_CRCX_ACK,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ tr_RSL_IE(RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
+ tr_RSL_IE(RSL_IE_Body:{ipa_local_ip := local_ip}),
+ tr_RSL_IE(RSL_IE_Body:{ipa_local_port := local_port})
+ /* Optional: RTP Payload Type 2 IE */
+ }
}
- }
- template RSL_Message tr_RSL_IPA_CRCX_ACK(template RslChannelNr chan_nr,
- template uint16_t ipa_conn_id,
- template uint32_t local_ip,
- template uint16_t local_port) := {
- msg_disc := tr_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
- msg_type := RSL_MT_IPAC_CRCX_ACK,
- ies := {
- tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
- tr_RSL_IE(RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
- tr_RSL_IE(RSL_IE_Body:{ipa_local_ip := local_ip}),
- tr_RSL_IE(RSL_IE_Body:{ipa_local_port := local_port})
- /* Optional: RTP Payload Type 2 IE */
+ if (not istemplatekind(osmux_cid, "omit")) {
+ msg.ies[lengthof(msg.ies)] := tr_RSL_IE(RSL_IE_Body:{osmux_cid := f_tr_RSL_IE_OSMO_Osmux_CID(osmux_cid)});
}
+ return msg;
}
template (value) RSL_Message ts_RSL_IPA_CRCX_NACK(template (value) RslChannelNr chan_nr,
@@ -1908,20 +2505,28 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
- template (value) RSL_Message ts_RSL_IPA_MDCX(template (value) RslChannelNr chan_nr,
- uint16_t ipa_conn_id,
- uint32_t remote_ip, uint16_t remote_port,
- uint7_t rtp_pt2) := {
- msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
- msg_type := RSL_MT_IPAC_MDCX,
- ies := {
- t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
- t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
- t_RSL_IE(RSL_IE_IPAC_REMOTE_IP, RSL_IE_Body:{ipa_remote_ip := remote_ip}),
- t_RSL_IE(RSL_IE_IPAC_REMOTE_PORT, RSL_IE_Body:{ipa_remote_port := remote_port}),
- /* optional: RTP Payload Type */
- t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ function ts_RSL_IPA_MDCX(template (value) RslChannelNr chan_nr,
+ uint16_t ipa_conn_id,
+ OCT4 remote_ip, uint16_t remote_port,
+ uint7_t rtp_pt2,
+ template (omit) uint8_t osmux_cid := omit)
+ return template (value) RSL_Message {
+ var template (value) RSL_Message msg := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
+ msg_type := RSL_MT_IPAC_MDCX,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
+ t_RSL_IE(RSL_IE_IPAC_REMOTE_IP, RSL_IE_Body:{ipa_remote_ip := remote_ip}),
+ t_RSL_IE(RSL_IE_IPAC_REMOTE_PORT, RSL_IE_Body:{ipa_remote_port := remote_port}),
+ /* optional: RTP Payload Type */
+ t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ }
}
+ if (not istemplatekind(osmux_cid, "omit")) {
+ msg.ies[lengthof(msg.ies)] := t_RSL_IE(RSL_IE_OSMO_OSMUX_CID, RSL_IE_Body:{osmux_cid := ts_RSL_IE_OSMO_Osmux_CID(osmux_cid)});
+ }
+ return msg;
}
template RSL_Message tr_RSL_IPA_MDCX(template RslChannelNr chan_nr,
template uint16_t ipa_conn_id) := {
@@ -1934,38 +2539,54 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
- template (value) RSL_Message ts_RSL_IPA_MDCX_ACK(template (value) RslChannelNr chan_nr,
- uint16_t ipa_conn_id,
- uint32_t local_ip, uint16_t local_port,
- uint7_t rtp_pt2) := {
- msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
- msg_type := RSL_MT_IPAC_MDCX_ACK,
- ies := {
- t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
- /* optional */
- t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
- t_RSL_IE(RSL_IE_IPAC_LOCAL_IP, RSL_IE_Body:{ipa_local_ip := local_ip}),
- t_RSL_IE(RSL_IE_IPAC_LOCAL_PORT, RSL_IE_Body:{ipa_local_port := local_port}),
- /* optional: RTP Payload Type */
- t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ function ts_RSL_IPA_MDCX_ACK(template (value) RslChannelNr chan_nr,
+ uint16_t ipa_conn_id,
+ OCT4 local_ip, uint16_t local_port,
+ uint7_t rtp_pt2,
+ template (omit) uint8_t osmux_cid := omit)
+ return template (value) RSL_Message {
+ var template (value) RSL_Message msg := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
+ msg_type := RSL_MT_IPAC_MDCX_ACK,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr}),
+ /* optional */
+ t_RSL_IE(RSL_IE_IPAC_CONN_ID, RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
+ t_RSL_IE(RSL_IE_IPAC_LOCAL_IP, RSL_IE_Body:{ipa_local_ip := local_ip}),
+ t_RSL_IE(RSL_IE_IPAC_LOCAL_PORT, RSL_IE_Body:{ipa_local_port := local_port}),
+ /* optional: RTP Payload Type */
+ t_RSL_IE(RSL_IE_IPAC_RTP_PAYLOAD2, RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ }
}
- }
- template RSL_Message tr_RSL_IPA_MDCX_ACK(template RslChannelNr chan_nr,
- template uint16_t ipa_conn_id,
- template uint32_t local_ip,
- template uint16_t local_port,
- template uint7_t rtp_pt2) := {
- msg_disc := tr_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
- msg_type := RSL_MT_IPAC_MDCX_ACK,
- ies := {
- tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
- /* optional */
- tr_RSL_IE(RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
- tr_RSL_IE(RSL_IE_Body:{ipa_local_ip := local_ip}),
- tr_RSL_IE(RSL_IE_Body:{ipa_local_port := local_port}),
- /* optional: RTP Payload Type */
- tr_RSL_IE(RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ if (not istemplatekind(osmux_cid, "omit")) {
+ msg.ies[lengthof(msg.ies)] := t_RSL_IE(RSL_IE_OSMO_OSMUX_CID, RSL_IE_Body:{osmux_cid := ts_RSL_IE_OSMO_Osmux_CID(osmux_cid)});
+ }
+ return msg;
+ }
+ function tr_RSL_IPA_MDCX_ACK(template RslChannelNr chan_nr,
+ template uint16_t ipa_conn_id,
+ template OCT4 local_ip,
+ template uint16_t local_port,
+ template uint7_t rtp_pt2,
+ template uint8_t osmux_cid := omit)
+ return template RSL_Message {
+ var template RSL_Message msg := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_IPACCESS, false),
+ msg_type := RSL_MT_IPAC_MDCX_ACK,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+ /* optional */
+ tr_RSL_IE(RSL_IE_Body:{ipa_conn_id := ipa_conn_id}),
+ tr_RSL_IE(RSL_IE_Body:{ipa_local_ip := local_ip}),
+ tr_RSL_IE(RSL_IE_Body:{ipa_local_port := local_port}),
+ /* optional: RTP Payload Type */
+ tr_RSL_IE(RSL_IE_Body:{ipa_rtp_pt2 := rtp_pt2})
+ }
}
+ if (not istemplatekind(osmux_cid, "omit")) {
+ msg.ies[lengthof(msg.ies)] := tr_RSL_IE(RSL_IE_Body:{osmux_cid := f_tr_RSL_IE_OSMO_Osmux_CID(osmux_cid)});
+ }
+ return msg;
}
template (value) RSL_Message ts_RSL_IPA_MDCX_NACK(template (value) RslChannelNr chan_nr,
@@ -2077,14 +2698,16 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
- template (value) RSL_Message ts_RSL_IPA_PDCH_ACT(RslChannelNr chan_nr) := {
+ template (value) RSL_Message
+ ts_RSL_IPA_PDCH_ACT(template (value) RslChannelNr chan_nr) := {
msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
msg_type := RSL_MT_IPAC_PDCH_ACT,
ies := {
t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := chan_nr})
}
}
- template RSL_Message tr_RSL_IPA_PDCH_ACT(template RslChannelNr chan_nr) := {
+ template RSL_Message
+ tr_RSL_IPA_PDCH_ACT(template (present) RslChannelNr chan_nr) := {
msg_disc := ts_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
msg_type := RSL_MT_IPAC_PDCH_ACT,
ies := {
@@ -2197,6 +2820,50 @@ template RSL_Message tr_RSL_MsgTypeDR(template RSL_MessageType msg_type) modifie
}
}
+ template (value) RSL_Message ts_RSL_NOTIF_CMD_START(template (value) GroupCallRef group_call_ref,
+ template (value) octetstring chan_desc) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_CCHAN, false),
+ msg_type := RSL_MT_NOT_CMD,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := ts_RslChanNr_PCH_AGCH(0)}),
+ t_RSL_IE(RSL_IE_CMD_INDICATOR, RSL_IE_Body:{cmd_indicator := ts_CommandInd(CMD_IND_START)}),
+ t_RSL_IE(RSL_IE_GROUP_CALL_REF, RSL_IE_Body:{group_call_ref := ts_GroupCallRef(group_call_ref)}),
+ t_RSL_IE(RSL_IE_GROUP_CHAN_DESC, RSL_IE_Body:{group_chan_desc := ts_GroupChanDesc(chan_desc)})
+ }
+ }
+ template RSL_Message tr_RSL_NOTIF_CMD_START(template (present) GroupCallRef group_call_ref,
+ template (present) octetstring chan_desc := ?) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false),
+ msg_type := RSL_MT_NOT_CMD,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := t_RslChanNr_PCH_AGCH(0)}),
+ tr_RSL_IE(RSL_IE_Body:{cmd_indicator := tr_CommandInd(CMD_IND_START)}),
+ tr_RSL_IE(RSL_IE_Body:{group_call_ref := tr_GroupCallRef(group_call_ref)}),
+ tr_RSL_IE(RSL_IE_Body:{group_chan_desc := tr_GroupChanDesc(chan_desc)}),
+ *
+ }
+ }
+
+ template (value) RSL_Message ts_RSL_NOTIF_CMD_STOP(template (value) GroupCallRef group_call_ref) := {
+ msg_disc := ts_RSL_MsgDisc(RSL_MDISC_CCHAN, false),
+ msg_type := RSL_MT_NOT_CMD,
+ ies := {
+ t_RSL_IE(RSL_IE_CHAN_NR, RSL_IE_Body:{chan_nr := ts_RslChanNr_PCH_AGCH(0)}),
+ t_RSL_IE(RSL_IE_CMD_INDICATOR, RSL_IE_Body:{cmd_indicator := ts_CommandInd(CMD_IND_STOP)}),
+ t_RSL_IE(RSL_IE_GROUP_CALL_REF, RSL_IE_Body:{group_call_ref := ts_GroupCallRef(group_call_ref)})
+ }
+ }
+ template RSL_Message tr_RSL_NOTIF_CMD_STOP(template (present) GroupCallRef group_call_ref) := {
+ msg_disc := tr_RSL_MsgDisc(RSL_MDISC_CCHAN, false),
+ msg_type := RSL_MT_NOT_CMD,
+ ies := {
+ tr_RSL_IE(RSL_IE_Body:{chan_nr := t_RslChanNr_PCH_AGCH(0)}),
+ tr_RSL_IE(RSL_IE_Body:{cmd_indicator := tr_CommandInd(CMD_IND_STOP)}),
+ tr_RSL_IE(RSL_IE_Body:{group_call_ref := tr_GroupCallRef(group_call_ref)}),
+ *
+ }
+ }
+
function f_rsl_find_ie(RSL_Message msg, RSL_IE_Type iei, out RSL_IE_Body ret) return boolean {
diff --git a/library/RTP_Emulation.ttcn b/library/RTP_Emulation.ttcn
index 70604dc2..90952148 100644
--- a/library/RTP_Emulation.ttcn
+++ b/library/RTP_Emulation.ttcn
@@ -4,7 +4,7 @@ module RTP_Emulation {
* * act as a RTP source that generates a RTP Stream
* * act asaa RTP sink that consumes a RTP Stream
*
- * for all of the above, we want to be able to
+ * for all of the above, we want to be able to
* * specify the payload type
* * specify the interval / sample rate
* * create drop-outs in the stream
@@ -81,6 +81,8 @@ type component RTP_Emulation_CT {
/* user-facing port for controlling the binding */
port RTPEM_CTRL_PT CTRL;
+ /* user-facing port for sniffing RTP frames */
+ port RTPEM_DATA_PT DATA;
/* configurable by user, should be fixed */
var RtpemConfig g_cfg := c_RtpemDefaultCfg;
@@ -95,6 +97,7 @@ type component RTP_Emulation_CT {
var PortNumber g_local_port;
/* state variables, change over time */
+ var boolean g_loopback := false;
var boolean g_rx_enabled := false;
var boolean g_tx_connected := false; /* Set to true after connect() */
var LIN2_BO_LAST g_tx_next_seq := 0;
@@ -114,7 +117,8 @@ type enumerated RtpemMode {
RTPEM_MODE_NONE,
RTPEM_MODE_TXONLY,
RTPEM_MODE_RXONLY,
- RTPEM_MODE_BIDIR
+ RTPEM_MODE_BIDIR,
+ RTPEM_MODE_LOOPBACK
};
type record RtpemStats {
@@ -151,26 +155,29 @@ const RtpemStats c_RtpemStatsReset := {
num_pkts_rx_err_payload := 0
}
+type record RtpemConfigPayload {
+ INT7b payload_type,
+ octetstring fixed_payload optional
+};
+
type record RtpemConfig {
- INT7b tx_payload_type,
integer tx_samplerate_hz,
integer tx_duration_ms,
BIT32_BO_LAST tx_ssrc,
- octetstring tx_fixed_payload optional,
- octetstring rx_fixed_payload optional,
+ record of RtpemConfigPayload tx_payloads,
+ record of RtpemConfigPayload rx_payloads,
boolean iuup_mode,
- boolean iuup_tx_init
+ IuUP_Config iuup_cfg
};
const RtpemConfig c_RtpemDefaultCfg := {
- tx_payload_type := 0,
tx_samplerate_hz := 8000,
tx_duration_ms := 20,
tx_ssrc := '11011110101011011011111011101111'B,
- tx_fixed_payload := '01020304'O,
- rx_fixed_payload := '01020304'O,
+ tx_payloads := {{0, '01020304'O}},
+ rx_payloads := {{0, '01020304'O}},
iuup_mode := false,
- iuup_tx_init := true
+ iuup_cfg := c_IuUP_Config_def
}
signature RTPEM_bind(in HostName local_host, inout PortNumber local_port);
@@ -186,6 +193,10 @@ type port RTPEM_CTRL_PT procedure {
RTPEM_conn_refuse_received;
} with { extension "internal" };
+type port RTPEM_DATA_PT message {
+ inout PDU_RTP, PDU_RTCP;
+} with { extension "internal" };
+
function f_rtpem_bind(RTPEM_CTRL_PT pt, in HostName local_host, inout PortNumber local_port) {
pt.call(RTPEM_bind:{local_host, local_port}) {
[] pt.getreply(RTPEM_bind:{local_host, ?}) -> param (local_port) {};
@@ -269,38 +280,49 @@ function f_rtpem_stats_compare(RtpemStats a, RtpemStats b, integer tolerance :=
* check that will fit most situations and is intended to be executed by
* the testcases as as needed. */
function f_rtpem_stats_err_check(RtpemStats s) {
+ var boolean do_stop := false;
log("stats: ", s);
/* Check if there was some activity at either on the RX or on the
* TX side, but complete silence would indicate some problem */
if (s.num_pkts_tx < 1 and s.num_pkts_rx < 1) {
setverdict(fail, "no RTP packet activity detected (packets)");
- mtc.stop;
+ do_stop := true;
}
if (s.bytes_payload_tx < 1 and s.bytes_payload_rx < 1) {
setverdict(fail, "no RTP packet activity detected (bytes)");
- mtc.stop;
+ do_stop := true;
}
/* Check error counters */
if (s.num_pkts_rx_err_seq != 0) {
- setverdict(fail, "RTP packet sequence number errors occurred");
- mtc.stop;
+ setverdict(fail, log2str(s.num_pkts_rx_err_seq, " RTP packet sequence number errors occurred"));
+ do_stop := true;
}
if (s.num_pkts_rx_err_ts != 0) {
- setverdict(fail, "RTP packet timestamp errors occurred");
- mtc.stop;
+ setverdict(fail, log2str(s.num_pkts_rx_err_ts, " RTP packet timestamp errors occurred"));
+ do_stop := true;
}
if (s.num_pkts_rx_err_pt != 0) {
- setverdict(fail, "RTP packet payload type errors occurred");
- mtc.stop;
+ setverdict(fail, log2str(s.num_pkts_rx_err_pt, " RTP packet payload type errors occurred"));
+ do_stop := true;
}
if (s.num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "RTP packets received while RX was disabled");
- mtc.stop;
+ setverdict(fail, log2str(s.num_pkts_rx_err_disabled, " RTP packets received while RX was disabled"));
+ do_stop := true;
}
if (s.num_pkts_rx_err_payload != 0) {
- setverdict(fail, "RTP packets with mismatching payload received");
+ setverdict(fail, log2str(s.num_pkts_rx_err_payload, " RTP packets with mismatching payload received"));
+ do_stop := true;
+ }
+
+ if (do_stop) {
+ if (self == mtc) {
+ /* Properly stop all ports before disconnecting them. This avoids
+ * running into the dynamic testcase error due to messages arriving on
+ * unconnected ports. */
+ all component.stop;
+ }
mtc.stop;
}
}
@@ -336,11 +358,15 @@ template PDU_RTP ts_RTP(BIT32_BO_LAST ssrc, INT7b pt, LIN2_BO_LAST seq, uint32_t
data := payload
}
-private function f_tx_rtp(octetstring payload, BIT1 marker := '0'B) runs on RTP_Emulation_CT {
+private function f_tx_rtp(octetstring payload, INT7b rtp_payload_type, BIT1 marker := '0'B) runs on RTP_Emulation_CT {
if (g_cfg.iuup_mode) {
payload := f_IuUP_Em_tx_encap(g_iuup_ent, payload);
+ if (lengthof(payload) == 0) {
+ /* Nothing to transmit, waiting for INIT-ACK */
+ return;
+ }
}
- var PDU_RTP rtp := valueof(ts_RTP(g_cfg.tx_ssrc, g_cfg.tx_payload_type, g_tx_next_seq,
+ var PDU_RTP rtp := valueof(ts_RTP(g_cfg.tx_ssrc, rtp_payload_type, g_tx_next_seq,
g_tx_next_ts, payload, marker));
RTP.send(t_RTP_Send(g_rtp_conn_id, RTP_messages_union:{rtp:=rtp}));
/* increment sequence + timestamp for next transmit */
@@ -348,6 +374,58 @@ private function f_tx_rtp(octetstring payload, BIT1 marker := '0'B) runs on RTP_
g_tx_next_ts := g_tx_next_ts + (g_cfg.tx_samplerate_hz / (1000 / g_cfg.tx_duration_ms));
}
+private function f_check_fixed_rx_payloads(INT7b rtp_payload_type, octetstring rtp_data) runs on RTP_Emulation_CT {
+ var boolean payload_type_match := false;
+
+ /* The API user has the option to define zero or multiple sets of rx_payloads. Each rx_payload set contains
+ the payload type number of the expected payload and an optional fixed_payload, which resembles the actual
+ payload.
+
+ In case zero rx_payloads are defined nothing is verified and no errors are counted. This is a corner case
+ and should be avoided since it would not yield any good test coverage.
+
+ During verification the payload type has the highest priority. It must match before the optional fixed
+ payload is checked. Since the fixed_payload is optional multiple error situations may apply:
+
+ | payload_type | fixed_payload | result
+ | match | match | full match => no error counter is incremented
+ | match | not present | counts as full match => no error counter is incremented
+ | match | mismatch | payload type match => only num_pkts_rx_err_payload is incremented
+ | | | unless something of the above is detected later.
+ | mismatch | (not checked) | no match => num_pkts_rx_err_payload and num_pkts_rx_err_pt
+ | | | are increment unless something of the above is
+ | | | detected later.
+ */
+
+ /* In case no rx payloads are defined any payload is accepted and no errors are counted. */
+ if (lengthof(g_cfg.rx_payloads) == 0) {
+ return;
+ }
+
+ /* Evaluate rtp_data and rtp_payload_type */
+ for (var integer i := 0; i < lengthof(g_cfg.rx_payloads); i := i + 1) {
+ if (rtp_payload_type == g_cfg.rx_payloads[i].payload_type) {
+ if (not ispresent(g_cfg.rx_payloads[i].fixed_payload)) {
+ /* full match */
+ return;
+ }
+ if (g_cfg.rx_payloads[i].fixed_payload == rtp_data) {
+ /* counts as full match */
+ return;
+ }
+
+ /* At least the payload type number did match
+ * (but we still may see a full match later) */
+ payload_type_match := true;
+ }
+ }
+
+ g_stats_rtp.num_pkts_rx_err_payload := g_stats_rtp.num_pkts_rx_err_payload + 1;
+ if (not payload_type_match) {
+ g_stats_rtp.num_pkts_rx_err_pt := g_stats_rtp.num_pkts_rx_err_pt + 1;
+ }
+}
+
function f_main() runs on RTP_Emulation_CT
{
var Result res;
@@ -374,7 +452,7 @@ function f_main() runs on RTP_Emulation_CT
os_error_code := 111,
os_error_text := ? /* "Connection refused" */}};
- g_iuup_ent := valueof(t_IuUP_Entity(g_cfg.iuup_tx_init));
+ g_iuup_ent := valueof(t_IuUP_Entity(g_cfg.iuup_cfg));
while (true) {
alt {
@@ -387,6 +465,11 @@ function f_main() runs on RTP_Emulation_CT
}
g_tx_connected := false; /* will set it back to true upon next connect() call */
+
+ if (g_rtp_conn_id != -1) {
+ res := RTP_CodecPort_CtrlFunct.f_IPL4_close(RTP, g_rtp_conn_id, {udp := {}});
+ g_rtp_conn_id := -1;
+ }
res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTP, g_local_host,
g_local_port, {udp:={}});
if (not ispresent(res.connId)) {
@@ -395,6 +478,11 @@ function f_main() runs on RTP_Emulation_CT
}
g_rtp_conn_id := res.connId;
tr_rtp.connId := g_rtp_conn_id;
+
+ if (g_rtcp_conn_id != -1) {
+ res := RTP_CodecPort_CtrlFunct.f_IPL4_close(RTCP, g_rtcp_conn_id, {udp := {}});
+ g_rtcp_conn_id := -1;
+ }
res := RTP_CodecPort_CtrlFunct.f_IPL4_listen(RTCP, g_local_host,
g_local_port+1, {udp:={}});
if (not ispresent(res.connId)) {
@@ -428,17 +516,23 @@ function f_main() runs on RTP_Emulation_CT
mtc.stop;
}
g_tx_connected := true;
+ /* Send any pending IuUP CTRL message whichwas delayed due to not being connected: */
+ if (isvalue(g_iuup_ent.pending_tx_pdu)) {
+ f_tx_rtp(''O, g_cfg.tx_payloads[0].payload_type);
+ }
CTRL.reply(RTPEM_connect:{g_remote_host, g_remote_port});
}
[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_NONE}) {
T_transmit.stop;
g_rx_enabled := false;
+ g_loopback := false;
CTRL.reply(RTPEM_mode:{RTPEM_MODE_NONE});
}
[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_TXONLY}) {
/* start transmit timer */
T_transmit.start;
g_rx_enabled := false;
+ g_loopback := false;
CTRL.reply(RTPEM_mode:{RTPEM_MODE_TXONLY});
}
[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_RXONLY}) {
@@ -450,6 +544,7 @@ function f_main() runs on RTP_Emulation_CT
RTCP.clear;
g_rx_enabled := true;
}
+ g_loopback := false;
CTRL.reply(RTPEM_mode:{RTPEM_MODE_RXONLY});
}
[] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_BIDIR}) {
@@ -460,11 +555,23 @@ function f_main() runs on RTP_Emulation_CT
RTCP.clear;
g_rx_enabled := true;
}
+ g_loopback := false;
CTRL.reply(RTPEM_mode:{RTPEM_MODE_BIDIR});
}
+ [] CTRL.getcall(RTPEM_mode:{RTPEM_MODE_LOOPBACK}) {
+ T_transmit.stop;
+ if (g_rx_enabled == false) {
+ /* flush queues */
+ RTP.clear;
+ RTCP.clear;
+ g_rx_enabled := true;
+ }
+ g_loopback := true;
+ CTRL.reply(RTPEM_mode:{RTPEM_MODE_LOOPBACK});
+ }
[] CTRL.getcall(RTPEM_configure:{?}) -> param (cfg) {
g_cfg := cfg;
- g_iuup_ent.cfg.active_init := g_cfg.iuup_tx_init;
+ g_iuup_ent.cfg := g_cfg.iuup_cfg;
CTRL.reply(RTPEM_configure:{cfg});
}
[] CTRL.getcall(RTPEM_stats_get:{?, ?}) -> param (is_rtcp) {
@@ -482,44 +589,77 @@ function f_main() runs on RTP_Emulation_CT
}
- /* simply ignore any RTTP/RTP if receiver not enabled */
- [g_rx_enabled==false] RTP.receive(tr_rtp) {
- g_stats_rtp.num_pkts_rx_err_disabled := g_stats_rtp.num_pkts_rx_err_disabled+1;
+ /* simply ignore any RTCP/RTP if receiver not enabled */
+ [not g_rx_enabled] RTP.receive(tr_rtp) -> value rx_rtp {
+ /* In IuUP we need to decode possible Control packets, such as INIT-ACK: */
+ if (g_cfg.iuup_mode) {
+ /* In IuUP we need to decode possible Control packets, such as INIT-ACK: */
+ rx_rtp.msg.rtp.data := f_IuUP_Em_rx_decaps(g_iuup_ent, rx_rtp.msg.rtp.data);
+ if (lengthof(rx_rtp.msg.rtp.data) != 0) {
+ /* Unexpected RTP payload (user data) arrived: */
+ g_stats_rtp.num_pkts_rx_err_disabled := g_stats_rtp.num_pkts_rx_err_disabled+1;
+ } else if (g_tx_connected and isvalue(g_iuup_ent.pending_tx_pdu)) {
+ /* IuUP Control packet was received and requires sending back something: */
+ f_tx_rtp(''O, g_cfg.tx_payloads[0].payload_type);
+ }
+ } else {
+ g_stats_rtp.num_pkts_rx_err_disabled := g_stats_rtp.num_pkts_rx_err_disabled+1;
}
- [g_rx_enabled==false] RTCP.receive(tr_rtcp) {
+ }
+ [not g_rx_enabled] RTCP.receive(tr_rtcp) {
g_stats_rtcp.num_pkts_rx_err_disabled := g_stats_rtcp.num_pkts_rx_err_disabled+1;
}
/* process received RTCP/RTP if receiver enabled */
[g_rx_enabled] RTP.receive(tr_rtp) -> value rx_rtp {
/* increment counters */
- if (rx_rtp.msg.rtp.payload_type != g_cfg.tx_payload_type) {
- g_stats_rtp.num_pkts_rx_err_pt := g_stats_rtp.num_pkts_rx_err_pt+1;
- }
g_stats_rtp.num_pkts_rx := g_stats_rtp.num_pkts_rx+1;
g_stats_rtp.bytes_payload_rx := g_stats_rtp.bytes_payload_rx +
lengthof(rx_rtp.msg.rtp.data);
- if (ispresent(g_cfg.rx_fixed_payload) and rx_rtp.msg.rtp.data != g_cfg.rx_fixed_payload) {
- g_stats_rtp.num_pkts_rx_err_payload := g_stats_rtp.num_pkts_rx_err_payload + 1;
- }
if (g_cfg.iuup_mode) {
rx_rtp.msg.rtp.data := f_IuUP_Em_rx_decaps(g_iuup_ent, rx_rtp.msg.rtp.data);
+ /* IuUP Control packet was received which may require sending back something: */
+ if (lengthof(rx_rtp.msg.rtp.data) == 0) {
+ if (g_tx_connected and isvalue(g_iuup_ent.pending_tx_pdu)) {
+ f_tx_rtp(''O, g_cfg.tx_payloads[0].payload_type);
+ }
+ repeat;
+ }
+ }
+
+ if (g_loopback) {
+ f_tx_rtp(rx_rtp.msg.rtp.data, rx_rtp.msg.rtp.payload_type);
+ /* update counters */
+ g_stats_rtp.num_pkts_tx := g_stats_rtp.num_pkts_tx + 1;
+ g_stats_rtp.bytes_payload_tx := g_stats_rtp.bytes_payload_tx
+ + lengthof(rx_rtp.msg.rtp.data);
+ } else {
+ /* Match the received payload against any of the predefined fixed rx payloads */
+ f_check_fixed_rx_payloads(rx_rtp.msg.rtp.payload_type, rx_rtp.msg.rtp.data);
+ }
+
+ if (DATA.checkstate("Connected")) {
+ DATA.send(rx_rtp.msg.rtp);
}
}
[g_rx_enabled] RTCP.receive(tr_rtcp) -> value rx_rtp {
//log("RX RTCP: ", rx_rtp);
g_stats_rtcp.num_pkts_rx := g_stats_rtcp.num_pkts_rx+1;
+ if (DATA.checkstate("Connected")) {
+ DATA.send(rx_rtp.msg.rtcp);
+ }
}
/* transmit if timer has expired */
[g_tx_connected] T_transmit.timeout {
+ var octetstring payload := g_cfg.tx_payloads[g_tx_next_seq mod lengthof(g_cfg.tx_payloads)].fixed_payload;
+ var INT7b rtp_payload_type := g_cfg.tx_payloads[g_tx_next_seq mod lengthof(g_cfg.tx_payloads)].payload_type;
/* send one RTP frame, re-start timer */
- f_tx_rtp(g_cfg.tx_fixed_payload);
+ f_tx_rtp(payload, rtp_payload_type);
T_transmit.start;
/* update counters */
g_stats_rtp.num_pkts_tx := g_stats_rtp.num_pkts_tx+1;
- g_stats_rtp.bytes_payload_tx := g_stats_rtp.bytes_payload_tx +
- lengthof(g_cfg.tx_fixed_payload);
+ g_stats_rtp.bytes_payload_tx := g_stats_rtp.bytes_payload_tx + lengthof(payload);
}
/* connection refused */
diff --git a/library/S1AP_Emulation.ttcn b/library/S1AP_Emulation.ttcn
index d09b4996..955c690f 100644
--- a/library/S1AP_Emulation.ttcn
+++ b/library/S1AP_Emulation.ttcn
@@ -1,22 +1,27 @@
module S1AP_Emulation {
-/* S1AP Emulation, runs on top of S1AP_CodecPort. It multiplexes/demultiplexes
- * the individual IMSIs/subscribers, so there can be separate TTCN-3 components handling
- * each of them.
+/* S1AP Emulation, runs on top of S1AP_CodecPort. It multiplexes/demultiplexes
+ * the individual subscribers by their UE association (MME_UE_S1AP_ID/
+ * ENB_UE_S1AP_ID identifiers), so there can be separate TTCN-3 components
+ * handling each of them.
*
* The S1AP_Emulation.main() function processes S1AP primitives from the S1AP
- * socket via the S1AP_CodecPort, and dispatches them to the per-IMSI components.
+ * socket via the S1AP_CodecPort, and dispatches them to the per-subscriber
+ * components.
*
- * For each new IMSI, the S1apOps.create_cb() is called. It can create
- * or resolve a TTCN-3 component, and returns a component reference to which that IMSI
- * is routed/dispatched.
+ * For each new subscruber, the S1apOps.create_cb() is called. It can create
+ * or resolve a TTCN-3 component, and returns a component reference to which
+ * that subscriber traffic is routed/dispatched.
*
- * If a pre-existing component wants to register to handle a future inbound IMSI, it can
- * do so by registering an "expect" with the expected IMSI.
+ * If a pre-existing component wants to register to handle a future inbound UE
+ * association, it can do so by registering an "expect" with the expected
+ * MME_UE_S1AP_ID/ENB_UE_S1AP_ID identifiers. It is also possible to register
+ * an expect for a specific procedureCode, in case the expected message is non
+ * UE related (unit-data).
*
- * Inbound non-UE related S1AP messages (such as RESET, SETUP, OVERLOAD) are dispatched to
- * the S1apOps.unitdata_cb() callback, which is registered with an argument to the
- * main() function below.
+ * Inbound non-UE related S1AP messages (such as RESET, SETUP, OVERLOAD) are
+ * dispatched to the S1apOps.unitdata_cb() callback, which is registered with
+ * an argument to the main() function below.
*
* (C) 2019 by Harald Welte <laforge@gnumonks.org>
* All rights reserved.
@@ -62,8 +67,13 @@ type record NAS_Keys {
octetstring k_nas_int,
octetstring k_nas_enc
};
+type record ResetNAScounts {
+/* empty */
+};
type union S1APEM_Config {
- NAS_Keys set_nas_keys
+ NAS_Keys set_nas_keys,
+ ResetNAScounts reset_nas_counts,
+ NAS_ALG_INT set_nas_alg_int
};
type enumerated S1APEM_EventUpDown {
@@ -91,8 +101,6 @@ type record AssociationData {
EUTRAN_CGI cgi optional,
TAI tai optional,
NAS_UE_State nus
-
- //hexstring imsi optional
};
type component S1AP_Emulation_CT {
@@ -104,8 +112,10 @@ type component S1AP_Emulation_CT {
port S1AP_Conn_PT S1AP_CLIENT;
/* currently tracked connections */
var AssociationData S1apAssociationTable[16];
- /* pending expected CRCX */
+ /* pending expected S1AP Association (UE oriented) */
var ExpectData S1apExpectTable[8];
+ /* pending expected S1AP PDU */
+ var ExpectDataProc S1apExpectTableProc[8];
/* procedure based port to register for incoming connections */
port S1APEM_PROC_PT S1AP_PROC;
/* test port for unit data messages */
@@ -196,7 +206,8 @@ private function f_assoc_id_by_s1ap_ids(template (omit) MME_UE_S1AP_ID mme_id,
runs on S1AP_Emulation_CT return integer {
var integer i;
for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {
- if (match(S1apAssociationTable[i].enb_ue_s1ap_id, enb_id)) {
+ if (istemplatekind(enb_id, "omit") or
+ match(S1apAssociationTable[i].enb_ue_s1ap_id, enb_id)) {
if (istemplatekind(mme_id, "omit")) {
return i;
} else {
@@ -253,7 +264,7 @@ runs on S1AP_Emulation_CT {
var integer i;
for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {
if (S1apAssociationTable[i].comp_ref == comp_ref and
- S1apAssociationTable[i].mme_ue_s1ap_id == enb_id) {
+ S1apAssociationTable[i].enb_ue_s1ap_id == enb_id) {
S1apAssociationTable[i].enb_ue_s1ap_id := omit;
S1apAssociationTable[i].mme_ue_s1ap_id := omit;
S1apAssociationTable[i].comp_ref := null;
@@ -273,6 +284,7 @@ runs on S1AP_Emulation_CT {
S1apAssociationTable[i].cgi := omit;
S1apAssociationTable[i].tai := omit;
S1apAssociationTable[i].nus := valueof(t_NAS_UE_State(g_pars.role));
+ S1apAssociationTable[i].comp_ref := null;
}
}
@@ -342,6 +354,55 @@ private function f_nas_try_decaps(PDU_NAS_EPS nas) return PDU_NAS_EPS
}
*/
+function handle_S1AP_UeContextReleaseCmd(template (present) S1AP_PDU rel_cmd) runs on S1AP_Emulation_CT {
+ if (ispresent(rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
+ var template MME_UE_S1AP_ID mme_ue_id;
+ var template ENB_UE_S1AP_ID enb_ue_id;
+ var integer assoc_id;
+ var S1AP_ConnHdlr vc_conn
+
+ mme_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
+ enb_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
+
+ assoc_id := f_assoc_id_by_s1ap_ids(mme_ue_id, enb_ue_id);
+ vc_conn := S1apAssociationTable[assoc_id].comp_ref;
+
+ f_s1ap_id_table_del(vc_conn, valueof(enb_ue_id));
+ } else {
+ /* TODO: The UE CONTEXT RELEASE COMMAND (see also: 3GPP TS 36.413, section 9.1.4.6), may identify the
+ * context by either an uE_S1AP_ID_pair (MME_UE_S1AP_ID and ENB_UE_S1AP_ID) or an MME_UE_S1AP_ID alone.
+ * The latter case is not implemented here yet. */
+ setverdict(fail, "complete implementation of UeContextReleaseCmd handling");
+ mtc.stop;
+ }
+}
+
+private function SendToS1apExpectTableProc(S1AP_PDU msg) runs on S1AP_Emulation_CT {
+ var integer procedureCode;
+ var S1AP_ConnHdlr vc_conn;
+
+ if (ispresent(msg.initiatingMessage.procedureCode)) {
+ procedureCode := msg.initiatingMessage.procedureCode;
+ } else if (ispresent(msg.unsuccessfulOutcome.procedureCode)) {
+ procedureCode := msg.unsuccessfulOutcome.procedureCode;
+ } else if (ispresent(msg.successfulOutcome.procedureCode)) {
+ procedureCode := msg.successfulOutcome.procedureCode;
+ } else {
+ return;
+ }
+
+ for (var integer i := 0; i < sizeof(S1apExpectTableProc); i := i+1) {
+ if (S1apExpectTableProc[i].procedureCode == procedureCode) {
+ vc_conn := S1apExpectTableProc[i].vc_conn;
+ if (vc_conn != null) {
+ S1AP_CLIENT.send(msg) to vc_conn;
+ }
+ }
+ }
+
+ return;
+}
+
function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_Emulation_CT {
var Result res;
g_pars := p;
@@ -370,12 +431,15 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
while (true) {
var S1AP_ConnHdlr vc_conn;
var PDU_NAS_EPS nas;
- var hexstring imsi;
+ var MME_UE_S1AP_ID mme_id;
+ var ENB_UE_S1AP_ID enb_id;
+ var integer procedureCode;
var S1AP_RecvFrom mrf;
var S1AP_PDU msg;
var S1APEM_Config s1cfg;
var charstring vlr_name, mme_name;
var integer ai;
+ var octetstring kasme;
alt {
/* Configuration primitive from client */
@@ -384,6 +448,17 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
S1apAssociationTable[assoc_id].nus.k_nas_int := s1cfg.set_nas_keys.k_nas_int;
S1apAssociationTable[assoc_id].nus.k_nas_enc := s1cfg.set_nas_keys.k_nas_enc;
}
+ /* Configuration primitive from client */
+ [] S1AP_CLIENT.receive(S1APEM_Config:{reset_nas_counts:=?}) -> value s1cfg sender vc_conn {
+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);
+ S1apAssociationTable[assoc_id].nus.rx_count := 0;
+ S1apAssociationTable[assoc_id].nus.tx_count := 0;
+ }
+ /* Configuration primitive from client */
+ [] S1AP_CLIENT.receive(S1APEM_Config:{set_nas_alg_int:=?}) -> value s1cfg sender vc_conn {
+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);
+ S1apAssociationTable[assoc_id].nus.alg_int := s1cfg.set_nas_alg_int;
+ }
/* S1AP from client: InitialUE */
[] S1AP_CLIENT.receive(tr_S1AP_InitialUE) -> value msg sender vc_conn {
/* create a table entry about this connection */
@@ -422,14 +497,11 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
[] S1AP.receive(tr_S1AP_RecvFrom_R(?)) -> value mrf {
if (match(mrf.msg, tr_S1AP_nonUErelated)) {
/* non-UE-related S1AP message */
+ SendToS1apExpectTableProc(mrf.msg);
var template S1AP_PDU resp := ops.unitdata_cb.apply(mrf.msg);
if (isvalue(resp)) {
S1AP.send(t_S1AP_Send(g_s1ap_conn_id, valueof(resp)));
}
- } else if (match(mrf.msg, tr_S1AP_UeContextReleaseCmd)) {
- /* TODO: special handling, as it contains multiple eNB or MME IDs */
- setverdict(fail, "implement UeContextReleaseCmd handling");
- mtc.stop;
} else {
/* Ue-related S1AP message */
/* obtain MME + ENB UE S1AP ID */
@@ -439,7 +511,7 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
if (f_s1ap_ids_known(mme_ue_id, enb_ue_id)) {
/* if yes, dispatch to the ConnHdlr for this Ue-Connection */
var template (omit) octetstring nas_enc;
- var integer assoc_id := f_assoc_id_by_s1ap_ids(mme_ue_id, enb_ue_id);
+ var integer assoc_id := f_assoc_id_by_s1ap_ids(mme_ue_id, enb_ue_id);
vc_conn := S1apAssociationTable[assoc_id].comp_ref;
nas_enc := f_S1AP_get_NAS_PDU(mrf.msg);
if (isvalue(nas_enc)) {
@@ -447,6 +519,11 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
if (match(nas, tr_NAS_EMM_SecurityProtected)) {
nas := f_nas_try_decaps(S1apAssociationTable[assoc_id].nus, nas);
}
+ /* DL/UlNasTransport are not interesting, don't send them */
+ if (not match(mrf.msg, (tr_S1AP_DlNasTransport, tr_S1AP_UlNasTransport))) {
+ /* send raw S1AP */
+ S1AP_CLIENT.send(mrf.msg) to vc_conn;
+ }
/* send decoded NAS */
S1AP_CLIENT.send(nas) to vc_conn;
} else {
@@ -459,46 +536,74 @@ function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_E
f_s1ap_id_table_add(vc_conn, mme_ue_id, valueof(enb_ue_id));
S1AP_CLIENT.send(mrf.msg) to vc_conn;
}
+ if (match(mrf.msg, tr_S1AP_UeContextReleaseCmd)) {
+ handle_S1AP_UeContextReleaseCmd(mrf.msg);
+ }
}
}
[] S1AP.receive(tr_SctpAssocChange) { }
[] S1AP.receive(tr_SctpPeerAddrChange) { }
- [] S1AP_PROC.getcall(S1APEM_register:{?,?}) -> param(imsi, vc_conn) {
- f_create_expect(imsi, vc_conn);
- S1AP_PROC.reply(S1APEM_register:{imsi, vc_conn}) to vc_conn;
+ [] S1AP_PROC.getcall(S1APEM_register:{?,?,?}) -> param(mme_id, enb_id, vc_conn) {
+ f_create_expect(mme_id, enb_id, vc_conn);
+ S1AP_PROC.reply(S1APEM_register:{mme_id, enb_id, vc_conn}) to vc_conn;
+ }
+ [] S1AP_PROC.getcall(S1APEM_register_proc:{?,?}) -> param(procedureCode, vc_conn) {
+ f_create_expect_proc(procedureCode, vc_conn);
+ S1AP_PROC.reply(S1APEM_register_proc:{procedureCode, vc_conn}) to vc_conn;
+ }
+ [] S1AP_PROC.getcall(S1APEM_derive_nas_token:{?, ?, -}) -> param(kasme, vc_conn) {
+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);
+ var OCT32 nas_token := f_kdf_nas_token(kasme, S1apAssociationTable[assoc_id].nus.tx_count)
+ S1apAssociationTable[assoc_id].nus.tx_count := S1apAssociationTable[assoc_id].nus.tx_count + 1;
+ S1AP_PROC.reply(S1APEM_derive_nas_token:{kasme, vc_conn, nas_token}) to vc_conn;
}
}
-
}
}
/* "Expect" Handling */
type record ExpectData {
- hexstring imsi optional,
+ MME_UE_S1AP_ID mme_id optional,
+ ENB_UE_S1AP_ID enb_id optional,
S1AP_ConnHdlr vc_conn
}
-signature S1APEM_register(in hexstring imsi, in S1AP_ConnHdlr hdlr);
+/* represents a single S1AP PDU that we expect. When a matching PDU is seen, it is forwarded to the registered
+ * component */
+type record ExpectDataProc {
+ integer procedureCode optional,
+ S1AP_ConnHdlr vc_conn /* component handling this UE connection */
+};
+
+signature S1APEM_register(in MME_UE_S1AP_ID mme_id, in ENB_UE_S1AP_ID enb_id, in S1AP_ConnHdlr hdlr);
+signature S1APEM_register_proc(in integer procedureCode, in S1AP_ConnHdlr hdlr);
+signature S1APEM_derive_nas_token(in octetstring kasme, in S1AP_ConnHdlr hdlr, out OCT32 nas_token);
type port S1APEM_PROC_PT procedure {
inout S1APEM_register;
+ inout S1APEM_register_proc;
+ inout S1APEM_derive_nas_token;
} with { extension "internal" };
-/* Function that can be used as create_cb and will usse the expect table */
-function ExpectedCreateCallback(S1AP_PDU msg, hexstring imsi, charstring id)
+/* Function that can be used as create_cb and will use the expect table */
+function ExpectedCreateCallback(S1AP_PDU msg,
+ template (omit) MME_UE_S1AP_ID mme_id,
+ template (omit) ENB_UE_S1AP_ID enb_id, charstring id)
runs on S1AP_Emulation_CT return S1AP_ConnHdlr {
var S1AP_ConnHdlr ret := null;
var integer i;
for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {
- if (not ispresent(S1apExpectTable[i].imsi)) {
+ if (not ispresent(S1apExpectTable[i].mme_id) and not ispresent(S1apExpectTable[i].enb_id)) {
continue;
}
- if (imsi == S1apExpectTable[i].imsi) {
+
+ if (valueof(mme_id) == S1apExpectTable[i].mme_id and valueof(enb_id) == S1apExpectTable[i].enb_id) {
ret := S1apExpectTable[i].vc_conn;
/* Release this entry */
- S1apExpectTable[i].imsi := omit;
+ S1apExpectTable[i].mme_id := omit;
+ S1apExpectTable[i].enb_id := omit;
S1apExpectTable[i].vc_conn := null;
log("Found Expect[", i, "] for ", msg, " handled at ", ret);
return ret;
@@ -508,22 +613,28 @@ runs on S1AP_Emulation_CT return S1AP_ConnHdlr {
mtc.stop;
}
-private function f_create_expect(hexstring imsi, S1AP_ConnHdlr hdlr)
+private function f_create_expect(template (omit) MME_UE_S1AP_ID mme_id,
+ template (omit) ENB_UE_S1AP_ID enb_id,
+ S1AP_ConnHdlr hdlr)
runs on S1AP_Emulation_CT {
var integer i;
/* Check an entry like this is not already presnt */
for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {
- if (imsi == S1apExpectTable[i].imsi) {
- setverdict(fail, "IMSI already present", imsi);
+ if (not ispresent(S1apExpectTable[i].mme_id) and not ispresent(S1apExpectTable[i].enb_id)) {
+ continue;
+ }
+ if (valueof(mme_id) == S1apExpectTable[i].mme_id and valueof(enb_id) == S1apExpectTable[i].enb_id) {
+ setverdict(fail, "UE MME id / UE ENB id pair already present", mme_id, enb_id);
mtc.stop;
}
}
for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {
- if (not ispresent(S1apExpectTable[i].imsi)) {
- S1apExpectTable[i].imsi := imsi;
+ if (not ispresent(S1apExpectTable[i].mme_id) and not ispresent(S1apExpectTable[i].enb_id)) {
+ S1apExpectTable[i].mme_id := valueof(mme_id);
+ S1apExpectTable[i].enb_id := valueof(enb_id);
S1apExpectTable[i].vc_conn := hdlr;
- log("Created Expect[", i, "] for ", imsi, " to be handled at ", hdlr);
+ log("Created Expect[", i, "] for UE MME id:", mme_id, ", UE ENB id:", enb_id, " to be handled at ", hdlr);
return;
}
}
@@ -531,18 +642,70 @@ runs on S1AP_Emulation_CT {
}
/* client/conn_hdlr side function to use procedure port to create expect in emulation */
-function f_create_s1ap_expect(hexstring imsi) runs on S1AP_ConnHdlr {
- S1AP_PROC.call(S1APEM_register:{imsi, self}) {
- [] S1AP_PROC.getreply(S1APEM_register:{?,?}) {};
+function f_create_s1ap_expect(template (omit) MME_UE_S1AP_ID mme_id,
+ template (omit) ENB_UE_S1AP_ID enb_id) runs on S1AP_ConnHdlr {
+ S1AP_PROC.call(S1APEM_register:{mme_id, enb_id, self}) {
+ [] S1AP_PROC.getreply(S1APEM_register:{?,?,?}) {};
}
}
+private function f_create_expect_proc(integer procedureCode, S1AP_ConnHdlr hdlr) runs on S1AP_Emulation_CT {
+ var integer i;
+
+ /* Check an entry like this is not already presnt */
+ for (i := 0; i < sizeof(S1apExpectTableProc); i := i+1) {
+ if (S1apExpectTableProc[i].vc_conn == null) {
+ continue;
+ }
+ if (S1apExpectTableProc[i].procedureCode == procedureCode) {
+ setverdict(fail, "procedureCode ", procedureCode, " already present");
+ mtc.stop;
+ }
+ }
+ for (i := 0; i < sizeof(S1apExpectTableProc); i := i+1) {
+ if (S1apExpectTableProc[i].vc_conn == null) {
+ S1apExpectTableProc[i].procedureCode := procedureCode;
+ S1apExpectTableProc[i].vc_conn := hdlr;
+ log("Created Expect[", i, "] for PDU:", procedureCode, " to be handled at ", hdlr);
+ return;
+ }
+ }
+ testcase.stop("No space left in S1apExpectTableProc")
+}
+
+/* client/conn_hdlr side function to use procedure port to create expect (PDU) in emulation */
+function f_create_s1ap_expect_proc(integer procedureCode, S1AP_ConnHdlr hdlr) runs on S1AP_ConnHdlr
+{
+ S1AP_PROC.call(S1APEM_register_proc:{procedureCode, self}) {
+ [] S1AP_PROC.getreply(S1APEM_register_proc:{?,?}) {};
+ }
+
+ log(procedureCode);
+}
+
+/* Derive NAS Token (and post-increment ul_count): */
+function f_s1apem_derive_nas_token(in octetstring kasme) runs on S1AP_ConnHdlr return OCT32
+{
+ var OCT32 nas_token;
+ S1AP_PROC.call(S1APEM_derive_nas_token:{kasme, self, -}) {
+ [] S1AP_PROC.getreply(S1APEM_derive_nas_token:{kasme, self, ?}) -> param(nas_token) {
+ return nas_token;
+ };
+ }
+}
private function f_expect_table_init()
runs on S1AP_Emulation_CT {
var integer i;
for (i := 0; i < sizeof(S1apExpectTable); i := i + 1) {
- S1apExpectTable[i].imsi := omit;
+ S1apExpectTable[i].mme_id := omit;
+ S1apExpectTable[i].enb_id := omit;
+ S1apExpectTable[i].vc_conn := null;
+ }
+
+ for (i := 0; i < sizeof(S1apExpectTableProc); i := i + 1) {
+ S1apExpectTableProc[i].procedureCode := omit;
+ S1apExpectTableProc[i].vc_conn := null;
}
}
@@ -573,7 +736,13 @@ function f_S1AP_get_ENB_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) ENB_UE_
case (tr_S1AP_UeContextReleaseReq) {
return im.value_.UEContextReleaseRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;
}
- /* UeContextReleaseCmd needs special handling; it can contain any number of MME/UE IDs */
+ case (tr_S1AP_UeContextReleaseCmd) {
+ if (ispresent(im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
+ return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
+ } else {
+ return omit;
+ }
+ }
case (tr_S1AP_ConnEstInd) {
return im.value_.ConnectionEstablishmentIndication.protocolIEs[1].value_.ENB_UE_S1AP_ID;
}
@@ -619,7 +788,13 @@ function f_S1AP_get_MME_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) MME_UE_
case (tr_S1AP_UeContextReleaseReq) {
return im.value_.UEContextReleaseRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;
}
- /* UeContextReleaseCmd needs special handling; it can contain any number of MME/UE IDs */
+ case (tr_S1AP_UeContextReleaseCmd) {
+ if (ispresent(im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
+ return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
+ } else {
+ return im.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.mME_UE_S1AP_ID;
+ }
+ }
case (tr_S1AP_ConnEstInd) {
return im.value_.ConnectionEstablishmentIndication.protocolIEs[0].value_.MME_UE_S1AP_ID;
}
@@ -650,7 +825,7 @@ function f_S1AP_get_MME_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) MME_UE_
function f_S1AP_get_NAS_PDU(S1AP_PDU s1ap) return template (omit) NAS_PDU
{
- var integer i;
+ var integer i, j;
if (ischosen(s1ap.initiatingMessage)) {
var InitiatingMessage im := s1ap.initiatingMessage;
@@ -671,6 +846,19 @@ function f_S1AP_get_NAS_PDU(S1AP_PDU s1ap) return template (omit) NAS_PDU
}
}
}
+ case (tr_S1AP_IntialCtxSetupReq) {
+ var InitialContextSetupRequest msg := im.value_.initialContextSetupRequest;
+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {
+ if (msg.protocolIEs[i].id == id_E_RABToBeSetupListCtxtSUReq) {
+ var E_RABToBeSetupListCtxtSUReq rab_req := msg.protocolIEs[i].value_.E_RABToBeSetupListCtxtSUReq;
+ for (j := 0; j < lengthof(rab_req); j := j+1) {
+ var E_RABToBeSetupItemCtxtSUReq it := rab_req[j].value_.E_RABToBeSetupItemCtxtSUReq;
+ return it.nAS_PDU;
+ }
+ }
+ }
+ return omit;
+ }
}
}
return omit;
diff --git a/library/SCCP_Templates.ttcn b/library/SCCP_Templates.ttcn
index b0e6df75..6c977ac4 100644
--- a/library/SCCP_Templates.ttcn
+++ b/library/SCCP_Templates.ttcn
@@ -15,6 +15,19 @@ import from SCCP_Types all;
import from SCCPasp_Types all;
import from SCCP_Emulation all;
+/* construct a SCCP_PAR_Address with just SSN and no PC or GT */
+template (value) SCCP_PAR_Address ts_SccpAddr_SSN(integer ssn) := {
+ addressIndicator := {
+ pointCodeIndic := '0'B,
+ ssnIndicator := '1'B,
+ globalTitleIndic := '0000'B,
+ routingIndicator := '1'B
+ },
+ signPointCode := omit,
+ subsystemNumber := ssn,
+ globalTitle := omit
+}
+
/* construct a SCCP_PAR_Address with just PC + SSN and no GT */
template (value) SCCP_PAR_Address ts_SccpAddr_PC_SSN(integer pc, integer ssn, octetstring sio,
charstring sccp_srv_type) := {
@@ -100,6 +113,39 @@ return template (value) PDU_SCCP {
return ret;
}
+template (present) PDU_SCCP tr_SCCP_CR(template (present) OCT3 source_lref := ?,
+ template (present) SCCP_PAR_Address called := ?,
+ template (present) SCCP_PAR_Address calling := ?) := {
+ connrequest := {
+ messageType := cr,
+ sourceLocRef := source_lref,
+ protClass := c_class2,
+ pointer1 := ?,
+ pointer2 := ?,
+ calledPAddress := tr_Addr(called),
+ optionalPart := {
+ credit := omit,
+ callingPAddress := tr_Addr_opt(calling),
+ data := omit,
+ hopCounter := *,
+ importance := *
+ },
+ eop := *
+ }
+}
+
+template (value) PDU_SCCP ts_SCCP_CC(OCT3 source_lref, OCT3 dest_lref) := {
+ connconfirm := {
+ messageType := cc,
+ destLocRef := dest_lref,
+ sourceLocRef := source_lref,
+ protClass := c_class2,
+ pointer1 := 0, /* overwritten */
+ optionalPart := omit,
+ eop := { paramName:= con_SCCP_eop }
+ }
+}
+
template (present) PDU_SCCP tr_SCCP_CC(template (present) OCT3 source_lref,
template (present) OCT3 dest_lref) := {
connconfirm := {
@@ -113,6 +159,34 @@ template (present) PDU_SCCP tr_SCCP_CC(template (present) OCT3 source_lref,
}
}
+private function tr_Addr(template SCCP_PAR_Address addr := *)
+return template (present) SCCP_param_CPartyAddressEnc {
+ if (istemplatekind(addr, "?")) {
+ return ?;
+ } else {
+ return ConvertASPAddressToEncodedAddress_itu(valueof(addr));
+ }
+}
+
+private function tr_Addr_opt(template SCCP_PAR_Address addr := *)
+return template SCCP_param_CPartyAddressEnc_opt {
+ if (istemplatekind(addr, "omit")) {
+ return omit;
+ } else if (istemplatekind(addr, "*")) {
+ return *;
+ } else if (istemplatekind(addr, "?")) {
+ return ?;
+ } else {
+ var SCCP_param_CPartyAddressEnc enc := ConvertASPAddressToEncodedAddress_itu(valueof(addr));
+ var SCCP_param_CPartyAddressEnc_opt enc_opt := {
+ paramName := con_SCCP_cgPA,
+ paramLength := enc.paramLength, /* overwritten */
+ addr := enc.addr
+ };
+ return enc_opt;
+ }
+}
+
template (value) PDU_SCCP ts_SCCP_UDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
template (value) octetstring data,
template (value) BIT4 msg_hdl := '0000'B) := {
@@ -131,7 +205,7 @@ template (value) PDU_SCCP ts_SCCP_UDT(SCCP_PAR_Address calling, SCCP_PAR_Address
}
}
-template PDU_SCCP tr_SCCP_UDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
+template PDU_SCCP tr_SCCP_UDT(template (present) SCCP_PAR_Address calling, template (present) SCCP_PAR_Address called,
template octetstring data := ?,
template BIT4 msg_hdl := '0000'B) := {
unitdata := {
@@ -140,15 +214,108 @@ template PDU_SCCP tr_SCCP_UDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
pointer1 := ?,
pointer2 := ?,
pointer3 := ?,
+ calledPAddress := tr_Addr(called),
+ callingPAddress := tr_Addr(calling),
+ data := {
+ paramLength := ?,
+ data := data
+ }
+ }
+}
+
+template (value) PDU_SCCP ts_SCCP_XUDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
+ template (value) octetstring data,
+ template (value) BIT4 msg_hdl := '0000'B,
+ template (value) integer hop_ctr := 16) := {
+ extudata := {
+ messageType := xudt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := 0, /* overwritten */
+ pointer2 := 0, /* overwritten */
+ pointer3 := 0, /* overwritten */
+ pointer4 := 0, /* overwritten */
calledPAddress := ConvertASPAddressToEncodedAddress_itu(called),
callingPAddress := ConvertASPAddressToEncodedAddress_itu(calling),
data := {
- paramLength := lengthof(data),
+ paramLength := 0,
data := data
- }
+ },
+ optionalPart := omit,
+ eop := omit
}
}
+template PDU_SCCP tr_SCCP_XUDT(template (present) SCCP_PAR_Address calling, template (present) SCCP_PAR_Address called,
+ template octetstring data := ?,
+ template BIT4 msg_hdl := '0000'B,
+ template integer hop_ctr := ?) := {
+ extudata := {
+ messageType := xudt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := ?,
+ pointer2 := ?,
+ pointer3 := ?,
+ pointer4 := ?,
+ calledPAddress := tr_Addr(called),
+ callingPAddress := tr_Addr(calling),
+ data := {
+ paramLength := ?,
+ data := data
+ },
+ optionalPart := { segmentation:= omit, importance := * } ifpresent,
+ eop := { paramName:= con_SCCP_eop } ifpresent
+ }
+}
+
+template (value) PDU_SCCP ts_SCCP_LUDT(SCCP_PAR_Address calling, SCCP_PAR_Address called,
+ template (value) octetstring data,
+ template (value) BIT4 msg_hdl := '0000'B,
+ template (value) integer hop_ctr := 16) := {
+ longudata := {
+ messageType := ludt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := 0, /* overwritten */
+ pointer2 := 0, /* overwritten */
+ pointer3 := 0, /* overwritten */
+ pointer4 := 0, /* overwritten */
+ calledPAddress := ConvertASPAddressToEncodedAddress_itu(called),
+ callingPAddress := ConvertASPAddressToEncodedAddress_itu(calling),
+ longData := {
+ paramLength := 0,
+ data := data
+ },
+ optionalPart := omit,
+ eop := omit
+ }
+}
+
+template PDU_SCCP tr_SCCP_LUDT(template (present) SCCP_PAR_Address calling, template (present) SCCP_PAR_Address called,
+ template octetstring data := ?,
+ template BIT4 msg_hdl := '0000'B,
+ template integer hop_ctr := ?) := {
+ longudata := {
+ messageType := ludt,
+ protClass := {'0000'B, msg_hdl},
+ hopCounter := hop_ctr,
+ pointer1 := ?,
+ pointer2 := ?,
+ pointer3 := ?,
+ pointer4 := ?,
+ calledPAddress := tr_Addr(called),
+ callingPAddress := tr_Addr(calling),
+ longData := {
+ paramLength := ?,
+ data := data
+ },
+ optionalPart := { segmentation:= omit, importance := * } ifpresent,
+ eop := { paramName:= con_SCCP_eop } ifpresent
+ }
+}
+
+
template PDU_SCCP tr_SCCP_IT(template (present) OCT3 source_lref := ?,
template (present) OCT3 dest_lref := ?) := {
inacttest := {
@@ -215,5 +382,90 @@ template PDU_SCCP tr_SCCP_RLC(template (present) OCT3 source_lref := ?,
}
}
+private function f_pc_int2bit(template (present) integer pc)
+return template SCMG_param_AffectedPointCode {
+ if (istemplatekind(pc, "?")) {
+ return ?;
+ } else {
+ return int2bit(valueof(pc), 16);
+ }
+}
+
+template (value) PDU_SCMG_message ts_SCMG_SSA(template (value) integer ssn,
+ integer pc,
+ template (value) BIT2 smi := '00'B) := {
+ messageType := sSAallowed,
+ affectedSSN := ssn,
+ affectedPC := int2bit(valueof(pc), 16),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+template (present) PDU_SCMG_message tr_SCMG_SSA(template (present) integer ssn := ?,
+ template (present) integer pc := ?,
+ template (present) BIT2 smi := ?) := {
+ messageType := sSAallowed,
+ affectedSSN := ssn,
+ affectedPC := f_pc_int2bit(pc),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+
+template (value) PDU_SCMG_message ts_SCMG_SSP(template (value) integer ssn,
+ integer pc,
+ template (value) BIT2 smi := '00'B) := {
+ messageType := sSPprohib,
+ affectedSSN := ssn,
+ affectedPC := int2bit(valueof(pc), 16),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+template (present) PDU_SCMG_message tr_SCMG_SSP(template (present) integer ssn := ?,
+ template (present) integer pc := ?,
+ template (present) BIT2 smi := ?) := {
+ messageType := sSPprohib,
+ affectedSSN := ssn,
+ affectedPC := f_pc_int2bit(pc),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+
+template (value) PDU_SCMG_message ts_SCMG_SST(template (value) integer ssn,
+ integer pc,
+ template (value) BIT2 smi := '00'B) := {
+ messageType := sSTstaTest,
+ affectedSSN := ssn,
+ affectedPC := int2bit(valueof(pc), 16),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+template (present) PDU_SCMG_message tr_SCMG_SST(template (present) integer ssn := ?,
+ template (present) integer pc := ?,
+ template (present) BIT2 smi := ?) := {
+ messageType := sSTstaTest,
+ affectedSSN := ssn,
+ affectedPC := f_pc_int2bit(pc),
+ smi := {
+ smi := smi,
+ reserved := '000000'B
+ },
+ congLevel := omit
+}
+
+
}
diff --git a/library/SDP_Templates.ttcn b/library/SDP_Templates.ttcn
new file mode 100644
index 00000000..525da8e6
--- /dev/null
+++ b/library/SDP_Templates.ttcn
@@ -0,0 +1,159 @@
+module SDP_Templates {
+
+/* SDP Templates, building on top of SDP_Types from Ericsson.
+ *
+ * (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+import from SDP_Types all;
+
+/* SDP Templates */
+template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
+ charstring session_version := "1",
+ charstring addr_type := "IP4",
+ charstring user_name := "-") := {
+ user_name := user_name,
+ session_id := session_id,
+ session_version := session_version,
+ net_type := "IN",
+ addr_type := addr_type,
+ addr := addr
+}
+
+template SDP_connection ts_SDP_connection_IP(charstring addr, charstring addr_type := "IP4",
+ template integer ttl := omit,
+ template integer num_of_addr := omit) :={
+ net_type := "IN",
+ addr_type := addr_type,
+ conn_addr := {
+ addr := addr,
+ ttl := ttl,
+ num_of_addr := num_of_addr
+ }
+}
+
+template SDP_connection tr_SDP_connection_IP(template charstring addr, template charstring addr_type := ?,
+ template integer ttl := *,
+ template integer num_of_addr := *) := {
+ net_type := "IN",
+ addr_type := addr_type,
+ conn_addr := {
+ addr := addr,
+ ttl := ttl,
+ num_of_addr := num_of_addr
+ }
+}
+
+template SDP_time ts_SDP_time(charstring beg, charstring end) := {
+ time_field := {
+ start_time := beg,
+ stop_time := end
+ },
+ time_repeat := omit
+}
+
+template SDP_media_desc ts_SDP_media_desc(integer port_number, SDP_fmt_list fmts,
+ SDP_attribute_list attributes) := {
+ media_field := {
+ media := "audio",
+ ports := {
+ port_number := port_number,
+ num_of_ports := omit
+ },
+ transport := "RTP/AVP",
+ fmts := fmts
+ },
+ information := omit,
+ connections := omit,
+ bandwidth := omit,
+ key := omit,
+ attributes := attributes
+}
+
+template SDP_media_desc tr_SDP_media_desc(template integer port_number := ?,
+ template SDP_fmt_list fmts := ?,
+ template SDP_attribute_list attributes := ?) := {
+ media_field := {
+ media := "audio",
+ ports := {
+ port_number := port_number,
+ num_of_ports := omit
+ },
+ transport := "RTP/AVP",
+ fmts := fmts
+ },
+ information := *,
+ connections := *,
+ bandwidth := *,
+ key := *,
+ attributes := attributes
+}
+
+/* master template for generating SDP based in template arguments */
+template SDP_Message ts_SDP(charstring local_addr, charstring remote_addr,
+ charstring session_id, charstring session_version,
+ integer rtp_port, SDP_fmt_list fmts,
+ SDP_attribute_list attributes) := {
+ protocol_version := 0,
+ origin := ts_SDP_origin(local_addr, session_id, session_version, f_sdp_addr2addrtype(local_addr)),
+ session_name := "-",
+ information := omit,
+ uri := omit,
+ emails := omit,
+ phone_numbers := omit,
+ connection := ts_SDP_connection_IP(remote_addr, f_sdp_addr2addrtype(remote_addr)),
+ bandwidth := omit,
+ times := { ts_SDP_time("0","0") },
+ timezone_adjustments := omit,
+ key := omit,
+ attributes := omit,
+ media_list := { ts_SDP_media_desc(rtp_port, fmts, attributes) }
+}
+
+template SDP_Message tr_SDP(template charstring remote_addr := ?, template integer rtp_port := ?) := {
+ protocol_version := 0,
+ origin := ?,
+ session_name := ?,
+ information := *,
+ uri := *,
+ emails := *,
+ phone_numbers := *,
+ connection := tr_SDP_connection_IP(remote_addr, ?),
+ bandwidth := *,
+ times := ?,
+ timezone_adjustments := *,
+ key := *,
+ attributes := *,
+ media_list := { tr_SDP_media_desc(rtp_port) }
+}
+
+template SDP_attribute ts_SDP_rtpmap(integer fmt, charstring val) := {
+ rtpmap := {
+ attr_value := int2str(fmt) & " " & val
+ }
+}
+template SDP_attribute ts_SDP_ptime(integer p) := {
+ ptime := {
+ attr_value := int2str(p)
+ }
+}
+template SDP_attribute ts_SDP_fmtp(integer fmt, charstring val) := {
+ fmtp := {
+ attr_value := int2str(fmt) & " " & val
+ }
+}
+
+function f_sdp_addr2addrtype(charstring addr) return charstring {
+ for (var integer i := 0; i < lengthof(addr); i := i + 1) {
+ if (addr[i] == ":") {
+ return "IP6";
+ }
+ }
+ return "IP4";
+}
+
+}
diff --git a/library/SGsAP_Emulation.ttcn b/library/SGsAP_Emulation.ttcn
index 6cd1052e..b860fe25 100644
--- a/library/SGsAP_Emulation.ttcn
+++ b/library/SGsAP_Emulation.ttcn
@@ -415,7 +415,7 @@ type port SGsAPEM_PROC_PT procedure {
inout SGsAPEM_register, SGsAPEM_reset_vlr, SGsAPEM_reset_mme;
} with { extension "internal" };
-/* Function that can be used as create_cb and will usse the expect table */
+/* Function that can be used as create_cb and will use the expect table */
function ExpectedCreateCallback(PDU_SGsAP msg, hexstring imsi, charstring id)
runs on SGsAP_Emulation_CT return SGsAP_ConnHdlr {
var SGsAP_ConnHdlr ret := null;
diff --git a/library/SGsAP_Templates.ttcn b/library/SGsAP_Templates.ttcn
index 4414dd11..21fff9e8 100644
--- a/library/SGsAP_Templates.ttcn
+++ b/library/SGsAP_Templates.ttcn
@@ -13,6 +13,7 @@ module SGsAP_Templates {
import from SGsAP_Types all;
import from GSM_Types all;
import from General_Types all;
+import from Osmocom_Types all;
import from MobileL3_CommonIE_Types all;
/* 9.4.2 */
@@ -162,6 +163,29 @@ function tr_SGsAP_IE_Lai_omit(template LocationAreaIdValue lai) return template
}
}
+/* 9.4.21a */
+template (value) TrackingAreaIdentityValue ts_SGsAP_TAI(GsmMcc mcc, GsmMnc mnc, uint16_t tac) := {
+ mccDigit1 := mcc[0],
+ mccDigit2 := mcc[1],
+ mccDigit3 := mcc[2],
+ mncDigit3 := f_enc_mnc_digit3(mnc),
+ mncDigit1 := mnc[0],
+ mncDigit2 := mnc[1],
+ tAC := int2oct(tac, 2)
+}
+template (value) TrackingAreaIdentity ts_SGsAP_IE_TAI(template (value) TrackingAreaIdentityValue tai) := {
+ iEI := '00100011'B,
+ lengthIndicator := 5,
+ iD := tai
+}
+function ts_SGsAP_IE_TAI_omit(template (omit) TrackingAreaIdentityValue tai)
+return template (omit) TrackingAreaIdentity {
+ if (istemplatekind(tai, "omit")) {
+ return omit;
+ } else {
+ return ts_SGsAP_IE_TAI(tai);
+ }
+}
/* 9.4.12 */
@@ -505,7 +529,8 @@ template PDU_SGsAP tr_SGsAP_LU_REJECT(template hexstring imsi,
template (value) PDU_SGsAP ts_SGsAP_LU_REQ(hexstring imsi,
template (value) octetstring mme_name,
template (value) EPS_location_update_type eps_lu_type,
- template (value) LocationAreaIdValue new_lai) := {
+ template (value) LocationAreaIdValue new_lai,
+ template (omit) TrackingAreaIdentityValue tAI := omit) := {
sGsAP_LOCATION_UPDATE_REQUEST := {
messageType := '00001001'B,
iMSI := ts_SGsAP_IMSI(imsi),
@@ -515,7 +540,7 @@ template (value) PDU_SGsAP ts_SGsAP_LU_REQ(hexstring imsi,
oldLocationAreaId := omit,
tMSI_Status := omit,
iMEI_SV := omit,
- tAI := omit,
+ tAI := ts_SGsAP_IE_TAI_omit(tAI),
eCGI := omit,
tMSI_NRI := omit,
cS_DomainOperator := omit
diff --git a/simtrace/SIMTRACE_Emulation.ttcn b/library/SIMTRACE_Emulation.ttcn
index c9076089..c9076089 100644
--- a/simtrace/SIMTRACE_Emulation.ttcn
+++ b/library/SIMTRACE_Emulation.ttcn
diff --git a/simtrace/SIMTRACE_Templates.ttcn b/library/SIMTRACE_Templates.ttcn
index 934253ed..05f738fa 100644
--- a/simtrace/SIMTRACE_Templates.ttcn
+++ b/library/SIMTRACE_Templates.ttcn
@@ -216,11 +216,13 @@ template (present) CardEmu_FeatureFlags tr_FeatureFlags(template (present) boole
template (value) SIMTRACE_PDU
ts_SIMTRACE_CEMU_CONFIG(template (value) CardEmu_FeatureFlags flags) :=
- ts_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags } });
+ ts_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags,
+ slot_mux_nr := 0} });
template (present) SIMTRACE_PDU
tr_SIMTRACE_CEMU_CONFIG(template (present) CardEmu_FeatureFlags flags) :=
- tr_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags } });
+ tr_SIMTRACE(SIMTRACE_MSGT_BD_CEMU_CONFIG, { cardem_bd_config := { features := flags,
+ slot_mux_nr := * } });
/***********************************************************************
diff --git a/simtrace/SIMTRACE_Types.ttcn b/library/SIMTRACE_Types.ttcn
index 7b1c8577..d28df2f9 100644
--- a/simtrace/SIMTRACE_Types.ttcn
+++ b/library/SIMTRACE_Types.ttcn
@@ -273,7 +273,8 @@ type record CardEmu_FeatureFlags {
};
type record CardEmu_BD_Config {
- CardEmu_FeatureFlags features
+ CardEmu_FeatureFlags features,
+ uint8_t slot_mux_nr optional
};
/***********************************************************************
diff --git a/library/SIP_Emulation.ttcn b/library/SIP_Emulation.ttcn
index e71c611b..559b575d 100644
--- a/library/SIP_Emulation.ttcn
+++ b/library/SIP_Emulation.ttcn
@@ -72,6 +72,13 @@ template RequestLine tr_ReqLine(template Method method) := {
sipVersion := ?
}
+private template PDU_SIP_Request tr_SIP_REGISTER := {
+ requestLine := tr_ReqLine(REGISTER_E),
+ msgHeader := t_SIP_msgHeader_any,
+ messageBody := *,
+ payload := *
+}
+
private template PDU_SIP_Request tr_SIP_INVITE := {
requestLine := tr_ReqLine(INVITE_E),
msgHeader := t_SIP_msgHeader_any,
@@ -79,7 +86,6 @@ private template PDU_SIP_Request tr_SIP_INVITE := {
payload := *
}
-
template SipUrl tr_SIP_Url(template charstring user_or_num,
template charstring host := *,
template integer portField := *) := {
@@ -231,7 +237,7 @@ function f_init_sip(inout SIP_Emulation_CT ct, charstring id) {
create_cb := refers(SIP_Emulation.ExpectedCreateCallback)
};
- ct := SIP_Emulation_CT.create(id);
+ ct := SIP_Emulation_CT.create(id) alive;
map(ct:SIP, system:SIP);
ct.start(SIP_Emulation.main(ops, id));
}
@@ -286,6 +292,19 @@ runs on SIP_Emulation_CT {
}
}
+ /* a ConnHdlr is sending us a SIP REGISTER: Forward to SIP port */
+ [] CLIENT.receive(tr_SIP_REGISTER) -> value sip_req sender vc_conn {
+ var CallidString call_id := sip_req.msgHeader.callId.callid;
+ if (f_call_id_known(call_id)) {
+ /* re-register */
+ vc_conn := f_comp_by_call_id(call_id);
+ } else {
+ /* new REGISTER: add to table */
+ f_call_table_add(vc_conn, call_id);
+ }
+ SIP.send(sip_req);
+ }
+
/* a ConnHdlr is sending us a SIP INVITE: Forward to SIP port */
[] CLIENT.receive(tr_SIP_INVITE) -> value sip_req sender vc_conn {
var CallidString call_id := sip_req.msgHeader.callId.callid;
@@ -307,9 +326,9 @@ runs on SIP_Emulation_CT {
SIP.send(sip_resp);
}
- [] CLIENT_PROC.getcall(SIPEM_register:{?,?}) -> param(sip_to, vc_hdlr) {
+ [] CLIENT_PROC.getcall(SIPEM_register:{?,?}) -> param(sip_to, vc_hdlr) sender vc_conn {
f_create_expect(sip_to, vc_hdlr);
- CLIENT_PROC.reply(SIPEM_register:{sip_to, vc_hdlr});
+ CLIENT_PROC.reply(SIPEM_register:{sip_to, vc_hdlr}) to vc_conn;
}
}
@@ -361,6 +380,9 @@ runs on SIP_Emulation_CT return SIP_ConnHdlr {
}
if (not ispresent(t_exp.hostPort.portField)) {
t_exp.hostPort.portField := *;
+ } else if (valueof(t_exp.hostPort.portField) == 5060) {
+ /* if the port number is 5060, it may be omitted */
+ t_exp.hostPort.portField := 5060 ifpresent;
}
if (not ispresent(t_exp.urlParameters)) {
t_exp.urlParameters := *;
diff --git a/library/SIP_Templates.ttcn b/library/SIP_Templates.ttcn
index 75681a91..e115bb7c 100644
--- a/library/SIP_Templates.ttcn
+++ b/library/SIP_Templates.ttcn
@@ -1,6 +1,12 @@
module SIP_Templates {
import from SIPmsg_Types all;
+import from TCCConversion_Functions all;
+import from TCCOpenSecurity_Functions all;
+import from TCCDateTime_Functions all;
+import from Native_Functions all;
+import from Osmocom_Types all;
+import from Misc_Helpers all;
/* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */
type record SipAddr {
@@ -10,74 +16,281 @@ type record SipAddr {
const charstring c_SIP_VERSION := "SIP/2.0";
-template (value) SipUrl ts_SipUrl(charstring user_or_tel, charstring host, integer portnr) := {
+template (value) GenericParam ts_Param(template (value) charstring id,
+ template (omit) charstring paramValue := omit) := {
+ id := id,
+ paramValue := paramValue
+}
+template (present) GenericParam tr_Param(template (present) charstring id := ?,
+ template charstring paramValue := *) := {
+ id := id,
+ paramValue := paramValue
+}
+function f_ts_Param_omit(template (value) charstring id,
+ template (omit) charstring paramValue := omit)
+ return template (omit) GenericParam
+{
+ if (istemplatekind(paramValue, "omit")) {
+ return omit;
+ }
+ return ts_Param(id, paramValue);
+}
+
+template (value) SipUrl ts_SipUrl(template (value) HostPort host_port,
+ template (omit) UserInfo user_info := omit) := {
scheme := "sip",
- userInfo := {
- userOrTelephoneSubscriber := user_or_tel,
- password := omit
- },
- hostPort := {
- host := host,
- portField := portnr
- },
+ userInfo := user_info,
+ hostPort := host_port,
urlParameters := omit,
headers := omit
}
-template SipUrl tr_SipUrl(template charstring user_or_tel,
- template charstring host,
- template integer portnr) := {
+template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?,
+ template UserInfo user_info := *) := {
scheme := "sip",
- userInfo := {
- userOrTelephoneSubscriber := user_or_tel,
- password := *
- },
- hostPort := {
- host := host,
- portField := portnr
- },
+ userInfo := user_info,
+ hostPort := host_port,
urlParameters := *,
headers := *
}
-template (value) SipAddr ts_SipAddr(charstring user_or_tel, charstring host, integer portnr) := {
+template (value) SipUrl ts_SipUrlHost(template (value) charstring host,
+ template (omit) integer portField := omit)
+ := ts_SipUrl(ts_HostPort(host, portField));
+
+function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au)
+return template (value) SipUrl {
+ if (ischosen(au.nameAddr)) {
+ return au.nameAddr.addrSpec;
+ } else { /* au.addrSpecUnion */
+ return au.addrSpecUnion;
+ }
+}
+
+template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := {
+ digestResponse := digestResponse
+}
+
+template (value) Credentials ts_Credentials_DigestResponseMD5(
+ template (value) charstring username,
+ template (value) charstring realm,
+ template (value) charstring nonce,
+ template (value) charstring uri,
+ template (value) charstring response,
+ template (value) charstring opaque,
+ template (value) charstring algorithm := "MD5",
+ template (value) charstring qop := "auth",
+ template (omit) charstring cnonce := omit,
+ template (omit) charstring nc := omit
+ ) := {
+ digestResponse := {
+ // Already added by digestResponse automatically:
+ //ts_Param("Digest", omit),
+ ts_Param("username", f_sip_str_quote(username)),
+ ts_Param("realm", f_sip_str_quote(realm)),
+ ts_Param("nonce", f_sip_str_quote(nonce)),
+ ts_Param("uri", f_sip_str_quote(uri)),
+ ts_Param("response", f_sip_str_quote(response)),
+ ts_Param("opaque", f_sip_str_quote(opaque)),
+ ts_Param("algorithm", algorithm),
+ ts_Param("qop", qop),
+ // FIXME: If "omit" is passed, these below end up in;
+ // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam"
+ f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)),
+ f_ts_Param_omit("nc", nc)
+ }
+}
+
+template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := {
+ otherResponse := otherResponse
+}
+
+template (value) Authorization ts_Authorization(template (value) Credentials body) := {
+ fieldName := AUTHORIZATION_E,
+ body := body
+}
+
+// [20.10]
+template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?,
+ template charstring displayName := *) := {
+ displayName := displayName,
+ addrSpec := addrSpec
+}
+template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec,
+ template (omit) charstring displayName := omit) := {
+ displayName := displayName,
+ addrSpec := addrSpec
+}
+
+template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := {
+ nameAddr := nameAddr
+}
+template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := {
+ nameAddr := nameAddr
+}
+
+template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := {
+ addrSpecUnion := sipUrl
+}
+template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := {
+ addrSpecUnion := sipUrl
+}
+
+
+template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?,
+ template SemicolonParam_List contactParams := *) := {
+ addressField := addressField,
+ contactParams := contactParams
+}
+template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField,
+ template (omit) SemicolonParam_List contactParams := omit) := {
+ addressField := addressField,
+ contactParams := contactParams
+}
+
+template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := {
+ fieldName := CONTACT_E,
+ contactBody := {
+ contactAddresses := contactAddresses
+ }
+}
+template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := {
+ fieldName := CONTACT_E,
+ contactBody := {
+ contactAddresses := contactAddresses
+ }
+}
+
+template (value) Contact ts_ContactWildcard := {
+ fieldName := CONTACT_E,
+ contactBody := {
+ wildcard := "*"
+ }
+}
+
+template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?)
+ := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) });
+
+private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact
+{
+ if (istemplatekind(contact_addr, "omit")) {
+ return omit;
+ } else if (istemplatekind(contact_addr, "*")) {
+ return *;
+ }
+ return tr_Contact_SipAddr(contact_addr);
+}
+
+template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr)
+ := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) });
+private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact
+{
+ if (istemplatekind(contact_addr, "omit")) {
+ return omit;
+ }
+ return ts_Contact_SipAddr(contact_addr);
+}
+
+
+// [20.19]
+template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := {
+ fieldName := EXPIRES_E,
+ deltaSec := deltaSec
+}
+
+template (value) SipAddr ts_SipAddr(template (value) HostPort host_port,
+ template (omit) UserInfo user_info := omit,
+ template (omit) charstring displayName := omit,
+ template (omit) SemicolonParam_List params := omit) := {
addr := {
nameAddr := {
- displayName := omit,
- addrSpec := ts_SipUrl(user_or_tel, host, portnr)
+ displayName := displayName,
+ addrSpec := ts_SipUrl(host_port, user_info)
}
},
- params := omit
+ params := params
}
-template SipAddr tr_SipAddr(template charstring user_or_tel,
- template charstring host,
- template integer portnr) := {
+template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?,
+ template UserInfo user_info := *,
+ template charstring displayName := *,
+ template SemicolonParam_List params := *) := {
addr := {
nameAddr := {
- displayName := *,
- addrSpec := tr_SipUrl(user_or_tel, host, portnr)
+ displayName := displayName,
+ addrSpec := tr_SipUrl(host_port, user_info)
}
},
- params := *
+ params := params
}
/* build a receive template from a value: substitute '*' for omit */
-function tr_SipAddr_from_val(SipAddr tin) return template SipAddr {
- var template SipAddr ret := tin;
- if (tin.addr.nameAddr.displayName == omit) {
- ret.addr.nameAddr.displayName := *;
+function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl {
+ var template (present) SipUrl ret := tin;
+
+ /* if the port number is 5060, it may be omitted */
+ if (ispresent(tin.hostPort.portField) and
+ valueof(tin.hostPort.portField) == 5060) {
+ ret.hostPort.portField := 5060 ifpresent;
}
- if (tin.addr.nameAddr.addrSpec.userInfo.password == omit) {
- ret.addr.nameAddr.addrSpec.userInfo.password := *;
+ if (not ispresent(tin.userInfo.password)) {
+ ret.userInfo.password := *;
+ }
+
+ return ret;
+}
+function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr {
+ var template (present) SipAddr ret := tin;
+
+ if (not ispresent(tin.addr.nameAddr.displayName)) {
+ ret.addr.nameAddr.displayName := *;
+ } else if (f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == "anonymous") {
+ /* if the user is Anonymous, it may be omitted */
+ ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName ifpresent;
}
- if (tin.params == omit) {
+
+ ret.addr.nameAddr.addrSpec := tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec);
+
+ if (not ispresent(tin.params)) {
ret.params := *;
}
return ret;
}
+function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au,
+ template (omit) SemicolonParam_List params := omit)
+return template (value) SipAddr {
+ var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au);
+ var template (omit) charstring displayName;
+
+ if (ischosen(au.nameAddr)) {
+ displayName := au.nameAddr.displayName;
+ } else { /* au.addrSpecUnion */
+ displayName := omit
+ }
-function tr_HostPort(template HostPort hp) return template HostPort {
- var template HostPort hpout := hp;
+ return ts_SipAddr(addrSpec.hostPort,
+ addrSpec.userInfo,
+ displayName,
+ params);
+}
+
+template (value) HostPort ts_HostPort(template (omit) charstring host := omit,
+ template (omit) integer portField := omit) := {
+ host := host,
+ portField := portField
+}
+
+template (present) HostPort tr_HostPort(template charstring host := *,
+ template integer portField := *) := {
+ host := host,
+ portField := portField
+}
+function f_tr_HostPort(template charstring host := *,
+ template integer portField := *)
+return template (present) HostPort {
+ return f_tr_HostPort_opt_defport(tr_HostPort(host, portField));
+}
+function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort {
+ var template (present) HostPort hpout := hp;
/* if the port number is 5060, it may be omitted */
if (isvalue(hp.portField) and valueof(hp.portField) == 5060) {
hpout.portField := 5060 ifpresent;
@@ -85,15 +298,33 @@ function tr_HostPort(template HostPort hp) return template HostPort {
return hpout;
}
-template (value) RequestLine ts_SIP_ReqLine(Method method, template (value) SipUrl uri,
+function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl {
+ var template (present) SipUrl urlout := url;
+ urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort);
+ return urlout;
+}
+
+template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber,
+ template (omit) charstring password := omit) := {
+ userOrTelephoneSubscriber := userOrTelephoneSubscriber,
+ password := password
+}
+template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?,
+ template charstring password := *) := {
+ userOrTelephoneSubscriber := userOrTelephoneSubscriber,
+ password := password
+}
+
+template (value) RequestLine ts_SIP_ReqLine(Method method,
+ template (value) SipUrl uri,
charstring ver := c_SIP_VERSION) := {
method := method,
requestUri := uri,
sipVersion := ver
}
-template RequestLine tr_SIP_ReqLine(template Method method,
- template SipUrl uri,
- template charstring ver := c_SIP_VERSION) := {
+template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?,
+ template (present) SipUrl uri := ?,
+ template (present) charstring ver := c_SIP_VERSION) := {
method := method,
requestUri := uri,
sipVersion := ver
@@ -104,7 +335,8 @@ template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring re
statusCode := status_code,
reasonPhrase := reason
}
-template StatusLine tr_SIP_StatusLine(template integer status_code, template charstring reason) := {
+template (present) StatusLine tr_SIP_StatusLine(template integer status_code,
+ template charstring reason) := {
sipVersion := "SIP/2.0",
statusCode := status_code,
reasonPhrase := reason
@@ -140,43 +372,105 @@ template (value) ContentType ts_CT_SDP := {
mediaType := "application/sdp"
};
-template (value) Via ts_Via_from(SipAddr from_addr) := {
+template (value) Via ts_Via_from(template (value) HostPort addr) := {
fieldName := VIA_E,
viaBody := {
{
sentProtocol := { "SIP", "2.0", "UDP" },
- sentBy := from_addr.addr.nameAddr.addrSpec.hostPort,
+ sentBy := addr,
viaParams := omit
}
}
}
+template (present) Via tr_Via_from(template (present) HostPort host_port := ?,
+ template SemicolonParam_List viaParams := *) := {
+ fieldName := VIA_E,
+ viaBody := {
+ {
+ sentProtocol := { "SIP", "2.0", "UDP" },
+ sentBy := host_port,
+ viaParams := viaParams
+ }
+ }
+}
+
+template (present) OtherAuth
+tr_OtherAuth(template (present) charstring authScheme := ?,
+ template (present) CommaParam_List authParams := ?) := {
+ authScheme := authScheme,
+ authParams := authParams
+}
+
+template (value) OtherAuth
+ts_OtherAuth(template (value) charstring authScheme,
+ template (value) CommaParam_List authParams) := {
+ authScheme := authScheme,
+ authParams := authParams
+}
+
+template (present) Challenge
+tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := {
+ digestCln := digestCln
+}
+
+template (value) Challenge
+ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := {
+ digestCln := digestCln
+}
-template (value) MessageHeader ts_SIP_msgHeader_empty :=c_SIP_msgHeader_empty;
-template (value) MessageHeader ts_SIP_msgh_std( CallidString call_id,
- SipAddr from_addr,
- SipAddr to_addr,
- template (omit) SipAddr contact_addr,
- charstring method,
- integer seq_nr,
- template (value) Via via,
- template (omit) ContentType content_type := omit,
- Method_List allow_methods := c_SIP_defaultMethods
- ) modifies ts_SIP_msgHeader_empty := {
+template (present) Challenge
+tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := {
+ otherChallenge := otherChallenge
+}
+
+template (value) Challenge
+ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := {
+ otherChallenge := otherChallenge
+}
+
+template (present) WwwAuthenticate
+tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := {
+ fieldName := WWW_AUTHENTICATE_E,
+ challenge := challenge
+}
+
+template (value) WwwAuthenticate
+ts_WwwAuthenticate(template (value) Challenge_list challenge) := {
+ fieldName := WWW_AUTHENTICATE_E,
+ challenge := challenge
+}
+
+template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty;
+template (value) MessageHeader
+ts_SIP_msgh_std(template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ template (omit) Contact contact,
+ template (value) charstring method,
+ template (value) integer seq_nr,
+ template (value) Via via,
+ template (omit) ContentType content_type := omit,
+ template (omit)Authorization authorization := omit,
+ template (value) Method_List allow_methods := c_SIP_defaultMethods,
+ template (omit) Expires expires := omit
+ ) modifies ts_SIP_msgHeader_empty := {
allow := {
fieldName := ALLOW_E,
methods := allow_methods
},
+ authorization := authorization,
callId := {
fieldName := CALL_ID_E,
callid := call_id
},
- contact := ts_Contact(contact_addr),
+ contact := contact,
contentType := content_type,
cSeq := {
fieldName := CSEQ_E,
seqNumber := seq_nr,
method := method
},
+ expires := expires,
fromField := {
fieldName := FROM_E,
addressField := from_addr.addr,
@@ -196,49 +490,6 @@ template (value) MessageHeader ts_SIP_msgh_std( CallidString call_id,
via := via
}
-private function tr_Contact(template SipAddr contact_addr) return template Contact
-{
- if (istemplatekind(contact_addr, "omit")) {
- return omit;
- } else if (istemplatekind(contact_addr, "*")) {
- return *;
- } else if (istemplatekind(contact_addr, "?")) {
- return ?;
- }
- var template Contact ret := {
- fieldName := CONTACT_E,
- contactBody := {
- contactAddresses := {
- {
- addressField := contact_addr.addr,
- contactParams := contact_addr.params
- }
- }
- }
- };
- return ret;
-}
-
-private function ts_Contact(template (omit) SipAddr contact_addr) return template (omit) Contact
-{
- if (istemplatekind(contact_addr, "omit")) {
- return omit;
- }
- var template (omit) Contact ret := {
- fieldName := CONTACT_E,
- contactBody := {
- contactAddresses := {
- {
- addressField := contact_addr.addr,
- contactParams := contact_addr.params
- }
- }
- }
- };
- return ret;
-}
-
-
function tr_AllowMethods(template Method_List allow_methods) return template Allow {
if (istemplatekind(allow_methods, "omit")) {
return omit;
@@ -247,34 +498,39 @@ function tr_AllowMethods(template Method_List allow_methods) return template All
} else if (istemplatekind(allow_methods, "?")) {
return ?;
}
- var template Allow ret := {
+ var template (present) Allow ret := {
fieldName := ALLOW_E,
methods := allow_methods
}
return ret
}
-template MessageHeader tr_SIP_msgh_std( template CallidString call_id,
- template SipAddr from_addr,
- template SipAddr to_addr,
- template SipAddr contact_addr,
- template charstring method,
- template ContentType content_type := *,
- template integer seq_nr := ?,
- template Method_List allow_methods := *
- ) modifies t_SIP_msgHeader_any := {
+template (present) MessageHeader
+tr_SIP_msgh_std(template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template Contact contact,
+ template (present) Via via := tr_Via_from(?),
+ template charstring method,
+ template ContentType content_type := *,
+ template integer seq_nr := ?,
+ template Method_List allow_methods := *,
+ template Expires expires := *,
+ template WwwAuthenticate wwwAuthenticate := *
+ ) modifies t_SIP_msgHeader_any := {
allow := tr_AllowMethods(allow_methods),
callId := {
fieldName := CALL_ID_E,
callid := call_id
},
- contact := tr_Contact(contact_addr),
+ contact := contact,
contentType := content_type,
cSeq := {
fieldName := CSEQ_E,
seqNumber := seq_nr,
method := method
},
+ expires := expires,
fromField := {
fieldName := FROM_E,
addressField := from_addr.addr,
@@ -286,105 +542,168 @@ template MessageHeader tr_SIP_msgh_std( template CallidString call_id,
toParams := to_addr.params
},
userAgent := *,
- via := {
- fieldName := VIA_E,
- viaBody := {
- {
- sentProtocol := { "SIP", "2.0", "UDP" },
- sentBy := tr_HostPort(from_addr.addr.nameAddr.addrSpec.hostPort),
- viaParams := *
- }
- }
- }
+ via := via,
+ wwwAuthenticate := wwwAuthenticate
}
-template (value) PDU_SIP_Request ts_SIP_INVITE( CallidString call_id,
- SipAddr from_addr,
- SipAddr to_addr,
- integer seq_nr,
- template (omit) charstring body
- ) := {
+template (value) PDU_SIP_Request
+ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port,
+ template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ template (value) Via via,
+ integer seq_nr,
+ template (omit) Contact contact,
+ template (omit) Expires expires,
+ template (omit) Authorization authorization := omit,
+ template (omit) charstring body := omit) := {
+ requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port),
+ msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
+ "REGISTER", seq_nr, via,
+ f_ContentTypeOrOmit(ts_CT_SDP, body),
+ authorization := authorization,
+ expires := expires),
+ messageBody := body,
+ payload := omit
+}
+template (present) PDU_SIP_Request
+tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?,
+ template (present) CallidString call_id := ?,
+ template (present) SipAddr from_addr := ?,
+ template (present) SipAddr to_addr := ?,
+ template integer seq_nr := *,
+ template Contact contact := *,
+ template Expires expires := *,
+ template charstring body := *) := {
+ requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
+ tr_Via_from(f_tr_HostPort_opt_defport(from_addr.addr.nameAddr.addrSpec.hostPort)),
+ "REGISTER", *, seq_nr,
+ expires := expires),
+ messageBody := body,
+ payload := omit
+}
+
+template (value) PDU_SIP_Request
+ts_SIP_INVITE(template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ template (value) Via via,
+ template (value) Contact contact,
+ integer seq_nr,
+ template (omit) charstring body := omit) := {
requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
- msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, from_addr, "INVITE", seq_nr,
- ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
+ msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact,
+ "INVITE", seq_nr,
+ via,
+ f_ContentTypeOrOmit(ts_CT_SDP, body)),
messageBody := body,
payload := omit
}
-template PDU_SIP_Request tr_SIP_INVITE( template CallidString call_id,
- template SipAddr from_addr,
- template SipAddr to_addr,
- template integer seq_nr,
- template charstring body
- ) := {
- requestLine := tr_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec),
- msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?, "INVITE", *, seq_nr),
+template (present) PDU_SIP_Request
+tr_SIP_INVITE(template (present) SipUrl uri,
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)),
+ template integer seq_nr,
+ template charstring body) := {
+ requestLine := tr_SIP_ReqLine(INVITE_E, uri),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?,
+ via, "INVITE", *, seq_nr),
messageBody := body,
payload := omit
}
-template (value) PDU_SIP_Request ts_SIP_BYE( CallidString call_id,
- SipAddr from_addr,
- SipAddr to_addr,
- integer seq_nr,
- template (omit) charstring body
- ) := {
+template (value) PDU_SIP_Request
+ts_SIP_BYE(CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ template (value) Via via,
+ integer seq_nr,
+ template (omit) charstring body) := {
requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr,
- ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
+ via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
messageBody := body,
payload := omit
}
-template PDU_SIP_Request tr_SIP_BYE( template CallidString call_id,
- template SipAddr from_addr,
- template SipAddr to_addr,
- template integer seq_nr,
- template charstring body
- ) := {
- requestLine := tr_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec),
- msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", *, seq_nr),
+template (present) PDU_SIP_Request
+tr_SIP_BYE(template (present) SipUrl uri,
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template Via via,
+ template integer seq_nr,
+ template charstring body := *) := {
+ requestLine := tr_SIP_ReqLine(BYE_E, uri),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
+ via, "BYE", *, seq_nr),
messageBody := body,
payload := omit
}
-template (value) PDU_SIP_Request ts_SIP_ACK( CallidString call_id,
- SipAddr from_addr,
- SipAddr to_addr,
- integer seq_nr,
- template (omit) charstring body
- ) := {
+template (value) PDU_SIP_Request
+ts_SIP_ACK(template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ template (value) Via via,
+ integer seq_nr,
+ template (omit) charstring body) := {
requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
- msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, from_addr, "ACK", seq_nr,
- ts_Via_from(from_addr), f_ContentTypeOrOmit(ts_CT_SDP, body)),
+ msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr,
+ ts_Contact_SipAddr(from_addr),
+ "ACK", seq_nr,
+ via,
+ f_ContentTypeOrOmit(ts_CT_SDP, body)),
messageBody := body,
payload := omit
}
-template PDU_SIP_Request tr_SIP_ACK( template CallidString call_id,
- template SipAddr from_addr,
- template SipAddr to_addr,
- template integer seq_nr,
- template charstring body
- ) := {
- requestLine := tr_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec),
- msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *, "ACK", *, seq_nr),
+template (present) PDU_SIP_Request
+tr_SIP_ACK(template (present) SipUrl uri,
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template Via via,
+ template integer seq_nr,
+ template charstring body) := {
+ requestLine := tr_SIP_ReqLine(ACK_E, uri),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
+ via,
+ "ACK", *, seq_nr),
messageBody := body,
payload := omit
}
+template (present) PDU_SIP_Request
+tr_SIP_CANCEL(template (present) SipUrl uri,
+ template (present) CallidString call_id,
+ template (present) SipAddr from_addr,
+ template (present) SipAddr to_addr,
+ template (present) Via via,
+ template (present) integer seq_nr,
+ template charstring body := *) := {
+ requestLine := tr_SIP_ReqLine(CANCEL_E, uri),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
+ via,
+ "CANCEL", *, seq_nr),
+ messageBody := body,
+ payload := omit
+}
-
-template (value) PDU_SIP_Response ts_SIP_Response( CallidString call_id,
- SipAddr from_addr,
- SipAddr to_addr,
- charstring method,
- integer status_code,
- integer seq_nr,
- charstring reason,
- Via via,
- template (omit) charstring body := omit
- ) := {
+template (value) PDU_SIP_Response
+ts_SIP_Response(template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ charstring method,
+ integer status_code,
+ integer seq_nr,
+ charstring reason,
+ Via via,
+ template (omit) charstring body := omit) := {
statusLine := ts_SIP_StatusLine(status_code, reason),
msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
@@ -392,22 +711,511 @@ template (value) PDU_SIP_Response ts_SIP_Response( CallidString call_id,
payload := omit
}
-template PDU_SIP_Response tr_SIP_Response( template CallidString call_id,
- template SipAddr from_addr,
- template SipAddr to_addr,
- template SipAddr contact_addr,
- template charstring method,
- template integer status_code,
- template integer seq_nr := ?,
- template charstring reason := ?,
- template charstring body := ?
- ) := {
+/* 180 Ringing */
+template (value) PDU_SIP_Response
+ts_SIP_Response_Ringing(
+ template (value) CallidString call_id,
+ template (value) SipAddr from_addr,
+ template (value) SipAddr to_addr,
+ Via via,
+ integer seq_nr,
+ charstring method := "INVITE",
+ template (omit) charstring body := omit) := {
+ statusLine := ts_SIP_StatusLine(180, "Ringing"),
+ msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr,
+ via, f_ContentTypeOrOmit(ts_CT_SDP, body)),
+ messageBody := body,
+ payload := omit
+}
+
+template (present) PDU_SIP_Response
+tr_SIP_Response(template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template (present) Via via := tr_Via_from(?),
+ template Contact contact,
+ template charstring method,
+ template integer status_code,
+ template integer seq_nr := ?,
+ template charstring reason := ?,
+ template charstring body := *) := {
+ statusLine := tr_SIP_StatusLine(status_code, reason),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
+ via,
+ method, *, seq_nr),
+ messageBody := body,
+ payload := omit
+}
+
+/* Expect during first REGISTER/INVITE/... when authorization is required: */
+template (present) PDU_SIP_Response
+tr_SIP_Response_Unauthorized(
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template (present) Via via := tr_Via_from(?),
+ template Contact contact := *,
+ template (present) WwwAuthenticate wwwAuthenticate := ?,
+ template integer seq_nr := ?,
+ template charstring method := "REGISTER",
+ template integer status_code := 401,
+ template charstring reason := "Unauthorized",
+ template charstring body := *) := {
+ statusLine := tr_SIP_StatusLine(status_code, reason),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact,
+ via,
+ method, *, seq_nr,
+ wwwAuthenticate := wwwAuthenticate),
+ messageBody := body,
+ payload := omit
+}
+
+/* 100 Trying */
+template (present) PDU_SIP_Response
+tr_SIP_Response_Trying(
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template (present) Via via := tr_Via_from(?),
+ template integer seq_nr := ?,
+ template charstring method := "INVITE",
+ template integer status_code := 100,
+ template charstring reason := "Trying",
+ template charstring body := *) := {
statusLine := tr_SIP_StatusLine(status_code, reason),
- msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact_addr, method, *, seq_nr),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit,
+ via,
+ method, *, seq_nr),
messageBody := body,
payload := omit
}
+/* 180 Ringing */
+template (present) PDU_SIP_Response
+tr_SIP_Response_Ringing(
+ template CallidString call_id,
+ template SipAddr from_addr,
+ template SipAddr to_addr,
+ template (present) Via via := tr_Via_from(?),
+ template integer seq_nr := ?,
+ template charstring method := "INVITE",
+ template integer status_code := 180,
+ template charstring reason := "Ringing",
+ template charstring body := *) := {
+ statusLine := tr_SIP_StatusLine(status_code, reason),
+ msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *,
+ via,
+ method, *, seq_nr),
+ messageBody := body,
+ payload := omit
+}
+
+/****************
+ * FUNCTIONS:
+ ****************/
+
+function f_sip_param_find(GenericParam_List li,
+ template (present) charstring id := ?)
+return template (omit) GenericParam {
+ var integer i;
+
+ for (i := 0; i < lengthof(li); i := i + 1) {
+ if (not ispresent(li[i])) {
+ continue;
+ }
+ if (match(li[i].id, id)) {
+ return li[i];
+ }
+ }
+ return omit;
+}
+
+function f_sip_param_find_or_fail(GenericParam_List li,
+ template (present) charstring id := ?)
+return GenericParam {
+ var template (omit) GenericParam parameter;
+ parameter := f_sip_param_find(li, id);
+ if (istemplatekind(parameter, "omit")) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Param ", id, " not found in ", li));
+ }
+ return valueof(parameter);
+}
+
+function f_sip_param_get_value(GenericParam_List li,
+ template (present) charstring id := ?)
+return template (omit) charstring {
+ var template (omit) GenericParam parameter;
+ parameter := f_sip_param_find(li, id);
+ if (istemplatekind(parameter, "omit")) {
+ return omit;
+ }
+ return parameter.paramValue;
+}
+
+function f_sip_param_get_value_or_fail(GenericParam_List li,
+ template (present) charstring id := ?)
+return template (omit) charstring {
+ var GenericParam parameter;
+ parameter := f_sip_param_find_or_fail(li, id);
+ return parameter.paramValue;
+}
+
+function f_sip_param_get_value_present_or_fail(GenericParam_List li,
+ template (present) charstring id := ?)
+return charstring {
+ var GenericParam parameter;
+ parameter := f_sip_param_find_or_fail(li, id);
+ if (not ispresent(parameter.paramValue)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Param ", id, " value not present in ", li));
+ }
+ return parameter.paramValue;
+}
+
+function f_sip_param_match_value(GenericParam_List li,
+ template (present) charstring id := ?,
+ template charstring exp_paramValue := *)
+return boolean {
+ var template (omit) charstring val;
+ val := f_sip_param_get_value_or_fail(li, id);
+ if (istemplatekind(val, "omit")) {
+ return istemplatekind(val, "omit") or istemplatekind(val, "*");
+ }
+ return match(valueof(val), exp_paramValue);
+}
+
+function f_sip_param_match_value_or_fail(GenericParam_List li,
+ template (present) charstring id := ?,
+ template charstring exp_paramValue := *)
+{
+ var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id);
+ if (istemplatekind(val, "omit")) {
+ if (istemplatekind(val, "omit") or istemplatekind(val, "*")) {
+ return;
+ } else {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Param ", id, " match failed: val ", val,
+ " vs exp ", exp_paramValue));
+ }
+ }
+ if (not match(valueof(val), exp_paramValue)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Param ", id, " match failed: val ", val,
+ " vs exp ", exp_paramValue));
+ }
+}
+
+function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id)
+return GenericParam_List {
+ var integer i;
+ var GenericParam_List li;
+ var GenericParam_List new_li := {};
+
+ if (istemplatekind(li_tpl, "omit")) {
+ return {};
+ }
+
+ li := valueof(li_tpl);
+ for (i := 0; i < lengthof(li); i := i + 1) {
+ if (not ispresent(li[i]) or
+ not match(li[i].id, id)) {
+ new_li := new_li & {li[i]};
+ }
+ }
+ return new_li;
+}
+
+function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val)
+return GenericParam_List {
+ var integer i;
+ var GenericParam_List li;
+ var GenericParam_List new_li := {};
+ var boolean found := false;
+
+ if (istemplatekind(li_tpl, "omit")) {
+ return { valueof(ts_Param(id, val)) };
+ }
+
+ li := valueof(li_tpl);
+ for (i := 0; i < lengthof(li); i := i + 1) {
+ if (not ispresent(li[i]) or
+ not match(li[i].id, id)) {
+ new_li := new_li & {li[i]};
+ continue;
+ }
+ new_li := new_li & { valueof(ts_Param(li[i].id, val)) };
+ found := true;
+ }
+
+ if (not found) {
+ new_li := new_li & { valueof(ts_Param(id, val)) };
+ }
+ return new_li;
+}
+
+/* Make sure string is quoted. */
+function f_sip_str_quote(template (value) charstring val) return charstring {
+ var charstring str := valueof(val);
+ if (lengthof(str) == 0) {
+ return "";
+ }
+
+ if (str[0] != "\"") {
+ return "\"" & str & "\"";
+ }
+ return str;
+}
+
+/* Make sure string is unquoted.
+ * Similar to unq() in RFC 2617 */
+function f_sip_str_unquote(template (value) charstring val) return charstring {
+ var charstring str := valueof(val);
+ var integer len := lengthof(str);
+
+ if (len <= 1) {
+ return str;
+ }
+
+ if (str[0] == "\"" and str[len - 1] == "\"") {
+ return substr(str, 1, len - 2);
+ }
+ return str;
+}
+
+/* RFC 2617 3.2.2.2 A1 */
+function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring {
+
+ /* RFC 2617 3.2.2.2 A1 */
+ var charstring A1 := f_sip_str_unquote(user) & ":" &
+ f_sip_str_unquote(realm) & ":" &
+ password;
+ var charstring digestA1 := f_str_tolower(f_calculateMD5(A1));
+ log("A1: md5('", A1, "') = ", digestA1);
+ return digestA1;
+}
+
+/* RFC 2617 3.2.2.2 A2 */
+function f_sip_digest_A2(charstring method, charstring uri) return charstring {
+
+ var charstring A2 := method & ":" & uri
+ var charstring digestA2 := f_str_tolower(f_calculateMD5(A2));
+ log("A2: md5('", A2, "') = ", digestA2);
+ return digestA2;
+}
+
+/* RFC 2617 3.2.2.1 Request-Digest */
+function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce,
+ charstring nc, charstring cnonce,
+ charstring qop, charstring digestA2) return charstring {
+ var charstring digest_data := f_sip_str_unquote(nonce) & ":" &
+ nc & ":" &
+ cnonce & ":" &
+ f_sip_str_unquote(qop) & ":" &
+ digestA2;
+ var charstring req_digest := f_sip_digest_KD(digestA1, digest_data);
+ log("Request-Digest: md5('", digestA1, ":", digest_data ,"') = ", req_digest);
+ return req_digest;
+}
+
+/* RFC 2617 3.2.1 The WWW-Authenticate Response Header
+ * KD(secret, data) = H(concat(secret, ":", data))
+ */
+function f_sip_digest_KD(charstring secret, charstring data) return charstring {
+ return f_str_tolower(f_calculateMD5(secret & ":" & data));
+}
+
+/* Digest Auth: RFC 2617 */
+function f_sip_digest_gen_Authorization(WwwAuthenticate www_authenticate,
+ charstring user, charstring password,
+ charstring method, charstring uri,
+ charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization {
+ var CommaParam_List digestCln;
+ var template (value) Authorization authorization;
+ var template (value) Credentials cred;
+ var template (omit) GenericParam rx_param;
+
+ digestCln := www_authenticate.challenge[0].digestCln;
+
+ var charstring algorithm;
+ rx_param := f_sip_param_find(digestCln, "algorithm");
+ if (istemplatekind(rx_param, "omit")) {
+ /* Assume MD5 if not set */
+ algorithm := "MD5"
+ } else {
+ algorithm := valueof(rx_param.paramValue);
+ if (f_strstr(algorithm, "MD5") == -1) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected algorithm: ", algorithm));
+ }
+ }
+
+ var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm");
+ var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce");
+ var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque");
+ var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop");
+
+ if (f_strstr(qop, "auth") == -1) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop));
+ }
+ var charstring selected_qop := "auth";
+
+ /* RFC 2617 3.2.2.2 A1 */
+ var charstring digestA1 := f_sip_digest_A1(user, realm, password);
+ /* RFC 2617 3.2.2.3 A2 */
+ var charstring digestA2 := f_sip_digest_A2(method, uri);
+
+ /* RFC 2617 3.2.2.1 Request-Digest */
+ var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8)));
+ var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce,
+ nc, cnonce,
+ selected_qop, digestA2);
+
+ cred := ts_Credentials_DigestResponseMD5(user, realm, nonce,
+ uri, req_digest,
+ opaque, algorithm, selected_qop, cnonce, nc);
+
+ authorization := ts_Authorization(cred);
+ return valueof(authorization);
+}
+
+/* RFC 2617 3.5 Example */
+function f_sip_digest_selftest() {
+/*
+The following example assumes that an access-protected document is
+being requested from the server via a GET request. The URI of the
+document is "http://www.nowhere.org/dir/index.html". Both client and
+server know that the username for this document is "Mufasa", and the
+password is "Circle Of Life" (with one space between each of the
+three words).
+
+HTTP/1.1 401 Unauthorized
+WWW-Authenticate: Digest
+ realm="testrealm@host.com",
+ qop="auth,auth-int",
+ nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
+ opaque="5ccc069c403ebaf9f0171e9517f40e41"
+
+Authorization: Digest username="Mufasa",
+ realm="testrealm@host.com",
+ nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
+ uri="/dir/index.html",
+ qop=auth,
+ nc=00000001,
+ cnonce="0a4f113b",
+ response="6629fae49393a05397450978507c4ef1",
+ opaque="5ccc069c403ebaf9f0171e9517f40e41"
+*/
+ var template (value) CommaParam_List digestCln := {
+ ts_Param("realm", f_sip_str_quote("testrealm@host.com")),
+ ts_Param("qop", f_sip_str_quote("auth,auth-int")),
+ ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")),
+ ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"))
+ };
+ var template (value) WwwAuthenticate www_authenticate :=
+ ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } )
+
+ var Authorization authorization :=
+ f_sip_digest_gen_Authorization(valueof(www_authenticate),
+ "Mufasa",
+ "Circle Of Life",
+ "GET",
+ "/dir/index.html",
+ cnonce := "0a4f113b",
+ nc_int := 1);
+
+ var CommaParam_List digestResp := authorization.body.digestResponse;
+ f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com"));
+ f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093"));
+ f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html"));
+ f_sip_param_match_value_or_fail(digestResp, "qop", "auth");
+ f_sip_param_match_value_or_fail(digestResp, "nc", "00000001");
+ f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b"));
+ f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1"));
+ f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41"));
+}
+
+/* RFC 3261 8.1.1.5:
+ * "The sequence number value MUST be expressible as a 32-bit unsigned integer
+ * and MUST be less than 2**31."
+ */
+function f_sip_rand_seq_nr() return integer {
+ /* 2**31 = 2147483648 */
+ return f_rnd_int(2147483648)
+}
+
+function f_sip_next_seq_nr(integer seq_nr) return integer {
+ return (seq_nr + 1) mod 2147483648;
+}
+
+function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) {
+ req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber));
+}
+function f_sip_rand_tag() return charstring {
+ /* Tags shall have at least 32 bit of randomness */
+ var integer rnd_int := f_rnd_int(4294967296);
+ /* Make collisions harder by appending time to the final string: */
+ var integer ts_int := f_time_ms() mod 4294967296;
+ return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8));
+}
+
+/* Generate a "branch" tag value.
+ * RFC 3261 p.105 section 8:
+ * "A common way to create this value is to compute a
+ * cryptographic hash of the To tag, From tag, Call-ID header
+ * field, the Request-URI of the request received (before
+ * translation), the topmost Via header, and the sequence number
+ * from the CSeq header field, in addition to any Proxy-Require
+ * and Proxy-Authorization header fields that may be present. The
+ * algorithm used to compute the hash is implementation-dependent,
+ * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable
+ * choice."
+ * See also Section 8.1.1.7:
+ * "The branch ID inserted by an element compliant with this
+ * specification MUST always begin with the characters "z9hG4bK"."
+ */
+const charstring sip_magic_cookie := "z9hG4bK";
+function f_sip_gen_branch(charstring tag_to,
+ charstring tag_from,
+ charstring tag_call_id,
+ integer cseq) return charstring {
+ var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq);
+ var charstring hash := f_calculateMD5(str);
+ var charstring branch := sip_magic_cookie & hash;
+ return branch;
+}
+
+function f_sip_HostPort_to_str(HostPort host_port) return charstring {
+ var charstring str := "";
+ if (ispresent(host_port.host)) {
+ str := host_port.host;
+ }
+ if (ispresent(host_port.portField)) {
+ str := str & ":" & int2str(host_port.portField);
+ }
+ return str;
+}
+
+function f_sip_SipUrl_to_str(SipUrl uri) return charstring {
+ var charstring str := uri.scheme & f_sip_HostPort_to_str(uri.hostPort);
+ return str;
+}
+
+function f_sip_NameAddr_to_str(NameAddr naddr) return charstring {
+ if (ispresent(naddr.displayName)) {
+ return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">";
+ } else {
+ return f_sip_SipUrl_to_str(naddr.addrSpec);
+ }
+}
+
+function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring {
+ if (ischosen(sip_addr.addr.nameAddr)) {
+ return f_sip_NameAddr_to_str(sip_addr.addr.nameAddr);
+ } else {
+ return f_sip_SipUrl_to_str(sip_addr.addr.addrSpecUnion);
+ }
+}
}
diff --git a/library/SMPP_Emulation.ttcn b/library/SMPP_Emulation.ttcn
index fdeed4b4..6c808ebe 100644
--- a/library/SMPP_Emulation.ttcn
+++ b/library/SMPP_Emulation.ttcn
@@ -362,6 +362,17 @@ type port SMPPEM_PROC_PT procedure {
private function f_create_expect(charstring dest_number, SMPP_ConnHdlr hdlr)
runs on SMPP_Emulation_CT {
for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) {
+ if (ExpectTable[i].dst_addr == dest_number) {
+ ExpectTable[i] := {
+ dst_ton := omit,
+ dst_npi := omit,
+ dst_addr := dest_number,
+ vc_conn := hdlr
+ }
+ return;
+ }
+ }
+ for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) {
if (ExpectTable[i].vc_conn == null) {
ExpectTable[i] := {
dst_ton := omit,
diff --git a/library/StatsD_Checker.ttcn b/library/StatsD_Checker.ttcn
new file mode 100644
index 00000000..2ad4c9f4
--- /dev/null
+++ b/library/StatsD_Checker.ttcn
@@ -0,0 +1,280 @@
+module StatsD_Checker {
+
+/* Verifies that StatsD metrics in a test match the expected values
+ * Uses StatsD_CodecPort to receive the statsd messages from the DUT
+ * and a separate VTY connection to reset and trigger the stats.
+ *
+ * When using this you should configure your stats reporter to disable
+ * interval-based reports and always send all metrics:
+ * > stats interval 0
+ * > stats reporter statsd
+ * > remote-ip a.b.c.d
+ * > remote-port 8125
+ * > level subscriber
+ * > flush-period 1
+ * > mtu 1024
+ * > enable
+ *
+ * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Author: Daniel Willmann <dwillmann@sysmocom.de>
+ *
+ * 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
+ */
+
+import from Misc_Helpers all;
+import from Socket_API_Definitions all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+
+import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+modulepar {
+ /* Whether to test stats values */
+ boolean mp_enable_stats := true;
+}
+
+type record StatsDExpect {
+ MetricName name,
+ MetricType mtype,
+ MetricValue min,
+ MetricValue max
+};
+
+type set of StatsDExpect StatsDExpects;
+
+type record StatsDExpectPriv {
+ StatsDExpect expect,
+ integer seen
+}
+
+type set of StatsDExpectPriv StatsDExpectPrivs;
+
+type enumerated StatsDResultType {
+ e_Matched,
+ e_Mismatched,
+ e_NotFound
+}
+
+type record StatsDExpectResult {
+ StatsDResultType kind,
+ integer idx
+}
+
+type component StatsD_Checker_CT {
+ port TELNETasp_PT STATSVTY;
+ port STATSD_PROC_PT STATSD_PROC;
+ port STATSD_CODEC_PT STATS;
+ timer T_statsd := 5.0;
+}
+
+type component StatsD_ConnHdlr {
+ port STATSD_PROC_PT STATSD_PROC;
+}
+
+signature STATSD_reset();
+signature STATSD_expect(in StatsDExpects expects) return boolean;
+
+type port STATSD_PROC_PT procedure {
+ inout STATSD_reset, STATSD_expect;
+} with {extension "internal"};
+
+/* Expect templates and functions */
+
+
+/* StatsD checker component */
+function main(charstring statsd_host, integer statsd_port) runs on StatsD_Checker_CT {
+ var StatsD_ConnHdlr vc_conn;
+ var StatsDExpects expects;
+ var Result res;
+
+ while (not mp_enable_stats) {
+ log("StatsD checker disabled by modulepar");
+ f_sleep(3600.0);
+ }
+
+ map(self:STATS, system:STATS);
+ res := StatsD_CodecPort_CtrlFunct.f_IPL4_listen(STATS, statsd_host, statsd_port, { udp := {} }, {});
+ if (not ispresent(res.connId)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Could not bind StatsD socket, check your configuration");
+ }
+
+ /* Connect to VTY and reset stats */
+ map(self:STATSVTY, system:STATSVTY);
+ f_vty_set_prompts(STATSVTY);
+ f_vty_transceive(STATSVTY, "enable");
+
+ /* Reset the stats system at start */
+ f_vty_transceive(STATSVTY, "stats reset");
+
+ while (true) {
+ alt {
+ [] STATSD_PROC.getcall(STATSD_reset:{}) -> sender vc_conn {
+ f_vty_transceive(STATSVTY, "stats reset");
+ STATSD_PROC.reply(STATSD_reset:{}) to vc_conn;
+ }
+ [] STATSD_PROC.getcall(STATSD_expect:{?}) -> param(expects) sender vc_conn {
+ var boolean success := f_statsd_checker_expect(expects);
+ STATSD_PROC.reply(STATSD_expect:{expects} value success) to vc_conn;
+ }
+ }
+ }
+}
+
+
+/* Return false if the expectation doesn't match the metric, otherwise return true */
+private function f_compare_expect(StatsDMetric metric, StatsDExpect expect) return boolean {
+ if ((metric.name == expect.name) and (metric.mtype == expect.mtype)
+ and (metric.val >= expect.min) and (metric.val <= expect.max)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+private function f_statsd_checker_metric_expects(StatsDExpectPrivs exp_seen, StatsDMetric metric)
+return StatsDExpectResult {
+ var StatsDExpectResult result := {
+ kind := e_NotFound,
+ idx := -1
+ };
+
+ for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
+ var StatsDExpectPriv exp := exp_seen[i];
+ if (exp.expect.name != metric.name) {
+ continue;
+ }
+ if (not f_compare_expect(metric, exp.expect)) {
+ log("EXP mismatch: ", metric, " vs ", exp.expect);
+ result := {
+ kind := e_Mismatched,
+ idx := i
+ };
+ break;
+ } else {
+ log("EXP match: ", metric, " vs ", exp.expect);
+ result := {
+ kind := e_Matched,
+ idx := i
+ };
+ break;
+ }
+ }
+ return result;
+}
+
+template StatsDExpectPriv t_statsd_expect_priv(template StatsDExpect expect) := {
+ expect := expect,
+ seen := 0
+}
+
+private function f_statsd_checker_expect(StatsDExpects expects) runs on StatsD_Checker_CT return boolean {
+ var default t;
+ var StatsDMessage msg;
+ var StatsDExpectResult res;
+ var StatsDExpectPrivs exp_seen := {};
+
+ for (var integer i := 0; i < lengthof(expects); i := i + 1) {
+ exp_seen := exp_seen & {valueof(t_statsd_expect_priv(expects[i]))};
+ }
+
+ /* Dismiss any messages we might have skipped from the last report */
+ STATS.clear;
+
+ f_vty_transceive(STATSVTY, "stats report");
+
+ var boolean seen_all := false;
+ T_statsd.start;
+ while (not seen_all) {
+ var StatsD_RecvFrom rf;
+ alt {
+ [] STATS.receive(tr_StatsD_RecvFrom(?, ?)) -> value rf {
+ msg := rf.msg;
+ }
+ [] T_statsd.timeout {
+ for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
+ /* We're still missing some expects, keep looking */
+ if (exp_seen[i].seen == 0) {
+ log("Timeout waiting for ", exp_seen[i].expect.name, " (min: ", exp_seen[i].expect.min,
+ ", max: ", exp_seen[i].expect.max, ")");
+ }
+ }
+ setverdict(fail, "Timeout waiting for metrics");
+ return false;
+ }
+ }
+
+ for (var integer i := 0; i < lengthof(msg); i := i + 1) {
+ var StatsDMetric metric := msg[i];
+
+ res := f_statsd_checker_metric_expects(exp_seen, metric);
+ if (res.kind == e_NotFound) {
+ continue;
+ }
+
+ if (res.kind == e_Mismatched) {
+ log("Metric: ", metric);
+ log("Expect: ", exp_seen[res.idx].expect);
+ setverdict(fail, "Metric failed expectation ", metric, " vs ", exp_seen[res.idx].expect);
+ return false;
+ } else if (res.kind == e_Matched) {
+ exp_seen[res.idx].seen := exp_seen[res.idx].seen + 1;
+ }
+ }
+
+ /* Check if all expected metrics were received */
+ seen_all := true;
+ for (var integer i := 0; i < lengthof(exp_seen); i := i + 1) {
+ /* We're still missing some expects, keep looking */
+ if (exp_seen[i].seen == 0) {
+ seen_all := false;
+ break;
+ }
+ }
+ }
+
+ T_statsd.stop;
+ return seen_all;
+}
+
+function f_init_statsd(charstring id, inout StatsD_Checker_CT vc_STATSD, charstring local_addr, integer local_port) {
+ id := id & "-STATS";
+
+ vc_STATSD := StatsD_Checker_CT.create(id);
+ vc_STATSD.start(StatsD_Checker.main(local_addr, local_port));
+}
+
+
+/* StatsD connhdlr */
+function f_statsd_reset() runs on StatsD_ConnHdlr {
+ if (not mp_enable_stats) {
+ return;
+ }
+
+ STATSD_PROC.call(STATSD_reset:{}) {
+ [] STATSD_PROC.getreply(STATSD_reset:{}) {}
+ }
+}
+
+function f_statsd_expect(StatsDExpects expects) runs on StatsD_ConnHdlr return boolean {
+ var boolean res;
+
+ if (not mp_enable_stats) {
+ return true;
+ }
+
+ STATSD_PROC.call(STATSD_expect:{expects}) {
+ [] STATSD_PROC.getreply(STATSD_expect:{expects}) -> value res;
+ }
+ return res;
+}
+
+}
diff --git a/library/StatsD_CodecPort.ttcn b/library/StatsD_CodecPort.ttcn
new file mode 100644
index 00000000..e7396b56
--- /dev/null
+++ b/library/StatsD_CodecPort.ttcn
@@ -0,0 +1,57 @@
+module StatsD_CodecPort {
+
+import from StatsD_Types all;
+import from IPL4asp_PortType all;
+import from IPL4asp_Types all;
+
+type record StatsD_RecvFrom {
+ ConnectionId connId,
+ HostName remName,
+ PortNumber remPort,
+ HostName locName,
+ PortNumber locPort,
+ StatsDMessage msg
+}
+
+template StatsD_RecvFrom tr_StatsD_RecvFrom(template ConnectionId cid, template StatsDMessage msg) := {
+ connId := cid,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := msg
+}
+
+type record StatsD_Send {
+ ConnectionId connId,
+ StatsDMessage msg
+}
+
+private function IPL4_to_StatsD_RecvFrom(in ASP_RecvFrom pin, out StatsD_RecvFrom pout) {
+ pout.connId := pin.connId;
+ pout.remName := pin.remName;
+ pout.remPort := pin.remPort;
+ pout.locName := pin.locName;
+ pout.locPort := pin.locPort;
+ pout.msg := dec_StatsDMessage(oct2char(pin.msg));
+} with { extension "prototype(fast)" };
+
+private function StatsD_to_IPL4_Send(in StatsD_Send pin, out ASP_Send pout) {
+ pout.connId := pin.connId;
+ pout.proto := { udp := {} };
+ pout.msg := char2oct(enc_StatsDMessage(pin.msg));
+} with { extension "prototype(fast)" };
+
+type port STATSD_CODEC_PT message {
+ out StatsD_Send;
+ in StatsD_RecvFrom,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+} with { extension "user IPL4asp_PT
+ out(StatsD_Send -> ASP_Send: function(StatsD_to_IPL4_Send))
+ in(ASP_RecvFrom -> StatsD_RecvFrom: function(IPL4_to_StatsD_RecvFrom);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)"
+}
+
+}
diff --git a/library/StatsD_CodecPort_CtrlFunct.ttcn b/library/StatsD_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..b2927c34
--- /dev/null
+++ b/library/StatsD_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,43 @@
+module StatsD_CodecPort_CtrlFunct {
+
+import from StatsD_CodecPort all;
+import from IPL4asp_Types all;
+
+external function f_IPL4_listen(
+ inout STATSD_CODEC_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+) return Result;
+
+external function f_IPL4_connect(
+ inout STATSD_CODEC_PT portRef,
+ in HostName remName,
+ in PortNumber remPort,
+ in HostName locName,
+ in PortNumber locPort,
+ in ConnectionId connId,
+ in ProtoTuple proto,
+ in OptionList options := {}
+) return Result;
+
+external function f_IPL4_close(
+ inout STATSD_CODEC_PT portRef,
+ in ConnectionId id,
+ in ProtoTuple proto := { unspecified := {} }
+) return Result;
+
+external function f_IPL4_setUserData(
+ inout STATSD_CODEC_PT portRef,
+ in ConnectionId id,
+ in UserData userData
+) return Result;
+
+external function f_IPL4_getUserData(
+ inout STATSD_CODEC_PT portRef,
+ in ConnectionId id,
+ out UserData userData
+) return Result;
+
+}
diff --git a/library/StatsD_CodecPort_CtrlFunctdef.cc b/library/StatsD_CodecPort_CtrlFunctdef.cc
new file mode 100644
index 00000000..1b78a7ea
--- /dev/null
+++ b/library/StatsD_CodecPort_CtrlFunctdef.cc
@@ -0,0 +1,55 @@
+#include "IPL4asp_PortType.hh"
+#include "IPL4asp_PT.hh"
+#include "StatsD_CodecPort.hh"
+
+namespace StatsD__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__IPL4__listen(
+ StatsD__CodecPort::STATSD__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__connect(
+ StatsD__CodecPort::STATSD__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& remName,
+ const IPL4asp__Types::PortNumber& remPort,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+ locName, locPort, connId, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__close(
+ StatsD__CodecPort::STATSD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto)
+ {
+ return f__IPL4__PROVIDER__close(portRef, connId, proto);
+ }
+
+ IPL4asp__Types::Result f__IPL4__setUserData(
+ StatsD__CodecPort::STATSD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+ }
+
+ IPL4asp__Types::Result f__IPL4__getUserData(
+ StatsD__CodecPort::STATSD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+ }
+
+}
diff --git a/library/StatsD_Types.ttcn b/library/StatsD_Types.ttcn
new file mode 100644
index 00000000..89385711
--- /dev/null
+++ b/library/StatsD_Types.ttcn
@@ -0,0 +1,65 @@
+module StatsD_Types {
+
+/* Definition of abstract types for the StatsD protocol. USes the TITAN "TEXT"
+ * codec to auto-generate encoder/decoder functions
+ *
+ * (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All rights reserved.
+ *
+ * Author: Daniel Willmann <dwillmann@sysmocom.de>
+ *
+ * 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
+ */
+
+type charstring MetricName with {
+ variant "END(':')";
+};
+
+type integer MetricValue with {
+ variant "END('|', '\|#(1)')";
+};
+
+type charstring MetricType (pattern "(g|c|ms|h|m)");
+
+type charstring MetricSampleRate (pattern "\d.\d+") with {
+ variant "BEGIN('|@')"
+};
+
+type record StatsDMetric {
+ MetricName name,
+ MetricValue val,
+ MetricType mtype,
+ MetricSampleRate srate optional
+};
+
+type record of StatsDMetric StatsDMessage with {
+ variant "SEPARATOR('\n')";
+};
+
+external function enc_StatsDMessage(in StatsDMessage id) return charstring
+with { extension "prototype(convert) encode(TEXT)"};
+
+external function dec_StatsDMessage(in charstring id) return StatsDMessage
+with { extension "prototype(convert) decode(TEXT)"};
+
+template StatsDMessage tr_StatsDMsg1(template StatsDMetric metric) := {
+ [0] := metric
+}
+
+template (present) StatsDMetric tr_StatsDMetric(template (present) MetricName name, template (present) MetricValue val := ?,
+ template (present) MetricType mtype) := {
+ name := name,
+ val := val,
+ mtype := mtype,
+ srate := *
+}
+
+template (present) StatsDMetric tr_StatsDMetricCounter(template (present) MetricName name, template (present) MetricValue val := ?) :=
+ tr_StatsDMetric(name, val, "c");
+
+template (present) StatsDMetric tr_StatsDMetricGauge(template (present) MetricName name, template (present) MetricValue val := ?) :=
+ tr_StatsDMetric(name, val, "g");
+
+} with { encode "TEXT" }
diff --git a/library/TRXC_CodecPort.ttcn b/library/TRXC_CodecPort.ttcn
index 09b29775..bb2193fd 100644
--- a/library/TRXC_CodecPort.ttcn
+++ b/library/TRXC_CodecPort.ttcn
@@ -59,7 +59,8 @@ template (value) TRXC_Send ts_TRXC_Send(ConnectionId cid, template (value) TrxcM
msg := msg
}
-function f_TRXC_transceive(TRXC_CODEC_PT pt, ConnectionId conn_id, TrxcMessage tx,
+function f_TRXC_transceive(TRXC_CODEC_PT pt, ConnectionId conn_id,
+ template (value) TrxcMessage tx,
template TrxcMessage tr := ?) return TrxcMessage {
var TRXC_RecvFrom rf;
timer T := 3.0;
diff --git a/library/TRXC_Types.ttcn b/library/TRXC_Types.ttcn
index b67243ba..aaa58eec 100644
--- a/library/TRXC_Types.ttcn
+++ b/library/TRXC_Types.ttcn
@@ -19,9 +19,9 @@ type charstring TrxcType ("CMD", "RSP", "IND") with {
type charstring TrxcVerb ("POWERON", "POWEROFF", "CLOCK",
"RXTUNE", "TXTUNE", "SETSLOT", "SETTSC", "SETBSIC", "SETPOWER",
"SETMAXDLY", "SETMAXDLYNB", "SETSLOT", "HANDOVER", "NOHANDOVER",
- "MEASURE", "FAKE_RSSI", "FAKE_TOA", "FAKE_CI" ) with {
+ "MEASURE", "FAKE_RSSI", "FAKE_TOA", "FAKE_CI", "FAKE_TRXC_DELAY") with {
variant "TEXT_CODING(,convert=upper_case,
- '((POWERON)|(POWEROFF)|(CLOCK)|(RXTUNE)|(TXTUNE)|(SETSLOT)|(SETTSC)|(SETBSIC)|(SETPOWER)|(SETMAXDLY)|(SETMAXDLYNB)|(HANDOVER)|(NOHANDOVER)|(MEASURE)|(FAKE_RSSI)|(FAKE_TOA)|(FAKE_CI))'
+ '((POWERON)|(POWEROFF)|(CLOCK)|(RXTUNE)|(TXTUNE)|(SETSLOT)|(SETTSC)|(SETBSIC)|(SETPOWER)|(SETMAXDLY)|(SETMAXDLYNB)|(HANDOVER)|(NOHANDOVER)|(MEASURE)|(FAKE_RSSI)|(FAKE_TOA)|(FAKE_CI)|(FAKE_TRXC_DELAY))'
,case_insensitive)"
}
@@ -93,5 +93,12 @@ template (value) TrxcMessage ts_TRXC_FAKE_CI(int16_t ci, int16_t thresh := 0) :=
}
}
+template (value) TrxcMessage ts_TRXC_FAKE_TRXC_DELAY(integer delay_ms := 0) := {
+ cmd := {
+ verb := "FAKE_TRXC_DELAY",
+ params := { int2str(delay_ms) }
+ }
+}
+
} with { encode "TEXT" }
diff --git a/library/euicc/PEDefinitions.asn b/library/euicc/PEDefinitions.asn
new file mode 100644
index 00000000..38823dff
--- /dev/null
+++ b/library/euicc/PEDefinitions.asn
@@ -0,0 +1,1128 @@
+PEDefinitions {joint-iso-itu-t(2) international-organizations(23) tca(143) euicc-profile(1) spec-version(1) version-three(3)}
+DEFINITIONS
+AUTOMATIC TAGS
+EXTENSIBILITY IMPLIED ::=
+BEGIN
+EXPORTS UICCCapability; -- Definition to be used in remote provisioning specifications for eligibility check
+
+-- Basic integer types, for size constraints
+maxUInt8 INTEGER ::= 255
+UInt8 ::= INTEGER (0..maxUInt8)
+maxUInt15 INTEGER ::= 32767
+UInt15 ::= INTEGER (0..maxUInt15)
+maxUInt16 INTEGER ::= 65535
+UInt16 ::= INTEGER (0..maxUInt16)
+maxUInt31 INTEGER ::= 2147483647
+UInt31 ::= INTEGER (0..maxUInt31)
+
+ApplicationIdentifier ::= OCTET STRING (SIZE(5..16))
+
+PEHeader ::= SEQUENCE {
+mandated NULL OPTIONAL,
+-- if set, indicate that the support of this PE is mandatory
+identification UInt15 -- Identification number of this PE
+}
+
+ProfileElement ::= CHOICE {
+ header ProfileHeader,
+
+/* PEs */
+ genericFileManagement PE-GenericFileManagement,
+ pinCodes PE-PINCodes,
+ pukCodes PE-PUKCodes,
+ akaParameter PE-AKAParameter,
+ cdmaParameter PE-CDMAParameter,
+ securityDomain PE-SecurityDomain,
+ rfm PE-RFM,
+ application PE-Application,
+ nonStandard PE-NonStandard,
+ end PE-End,
+ rfu1 PE-Dummy, -- this avoids renumbering of tag values
+ rfu2 PE-Dummy, -- in case other non-file-system PEs are
+ rfu3 PE-Dummy, -- added here in future versions
+ rfu4 PE-Dummy,
+ rfu5 PE-Dummy,
+
+/* PEs related to file system creation using templates defined in this specification */
+ mf PE-MF,
+ cd PE-CD,
+ telecom PE-TELECOM,
+ usim PE-USIM,
+ opt-usim PE-OPT-USIM,
+ isim PE-ISIM,
+ opt-isim PE-OPT-ISIM,
+ phonebook PE-PHONEBOOK,
+ gsm-access PE-GSM-ACCESS,
+ csim PE-CSIM,
+ opt-csim PE-OPT-CSIM,
+ eap PE-EAP,
+ df-5gs PE-DF-5GS,
+ df-saip PE-DF-SAIP,
+ df-snpn PE-DF-SNPN,
+ df-5gprose PE-DF-5GPROSE,
+ iot PE-IoT,
+ opt-iot PE-OPT-IoT,
+...
+}
+
+PE-Dummy ::= SEQUENCE {
+}
+
+ProfileHeader ::= SEQUENCE {
+major-version UInt8, -- set to 3 for this version of the specification
+minor-version UInt8, -- set to 3 for this version of the specification
+profileType UTF8String (SIZE (1..100)) OPTIONAL, -- Profile type
+iccid OCTET STRING (SIZE (10)), -- ICCID of the Profile
+pol OCTET STRING OPTIONAL,
+eUICC-Mandatory-services ServicesList,
+eUICC-Mandatory-GFSTEList SEQUENCE OF OBJECT IDENTIFIER,
+connectivityParameters OCTET STRING OPTIONAL,
+eUICC-Mandatory-AIDs SEQUENCE OF SEQUENCE {
+ aid ApplicationIdentifier,
+ version OCTET STRING (SIZE(2))
+} OPTIONAL,
+iotOptions IotOptions OPTIONAL -- details for IoT Minimal Profile, mandatory for IoT Minimal Profiles
+}
+
+IotOptions ::= SEQUENCE {
+pix OCTET STRING (SIZE (7..11)) -- PIX value to be used for IoT Minimal Profiles
+}
+
+ServicesList ::= SEQUENCE {
+/* Contactless */
+contactless NULL OPTIONAL,
+
+/* NAAs */
+usim NULL OPTIONAL,
+isim NULL OPTIONAL,
+csim NULL OPTIONAL,
+
+/* NAA algorithms */
+milenage NULL OPTIONAL,
+tuak128 NULL OPTIONAL,
+cave NULL OPTIONAL,
+
+/* USIM/ISIM services */
+gba-usim NULL OPTIONAL,
+gba-isim NULL OPTIONAL,
+mbms NULL OPTIONAL,
+
+/* EAP service */
+eap NULL OPTIONAL,
+
+/* Application Runtime environment */
+ javacard NULL OPTIONAL,
+ multos NULL OPTIONAL,
+
+/* NAAs */
+multiple-usim NULL OPTIONAL,
+multiple-isim NULL OPTIONAL,
+multiple-csim NULL OPTIONAL,
+
+/* Additional algorithms */
+tuak256 NULL OPTIONAL,
+usim-test-algorithm NULL OPTIONAL,
+
+/* File type */
+ber-tlv NULL OPTIONAL,
+
+/* Linked files */
+dfLink NULL OPTIONAL,
+
+/* Support of CAT_TP */
+cat-tp NULL OPTIONAL,
+
+/* Support of 5G */
+get-identity NULL OPTIONAL,
+profile-a-x25519 NULL OPTIONAL,
+profile-b-p256 NULL OPTIONAL,
+suciCalculatorApi NULL OPTIONAL,
+
+/* Support of DNS Resolution */
+dns-resolution NULL OPTIONAL,
+
+/* Support of GP Amd F SCP11 */
+scp11ac NULL OPTIONAL,
+scp11c-authorization-mechanism NULL OPTIONAL,
+
+/* Support of S16 mode as defined in GP Amd D and Amd F */
+s16mode NULL OPTIONAL,
+
+/* Support of enhanced AKA algorithm defined in 3GPP */
+eaka NULL OPTIONAL
+}
+
+-- Definition of UICCCapability
+UICCCapability ::= BIT STRING {
+ contactlessSupport(0), -- Contactless (SWP, HCI and associated APIs)
+ usimSupport(1), -- USIM as defined by 3GPP
+ isimSupport(2), -- ISIM as defined by 3GPP
+ csimSupport(3), -- CSIM as defined by 3GPP2
+
+ akaMilenage(4), -- Milenage as AKA algorithm
+ akaCave(5), -- CAVE as authentication algorithm
+ akaTuak128(6), -- TUAK as AKA algorithm with 128 bit key length
+ akaTuak256(7), -- TUAK as AKA algorithm with 256 bit key length
+ usimTestAlgorithm(8), -- USIM test algorithm
+ rfu2(9), -- reserved for further algorithms
+
+ gbaAuthenUsim(10), -- GBA authentication in the context of USIM
+ gbaAuthenISim(11), -- GBA authentication in the context of ISIM
+ mbmsAuthenUsim(12), -- MBMS authentication in the context of USIM
+ eapClient(13), -- EAP client
+
+ javacard(14), -- Java Card(TM) support
+ multos(15), -- Multos support
+
+ multipleUsimSupport(16), -- Multiple USIM applications are supported within the same Profile
+ multipleIsimSupport(17), -- Multiple ISIM applications are supported within the same Profile
+ multipleCsimSupport(18), -- Multiple CSIM applications are supported within the same Profile
+
+ berTlvFileSupport(19), -- BER TLV files
+ dfLinkSupport(20), -- Linked Directory Files
+ catTp(21), -- Support of CAT TP
+ getIdentity(22), -- Support of the GET IDENTITY command as defined in ETSI TS 102 221
+ profile-a-x25519(23), -- Support of ECIES Profile A as defined in 3GPP TS 33.501 [87]
+ profile-b-p256(24), -- Support of ECIES Profile B as defined in 3GPP TS 33.501 [87]
+ suciCalculatorApi(25), -- Support of the associated API for SUCI derivation as defined in 3GPP 31.130 [31.130]
+ dns-resolution(26), -- Support of DNS Resolution as defined by GP Amd B
+ scp11ac(27), -- Support of GP Amd F SCP11 variants a and c
+ scp11c-authorization-mechanism(28), -- Support of SCP11c authorization mechanism (Tag 'BF20')
+ s16mode(29), -- Support of S16 mode as defined in GP Amd D and Amd F
+ eaka(30), -- Support of enhanced AKA algorithm as defined in 3GPP TS [33.102]
+ iotminimal(31) -- Support of IoT Minimal Profile as described in section 7.5
+}
+
+ProprietaryInfo ::= SEQUENCE {
+ specialFileInformation [PRIVATE 0] OCTET STRING (SIZE (1)) DEFAULT '00'H,
+
+ /* fillPattern, repeatPattern
+ only one of the parameters may be present. Coding and rules defined within ETSI TS 102 222 [102 222] apply
+ */
+
+ fillPattern [PRIVATE 1] OCTET STRING (SIZE(1..200)) OPTIONAL,
+ repeatPattern [PRIVATE 2] OCTET STRING (SIZE(1..200)) OPTIONAL,
+ /* Specific parameters for BER-TLV files */
+ /* Shall be encoded on the minimum number of octets possible
+ (i.e. no leading bytes set to '00' are allowed)*/
+ maximumFileSize [6] OCTET STRING OPTIONAL,
+ fileDetails [4] OCTET STRING (SIZE(1)) DEFAULT '01'H
+}
+
+Fcp ::= SEQUENCE {
+ /* The fileDescriptor shall be encoded as defined in
+ ETSI TS 102 222 [102 222]
+ */
+ fileDescriptor [2] OCTET STRING (SIZE(2..4)) OPTIONAL,
+
+ /* fileID
+ For ADFs, the fileID is a temporary value (named temporary file ID
+ in this document) used only during the profile creation. It has to
+ be unique within a profile and is used for referencing files within
+ this ADF using the file path.
+ */
+ fileID [3] OCTET STRING (SIZE(2)) OPTIONAL,
+
+ /* dfName
+ Only applies for ADFs
+ */
+ dfName [4] ApplicationIdentifier OPTIONAL,
+
+ /* lcsi
+ Coding according to ETSI TS 102 222 [102 222]
+ */
+ lcsi [10] OCTET STRING (SIZE (1)) DEFAULT '05'H,
+
+ /* securityAttributesReferenced
+ Either containing EF ARR ID[2] + record number[1] or
+ record number[1] only and EF ARR ID implicitly known from the
+ context: File ID 2F06 is automatically applied for ADFs,
+ the MF and all files directly located under the MF
+ '6F06' for any other files
+ */
+ securityAttributesReferenced [11] OCTET STRING (SIZE (1..3)) OPTIONAL,
+
+ /* efFileSize
+ Mandatory for EF file types
+ Not allowed for DF files and EF link files
+ Shall be encoded on the minimum number of octets possible
+ (i.e. no leading bytes set to '00' are allowed)
+ */
+ efFileSize [0] OCTET STRING OPTIONAL,
+
+ /* pinStatusTemplateDO
+ Not allowed for EF files
+ Mandatory for DF/ADF files
+ */
+ pinStatusTemplateDO [PRIVATE 6] OCTET STRING OPTIONAL,
+
+ /* shortEFID
+ Not allowed for DF files
+ Optional for EF file types / equivalent to ETSI TS 102 222
+ shortEFID not provided: in case of a template file, SFI
+ is set according to Annex A. For files created
+ by using GenericFileManagement, SFI is calculated from FID
+ shortEFID provided with no value: no SFI is supported
+ for this EF
+ shortEFID available with a length of 1 byte:
+ The Short File Identifier is coded from bits b8 to b4.
+ Bits b3,b2,b1 = 000.
+ */
+ shortEFID [8] OCTET STRING (SIZE (0..1)) OPTIONAL,
+
+ /* proprietaryEFInfo
+ Optional for EF file types
+ Not allowed for DF files
+ */
+ proprietaryEFInfo [5] ProprietaryInfo OPTIONAL,
+
+ /* linkPath
+ Specifies the path to the file to which shall be linked,
+ also valid for DFs. Files within ADFs are addressed
+ by the temporary file ID of the respective ADF. For the coding
+ see filePath. In case of a template link file, an empty linkPath indicates that the link file shall be turned into an independent file.
+ */
+ linkPath [PRIVATE 7] OCTET STRING (SIZE (0..8)) OPTIONAL
+}
+
+File ::= SEQUENCE OF CHOICE {
+ doNotCreate NULL, /* Indicates that this file shall not be created by the eUICC even if present in a PE referencing a "Created by Default" template.
+This flag has no effect for the creation of files in the MF and shall not be used for all the files listed in a "Not Created by Default" template*/
+ fileDescriptor Fcp,
+ fillFileOffset UInt16,
+ fillFileContent OCTET STRING
+}
+
+PE-MF ::= SEQUENCE {
+mf-header PEHeader,
+templateID OBJECT IDENTIFIER,
+mf File,
+ef-pl File OPTIONAL,
+ef-iccid File,
+ef-dir File,
+ef-arr File,
+ef-umpc File OPTIONAL
+}
+
+PE-CD ::= SEQUENCE {
+cd-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-cd File,
+ef-launchpad File OPTIONAL,
+ef-icon File OPTIONAL
+}
+
+PE-TELECOM ::= SEQUENCE {
+telecom-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-telecom File,
+ef-arr File OPTIONAL,
+ef-rma File OPTIONAL,
+ef-sume File OPTIONAL,
+ef-ice-dn File OPTIONAL,
+ef-ice-ff File OPTIONAL,
+ef-psismsc File OPTIONAL,
+df-graphics File OPTIONAL,
+ ef-img File OPTIONAL,
+ ef-iidf File OPTIONAL,
+ ef-ice-graphics File OPTIONAL,
+ ef-launch-scws File OPTIONAL,
+ ef-icon File OPTIONAL,
+df-phonebook File OPTIONAL,
+ ef-pbr File OPTIONAL,
+ ef-ext1 File OPTIONAL,
+ ef-aas File OPTIONAL,
+ ef-gas File OPTIONAL,
+ ef-psc File OPTIONAL,
+ ef-cc File OPTIONAL,
+ ef-puid File OPTIONAL,
+ ef-iap File OPTIONAL,
+ ef-adn File OPTIONAL,
+ ef-pbc File OPTIONAL,
+ ef-anr File OPTIONAL,
+ ef-puri File OPTIONAL,
+ ef-email File OPTIONAL,
+ ef-sne File OPTIONAL,
+ ef-uid File OPTIONAL,
+ ef-grp File OPTIONAL,
+ ef-ccp1 File OPTIONAL,
+df-multimedia File OPTIONAL,
+ ef-mml File OPTIONAL,
+ ef-mmdf File OPTIONAL,
+df-mmss File OPTIONAL,
+ ef-mlpl File OPTIONAL,
+ ef-mspl File OPTIONAL,
+ ef-mmssmode File OPTIONAL,
+df-mcs File OPTIONAL,
+ ef-mst File OPTIONAL,
+ ef-mcs-config File OPTIONAL,
+df-v2x File OPTIONAL,
+ ef-vst File OPTIONAL,
+ ef-v2x-config File OPTIONAL,
+ ef-v2xp-pc5 File OPTIONAL,
+ ef-v2xp-Uu File OPTIONAL
+}
+
+PE-USIM ::= SEQUENCE {
+usim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+adf-usim File,
+ef-imsi File,
+ef-arr File,
+ef-keys File OPTIONAL,
+ef-keysPS File OPTIONAL,
+ef-hpplmn File OPTIONAL,
+ef-ust File, /* The content of UST file shall be modified by the eUICC during profile installation according to the functionality supported by the eUICC platform i.e. in the case where a service is not supported (and not indicated as required) the related bit(s) will be set to zero */
+ef-fdn File OPTIONAL,
+ef-sms File OPTIONAL,
+ef-smsp File OPTIONAL,
+ef-smss File OPTIONAL,
+ef-spn File,
+ef-est File,
+ef-start-hfn File OPTIONAL,
+ef-threshold File OPTIONAL,
+ef-psloci File OPTIONAL,
+ef-acc File,
+ef-fplmn File OPTIONAL,
+ef-loci File OPTIONAL,
+ef-ad File OPTIONAL,
+ef-ecc File,
+ef-netpar File OPTIONAL,
+ef-epsloci File OPTIONAL,
+ef-epsnsc File OPTIONAL
+}
+
+PE-OPT-USIM ::= SEQUENCE {
+optusim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+ef-li File OPTIONAL,
+ef-acmax File OPTIONAL,
+ef-acm File OPTIONAL,
+ef-gid1 File OPTIONAL,
+ef-gid2 File OPTIONAL,
+ef-msisdn File OPTIONAL,
+ef-puct File OPTIONAL,
+ef-cbmi File OPTIONAL,
+ef-cbmid File OPTIONAL,
+ef-sdn File OPTIONAL,
+ef-ext2 File OPTIONAL,
+ef-ext3 File OPTIONAL,
+ef-cbmir File OPTIONAL,
+ef-plmnwact File OPTIONAL,
+ef-oplmnwact File OPTIONAL,
+ef-hplmnwact File OPTIONAL,
+ef-dck File OPTIONAL,
+ef-cnl File OPTIONAL,
+ef-smsr File OPTIONAL,
+ef-bdn File OPTIONAL,
+ef-ext5 File OPTIONAL,
+ef-ccp2 File OPTIONAL,
+ef-ext4 File OPTIONAL,
+ef-acl File OPTIONAL,
+ef-cmi File OPTIONAL,
+ef-ici File OPTIONAL,
+ef-oci File OPTIONAL,
+ef-ict File OPTIONAL,
+ef-oct File OPTIONAL,
+ef-vgcs File OPTIONAL,
+ef-vgcss File OPTIONAL,
+ef-vbs File OPTIONAL,
+ef-vbss File OPTIONAL,
+ef-emlpp File OPTIONAL,
+ef-aaem File OPTIONAL,
+ef-hiddenkey File OPTIONAL,
+ef-pnn File OPTIONAL,
+ef-opl File OPTIONAL,
+ef-mbdn File OPTIONAL,
+ef-ext6 File OPTIONAL,
+ef-mbi File OPTIONAL,
+ef-mwis File OPTIONAL,
+ef-cfis File OPTIONAL,
+ef-ext7 File OPTIONAL,
+ef-spdi File OPTIONAL,
+ef-mmsn File OPTIONAL,
+ef-ext8 File OPTIONAL,
+ef-mmsicp File OPTIONAL,
+ef-mmsup File OPTIONAL,
+ef-mmsucp File OPTIONAL,
+ef-nia File OPTIONAL,
+ef-vgcsca File OPTIONAL,
+ef-vbsca File OPTIONAL,
+ef-gbabp File OPTIONAL,
+ef-msk File OPTIONAL,
+ef-muk File OPTIONAL,
+ef-ehplmn File OPTIONAL,
+ef-gbanl File OPTIONAL,
+ef-ehplmnpi File OPTIONAL,
+ef-lrplmnsi File OPTIONAL,
+ef-nafkca File OPTIONAL,
+ef-spni File OPTIONAL,
+ef-pnni File OPTIONAL,
+ef-ncp-ip File OPTIONAL,
+ef-ufc File OPTIONAL,
+ef-nasconfig File OPTIONAL,
+ef-uicciari File OPTIONAL,
+ef-pws File OPTIONAL,
+ef-fdnuri File OPTIONAL,
+ef-bdnuri File OPTIONAL,
+ef-sdnuri File OPTIONAL,
+ef-ial File OPTIONAL, -- This file was known as ef-iwl in Version 3.2 and earlier of this specification
+ef-ips File OPTIONAL,
+ef-ipd File OPTIONAL,
+ef-epdgid File OPTIONAL,
+ef-epdgselection File OPTIONAL,
+ef-epdgidem File OPTIONAL,
+ef-epdgselectionem File OPTIONAL,
+ef-frompreferred File OPTIONAL,
+ef-imsconfigdata File OPTIONAL,
+ef-3gpppsdataoff File OPTIONAL,
+ef-3gpppsdataoffservicelist File OPTIONAL,
+ef-xcapconfigdata File OPTIONAL,
+ef-earfcnlist File OPTIONAL,
+ef-mudmidconfigdata File OPTIONAL,
+ef-eaka File OPTIONAL
+}
+
+PE-PHONEBOOK ::= SEQUENCE {
+phonebook-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-phonebook File,
+ef-pbr File OPTIONAL,
+ef-ext1 File OPTIONAL,
+ef-aas File OPTIONAL,
+ef-gas File OPTIONAL,
+ef-psc File OPTIONAL,
+ef-cc File OPTIONAL,
+ef-puid File OPTIONAL,
+ef-iap File OPTIONAL,
+ef-adn File OPTIONAL,
+ef-pbc File OPTIONAL,
+ef-anr File OPTIONAL,
+ef-puri File OPTIONAL,
+ef-email File OPTIONAL,
+ef-sne File OPTIONAL,
+ef-uid File OPTIONAL,
+ef-grp File OPTIONAL,
+ef-ccp1 File OPTIONAL
+}
+
+PE-GSM-ACCESS ::= SEQUENCE {
+gsm-access-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-gsm-access File,
+ef-kc File OPTIONAL,
+ef-kcgprs File OPTIONAL,
+ef-cpbcch File OPTIONAL,
+ef-invscan File OPTIONAL
+}
+
+PE-DF-5GS ::= SEQUENCE {
+df-5gs-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-df-5gs File,
+ef-5gs3gpploci File OPTIONAL,
+ef-5gsn3gpploci File OPTIONAL,
+ef-5gs3gppnsc File OPTIONAL,
+ef-5gsn3gppnsc File OPTIONAL,
+ef-5gauthkeys File OPTIONAL,
+ef-uac-aic File OPTIONAL,
+ef-suci-calc-info File OPTIONAL,
+ef-opl5g File OPTIONAL,
+ef-supinai File OPTIONAL,
+ef-routing-indicator File OPTIONAL,
+ef-ursp File OPTIONAL,
+ef-tn3gppsnn File OPTIONAL,
+ef-cag File OPTIONAL,
+ef-sor-cmci File OPTIONAL,
+ef-dri File OPTIONAL,
+ef-5gsedrx File OPTIONAL,
+ef-5gnswo-conf File OPTIONAL,
+ef-mchpplmn File OPTIONAL,
+ef-kausf-derivation File OPTIONAL
+}
+
+PE-DF-SAIP ::= SEQUENCE {
+df-saip-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-df-saip File,
+ef-suci-calc-info-usim File OPTIONAL
+}
+
+PE-DF-SNPN ::= SEQUENCE {
+df-snpn-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-df-snpn File,
+ef-pws-snpn File OPTIONAL
+}
+
+PE-DF-5GPROSE ::= SEQUENCE {
+df-5g-prose-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-df-5g-prose File,
+ef-5g-prose-st File OPTIONAL,
+ef-5g-prose-dd File OPTIONAL,
+ef-5g-prose-dc File OPTIONAL,
+ef-5g-prose-u2nru File OPTIONAL,
+ef-5g-prose-ru File OPTIONAL,
+ef-5g-prose-uir File OPTIONAL
+}
+
+PE-ISIM ::= SEQUENCE {
+isim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+adf-isim File,
+ef-impi File,
+ef-impu File,
+ef-domain File,
+ef-ist File, /* The content of IST file shall be modified by the eUICC during profile installation according to the functionality supported by the eUICC platform i.e. in the case where a service is not supported (and not indicated as required) the related bit(s) will be set to zero */
+ef-ad File OPTIONAL,
+ef-arr File
+}
+
+PE-OPT-ISIM ::= SEQUENCE {
+optisim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+ef-pcscf File OPTIONAL,
+ef-sms File OPTIONAL,
+ef-smsp File OPTIONAL,
+ef-smss File OPTIONAL,
+ef-smsr File OPTIONAL,
+ef-gbabp File OPTIONAL,
+ef-gbanl File OPTIONAL,
+ef-nafkca File OPTIONAL,
+ef-uicciari File OPTIONAL,
+ef-frompreferred File OPTIONAL,
+ef-imsconfigdata File OPTIONAL,
+ef-xcapconfigdata File OPTIONAL,
+ef-webrtcuri File OPTIONAL,
+ef-mudmidconfigdata File OPTIONAL
+}
+
+PE-CSIM ::= SEQUENCE {
+csim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+adf-csim File,
+ef-arr File,
+ef-call-count File,
+ef-imsi-m File,
+ef-imsi-t File,
+ef-tmsi File,
+ef-ah File,
+ef-aop File,
+ef-aloc File,
+ef-cdmahome File,
+ef-znregi File,
+ef-snregi File,
+ef-distregi File,
+ef-accolc File,
+ef-term File,
+ef-acp File,
+ef-prl File,
+ef-ruimid File,
+ef-csim-st File,
+ef-spc File,
+ef-otapaspc File,
+ef-namlock File,
+ef-ota File,
+ef-sp File,
+ef-esn-meid-me File,
+ef-li File,
+ef-usgind File,
+ef-ad File,
+ef-max-prl File,
+ef-spcs File,
+ef-mecrp File,
+ef-home-tag File,
+ef-group-tag File,
+ef-specific-tag File,
+ef-call-prompt File
+}
+
+PE-OPT-CSIM ::= SEQUENCE {
+optcsim-header PEHeader,
+templateID OBJECT IDENTIFIER,
+ef-ssci File OPTIONAL,
+ef-fdn File OPTIONAL,
+ef-sms File OPTIONAL,
+ef-smsp File OPTIONAL,
+ef-smss File OPTIONAL,
+ef-ssfc File OPTIONAL,
+ef-spn File OPTIONAL,
+ef-mdn File OPTIONAL,
+ef-ecc File OPTIONAL,
+ef-me3gpdopc File OPTIONAL,
+ef-3gpdopm File OPTIONAL,
+ef-sipcap File OPTIONAL,
+ef-mipcap File OPTIONAL,
+ef-sipupp File OPTIONAL,
+ef-mipupp File OPTIONAL,
+ef-sipsp File OPTIONAL,
+ef-mipsp File OPTIONAL,
+ef-sippapss File OPTIONAL,
+ef-puzl File OPTIONAL,
+ef-maxpuzl File OPTIONAL,
+ef-hrpdcap File OPTIONAL,
+ef-hrpdupp File OPTIONAL,
+ef-csspr File OPTIONAL,
+ef-atc File OPTIONAL,
+ef-eprl File OPTIONAL,
+ef-bcsmscfg File OPTIONAL,
+ef-bcsmspref File OPTIONAL,
+ef-bcsmstable File OPTIONAL,
+ef-bcsmsp File OPTIONAL,
+ef-bakpara File OPTIONAL,
+ef-upbakpara File OPTIONAL,
+ef-mmsn File OPTIONAL,
+ef-ext8 File OPTIONAL,
+ef-mmsicp File OPTIONAL,
+ef-mmsup File OPTIONAL,
+ef-mmsucp File OPTIONAL,
+ef-auth-capability File OPTIONAL,
+ef-3gcik File OPTIONAL,
+ef-dck File OPTIONAL,
+ef-gid1 File OPTIONAL,
+ef-gid2 File OPTIONAL,
+ef-cdmacnl File OPTIONAL,
+ef-sf-euimid File OPTIONAL,
+ef-est File OPTIONAL,
+ef-hidden-key File OPTIONAL,
+ef-lcsver File OPTIONAL,
+ef-lcscp File OPTIONAL,
+ef-sdn File OPTIONAL,
+ef-ext2 File OPTIONAL,
+ef-ext3 File OPTIONAL,
+ef-ici File OPTIONAL,
+ef-oci File OPTIONAL,
+ef-ext5 File OPTIONAL,
+ef-ccp2 File OPTIONAL,
+ef-applabels File OPTIONAL,
+ef-model File OPTIONAL,
+ef-rc File OPTIONAL,
+ef-smscap File OPTIONAL,
+ef-mipflags File OPTIONAL,
+ef-3gpduppext File OPTIONAL,
+ef-ipv6cap File OPTIONAL,
+ef-tcpconfig File OPTIONAL,
+ef-dgc File OPTIONAL,
+ef-wapbrowsercp File OPTIONAL,
+ef-wapbrowserbm File OPTIONAL,
+ef-mmsconfig File OPTIONAL,
+ef-jdl File OPTIONAL
+}
+
+PE-EAP ::= SEQUENCE {
+eap-header PEHeader,
+templateID OBJECT IDENTIFIER,
+df-eap File,
+ef-eapkeys File OPTIONAL,
+ef-eapstatus File,
+ef-puid File OPTIONAL,
+ef-ps File OPTIONAL,
+ef-curid File OPTIONAL,
+ef-reid File OPTIONAL,
+ef-realm File OPTIONAL
+}
+
+PE-IoT ::= SEQUENCE {
+iot-header PEHeader,
+templateID OBJECT IDENTIFIER,
+mf File OPTIONAL,
+ef-pl File OPTIONAL,
+ef-iccid File OPTIONAL,
+ef-dir File OPTIONAL,
+ef-arr File OPTIONAL,
+ef-umpc File OPTIONAL,
+adf-usim File OPTIONAL,
+ef-imsi File,
+ef-arr-usim File OPTIONAL,
+ef-keys File OPTIONAL,
+ef-keysPS File OPTIONAL,
+ef-hpplmn File OPTIONAL,
+ef-ust File OPTIONAL,
+ef-start-hfn File OPTIONAL,
+ef-threshold File OPTIONAL,
+ef-psloci File OPTIONAL,
+ef-acc File,
+ef-fplmn File OPTIONAL,
+ef-loci File OPTIONAL,
+ef-ad File OPTIONAL,
+ef-ecc File OPTIONAL,
+ef-netpar File OPTIONAL
+}
+
+PE-OPT-IoT ::= SEQUENCE {
+optiot-header PEHeader,
+templateID OBJECT IDENTIFIER,
+ef-fdn File OPTIONAL,
+ef-sms File OPTIONAL,
+ef-smsp File OPTIONAL,
+ef-smss File OPTIONAL,
+ef-spn File OPTIONAL,
+ef-est File OPTIONAL,
+ef-oplmnwact File OPTIONAL,
+ef-hplmnwact File OPTIONAL,
+ef-ehplmn File OPTIONAL,
+ef-epsloci File OPTIONAL,
+ef-epsnsc File OPTIONAL,
+df-df-5gs File OPTIONAL,
+ef-5gs3gpploci File OPTIONAL,
+ef-5gsn3gpploci File OPTIONAL,
+ef-5gs3gppnsc File OPTIONAL,
+ef-5gsn3gppnsc File OPTIONAL,
+ef-5gauthkeys File OPTIONAL,
+ef-uac-aic File OPTIONAL,
+ef-suci-calc-info File OPTIONAL,
+ef-opl5g File OPTIONAL,
+ef-supi-nai File OPTIONAL,
+ef-routing-indicator File OPTIONAL,
+ef-ursp File OPTIONAL,
+ef-tn3gppsnn File OPTIONAL,
+df-df-saip File OPTIONAL,
+ef-suci-calc-info-usim File OPTIONAL
+}
+
+/* Create GenericFileManagement
+*/
+PE-GenericFileManagement ::= SEQUENCE {
+ gfm-header PEHeader,
+ fileManagementCMD SEQUENCE (SIZE (1..MAX)) OF FileManagement
+}
+
+FileManagement ::= SEQUENCE (SIZE (1..MAX)) OF CHOICE {
+filePath [0] OCTET STRING (SIZE (0..8)), -- Use Temporary File ID for ADF
+createFCP [APPLICATION 2] Fcp,
+fillFileOffset UInt16,
+fillFileContent [1] OCTET STRING
+}
+
+MappingParameter ::= SEQUENCE {
+mappingOptions OCTET STRING (SIZE(1)),
+ mappingSource ApplicationIdentifier
+}
+
+AlgoParameter ::= SEQUENCE {
+algorithmID INTEGER {
+ milenage(1),
+ tuak(2),
+ usim-test-algorithm(3)
+},
+algorithmOptions OCTET STRING (SIZE(1)),
+key OCTET STRING,
+opc OCTET STRING, /* OPc for Milenage; TOPc for TUAK; ignored in case of usim-test-algorithm */
+
+/* rotationConstants only apply for Milenage; ignored in case of TUAK and usim-test-algorithm */
+ rotationConstants OCTET STRING (SIZE (5)) DEFAULT '4000204060'H,
+
+/* xoringConstants only apply for Milenage; ignored in case of TUAK and usim-test-algorithm */
+xoringConstants OCTET STRING (SIZE (80)) DEFAULT '0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000020000000000000000000000000000000400000000000000000000000000000008'H,
+authCounterMax OCTET STRING (SIZE(3)) OPTIONAL, /* ignored in case of usim-test-algorithm */
+
+/* Number of iterations of Keccak-f[1600] (noted: ) permutation as recommended by 3GPP TS 35.231 [TUAK] in section 7.2.
+This parameter only applies for TUAK; ignored otherwise.*/
+numberOfKeccak UInt8 DEFAULT 1
+}
+
+PE-AKAParameter ::= SEQUENCE {
+ aka-header PEHeader,
+algoConfiguration CHOICE {
+ mappingParameter MappingParameter,
+ algoParameter AlgoParameter
+},
+
+sqnOptions OCTET STRING (SIZE(1)) DEFAULT '02'H, /* ignored in case of usim-test-algorithm */
+-- maximum value for sqnDelta and sqnAgeLimit is '07FFFFFFFFFF'H
+sqnDelta OCTET STRING (SIZE(6)) DEFAULT '000010000000'H, /* ignored in case of usim-test-algorithm */
+sqnAgeLimit OCTET STRING (SIZE(6)) DEFAULT '000010000000'H, /* ignored in case of usim-test-algorithm */
+
+-- Sequence numbers do not include the index (IND)
+-- maximum for any values within sqnInit is '07FFFFFFFFFF'H
+sqnInit SEQUENCE (SIZE (32)) OF OCTET STRING (SIZE (6)) DEFAULT {
+/* Index 0 */'000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H,'000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H,'000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H,'000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H, '000000000000'H,'000000000000'H, '000000000000'H, '000000000000'H,
+/* Index 31 */'000000000000'H } /* ignored in case of usim-test-algorithm */
+}
+
+PE-CDMAParameter ::= SEQUENCE {
+ cdma-header PEHeader,
+
+/* A-Key for CAVE Authentication */
+authenticationKey OCTET STRING (SIZE(8)),
+
+/*
+Optional value for ssd
+Bytes 1..8: value if shared secret data A
+Bytes 9..16: value if shared secret data B
+*/
+ssd OCTET STRING (SIZE (16)) OPTIONAL,
+
+/*
+ Shared Secrets for HRPD access authentication
+ Includes the shared secret data. This field is coded as defined in section 4.5.7.10 HRPD Access Authentication CHAP SS Parameters of [S0016].
+*/
+hrpdAccessAuthenticationData OCTET STRING (SIZE (2..32)) OPTIONAL,
+
+/*
+ Parameters for simple IP authentication are coded as defined in section 4.5.7.7 SimpleIP CHAP SS Parameters of [S0016].
+*/
+simpleIPAuthenticationData OCTET STRING (SIZE (3..483)) OPTIONAL,
+
+/*
+ Parameters for mobile IP authentication are coded as defined in section 4.5.7.8 MobileIP SS Parameters of [S0016].
+*/
+mobileIPAuthenticationData OCTET STRING (SIZE (5..957)) OPTIONAL
+}
+
+PINKeyReferenceValue ::= INTEGER {
+pinAppl1(1), -- PIN global of App 1
+pinAppl2(2), -- PIN global of App 2
+pinAppl3(3), -- PIN global of App 3
+pinAppl4(4), -- PIN global of App 4
+pinAppl5(5), -- PIN global of App 5
+pinAppl6(6), -- PIN global of App 6
+pinAppl7(7), -- PIN global of App 7
+pinAppl8(8), -- PIN global of App 8
+adm1(10), -- Administrative Key 1
+adm2(11), -- Administrative Key 2
+adm3(12), -- Administrative Key 3
+adm4(13), -- Administrative Key 4
+adm5(14), -- Administrative Key 5
+secondPINAppl1(129), -- PIN local of App 1
+secondPINAppl2(130), -- PIN local of App 2
+secondPINAppl3(131), -- PIN local of App 3
+secondPINAppl4(132), -- PIN local of App 4
+secondPINAppl5(133), -- PIN local of App 5
+secondPINAppl6(134), -- PIN local of App 6
+secondPINAppl7(135), -- PIN local of App 7
+secondPINAppl8(136), -- PIN local of App 8
+adm6(138), -- Administrative Key 6
+adm7(139), -- Administrative Key 7
+adm8(140), -- Administrative Key 8
+adm9(141), -- Administrative Key 9
+adm10(142) -- Administrative Key 10
+}
+
+PINConfiguration ::= SEQUENCE {
+/*
+For every value defined in PINKeyReferenceValue only one entry may be included per PE-PINCodes.
+Within the PE-PINCodes sent in the context of the MF only global PIN key references shall be used. For PINs in any ADF/DF only local PINs shall be defined: secondPINAppl1 secondPINAppl8. It is allowed to define the same PINKeyReferenceValue in multiple directories (e.g. secondPINAppl1 may be defined in the ISIM NAA and within the USIM NAA). Provided they are not linked they shall be handled as two independent PIN values which also may reference different PUK references.
+*/
+ keyReference PINKeyReferenceValue,
+ pinValue OCTET STRING (SIZE (8)),
+/*
+In case no unblockingPINReference is set, no PUK applies for the corresponding PIN.
+In case a PUKKeyReferenceValue is defined the related PUKKeyReferenceValue shall exist within the PE-PUKCodes list.
+Any value defined in PUKKeyReferenceValue may be applied for any PINKeyReferenceValue.
+*/
+ unblockingPINReference PUKKeyReferenceValue OPTIONAL,
+ pinAttributes UInt8 DEFAULT 7,
+ maxNumOfAttemps-retryNumLeft UInt8 DEFAULT 51
+/* maxNumOfAttemps-retryNumLeft is encoded as follows: max Number of Attempts is encoded in the high nibble of this value (Bits b8 to b5) and the Number of retry left is encoded in the low nibble of this value (Bits b4 to b1)*/
+}
+
+PE-PINCodes ::= SEQUENCE {
+ pin-Header PEHeader,
+pinCodes CHOICE {
+ pinconfig SEQUENCE (SIZE (1..26))OF PINConfiguration,
+ filePath OCTET STRING (SIZE (0..8)) /* temporary File ID for ADF, coding according to section 8.3.5 */
+}
+/* PIN can be either defined in the current context or shared
+ with another DF/ADF
+ Up to 26 PIN could be defined according to TS 102 221 [102 221]
+*/
+}
+
+PUKKeyReferenceValue ::= INTEGER {
+pukAppl1(1), -- PUK Reference 1
+pukAppl2(2), -- PUK Reference 2
+pukAppl3(3), -- PUK Reference 3
+pukAppl4(4), -- PUK Reference 4
+pukAppl5(5), -- PUK Reference 5
+pukAppl6(6), -- PUK Reference 6
+pukAppl7(7), -- PUK Reference 7
+pukAppl8(8), -- PUK Reference 8
+secondPUKAppl1(129), -- PUK Reference 9
+secondPUKAppl2(130), -- PUK Reference 10
+secondPUKAppl3(131), -- PUK Reference 11
+secondPUKAppl4(132), -- PUK Reference 12
+secondPUKAppl5(133), -- PUK Reference 13
+secondPUKAppl6(134), -- PUK Reference 14
+secondPUKAppl7(135), -- PUK Reference 15
+secondPUKAppl8(136) -- PUK Reference 16
+}
+
+PUKConfiguration ::= SEQUENCE {
+/*
+Any PUKKeyReferenceValue shall only be defined once within PE-PUKCodes.
+*/
+ keyReference PUKKeyReferenceValue,
+ pukValue OCTET STRING (SIZE (8)),
+ maxNumOfAttemps-retryNumLeft UInt8 DEFAULT 170
+/* maxNumOfAttemps-retryNumLeft is encoded as follows: max Number of Attempts is encoded in the high nibble of this value (Bits b8 to b5) and the Number of retry left is encoded in the low nibble of this value (Bits b4 to b1)*/
+}
+
+PE-PUKCodes ::= SEQUENCE {
+ puk-Header PEHeader,
+pukCodes SEQUENCE (SIZE (1..16))OF PUKConfiguration
+}
+
+PE-SecurityDomain ::= SEQUENCE {
+ sd-Header PEHeader,
+instance ApplicationInstance, -- see section 8.7.3
+keyList SEQUENCE (SIZE (1..MAX)) OF KeyObject OPTIONAL, -- see section 8.6.3
+sdPersoData SEQUENCE (SIZE (1..MAX)) OF OCTET STRING OPTIONAL, /* see section 8.6.4 */
+openPersoData SEQUENCE {
+ restrictParameter [PRIVATE 25] OCTET STRING (SIZE(1)) OPTIONAL,
+ contactlessProtocolParameters OCTET STRING OPTIONAL
+} OPTIONAL, /* see section 8.6.6 */
+catTpParameters SEQUENCE
+{ catTpMaxSduSize UInt16,
+ catTpMaxPduSize UInt16
+} OPTIONAL -- see section 8.6.7
+}
+
+KeyObject::= SEQUENCE {
+keyUsageQualifier [21] OCTET STRING (SIZE (1..2)), /* see [GPCS] section 11.1.9 */
+keyAccess [22] OCTET STRING (SIZE (1)) DEFAULT '00'H,
+keyIdentifier [2] OCTET STRING (SIZE (1)),
+keyVersionNumber [3] OCTET STRING (SIZE (1)),
+keyCounterValue [5] OCTET STRING OPTIONAL,
+keyCompontents SEQUENCE (SIZE (1..MAX)) OF SEQUENCE {
+ keyType [0] OCTET STRING,
+ keyData [6] OCTET STRING,
+ macLength[7] UInt8 DEFAULT 8
+ }
+}
+
+PE-Application ::= SEQUENCE {
+ app-Header PEHeader,
+loadBlock ApplicationLoadPackage OPTIONAL,
+instanceList SEQUENCE (SIZE (1..MAX)) OF ApplicationInstance OPTIONAL
+}
+
+ApplicationLoadPackage ::= SEQUENCE {
+loadPackageAID [APPLICATION 15] ApplicationIdentifier,
+securityDomainAID [APPLICATION 15] ApplicationIdentifier OPTIONAL,
+nonVolatileCodeLimitC6 [PRIVATE 6] OCTET STRING OPTIONAL,
+volatileDataLimitC7 [PRIVATE 7] OCTET STRING OPTIONAL,
+nonVolatileDataLimitC8 [PRIVATE 8] OCTET STRING OPTIONAL,
+hashValue [PRIVATE 1] OCTET STRING OPTIONAL,
+loadBlockObject [PRIVATE 4] OCTET STRING
+}
+
+ApplicationInstance ::= SEQUENCE {
+applicationLoadPackageAID [APPLICATION 15] ApplicationIdentifier,
+classAID [APPLICATION 15] ApplicationIdentifier,
+instanceAID [APPLICATION 15] ApplicationIdentifier,
+extraditeSecurityDomainAID [APPLICATION 15] ApplicationIdentifier OPTIONAL,
+applicationPrivileges [2] OCTET STRING,
+lifeCycleState [3] OCTET STRING (SIZE(1)) DEFAULT '07'H,
+/* Coding according to GP Life Cycle State. */
+
+applicationSpecificParametersC9 [PRIVATE 9] OCTET STRING,
+systemSpecificParameters [PRIVATE 15] ApplicationSystemParameters OPTIONAL,
+applicationParameters [PRIVATE 10] UICCApplicationParameters OPTIONAL,
+processData SEQUENCE (SIZE (1..MAX)) OF OCTET STRING OPTIONAL,
+controlReferenceTemplate [16] ControlReferenceTemplate OPTIONAL
+}
+
+ApplicationSystemParameters ::= SEQUENCE{
+volatileMemoryQuotaC7 [PRIVATE 7] OCTET STRING (SIZE (2..4)) OPTIONAL,
+nonVolatileMemoryQuotaC8 [PRIVATE 8] OCTET STRING (SIZE (2..4)) OPTIONAL,
+globalServiceParameters [PRIVATE 11] OCTET STRING OPTIONAL,
+implicitSelectionParameter [PRIVATE 15] OCTET STRING OPTIONAL,
+volatileReservedMemory [PRIVATE 23] OCTET STRING (SIZE (2..4)) OPTIONAL,
+nonVolatileReservedMemory [PRIVATE 24] OCTET STRING (SIZE (2..4)) OPTIONAL,
+ts102226SIMFileAccessToolkitParameter [PRIVATE 10] OCTET STRING OPTIONAL,
+ts102226AdditionalContactlessParameters [0] TS102226AdditionalContactlessParameters OPTIONAL,
+contactlessProtocolParameters [PRIVATE 25] OCTET STRING OPTIONAL, /* Coded according to Contactless Protocol Parameters Structure as defined in GP Amd. C */
+userInteractionContactlessParameters [PRIVATE 26] OCTET STRING OPTIONAL, /* Coded according to User Interaction Parameters Structure as defined in GP Amd. C */
+cumulativeGrantedVolatileMemory [2] OCTET STRING (SIZE (2..4)) OPTIONAL, /*
+Coded according to Contactless Specific Parameters as defined in GP Amd. C */
+
+cumulativeGrantedNonVolatileMemory [3] OCTET STRING (SIZE (2..4)) OPTIONAL /*
+Coded according to Contactless Specific Parameters as defined in GP Amd. C */
+}
+
+UICCApplicationParameters ::= SEQUENCE {
+uiccToolkitApplicationSpecificParametersField [0] OCTET STRING OPTIONAL,
+uiccAccessApplicationSpecificParametersField [1] OCTET STRING OPTIONAL,
+uiccAdministrativeAccessApplicationSpecificParametersField [2] OCTET STRING OPTIONAL
+}
+
+TS102226AdditionalContactlessParameters ::= SEQUENCE{
+protocolParameterData OCTET STRING /* Parameters for contactless applications encoded according to TS 102 226 */
+}
+
+ControlReferenceTemplate ::= SEQUENCE{
+applicationProviderIdentifier [APPLICATION 32] OCTET STRING
+}
+
+
+PE-RFM ::= SEQUENCE {
+rfm-header [0] PEHeader,
+
+ /* instanceAID
+ AID of the RFM instance
+ */
+ instanceAID [APPLICATION 15] ApplicationIdentifier,
+
+ /* securityDomainAID to which the RFM instance is associated
+ */
+ securityDomainAID [APPLICATION 15] ApplicationIdentifier OPTIONAL,
+
+ tarList [0] SEQUENCE (SIZE (1..MAX)) OF OCTET STRING (SIZE(3)) OPTIONAL,
+
+ minimumSecurityLevel [1] OCTET STRING (SIZE (1)),
+
+uiccAccessDomain OCTET STRING,
+ uiccAdminAccessDomain OCTET STRING,
+
+ /*
+ If the following parameter is available the respective ADF shall be the directory selected by default within an RFM script. In case it is not available the MF shall be the default selection.
+ */
+ adfRFMAccess ADFRFMAccess OPTIONAL
+}
+
+ADFRFMAccess ::= SEQUENCE {
+ adfAID ApplicationIdentifier,
+ adfAccessDomain OCTET STRING,
+ adfAdminAccessDomain OCTET STRING
+}
+
+PE-NonStandard ::= SEQUENCE {
+nonStandard-header PEHeader,
+issuerID OBJECT IDENTIFIER,
+content OCTET STRING
+}
+
+PE-End ::= SEQUENCE {
+end-header PEHeader
+}
+
+PEStatus ::= SEQUENCE {
+status INTEGER {
+ok(0), pe-not-supported(1), memory-failure(2),bad-values(3),
+not-enough-memory(4),invalid-request-format(5), invalid-parameter(6),
+runtime-not-supported (7), lib-not-supported (8),
+template-not-supported (9), feature-not-supported (10),
+pin-code-missing (11),
+unsupported-profile-version(31)
+/* ISO 7816 standard status values apply in the range of [24576...28671]
+and [36864...40959] for reporting status values '6xxx'H and '9xxx'H
+proprietary values apply in the range [40960...65535]
+*/
+},
+identification UInt15 OPTIONAL,
+-- Identification number of the PE triggering the error
+additional-information UInt8 OPTIONAL,
+-- Additional information related to the status code
+offset UInt31 OPTIONAL
+-- Position of the part of the PE generating this status code
+}
+
+EUICCResponse ::= SEQUENCE {
+ peStatus SEQUENCE OF PEStatus,
+profileInstallationAborted NULL OPTIONAL,
+statusMessage UTF8String (SIZE (2..64)) OPTIONAL
+}
+
+END
diff --git a/library/euicc/PKIX1Explicit88.asn b/library/euicc/PKIX1Explicit88.asn
new file mode 100644
index 00000000..f0197e15
--- /dev/null
+++ b/library/euicc/PKIX1Explicit88.asn
@@ -0,0 +1,619 @@
+PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) }
+
+DEFINITIONS EXPLICIT TAGS ::=
+
+BEGIN
+
+-- EXPORTS ALL --
+
+-- IMPORTS NONE --
+
+-- UNIVERSAL Types defined in 1993 and 1998 ASN.1
+-- and required by this specification
+
+-- UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING
+ -- UniversalString is defined in ASN.1:1993
+
+-- BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING
+ -- BMPString is the subtype of UniversalString and models
+ -- the Basic Multilingual Plane of ISO/IEC/ITU 10646-1
+
+-- UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING
+ -- The content of this type conforms to RFC 2279.
+
+-- PKIX specific OIDs
+
+id-pkix OBJECT IDENTIFIER ::=
+ { iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) }
+
+-- PKIX arcs
+
+id-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
+ -- arc for private certificate extensions
+id-qt OBJECT IDENTIFIER ::= { id-pkix 2 }
+ -- arc for policy qualifier types
+id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
+ -- arc for extended key purpose OIDS
+id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+ -- arc for access descriptors
+
+-- policyQualifierIds for Internet policy qualifiers
+
+id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 }
+ -- OID for CPS qualifier
+id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 }
+ -- OID for user notice qualifier
+
+-- access descriptor definitions
+
+id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+id-ad-timeStamping OBJECT IDENTIFIER ::= { id-ad 3 }
+id-ad-caRepository OBJECT IDENTIFIER ::= { id-ad 5 }
+
+-- attribute data types
+
+Attribute ::= SEQUENCE {
+ type AttributeType,
+ values SET OF AttributeValue }
+ -- at least one value is required
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= ANY
+
+AttributeTypeAndValue ::= SEQUENCE {
+ type AttributeType,
+ value AttributeValue }
+
+-- suggested naming attributes: Definition of the following
+-- information object set may be augmented to meet local
+-- requirements. Note that deleting members of the set may
+-- prevent interoperability with conforming implementations.
+-- presented in pairs: the AttributeType followed by the
+-- type definition for the corresponding AttributeValue
+--Arc for standard naming attributes
+id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
+
+-- Naming attributes of type X520name
+
+id-at-name AttributeType ::= { id-at 41 }
+id-at-surname AttributeType ::= { id-at 4 }
+id-at-givenName AttributeType ::= { id-at 42 }
+id-at-initials AttributeType ::= { id-at 43 }
+id-at-generationQualifier AttributeType ::= { id-at 44 }
+
+X520name ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-name)),
+ printableString PrintableString (SIZE (1..ub-name)),
+ universalString UniversalString (SIZE (1..ub-name)),
+ utf8String UTF8String (SIZE (1..ub-name)),
+ bmpString BMPString (SIZE (1..ub-name)) }
+
+-- Naming attributes of type X520CommonName
+
+id-at-commonName AttributeType ::= { id-at 3 }
+
+X520CommonName ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-common-name)),
+ printableString PrintableString (SIZE (1..ub-common-name)),
+ universalString UniversalString (SIZE (1..ub-common-name)),
+ utf8String UTF8String (SIZE (1..ub-common-name)),
+ bmpString BMPString (SIZE (1..ub-common-name)) }
+
+-- Naming attributes of type X520LocalityName
+
+id-at-localityName AttributeType ::= { id-at 7 }
+
+X520LocalityName ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-locality-name)),
+ printableString PrintableString (SIZE (1..ub-locality-name)),
+ universalString UniversalString (SIZE (1..ub-locality-name)),
+ utf8String UTF8String (SIZE (1..ub-locality-name)),
+ bmpString BMPString (SIZE (1..ub-locality-name)) }
+
+-- Naming attributes of type X520StateOrProvinceName
+
+id-at-stateOrProvinceName AttributeType ::= { id-at 8 }
+
+X520StateOrProvinceName ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-state-name)),
+ printableString PrintableString (SIZE (1..ub-state-name)),
+ universalString UniversalString (SIZE (1..ub-state-name)),
+ utf8String UTF8String (SIZE (1..ub-state-name)),
+ bmpString BMPString (SIZE(1..ub-state-name)) }
+
+-- Naming attributes of type X520OrganizationName
+
+id-at-organizationName AttributeType ::= { id-at 10 }
+
+X520OrganizationName ::= CHOICE {
+ teletexString TeletexString
+ (SIZE (1..ub-organization-name)),
+ printableString PrintableString
+ (SIZE (1..ub-organization-name)),
+ universalString UniversalString
+ (SIZE (1..ub-organization-name)),
+ utf8String UTF8String
+ (SIZE (1..ub-organization-name)),
+ bmpString BMPString
+ (SIZE (1..ub-organization-name)) }
+
+-- Naming attributes of type X520OrganizationalUnitName
+
+id-at-organizationalUnitName AttributeType ::= { id-at 11 }
+
+X520OrganizationalUnitName ::= CHOICE {
+ teletexString TeletexString
+ (SIZE (1..ub-organizational-unit-name)),
+ printableString PrintableString
+ (SIZE (1..ub-organizational-unit-name)),
+ universalString UniversalString
+ (SIZE (1..ub-organizational-unit-name)),
+ utf8String UTF8String
+ (SIZE (1..ub-organizational-unit-name)),
+ bmpString BMPString
+ (SIZE (1..ub-organizational-unit-name)) }
+
+-- Naming attributes of type X520Title
+
+id-at-title AttributeType ::= { id-at 12 }
+
+X520Title ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-title)),
+ printableString PrintableString (SIZE (1..ub-title)),
+ universalString UniversalString (SIZE (1..ub-title)),
+ utf8String UTF8String (SIZE (1..ub-title)),
+ bmpString BMPString (SIZE (1..ub-title)) }
+
+-- Naming attributes of type X520dnQualifier
+
+id-at-dnQualifier AttributeType ::= { id-at 46 }
+
+X520dnQualifier ::= PrintableString
+
+-- Naming attributes of type X520countryName (digraph from IS 3166)
+
+id-at-countryName AttributeType ::= { id-at 6 }
+
+X520countryName ::= PrintableString (SIZE (2))
+
+-- Naming attributes of type X520SerialNumber
+
+id-at-serialNumber AttributeType ::= { id-at 5 }
+
+X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number))
+
+-- Naming attributes of type X520Pseudonym
+
+id-at-pseudonym AttributeType ::= { id-at 65 }
+
+X520Pseudonym ::= CHOICE {
+ teletexString TeletexString (SIZE (1..ub-pseudonym)),
+ printableString PrintableString (SIZE (1..ub-pseudonym)),
+ universalString UniversalString (SIZE (1..ub-pseudonym)),
+ utf8String UTF8String (SIZE (1..ub-pseudonym)),
+ bmpString BMPString (SIZE (1..ub-pseudonym)) }
+
+-- Naming attributes of type DomainComponent (from RFC 2247)
+
+id-domainComponent AttributeType ::=
+ { 0 9 2342 19200300 100 1 25 }
+
+DomainComponent ::= IA5String
+
+-- Legacy attributes
+
+pkcs-9 OBJECT IDENTIFIER ::=
+ { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+
+id-emailAddress AttributeType ::= { pkcs-9 1 }
+
+EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length))
+
+-- naming data types --
+
+Name ::= CHOICE { -- only one possibility for now --
+ rdnSequence RDNSequence }
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+DistinguishedName ::= RDNSequence
+
+RelativeDistinguishedName ::=
+ SET SIZE (1 .. MAX) OF AttributeTypeAndValue
+
+-- Directory string type --
+
+DirectoryString ::= CHOICE {
+ teletexString TeletexString (SIZE (1..MAX)),
+ printableString PrintableString (SIZE (1..MAX)),
+ universalString UniversalString (SIZE (1..MAX)),
+ utf8String UTF8String (SIZE (1..MAX)),
+ bmpString BMPString (SIZE (1..MAX)) }
+
+-- certificate and CRL specific structures begin here
+
+Certificate ::= SEQUENCE {
+ tbsCertificate TBSCertificate,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertificate ::= SEQUENCE {
+ version [0] Version DEFAULT v1,
+ serialNumber CertificateSerialNumber,
+ signature AlgorithmIdentifier,
+ issuer Name,
+ validity Validity,
+ subject Name,
+ subjectPublicKeyInfo SubjectPublicKeyInfo,
+ issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version MUST be v2 or v3
+ subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
+ -- If present, version MUST be v2 or v3
+ extensions [3] Extensions OPTIONAL
+ -- If present, version MUST be v3 -- }
+
+Version ::= INTEGER { v1(0), v2(1), v3(2) }
+
+CertificateSerialNumber ::= INTEGER (0..999999999999999999999999999999999999) -- apply a range to suitable to force asn1c to uses INTEGER_t
+
+Validity ::= SEQUENCE {
+ notBefore Time,
+ notAfter Time }
+
+Time ::= CHOICE {
+ utcTime UTCTime,
+ generalTime GeneralizedTime }
+
+UniqueIdentifier ::= BIT STRING
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+ algorithm AlgorithmIdentifier,
+ subjectPublicKey BIT STRING }
+
+Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
+
+Extension ::= SEQUENCE {
+ extnID OBJECT IDENTIFIER,
+ critical BOOLEAN DEFAULT FALSE,
+ extnValue OCTET STRING }
+
+-- CRL structures
+
+CertificateList ::= SEQUENCE {
+ tbsCertList TBSCertList,
+ signatureAlgorithm AlgorithmIdentifier,
+ signature BIT STRING }
+
+TBSCertList ::= SEQUENCE {
+ version Version OPTIONAL,
+ -- if present, MUST be v2
+ signature AlgorithmIdentifier,
+ issuer Name,
+ thisUpdate Time,
+ nextUpdate Time OPTIONAL,
+ revokedCertificates SEQUENCE OF SEQUENCE {
+ userCertificate CertificateSerialNumber,
+ revocationDate Time,
+ crlEntryExtensions Extensions OPTIONAL
+ -- if present, MUST be v2
+ } OPTIONAL,
+ crlExtensions [0] Extensions OPTIONAL }
+ -- if present, MUST be v2
+
+-- Version, Time, CertificateSerialNumber, and Extensions were
+-- defined earlier for use in the certificate structure
+
+AlgorithmIdentifier ::= SEQUENCE {
+ algorithm OBJECT IDENTIFIER,
+ parameters ANY DEFINED BY algorithm OPTIONAL }
+ -- contains a value of the type
+ -- registered for use with the
+ -- algorithm object identifier value
+
+-- X.400 address syntax starts here
+
+ORAddress ::= SEQUENCE {
+ built-in-standard-attributes BuiltInStandardAttributes,
+ built-in-domain-defined-attributes
+ BuiltInDomainDefinedAttributes OPTIONAL,
+ -- see also teletex-domain-defined-attributes
+ extension-attributes ExtensionAttributes OPTIONAL }
+
+-- Built-in Standard Attributes
+
+BuiltInStandardAttributes ::= SEQUENCE {
+ country-name CountryName OPTIONAL,
+ administration-domain-name AdministrationDomainName OPTIONAL,
+ network-address [0] IMPLICIT NetworkAddress OPTIONAL,
+ -- see also extended-network-address
+ terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL,
+ private-domain-name [2] PrivateDomainName OPTIONAL,
+ organization-name [3] IMPLICIT OrganizationName OPTIONAL,
+ -- see also teletex-organization-name
+ numeric-user-identifier [4] IMPLICIT NumericUserIdentifier
+ OPTIONAL,
+ personal-name [5] IMPLICIT PersonalName OPTIONAL,
+ -- see also teletex-personal-name
+ organizational-unit-names [6] IMPLICIT OrganizationalUnitNames
+ OPTIONAL }
+ -- see also teletex-organizational-unit-names
+
+CountryName ::= [APPLICATION 1] CHOICE {
+ x121-dcc-code NumericString
+ (SIZE (ub-country-name-numeric-length)),
+ iso-3166-alpha2-code PrintableString
+ (SIZE (ub-country-name-alpha-length)) }
+
+AdministrationDomainName ::= [APPLICATION 2] CHOICE {
+ numeric NumericString (SIZE (0..ub-domain-name-length)),
+ printable PrintableString (SIZE (0..ub-domain-name-length)) }
+
+NetworkAddress ::= X121Address -- see also extended-network-address
+
+X121Address ::= NumericString (SIZE (1..ub-x121-address-length))
+
+TerminalIdentifier ::= PrintableString (SIZE
+(1..ub-terminal-id-length))
+
+PrivateDomainName ::= CHOICE {
+ numeric NumericString (SIZE (1..ub-domain-name-length)),
+ printable PrintableString (SIZE (1..ub-domain-name-length)) }
+
+OrganizationName ::= PrintableString
+ (SIZE (1..ub-organization-name-length))
+ -- see also teletex-organization-name
+
+NumericUserIdentifier ::= NumericString
+ (SIZE (1..ub-numeric-user-id-length))
+
+PersonalName ::= SET {
+ surname [0] IMPLICIT PrintableString
+ (SIZE (1..ub-surname-length)),
+ given-name [1] IMPLICIT PrintableString
+ (SIZE (1..ub-given-name-length)) OPTIONAL,
+ initials [2] IMPLICIT PrintableString
+ (SIZE (1..ub-initials-length)) OPTIONAL,
+ generation-qualifier [3] IMPLICIT PrintableString
+ (SIZE (1..ub-generation-qualifier-length))
+ OPTIONAL }
+ -- see also teletex-personal-name
+
+OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units)
+ OF OrganizationalUnitName
+ -- see also teletex-organizational-unit-names
+
+OrganizationalUnitName ::= PrintableString (SIZE
+ (1..ub-organizational-unit-name-length))
+
+-- Built-in Domain-defined Attributes
+
+BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE
+ (1..ub-domain-defined-attributes) OF
+ BuiltInDomainDefinedAttribute
+
+BuiltInDomainDefinedAttribute ::= SEQUENCE {
+ type PrintableString (SIZE
+ (1..ub-domain-defined-attribute-type-length)),
+ value PrintableString (SIZE
+ (1..ub-domain-defined-attribute-value-length)) }
+
+-- Extension Attributes
+
+ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF
+ ExtensionAttribute
+
+ExtensionAttribute ::= SEQUENCE {
+ extension-attribute-type [0] IMPLICIT INTEGER
+ (0..ub-extension-attributes),
+ extension-attribute-value [1]
+ ANY DEFINED BY extension-attribute-type }
+
+-- Extension types and attribute values
+
+common-name INTEGER ::= 1
+
+CommonName ::= PrintableString (SIZE (1..ub-common-name-length))
+
+teletex-common-name INTEGER ::= 2
+
+TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length))
+
+teletex-organization-name INTEGER ::= 3
+
+TeletexOrganizationName ::=
+ TeletexString (SIZE (1..ub-organization-name-length))
+
+teletex-personal-name INTEGER ::= 4
+
+TeletexPersonalName ::= SET {
+ surname [0] IMPLICIT TeletexString
+ (SIZE (1..ub-surname-length)),
+ given-name [1] IMPLICIT TeletexString
+ (SIZE (1..ub-given-name-length)) OPTIONAL,
+ initials [2] IMPLICIT TeletexString
+ (SIZE (1..ub-initials-length)) OPTIONAL,
+ generation-qualifier [3] IMPLICIT TeletexString
+ (SIZE (1..ub-generation-qualifier-length))
+ OPTIONAL }
+
+teletex-organizational-unit-names INTEGER ::= 5
+
+TeletexOrganizationalUnitNames ::= SEQUENCE SIZE
+ (1..ub-organizational-units) OF TeletexOrganizationalUnitName
+
+TeletexOrganizationalUnitName ::= TeletexString
+ (SIZE (1..ub-organizational-unit-name-length))
+
+pds-name INTEGER ::= 7
+
+PDSName ::= PrintableString (SIZE (1..ub-pds-name-length))
+
+physical-delivery-country-name INTEGER ::= 8
+
+PhysicalDeliveryCountryName ::= CHOICE {
+ x121-dcc-code NumericString (SIZE
+(ub-country-name-numeric-length)),
+ iso-3166-alpha2-code PrintableString
+ (SIZE (ub-country-name-alpha-length)) }
+
+postal-code INTEGER ::= 9
+
+PostalCode ::= CHOICE {
+ numeric-code NumericString (SIZE (1..ub-postal-code-length)),
+ printable-code PrintableString (SIZE (1..ub-postal-code-length)) }
+
+physical-delivery-office-name INTEGER ::= 10
+
+PhysicalDeliveryOfficeName ::= PDSParameter
+
+physical-delivery-office-number INTEGER ::= 11
+
+PhysicalDeliveryOfficeNumber ::= PDSParameter
+
+extension-OR-address-components INTEGER ::= 12
+
+ExtensionORAddressComponents ::= PDSParameter
+
+physical-delivery-personal-name INTEGER ::= 13
+
+PhysicalDeliveryPersonalName ::= PDSParameter
+
+physical-delivery-organization-name INTEGER ::= 14
+
+PhysicalDeliveryOrganizationName ::= PDSParameter
+
+extension-physical-delivery-address-components INTEGER ::= 15
+
+ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter
+
+unformatted-postal-address INTEGER ::= 16
+
+UnformattedPostalAddress ::= SET {
+ printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines)
+ OF PrintableString (SIZE (1..ub-pds-parameter-length))
+ OPTIONAL,
+ teletex-string TeletexString
+ (SIZE (1..ub-unformatted-address-length)) OPTIONAL }
+
+street-address INTEGER ::= 17
+
+StreetAddress ::= PDSParameter
+
+post-office-box-address INTEGER ::= 18
+
+PostOfficeBoxAddress ::= PDSParameter
+
+poste-restante-address INTEGER ::= 19
+
+PosteRestanteAddress ::= PDSParameter
+
+unique-postal-name INTEGER ::= 20
+
+UniquePostalName ::= PDSParameter
+
+local-postal-attributes INTEGER ::= 21
+
+LocalPostalAttributes ::= PDSParameter
+
+PDSParameter ::= SET {
+ printable-string PrintableString
+ (SIZE(1..ub-pds-parameter-length)) OPTIONAL,
+ teletex-string TeletexString
+ (SIZE(1..ub-pds-parameter-length)) OPTIONAL }
+
+extended-network-address INTEGER ::= 22
+
+ExtendedNetworkAddress ::= CHOICE {
+ e163-4-address SEQUENCE {
+ number [0] IMPLICIT NumericString
+ (SIZE (1..ub-e163-4-number-length)),
+ sub-address [1] IMPLICIT NumericString
+ (SIZE (1..ub-e163-4-sub-address-length))
+ OPTIONAL },
+ psap-address [0] IMPLICIT PresentationAddress }
+
+PresentationAddress ::= SEQUENCE {
+ pSelector [0] EXPLICIT OCTET STRING OPTIONAL,
+ sSelector [1] EXPLICIT OCTET STRING OPTIONAL,
+ tSelector [2] EXPLICIT OCTET STRING OPTIONAL,
+ nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING }
+
+terminal-type INTEGER ::= 23
+
+TerminalType ::= INTEGER {
+ telex (3),
+ teletex (4),
+ g3-facsimile (5),
+ g4-facsimile (6),
+ ia5-terminal (7),
+ videotex (8) }
+
+-- Extension Domain-defined Attributes
+
+teletex-domain-defined-attributes INTEGER ::= 6
+
+TeletexDomainDefinedAttributes ::= SEQUENCE SIZE
+ (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute
+
+TeletexDomainDefinedAttribute ::= SEQUENCE {
+ type TeletexString
+ (SIZE (1..ub-domain-defined-attribute-type-length)),
+ value TeletexString
+ (SIZE (1..ub-domain-defined-attribute-value-length)) }
+
+-- specifications of Upper Bounds MUST be regarded as mandatory
+-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
+-- Upper Bounds
+
+-- Upper Bounds
+ub-name INTEGER ::= 32768
+ub-common-name INTEGER ::= 64
+ub-locality-name INTEGER ::= 128
+ub-state-name INTEGER ::= 128
+ub-organization-name INTEGER ::= 64
+ub-organizational-unit-name INTEGER ::= 64
+ub-title INTEGER ::= 64
+ub-serial-number INTEGER ::= 64
+ub-match INTEGER ::= 128
+ub-emailaddress-length INTEGER ::= 255
+ub-common-name-length INTEGER ::= 64
+ub-country-name-alpha-length INTEGER ::= 2
+ub-country-name-numeric-length INTEGER ::= 3
+ub-domain-defined-attributes INTEGER ::= 4
+ub-domain-defined-attribute-type-length INTEGER ::= 8
+ub-domain-defined-attribute-value-length INTEGER ::= 128
+ub-domain-name-length INTEGER ::= 16
+ub-extension-attributes INTEGER ::= 256
+ub-e163-4-number-length INTEGER ::= 15
+ub-e163-4-sub-address-length INTEGER ::= 40
+ub-generation-qualifier-length INTEGER ::= 3
+ub-given-name-length INTEGER ::= 16
+ub-initials-length INTEGER ::= 5
+ub-integer-options INTEGER ::= 256
+ub-numeric-user-id-length INTEGER ::= 32
+ub-organization-name-length INTEGER ::= 64
+ub-organizational-unit-name-length INTEGER ::= 32
+ub-organizational-units INTEGER ::= 4
+ub-pds-name-length INTEGER ::= 16
+ub-pds-parameter-length INTEGER ::= 30
+ub-pds-physical-address-lines INTEGER ::= 6
+ub-postal-code-length INTEGER ::= 16
+ub-pseudonym INTEGER ::= 128
+ub-surname-length INTEGER ::= 40
+ub-terminal-id-length INTEGER ::= 24
+ub-unformatted-address-length INTEGER ::= 180
+ub-x121-address-length INTEGER ::= 16
+
+-- Note - upper bounds on string types, such as TeletexString, are
+-- measured in characters. Excepting PrintableString or IA5String, a
+-- significantly greater number of octets will be required to hold
+-- such a value. As a minimum, 16 octets, or twice the specified
+-- upper bound, whichever is the larger, should be allowed for
+-- TeletexString. For UTF8String or UniversalString at least four
+-- times the upper bound should be allowed.
+
+END
diff --git a/library/euicc/PKIX1Explicit88_EncDec.cc b/library/euicc/PKIX1Explicit88_EncDec.cc
new file mode 100644
index 00000000..3cfb156d
--- /dev/null
+++ b/library/euicc/PKIX1Explicit88_EncDec.cc
@@ -0,0 +1,213 @@
+#include "PKIX1Explicit88.hh"
+
+namespace PKIX1Explicit88__Types {
+
+using namespace PKIX1Explicit88;
+
+TTCN_Module PKIX1Explicit88__EncDec("PKIX1Explicit88_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__X520name(const X520name &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520name_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520name dec__X520name(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520name msg;
+ buf.put_os(stream);
+
+ msg.decode(X520name_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520CommonName(const X520CommonName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520CommonName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520CommonName dec__X520CommonName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520CommonName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520CommonName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520LocalityName(const X520LocalityName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520LocalityName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520LocalityName dec__X520LocalityName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520LocalityName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520LocalityName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520StateOrProvinceName(const X520StateOrProvinceName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520StateOrProvinceName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520StateOrProvinceName dec__X520StateOrProvinceName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520StateOrProvinceName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520StateOrProvinceName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520OrganizationName(const X520OrganizationName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520OrganizationName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520OrganizationName dec__X520OrganizationName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520OrganizationName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520OrganizationName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520OrganizationalUnitName(const X520OrganizationalUnitName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520OrganizationalUnitName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520OrganizationalUnitName dec__X520OrganizationalUnitName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520OrganizationalUnitName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520OrganizationalUnitName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520Title(const X520Title &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520Title_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520Title dec__X520Title(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520Title msg;
+ buf.put_os(stream);
+
+ msg.decode(X520Title_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520dnQualifier(const X520dnQualifier &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520dnQualifier_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520dnQualifier dec__X520dnQualifier(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520dnQualifier msg;
+ buf.put_os(stream);
+
+ msg.decode(X520dnQualifier_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520countryName(const X520countryName &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520countryName_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520countryName dec__X520countryName(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520countryName msg;
+ buf.put_os(stream);
+
+ msg.decode(X520countryName_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520SerialNumber(const X520SerialNumber &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520SerialNumber_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520SerialNumber dec__X520SerialNumber(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520SerialNumber msg;
+ buf.put_os(stream);
+
+ msg.decode(X520SerialNumber_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__X520Pseudonym(const X520Pseudonym &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(X520Pseudonym_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+X520Pseudonym dec__X520Pseudonym(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ X520Pseudonym msg;
+ buf.put_os(stream);
+
+ msg.decode(X520Pseudonym_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__Certificate(const Certificate &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(Certificate_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+Certificate dec__Certificate(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ Certificate msg;
+ buf.put_os(stream);
+
+ msg.decode(Certificate_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+}
diff --git a/library/euicc/PKIX1Explicit88_Templates.ttcn b/library/euicc/PKIX1Explicit88_Templates.ttcn
new file mode 100644
index 00000000..d2cc7bb9
--- /dev/null
+++ b/library/euicc/PKIX1Explicit88_Templates.ttcn
@@ -0,0 +1,1901 @@
+/* PKIX1 Templates in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * 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 PKIX1Explicit88_Templates {
+
+import from PKIX1Explicit88_Types all;
+import from PKIX1Explicit88 all;
+import from PKIX1Implicit88 all;
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/CertificateIssuer/CERT_CI_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ b8:74:f3:ab:fa:6c:44:d3
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Feb 1 15:39:42 2017 GMT
+ Not After : Feb 1 15:39:42 2052 GMT
+ Subject: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:94:06:57:a6:73:dc:28:8f:89:d5:2e:a8:a4:77:
+ 04:99:27:91:f9:c3:4b:00:36:e6:33:e2:d0:cb:a9:
+ 45:4d:65:db:32:eb:17:98:17:99:d2:f2:43:88:ee:
+ 2b:95:c1:09:45:46:c9:79:01:ce:ae:ba:96:50:91:
+ 9a:2e:20:d2:29
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.0
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.1
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:46:02:21:00:91:f2:51:c9:71:53:b9:cf:85:37:9a:74:8b:
+ 57:2a:49:68:52:45:56:c4:7f:33:eb:69:7b:55:91:2c:c0:f2:
+ d2:02:21:00:dc:e4:9e:73:f3:49:ec:d0:59:10:ef:9d:f6:b6:
+ 9a:86:7a:bf:38:9d:c8:6b:84:11:b4:df:e1:96:91:50:f5:f9
+*/
+const octetstring cert_ci_nist :=
+'30820256308201fba003020102020900b874f3abfa6c44d3300a06082a86
+48ce3d04030230493115301306035504030c0c47534d4120546573742043
+493111300f060355040b0c0854455354434552543110300e060355040a0c
+0752535054455354310b30090603550406130249543020170d3137303230
+313135333934325a180f32303532303230313135333934325a3049311530
+1306035504030c0c47534d4120546573742043493111300f060355040b0c
+0854455354434552543110300e060355040a0c0752535054455354310b30
+090603550406130249543059301306072a8648ce3d020106082a8648ce3d
+03010703420004940657a673dc288f89d52ea8a47704992791f9c34b0036
+e633e2d0cba9454d65db32eb17981799d2f24388ee2b95c1094546c97901
+ceaeba9650919a2e20d229a381c93081c6301d0603551d0e04160414f541
+72bdf98a95d65cbeb88a38a1c11d800a85c3300f0603551d130101ff0405
+30030101ff30170603551d200101ff040d300b3009060767811201020100
+300e0603551d0f0101ff040403020106300e0603551d1104073005880388
+3701305b0603551d1f045430523027a025a0238621687474703a2f2f6369
+2e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+422e63726c300a06082a8648ce3d040302034900304602210091f251c971
+53b9cf85379a748b572a4968524556c47f33eb697b55912cc0f2d2022100
+dce49e73f349ecd05910ef9df6b69a867abf389dc86b8411b4dfe1969150
+f5f9'O
+function f_ts_cert_ci_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_ci_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_ci_nist := f_ts_cert_ci_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/CertificateIssuer/CERT_CI_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ b8:74:f3:ab:fa:6c:44:d3
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Apr 19 10:34:38 2017 GMT
+ Not After : Apr 18 10:34:38 2052 GMT
+ Subject: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:27:87:b4:d5:6e:d8:24:a9:e6:be:04:e1:88:7f:
+ 6b:98:ba:fe:b8:c7:63:f5:28:37:f7:01:13:e9:36:
+ 4e:dd:be:13:9b:c0:c7:de:7e:16:8f:1e:5c:d0:c1:
+ 85:34:fc:50:64:e6:4f:68:6d:c5:33:27:ca:7f:1d:
+ ce:a8:5a:29:94
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.0
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.1
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:06:c6:c3:9f:5a:b9:71:5d:72:c5:65:dc:f5:ff:
+ 3b:fe:f3:fb:70:ef:0a:e3:3a:07:36:66:91:35:86:d0:ef:92:
+ 02:20:16:b2:44:eb:46:9f:2a:2f:58:6b:c1:c3:20:b4:b6:43:
+ 1b:8f:74:d9:41:f7:f1:83:2b:43:25:52:b1:61:df:a2
+*/
+const octetstring cert_ci_brp :=
+'30820255308201fca003020102020900b874f3abfa6c44d3300a06082a86
+48ce3d04030230493115301306035504030c0c47534d4120546573742043
+493111300f060355040b0c0854455354434552543110300e060355040a0c
+0752535054455354310b30090603550406130249543020170d3137303431
+393130333433385a180f32303532303431383130333433385a3049311530
+1306035504030c0c47534d4120546573742043493111300f060355040b0c
+0854455354434552543110300e060355040a0c0752535054455354310b30
+09060355040613024954305a301406072a8648ce3d020106092b24030302
+08010107034200042787b4d56ed824a9e6be04e1887f6b98bafeb8c763f5
+2837f70113e9364eddbe139bc0c7de7e168f1e5cd0c18534fc5064e64f68
+6dc53327ca7f1dcea85a2994a381c93081c6301d0603551d0e04160414c0
+bc70ba36929d43b467ff57570530e57ab8fcd8300f0603551d130101ff04
+0530030101ff30170603551d200101ff040d300b30090607678112010201
+00300e0603551d0f0101ff040403020106300e0603551d11040730058803
+883701305b0603551d1f045430523027a025a0238621687474703a2f2f63
+692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a0
+238621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c
+2d422e63726c300a06082a8648ce3d0403020347003044022006c6c39f5a
+b9715d72c565dcf5ff3bfef3fb70ef0ae33a073666913586d0ef92022016
+b244eb469f2a2f586bc1c320b4b6431b8f74d941f7f1832b432552b161df
+a2'O
+function f_ts_cert_ci_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_ci_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_ci_brp := f_ts_cert_ci_brp();
+
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/eUICC/CERT_EUICC_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 02:00:00:00:00:00:00:00:01
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = DE, O = RSP Test EUM, CN = EUM Test
+ Validity
+ Not Before: Jan 9 14:39:03 2017 GMT
+ Not After : Nov 2 14:39:03 7492 GMT
+ Subject: C = DE, O = RSP Test EUM, serialNumber = 89049032123451234512345678901235, CN = Test eUICC
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:6d:b3:f5:3a:dc:87:dc:2f:f1:0c:7b:fc:d8:7a:
+ d1:3a:e9:70:09:af:a0:65:a6:75:7e:e5:71:b3:f2:
+ eb:b1:8f:46:c1:d6:8f:3e:de:b0:e7:4b:2e:5d:54:
+ 20:51:e7:d2:7f:50:95:20:28:60:5a:fd:ef:79:fe:
+ 9f:ff:d0:39:59
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:DD:3D:A2:4D:35:0C:1C:C5:D0:AF:09:65:F4:0E:C3:4C:5E:E4:09:F1
+
+ X509v3 Subject Key Identifier:
+ A5:24:76:AF:5D:50:AA:37:64:37:CC:B1:DA:21:72:EF:45:F4:84:F0
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.1
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:5e:da:e9:e3:b9:27:8a:36:12:65:dc:bd:13:a3:
+ bf:48:d7:ae:c4:3d:29:05:12:5b:fa:ca:2f:4c:f3:a7:e6:54:
+ 02:20:08:9f:95:6b:b9:89:59:65:77:ec:98:6d:f7:af:66:f2:
+ a4:46:25:f3:85:77:4c:56:65:07:f6:f2:cd:72:e0:2c
+*/
+const octetstring cert_euicc_nist :=
+'308201fe308201a5a0030201020209020000000000000001300a06082a86
+48ce3d0403023037310b300906035504061302444531153013060355040a
+0c0c52535020546573742045554d3111300f06035504030c0845554d2054
+6573743020170d3137303130393134333930335a180f3734393231313032
+3134333930335a3064310b30090603550406130244453115301306035504
+0a0c0c52535020546573742045554d312930270603550405132038393034
+393033323132333435313233343531323334353637383930313233353113
+301106035504030c0a546573742065554943433059301306072a8648ce3d
+020106082a8648ce3d030107034200046db3f53adc87dc2ff10c7bfcd87a
+d13ae97009afa065a6757ee571b3f2ebb18f46c1d68f3edeb0e74b2e5d54
+2051e7d27f50952028605afdef79fe9fffd03959a36b3069301f0603551d
+23041830168014dd3da24d350c1cc5d0af0965f40ec34c5ee409f1301d06
+03551d0e04160414a52476af5d50aa376437ccb1da2172ef45f484f0300e
+0603551d0f0101ff04040302078030170603551d200101ff040d300b3009
+060767811201020101300a06082a8648ce3d040302034700304402205eda
+e9e3b9278a361265dcbd13a3bf48d7aec43d2905125bfaca2f4cf3a7e654
+0220089f956bb989596577ec986df7af66f2a44625f385774c566507f6f2
+cd72e02c'O;
+function f_ts_cert_euicc_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_euicc_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_euicc_nist := f_ts_cert_euicc_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/eUICC/CERT_EUICC_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 02:00:00:00:00:00:00:00:01
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = DE, O = RSP Test EUM, CN = EUM Test
+ Validity
+ Not Before: Apr 20 12:07:50 2017 GMT
+ Not After : Feb 11 12:07:50 7493 GMT
+ Subject: C = DE, O = RSP Test EUM, serialNumber = 89049032123451234512345678901235, CN = Test eUICC
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:3e:59:0c:38:a9:c2:56:31:5e:cf:f3:29:14:16:
+ dd:33:54:09:a6:66:fd:41:b3:b5:1e:5e:51:14:f3:
+ 43:ab:f0:a2:67:74:c6:c2:6c:48:75:3a:fe:28:36:
+ 43:22:7b:b6:60:8c:d2:61:cc:97:2d:37:4a:47:91:
+ 24:eb:f2:77:22
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:6F:A1:E5:21:73:63:A8:22:BD:ED:98:8A:1A:0D:0F:F5:D7:62:0D:B7
+
+ X509v3 Subject Key Identifier:
+ C8:A6:4F:34:3B:85:B7:B0:57:8D:C5:7F:8F:13:58:6D:C8:04:ED:84
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.1
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:00:b4:f8:6f:2e:a1:4c:cc:04:66:51:99:88:4c:
+ ad:75:ca:dd:c3:36:79:77:2f:ff:d4:db:cf:1b:d2:a8:e4:1b:
+ 02:21:00:8b:4d:40:a2:d9:bd:3a:53:c6:80:bd:c8:a3:08:c3:
+ fb:dd:fe:e7:c6:6a:18:b4:dc:dd:03:77:0f:ff:aa:49:82
+*/
+const octetstring cert_euicc_brp :=
+'30820200308201a6a0030201020209020000000000000001300a06082a86
+48ce3d0403023037310b300906035504061302444531153013060355040a
+0c0c52535020546573742045554d3111300f06035504030c0845554d2054
+6573743020170d3137303432303132303735305a180f3734393330323131
+3132303735305a3064310b30090603550406130244453115301306035504
+0a0c0c52535020546573742045554d312930270603550405132038393034
+393033323132333435313233343531323334353637383930313233353113
+301106035504030c0a54657374206555494343305a301406072a8648ce3d
+020106092b2403030208010107034200043e590c38a9c256315ecff32914
+16dd335409a666fd41b3b51e5e5114f343abf0a26774c6c26c48753afe28
+3643227bb6608cd261cc972d374a479124ebf27722a36b3069301f060355
+1d230418301680146fa1e5217363a822bded988a1a0d0ff5d7620db7301d
+0603551d0e04160414c8a64f343b85b7b0578dc57f8f13586dc804ed8430
+0e0603551d0f0101ff04040302078030170603551d200101ff040d300b30
+09060767811201020101300a06082a8648ce3d0403020348003045022000
+b4f86f2ea14ccc04665199884cad75caddc33679772fffd4dbcf1bd2a8e4
+1b0221008b4d40a2d9bd3a53c680bdc8a308c3fbddfee7c66a18b4dcdd03
+770fffaa4982'O;
+function f_ts_cert_euicc_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_euicc_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_euicc_brp := f_ts_cert_euicc_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/EUM/CERT_EUM_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 305419896 (0x12345678)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jan 19 18:10:30 2017 GMT
+ Not After : Jan 19 18:10:30 2051 GMT
+ Subject: C = DE, O = RSP Test EUM, CN = EUM Test
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:13:30:d5:92:56:ac:0c:b5:0b:d9:28:d0:f4:c6:
+ 80:07:c4:85:fe:3f:42:98:8a:d3:ee:38:75:ae:33:
+ f4:98:3a:b2:3b:4d:d4:c3:13:40:d6:76:dd:8e:11:
+ f9:c5:cb:a1:b1:1e:b6:94:ee:d0:99:4d:b5:29:28:
+ 5e:63:2c:89:06
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Key Identifier:
+ DD:3D:A2:4D:35:0C:1C:C5:D0:AF:09:65:F4:0E:C3:4C:5E:E4:09:F1
+ X509v3 Key Usage: critical
+ Certificate Sign
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.2
+
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.5
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ X509v3 Name Constraints: critical
+ Permitted:
+ DirName:O = RSP Test EUM, serialNumber = 89049032
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:46:02:21:00:8c:4d:4b:26:40:4e:a5:dd:ea:65:eb:b4:3c:
+ 18:db:ab:12:cb:90:97:de:b7:7f:0b:a1:57:e3:8c:7b:18:b4:
+ ee:02:21:00:d1:8d:9c:f3:a1:34:87:ee:65:ca:6b:48:f8:c1:
+ ad:c0:2e:7a:7d:89:f1:74:b5:ae:2b:5e:1d:82:0a:9b:23:23
+*/
+const octetstring cert_eum_nist :=
+'3082027c30820221a003020102020412345678300a06082a8648ce3d0403
+0230493115301306035504030c0c47534d4120546573742043493111300f
+060355040b0c0854455354434552543110300e060355040a0c0752535054
+455354310b30090603550406130249543020170d31373031313931383130
+33305a180f32303531303131393138313033305a3037310b300906035504
+061302444531153013060355040a0c0c52535020546573742045554d3111
+300f06035504030c0845554d20546573743059301306072a8648ce3d0201
+06082a8648ce3d030107034200041330d59256ac0cb50bd928d0f4c68007
+c485fe3f42988ad3ee3875ae33f4983ab23b4dd4c31340d676dd8e11f9c5
+cba1b11eb694eed0994db529285e632c8906a382010530820101301f0603
+551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d800a85c330
+1d0603551d0e04160414dd3da24d350c1cc5d0af0965f40ec34c5ee409f1
+300e0603551d0f0101ff04040302020430170603551d200101ff040d300b
+3009060767811201020102300e0603551d11040730058803883705301206
+03551d130101ff040830060101ff02010030320603551d1f042b30293027
+a025a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f
+43524c2d422e63726c303e0603551d1e0101ff04343032a030302ea42c30
+2a31153013060355040a0c0c52535020546573742045554d3111300f0603
+55040513083839303439303332300a06082a8648ce3d0403020349003046
+0221008c4d4b26404ea5ddea65ebb43c18dbab12cb9097deb77f0ba157e3
+8c7b18b4ee022100d18d9cf3a13487ee65ca6b48f8c1adc02e7a7d89f174
+b5ae2b5e1d820a9b2323'O
+function f_ts_cert_eum_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_eum_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_eum_nist := f_ts_cert_eum_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/EUM/CERT_EUM_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 305419896 (0x12345678)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Apr 20 10:23:31 2017 GMT
+ Not After : Apr 20 10:23:31 2051 GMT
+ Subject: C = DE, O = RSP Test EUM, CN = EUM Test
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:a2:e5:2a:32:df:e8:99:65:71:c5:3a:f5:32:8e:
+ f6:82:09:3f:c1:d0:5f:52:65:2f:6b:71:1c:24:38:
+ 21:f7:f1:6b:0c:ec:8d:21:9b:23:d3:f9:90:f4:34:
+ d0:b9:0d:42:71:6c:02:e0:93:05:26:44:63:f6:11:
+ e6:50:c3:7f:f7
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Key Identifier:
+ 6F:A1:E5:21:73:63:A8:22:BD:ED:98:8A:1A:0D:0F:F5:D7:62:0D:B7
+ X509v3 Key Usage: critical
+ Certificate Sign
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.2
+
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.5
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:0
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ X509v3 Name Constraints: critical
+ Permitted:
+ DirName:O = RSP Test EUM, serialNumber = 89049032
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:2b:46:5c:c1:ac:87:8d:46:a8:7d:4a:70:72:ca:
+ 2c:f9:1c:27:10:87:02:19:ae:80:29:c6:96:bc:39:f0:5c:dc:
+ 02:20:40:cc:35:b4:9c:3b:30:ee:39:b0:5d:da:8f:6d:0d:a6:
+ 43:ab:8e:bd:6a:05:23:91:cf:46:c9:ee:4c:95:3b:19
+*/
+const octetstring cert_eum_brp :=
+'3082027b30820222a003020102020412345678300a06082a8648ce3d0403
+0230493115301306035504030c0c47534d4120546573742043493111300f
+060355040b0c0854455354434552543110300e060355040a0c0752535054
+455354310b30090603550406130249543020170d31373034323031303233
+33315a180f32303531303432303130323333315a3037310b300906035504
+061302444531153013060355040a0c0c52535020546573742045554d3111
+300f06035504030c0845554d2054657374305a301406072a8648ce3d0201
+06092b240303020801010703420004a2e52a32dfe8996571c53af5328ef6
+82093fc1d05f52652f6b711c243821f7f16b0cec8d219b23d3f990f434d0
+b90d42716c02e09305264463f611e650c37ff7a382010530820101301f06
+03551d23041830168014c0bc70ba36929d43b467ff57570530e57ab8fcd8
+301d0603551d0e041604146fa1e5217363a822bded988a1a0d0ff5d7620d
+b7300e0603551d0f0101ff04040302020430170603551d200101ff040d30
+0b3009060767811201020102300e0603551d110407300588038837053012
+0603551d130101ff040830060101ff02010030320603551d1f042b302930
+27a025a0238621687474703a2f2f63692e746573742e67736d612e636f6d
+2f43524c2d422e63726c303e0603551d1e0101ff04343032a030302ea42c
+302a31153013060355040a0c0c52535020546573742045554d3111300f06
+0355040513083839303439303332300a06082a8648ce3d04030203470030
+4402202b465cc1ac878d46a87d4a7072ca2cf91c2710870219ae8029c696
+bc39f05cdc022040cc35b49c3b30ee39b05dda8f6d0da643ab8ebd6a0523
+91cf46c9ee4c953b19'O;
+function f_ts_cert_eum_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_eum_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_eum_brp := f_ts_cert_eum_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPauth/CERT_S_SM_DPauth_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 100 (0x64)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Feb 1 13:38:56 2017 GMT
+ Not After : Feb 1 13:38:56 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:4d:fe:d4:f4:69:47:91:bf:16:95:ce:a0:30:7a:
+ 35:b4:18:01:96:95:38:7b:b7:5b:7d:24:47:b6:b5:
+ 20:9f:04:45:ae:4e:5e:52:1c:d1:38:88:d7:5f:e0:
+ 7c:85:80:22:2a:e2:0d:ba:ac:1d:77:cd:76:30:49:
+ 93:42:1b:d7:39
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Key Identifier:
+ BD:5A:82:CC:1A:96:60:21:18:BA:75:60:A1:FF:83:A7:8B:21:0B:E5
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.10
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.4
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:21:00:f1:cf:ef:41:e2:b8:a0:22:62:17:10:b9:6a:
+ 65:4f:ff:e4:85:d0:8c:20:e6:64:e8:5b:f2:d7:27:00:2a:07:
+ 38:02:20:69:25:bd:f7:bb:87:d0:c8:be:2b:78:a0:c5:9a:61:
+ 01:78:29:30:c2:fe:98:ad:2d:70:38:65:6a:02:14:a3:97
+*/
+const octetstring cert_s_sm_dpauth_nist :=
+'30820237308201dda003020102020164300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303230313133333835365a
+170d3230303230313133333835365a3025310d300b060355040a0c044143
+4d453114301206035504030c0b5445535420534d2d44502b305930130607
+2a8648ce3d020106082a8648ce3d030107034200044dfed4f4694791bf16
+95cea0307a35b418019695387bb75b7d2447b6b5209f0445ae4e5e521cd1
+3888d75fe07c8580222ae20dbaac1d77cd76304993421bd739a381d93081
+d6301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d
+800a85c3301d0603551d0e04160414bd5a82cc1a96602118ba7560a1ff83
+a78b210be5300e0603551d1104073005880388370a300e0603551d0f0101
+ff04040302078030170603551d200101ff040d300b300906076781120102
+0104305b0603551d1f045430523027a025a0238621687474703a2f2f6369
+2e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+422e63726c300a06082a8648ce3d0403020348003045022100f1cfef41e2
+b8a022621710b96a654fffe485d08c20e664e85bf2d727002a0738022069
+25bdf7bb87d0c8be2b78a0c59a6101782930c2fe98ad2d7038656a0214a3
+97'O;
+function f_ts_cert_s_sm_dpauth_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dpauth_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dpauth_nist := f_ts_cert_s_sm_dpauth_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPauth/CERT_S_SM_DPauth_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 100 (0x64)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Apr 26 15:20:12 2017 GMT
+ Not After : Apr 25 15:20:12 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:25:5d:7d:af:00:ef:84:1d:76:fa:7a:63:d6:3e:
+ b3:fe:6c:9f:70:49:2d:38:19:23:f8:f8:bd:7b:24:
+ f3:c5:ad:16:8e:be:3b:09:dd:80:f2:9e:7f:fd:24:
+ a4:d1:be:74:7f:83:23:e4:72:92:83:96:dd:e9:e0:
+ 15:1c:ea:ba:18
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Key Identifier:
+ 79:A4:BD:4D:78:FF:47:34:BC:60:45:CF:91:96:24:4A:1F:B8:4B:EB
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.10
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.4
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:30:45:fe:e3:ed:cc:6c:84:36:3d:d7:b8:6e:98:
+ 4b:dd:1c:94:78:cd:0f:2c:da:8e:4c:b9:63:13:f7:85:b2:db:
+ 02:21:00:81:29:01:29:4a:5f:c6:82:cf:fa:57:0f:8a:42:d5:
+ 59:b0:7c:ef:83:05:f7:d2:36:41:64:df:4d:f8:8c:a7:fa
+*/
+const octetstring cert_s_sm_dpauth_brp :=
+'30820238308201dea003020102020164300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303432363135323031325a
+170d3230303432353135323031325a3025310d300b060355040a0c044143
+4d453114301206035504030c0b5445535420534d2d44502b305a30140607
+2a8648ce3d020106092b240303020801010703420004255d7daf00ef841d
+76fa7a63d63eb3fe6c9f70492d381923f8f8bd7b24f3c5ad168ebe3b09dd
+80f29e7ffd24a4d1be747f8323e472928396dde9e0151ceaba18a381d930
+81d6301f0603551d23041830168014c0bc70ba36929d43b467ff57570530
+e57ab8fcd8301d0603551d0e0416041479a4bd4d78ff4734bc6045cf9196
+244a1fb84beb300e0603551d1104073005880388370a300e0603551d0f01
+01ff04040302078030170603551d200101ff040d300b3009060767811201
+020104305b0603551d1f045430523027a025a0238621687474703a2f2f63
+692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a0
+238621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c
+2d422e63726c300a06082a8648ce3d040302034800304502203045fee3ed
+cc6c84363dd7b86e984bdd1c9478cd0f2cda8e4cb96313f785b2db022100
+812901294a5fc682cffa570f8a42d559b07cef8305f7d2364164df4df88c
+a7fa'O;
+function f_ts_cert_s_sm_dpauth_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dpauth_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dpauth_brp := f_ts_cert_s_sm_dpauth_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPauth/CERT_S_SM_DP2auth_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 200 (0xc8)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Aug 21 14:19:48 2017 GMT
+ Not After : Aug 20 14:19:48 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+2"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:2b:2e:9b:45:d3:51:c0:9a:f4:0e:91:43:83:a1:
+ 90:38:47:f2:60:7d:e6:0e:f7:ab:25:c4:0e:03:f8:
+ db:b6:50:8e:14:57:50:8c:2b:e0:01:73:47:ec:fa:
+ 1b:f9:f7:75:e7:d0:7e:80:5e:52:e1:98:8b:7b:58:
+ 5a:71:11:ae:33
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Key Identifier:
+ 95:9E:F7:E6:50:C1:BE:21:6A:39:19:74:27:6D:26:B8:A9:35:61:71
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.12
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.4
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:46:02:21:00:c0:a5:cd:d1:0f:25:29:a9:f1:86:6d:93:21:
+ 65:91:ce:7a:8a:29:54:6d:1f:aa:2f:99:c2:4e:a6:52:23:35:
+ 98:02:21:00:85:92:01:17:04:fe:ab:d5:a6:af:fc:40:10:96:
+ 39:99:08:3f:5b:3e:94:60:05:a3:f1:b0:cb:81:a6:6b:b9:3c
+*/
+const octetstring cert_s_sm_dp2auth_nist :=
+'3082023a308201dfa003020102020200c8300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730383231313431393438
+5a170d3230303832303134313934385a3026310d300b060355040a0c0441
+434d453115301306035504030c0c5445535420534d2d44502b3230593013
+06072a8648ce3d020106082a8648ce3d030107034200042b2e9b45d351c0
+9af40e914383a1903847f2607de60ef7ab25c40e03f8dbb6508e1457508c
+2be0017347ecfa1bf9f775e7d07e805e52e1988b7b585a7111ae33a381d9
+3081d6301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1
+c11d800a85c3301d0603551d0e04160414959ef7e650c1be216a39197427
+6d26b8a9356171300e0603551d1104073005880388370c300e0603551d0f
+0101ff04040302078030170603551d200101ff040d300b30090607678112
+01020104305b0603551d1f045430523027a025a0238621687474703a2f2f
+63692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025
+a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f4352
+4c2d422e63726c300a06082a8648ce3d0403020349003046022100c0a5cd
+d10f2529a9f1866d93216591ce7a8a29546d1faa2f99c24ea65223359802
+21008592011704feabd5a6affc4010963999083f5b3e946005a3f1b0cb81
+a66bb93c'O;
+function f_ts_cert_s_sm_dp2auth_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp2auth_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp2auth_nist := f_ts_cert_s_sm_dp2auth_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPauth/CERT_S_SM_DP2auth_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 200 (0xc8)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Aug 21 14:27:16 2017 GMT
+ Not After : Aug 20 14:27:16 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+2"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:2e:ee:07:c9:6d:00:5b:e5:19:5f:79:ad:1d:ad:
+ cd:1d:37:8c:a3:09:5e:44:f7:2e:ea:41:0f:08:c7:
+ 56:12:2c:90:63:c9:65:b7:fc:85:29:c0:ca:4e:9b:
+ 4f:65:96:9c:28:3c:65:63:64:57:87:71:18:f6:d1:
+ 17:2d:6a:23:65
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Key Identifier:
+ D7:0E:FD:05:7B:AC:1F:7C:55:EA:5D:8C:26:BE:16:02:92:84:5B:AF
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.12
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.4
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:4b:32:a5:c9:ee:05:f2:9f:d4:4a:08:6f:f0:4a:
+ 10:9a:88:d6:e5:84:80:39:a5:16:ee:c7:8c:a4:ac:f0:c5:b3:
+ 02:20:52:9e:46:fa:10:9d:13:05:40:ba:d6:2a:46:fc:85:c3:
+ 95:b2:c4:cb:9e:8c:f1:50:79:d4:9a:9d:a5:37:df:e0
+*/
+const octetstring cert_s_sm_dp2auth_brp :=
+'30820239308201e0a003020102020200c8300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730383231313432373136
+5a170d3230303832303134323731365a3026310d300b060355040a0c0441
+434d453115301306035504030c0c5445535420534d2d44502b32305a3014
+06072a8648ce3d020106092b2403030208010107034200042eee07c96d00
+5be5195f79ad1dadcd1d378ca3095e44f72eea410f08c756122c9063c965
+b7fc8529c0ca4e9b4f65969c283c65636457877118f6d1172d6a2365a381
+d93081d6301f0603551d23041830168014c0bc70ba36929d43b467ff5757
+0530e57ab8fcd8301d0603551d0e04160414d70efd057bac1f7c55ea5d8c
+26be160292845baf300e0603551d1104073005880388370c300e0603551d
+0f0101ff04040302078030170603551d200101ff040d300b300906076781
+1201020104305b0603551d1f045430523027a025a0238621687474703a2f
+2f63692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a0
+25a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f43
+524c2d422e63726c300a06082a8648ce3d040302034700304402204b32a5
+c9ee05f29fd44a086ff04a109a88d6e5848039a516eec78ca4acf0c5b302
+20529e46fa109d130540bad62a46fc85c395b2c4cb9e8cf15079d49a9da5
+37dfe0'O;
+function f_ts_cert_s_sm_dp2auth_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp2auth_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp2auth_brp := f_ts_cert_s_sm_dp2auth_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPpb/CERT_S_SM_DPpb_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 101 (0x65)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Feb 1 13:38:57 2017 GMT
+ Not After : Feb 1 13:38:57 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:10:4c:2a:e3:d0:2d:ef:9c:97:92:61:a7:c6:71:
+ 00:76:b9:70:72:1d:09:55:a2:64:4a:e0:5f:ae:4b:
+ c2:31:4e:5d:c0:9f:6b:f0:11:80:26:16:53:42:e2:
+ 12:31:87:75:e3:65:f3:b5:73:25:37:30:66:b9:90:
+ 6e:0b:d1:38:8d
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Key Identifier:
+ E6:EA:F7:1E:E0:FB:94:30:EC:CD:1E:BB:42:1F:88:14:37:C1:32:63
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.10
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:43:02:1f:1d:c0:8e:8b:98:1f:4c:77:0c:e9:06:01:c5:2b:
+ 2a:28:e2:21:65:4b:d0:ba:a3:78:34:80:92:27:52:bf:f4:02:
+ 20:64:23:83:9e:85:e8:93:6f:7a:18:b2:b4:b8:5f:99:8c:4f:
+ 38:a8:db:9b:88:8c:23:e2:99:7c:9e:a5:af:6e:94
+*/
+const octetstring cert_s_sm_dppb_nist :=
+'30820235308201dda003020102020165300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303230313133333835375a
+170d3230303230313133333835375a3025310d300b060355040a0c044143
+4d453114301206035504030c0b5445535420534d2d44502b305930130607
+2a8648ce3d020106082a8648ce3d03010703420004104c2ae3d02def9c97
+9261a7c6710076b970721d0955a2644ae05fae4bc2314e5dc09f6bf01180
+26165342e212318775e365f3b57325373066b9906e0bd1388da381d93081
+d6301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d
+800a85c3301d0603551d0e04160414e6eaf71ee0fb9430eccd1ebb421f88
+1437c13263300e0603551d1104073005880388370a300e0603551d0f0101
+ff04040302078030170603551d200101ff040d300b300906076781120102
+0105305b0603551d1f045430523027a025a0238621687474703a2f2f6369
+2e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+422e63726c300a06082a8648ce3d0403020346003043021f1dc08e8b981f
+4c770ce90601c52b2a28e221654bd0baa3783480922752bff40220642383
+9e85e8936f7a18b2b4b85f998c4f38a8db9b888c23e2997c9ea5af6e94'O;
+function f_ts_cert_s_sm_dppb_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dppb_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dppb_nist := f_ts_cert_s_sm_dppb_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPpb/CERT_S_SM_DPpb_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 101 (0x65)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Apr 26 15:20:13 2017 GMT
+ Not After : Apr 25 15:20:13 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:89:32:53:ec:c9:4c:51:df:4f:ee:6e:0d:b0:95:
+ 1c:fc:65:62:74:81:b5:41:8e:55:70:69:f4:87:fa:
+ a1:54:66:a5:cb:8e:10:cc:2b:38:09:9c:f2:a9:29:
+ f7:f8:2d:ac:06:51:26:b7:1d:06:40:96:1d:b7:f9:
+ 1a:49:e9:56:12
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Key Identifier:
+ A8:C6:8D:F4:49:EB:71:EC:72:3E:AC:13:2E:40:E4:B6:F5:46:44:FE
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.10
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:5f:33:63:c1:01:b4:db:d0:2a:61:3c:8a:ca:32:
+ df:4f:2f:51:4c:21:73:e8:93:6e:9b:ff:af:02:a1:f5:e2:56:
+ 02:20:01:c0:99:36:19:43:29:65:fe:5a:87:a0:38:ae:91:bf:
+ 02:45:07:06:a3:2c:4b:13:07:af:4b:e8:ec:41:68:1d
+*/
+const octetstring cert_s_sm_dppb_brp :=
+'30820237308201dea003020102020165300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303432363135323031335a
+170d3230303432353135323031335a3025310d300b060355040a0c044143
+4d453114301206035504030c0b5445535420534d2d44502b305a30140607
+2a8648ce3d020106092b240303020801010703420004893253ecc94c51df
+4fee6e0db0951cfc65627481b5418e557069f487faa15466a5cb8e10cc2b
+38099cf2a929f7f82dac065126b71d0640961db7f91a49e95612a381d930
+81d6301f0603551d23041830168014c0bc70ba36929d43b467ff57570530
+e57ab8fcd8301d0603551d0e04160414a8c68df449eb71ec723eac132e40
+e4b6f54644fe300e0603551d1104073005880388370a300e0603551d0f01
+01ff04040302078030170603551d200101ff040d300b3009060767811201
+020105305b0603551d1f045430523027a025a0238621687474703a2f2f63
+692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a0
+238621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c
+2d422e63726c300a06082a8648ce3d040302034700304402205f3363c101
+b4dbd02a613c8aca32df4f2f514c2173e8936e9bffaf02a1f5e256022001
+c0993619432965fe5a87a038ae91bf02450706a32c4b1307af4be8ec4168
+1d'O;
+function f_ts_cert_s_sm_dppb_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dppb_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dppb_brp := f_ts_cert_s_sm_dppb_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPpb/CERT_S_SM_DP2pb_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 201 (0xc9)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Aug 21 14:23:52 2017 GMT
+ Not After : Aug 20 14:23:52 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+2"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:3e:2d:75:a1:06:22:12:16:c2:ae:e8:fa:d5:84:
+ f7:79:63:3c:f9:44:68:1b:5e:c7:5a:96:65:3f:5f:
+ 40:1c:47:6a:e3:9d:54:6c:03:2d:32:d0:07:0a:7b:
+ 86:e5:dc:eb:aa:dd:f3:1c:a5:c2:76:6c:19:6b:d7:
+ 9b:c2:1a:01:80
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Key Identifier:
+ 20:A3:A8:30:E9:2E:E7:A4:68:C5:EB:27:BA:8D:F1:84:59:AD:FD:D7
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.12
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:17:81:a1:df:74:e8:c6:60:88:67:17:b7:6c:fd:
+ ce:a0:2d:f7:b2:85:5a:5b:6c:5e:a9:cc:8d:ec:97:4c:e1:9b:
+ 02:21:00:ca:a8:9b:fb:af:26:13:02:1b:8f:7c:2c:63:59:44:
+ b3:5b:14:38:c0:09:e6:81:dc:e6:7a:58:b3:97:b8:f4:c1
+*/
+const octetstring cert_s_sm_dp2pb_nist :=
+'30820239308201dfa003020102020200c9300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730383231313432333532
+5a170d3230303832303134323335325a3026310d300b060355040a0c0441
+434d453115301306035504030c0c5445535420534d2d44502b3230593013
+06072a8648ce3d020106082a8648ce3d030107034200043e2d75a1062212
+16c2aee8fad584f779633cf944681b5ec75a96653f5f401c476ae39d546c
+032d32d0070a7b86e5dcebaaddf31ca5c2766c196bd79bc21a0180a381d9
+3081d6301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1
+c11d800a85c3301d0603551d0e0416041420a3a830e92ee7a468c5eb27ba
+8df18459adfdd7300e0603551d1104073005880388370c300e0603551d0f
+0101ff04040302078030170603551d200101ff040d300b30090607678112
+01020105305b0603551d1f045430523027a025a0238621687474703a2f2f
+63692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025
+a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f4352
+4c2d422e63726c300a06082a8648ce3d040302034800304502201781a1df
+74e8c660886717b76cfdcea02df7b2855a5b6c5ea9cc8dec974ce19b0221
+00caa89bfbaf2613021b8f7c2c635944b35b1438c009e681dce67a58b397
+b8f4c1'O
+function f_ts_cert_s_sm_dp2pb_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp2pb_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp2pb_nist := f_ts_cert_s_sm_dp2pb_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPpb/CERT_S_SM_DP2pb_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 201 (0xc9)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Aug 21 14:31:07 2017 GMT
+ Not After : Aug 20 14:31:07 2020 GMT
+ Subject: O = ACME, CN = "TEST SM-DP+2"
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:73:61:85:5e:59:02:64:b2:52:c7:1a:60:62:a0:
+ 21:e2:7b:46:f7:60:b8:13:82:06:a7:f7:44:20:ef:
+ 8b:c5:5a:8b:98:8d:16:58:f9:d7:0d:3a:2d:84:80:
+ aa:df:64:e6:2c:4d:71:27:de:5a:0a:2b:91:7a:94:
+ 3f:44:74:aa:dd
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Key Identifier:
+ 31:03:8A:55:B6:BE:CF:6C:EA:59:DE:2F:DA:14:F4:32:7F:B8:B6:A9
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.12
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.5
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:0b:2f:51:21:0c:e1:39:f1:80:69:54:a2:74:7b:
+ 18:bd:7b:39:0b:25:0c:4a:12:ae:8d:d2:1e:43:42:0e:3c:73:
+ 02:20:7b:e1:51:0d:c0:52:93:9e:c1:77:4e:3a:cd:d8:78:8d:
+ e9:47:49:fd:81:9a:28:6c:8d:c6:81:3a:45:64:9b:b4
+*/
+const octetstring cert_s_sm_dp2pb_brp :=
+'30820239308201e0a003020102020200c9300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730383231313433313037
+5a170d3230303832303134333130375a3026310d300b060355040a0c0441
+434d453115301306035504030c0c5445535420534d2d44502b32305a3014
+06072a8648ce3d020106092b2403030208010107034200047361855e5902
+64b252c71a6062a021e27b46f760b8138206a7f74420ef8bc55a8b988d16
+58f9d70d3a2d8480aadf64e62c4d7127de5a0a2b917a943f4474aadda381
+d93081d6301f0603551d23041830168014c0bc70ba36929d43b467ff5757
+0530e57ab8fcd8301d0603551d0e0416041431038a55b6becf6cea59de2f
+da14f4327fb8b6a9300e0603551d1104073005880388370c300e0603551d
+0f0101ff04040302078030170603551d200101ff040d300b300906076781
+1201020105305b0603551d1f045430523027a025a0238621687474703a2f
+2f63692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a0
+25a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f43
+524c2d422e63726c300a06082a8648ce3d040302034700304402200b2f51
+210ce139f1806954a2747b18bd7b390b250c4a12ae8dd21e43420e3c7302
+207be1510dc052939ec1774e3acdd8788de94749fd819a286c8dc6813a45
+649bb4'O;
+function f_ts_cert_s_sm_dp2pb_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp2pb_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp2pb_brp := f_ts_cert_s_sm_dp2pb_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPtls/CERT_S_SM_DP2_TLS.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 153 (0x99)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Sep 1 11:26:44 2017 GMT
+ Not After : Aug 31 11:26:44 2020 GMT
+ Subject: O = ACME, CN = testsmdpplus2.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:1a:d9:00:0c:75:4e:37:61:3e:75:0f:b7:bf:73:
+ 42:fe:d5:0b:c0:72:52:ed:84:65:6b:45:d6:f7:08:
+ 78:95:08:a9:ff:e0:96:17:23:af:11:ef:c8:dd:a6:
+ 9a:69:f2:b5:18:8b:b3:12:13:82:0a:b2:dd:1e:f5:
+ 80:2e:8f:d4:b6
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.3
+
+ X509v3 Subject Key Identifier:
+ 9F:5F:6B:0C:E7:00:32:25:2D:CE:10:D3:49:A6:55:18:1B:85:3E:CE
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testsmdpplus2.gsma.com, Registered ID:2.999.12
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:21:00:94:1a:fc:27:73:40:ce:05:d5:d4:1b:49:90:
+ d9:c5:d7:02:6c:7e:a7:3b:7a:07:0f:30:ad:69:b1:78:a3:e9:
+ 65:02:20:28:59:fb:74:a0:6f:d1:36:c3:9f:94:14:16:23:e3:
+ b5:88:ae:ef:d8:42:6d:2c:0b:df:51:3d:fe:58:7a:ac:31
+*/
+const octetstring cert_s_sm_dp2_tls :=
+'3082027c30820222a00302010202020099300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730393031313132363434
+5a170d3230303833313131323634345a3030310d300b060355040a0c0441
+434d45311f301d06035504030c1674657374736d6470706c7573322e6773
+6d612e636f6d3059301306072a8648ce3d020106082a8648ce3d03010703
+4200041ad9000c754e37613e750fb7bf7342fed50bc07252ed84656b45d6
+f708789508a9ffe0961723af11efc8dda69a69f2b5188bb31213820ab2dd
+1ef5802e8fd4b6a38201113082010d300e0603551d0f0101ff0404030207
+8030200603551d250101ff0416301406082b0601050507030106082b0601
+050507030230140603551d20040d300b3009060767811201020103301d06
+03551d0e041604149f5f6b0ce70032252dce10d349a655181b853ece301f
+0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d800a85
+c330260603551d11041f301d821674657374736d6470706c7573322e6773
+6d612e636f6d880388370c305b0603551d1f045430523027a025a0238621
+687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d412e
+63726c3027a025a0238621687474703a2f2f63692e746573742e67736d61
+2e636f6d2f43524c2d422e63726c300a06082a8648ce3d04030203480030
+45022100941afc277340ce05d5d41b4990d9c5d7026c7ea73b7a070f30ad
+69b178a3e96502202859fb74a06fd136c39f94141623e3b588aeefd8426d
+2c0bdf513dfe587aac31'O;
+function f_ts_cert_s_sm_dp2_tls() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp2_tls);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp2_tls := f_ts_cert_s_sm_dp2_tls();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPtls/CERT_S_SM_DP4_TLS.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2452 (0x994)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Dec 5 13:32:17 2017 GMT
+ Not After : Dec 4 13:32:17 2020 GMT
+ Subject: O = ACME, CN = testsmdpplus4.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:3a:db:e8:4d:23:a8:1a:f6:3b:a2:d8:99:83:6c:
+ bb:68:a7:62:56:b3:0d:70:26:30:3d:c3:6b:c1:5d:
+ f6:11:36:c4:fb:e7:02:01:b4:c5:a6:6e:3d:ac:6b:
+ 2b:3b:95:7a:99:bb:4e:74:10:03:e8:bf:74:2f:08:
+ 13:02:aa:7d:a6
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.3
+
+ X509v3 Subject Key Identifier:
+ 13:0F:3D:7B:B3:B0:65:AD:3C:58:78:76:BC:BB:6B:84:FD:49:7A:AB
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testsmdpplus4.gsma.com, Registered ID:2.999.14
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:6e:eb:6d:9e:59:01:39:c4:9a:2c:9b:d5:05:6e:
+ c9:a6:f6:03:73:29:62:da:e3:6e:d1:de:6d:fe:c1:31:95:8f:
+ 02:20:39:5c:3b:44:d5:de:84:73:ce:be:82:3d:33:5f:b4:fe:
+ 5b:2c:7f:47:3d:e6:5e:70:4a:ae:66:2a:6c:af:ec:5c
+*/
+const octetstring cert_s_sm_dp4_tls :=
+'3082027b30820222a00302010202020994300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313731323035313333323137
+5a170d3230313230343133333231375a3030310d300b060355040a0c0441
+434d45311f301d06035504030c1674657374736d6470706c7573342e6773
+6d612e636f6d3059301306072a8648ce3d020106082a8648ce3d03010703
+4200043adbe84d23a81af63ba2d899836cbb68a76256b30d7026303dc36b
+c15df61136c4fbe70201b4c5a66e3dac6b2b3b957a99bb4e741003e8bf74
+2f081302aa7da6a38201113082010d300e0603551d0f0101ff0404030207
+8030200603551d250101ff0416301406082b0601050507030106082b0601
+050507030230140603551d20040d300b3009060767811201020103301d06
+03551d0e04160414130f3d7bb3b065ad3c587876bcbb6b84fd497aab301f
+0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d800a85
+c330260603551d11041f301d821674657374736d6470706c7573342e6773
+6d612e636f6d880388370e305b0603551d1f045430523027a025a0238621
+687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d412e
+63726c3027a025a0238621687474703a2f2f63692e746573742e67736d61
+2e636f6d2f43524c2d422e63726c300a06082a8648ce3d04030203470030
+4402206eeb6d9e590139c49a2c9bd5056ec9a6f603732962dae36ed1de6d
+fec131958f0220395c3b44d5de8473cebe823d335fb4fe5b2c7f473de65e
+704aae662a6cafec5c'O;
+function f_ts_cert_s_sm_dp4_tls() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp4_tls);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp4_tls := f_ts_cert_s_sm_dp4_tls();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPtls/CERT_S_SM_DP8_TLS.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2456 (0x998)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Dec 5 13:37:06 2017 GMT
+ Not After : Dec 4 13:37:06 2020 GMT
+ Subject: O = ACME, CN = testsmdpplus8.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:ce:41:31:18:fa:64:99:6e:d8:b2:9b:fc:ac:85:
+ 33:83:e6:5d:3f:22:a1:99:e7:96:6b:f4:06:9a:69:
+ 58:39:2b:e5:39:d0:00:ea:51:a5:48:8b:10:87:d6:
+ eb:47:c0:01:84:6d:1e:68:7e:c4:90:e8:1a:80:96:
+ 49:42:0c:52:6b
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.3
+
+ X509v3 Subject Key Identifier:
+ B8:7E:0A:73:F2:44:D5:99:4C:28:61:E6:EA:6E:30:70:D6:34:2A:53
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testsmdpplus8.gsma.com, Registered ID:2.999.18
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:21:00:c1:74:e5:e3:ad:32:a9:6c:26:14:29:de:cd:
+ c3:09:e5:fe:8a:c1:9d:be:e2:54:73:94:e1:43:be:84:f0:33:
+ 4a:02:20:55:c4:13:42:f8:b4:f1:d2:2f:0f:31:20:3f:fe:27:
+ 75:69:6a:0c:72:89:86:7e:66:35:2a:03:ae:e2:b8:71:3c
+*/
+const octetstring cert_s_sm_dp8_tls :=
+'3082027c30820222a00302010202020998300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313731323035313333373036
+5a170d3230313230343133333730365a3030310d300b060355040a0c0441
+434d45311f301d06035504030c1674657374736d6470706c7573382e6773
+6d612e636f6d3059301306072a8648ce3d020106082a8648ce3d03010703
+420004ce413118fa64996ed8b29bfcac853383e65d3f22a199e7966bf406
+9a6958392be539d000ea51a5488b1087d6eb47c001846d1e687ec490e81a
+809649420c526ba38201113082010d300e0603551d0f0101ff0404030207
+8030200603551d250101ff0416301406082b0601050507030106082b0601
+050507030230140603551d20040d300b3009060767811201020103301d06
+03551d0e04160414b87e0a73f244d5994c2861e6ea6e3070d6342a53301f
+0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d800a85
+c330260603551d11041f301d821674657374736d6470706c7573382e6773
+6d612e636f6d8803883712305b0603551d1f045430523027a025a0238621
+687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d412e
+63726c3027a025a0238621687474703a2f2f63692e746573742e67736d61
+2e636f6d2f43524c2d422e63726c300a06082a8648ce3d04030203480030
+45022100c174e5e3ad32a96c261429decdc309e5fe8ac19dbee2547394e1
+43be84f0334a022055c41342f8b4f1d22f0f31203ffe2775696a0c728986
+7e66352a03aee2b8713c'O;
+function f_ts_cert_s_sm_dp8_tls() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp8_tls);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp8_tls := f_ts_cert_s_sm_dp8_tls();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPtls/CERT_S_SM_DP_TLS_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9 (0x9)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jun 29 12:21:14 2017 GMT
+ Not After : Jun 28 12:21:14 2020 GMT
+ Subject: O = ACME, CN = testsmdpplus1.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:28:24:30:75:ce:8e:fd:1f:ae:67:68:39:40:7d:
+ b2:6e:4c:cb:43:70:94:62:1c:9b:39:61:33:f1:b2:
+ 4b:b5:01:b8:fe:4e:b2:4d:3e:0d:39:2f:25:3f:6f:
+ 1b:94:62:70:b3:ca:29:2e:34:db:6f:7a:87:b3:a5:
+ f6:ac:94:5f:08
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.3
+
+ X509v3 Subject Key Identifier:
+ 27:FE:F1:F2:29:18:7E:C7:83:ED:F6:E0:29:64:A4:51:8D:57:D4:A9
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testsmdpplus1.gsma.com, Registered ID:2.999.10
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:2a:68:cf:75:5a:8b:0b:87:c9:41:25:6b:4d:af:
+ 4b:f2:09:6d:01:c8:3f:27:2b:cc:ce:63:df:d5:cc:5a:39:e3:
+ 02:21:00:b0:f5:02:4b:9e:aa:15:26:28:ab:19:77:21:a1:d1:
+ a5:9e:05:c0:2e:20:83:79:15:8c:d4:74:4d:37:48:67:8a
+*/
+const octetstring cert_s_sm_dp_tls_nist :=
+'3082027b30820221a003020102020109300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303632393132323131345a
+170d3230303632383132323131345a3030310d300b060355040a0c044143
+4d45311f301d06035504030c1674657374736d6470706c7573312e67736d
+612e636f6d3059301306072a8648ce3d020106082a8648ce3d0301070342
+000428243075ce8efd1fae676839407db26e4ccb437094621c9b396133f1
+b24bb501b8fe4eb24d3e0d392f253f6f1b946270b3ca292e34db6f7a87b3
+a5f6ac945f08a38201113082010d300e0603551d0f0101ff040403020780
+30200603551d250101ff0416301406082b0601050507030106082b060105
+0507030230140603551d20040d300b3009060767811201020103301d0603
+551d0e0416041427fef1f229187ec783edf6e02964a4518d57d4a9301f06
+03551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d800a85c3
+30260603551d11041f301d821674657374736d6470706c7573312e67736d
+612e636f6d880388370a305b0603551d1f045430523027a025a023862168
+7474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d412e63
+726c3027a025a0238621687474703a2f2f63692e746573742e67736d612e
+636f6d2f43524c2d422e63726c300a06082a8648ce3d0403020348003045
+02202a68cf755a8b0b87c941256b4daf4bf2096d01c83f272bccce63dfd5
+cc5a39e3022100b0f5024b9eaa152628ab197721a1d1a59e05c02e208379
+158cd4744d3748678a'O;
+function f_ts_cert_s_sm_dp_tls_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp_tls_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp_tls_nist := f_ts_cert_s_sm_dp_tls_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DP+/DPtls/CERT_S_SM_DP_TLS_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9 (0x9)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jul 6 13:49:28 2017 GMT
+ Not After : Jul 5 13:49:28 2020 GMT
+ Subject: O = ACME, CN = smdp-plus.test.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:4c:22:cc:d8:2c:8d:02:21:f9:d8:54:3b:72:e1:
+ 07:bc:c9:fd:90:54:d6:6c:75:c0:eb:74:a7:bd:e7:
+ 30:e7:61:8e:f6:5b:27:0b:5e:82:e4:3a:79:6f:8d:
+ ee:0b:af:8a:fb:eb:8a:53:62:53:7a:02:fd:65:c7:
+ 9e:41:19:6b:b5
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.3
+
+ X509v3 Subject Key Identifier:
+ 3D:33:09:83:F3:9F:CC:5B:D2:E4:AD:68:A6:19:A7:47:48:AE:8B:9D
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Alternative Name:
+ DNS:smdp-plus.test.gsma.com, Registered ID:2.999.10
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:4a:9c:78:38:89:c0:ef:f1:9d:68:c3:9f:67:d5:
+ b5:81:d3:c9:df:3e:1d:52:67:40:3a:e1:f1:ea:6f:1e:4c:d5:
+ 02:20:5a:9f:b1:a7:3b:5e:6f:1b:ac:a3:16:55:90:ec:56:c5:
+ 0a:91:25:ed:76:39:d6:c8:49:1c:a3:c8:3e:55:59:11
+*/
+const octetstring cert_s_sm_dp_tls_brp :=
+'3082027d30820224a003020102020109300a06082a8648ce3d0403023049
+3115301306035504030c0c47534d4120546573742043493111300f060355
+040b0c0854455354434552543110300e060355040a0c0752535054455354
+310b3009060355040613024954301e170d3137303730363133343932385a
+170d3230303730353133343932385a3031310d300b060355040a0c044143
+4d453120301e06035504030c17736d64702d706c75732e746573742e6773
+6d612e636f6d305a301406072a8648ce3d020106092b2403030208010107
+034200044c22ccd82c8d0221f9d8543b72e107bcc9fd9054d66c75c0eb74
+a7bde730e7618ef65b270b5e82e43a796f8dee0baf8afbeb8a5362537a02
+fd65c79e41196bb5a38201123082010e300e0603551d0f0101ff04040302
+078030200603551d250101ff0416301406082b0601050507030106082b06
+01050507030230140603551d20040d300b3009060767811201020103301d
+0603551d0e041604143d330983f39fcc5bd2e4ad68a619a74748ae8b9d30
+1f0603551d23041830168014c0bc70ba36929d43b467ff57570530e57ab8
+fcd830270603551d110420301e8217736d64702d706c75732e746573742e
+67736d612e636f6d880388370a305b0603551d1f045430523027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+412e63726c3027a025a0238621687474703a2f2f63692e746573742e6773
+6d612e636f6d2f43524c2d422e63726c300a06082a8648ce3d0403020347
+00304402204a9c783889c0eff19d68c39f67d5b581d3c9df3e1d5267403a
+e1f1ea6f1e4cd502205a9fb1a73b5e6f1baca3165590ec56c50a9125ed76
+39d6c8491ca3c83e555911'O;
+function f_ts_cert_s_sm_dp_tls_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dp_tls_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dp_tls_brp := f_ts_cert_s_sm_dp_tls_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DS/DSauth/CERT_S_SM_DSauth_ECDSA_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7495 (0x1d47)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jan 30 11:08:22 2017 GMT
+ Not After : Jan 30 11:08:22 2020 GMT
+ Subject: O = ACME, CN = TEST SM-DS
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:37:fb:94:e3:a2:be:fe:76:3e:1a:77:4a:48:54:
+ 88:0f:10:6d:80:f9:36:84:5b:ad:2f:dd:97:1b:c0:
+ 68:d8:ab:61:a5:48:1a:ee:97:7d:5a:81:68:bb:9f:
+ 79:00:4b:1d:00:72:c1:ba:76:73:b0:cb:64:81:6e:
+ 10:19:b2:4f:d0
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Subject Key Identifier:
+ C1:F4:06:4B:3B:25:8A:FB:61:38:8B:3F:F2:EE:6A:61:E2:C4:4D:72
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.15
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.7
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:21:00:d3:41:14:3c:60:cd:36:14:93:12:ed:a8:4d:
+ 40:08:7a:ee:cc:e9:7d:de:06:44:dc:e8:b7:6a:16:8f:e8:e2:
+ 61:02:20:09:d6:1d:c9:40:e3:13:08:33:32:78:77:44:0d:6f:
+ ac:eb:9f:6b:92:72:88:6b:f5:fa:a1:47:98:76:99:59:f2
+*/
+const octetstring cert_s_sm_dsauth_nist :=
+'30820237308201dda00302010202021d47300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730313330313130383232
+5a170d3230303133303131303832325a3024310d300b060355040a0c0441
+434d453113301106035504030c0a5445535420534d2d4453305930130607
+2a8648ce3d020106082a8648ce3d0301070342000437fb94e3a2befe763e
+1a774a4854880f106d80f936845bad2fdd971bc068d8ab61a5481aee977d
+5a8168bb9f79004b1d0072c1ba7673b0cb64816e1019b24fd0a381d93081
+d6301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1c11d
+800a85c3300e0603551d0f0101ff040403020780301d0603551d0e041604
+14c1f4064b3b258afb61388b3ff2ee6a61e2c44d72300e0603551d110407
+3005880388370f30170603551d200101ff040d300b300906076781120102
+0107305b0603551d1f045430523027a025a0238621687474703a2f2f6369
+2e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+422e63726c300a06082a8648ce3d0403020348003045022100d341143c60
+cd36149312eda84d40087aeecce97dde0644dce8b76a168fe8e261022009
+d61dc940e3130833327877440d6faceb9f6b9272886bf5faa14798769959
+f2'O;
+function f_ts_cert_s_sm_dsauth_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dsauth_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dsauth_nist := f_ts_cert_s_sm_dsauth_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DS/DSauth/CERT_S_SM_DSauth_ECDSA_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7495 (0x1d47)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: May 5 17:03:51 2017 GMT
+ Not After : May 4 17:03:51 2020 GMT
+ Subject: O = ACME, CN = TEST SM-DS
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:81:d1:d0:23:f3:9f:18:43:34:18:c2:8c:d2:3d:
+ 42:15:7a:43:9f:ed:d2:9e:59:ab:11:86:e1:30:89:
+ 81:96:c1:56:3a:13:f4:8b:36:d6:d4:b1:3b:4d:08:
+ 5a:57:60:ae:61:3d:06:1f:fe:6f:c7:a4:0c:65:02:
+ e3:ff:73:3c:31
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Subject Key Identifier:
+ F0:5F:0B:54:AE:E8:AE:01:08:F0:1D:EF:54:8E:D9:85:97:14:DD:48
+ X509v3 Subject Alternative Name:
+ Registered ID:2.999.15
+ X509v3 Certificate Policies: critical
+ Policy: 2.23.146.1.2.1.7
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:25:a0:29:5d:1a:46:6e:2d:07:48:83:c5:f9:43:
+ e2:fb:0a:72:ee:96:b5:75:95:d9:7d:91:b5:cb:b1:ea:6e:63:
+ 02:21:00:8d:4c:5b:4a:e7:48:86:82:28:72:15:0c:13:90:b9:
+ 64:39:f0:30:71:d2:4a:a4:11:45:5d:bb:16:2e:05:54:77
+*/
+const octetstring cert_s_sm_dsauth_brp :=
+'30820238308201dea00302010202021d47300a06082a8648ce3d04030230
+493115301306035504030c0c47534d4120546573742043493111300f0603
+55040b0c0854455354434552543110300e060355040a0c07525350544553
+54310b3009060355040613024954301e170d313730353035313730333531
+5a170d3230303530343137303335315a3024310d300b060355040a0c0441
+434d453113301106035504030c0a5445535420534d2d4453305a30140607
+2a8648ce3d020106092b24030302080101070342000481d1d023f39f1843
+3418c28cd23d42157a439fedd29e59ab1186e130898196c1563a13f48b36
+d6d4b13b4d085a5760ae613d061ffe6fc7a40c6502e3ff733c31a381d930
+81d6301f0603551d23041830168014c0bc70ba36929d43b467ff57570530
+e57ab8fcd8300e0603551d0f0101ff040403020780301d0603551d0e0416
+0414f05f0b54aee8ae0108f01def548ed9859714dd48300e0603551d1104
+073005880388370f30170603551d200101ff040d300b3009060767811201
+020107305b0603551d1f045430523027a025a0238621687474703a2f2f63
+692e746573742e67736d612e636f6d2f43524c2d412e63726c3027a025a0
+238621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c
+2d422e63726c300a06082a8648ce3d0403020348003045022025a0295d1a
+466e2d074883c5f943e2fb0a72ee96b57595d97d91b5cbb1ea6e63022100
+8d4c5b4ae74886822872150c1390b96439f03071d24aa411455dbb162e05
+5477'O;
+function f_ts_cert_s_sm_dsauth_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_dsauth_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_dsauth_brp := f_ts_cert_s_sm_dsauth_brp();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DS/DStls/CERT_SM_DS_TLS_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 77899973700 (0x1223334444)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jul 28 13:34:55 2017 GMT
+ Not After : Jul 27 13:34:55 2020 GMT
+ Subject: O = RSPTEST, CN = testrootsmds.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:92:0c:d5:ff:68:04:d8:7d:99:1d:ad:f6:38:c9:
+ b7:83:c5:85:00:a5:7b:a4:93:5b:9e:e2:ef:02:52:
+ b6:a6:dd:9a:50:1c:21:fd:35:42:6b:3b:51:c4:e4:
+ 61:e5:6c:3f:77:2e:69:5f:b8:61:7f:9a:74:82:30:
+ 4b:bb:2f:e2:84
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.6
+
+ X509v3 Subject Key Identifier:
+ A0:36:C1:62:75:35:1E:C7:B0:15:53:A1:3F:83:E2:8D:44:00:BD:0A
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testrootsmds.gsma.com, Registered ID:2.999.15
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:20:15:19:8e:b1:3b:3c:b2:cd:90:f2:02:c0:1c:
+ 55:88:0c:4b:94:64:5a:88:f2:87:2b:44:f4:fa:42:15:bb:64:
+ 02:21:00:8f:0d:7e:67:1f:bf:34:a4:0e:51:d2:11:2f:ca:21:
+ 47:0c:ba:c9:84:06:30:39:5b:66:66:60:61:d3:86:3e:33
+*/
+const octetstring cert_sm_ds_tls_nist :=
+'3082028030820226a00302010202051223334444300a06082a8648ce3d04
+030230493115301306035504030c0c47534d412054657374204349311130
+0f060355040b0c0854455354434552543110300e060355040a0c07525350
+54455354310b3009060355040613024954301e170d313730373238313333
+3435355a170d3230303732373133333435355a30323110300e060355040a
+0c0752535054455354311e301c06035504030c1574657374726f6f74736d
+64732e67736d612e636f6d3059301306072a8648ce3d020106082a8648ce
+3d03010703420004920cd5ff6804d87d991dadf638c9b783c58500a57ba4
+935b9ee2ef0252b6a6dd9a501c21fd35426b3b51c4e461e56c3f772e695f
+b8617f9a7482304bbb2fe284a38201103082010c300e0603551d0f0101ff
+04040302078030200603551d250101ff0416301406082b06010505070301
+06082b0601050507030230140603551d20040d300b300906076781120102
+0106301d0603551d0e04160414a036c16275351ec7b01553a13f83e28d44
+00bd0a301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1
+c11d800a85c330250603551d11041e301c821574657374726f6f74736d64
+732e67736d612e636f6d880388370f305b0603551d1f045430523027a025
+a0238621687474703a2f2f63692e746573742e67736d612e636f6d2f4352
+4c2d412e63726c3027a025a0238621687474703a2f2f63692e746573742e
+67736d612e636f6d2f43524c2d422e63726c300a06082a8648ce3d040302
+034800304502202015198eb13b3cb2cd90f202c01c55880c4b94645a88f2
+872b44f4fa4215bb640221008f0d7e671fbf34a40e51d2112fca21470cba
+c9840630395b66666061d3863e33'O;
+function f_ts_cert_sm_ds_tls_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_sm_ds_tls_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_sm_ds_tls_nist := f_ts_cert_sm_ds_tls_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DS/DStls/CERT_S_SM_DS2_TLS_NIST.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 81684042822800725 (0x122333444455555)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jul 31 09:36:23 2017 GMT
+ Not After : Jul 30 09:36:23 2020 GMT
+ Subject: O = RSPTEST, CN = testsmds1.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:19:d0:a3:31:cf:30:2c:7a:07:61:52:90:92:56:
+ 75:ad:14:62:cc:58:ba:57:b2:a8:fa:67:69:fd:65:
+ f5:c3:ad:34:d4:92:89:77:cf:57:39:30:ca:01:d8:
+ 61:15:a6:8d:45:a6:86:0c:7b:9d:b2:3d:82:18:58:
+ 11:41:8c:2a:09
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.6
+
+ X509v3 Subject Key Identifier:
+ 53:82:04:27:91:71:ED:3D:0A:79:C0:AD:61:A5:35:31:2C:86:48:6C
+ X509v3 Authority Key Identifier:
+ keyid:F5:41:72:BD:F9:8A:95:D6:5C:BE:B8:8A:38:A1:C1:1D:80:0A:85:C3
+
+ X509v3 Subject Alternative Name:
+ DNS:testsmds1.gsma.com, Registered ID:2.999.15.2
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:20:5c:b0:bd:6d:48:5b:13:21:c3:bf:28:37:22:a6:
+ 43:09:a5:d2:0e:8f:67:1b:d0:05:f3:f9:1e:17:6f:8b:a4:80:
+ 02:21:00:c7:73:03:63:64:ab:76:34:f2:61:24:99:d8:24:8c:
+ af:df:81:d1:6d:3c:2c:5b:d6:0c:4b:ee:60:68:31:c4:f1
+*/
+const octetstring cert_s_sm_ds2_tls_nist :=
+'3082027e30820224a00302010202080122333444455555300a06082a8648
+ce3d04030230493115301306035504030c0c47534d412054657374204349
+3111300f060355040b0c0854455354434552543110300e060355040a0c07
+52535054455354310b3009060355040613024954301e170d313730373331
+3039333632335a170d3230303733303039333632335a302f3110300e0603
+55040a0c0752535054455354311b301906035504030c1274657374736d64
+73312e67736d612e636f6d3059301306072a8648ce3d020106082a8648ce
+3d0301070342000419d0a331cf302c7a07615290925675ad1462cc58ba57
+b2a8fa6769fd65f5c3ad34d4928977cf573930ca01d86115a68d45a6860c
+7b9db23d82185811418c2a09a382010e3082010a300e0603551d0f0101ff
+04040302078030200603551d250101ff0416301406082b06010505070301
+06082b0601050507030230140603551d20040d300b300906076781120102
+0106301d0603551d0e04160414538204279171ed3d0a79c0ad61a535312c
+86486c301f0603551d23041830168014f54172bdf98a95d65cbeb88a38a1
+c11d800a85c330230603551d11041c301a821274657374736d6473312e67
+736d612e636f6d880488370f02305b0603551d1f045430523027a025a023
+8621687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d
+412e63726c3027a025a0238621687474703a2f2f63692e746573742e6773
+6d612e636f6d2f43524c2d422e63726c300a06082a8648ce3d0403020348
+00304502205cb0bd6d485b1321c3bf283722a64309a5d20e8f671bd005f3
+f91e176f8ba480022100c773036364ab7634f2612499d8248cafdf81d16d
+3c2c5bd60c4bee606831c4f1'O;
+function f_ts_cert_s_sm_ds2_tls_nist() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_ds2_tls_nist);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_ds2_tls_nist := f_ts_cert_s_sm_ds2_tls_nist();
+
+/* Test certificate:
+SGP.26_v1.2_files/Valid test cases/SM-DS/DStls/CERT_S_SM_DS_TLS_BRP.der
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1246399579205 (0x12233344445)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: CN = GSMA Test CI, OU = TESTCERT, O = RSPTEST, C = IT
+ Validity
+ Not Before: Jul 7 06:18:01 2017 GMT
+ Not After : Jul 6 06:18:01 2020 GMT
+ Subject: O = TESTCERT, CN = smds.test.gsma.com
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:39:ef:3f:92:a3:bc:a8:ef:7d:66:26:7f:1e:1a:
+ d8:b9:43:fd:2d:b2:27:cb:e1:a1:0b:f4:92:72:61:
+ 81:c4:81:5b:2a:31:60:7c:7d:e5:b3:1c:a0:22:1d:
+ ff:ed:ad:58:70:63:3d:30:ed:55:aa:bb:51:7a:e4:
+ 39:9c:4a:64:81
+ ASN1 OID: brainpoolP256r1
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage: critical
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Certificate Policies:
+ Policy: 2.23.146.1.2.1.6
+
+ X509v3 Subject Key Identifier:
+ 73:99:CA:C7:B1:5F:AB:2F:F9:33:CF:2D:22:15:E4:84:4A:DE:F8:05
+ X509v3 Authority Key Identifier:
+ keyid:C0:BC:70:BA:36:92:9D:43:B4:67:FF:57:57:05:30:E5:7A:B8:FC:D8
+
+ X509v3 Subject Alternative Name:
+ DNS:smds.test.gsma.com, Registered ID:2.999.15
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-A.crl
+
+ Full Name:
+ URI:http://ci.test.gsma.com/CRL-B.crl
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:18:56:2e:17:de:40:a4:93:18:dc:8e:a5:26:dc:
+ e5:71:9d:85:42:c8:5b:cc:2c:6c:86:a4:6a:58:db:b5:ce:1a:
+ 02:20:4a:91:75:54:26:98:e5:85:6e:27:57:41:0c:46:f2:fb:
+ 22:7e:04:2c:79:6a:99:77:69:5b:20:2e:89:49:c3:4d
+*/
+const octetstring cert_s_sm_ds_tls_brp :=
+'3082027c30820223a0030201020206012233344445300a06082a8648ce3d
+04030230493115301306035504030c0c47534d4120546573742043493111
+300f060355040b0c0854455354434552543110300e060355040a0c075253
+5054455354310b3009060355040613024954301e170d3137303730373036
+313830315a170d3230303730363036313830315a30303111300f06035504
+0a0c085445535443455254311b301906035504030c12736d64732e746573
+742e67736d612e636f6d305a301406072a8648ce3d020106092b24030302
+080101070342000439ef3f92a3bca8ef7d66267f1e1ad8b943fd2db227cb
+e1a10bf492726181c4815b2a31607c7de5b31ca0221dffedad5870633d30
+ed55aabb517ae4399c4a6481a382010d30820109300e0603551d0f0101ff
+04040302078030200603551d250101ff0416301406082b06010505070301
+06082b0601050507030230140603551d20040d300b300906076781120102
+0106301d0603551d0e041604147399cac7b15fab2ff933cf2d2215e4844a
+def805301f0603551d23041830168014c0bc70ba36929d43b467ff575705
+30e57ab8fcd830220603551d11041b30198212736d64732e746573742e67
+736d612e636f6d880388370f305b0603551d1f045430523027a025a02386
+21687474703a2f2f63692e746573742e67736d612e636f6d2f43524c2d41
+2e63726c3027a025a0238621687474703a2f2f63692e746573742e67736d
+612e636f6d2f43524c2d422e63726c300a06082a8648ce3d040302034700
+3044022018562e17de40a49318dc8ea526dce5719d8542c85bcc2c6c86a4
+6a58dbb5ce1a02204a9175542698e5856e2757410c46f2fb227e042c796a
+9977695b202e8949c34d'O;
+function f_ts_cert_s_sm_ds_tls_brp() return Certificate {
+ var Certificate cert_decoded;
+ cert_decoded := dec_Certificate(cert_s_sm_ds_tls_brp);
+ return cert_decoded;
+}
+template (value) Certificate ts_cert_s_sm_ds_tls_brp := f_ts_cert_s_sm_ds_tls_brp();
+
+}
diff --git a/library/euicc/PKIX1Explicit88_Types.ttcn b/library/euicc/PKIX1Explicit88_Types.ttcn
new file mode 100644
index 00000000..4f33f8cd
--- /dev/null
+++ b/library/euicc/PKIX1Explicit88_Types.ttcn
@@ -0,0 +1,42 @@
+module PKIX1Explicit88_Types {
+
+import from PKIX1Explicit88 all;
+import from Native_Functions all;
+
+external function dec_X520name(in octetstring stream) return X520name;
+external function enc_X520name(in X520name msg) return octetstring;
+
+external function dec_X520CommonName(in octetstring stream) return X520CommonName;
+external function enc_X520CommonName(in X520CommonName msg) return octetstring;
+
+external function dec_X520LocalityName(in octetstring stream) return X520LocalityName;
+external function enc_X520LocalityName(in X520LocalityName msg) return octetstring;
+
+external function dec_X520StateOrProvinceName(in octetstring stream) return X520StateOrProvinceName;
+external function enc_X520StateOrProvinceName(in X520StateOrProvinceName msg) return octetstring;
+
+external function dec_X520OrganizationName(in octetstring stream) return X520OrganizationName;
+external function enc_X520OrganizationName(in X520OrganizationName msg) return octetstring;
+
+external function dec_X520OrganizationalUnitName(in octetstring stream) return X520OrganizationalUnitName;
+external function enc_X520OrganizationalUnitName(in X520OrganizationalUnitName msg) return octetstring;
+
+external function dec_X520Title(in octetstring stream) return X520Title;
+external function enc_X520Title(in X520Title msg) return octetstring;
+
+external function dec_X520dnQualifier(in octetstring stream) return X520dnQualifier;
+external function enc_X520dnQualifier(in X520dnQualifier msg) return octetstring;
+
+external function dec_X520countryName(in octetstring stream) return X520countryName;
+external function enc_X520countryName(in X520countryName msg) return octetstring;
+
+external function dec_X520SerialNumber(in octetstring stream) return X520SerialNumber;
+external function enc_X520SerialNumber(in X520SerialNumber msg) return octetstring;
+
+external function dec_X520Pseudonym(in octetstring stream) return X520Pseudonym;
+external function enc_X520Pseudonym(in X520Pseudonym msg) return octetstring;
+
+external function dec_Certificate(in octetstring stream) return Certificate;
+external function enc_Certificate(in Certificate msg) return octetstring;
+
+}
diff --git a/library/euicc/PKIX1Implicit88.asn b/library/euicc/PKIX1Implicit88.asn
new file mode 100644
index 00000000..9b547a64
--- /dev/null
+++ b/library/euicc/PKIX1Implicit88.asn
@@ -0,0 +1,387 @@
+
+--
+-- ASN.1 module found by ./crfc2asn1.pl in rfc3280.txt at line 5850
+--
+
+PKIX1Implicit88 { iso(1) identified-organization(3) dod(6) internet(1)
+ security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19) }
+
+DEFINITIONS IMPLICIT TAGS ::=
+
+BEGIN
+
+-- EXPORTS ALL --
+
+IMPORTS
+ id-pe, id-kp, id-qt-unotice, id-qt-cps,
+ ORAddress, Name, RelativeDistinguishedName,
+ CertificateSerialNumber, Attribute, DirectoryString
+ FROM PKIX1Explicit88 { iso(1) identified-organization(3)
+ dod(6) internet(1) security(5) mechanisms(5) pkix(7)
+ id-mod(0) id-pkix1-explicit(18) };
+
+
+-- ISO arc for standard certificate and CRL extensions
+
+id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29}
+
+-- authority key identifier OID and syntax
+
+id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 }
+
+
+
+
+
+
+
+
+
+
+AuthorityKeyIdentifier ::= SEQUENCE {
+ keyIdentifier [0] KeyIdentifier OPTIONAL,
+ authorityCertIssuer [1] GeneralNames OPTIONAL,
+ authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ -- authorityCertIssuer and authorityCertSerialNumber MUST both
+ -- be present or both be absent
+
+KeyIdentifier ::= OCTET STRING
+
+-- subject key identifier OID and syntax
+
+id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 }
+
+SubjectKeyIdentifier ::= KeyIdentifier
+
+-- key usage extension OID and syntax
+
+id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
+
+KeyUsage ::= BIT STRING {
+ digitalSignature (0),
+ nonRepudiation (1),
+ keyEncipherment (2),
+ dataEncipherment (3),
+ keyAgreement (4),
+ keyCertSign (5),
+ cRLSign (6),
+ encipherOnly (7),
+ decipherOnly (8) }
+
+-- private key usage period extension OID and syntax
+
+id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 }
+
+PrivateKeyUsagePeriod ::= SEQUENCE {
+ notBefore [0] GeneralizedTime OPTIONAL,
+ notAfter [1] GeneralizedTime OPTIONAL }
+ -- either notBefore or notAfter MUST be present
+
+-- certificate policies extension OID and syntax
+
+id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 }
+
+anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 }
+
+CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+PolicyInformation ::= SEQUENCE {
+
+
+
+
+
+ policyIdentifier CertPolicyId,
+ policyQualifiers SEQUENCE SIZE (1..MAX) OF
+ PolicyQualifierInfo OPTIONAL }
+
+CertPolicyId ::= OBJECT IDENTIFIER
+
+PolicyQualifierInfo ::= SEQUENCE {
+ policyQualifierId PolicyQualifierId,
+ qualifier ANY DEFINED BY policyQualifierId }
+
+-- Implementations that recognize additional policy qualifiers MUST
+-- augment the following definition for PolicyQualifierId
+
+PolicyQualifierId ::=
+ OBJECT IDENTIFIER -- ( id-qt-cps | id-qt-unotice )
+
+-- CPS pointer qualifier
+
+CPSuri ::= IA5String
+
+-- user notice qualifier
+
+UserNotice ::= SEQUENCE {
+ noticeRef NoticeReference OPTIONAL,
+ explicitText DisplayText OPTIONAL}
+
+NoticeReference ::= SEQUENCE {
+ organization DisplayText,
+ noticeNumbers SEQUENCE OF INTEGER }
+
+DisplayText ::= CHOICE {
+ ia5String IA5String (SIZE (1..200)),
+ visibleString VisibleString (SIZE (1..200)),
+ bmpString BMPString (SIZE (1..200)),
+ utf8String UTF8String (SIZE (1..200)) }
+
+-- policy mapping extension OID and syntax
+
+id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 }
+
+PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
+ issuerDomainPolicy CertPolicyId,
+ subjectDomainPolicy CertPolicyId }
+
+-- subject alternative name extension OID and syntax
+
+id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 }
+
+
+
+
+
+
+SubjectAltName ::= GeneralNames
+
+GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+
+GeneralName ::= CHOICE {
+ otherName [0] AnotherName,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ORAddress,
+ directoryName [4] Name,
+ ediPartyName [5] EDIPartyName,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER }
+
+-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as
+-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax
+
+AnotherName ::= SEQUENCE {
+ type-id OBJECT IDENTIFIER,
+ value [0] EXPLICIT ANY DEFINED BY type-id }
+
+EDIPartyName ::= SEQUENCE {
+ nameAssigner [0] DirectoryString OPTIONAL,
+ partyName [1] DirectoryString }
+
+-- issuer alternative name extension OID and syntax
+
+id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 }
+
+IssuerAltName ::= GeneralNames
+
+id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 }
+
+SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+
+-- basic constraints extension OID and syntax
+
+id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
+
+BasicConstraints ::= SEQUENCE {
+ cA BOOLEAN DEFAULT FALSE,
+ pathLenConstraint INTEGER (0..MAX) OPTIONAL }
+
+-- name constraints extension OID and syntax
+
+id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 }
+
+
+
+
+
+
+NameConstraints ::= SEQUENCE {
+ permittedSubtrees [0] GeneralSubtrees OPTIONAL,
+ excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+
+GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+
+GeneralSubtree ::= SEQUENCE {
+ base GeneralName,
+ minimum [0] BaseDistance DEFAULT 0,
+ maximum [1] BaseDistance OPTIONAL }
+
+BaseDistance ::= INTEGER (0..MAX)
+
+-- policy constraints extension OID and syntax
+
+id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 }
+
+PolicyConstraints ::= SEQUENCE {
+ requireExplicitPolicy [0] SkipCerts OPTIONAL,
+ inhibitPolicyMapping [1] SkipCerts OPTIONAL }
+
+SkipCerts ::= INTEGER (0..MAX)
+
+-- CRL distribution points extension OID and syntax
+
+id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31}
+
+CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+DistributionPoint ::= SEQUENCE {
+ distributionPoint [0] DistributionPointName OPTIONAL,
+ reasons [1] ReasonFlags OPTIONAL,
+ cRLIssuer [2] GeneralNames OPTIONAL }
+
+DistributionPointName ::= CHOICE {
+ fullName [0] GeneralNames,
+ nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
+
+ReasonFlags ::= BIT STRING {
+ unused (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ privilegeWithdrawn (7),
+ aACompromise (8) }
+
+
+
+
+
+-- extended key usage extension OID and syntax
+
+id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37}
+
+ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+
+
+KeyPurposeId ::= OBJECT IDENTIFIER
+
+-- permit unspecified key uses
+
+anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
+
+-- extended key purpose OIDs
+
+id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
+id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
+id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
+id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
+id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
+id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
+
+-- inhibit any policy OID and syntax
+
+id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 }
+
+InhibitAnyPolicy ::= SkipCerts
+
+-- freshest (delta)CRL extension OID and syntax
+
+id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 }
+
+FreshestCRL ::= CRLDistributionPoints
+
+-- authority info access
+
+id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+
+AuthorityInfoAccessSyntax ::=
+ SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+AccessDescription ::= SEQUENCE {
+ accessMethod OBJECT IDENTIFIER,
+ accessLocation GeneralName }
+
+-- subject info access
+
+id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 }
+
+
+
+
+
+SubjectInfoAccessSyntax ::=
+ SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+-- CRL number extension OID and syntax
+
+id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 }
+
+CRLNumber ::= INTEGER (0..MAX)
+
+-- issuing distribution point extension OID and syntax
+
+id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 }
+
+IssuingDistributionPoint ::= SEQUENCE {
+ distributionPoint [0] DistributionPointName OPTIONAL,
+ onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE,
+ onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE,
+ onlySomeReasons [3] ReasonFlags OPTIONAL,
+ indirectCRL [4] BOOLEAN DEFAULT FALSE,
+ onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+
+id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 }
+
+BaseCRLNumber ::= CRLNumber
+
+-- CRL reasons extension OID and syntax
+
+id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 }
+
+CRLReason ::= ENUMERATED {
+ unspecified (0),
+ keyCompromise (1),
+ cACompromise (2),
+ affiliationChanged (3),
+ superseded (4),
+ cessationOfOperation (5),
+ certificateHold (6),
+ removeFromCRL (8),
+ privilegeWithdrawn (9),
+ aACompromise (10) }
+
+-- certificate issuer CRL entry extension OID and syntax
+
+id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 }
+
+CertificateIssuer ::= GeneralNames
+
+-- hold instruction extension OID and syntax
+
+
+
+
+
+id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 }
+
+HoldInstructionCode ::= OBJECT IDENTIFIER
+
+-- ANSI x9 holdinstructions
+
+-- ANSI x9 arc holdinstruction arc
+
+holdInstruction OBJECT IDENTIFIER ::=
+ {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2}
+
+-- ANSI X9 holdinstructions referenced by this standard
+
+id-holdinstruction-none OBJECT IDENTIFIER ::=
+ {holdInstruction 1} -- deprecated
+
+id-holdinstruction-callissuer OBJECT IDENTIFIER ::=
+ {holdInstruction 2}
+
+id-holdinstruction-reject OBJECT IDENTIFIER ::=
+ {holdInstruction 3}
+
+-- invalidity date CRL entry extension OID and syntax
+
+id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 }
+
+InvalidityDate ::= GeneralizedTime
+
+END \ No newline at end of file
diff --git a/library/euicc/PKIX1Implicit88_EncDec.cc b/library/euicc/PKIX1Implicit88_EncDec.cc
new file mode 100644
index 00000000..7ce2b167
--- /dev/null
+++ b/library/euicc/PKIX1Implicit88_EncDec.cc
@@ -0,0 +1,26 @@
+#include "PKIX1Implicit88.hh"
+
+namespace PKIX1Implicit88__Types {
+
+using namespace PKIX1Implicit88;
+
+TTCN_Module PKIX1Implicit88__EncDec("PKIX1Implicit88_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__SubjectKeyIdentifier(const SubjectKeyIdentifier &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(SubjectKeyIdentifier_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+SubjectKeyIdentifier dec__SubjectKeyIdentifier(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ SubjectKeyIdentifier msg;
+ buf.put_os(stream);
+
+ msg.decode(SubjectKeyIdentifier_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+}
diff --git a/library/euicc/PKIX1Implicit88_Templates.ttcn b/library/euicc/PKIX1Implicit88_Templates.ttcn
new file mode 100644
index 00000000..53401ff6
--- /dev/null
+++ b/library/euicc/PKIX1Implicit88_Templates.ttcn
@@ -0,0 +1,16 @@
+/* PKIX1 Templates in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * 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 PKIX1Implicit88_Templates {
+
+import from PKIX1Implicit88_Types all;
+import from PKIX1Implicit88 all;
+
+}
diff --git a/library/euicc/PKIX1Implicit88_Types.ttcn b/library/euicc/PKIX1Implicit88_Types.ttcn
new file mode 100644
index 00000000..f816c6e8
--- /dev/null
+++ b/library/euicc/PKIX1Implicit88_Types.ttcn
@@ -0,0 +1,9 @@
+module PKIX1Implicit88_Types {
+
+import from PKIX1Implicit88 all;
+import from Native_Functions all;
+
+external function dec_SubjectKeyIdentifier(in octetstring stream) return SubjectKeyIdentifier;
+external function enc_SubjectKeyIdentifier(in SubjectKeyIdentifier msg) return octetstring;
+
+}
diff --git a/library/euicc/RSPDefinitions.asn b/library/euicc/RSPDefinitions.asn
new file mode 100644
index 00000000..56dd1afc
--- /dev/null
+++ b/library/euicc/RSPDefinitions.asn
@@ -0,0 +1,825 @@
+--Version V2.5
+RSPDefinitions {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1)
+asn1modules(1) sgp22v2(2)}
+DEFINITIONS
+AUTOMATIC TAGS
+EXTENSIBILITY IMPLIED ::=
+BEGIN
+
+IMPORTS Certificate, CertificateList, Time FROM PKIX1Explicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18)}
+SubjectKeyIdentifier FROM PKIX1Implicit88 {iso(1) identified-organization(3) dod(6)
+internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19)}
+UICCCapability FROM PEDefinitions {joint-iso-itu-t(2) international-organizations(23) tca(143) euicc-profile(1) spec-version(1) version-three(3)};
+-- The UICCCapability import module version is defined in section 5.7.8
+
+id-rsp OBJECT IDENTIFIER ::= {joint-iso-itu-t(2) international-organizations(23)
+gsma(146) rsp(1)}
+
+-- Basic types, for size constraints
+Octet8 ::= OCTET STRING (SIZE(8))
+Octet4 ::= OCTET STRING (SIZE(4))
+Octet16 ::= OCTET STRING (SIZE(16))
+OctetTo16 ::= OCTET STRING (SIZE(1..16))
+Octet32 ::= OCTET STRING (SIZE(32))
+Octet1 ::= OCTET STRING(SIZE(1))
+Octet2 ::= OCTET STRING (SIZE(2))
+VersionType ::= OCTET STRING(SIZE(3)) -- major/minor/revision version are coded as binary value on byte 1/2/3, e.g. '02 00 0C' for v2.0.12.
+-- If revision is not used (e.g. v2.1), byte 3 SHALL be set to '00'.
+Iccid ::= [APPLICATION 26] OCTET STRING (SIZE(10)) -- ICCID as coded in EFiccid, corresponding tag is '5A'
+RemoteOpId ::= [2] INTEGER {installBoundProfilePackage(1)}
+TransactionId ::= OCTET STRING (SIZE(1..16))
+
+-- Definition of EUICCInfo1 --------------------------
+GetEuiccInfo1Request ::= [32] SEQUENCE { -- Tag 'BF20'
+}
+
+EUICCInfo1 ::= [32] SEQUENCE { -- Tag 'BF20'
+ svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
+ euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification
+ euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier -- List of CI Public Key Identifier supported on the eUICC for signature creation
+}
+
+-- Definition of EUICCInfo2 --------------------------
+GetEuiccInfo2Request ::= [34] SEQUENCE { -- Tag 'BF22'
+}
+
+EUICCInfo2 ::= [34] SEQUENCE { -- Tag 'BF22'
+ profileVersion [1] VersionType, -- Base eUICC Profile package version supported
+ svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
+ euiccFirmwareVer [3] VersionType, -- eUICC Firmware version
+ extCardResource [4] OCTET STRING, -- Extended Card Resource Information according to ETSI TS 102 226
+ uiccCapability [5] UICCCapability,
+ ts102241Version [6] VersionType OPTIONAL,
+ globalplatformVersion [7] VersionType OPTIONAL,
+ rspCapability [8] RspCapability,
+ euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification
+ euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifier supported on the eUICC for signature creation
+ euiccCategory [11] INTEGER {
+ other(0),
+ basicEuicc(1),
+ mediumEuicc(2),
+ contactlessEuicc(3)
+ } OPTIONAL,
+ forbiddenProfilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
+ ppVersion VersionType, -- Protection Profile version
+ sasAcreditationNumber UTF8String (SIZE(0..64)),
+ certificationDataObject [12] CertificationDataObject OPTIONAL,
+ treProperties [13] BIT STRING {
+ isDiscrete(0),
+ isIntegrated(1),
+ usesRemoteMemory(2) -- refers to the usage of remote memory protected by the Remote Memory Protection Function described in SGP.21 [4]
+ } OPTIONAL,
+ treProductReference [14] UTF8String OPTIONAL, -- Platform_Label as defined in GlobalPlatform DLOA specification [57]
+ additionalEuiccProfilePackageVersions [15] SEQUENCE OF VersionType OPTIONAL
+}
+
+-- Definition of RspCapability
+RspCapability ::= BIT STRING {
+ additionalProfile(0), -- at least one more Profile can be installed
+ crlSupport(1), -- CRL
+ rpmSupport(2), -- Remote Profile Management
+ testProfileSupport (3), -- support for test profile
+ deviceInfoExtensibilitySupport (4), -- support for ASN.1 extensibility in the Device Info
+ serviceSpecificDataSupport (5) -- support for Service Specific Data in the Profile Metadata
+}
+
+-- Definition of CertificationDataObject
+CertificationDataObject ::= SEQUENCE {
+ platformLabel UTF8String, -- Platform_Label as defined in GlobalPlatform DLOA specification [57]
+ discoveryBaseURL UTF8String -- Discovery Base URL of the SE default DLOA Registrar as defined in GlobalPlatform DLOA specification [57]
+}
+
+CertificateInfo ::= BIT STRING {
+ reserved(0), -- eUICC has a CERT.EUICC.ECDSA in GlobalPlatform format. The use of this bit is deprecated.
+ certSigningX509(1), -- eUICC has a CERT.EUICC.ECDSA in X.509 format
+ rfu2(2),
+ rfu3(3),
+ reserved2(4), -- Handling of Certificate in GlobalPlatform format. The use of this bit is deprecated.
+ certVerificationX509(5)-- Handling of Certificate in X.509 format
+}
+
+
+-- Definition of DeviceInfo
+DeviceInfo ::= SEQUENCE {
+ tac Octet4,
+ deviceCapabilities DeviceCapabilities,
+ imei Octet8 OPTIONAL
+}
+
+DeviceCapabilities ::= SEQUENCE { -- Highest fully supported release for each definition
+ -- The device SHALL set all the capabilities it supports
+ gsmSupportedRelease VersionType OPTIONAL,
+ utranSupportedRelease VersionType OPTIONAL,
+ cdma2000onexSupportedRelease VersionType OPTIONAL,
+ cdma2000hrpdSupportedRelease VersionType OPTIONAL,
+ cdma2000ehrpdSupportedRelease VersionType OPTIONAL,
+ eutranEpcSupportedRelease VersionType OPTIONAL,
+ contactlessSupportedRelease VersionType OPTIONAL,
+ rspCrlSupportedVersion VersionType OPTIONAL,
+ nrEpcSupportedRelease VersionType OPTIONAL,
+ nr5gcSupportedRelease VersionType OPTIONAL,
+ eutran5gcSupportedRelease VersionType OPTIONAL,
+ lpaSvn VersionType OPTIONAL, -- Not defined in this version of SGP.22
+ catSupportedClasses CatSupportedClasses OPTIONAL, -- Not defined in this version of SGP.22
+ euiccFormFactorType EuiccFormFactorType OPTIONAL, -- Not defined in this version of SGP.22
+ deviceAdditionalFeatureSupport DeviceAdditionalFeatureSupport OPTIONAL
+}
+
+-- Definition of DeviceAdditionalFeatureSupport
+DeviceAdditionalFeatureSupport ::= SEQUENCE {
+ naiSupport VersionType OPTIONAL -- Device supports Network Access Identifier
+}
+
+CatSupportedClasses ::= BIT STRING
+EuiccFormFactorType ::= INTEGER
+
+
+ProfileInfoListRequest ::= [45] SEQUENCE { -- Tag 'BF2D'
+ searchCriteria [0] CHOICE {
+ isdpAid [APPLICATION 15] OctetTo16, -- AID of the ISD-P, tag '4F'
+ iccid Iccid, -- ICCID, tag '5A'
+ profileClass [21] ProfileClass -- Tag '95'
+ } OPTIONAL,
+ tagList [APPLICATION 28] OCTET STRING OPTIONAL -- tag '5C'
+}
+
+-- Definition of ProfileInfoList
+ProfileInfoListResponse ::= [45] CHOICE { -- Tag 'BF2D'
+ profileInfoListOk SEQUENCE OF ProfileInfo,
+ profileInfoListError ProfileInfoListError
+}
+
+ProfileInfo ::= [PRIVATE 3] SEQUENCE { -- Tag 'E3'
+ iccid Iccid OPTIONAL,
+ isdpAid [APPLICATION 15] OctetTo16 OPTIONAL, -- AID of the ISD-P containing the Profile, tag '4F'
+ profileState [112] ProfileState OPTIONAL, -- Tag '9F70'
+ profileNickname [16] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '90'
+ serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91'
+ profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92'
+ iconType [19] IconType OPTIONAL, -- Tag '93'
+ icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94', see condition in ES10c:GetProfilesInfo
+ profileClass [21] ProfileClass OPTIONAL, -- Tag '95'
+ notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL, -- Tag 'B6'
+ profileOwner [23] OperatorId OPTIONAL, -- Tag 'B7'
+ dpProprietaryData [24] DpProprietaryData OPTIONAL, -- Tag 'B8'
+ profilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
+ serviceSpecificDataStoredInEuicc [34] VendorSpecificExtension OPTIONAL -- Tag 'BF22'
+}
+
+PprIds ::= BIT STRING {-- Definition of Profile Policy Rules identifiers
+ pprUpdateControl(0), -- defines how to update PPRs via ES6
+ ppr1(1), -- Indicator for PPR1 'Disabling of this Profile is not allowed'
+ ppr2(2) -- Indicator for PPR2 'Deletion of this Profile is not allowed'
+}
+
+OperatorId ::= SEQUENCE {
+ mccMnc OCTET STRING (SIZE(3)), -- MCC and MNC coded as defined in 3GPP TS 24.008 [32]
+ gid1 OCTET STRING OPTIONAL, -- referring to content of EF GID1 (file identifier '6F3E') as defined in 3GPP TS 31.102 [54]
+ gid2 OCTET STRING OPTIONAL -- referring to content of EF GID2 (file identifier '6F3F') as defined in 3GPP TS 31.102 [54]
+}
+
+ProfileInfoListError ::= INTEGER {incorrectInputValues(1), undefinedError(127)}
+
+-- Definition of StoreMetadata request
+
+StoreMetadataRequest ::= [37] SEQUENCE { -- Tag 'BF25'
+ iccid Iccid,
+ serviceProviderName [17] UTF8String (SIZE(0..32)), -- Tag '91'
+ profileName [18] UTF8String (SIZE(0..64)), -- Tag '92' (corresponds to 'Short Description' defined in SGP.21 [2])
+ iconType [19] IconType OPTIONAL, -- Tag '93' (JPG or PNG)
+ icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94'(Data of the icon. Size 64 x 64 pixel. This field SHALL only be present if iconType is present)
+ profileClass [21] ProfileClass DEFAULT operational, -- Tag '95'
+ notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL,
+ profileOwner [23] OperatorId OPTIONAL, -- Tag 'B7'
+ profilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
+ serviceSpecificDataStoredInEuicc [34] VendorSpecificExtension OPTIONAL, -- Tag 'BF22'
+ serviceSpecificDataNotStoredInEuicc [35] VendorSpecificExtension OPTIONAL -- Tag 'BF23'
+}
+
+NotificationEvent ::= BIT STRING {
+ notificationInstall(0),
+ notificationEnable(1),
+ notificationDisable(2),
+ notificationDelete(3)
+}
+
+NotificationConfigurationInformation ::= SEQUENCE {
+ profileManagementOperation NotificationEvent,
+ notificationAddress UTF8String -- FQDN to forward the notification
+}
+
+OPENTYPE ::= CLASS {
+ &typeId OBJECT IDENTIFIER,
+ &Type
+}
+
+VendorSpecificExtension ::= SEQUENCE OF SEQUENCE {
+ vendorOid [0] OPENTYPE.&typeId, -- OID of the vendor who defined this specific extension
+ vendorSpecificData [1] OPENTYPE.&Type
+}
+
+IconType ::= INTEGER {jpg(0), png(1)}
+ProfileState ::= INTEGER {disabled(0), enabled(1)}
+ProfileClass ::= INTEGER {test(0), provisioning(1), operational(2)}
+
+-- Definition of UpdateMetadata request
+UpdateMetadataRequest ::= [42] SEQUENCE { -- Tag 'BF2A'
+ serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91'
+ profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92'
+ iconType [19] IconType OPTIONAL, -- Tag '93'
+ icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94'
+ profilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
+ serviceSpecificDataStoredInEuicc [34] VendorSpecificExtension OPTIONAL -- Tag 'BF22'
+}
+
+-- Definition of data objects for command PrepareDownload -------------------------
+PrepareDownloadRequest ::= [33] SEQUENCE { -- Tag 'BF21'
+ smdpSigned2 SmdpSigned2, -- Signed information
+ smdpSignature2 [APPLICATION 55] OCTET STRING, -- DP_Sign1, tag '5F37'
+ hashCc Octet32 OPTIONAL, -- Hash of confirmation code
+ smdpCertificate Certificate -- CERT.DPpb.ECDSA
+}
+
+SmdpSigned2 ::= SEQUENCE {
+ transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
+ ccRequiredFlag BOOLEAN, --Indicates if the Confirmation Code is required
+ bppEuiccOtpk [APPLICATION 73] OCTET STRING OPTIONAL -- otPK.EUICC.ECKA already used for binding the BPP, tag '5F49'
+}
+
+PrepareDownloadResponse ::= [33] CHOICE { -- Tag 'BF21'
+ downloadResponseOk PrepareDownloadResponseOk,
+ downloadResponseError PrepareDownloadResponseError
+}
+
+PrepareDownloadResponseOk ::= SEQUENCE {
+ euiccSigned2 EUICCSigned2, -- Signed information
+ euiccSignature2 [APPLICATION 55] OCTET STRING -- tag '5F37'
+}
+
+EUICCSigned2 ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ euiccOtpk [APPLICATION 73] OCTET STRING, -- otPK.EUICC.ECKA, tag '5F49'
+ hashCc Octet32 OPTIONAL -- Hash of confirmation code
+}
+
+PrepareDownloadResponseError ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ downloadErrorCode DownloadErrorCode
+}
+
+DownloadErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2),
+unsupportedCurve(3), noSessionContext(4), invalidTransactionId(5),
+undefinedError(127)}
+
+-- Definition of data objects for command AuthenticateServer--------------------
+AuthenticateServerRequest ::= [56] SEQUENCE { -- Tag 'BF38'
+ serverSigned1 ServerSigned1, -- Signed information
+ serverSignature1 [APPLICATION 55] OCTET STRING, -- tag ‘5F37’
+ euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- CI Public Key Identifier to be used
+ serverCertificate Certificate, -- RSP Server Certificate CERT.XXauth.ECDSA
+ ctxParams1 CtxParams1
+}
+
+ServerSigned1 ::= SEQUENCE {
+ transactionId [0] TransactionId, -- The Transaction ID generated by the RSP Server
+ euiccChallenge [1] Octet16, -- The eUICC Challenge
+ serverAddress [3] UTF8String, -- The RSP Server address
+ serverChallenge [4] Octet16 -- The RSP Server Challenge
+}
+
+CtxParams1 ::= CHOICE {
+ ctxParamsForCommonAuthentication CtxParamsForCommonAuthentication -- New contextual data objects MAY be defined for extensibility
+}
+
+CtxParamsForCommonAuthentication ::= SEQUENCE {
+ matchingId UTF8String OPTIONAL,-- The MatchingId could be the Activation code token or EventID or empty
+ deviceInfo DeviceInfo -- The Device information
+}
+
+AuthenticateServerResponse ::= [56] CHOICE { -- Tag 'BF38'
+ authenticateResponseOk AuthenticateResponseOk,
+ authenticateResponseError AuthenticateResponseError
+}
+
+AuthenticateResponseOk ::= SEQUENCE {
+ euiccSigned1 EuiccSigned1, -- Signed information
+ euiccSignature1 [APPLICATION 55] OCTET STRING, --EUICC_Sign1, tag 5F37
+ euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM
+ eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI
+}
+
+EuiccSigned1 ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ serverAddress [3] UTF8String,
+ serverChallenge [4] Octet16, -- The RSP Server Challenge
+ euiccInfo2 [34] EUICCInfo2,
+ ctxParams1 CtxParams1
+}
+
+AuthenticateResponseError ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ authenticateErrorCode AuthenticateErrorCode
+}
+
+AuthenticateErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2),
+unsupportedCurve(3), noSessionContext(4), invalidOid(5), euiccChallengeMismatch(6),
+ciPKUnknown(7), undefinedError(127)}
+
+-- Definition of Cancel Session------------------------------
+CancelSessionRequest ::= [65] SEQUENCE { -- Tag 'BF41'
+ transactionId TransactionId, -- The TransactionID generated by the RSP Server
+ reason CancelSessionReason
+}
+
+CancelSessionReason ::= INTEGER {endUserRejection(0), postponed(1), timeout(2),
+pprNotAllowed(3), metadataMismatch(4), loadBppExecutionError(5),
+undefinedReason(127)}
+
+CancelSessionResponse ::= [65] CHOICE { -- Tag 'BF41'
+ cancelSessionResponseOk CancelSessionResponseOk,
+ cancelSessionResponseError INTEGER {invalidTransactionId(5),
+undefinedError(127)}
+}
+
+CancelSessionResponseOk ::= SEQUENCE {
+ euiccCancelSessionSigned EuiccCancelSessionSigned, -- Signed information
+ euiccCancelSessionSignature [APPLICATION 55] OCTET STRING -- tag '5F37
+}
+
+EuiccCancelSessionSigned ::= SEQUENCE {
+ transactionId TransactionId,
+ smdpOid OBJECT IDENTIFIER, -- SM-DP+ OID as contained in CERT.DPauth.ECDSA
+ reason CancelSessionReason
+}
+
+-- Definition of Bound Profile Package --------------------------
+BoundProfilePackage ::= [54] SEQUENCE { -- Tag 'BF36'
+ initialiseSecureChannelRequest [35] InitialiseSecureChannelRequest, -- Tag 'BF23'
+ firstSequenceOf87 [0] SEQUENCE OF [7] OCTET STRING, -- sequence of '87' TLVs
+ sequenceOf88 [1] SEQUENCE OF [8] OCTET STRING, -- sequence of '88' TLVs
+ secondSequenceOf87 [2] SEQUENCE OF [7] OCTET STRING OPTIONAL, -- sequence of '87' TLVs
+ sequenceOf86 [3] SEQUENCE OF [6] OCTET STRING -- sequence of '86' TLVs
+}
+
+-- Definition of Get eUICC Challenge --------------------------
+GetEuiccChallengeRequest ::= [46] SEQUENCE { -- Tag 'BF2E'
+}
+
+GetEuiccChallengeResponse ::= [46] SEQUENCE { -- Tag 'BF2E'
+ euiccChallenge Octet16 -- random eUICC challenge
+}
+
+-- Definition of Profile Installation Result
+ProfileInstallationResult ::= [55] SEQUENCE { -- Tag 'BF37'
+ profileInstallationResultData [39] ProfileInstallationResultData,
+ euiccSignPIR EuiccSignPIR
+}
+
+ProfileInstallationResultData ::= [39] SEQUENCE { -- Tag 'BF27'
+ transactionId[0] TransactionId, -- The TransactionID generated by the SM-DP+
+ notificationMetadata[47] NotificationMetadata,
+ smdpOid OBJECT IDENTIFIER, -- SM-DP+ OID (same value as in CERT.DPpb.ECDSA)
+ finalResult [2] CHOICE {
+ successResult SuccessResult,
+ errorResult ErrorResult
+ }
+}
+
+EuiccSignPIR ::= [APPLICATION 55] OCTET STRING -- Tag '5F37', eUICC’s signature
+
+SuccessResult ::= SEQUENCE {
+ aid [APPLICATION 15] OCTET STRING (SIZE (5..16)), -- AID of ISD-P
+ simaResponse OCTET STRING -- contains (multiple) 'EUICCResponse' as defined in [5]
+}
+
+ErrorResult ::= SEQUENCE {
+ bppCommandId BppCommandId,
+ errorReason ErrorReason,
+ simaResponse OCTET STRING OPTIONAL -- contains (multiple) 'EUICCResponse' as defined in [5]
+}
+
+BppCommandId ::= INTEGER {initialiseSecureChannel(0), configureISDP(1),
+storeMetadata(2), storeMetadata2(3), replaceSessionKeys(4), loadProfileElements(5)}
+
+ErrorReason ::= INTEGER {
+ incorrectInputValues(1),
+ invalidSignature(2),
+ invalidTransactionId(3),
+ unsupportedCrtValues(4),
+ unsupportedRemoteOperationType(5),
+ unsupportedProfileClass(6),
+ scp03tStructureError(7),
+ scp03tSecurityError(8),
+ installFailedDueToIccidAlreadyExistsOnEuicc(9),
+ installFailedDueToInsufficientMemoryForProfile(10),
+ installFailedDueToInterruption(11),
+ installFailedDueToPEProcessingError (12),
+ installFailedDueToDataMismatch(13),
+ testProfileInstallFailedDueToInvalidNaaKey(14),
+ pprNotAllowed(15),
+ installFailedDueToUnknownError(127)
+}
+
+ListNotificationRequest ::= [40] SEQUENCE { -- Tag 'BF28'
+ profileManagementOperation [1] NotificationEvent OPTIONAL
+}
+
+ListNotificationResponse ::= [40] CHOICE { -- Tag 'BF28'
+ notificationMetadataList SEQUENCE OF NotificationMetadata,
+ listNotificationsResultError INTEGER {undefinedError(127)}
+}
+
+NotificationMetadata ::= [47] SEQUENCE { -- Tag 'BF2F'
+ seqNumber [0] INTEGER,
+ profileManagementOperation [1] NotificationEvent, /*Only one bit SHALL be set to
+1*/
+ notificationAddress UTF8String, -- FQDN to forward the notification
+ iccid Iccid OPTIONAL
+}
+
+-- Definition of Profile Nickname Information
+SetNicknameRequest ::= [41] SEQUENCE { -- Tag 'BF29'
+ iccid Iccid,
+ profileNickname [16] UTF8String (SIZE(0..64))
+}
+
+SetNicknameResponse ::= [41] SEQUENCE { -- Tag 'BF29'
+ setNicknameResult INTEGER {ok(0), iccidNotFound (1), undefinedError(127)}
+}
+
+id-rsp-cert-objects OBJECT IDENTIFIER ::= { id-rsp cert-objects(2)}
+
+id-rspExt OBJECT IDENTIFIER ::= {id-rsp-cert-objects 0}
+
+id-rspRole OBJECT IDENTIFIER ::= {id-rsp-cert-objects 1}
+
+-- Definition of OIDs for role identification
+id-rspRole-ci OBJECT IDENTIFIER ::= {id-rspRole 0}
+id-rspRole-euicc OBJECT IDENTIFIER ::= {id-rspRole 1}
+id-rspRole-eum OBJECT IDENTIFIER ::= {id-rspRole 2}
+id-rspRole-dp-tls OBJECT IDENTIFIER ::= {id-rspRole 3}
+id-rspRole-dp-auth OBJECT IDENTIFIER ::= {id-rspRole 4}
+id-rspRole-dp-pb OBJECT IDENTIFIER ::= {id-rspRole 5}
+id-rspRole-ds-tls OBJECT IDENTIFIER ::= {id-rspRole 6}
+id-rspRole-ds-auth OBJECT IDENTIFIER ::= {id-rspRole 7}
+
+--Definition of data objects for InitialiseSecureChannel Request
+InitialiseSecureChannelRequest ::= [35] SEQUENCE { -- Tag 'BF23'
+ remoteOpId RemoteOpId, -- Remote Operation Type Identifier (value SHALL be set to installBoundProfilePackage)
+ transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
+ controlRefTemplate[6] IMPLICIT ControlRefTemplate, -- Control Reference Template (Key Agreement). Current specification considers a subset of CRT specified in GlobalPlatform Card Specification [8], section 6.4.2.3 for the Mutual Authentication Data Field
+ smdpOtpk [APPLICATION 73] OCTET STRING, ---otPK.DP.ECKA as specified in GlobalPlatform Card Specification [8] section 6.4.2.3 for ePK.OCE.ECKA, tag '5F49'
+ smdpSign [APPLICATION 55] OCTET STRING -- SM-DP's signature, tag '5F37'
+}
+
+ControlRefTemplate ::= SEQUENCE {
+ keyType[0] Octet1, -- Key type according to GlobalPlatform Card Specification [8] Table 11-16, AES= '88', Tag '80'
+ keyLen[1] Octet1, --Key length in number of bytes. For current specification key length SHALL by 0x10 bytes, Tag '81'
+ hostId[4] OctetTo16 -- Host ID value , Tag '84'
+}
+
+--Definition of data objects for ConfigureISDPRequest
+ConfigureISDPRequest ::= [36] SEQUENCE { -- Tag 'BF24'
+ dpProprietaryData [24] DpProprietaryData OPTIONAL -- Tag 'B8'
+}
+
+DpProprietaryData ::= SEQUENCE { -- maximum size including tag and length field: 128 bytes
+ dpOid OBJECT IDENTIFIER -- OID in the tree of the SM-DP+ that created the Profile
+ -- additional data objects defined by the SM-DP+ MAY follow
+}
+
+-- Definition of request message for command ReplaceSessionKeys
+ReplaceSessionKeysRequest ::= [38] SEQUENCE { -- tag 'BF26'
+/*The new initial MAC chaining value*/
+ initialMacChainingValue OCTET STRING,
+/*New session key value for encryption/decryption (PPK-ENC)*/
+ ppkEnc OCTET STRING,
+/*New session key value of the session key C-MAC computation/verification (PPK-MAC)*/
+ ppkCmac OCTET STRING
+}
+
+-- Definition of data objects for RetrieveNotificationsList
+RetrieveNotificationsListRequest ::= [43] SEQUENCE { -- Tag 'BF2B'
+ searchCriteria CHOICE {
+ seqNumber [0] INTEGER,
+ profileManagementOperation [1] NotificationEvent
+ } OPTIONAL
+}
+
+RetrieveNotificationsListResponse ::= [43] CHOICE { -- Tag 'BF2B'
+ notificationList SEQUENCE OF PendingNotification,
+ notificationsListResultError INTEGER { undefinedError(127)}
+}
+
+PendingNotification ::= CHOICE {
+ profileInstallationResult [55] ProfileInstallationResult, -- tag 'BF37'
+ otherSignedNotification OtherSignedNotification
+}
+
+OtherSignedNotification ::= SEQUENCE {
+ tbsOtherNotification NotificationMetadata,
+ euiccNotificationSignature [APPLICATION 55] OCTET STRING, -- eUICC signature of tbsOtherNotification, Tag '5F37'
+ euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM
+ eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI
+}
+
+-- Definition of notificationSent
+NotificationSentRequest ::= [48] SEQUENCE { -- Tag 'BF30'
+ seqNumber [0] INTEGER
+}
+
+NotificationSentResponse ::= [48] SEQUENCE { -- Tag 'BF30'
+ deleteNotificationStatus INTEGER {ok(0), nothingToDelete(1),
+undefinedError(127)}
+}
+
+-- Definition of Enable Profile --------------------------
+EnableProfileRequest ::= [49] SEQUENCE { -- Tag 'BF31'
+ profileIdentifier CHOICE {
+ isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
+ iccid Iccid -- ICCID, tag '5A'
+ },
+ refreshFlag BOOLEAN -- indicating whether REFRESH is required
+}
+
+EnableProfileResponse ::= [49] SEQUENCE { -- Tag 'BF31'
+ enableResult INTEGER {ok(0), iccidOrAidNotFound (1),
+profileNotInDisabledState(2), disallowedByPolicy(3), wrongProfileReenabling(4),
+catBusy(5), undefinedError(127)}
+}
+
+-- Definition of Disable Profile --------------------------
+DisableProfileRequest ::= [50] SEQUENCE { -- Tag 'BF32'
+ profileIdentifier CHOICE {
+ isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
+ iccid Iccid -- ICCID, tag '5A'
+ },
+ refreshFlag BOOLEAN -- indicating whether REFRESH is required
+}
+
+DisableProfileResponse ::= [50] SEQUENCE { -- Tag 'BF32'
+ disableResult INTEGER {ok(0), iccidOrAidNotFound (1),
+profileNotInEnabledState(2), disallowedByPolicy(3), catBusy(5),
+undefinedError(127)}
+}
+
+-- Definition of Delete Profile --------------------------
+DeleteProfileRequest ::= [51] CHOICE { -- Tag 'BF33'
+ isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F'
+ iccid Iccid -- ICCID, tag '5A'
+}
+
+DeleteProfileResponse ::= [51] SEQUENCE { -- Tag 'BF33'
+ deleteResult INTEGER {ok(0), iccidOrAidNotFound (1),
+profileNotInDisabledState(2), disallowedByPolicy(3), undefinedError(127)}
+}
+
+-- Definition of Memory Reset --------------------------
+EuiccMemoryResetRequest ::= [52] SEQUENCE { -- Tag 'BF34'
+ resetOptions [2] BIT STRING {
+ deleteOperationalProfiles(0),
+ deleteFieldLoadedTestProfiles(1),
+ resetDefaultSmdpAddress(2)}
+}
+
+EuiccMemoryResetResponse ::= [52] SEQUENCE { -- Tag 'BF34'
+ resetResult INTEGER {ok(0), nothingToDelete(1), catBusy(5), undefinedError(127)}
+}
+
+-- Definition of Get EID --------------------------
+GetEuiccDataRequest ::= [62] SEQUENCE { -- Tag 'BF3E'
+ tagList [APPLICATION 28] Octet1 -- tag '5C', the value SHALL be set to '5A'
+}
+
+GetEuiccDataResponse ::= [62] SEQUENCE { -- Tag 'BF3E'
+ eidValue [APPLICATION 26] Octet16 -- tag '5A'
+}
+
+-- Definition of Get Rat
+
+GetRatRequest ::= [67] SEQUENCE { -- Tag ' BF43'
+ -- No input data
+}
+
+
+GetRatResponse ::= [67] SEQUENCE { -- Tag 'BF43'
+ rat RulesAuthorisationTable
+}
+
+RulesAuthorisationTable ::= SEQUENCE OF ProfilePolicyAuthorisationRule
+ProfilePolicyAuthorisationRule ::= SEQUENCE {
+ pprIds PprIds,
+ allowedOperators SEQUENCE OF OperatorId,
+ pprFlags BIT STRING {consentRequired(0)}
+}
+
+-- Definition of data structure containing the list of CRL segments
+SegmentedCrlList ::= SEQUENCE OF CertificateList
+
+-- Definition of data structure command for loading a CRL
+LoadCRLRequest ::= [53] SEQUENCE { -- Tag 'BF35'
+ -- A CRL
+ crl CertificateList
+}
+
+-- Definition of data structure response for loading a CRL
+LoadCRLResponse ::= [53] CHOICE { -- Tag 'BF35'
+ loadCRLResponseOk LoadCRLResponseOk,
+ loadCRLResponseError LoadCRLResponseError
+}
+
+LoadCRLResponseOk ::= SEQUENCE {
+ missingParts SEQUENCE OF INTEGER OPTIONAL
+}
+LoadCRLResponseError ::= INTEGER {invalidSignature(1), invalidCRLFormat(2),
+notEnoughMemorySpace(3), verificationKeyNotFound(4), fresherCrlAlreadyLoaded(5),
+baseCrlMissing(6), undefinedError(127)}
+
+-- Definition of the extension for Certificate Expiration Date
+id-rsp-expDate OBJECT IDENTIFIER ::= {id-rspExt 1}
+ExpirationDate ::= Time
+
+-- Definition of the extension id for total partial-CRL number
+id-rsp-totalPartialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 2}
+TotalPartialCrlNumber ::= INTEGER
+
+-- Definition of the extension id for the partial-CRL number
+id-rsp-partialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 3}
+PartialCrlNumber ::= INTEGER
+
+-- Definition for ES9+ ASN.1 Binding --------------------------
+RemoteProfileProvisioningRequest ::= [2] CHOICE { -- Tag 'A2'
+ initiateAuthenticationRequest [57] InitiateAuthenticationRequest, -- Tag 'BF39'
+ authenticateClientRequest [59] AuthenticateClientRequest, -- Tag 'BF3B'
+ getBoundProfilePackageRequest [58] GetBoundProfilePackageRequest, -- Tag 'BF3A'
+ cancelSessionRequestEs9 [65] CancelSessionRequestEs9, -- Tag 'BF41'
+ handleNotification [61] HandleNotification -- tag 'BF3D'
+}
+
+RemoteProfileProvisioningResponse ::= [2] CHOICE { -- Tag 'A2'
+ initiateAuthenticationResponse [57] InitiateAuthenticationResponse, -- Tag 'BF39'
+ authenticateClientResponseEs9 [59] AuthenticateClientResponseEs9, -- Tag 'BF3B'
+ getBoundProfilePackageResponse [58] GetBoundProfilePackageResponse, -- Tag 'BF3A'
+ cancelSessionResponseEs9 [65] CancelSessionResponseEs9, -- Tag 'BF41'
+ authenticateClientResponseEs11 [64] AuthenticateClientResponseEs11 -- Tag 'BF40'
+}
+
+InitiateAuthenticationRequest ::= [57] SEQUENCE { -- Tag 'BF39'
+ euiccChallenge [1] Octet16, -- random eUICC challenge
+ smdpAddress [3] UTF8String,
+ euiccInfo1 EUICCInfo1
+}
+
+InitiateAuthenticationResponse ::= [57] CHOICE { -- Tag 'BF39'
+ initiateAuthenticationOk InitiateAuthenticationOkEs9,
+ initiateAuthenticationError INTEGER {
+ invalidDpAddress(1),
+ euiccVersionNotSupportedByDp(2),
+ ciPKNotSupported(3)
+ }
+}
+
+InitiateAuthenticationOkEs9 ::= SEQUENCE {
+ transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
+ serverSigned1 ServerSigned1, -- Signed information
+ serverSignature1 [APPLICATION 55] OCTET STRING, -- Server_Sign1, tag '5F37'
+ euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- The curve CI Public Key to be used as required by ES10b.AuthenticateServer
+ serverCertificate Certificate
+}
+
+AuthenticateClientRequest ::= [59] SEQUENCE { -- Tag 'BF3B'
+ transactionId [0] TransactionId,
+ authenticateServerResponse [56] AuthenticateServerResponse -- This is the response from ES10b.AuthenticateServer
+}
+
+AuthenticateClientResponseEs9 ::= [59] CHOICE { -- Tag 'BF3B'
+ authenticateClientOk AuthenticateClientOk,
+ authenticateClientError INTEGER {
+ eumCertificateInvalid(1),
+ eumCertificateExpired(2),
+ euiccCertificateInvalid(3),
+ euiccCertificateExpired(4),
+ euiccSignatureInvalid(5),
+ matchingIdRefused(6),
+ eidMismatch(7),
+ noEligibleProfile(8),
+ ciPKUnknown(9),
+ invalidTransactionId(10),
+ insufficientMemory(11),
+ undefinedError(127)
+ }
+}
+
+AuthenticateClientOk ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ profileMetaData [37] StoreMetadataRequest,
+ smdpSigned2 SmdpSigned2, -- Signed information
+ smdpSignature2 [APPLICATION 55] OCTET STRING, -- tag '5F37'
+ smdpCertificate Certificate -- CERT.DPpb.ECDSA
+}
+
+GetBoundProfilePackageRequest ::= [58] SEQUENCE { -- Tag 'BF3A'
+ transactionId [0] TransactionId,
+ prepareDownloadResponse [33] PrepareDownloadResponse
+}
+
+GetBoundProfilePackageResponse ::= [58] CHOICE { -- Tag 'BF3A'
+ getBoundProfilePackageOk GetBoundProfilePackageOk,
+ getBoundProfilePackageError INTEGER {
+ euiccSignatureInvalid(1),
+ confirmationCodeMissing(2),
+ confirmationCodeRefused(3),
+ confirmationCodeRetriesExceeded(4),
+ bppRebindingRefused(5),
+ downloadOrderExpired(6),
+ invalidTransactionId(95),
+ undefinedError(127)
+ }
+}
+
+GetBoundProfilePackageOk ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ boundProfilePackage [54] BoundProfilePackage
+}
+
+HandleNotification ::= [61] SEQUENCE { -- Tag 'BF3D'
+ pendingNotification PendingNotification
+}
+
+CancelSessionRequestEs9 ::= [65] SEQUENCE { -- Tag 'BF41'
+ transactionId TransactionId,
+ cancelSessionResponse CancelSessionResponse -- data structure defined for ES10b.CancelSession function
+}
+
+CancelSessionResponseEs9 ::= [65] CHOICE { -- Tag 'BF41'
+ cancelSessionOk CancelSessionOk,
+ cancelSessionError INTEGER {
+ invalidTransactionId(1),
+ euiccSignatureInvalid(2),
+ undefinedError(127)
+ }
+}
+
+CancelSessionOk ::= SEQUENCE { -- This function has no output data
+}
+
+EuiccConfiguredAddressesRequest ::= [60] SEQUENCE { -- Tag 'BF3C'
+}
+
+EuiccConfiguredAddressesResponse ::= [60] SEQUENCE { -- Tag 'BF3C'
+ defaultDpAddress UTF8String OPTIONAL, -- Default SM-DP+ address as an FQDN
+ rootDsAddress UTF8String -- Root SM-DS address as an FQDN
+}
+
+ISDRProprietaryApplicationTemplate ::= [PRIVATE 0] SEQUENCE { -- Tag 'E0'
+ svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)
+ lpaeSupport BIT STRING {
+ lpaeUsingCat(0), -- LPA in the eUICC using Card Application Toolkit
+ lpaeUsingScws(1) -- LPA in the eUICC using Smartcard Web Server
+ } OPTIONAL
+}
+
+LpaeActivationRequest ::= [66] SEQUENCE { -- Tag 'BF42'
+ lpaeOption BIT STRING {
+ activateCatBasedLpae(0), -- LPAe with LUIe based on CAT
+ activateScwsBasedLpae(1) -- LPAe with LUIe based on SCWS
+ }
+}
+
+LpaeActivationResponse ::= [66] SEQUENCE { -- Tag 'BF42'
+ lpaeActivationResult INTEGER {ok(0), notSupported(1)}
+}
+
+SetDefaultDpAddressRequest ::= [63] SEQUENCE { -- Tag 'BF3F'
+ defaultDpAddress UTF8String -- Default SM-DP+ address as an FQDN
+}
+
+SetDefaultDpAddressResponse ::= [63] SEQUENCE { -- Tag 'BF3F'
+ setDefaultDpAddressResult INTEGER { ok (0), undefinedError (127)}
+}
+
+AuthenticateClientResponseEs11 ::= [64] CHOICE { -- Tag 'BF40'
+ authenticateClientOk AuthenticateClientOkEs11,
+ authenticateClientError INTEGER {
+ eumCertificateInvalid(1),
+ eumCertificateExpired(2),
+ euiccCertificateInvalid(3),
+ euiccCertificateExpired(4),
+ euiccSignatureInvalid(5),
+ eventIdUnknown(6),
+ invalidTransactionId(7),
+ undefinedError(127)
+ }
+}
+
+AuthenticateClientOkEs11 ::= SEQUENCE {
+ transactionId TransactionId,
+ eventEntries SEQUENCE OF EventEntries
+}
+
+EventEntries ::= SEQUENCE {
+ eventId UTF8String,
+ rspServerAddress UTF8String
+}
+
+END
diff --git a/library/euicc/RSPDefinitions_EncDec.cc b/library/euicc/RSPDefinitions_EncDec.cc
new file mode 100644
index 00000000..6441201b
--- /dev/null
+++ b/library/euicc/RSPDefinitions_EncDec.cc
@@ -0,0 +1,281 @@
+#include "RSPDefinitions.hh"
+
+namespace RSPDefinitions__Types {
+
+using namespace RSPDefinitions;
+
+TTCN_Module RSPDefinitions__EncDec("RSPDefinitions_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__GetEuiccChallengeResponse(const GetEuiccChallengeResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(GetEuiccChallengeResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+GetEuiccChallengeResponse dec__GetEuiccChallengeResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ GetEuiccChallengeResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(GetEuiccChallengeResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__EUICCInfo1(const EUICCInfo1 &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EUICCInfo1_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EUICCInfo1 dec__EUICCInfo1(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EUICCInfo1 msg;
+ buf.put_os(stream);
+
+ msg.decode(EUICCInfo1_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__EUICCInfo2(const EUICCInfo2 &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EUICCInfo2_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EUICCInfo2 dec__EUICCInfo2(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EUICCInfo2 msg;
+ buf.put_os(stream);
+
+ msg.decode(EUICCInfo2_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__AuthenticateServerResponse(const AuthenticateServerResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(AuthenticateServerResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+AuthenticateServerResponse dec__AuthenticateServerResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ AuthenticateServerResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(AuthenticateServerResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__CancelSessionResponse(const CancelSessionResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(CancelSessionResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+CancelSessionResponse dec__CancelSessionResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ CancelSessionResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(CancelSessionResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__PrepareDownloadResponse(const PrepareDownloadResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(PrepareDownloadResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+PrepareDownloadResponse dec__PrepareDownloadResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ PrepareDownloadResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(PrepareDownloadResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__ProfileInstallationResult(const ProfileInstallationResult &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(ProfileInstallationResult_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+ProfileInstallationResult dec__ProfileInstallationResult(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ ProfileInstallationResult msg;
+ buf.put_os(stream);
+
+ msg.decode(ProfileInstallationResult_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__NotificationSentResponse(const NotificationSentResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(NotificationSentResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+NotificationSentResponse dec__NotificationSentResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ NotificationSentResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(NotificationSentResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__RetrieveNotificationsListResponse(const RetrieveNotificationsListResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(RetrieveNotificationsListResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+RetrieveNotificationsListResponse dec__RetrieveNotificationsListResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ RetrieveNotificationsListResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(RetrieveNotificationsListResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__GetEuiccDataResponse(const GetEuiccDataResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(GetEuiccDataResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+GetEuiccDataResponse dec__GetEuiccDataResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ GetEuiccDataResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(GetEuiccDataResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__EuiccConfiguredAddressesResponse(const EuiccConfiguredAddressesResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EuiccConfiguredAddressesResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EuiccConfiguredAddressesResponse dec__EuiccConfiguredAddressesResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EuiccConfiguredAddressesResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(EuiccConfiguredAddressesResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__PendingNotification(const PendingNotification &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(PendingNotification_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+PendingNotification dec__PendingNotification(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ PendingNotification msg;
+ buf.put_os(stream);
+
+ msg.decode(PendingNotification_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__ServerSigned1(const ServerSigned1 &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(ServerSigned1_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+ServerSigned1 dec__ServerSigned1(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ ServerSigned1 msg;
+ buf.put_os(stream);
+
+ msg.decode(ServerSigned1_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__BoundProfilePackage(const BoundProfilePackage &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(BoundProfilePackage_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+BoundProfilePackage dec__BoundProfilePackage(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ BoundProfilePackage msg;
+ buf.put_os(stream);
+
+ msg.decode(BoundProfilePackage_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__StoreMetadataRequest(const StoreMetadataRequest &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(StoreMetadataRequest_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+StoreMetadataRequest dec__StoreMetadataRequest(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ StoreMetadataRequest msg;
+ buf.put_os(stream);
+
+ msg.decode(StoreMetadataRequest_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__SmdpSigned2(const SmdpSigned2 &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(SmdpSigned2_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+SmdpSigned2 dec__SmdpSigned2(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ SmdpSigned2 msg;
+ buf.put_os(stream);
+
+ msg.decode(SmdpSigned2_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+}
diff --git a/library/euicc/RSPDefinitions_Templates.ttcn b/library/euicc/RSPDefinitions_Templates.ttcn
new file mode 100644
index 00000000..86cdb0cb
--- /dev/null
+++ b/library/euicc/RSPDefinitions_Templates.ttcn
@@ -0,0 +1,579 @@
+/* SGP22 Templates in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * 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 RSPDefinitions_Templates {
+
+import from PEDefinitions all;
+import from RSPDefinitions all;
+import from RSPDefinitions_Types all;
+
+import from PKIX1Explicit88 all;
+import from PKIX1Explicit88_Templates all;
+import from PKIX1Explicit88_Types all;
+
+import from PKIX1Implicit88 all;
+
+/* GSMA SGP.22, section 2.5.4 */
+template (present) BoundProfilePackage
+tr_boundProfilePackage := {
+ initialiseSecureChannelRequest := {
+ remoteOpId := ?,
+ transactionId := ?,
+ controlRefTemplate := {
+ keyType := ?,
+ keyLen := ?,
+ hostId := ?
+ },
+ smdpOtpk := ?,
+ smdpSign := ?
+ },
+ /* ES8+.ConfigureISDP */
+ firstSequenceOf87 := ?,
+ /* ES8+.StoreMetadata */
+ sequenceOf88 := ?,
+ /* ES8+.ReplaceSessionKeys (optional) */
+ secondSequenceOf87 := *,
+ /* ES8+.LoadProfileElements */
+ sequenceOf86 := ?
+}
+template (value) BoundProfilePackage
+ts_boundProfilePackage := {
+ initialiseSecureChannelRequest := {
+ remoteOpId := 1,
+ transactionId := 'AABBCC'O,
+ controlRefTemplate := {
+ keyType := '88'O, /* AES */
+ keyLen := '10'O, /* 16 byte key-length */
+ hostId := '01020304050607080910111213141516'O
+ },
+ smdpOtpk := '1122334455667788'O,
+ smdpSign := 'AABBCCDDEEFF0000'O
+ },
+ /* ES8+.ConfigureISDP */
+ firstSequenceOf87 := {'41414141414141414141414141414141414141414141414141414141414141'O,
+ '42424242424242424242424242424242424242424242424242424242424242'O,
+ '43434343434343434343434343434343434343434343434343434343434343'O},
+ /* ES8+.StoreMetadata */
+ sequenceOf88 := {'444444444444444444444444444444444444444444'O,
+ '454545454545454545454545454545454545454545'O,
+ '464646464646464646464646464646464646464646'O},
+ /* ES8+.ReplaceSessionKeys (optional) */
+ secondSequenceOf87 := omit,
+ /* ES8+.LoadProfileElements */
+ sequenceOf86 := {'474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747474747'O,
+ '484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848484848'O,
+ '494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949494949'O,
+ '505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050'O,
+ '515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151'O}
+}
+
+/* GSMA SGP.22, section 2.5.6 */
+template (present) ProfileInstallationResult
+tr_profileInstallationResult := {
+ profileInstallationResultData := {
+ transactionId := ?,
+ notificationMetadata := {
+ seqNumber := ?,
+ profileManagementOperation := ?,
+ notificationAddress := ?,
+ iccid := *
+ },
+ smdpOid := ?,
+ finalResult := ?
+ },
+ euiccSignPIR := ?
+}
+template (value) ProfileInstallationResult
+ts_profileInstallationResult := {
+ profileInstallationResultData := {
+ transactionId := 'AABBCC'O,
+ notificationMetadata := {
+ seqNumber := 1234,
+ profileManagementOperation := '01'B, /* is this correct? (notificationInstall) */
+ notificationAddress := "smdp.example.com",
+ iccid := omit
+ },
+ smdpOid := id_rsp, /* random OBJECT IDENTIFIER for testing */
+ finalResult := {
+ successResult := {
+ aid := '0102030405'O,
+ simaResponse := '4141414141414141414141414141414141414141414141414141'O
+ }
+ }
+ },
+ euiccSignPIR := '00112233445566778899AABBCCDDEEFF'O
+}
+
+
+/* GSMA SGP.22, section 5.6.1 (ES9+) */
+template (present) RemoteProfileProvisioningRequest
+tr_initiateAuthenticationRequest(template (present) octetstring euiccChallenge := ?,
+ template (present) charstring smdpAddress := ?,
+ template (present) EUICCInfo1 euiccInfo1 := ?) := {
+ initiateAuthenticationRequest := {
+ euiccChallenge := euiccChallenge,
+ smdpAddress := smdpAddress,
+ euiccInfo1 := euiccInfo1
+ }
+}
+template (value) RemoteProfileProvisioningRequest
+ts_initiateAuthenticationRequest(template (value) octetstring euiccChallenge,
+ template (value) charstring smdpAddress,
+ template (value) EUICCInfo1 euiccInfo1) := {
+ initiateAuthenticationRequest := {
+ euiccChallenge := euiccChallenge,
+ smdpAddress := smdpAddress,
+ euiccInfo1 := euiccInfo1
+ }
+}
+template (present) RemoteProfileProvisioningResponse
+tr_initiateAuthenticationResponse(template (present) octetstring transactionId := ?,
+ template (present) ServerSigned1 serverSigned1 := ?,
+ template (present) octetstring serverSignature1 := ?,
+ template (present) SubjectKeyIdentifier euiccCiPKIdToBeUsed := ?,
+ template (present) Certificate serverCertificate := ?) := {
+ initiateAuthenticationResponse := {
+ initiateAuthenticationOk := {
+ transactionId := transactionId,
+ serverSigned1 := serverSigned1,
+ serverSignature1 := serverSignature1,
+ euiccCiPKIdToBeUsed := euiccCiPKIdToBeUsed,
+ serverCertificate := serverCertificate
+ }
+ }
+}
+template (value) RemoteProfileProvisioningResponse
+ts_initiateAuthenticationResponse(template (value) octetstring transactionId,
+ template (value) ServerSigned1 serverSigned1,
+ template (value) octetstring serverSignature1,
+ template (value) SubjectKeyIdentifier euiccCiPKIdToBeUsed,
+ template (value) Certificate serverCertificate) := {
+ initiateAuthenticationResponse := {
+ initiateAuthenticationOk := {
+ transactionId := transactionId,
+ serverSigned1 := serverSigned1,
+ serverSignature1 := serverSignature1,
+ euiccCiPKIdToBeUsed := euiccCiPKIdToBeUsed,
+ serverCertificate := serverCertificate
+ }
+ }
+}
+
+/* GSMA SGP.22, section 5.6.2 (ES9+) */
+template (present) RemoteProfileProvisioningRequest
+tr_getBoundProfilePackageRequest(template (present) octetstring transactionId := ?,
+ template (present) PrepareDownloadResponse prepareDownloadResponse := ?) := {
+ getBoundProfilePackageRequest := {
+ transactionId := transactionId,
+ prepareDownloadResponse := prepareDownloadResponse
+ }
+}
+template (value) RemoteProfileProvisioningRequest
+ts_getBoundProfilePackageRequest(template (value) octetstring transactionId,
+ template (value) PrepareDownloadResponse prepareDownloadResponse) := {
+ getBoundProfilePackageRequest := {
+ transactionId := transactionId,
+ prepareDownloadResponse := prepareDownloadResponse
+ }
+}
+template (present) RemoteProfileProvisioningResponse
+tr_getBoundProfilePackageResponse(template (present) octetstring transactionId := ?,
+ template (present) BoundProfilePackage boundProfilePackage := ?) := {
+ getBoundProfilePackageResponse := {
+ getBoundProfilePackageOk := {
+ transactionId := transactionId,
+ boundProfilePackage := boundProfilePackage
+ }
+ }
+}
+template (value) RemoteProfileProvisioningResponse
+ts_getBoundProfilePackageResponse(template (value) octetstring transactionId,
+ template (value) BoundProfilePackage boundProfilePackage) := {
+ getBoundProfilePackageResponse := {
+ getBoundProfilePackageOk := {
+ transactionId := transactionId,
+ boundProfilePackage := boundProfilePackage
+ }
+ }
+}
+
+/* GSMA SGP.22, section 5.6.3 (ES9+) */
+template (present) RemoteProfileProvisioningRequest
+tr_authenticateClientRequest(template (present) octetstring transactionId := ?,
+ template (present) AuthenticateServerResponse authenticateServerResponse := ?) := {
+ authenticateClientRequest := {
+ transactionId := transactionId,
+ authenticateServerResponse := authenticateServerResponse
+ }
+}
+template (value) RemoteProfileProvisioningRequest
+ts_authenticateClientRequest(template (value) octetstring transactionId,
+ template (value) AuthenticateServerResponse authenticateServerResponse) := {
+ authenticateClientRequest := {
+ transactionId := transactionId,
+ authenticateServerResponse := authenticateServerResponse
+ }
+}
+template (present) RemoteProfileProvisioningResponse
+tr_authenticateClientResponseEs9(template (present) octetstring transactionId := ?,
+ template (present) StoreMetadataRequest profileMetaData := ?,
+ template (present) SmdpSigned2 smdpSigned2 := ?,
+ template (present) octetstring smdpSignature2 := ?,
+ template (present) Certificate smdpCertificate := ?) := {
+ authenticateClientResponseEs9 := {
+ authenticateClientOk := {
+ transactionId := transactionId,
+ profileMetaData := profileMetaData,
+ smdpSigned2 := smdpSigned2,
+ smdpSignature2 := smdpSignature2,
+ smdpCertificate := smdpCertificate
+ }
+ }
+}
+template (value) RemoteProfileProvisioningResponse
+ts_authenticateClientResponseEs9(template (value) octetstring transactionId,
+ template (value) StoreMetadataRequest profileMetaData,
+ template (value) SmdpSigned2 smdpSigned2,
+ template (value) octetstring smdpSignature2,
+ template (value) Certificate smdpCertificate) := {
+ authenticateClientResponseEs9 := {
+ authenticateClientOk := {
+ transactionId := transactionId,
+ profileMetaData := profileMetaData,
+ smdpSigned2 := smdpSigned2,
+ smdpSignature2 := smdpSignature2,
+ smdpCertificate := smdpCertificate
+ }
+ }
+}
+
+/* GSMA SGP.22, section 5.6.4 (ES9+) */
+template (present) RemoteProfileProvisioningRequest
+tr_handleNotification(template (present) PendingNotification pendingNotification := ?) := {
+ handleNotification := {
+ pendingNotification := pendingNotification
+ }
+}
+template (value) RemoteProfileProvisioningRequest
+ts_handleNotification(template (value) PendingNotification pendingNotification) := {
+ handleNotification := {
+ pendingNotification := pendingNotification
+ }
+}
+
+/* GSMA SGP.22, section 5.6.5 (ES9+) */
+template (present) RemoteProfileProvisioningRequest
+tr_cancelSessionRequestEs9(template (present) octetstring transactionId := ?,
+ template (present) CancelSessionResponse cancelSessionResponse := ?) := {
+ cancelSessionRequestEs9 := {
+ transactionId := transactionId,
+ cancelSessionResponse := cancelSessionResponse
+ }
+}
+template (value) RemoteProfileProvisioningRequest
+ts_cancelSessionRequestEs9(template (value) octetstring transactionId,
+ template (value) CancelSessionResponse cancelSessionResponse) := {
+ cancelSessionRequestEs9 := {
+ transactionId := transactionId,
+ cancelSessionResponse := cancelSessionResponse
+ }
+}
+template (present) RemoteProfileProvisioningResponse
+tr_cancelSessionResponseEs9 := {
+ cancelSessionResponseEs9 := {
+ cancelSessionOk := { } /* This function has no output data */
+ }
+}
+template (value) RemoteProfileProvisioningResponse
+ts_cancelSessionResponseEs9 := {
+ cancelSessionResponseEs9 := {
+ cancelSessionOk := { } /* This function has no output data */
+ }
+}
+
+
+/* GSMA SGP.22, section 5.7.3 (ES10x) */
+template (present) EuiccConfiguredAddressesResponse
+tr_euiccConfiguredAddressesResponse := {
+ defaultDpAddress := *,
+ rootDsAddress := ?
+}
+template (value) EuiccConfiguredAddressesResponse
+ts_euiccConfiguredAddressesResponse := {
+ defaultDpAddress := "smdp.example.com",
+ rootDsAddress := "smds.example.com"
+}
+
+/* GSMA SGP.22, section 5.7.5 (ES10x) */
+template (present) PrepareDownloadResponse
+tr_prepareDownloadResponse := {
+ downloadResponseOk := {
+ euiccSigned2 := {
+ transactionId := ?,
+ euiccOtpk := ?,
+ hashCc := *
+ },
+ euiccSignature2 := ?
+ }
+}
+template (value) PrepareDownloadResponse
+ts_prepareDownloadResponse := {
+ downloadResponseOk := {
+ euiccSigned2 := {
+ transactionId := 'ABCDEF'O,
+ euiccOtpk := 'AABBCCDDEEFF'O,
+ hashCc := omit
+ },
+ euiccSignature2 := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'O
+ }
+}
+
+/* GSMA SGP.22, section 5.7.7 (ES10x) */
+template (present) GetEuiccChallengeResponse
+tr_GetEuiccChallengeResponse := {
+ euiccChallenge := ?
+}
+template (value) GetEuiccChallengeResponse
+ts_GetEuiccChallengeResponse(template (value) octetstring euiccChallenge := '00112233445566778899AABBCCDDEEFF'O) := {
+ euiccChallenge := euiccChallenge
+}
+
+/* GSMA SGP.22, section 5.7.8 (ES10x) */
+template (present) EUICCInfo1
+tr_EUICCInfo1 := {
+ svn := ?,
+ euiccCiPKIdListForVerification := ?,
+ euiccCiPKIdListForSigning := ?
+}
+template (value) EUICCInfo1
+ts_EUICCInfo1 := {
+ svn := '020200'O,
+ euiccCiPKIdListForVerification := {
+ 'C0BC70BA36929D43B467FF57570530E57AB8FCD8'O,
+ 'F54172BDF98A95D65CBEB88A38A1C11D800A85C3'O
+ },
+ euiccCiPKIdListForSigning := {
+ 'C0BC70BA36929D43B467FF57570530E57AB8FCD8'O,
+ 'F54172BDF98A95D65CBEB88A38A1C11D800A85C3'O
+ }
+}
+
+/* GSMA SGP.22, section 5.7.8 (ES10x) */
+template (present) EUICCInfo2
+tr_EUICCInfo2 := {
+ profileVersion := ?,
+ svn := ?,
+ euiccFirmwareVer := ?,
+ extCardResource := ?,
+ uiccCapability := ?,
+ ts102241Version := *,
+ globalplatformVersion := *,
+ rspCapability := ?,
+ euiccCiPKIdListForVerification := ?,
+ euiccCiPKIdListForSigning := ?,
+ euiccCategory := *,
+ forbiddenProfilePolicyRules := *,
+ ppVersion := ?,
+ sasAcreditationNumber := ?,
+ certificationDataObject := *,
+ treProperties := *,
+ treProductReference := *,
+ additionalEuiccProfilePackageVersions := *
+}
+template (value) EUICCInfo2
+ts_EUICCInfo2 := {
+ profileVersion := '414243'O,
+ svn := '02000C'O,
+ euiccFirmwareVer := '414243'O,
+ extCardResource := '414243'O,
+ uiccCapability := '1111111111111111111'B,
+ ts102241Version := omit,
+ globalplatformVersion := omit,
+ rspCapability := '1111'B,
+ euiccCiPKIdListForVerification := {
+ 'C0BC70BA36929D43B467FF57570530E57AB8FCD8'O,
+ 'F54172BDF98A95D65CBEB88A38A1C11D800A85C3'O
+ },
+ euiccCiPKIdListForSigning := {
+ 'C0BC70BA36929D43B467FF57570530E57AB8FCD8'O,
+ 'F54172BDF98A95D65CBEB88A38A1C11D800A85C3'O
+ },
+ euiccCategory := omit,
+ forbiddenProfilePolicyRules := omit,
+ ppVersion := '414243'O,
+ sasAcreditationNumber := "123456",
+ certificationDataObject := omit,
+ treProperties := omit,
+ treProductReference := omit,
+ additionalEuiccProfilePackageVersions := omit
+}
+
+/* GSMA SGP.22, section 5.7.10 (ES10x) */
+template (value) RetrieveNotificationsListResponse
+ts_retrieveNotificationsListResponse := {
+ notificationList := {
+ {
+ profileInstallationResult := {
+ profileInstallationResultData := {
+ transactionId := 'AABBCC'O,
+ notificationMetadata := {
+ seqNumber := 1234,
+ profileManagementOperation := '01'B, /* is this correct? (notificationInstall) */
+ notificationAddress := "smdp.example.com",
+ iccid := omit
+ },
+ smdpOid := id_rsp, /* random OBJECT IDENTIFIER for testing */
+ finalResult := {
+ successResult := {
+ aid := 'A0000005591010FFFFFFFF8900000D00'O,
+ simaResponse := 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'O
+ }
+ }
+ },
+ euiccSignPIR := 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'O
+ }
+ }
+ }
+}
+
+/* GSMA SGP.22, section 5.7.11 (ES10x) */
+template (present) NotificationSentResponse
+tr_notificationSentResponse := {
+ deleteNotificationStatus := ?
+}
+template (value) NotificationSentResponse
+ts_notificationSentResponse := {
+ deleteNotificationStatus := 0 /* 0k */
+}
+
+/* GSMA SGP.22, section 5.7.13 (ES10x) */
+template (present) AuthenticateServerResponse
+tr_authenticateServerResponse := {
+ authenticateResponseOk := {
+ euiccSigned1 := {
+ transactionId := ?,
+ serverAddress := ?,
+ serverChallenge := ?,
+ euiccInfo2 := ?,
+ ctxParams1 := {
+ ctxParamsForCommonAuthentication := {
+ matchingId := *,
+ deviceInfo := {
+ tac := ?,
+ deviceCapabilities := {
+ gsmSupportedRelease := *,
+ utranSupportedRelease := *,
+ cdma2000onexSupportedRelease := *,
+ cdma2000hrpdSupportedRelease := *,
+ cdma2000ehrpdSupportedRelease := *,
+ eutranEpcSupportedRelease := *,
+ contactlessSupportedRelease := *,
+ rspCrlSupportedVersion := *,
+ nrEpcSupportedRelease := *,
+ nr5gcSupportedRelease := *,
+ eutran5gcSupportedRelease := *,
+ lpaSvn := *,
+ catSupportedClasses := *,
+ euiccFormFactorType := *,
+ deviceAdditionalFeatureSupport := *
+ },
+ imei := *
+ }
+ }
+ }
+ },
+ euiccSignature1 := ?,
+ euiccCertificate := ?,
+ eumCertificate := ?
+ }
+}
+template (value) AuthenticateServerResponse
+ts_authenticateServerResponse := {
+ authenticateResponseOk := {
+ euiccSigned1 := {
+ transactionId := 'ABCDEF'O,
+ serverAddress := "smdp.example.com",
+ serverChallenge := '01020304050607080910111213141516'O,
+ euiccInfo2 := ts_EUICCInfo2,
+ ctxParams1 := {
+ ctxParamsForCommonAuthentication := {
+ matchingId := omit,
+ deviceInfo := {
+ tac := '12345678'O,
+ deviceCapabilities := {
+ gsmSupportedRelease := omit,
+ utranSupportedRelease := omit,
+ cdma2000onexSupportedRelease := omit,
+ cdma2000hrpdSupportedRelease := omit,
+ cdma2000ehrpdSupportedRelease := omit,
+ eutranEpcSupportedRelease := omit,
+ contactlessSupportedRelease := omit,
+ rspCrlSupportedVersion := omit,
+ nrEpcSupportedRelease := omit,
+ nr5gcSupportedRelease := omit,
+ eutran5gcSupportedRelease := omit,
+ lpaSvn := omit,
+ catSupportedClasses := omit,
+ euiccFormFactorType := omit,
+ deviceAdditionalFeatureSupport := omit
+ },
+ imei := omit
+ }
+ }
+ }
+ },
+ euiccSignature1 := '12345678'O,
+ euiccCertificate := ts_cert_euicc_nist,
+// euiccCertificate := ts_cert_euicc_brp,
+ eumCertificate := ts_cert_eum_nist
+// eumCertificate := ts_cert_eum_brp
+
+ }
+}
+
+/* GSMA SGP.22, section 5.7.13 (ES10x) */
+template (present) CancelSessionResponseOk
+tr_cancelSessionResponseOk := {
+ euiccCancelSessionSigned := {
+ transactionId := ?,
+ smdpOid := ?,
+ reason := ?
+ },
+ euiccCancelSessionSignature := ?
+}
+template (value) CancelSessionResponseOk
+ts_cancelSessionResponseOk := {
+ euiccCancelSessionSigned := {
+ transactionId := 'AABBCC'O,
+ smdpOid := id_rspRole_euicc,
+ reason := 5
+ },
+ euiccCancelSessionSignature := '1234567890'O
+}
+template (present) CancelSessionResponse
+tr_cancelSessionResponse := {
+ cancelSessionResponseOk := tr_cancelSessionResponseOk
+}
+template (value) CancelSessionResponse
+ts_cancelSessionResponse := {
+ cancelSessionResponseOk := ts_cancelSessionResponseOk
+}
+
+/* GSMA SGP.22, section 5.7.20 (ES10x) */
+template (present) GetEuiccDataResponse
+tr_getEuiccDataResponse := {
+ eidValue := ?
+}
+template (value) GetEuiccDataResponse
+ts_getEuiccDataResponse(template (value) octetstring eidValue := '000102030405060708090A0B0C0D0E0F'O) := {
+ eidValue := eidValue
+}
+
+} \ No newline at end of file
diff --git a/library/euicc/RSPDefinitions_Types.ttcn b/library/euicc/RSPDefinitions_Types.ttcn
new file mode 100644
index 00000000..b031aa3b
--- /dev/null
+++ b/library/euicc/RSPDefinitions_Types.ttcn
@@ -0,0 +1,54 @@
+module RSPDefinitions_Types {
+
+import from RSPDefinitions all;
+import from Native_Functions all;
+
+external function dec_GetEuiccChallengeResponse(in octetstring stream) return GetEuiccChallengeResponse;
+external function enc_GetEuiccChallengeResponse(in GetEuiccChallengeResponse msg) return octetstring;
+
+external function dec_EUICCInfo1(in octetstring stream) return EUICCInfo1;
+external function enc_EUICCInfo1(in EUICCInfo1 msg) return octetstring;
+
+external function dec_EUICCInfo2(in octetstring stream) return EUICCInfo2;
+external function enc_EUICCInfo2(in EUICCInfo2 msg) return octetstring;
+
+external function dec_AuthenticateServerResponse(in octetstring stream) return AuthenticateServerResponse;
+external function enc_AuthenticateServerResponse(in AuthenticateServerResponse msg) return octetstring;
+
+external function dec_CancelSessionResponse(in octetstring stream) return CancelSessionResponse;
+external function enc_CancelSessionResponse(in CancelSessionResponse msg) return octetstring;
+
+external function dec_PrepareDownloadResponse(in octetstring stream) return PrepareDownloadResponse;
+external function enc_PrepareDownloadResponse(in PrepareDownloadResponse msg) return octetstring;
+
+external function dec_ProfileInstallationResult(in octetstring stream) return ProfileInstallationResult;
+external function enc_ProfileInstallationResult(in ProfileInstallationResult msg) return octetstring;
+
+external function dec_NotificationSentResponse(in octetstring stream) return NotificationSentResponse;
+external function enc_NotificationSentResponse(in NotificationSentResponse msg) return octetstring;
+
+external function dec_RetrieveNotificationsListResponse(in octetstring stream) return RetrieveNotificationsListResponse;
+external function enc_RetrieveNotificationsListResponse(in RetrieveNotificationsListResponse msg) return octetstring;
+
+external function dec_GetEuiccDataResponse(in octetstring stream) return GetEuiccDataResponse;
+external function enc_GetEuiccDataResponse(in GetEuiccDataResponse msg) return octetstring;
+
+external function dec_EuiccConfiguredAddressesResponse(in octetstring stream) return EuiccConfiguredAddressesResponse;
+external function enc_EuiccConfiguredAddressesResponse(in EuiccConfiguredAddressesResponse msg) return octetstring;
+
+external function dec_PendingNotification(in octetstring stream) return PendingNotification;
+external function enc_PendingNotification(in PendingNotification msg) return octetstring;
+
+external function dec_ServerSigned1(in octetstring stream) return ServerSigned1;
+external function enc_ServerSigned1(in ServerSigned1 msg) return octetstring;
+
+external function dec_BoundProfilePackage(in octetstring stream) return BoundProfilePackage;
+external function enc_BoundProfilePackage(in BoundProfilePackage msg) return octetstring;
+
+external function dec_StoreMetadataRequest(in octetstring stream) return StoreMetadataRequest;
+external function enc_StoreMetadataRequest(in StoreMetadataRequest msg) return octetstring;
+
+external function dec_SmdpSigned2(in octetstring stream) return SmdpSigned2;
+external function enc_SmdpSigned2(in SmdpSigned2 msg) return octetstring;
+
+}
diff --git a/library/euicc/SGP32Definitions.asn b/library/euicc/SGP32Definitions.asn
new file mode 100644
index 00000000..8456ef49
--- /dev/null
+++ b/library/euicc/SGP32Definitions.asn
@@ -0,0 +1,806 @@
+-- Section 2.1.3
+-- ASN1START
+SGP32Definitions {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1) asn1modules(1) sgp32v1(31)}
+DEFINITIONS
+AUTOMATIC TAGS
+EXTENSIBILITY IMPLIED ::=
+BEGIN
+
+IMPORTS Certificate, SubjectPublicKeyInfo
+FROM PKIX1Explicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18)}
+SubjectKeyIdentifier FROM PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19)}
+
+ProfileInfo, EuiccSigned1, CancelSessionReason, RetrieveNotificationsListResponse,
+ServerSigned1, RspCapability, Iccid, TransactionId, ProfileInfoListRequest,
+ProfileInfoListResponse, RulesAuthorisationTable, EUICCInfo1, DeviceInfo,
+VersionType, UICCCapability, PprIds,
+CertificationDataObject, Octet1, Octet16, Octet32, PrepareDownloadResponse,
+PrepareDownloadResponseOk, PrepareDownloadResponseError,
+AuthenticateServerResponse, AuthenticateResponseOk, AuthenticateResponseError,
+CtxParams1, ProfileInstallationResult, ProfileInstallationResultData,
+OtherSignedNotification, EuiccSignPIR, ErrorResult, NotificationMetadata,
+CancelSessionResponse, CancelSessionResponseOk,
+StoreMetadataRequest, SmdpSigned2, BoundProfilePackage, NotificationEvent
+FROM RSPDefinitions {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1) asn1modules(1) sgp22v2(2)};
+-- ASN1STOP
+
+-- Section 2.11.1.1
+-- ASN1START
+EuiccPackageRequest ::= [81] SEQUENCE { -- Tag ' BF51', #SupportedForPsmoV1.0.0#
+ euiccPackageSigned EuiccPackageSigned,
+ eimSignature [APPLICATION 55] OCTET STRING -- Tag '5F37'
+}
+EuiccPackageSigned ::= SEQUENCE {
+ eimId [0] UTF8String,
+ eidValue [APPLICATION 26] Octet16, -- Tag '5A'
+ counterValue [1] INTEGER,
+ transactionId [2] TransactionId OPTIONAL,
+ euiccPackage EuiccPackage
+}
+EuiccPackage ::= CHOICE {
+ psmoList SEQUENCE OF Psmo, -- #SupportedForPsmoV1.0.0#
+ ecoList SEQUENCE OF Eco -- #SupportedForEcoV1.0.0#
+}
+-- ASN1STOP
+
+
+-- Section 2.11.1.1.1
+-- ASN1START
+EimConfigurationData ::= SEQUENCE {
+ eimId [0] UTF8String, -- eimId of eIM
+ eimFqdn [1] UTF8String OPTIONAL, -- FQDN of eIM
+ eimIdType [2] EimIdType OPTIONAL,
+ counterValue [3] INTEGER OPTIONAL, -- initial counterValue for the eIM
+ associationToken [4] INTEGER OPTIONAL,
+ eimPublicKeyData [5] CHOICE {
+ eimPublicKey SubjectPublicKeyInfo, -- public key of eIM, used for eUICC Package signature verification, where the encoding follows X.509 standard
+ eimCertificate Certificate -- certificate of eIM, used for eUICC Package signature verification, where the encoding follows X.509 standard
+ } OPTIONAL,
+ trustedPublicKeyDataTls [6] CHOICE {
+ trustedEimPkTls SubjectPublicKeyInfo, -- public key of eIM, used for TLS or DTLS, where the encoding follows X.509 standard
+ trustedCertificateTls Certificate -- either the certificate of eIM, used for (D)TLS, or the certificate of the CA, where the encoding follows X.509 standard
+ } OPTIONAL,
+ eimSupportedProtocol [7] EimSupportedProtocol OPTIONAL,
+ euiccCiPKId [8] SubjectKeyIdentifier OPTIONAL -- CI Public Key Identifier supported on the eUICC for signature creation
+}
+EimIdType ::= INTEGER {
+ eimIdTypeOid(1),
+ eimIdTypeFqdn(2),
+ eimIdTypeProprietary(3)
+}
+ EimSupportedProtocol ::= BIT STRING {
+ eimRetrieveHttps(0),
+ eimRetrieveCoaps(1),
+ eimInjectHttps(2),
+ eimInjectCoaps(3),
+ eimProprietary(4)
+}
+-- ASN1STOP
+
+-- Section 2.11.1.1.2
+-- ASN1START
+Eco ::= CHOICE {
+ addEim [8] EimConfigurationData, -- for eIM configuration data see 2.11.1
+ deleteEim [9] SEQUENCE {eimId [0] UTF8String},
+ updateEim [10] EimConfigurationData,
+ listEim [11] SEQUENCE {}
+}
+-- ASN1STOP
+
+-- Section 2.11.1.1.3
+-- ASN1START
+Psmo ::= CHOICE {
+ enable [3] SEQUENCE {
+ iccid [APPLICATION 26] Iccid,
+ rollbackFlag NULL OPTIONAL
+ },
+ disable [4] SEQUENCE {iccid [APPLICATION 26] Iccid},
+ delete [5] SEQUENCE {iccid [APPLICATION 26] Iccid},
+ listProfileInfo [45] ProfileInfoListRequest, -- Tag 'BF2D'
+ getRAT [6] SEQUENCE {},
+ configureAutoEnable [7] SEQUENCE {
+ autoEnableFlag [0] NULL OPTIONAL,
+ smdpOid [1] OBJECT IDENTIFIER OPTIONAL,
+ smdpAddress [2] UTF8String OPTIONAL
+ }
+}
+-- ASN1STOP
+
+
+-- Section 2.11.1.2
+-- ASN1START
+IpaEuiccDataRequest ::= [82] SEQUENCE { -- Tag BF52
+ tagList [APPLICATION 28] OCTET STRING, -- Tag '5C'
+ euiccCiPKId SubjectKeyIdentifier OPTIONAL, -- CI Public Key Identifier supported on the eUICC for signature creation
+ searchCriteria [1] CHOICE {
+ seqNumber [0] INTEGER,
+ profileManagementOperation [1] NotificationEvent,
+ euiccPackageResults [2] NULL
+ } OPTIONAL
+}
+-- ASN1STOP
+
+-- Section 2.11.1.3
+-- ASN1START
+ProfileDownloadTriggerRequest ::= [84] SEQUENCE { -- Tag 'BF54'
+ profileDownloadData [0] ProfileDownloadData OPTIONAL,
+ eimTransactionId [2] TransactionId OPTIONAL
+}
+ProfileDownloadData ::= CHOICE {
+ activationCode [0] UTF8String (SIZE(0..255)),
+ contactDefaultSmdp [1] NULL,
+ contactSmds [2] SEQUENCE {
+ smdsAddress UTF8String OPTIONAL
+ }
+}
+-- ASN1STOP
+
+-- Section 2.11.1.4
+-- ASN1START
+EimAcknowledgements ::= [83] SEQUENCE OF SequenceNumber -- Tag BF53
+SequenceNumber ::= [0] INTEGER
+-- ASN1STOP
+
+
+-- Section 2.11.2.1
+-- ASN1START
+EuiccPackageResult ::= [81] CHOICE { -- Tag 'BF51' #SupportedForPsmoV1.0.0#
+ euiccPackageResultSigned EuiccPackageResultSigned,
+ euiccPackageErrorSigned EuiccPackageErrorSigned,
+ euiccPackageErrorUnsigned EuiccPackageErrorUnsigned
+}
+EuiccPackageResultSigned ::= SEQUENCE {
+ euiccPackageResultDataSigned EuiccPackageResultDataSigned,
+ euiccSignEPR [APPLICATION 55] OCTET STRING -- Tag '5F37'
+}
+EuiccPackageResultDataSigned ::= SEQUENCE { -- #SupportedForPsmoV1.0.0#
+ eimId [0] UTF8String,
+ counterValue [1] INTEGER,
+ transactionId[2] TransactionId OPTIONAL,
+ seqNumber [3] INTEGER,
+ euiccResult SEQUENCE OF EuiccResultData
+}
+EuiccResultData ::= CHOICE {
+ enableResult [3] EnableProfileResult,
+ disableResult [4] DisableProfileResult,
+ deleteResult [5] DeleteProfileResult,
+ listProfileInfoResult [45] SGP32-ProfileInfoListResponse,
+ getRATResult [6] RulesAuthorisationTable, -- see SGP.22
+ configureAutoEnableResult [7] ConfigureAutoEnableResult,
+ addEimResult [8] AddEimResult,
+ deleteEimResult [9] DeleteEimResult,
+ updateEimResult [10] UpdateEimResult,
+ listEimResult [11] ListEimResult,
+ rollbackResult [12] RollbackProfileResult,
+ processingTerminated INTEGER {
+ resultSizeOverflow(1),
+ unknownOrDamagedCommand(2),
+ interruption(3),
+ undefinedError(127)
+ }
+}
+EuiccPackageErrorSigned ::= SEQUENCE {
+ euiccPackageErrorDataSigned EuiccPackageErrorDataSigned,
+ euiccSignEPE [APPLICATION 55] OCTET STRING -- Tag '5F37'
+}
+EuiccPackageErrorDataSigned ::= SEQUENCE {
+ eimId [0] UTF8String,
+ counterValue [1] INTEGER,
+ transactionId [2] TransactionId OPTIONAL,
+ euiccPackageErrorCode EuiccPackageErrorCode
+}
+EuiccPackageErrorCode ::= INTEGER { invalidEid(3), replayError(4), counterValueOutOfRange(6), sizeOverflow(15), undefinedError(127)}
+EuiccPackageErrorUnsigned ::= SEQUENCE {
+ eimId [0] UTF8String,
+ associationToken [4] INTEGER OPTIONAL
+}
+ConfigureAutoEnableResult ::= INTEGER {
+ ok(0),
+ insufficientMemory(1),
+ commandError(7),
+ undefinedError(127)
+}
+EnableProfileResult ::= INTEGER {
+ ok(0),
+ iccidOrAidNotFound(1),
+ profileNotInDisabledState(2),
+ undefinedError(127)
+}
+DisableProfileResult ::= INTEGER {
+ ok(0),
+ iccidOrAidNotFound(1),
+ profileNotInEnabledState(2),
+ undefinedError(127)
+}
+DeleteProfileResult ::= INTEGER {
+ ok(0),
+ iccidOrAidNotFound(1),
+ profileNotInDisabledState(2),
+ undefinedError(127)
+}
+SGP32-ProfileInfoListResponse ::= [45] CHOICE {
+ profileInfoListOk SEQUENCE OF ProfileInfo, -- see SGP.22
+ profileInfoListError SGP32-ProfileInfoListError
+}
+SGP32-ProfileInfoListError ::= INTEGER {
+ incorrectInputValues(1),
+ profileChangeOngoing (11),
+ undefinedError(127)
+}
+RollbackProfileResult ::= INTEGER {
+ ok(0),
+ undefinedError(127)
+}
+AddEimResult ::= CHOICE {
+ associationToken [4] INTEGER,
+ addEimResultCode INTEGER {
+ ok(0),
+ insufficientMemory(1),
+ ciPKUnknown(3),
+ invalidAssociationToken(5),
+ counterValueOutOfRange(6),
+ commandError(7),
+ undefinedError(127)
+ }
+}
+DeleteEimResult ::= INTEGER {
+ ok(0),
+ eimNotFound(1),
+ lastEimDeleted(2), -- no eIM Configuration Data available in eUICC,
+ commandError(7),
+ undefinedError(127)
+}
+UpdateEimResult ::= INTEGER {
+ ok(0),
+ eimNotFound (1),
+ ciPKUnknown(3),
+ counterValueOutOfRange(6),
+ commandError(7),
+ undefinedError(127)
+}
+ListEimResult ::= CHOICE {
+ eimIdList SEQUENCE OF EimIdInfo,
+ listEimError INTEGER {
+ commandError(7),
+ undefinedError(127)
+ }
+}
+EimIdInfo ::= SEQUENCE {
+ eimId [0] UTF8String,
+ eimIdType [4] EimIdType OPTIONAL -- present in case of eimIdTypeOid and eimIdTypeFqdn
+}
+-- ASN1STOP
+
+-- Section 2.11.2.2
+-- ASN1START
+IpaEuiccDataResponse ::= [82] CHOICE { -- Tag 'BF52'
+ ipaEuiccData IpaEuiccData,
+ ipaEuiccDataError INTEGER {
+ incorrectTagList (1),
+ euiccCiPKIdNotFound(5),
+ undefinedError(127)
+ }
+}
+IpaEuiccData ::= SEQUENCE {
+ defaultSmdpAddress [0] UTF8String OPTIONAL, -- Tag '80'
+ euiccInfo1 [32] EUICCInfo1 OPTIONAL, -- Tag 'BF20'
+ euiccInfo2 [34] SGP32-EUICCInfo2 OPTIONAL, -- Tag 'BF22'
+ rootSmdsAddress [3] UTF8String OPTIONAL, -- Tag '83'
+ associationToken [4] INTEGER OPTIONAL, -- Tag '84'
+ eumCertificate [5] Certificate OPTIONAL, -- Tag 'A5'
+ euiccCertificate [6] Certificate OPTIONAL, -- Tag 'A6'
+ ipaCapabilities [8] IpaCapabilities OPTIONAL, -- Tag '88'
+ deviceInfo [9] DeviceInfo OPTIONAL, -- Tag 'A9'
+ notificationsList [43] SGP32-RetrieveNotificationsListResponse OPTIONAL -- Tag 'BF2B'.
+}
+-- ASN1STOP
+
+-- Section 2.11.2.3
+-- ASN1START
+ProfileDownloadTriggerResult ::= [84] SEQUENCE { -- tag 'BF54'
+ eimTransactionId [2] TransactionId OPTIONAL,
+ profileDownloadTriggerResultData CHOICE {
+ profileInstallationResult [55] SGP32-ProfileInstallationResult, -- see SGP.22 [4]
+ profileDownloadError SEQUENCE {
+ errorResponse OCTET STRING OPTIONAL
+ }
+ }
+}
+-- ASN1STOP
+
+-- Section 4.1
+-- ASN1START
+IpaCapabilities ::= SEQUENCE {
+ ipaFeatures [0] BIT STRING {
+ directRspServerCommunication (0),
+ indirectRspServerCommunication (1),
+ eimDownloadDataHandling (2),
+ eimCtxParams1Generation (3),
+ eimProfileMetadataVerification (4),
+ minimizeEsipaBytes (5)
+ },
+ ipaSupportedProtocols [1] BIT STRING {
+ ipaRetrieveHttps(0),
+ ipaRetrieveCoaps(1),
+ ipaInjectHttps(2),
+ ipaInjectCoaps(3),
+ ipaProprietary(4)
+ } OPTIONAL
+}
+-- ASN1STOP
+
+-- Section 5.9.2
+-- ASN1START
+SGP32-EUICCInfo2 ::= [34] SEQUENCE { -- Tag 'BF22'
+ profileVersion [1] VersionType, -- Base eUICC Profile package version supported
+ svn [2] VersionType, -- GSMA SGP.22 version supported (SVN)referenced by SGP.32
+ euiccFirmwareVer [3] VersionType, -- eUICC Firmware version
+ extCardResource [4] OCTET STRING, -- Extended Card Resource Information according to ETSI TS 102 226
+ uiccCapability [5] UICCCapability,
+ ts102241Version [6] VersionType OPTIONAL,
+ globalplatformVersion [7] VersionType OPTIONAL,
+ rspCapability [8] RspCapability,
+ euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification
+ euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifier supported on the eUICC for signature creation
+ euiccCategory [11] INTEGER {
+ other(0),
+ basicEuicc(1),
+ mediumEuicc(2),
+ contactlessEuicc(3)
+ } OPTIONAL,
+ forbiddenProfilePolicyRules [25] PprIds OPTIONAL, -- Tag '99'
+ ppVersion VersionType, -- Protection Profile version
+ sasAcreditationNumber UTF8String (SIZE(0..64)),
+ certificationDataObject [12] CertificationDataObject OPTIONAL,
+ treProperties [13] BIT STRING {
+ isDiscrete(0),
+ isIntegrated(1),
+ usesRemoteMemory(2) -- refers to the usage of remote memory protected by the Remote Memory Protection Function described in SGP.21 [4]
+ } OPTIONAL,
+ treProductReference [14] UTF8String OPTIONAL, -- Platform_Label as defined in GlobalPlatform DLOA specification [57]
+ additionalEuiccProfilePackageVersions [15] SEQUENCE OF VersionType OPTIONAL,
+ ipaMode [16] IpaMode OPTIONAL, -- active IPA, mandatory within SGP.32
+ rfu2 [17] SEQUENCE OF SubjectKeyIdentifier OPTIONAL, -- not used by this version of SGP.32.
+ rfu3 [18] OCTET STRING (SIZE(0..32)) OPTIONAL,
+ -- not used by this version of SGP.32
+ rfu4 [19] VersionType OPTIONAL, -- not used by this version of SGP.32
+ iotSpecificInfo [20] IoTSpecificInfo OPTIONAL -- mandatory within SGP.32
+}
+-- Definition of IoTSpecificInfo
+IoTSpecificInfo ::= SEQUENCE {
+iotVersion [0] SEQUENCE OF VersionType -- SGP.32 version(s) supported by the eUICC, at least one must be present
+}
+-- Definition of IpaMode
+IpaMode ::= INTEGER {
+ipad (0), -- IPAd is active
+ipae (1) -- IPAe is active
+}
+-- ASN1STOP
+
+-- Section 5.9.4
+-- ASN1START
+AddInitialEimRequest ::= [87] SEQUENCE { -- Tag 'BF57'
+ eimConfigurationDataList [0] SEQUENCE OF EimConfigurationData
+}
+-- ASN1STOP
+
+-- Section 5.9.4
+-- ASN1START
+AddInitialEimResponse ::= [87] CHOICE { -- Tag 'BF57'
+ addInitialEimOk SEQUENCE OF CHOICE {
+ associationToken [4] INTEGER,
+ addOk NULL
+ },
+ addInitialEimError INTEGER {
+ insufficientMemory(1),
+ unsignedEimConfigDisallowed(2),
+ ciPKUnknown(3),
+ invalidAssociationToken(5),
+ counterValueOutOfRange(6),
+ undefinedError(127)
+ }
+}
+-- ASN1STOP
+
+
+-- Section 5.9.10
+-- ASN1START
+GetCertsRequest ::= [86] SEQUENCE { -- Tag 'BF56'
+ euiccCiPKId SubjectKeyIdentifier OPTIONAL -- CI Public Key Identifier supported on the eUICC for signature creation
+}
+-- ASN1STOP
+-- ASN1START
+GetCertsResponse ::= [86] CHOICE { -- Tag 'BF56'
+ certs SEQUENCE {
+ eumCertificate [5] Certificate, -- Tag 'A5'
+ euiccCertificate [6] Certificate -- Tag 'A6'
+ },
+ getCertsError INTEGER {invalidCiPKId(1), undfinedError(127)}
+}
+-- ASN1STOP
+
+-- Section 5.9.11 (no ASN1START/STOP)!
+SGP32-RetrieveNotificationsListRequest ::= [43] SEQUENCE { -- Tag 'BF2B'
+ searchCriteria CHOICE {
+ seqNumber [0] INTEGER,
+ profileManagementOperation [1] NotificationEvent,
+ euiccPackageResults [2] NULL
+ } OPTIONAL
+}
+
+-- ASN1START
+SGP32-RetrieveNotificationsListResponse ::= [43] CHOICE { -- Tag 'BF2B'
+ notificationList SEQUENCE OF SGP32-PendingNotification,
+ notificationsListResultError INTEGER { undefinedError(127)},
+ euiccPackageResultList SEQUENCE OF EuiccPackageResult,
+ notificationAndEprList SEQUENCE {
+ notificationList SEQUENCE OF SGP32-PendingNotification,
+ euiccPackageResultList SEQUENCE OF EuiccPackageResult
+ }
+}
+-- ASN1STOP
+
+-- Section 5.9.15
+-- ASN1START
+EnableUsingDDRequest ::= [90] SEQUENCE { -- Tag 'BF5A'
+}
+-- ASN1STOP
+-- ASN1START
+EnableUsingDDResponse ::= [90] SEQUENCE { -- Tag 'BF5A'
+ enableUsingDDResult [0] INTEGER {
+ ok(0),
+ autoEnableNotAvailable(1),
+ noSessionContext(4),
+ undefinedError(127)
+ }
+}
+-- ASN1STOP
+
+-- Section 5.9.16
+-- ASN1START
+ProfileRollbackRequest ::= [88] SEQUENCE { -- Tag 'BF58'
+ refreshFlag BOOLEAN -- indicating whether REFRESH is required
+}
+-- ASN1STOP
+-- ASN1START
+ProfileRollbackResponse ::= [88] SEQUENCE { -- Tag 'BF58'
+ cmdResult INTEGER {
+ ok(0),
+ rollbackNotAllowed(1), -- Usage of rollback was not granted by the eIM
+ catBusy(5),
+ commandError(7),
+ undefinedError(127)
+ },
+ eUICCPackageResult [81] EuiccPackageResult OPTIONAL
+}
+-- ASN1STOP
+
+-- Section 5.9.17
+-- ASN1START
+ConfigureAutoProfileEnablingRequest ::= [89] SEQUENCE { -- Tag 'BF59'
+ autoEnableFlag [0] NULL OPTIONAL,
+ smdpOid [1] OBJECT IDENTIFIER OPTIONAL,
+ smdpAddress [2] UTF8String OPTIONAL
+}
+-- ASN1STOP
+-- ASN1START
+ConfigureAutoProfileEnablingResponse ::= [89] SEQUENCE { -- Tag 'BF59'
+ configAutoEnableResult [0] INTEGER {
+ ok(0),
+ insufficientMemory(1),
+ unsignedAutoEnableConfigDisallowed(2),
+ undefinedError(127)
+ }
+}
+-- ASN1STOP
+
+-- Section 5.9.18
+-- ASN1START
+GetEimConfigurationDataRequest ::= [85] SEQUENCE { -- Tag 'BF55'
+}
+-- ASN1STOP
+-- ASN1START
+GetEimConfigurationDataResponse ::= [85] SEQUENCE { -- Tag 'BF55'
+ eimConfigurationDataList [0] SEQUENCE OF EimConfigurationData
+}
+-- ASN1STOP
+
+-- Section 5.14.2
+-- ASN1START
+SGP32-PrepareDownloadResponse ::= [33] CHOICE { -- Tag 'BF21'
+ downloadResponseOk PrepareDownloadResponseOk,
+ downloadResponseError PrepareDownloadResponseError,
+ compactDownloadResponseOk CompactPrepareDownloadResponseOk
+}
+CompactPrepareDownloadResponseOk ::= SEQUENCE {
+ compactEuiccSigned2 CompactEuiccSigned2, -- Compact version of EuiccSigned2
+ euiccSignature2 [APPLICATION 55] OCTET STRING -- tag '5F37' signature on EuiccSigned2
+}
+CompactEuiccSigned2 ::= SEQUENCE {
+ euiccOtpk [APPLICATION 73] OCTET STRING OPTIONAL, -- otPK.EUICC.ECKA, tag '5F49' euiccOtpk is always present except if bppEuiccOtpk was chosen by the eUICC
+ hashCc Octet32 OPTIONAL -- Hash of confirmation code, if not received from Eim
+}
+-- ASN1STOP
+
+-- Section 5.14.3
+-- ASN1START
+SGP32-AuthenticateServerResponse ::= [56] CHOICE { -- Tag 'BF38'
+ authenticateResponseOk AuthenticateResponseOk,
+ authenticateResponseError AuthenticateResponseError,
+ compactAuthenticateResponseOk CompactAuthenticateResponseOk
+}
+CompactAuthenticateResponseOk ::= SEQUENCE {
+ signedData CHOICE {
+ euiccSigned1 EuiccSigned1,
+ compactEuiccSigned1 [0] CompactEuiccSigned1 -- Compact version of EuiccSigned1
+ },
+ euiccSignature1 [APPLICATION 55] OCTET STRING, -- tag 5F37 signature on EuiccSigned1
+ euiccCertificate [1] Certificate OPTIONAL, -- eUICC Certificate (CERT.EUICC.ECDSA)
+ eumCertificate [2] Certificate OPTIONAL -- EUM Certificate (CERT.EUM.ECDSA)
+}
+CompactEuiccSigned1 ::= SEQUENCE {
+ extCardResource [4] OCTET STRING, -- Extended Card Resource Information according to ETSI TS 102 226 extracted from euiccInfo2,
+ ctxParams1 [2] CtxParams1 OPTIONAL -- ctxParams1 may be left out by IPA if eIM ctxParams1 was received from the eIM
+}
+-- ASN1STOP
+
+-- Section 5.14.7
+-- ASN1START
+SGP32-PendingNotification ::= CHOICE {
+ profileInstallationResult [55] SGP32-ProfileInstallationResult, -- tag 'BF37'
+ otherSignedNotification OtherSignedNotification,
+ compactProfileInstallationResult [0] CompactProfileInstallationResult,
+ compactOtherSignedNotification [1] CompactOtherSignedNotification
+}
+SGP32-ProfileInstallationResult ::= [55] SEQUENCE { -- Tag 'BF37'
+ profileInstallationResultData [39] ProfileInstallationResultData,
+ euiccSignPIR EuiccSignPIR
+}
+CompactProfileInstallationResult ::= SEQUENCE {
+ compactProfileInstallationResultData [0] CompactProfileInstallationResultData,
+ euiccSignPIR EuiccSignPIR
+}
+CompactProfileInstallationResultData ::= SEQUENCE {
+ transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+
+ seqNumber INTEGER,
+ iccidPresent BOOLEAN DEFAULT TRUE,
+ compactFinalResult [2] CHOICE {
+ compactSuccessResult CompactSuccessResult,
+ errorResult ErrorResult
+ }
+}
+CompactSuccessResult ::= SEQUENCE {
+ compactAid [APPLICATION 15] OCTET STRING (SIZE (2)), -- Byte 14 and 15 of ISD-P AID
+ simaResponse OCTET STRING OPTIONAL -- MUST be present if the simaResponse value (EUICCResponse) is different from the 9-byte value ‘30 07 A0 05 30 03 80 01 00’ representing success
+}
+CompactOtherSignedNotification ::= SEQUENCE {
+ tbsOtherNotification NotificationMetadata,
+ euiccNotificationSignature [APPLICATION 55] OCTET STRING -- eUICC signature of tbsOtherNotification, Tag '5F37'
+}
+-- ASN1STOP
+
+-- Section 5.14.8
+-- ASN1START
+SGP32-CancelSessionResponse ::= [65] CHOICE { -- Tag 'BF41'
+ cancelSessionResponseOk CancelSessionResponseOk,
+ cancelSessionResponseError INTEGER {invalidTransactionId(5), undefinedError(127)},
+ compactCancelSessionResponseOk CompactCancelSessionResponseOk
+}
+CompactCancelSessionResponseOk ::= SEQUENCE {
+ compactEuiccCancelSessionSigned CompactEuiccCancelSessionSigned, -- Compact version of euiccCancelSessionSigned
+ euiccCancelSessionSignature [APPLICATION 55] OCTET STRING -- tag 5F37 signature on euiccCancelSessionSigned
+}
+CompactEuiccCancelSessionSigned ::= SEQUENCE {
+ reason CancelSessionReason OPTIONAL
+}
+-- ASN1STOP
+
+-- Section 6.3.1
+-- ASN1START
+EsipaMessageFromIpaToEim ::= CHOICE {
+ initiateAuthenticationRequestEsipa [57] InitiateAuthenticationRequestEsipa, -- Tag 'BF39'
+ authenticateClientRequestEsipa [59] AuthenticateClientRequestEsipa, -- Tag 'BF3B'
+ getBoundProfilePackageRequestEsipa [58] GetBoundProfilePackageRequestEsipa, -- Tag 'BF3A'
+ cancelSessionRequestEsipa [65] CancelSessionRequestEsipa, -- Tag 'BF41'
+ handleNotificationEsipa [61] HandleNotificationEsipa, -- Tag 'BF3D'
+ transferEimPackageResponse [78] TransferEimPackageResponse, -- Tag 'BF4E'
+ getEimPackageRequest [79] GetEimPackageRequest, -- Tag 'BF4F'
+ provideEimPackageResult [80] ProvideEimPackageResult -- Tag 'BF50'
+}
+EsipaMessageFromEimToIpa ::= CHOICE {
+ initiateAuthenticationResponseEsipa [57] InitiateAuthenticationResponseEsipa, -- Tag 'BF39'
+ authenticateClientResponseEsipa [59] AuthenticateClientResponseEsipa, -- Tag 'BF3B'
+ getBoundProfilePackageResponseEsipa [58] GetBoundProfilePackageResponseEsipa, -- Tag 'BF3A'
+ cancelSessionResponseEsipa [65] CancelSessionResponseEsipa, -- Tag 'BF41'
+ transferEimPackageRequest [78] TransferEimPackageRequest, -- Tag 'BF4E'
+ getEimPackageResponse [79] GetEimPackageResponse, -- Tag 'BF4F'
+ provideEimPackageResultResponse [80] ProvideEimPackageResultResponse -- Tag 'BF50'
+}
+-- ASN1STOP
+
+-- Section 6.3.2
+-- ASN1START
+InitiateAuthenticationRequestEsipa ::= [57] SEQUENCE { -- Tag 'BF39'
+ euiccChallenge [1] Octet16, -- random eUICC challenge
+ smdpAddress [3] UTF8String OPTIONAL,
+ euiccInfo1 EUICCInfo1 OPTIONAL
+}
+InitiateAuthenticationResponseEsipa ::= [57] CHOICE { -- Tag 'BF39'
+ initiateAuthenticationOkEsipa InitiateAuthenticationOkEsipa,
+ initiateAuthenticationErrorEsipa INTEGER {
+ invalidDpAddress(1),
+ euiccVersionNotSupportedByDp(2),
+ ciPKIdNotSupported(3),
+ smdpAddressMismatch(50),
+ smdpOidMismatch(51)
+}
+}
+InitiateAuthenticationOkEsipa ::= SEQUENCE {
+ transactionId [0] TransactionId OPTIONAL, -- The TransactionID generated by the SM-DP+
+ serverSigned1 ServerSigned1, -- Signed information
+ serverSignature1 [APPLICATION 55] OCTET STRING, -- Server Sign1, Tag '5F37'
+ euiccCiPKIdToBeUsed OCTET STRING, -- Key identifier (possibly truncated) of the CI Public Key to be used as required by ES10b.AuthenticateServer
+ serverCertificate Certificate,
+ matchingId UTF8String OPTIONAL,
+ ctxParams1 [2] CtxParams1 OPTIONAL
+}
+-- ASN1STOP
+
+-- Section 6.3.2.2
+-- ASN1START
+AuthenticateClientRequestEsipa ::= [59] SEQUENCE { -- Tag 'BF3B'
+ transactionId [0] TransactionId,
+ authenticateServerResponse [56] SGP32-AuthenticateServerResponse -- This is the response from ES10b.AuthenticateServer, possibly in compact format
+}
+AuthenticateClientResponseEsipa ::= [59] CHOICE { -- Tag 'BF3B'
+ authenticateClientOkDPEsipa AuthenticateClientOkDPEsipa,
+ authenticateClientOkDSEsipa AuthenticateClientOkDSEsipa,
+ authenticateClientErrorEsipa INTEGER {
+ eumCertificateInvalid(1),
+ eumCertificateExpired(2),
+ euiccCertificateInvalid(3),
+ euiccCertificateExpired(4),
+ euiccSignatureInvalid(5),
+ matchingIdRefused(6),
+ eidMismatch(7),
+ noEligibleProfile(8),
+ ciPKUnknown(9),
+ invalidTransactionId(10),
+ insufficientMemory(11),
+ pprNotAllowed(50),
+ eventIdUnknown(56),
+ undefinedError(127)
+ }
+}
+AuthenticateClientOkDPEsipa ::= SEQUENCE {
+ transactionId [0] TransactionId OPTIONAL,
+ profileMetaData [37] StoreMetadataRequest OPTIONAL,
+ smdpSigned2 SmdpSigned2, -- Signed information
+ smdpSignature2 [APPLICATION 55] OCTET STRING, -- Tag '5F37'
+ smdpCertificate Certificate, -- CERT.DPpb.ECDSA
+ hashCc Octet32 OPTIONAL -- Hash of confirmation code
+}
+AuthenticateClientOkDSEsipa ::= SEQUENCE {
+ transactionId [0] TransactionId,
+ profileDownloadTrigger [84] ProfileDownloadTriggerRequest OPTIONAL -- Tag 'BF54'
+}
+-- ASN1STOP
+
+-- Section 6.3.2.3
+-- ASN1START
+GetBoundProfilePackageRequestEsipa ::= [58] SEQUENCE { -- Tag 'BF3A'
+ transactionId [0] TransactionId,
+ prepareDownloadResponse [33] SGP32-PrepareDownloadResponse -- This is the response from ES10b.PrepareDownload, possibly in compact format
+}
+GetBoundProfilePackageResponseEsipa ::= [58] CHOICE { -- Tag 'BF3A'
+ getBoundProfilePackageOkEsipa GetBoundProfilePackageOkEsipa,
+ getBoundProfilePackageErrorEsipa INTEGER {
+ euiccSignatureInvalid(1),
+ confirmationCodeMissing(2),
+ confirmationCodeRefused(3),
+ confirmationCodeRetriesExceeded(4),
+ bppRebindingRefused(5),
+ downloadOrderExpired(6),
+ profileMetadataMismatch(50),
+ invalidTransactionId(95),
+ undefinedError(127)
+ }
+}
+GetBoundProfilePackageOkEsipa ::= SEQUENCE {
+ transactionId [0] TransactionId OPTIONAL,
+ boundProfilePackage [54] BoundProfilePackage
+}
+-- ASN1STOP
+
+-- Section 6.3.2.4
+-- ASN1START
+HandleNotificationEsipa ::= [61] CHOICE { -- Tag 'BF3D'
+ pendingNotification SGP32-PendingNotification, -- A Notification to be delivered to a Notification Receiver, possibly in compact format
+ provideEimPackageResult ProvideEimPackageResult
+}
+-- ASN1STOP
+
+-- Section 6.3.2.5
+-- ASN1START
+CancelSessionRequestEsipa ::= [65] SEQUENCE { -- Tag 'BF41'
+ transactionId TransactionId,
+ cancelSessionResponse SGP32-CancelSessionResponse -- This is the response from ES10b. CancelSession function, possibly in compact format
+}
+CancelSessionResponseEsipa ::= [65] CHOICE { -- Tag 'BF41'
+ cancelSessionOk SGP32-CancelSessionOk,
+ cancelSessionError INTEGER {
+ invalidTransactionId(1),
+ euiccSignatureInvalid(2),
+ undefinedError(127)
+ }
+}
+SGP32-CancelSessionOk ::= SEQUENCE { -- This function has no output data
+}
+-- ASN1STOP
+
+
+-- Section 6.3.2.6
+-- ASN1START
+GetEimPackageRequest ::= [79] SEQUENCE { -- Tag 'BF4F'
+ eidValue [APPLICATION 26] Octet16, -- Tag '5A'
+ notifyStateChange [0] NULL OPTIONAL, -- Notification to the eIM that it should update its information about the eUICC (e.g. list of profiles, profile states...)
+ rPLMN [1] OCTET STRING (SIZE(3)) OPTIONAL -- MCC and MNC of the last registered PLMN, coded as defined in 3GPP TS 24.008 [22]
+}
+GetEimPackageResponse ::= [79] CHOICE { -- Tag 'BF4F'
+ euiccPackageRequest [81] EuiccPackageRequest, -- Tag 'BF51'
+ ipaEuiccDataRequest [82] IpaEuiccDataRequest, -- Tag 'BF52'
+ profileDownloadTriggerRequest [84] ProfileDownloadTriggerRequest, -- Tag 'BF54'
+ eimPackageError INTEGER {
+ noEimPackageAvailable(1),
+ undefinedError(127)
+ }
+}
+-- ASN1STOP
+
+-- Section 6.3.2.7
+-- ASN1START
+ProvideEimPackageResult ::= [80] CHOICE { -- Tag 'BF50'
+ euiccPackageResult [81] EuiccPackageResult, -- Tag 'BF51'
+ ePRAndNotifications SEQUENCE {
+ euiccPackageResult [81] EuiccPackageResult, -- Tag 'BF51'
+ notificationList [43] SGP32-RetrieveNotificationsListResponse -- Tag 'BF2B'
+ },
+ ipaEuiccDataResponse [82] IpaEuiccDataResponse, -- Tag 'BF52'
+ profileDownloadTriggerResult [84] ProfileDownloadTriggerResult, -- Tag 'BF54'
+ eimPackageError INTEGER {
+ invalidPackageFormat(1),
+ unknownPackage(2),
+ undefinedError(127)
+ }
+}
+ProvideEimPackageResultResponse ::= [80] SEQUENCE { -- Tag 'BF50'
+ eimAcknowledgements [83] EimAcknowledgements OPTIONAL -- Tag 'BF53'
+}
+-- ASN1STOP
+
+-- Section 6.3.3.1
+-- ASN1START
+TransferEimPackageRequest ::= [78] CHOICE { -- Tag 'BF4E'
+ euiccPackageRequest [81] EuiccPackageRequest, -- Tag 'BF51'
+ ipaEuiccDataRequest [82] IpaEuiccDataRequest, -- Tag 'BF52'
+ eimAcknowledgements [83] EimAcknowledgements, -- Tag 'BF53'
+ profileDownloadTriggerRequest [84] ProfileDownloadTriggerRequest -- Tag 'BF54'
+}
+TransferEimPackageResponse ::= [78] CHOICE { -- Tag 'BF4E'
+ euiccPackageResult [81] EuiccPackageResult, -- Tag 'BF51'
+ ePRAndNotifications SEQUENCE {
+ euiccPackageResult [81] EuiccPackageResult, -- Tag 'BF51'
+ notificationList [43] SGP32-RetrieveNotificationsListResponse -- Tag 'BF2B'
+ },
+ ipaEuiccDataResponse [82] IpaEuiccDataResponse, -- Tag 'BF52'
+ eimPackageReceived NULL,
+ eimPackageError INTEGER {
+ invalidPackageFormat(1),
+ unknownPackage(2),
+ undefinedError(127)
+ }
+}
+-- ASN1STOP
+
+
+END
diff --git a/library/euicc/SGP32Definitions_EncDec.cc b/library/euicc/SGP32Definitions_EncDec.cc
new file mode 100644
index 00000000..4dfcc6b9
--- /dev/null
+++ b/library/euicc/SGP32Definitions_EncDec.cc
@@ -0,0 +1,113 @@
+#include "SGP32Definitions.hh"
+
+namespace SGP32Definitions__Types {
+
+using namespace SGP32Definitions;
+using namespace PKIX1Explicit88;
+
+TTCN_Module SGP32Definitions__EncDec("SGP32Definitions_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__EsipaMessageFromIpaToEim(const EsipaMessageFromIpaToEim &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EsipaMessageFromIpaToEim_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EsipaMessageFromIpaToEim dec__EsipaMessageFromIpaToEim(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EsipaMessageFromIpaToEim msg;
+ buf.put_os(stream);
+
+ msg.decode(EsipaMessageFromIpaToEim_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__EsipaMessageFromEimToIpa(const EsipaMessageFromEimToIpa &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EsipaMessageFromEimToIpa_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EsipaMessageFromEimToIpa dec__EsipaMessageFromEimToIpa(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EsipaMessageFromEimToIpa msg;
+ buf.put_os(stream);
+
+ msg.decode(EsipaMessageFromEimToIpa_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__EuiccPackageResult(const EuiccPackageResult &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(EuiccPackageResult_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+EuiccPackageResult dec__EuiccPackageResult(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ EuiccPackageResult msg;
+ buf.put_os(stream);
+
+ msg.decode(EuiccPackageResult_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__GetCertsResponse(const GetCertsResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(GetCertsResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+GetCertsResponse dec__GetCertsResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ GetCertsResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(GetCertsResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__GetEimConfigurationDataResponse(const GetEimConfigurationDataResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(GetEimConfigurationDataResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+GetEimConfigurationDataResponse dec__GetEimConfigurationDataResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ GetEimConfigurationDataResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(GetEimConfigurationDataResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+OCTETSTRING enc__AddInitialEimResponse(const AddInitialEimResponse &msg) {
+ TTCN_Buffer buf;
+
+ buf.clear();
+ msg.encode(AddInitialEimResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+ return OCTETSTRING(buf.get_len(), buf.get_data());
+}
+
+AddInitialEimResponse dec__AddInitialEimResponse(const OCTETSTRING &stream) {
+ TTCN_Buffer buf;
+ AddInitialEimResponse msg;
+ buf.put_os(stream);
+
+ msg.decode(AddInitialEimResponse_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+ return msg;
+}
+
+
+}
diff --git a/library/euicc/SGP32Definitions_Templates.ttcn b/library/euicc/SGP32Definitions_Templates.ttcn
new file mode 100644
index 00000000..f22778c1
--- /dev/null
+++ b/library/euicc/SGP32Definitions_Templates.ttcn
@@ -0,0 +1,433 @@
+/* SGP32 Templates in TTCN-3
+ *
+ * Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+ *
+ * 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 SGP32Definitions_Templates {
+
+import from SGP32Definitions all;
+import from SGP32Definitions_Types all;
+
+import from RSPDefinitions all;
+import from RSPDefinitions_Types all;
+import from RSPDefinitions_Templates all;
+
+import from PKIX1Explicit88 all;
+import from PKIX1Explicit88_Templates all;
+import from PKIX1Explicit88_Types all;
+
+/* GSMA SGP.32, section 6.3.2.1 */
+template (present) EsipaMessageFromEimToIpa
+tr_initiateAuthenticationResponseEsipa(template (present) octetstring euiccChallenge := ?,
+ template (present) universal charstring serverAddress := ?) := {
+ initiateAuthenticationResponseEsipa := {
+ initiateAuthenticationOkEsipa := {
+ transactionId := *,
+ serverSigned1 := {
+ transactionId := ?,
+ euiccChallenge := euiccChallenge,
+ serverAddress := serverAddress,
+ serverChallenge := ?
+ },
+ serverSignature1 := ?,
+ euiccCiPKIdToBeUsed := ?,
+ serverCertificate := ?,
+ matchingId := *,
+ ctxParams1 := *
+ }
+ }
+}
+
+template (value) EsipaMessageFromEimToIpa
+ts_initiateAuthenticationResponseEsipa(template (value) octetstring euiccChallenge := '00112233445566778899AABBCCDDEEFF'O,
+ template (value) universal charstring serverAddress := "smdp.example.com") := {
+ initiateAuthenticationResponseEsipa := {
+ initiateAuthenticationOkEsipa := {
+ transactionId := omit,
+ serverSigned1 := {
+ transactionId := 'ABCDEF'O,
+ euiccChallenge := euiccChallenge,
+ serverAddress := "smdp.example.com",
+ serverChallenge := '01020304050607080910111213141516'O
+ },
+ serverSignature1 := '01020304'O,
+ euiccCiPKIdToBeUsed := 'F54172BDF98A95D65CBEB88A38A1C11D800A85C3'O, /* NIST */
+ serverCertificate := ts_cert_s_sm_dpauth_nist,
+// serverCertificate := ts_cert_s_sm_dpauth_brp,
+// serverCertificate := ts_cert_s_sm_dp2auth_nist,
+// serverCertificate := ts_cert_s_sm_dp2auth_brp,
+ matchingId := omit,
+ ctxParams1 := omit
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.1 */
+template (present) EsipaMessageFromIpaToEim
+tr_initiateAuthenticationRequestEsipa(template (present) octetstring euiccChallenge := ?) := {
+ initiateAuthenticationRequestEsipa := {
+ euiccChallenge := euiccChallenge,
+ smdpAddress := *,
+ euiccInfo1 := *
+ }
+}
+template (value) EsipaMessageFromIpaToEim
+ts_initiateAuthenticationRequestEsipa(template (value) octetstring euiccChallenge := '00112233445566778899aabbccddeeff'O) := {
+ initiateAuthenticationRequestEsipa := {
+ euiccChallenge := euiccChallenge,
+ smdpAddress := omit,
+ euiccInfo1 := omit
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.2 */
+template (present) EsipaMessageFromIpaToEim
+tr_authenticateClientRequestEsipa := {
+ authenticateClientRequestEsipa := {
+ transactionId := ?,
+ authenticateServerResponse := {
+ authenticateResponseOk := ?
+ }
+ }
+}
+/* TODO: create coresponding ts_ template */
+
+/* GSMA SGP.32, section 6.3.2.2 */
+template (present) EsipaMessageFromEimToIpa
+tr_authenticateClientResponseEsipa_dse(template (present) octetstring transactionId := ?,
+ template (present) charstring activationCode := ?) := {
+ authenticateClientResponseEsipa := {
+ authenticateClientOkDSEsipa := {
+ transactionId := transactionId,
+ profileDownloadTrigger := {
+ profileDownloadData := {
+ activationCode := ?
+ },
+ eimTransactionId := *
+ }
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_authenticateClientResponseEsipa_dse(template (value) octetstring transactionId := 'ABCDEF'O,
+ template (value) charstring activationCode := "1$SMDP.EXAMPLE.COM$$1.3.6.1.4.1.31746") := {
+ authenticateClientResponseEsipa := {
+ authenticateClientOkDSEsipa := {
+ transactionId := transactionId,
+ profileDownloadTrigger := {
+ profileDownloadData := {
+ activationCode := activationCode
+ },
+ eimTransactionId := omit
+ }
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.2 */
+template (present) EsipaMessageFromEimToIpa
+tr_authenticateClientResponseEsipa_dpe(template (present) octetstring transactionId := ?) := {
+ authenticateClientResponseEsipa := {
+ authenticateClientOkDPEsipa := {
+ transactionId := transactionId,
+ profileMetaData := *,
+ smdpSigned2 := {
+ transactionId := ?,
+ ccRequiredFlag := ?,
+ bppEuiccOtpk := *
+ },
+ smdpSignature2 := ?,
+ smdpCertificate := ?,
+ hashCc := *
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_authenticateClientResponseEsipa_dpe(template (value) octetstring transactionId := 'ABCDEF'O) := {
+ authenticateClientResponseEsipa := {
+ authenticateClientOkDPEsipa := {
+ transactionId := transactionId,
+ profileMetaData := omit,
+ smdpSigned2 := {
+ transactionId := transactionId,
+ ccRequiredFlag := false,
+ bppEuiccOtpk := omit
+ },
+ smdpSignature2 := 'AAAAAAAAAAAAAAAAAAAAAAAA'O,
+ smdpCertificate := ts_cert_s_sm_dpauth_nist,
+// smdpCertificate := ts_cert_s_sm_dpauth_brp,
+// smdpCertificate := ts_cert_s_sm_dp2auth_nist,
+// smdpCertificate := ts_cert_s_sm_dp2auth_brp,
+ hashCc := omit
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.6 */
+template (present) EsipaMessageFromIpaToEim
+tr_getEimPackageRequest(template (present) octetstring eidValue := ?) := {
+ getEimPackageRequest := {
+ eidValue := eidValue,
+ notifyStateChange := *,
+ rPLMN := *
+ }
+}
+template (value) EsipaMessageFromIpaToEim
+ts_getEimPackageRequest(template (value) octetstring eidValue) := {
+ getEimPackageRequest := {
+ eidValue := eidValue,
+ notifyStateChange := omit,
+ rPLMN := omit
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.6 and 2.11.1.3 */
+template (present) EsipaMessageFromEimToIpa
+tr_getEimPackageResponse_dnlTrigReq(template (present) charstring activationCode := ?) := {
+ getEimPackageResponse := {
+ profileDownloadTriggerRequest := {
+ profileDownloadData := {
+ activationCode := activationCode
+ },
+ eimTransactionId := *
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_getEimPackageResponse_dnlTrigReq(template (value) charstring activationCode := "1$SMDP.EXAMPLE.COM$$1.3.6.1.4.1.31746") := {
+ getEimPackageResponse := {
+ profileDownloadTriggerRequest := {
+ profileDownloadData := {
+ activationCode := activationCode
+ },
+ eimTransactionId := omit
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.6 and 2.11.1.2 */
+template (present) EsipaMessageFromEimToIpa
+tr_getEimPackageResponse_euiccDataReq := {
+ getEimPackageResponse := {
+ ipaEuiccDataRequest := {
+ tagList := ?,
+ euiccCiPKId := *,
+ searchCriteria := *
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_getEimPackageResponse_euiccDataReq := {
+ getEimPackageResponse := {
+ ipaEuiccDataRequest := {
+ tagList := '80BF20BF228384A5A688A9BF2B'O,
+ euiccCiPKId := omit,
+ searchCriteria := omit
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.6 */
+template (present) EsipaMessageFromEimToIpa
+tr_getEimPackageResponse_eimPkgErrUndef := {
+ getEimPackageResponse := {
+ eimPackageError := ?
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_getEimPackageResponse_eimPkgErrUndef := {
+ getEimPackageResponse := {
+ eimPackageError := 127
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.6 */
+template (value) EsipaMessageFromEimToIpa
+ts_getEimPackageResponse_euiccPkgReq := {
+ getEimPackageResponse := {
+ euiccPackageRequest := {
+ euiccPackageSigned := {
+ eimId := "myEim",
+ eidValue := '00112233445566778899AABBCCDDEEFF'O,
+ counterValue := 123,
+ transactionId := omit,
+ euiccPackage := {
+ psmoList := {
+ {
+ configureAutoEnable := {
+ autoEnableFlag := NULL,
+ smdpOid := omit,
+ smdpAddress := omit
+ }
+ }
+ }
+ }
+ },
+ eimSignature := '1234567890'O
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.5 */
+template (present) EsipaMessageFromIpaToEim
+tr_cancelSessionRequestEsipa := {
+ cancelSessionRequestEsipa := {
+ transactionId := ?,
+ cancelSessionResponse := {
+ cancelSessionResponseOk := tr_cancelSessionResponseOk
+ }
+ }
+}
+template (value) EsipaMessageFromIpaToEim
+ts_cancelSessionRequestEsipa := {
+ cancelSessionRequestEsipa := {
+ transactionId := 'AABBCC'O,
+ cancelSessionResponse := {
+ cancelSessionResponseOk := ts_cancelSessionResponseOk
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.5 */
+template (present) EsipaMessageFromEimToIpa
+tr_cancelSessionResponseEsipa := {
+ cancelSessionResponseEsipa := {
+ cancelSessionOk := {
+ /* This function has no output data */
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_cancelSessionResponseEsipa := {
+ cancelSessionResponseEsipa := {
+ cancelSessionOk := {
+ /* This function has no output data */
+ }
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.3 */
+template (present) EsipaMessageFromEimToIpa
+tr_getBoundProfilePackageResponseEsipa := {
+ getBoundProfilePackageResponseEsipa := {
+ getBoundProfilePackageOkEsipa := {
+ transactionId := *,
+ boundProfilePackage := tr_boundProfilePackage
+ }
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_getBoundProfilePackageResponseEsipa := {
+ getBoundProfilePackageResponseEsipa := {
+ getBoundProfilePackageOkEsipa := {
+ transactionId := omit,
+ boundProfilePackage := ts_boundProfilePackage
+ }
+ }
+}
+
+/* GSMA SGP.32, section 5.9.1 */
+template (present) EuiccPackageResult
+tr_euiccPackageResult := {
+ euiccPackageResultSigned := {
+ euiccPackageResultDataSigned := {
+ eimId := ?,
+ counterValue := ?,
+ transactionId := *,
+ seqNumber := ?,
+ euiccResult := ?
+ },
+ euiccSignEPR := ?
+ }
+}
+template (value) EuiccPackageResult
+ts_euiccPackageResult := {
+ euiccPackageResultSigned := {
+ euiccPackageResultDataSigned := {
+ eimId := "myEim",
+ counterValue := 333,
+ transactionId := omit,
+ seqNumber := 1234,
+ euiccResult := {
+ {
+ configureAutoEnableResult := 0
+ }
+ }
+ },
+ euiccSignEPR := 'AABBCCDDEEFF'O
+ }
+}
+
+/* GSMA SGP.32, section 6.3.2.7 */
+/* TODO rename tr_provideEimPackageResultResponse to something like tr_provideEimPackageResultResponse_eimAck */
+template (present) EsipaMessageFromEimToIpa
+tr_provideEimPackageResultResponse := {
+ provideEimPackageResultResponse := {
+ eimAcknowledgements := *
+ }
+}
+template (value) EsipaMessageFromEimToIpa
+ts_provideEimPackageResultResponse(template (value) EimAcknowledgements eimAcknowledgements := {}) := {
+ provideEimPackageResultResponse := {
+ eimAcknowledgements := eimAcknowledgements
+ }
+}
+
+/* GSMA SGP.32, section 2.11.1.2 */
+template (present) GetCertsResponse
+tr_getCertsResponse := {
+ certs := {
+ eumCertificate := ?,
+ euiccCertificate := ?
+ }
+}
+template (value) GetCertsResponse
+ts_getCertsResponse := {
+ certs := {
+ eumCertificate := ts_cert_s_sm_dpauth_nist,
+ euiccCertificate := ts_cert_eum_nist
+ }
+}
+
+/* GSMA SGP.32, section 5.9.18 */
+template (present) GetEimConfigurationDataResponse
+tr_getEimConfigurationDataResponse := {
+ eimConfigurationDataList := ?
+}
+template (value) GetEimConfigurationDataResponse
+ts_getEimConfigurationDataResponse(template (value) charstring eimFqdn := "127.0.0.1") := {
+ eimConfigurationDataList := {
+ {
+ eimId := "myEIM",
+ eimFqdn := eimFqdn,
+ eimIdType := omit,
+ counterValue := omit,
+ associationToken := 123,
+ eimPublicKeyData := omit,
+ trustedPublicKeyDataTls := omit,
+ eimSupportedProtocol := omit,
+ euiccCiPKId := omit
+ }
+ }
+}
+
+/* GSMA SGP.32, section 5.9.4 */
+template (present) AddInitialEimResponse
+tr_addInitialEimResponse := {
+ addInitialEimOk := ?
+}
+template (value) AddInitialEimResponse
+ts_addInitialEimResponse(template (value) charstring eimFqdn := "127.0.0.1") := {
+ addInitialEimOk := {
+ {
+ addOk := NULL
+ }
+ }
+}
+
+} \ No newline at end of file
diff --git a/library/euicc/SGP32Definitions_Types.ttcn b/library/euicc/SGP32Definitions_Types.ttcn
new file mode 100644
index 00000000..44a1a074
--- /dev/null
+++ b/library/euicc/SGP32Definitions_Types.ttcn
@@ -0,0 +1,24 @@
+module SGP32Definitions_Types {
+
+import from SGP32Definitions all;
+import from Native_Functions all;
+
+external function dec_EsipaMessageFromIpaToEim(in octetstring stream) return EsipaMessageFromIpaToEim;
+external function enc_EsipaMessageFromIpaToEim(in EsipaMessageFromIpaToEim msg) return octetstring;
+
+external function dec_EsipaMessageFromEimToIpa(in octetstring stream) return EsipaMessageFromEimToIpa;
+external function enc_EsipaMessageFromEimToIpa(in EsipaMessageFromEimToIpa msg) return octetstring;
+
+external function dec_EuiccPackageResult(in octetstring stream) return EuiccPackageResult;
+external function enc_EuiccPackageResult(in EuiccPackageResult msg) return octetstring;
+
+external function dec_GetCertsResponse(in octetstring stream) return GetCertsResponse;
+external function enc_GetCertsResponse(in GetCertsResponse msg) return octetstring;
+
+external function dec_GetEimConfigurationDataResponse(in octetstring stream) return GetEimConfigurationDataResponse;
+external function enc_GetEimConfigurationDataResponse(in GetEimConfigurationDataResponse msg) return octetstring;
+
+external function dec_AddInitialEimResponse(in octetstring stream) return AddInitialEimResponse;
+external function enc_AddInitialEimResponse(in AddInitialEimResponse msg) return octetstring;
+
+}
diff --git a/library/hnbap/HNBAP_Templates.ttcn b/library/hnbap/HNBAP_Templates.ttcn
new file mode 100644
index 00000000..7a86e0c9
--- /dev/null
+++ b/library/hnbap/HNBAP_Templates.ttcn
@@ -0,0 +1,422 @@
+/* HNBAP Templates in TTCN-3
+ * (C) 2021 Pau Espin Pedrol <pespin@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 HNBAP_Templates {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from HNBAP_IEs all;
+import from HNBAP_CommonDataTypes all;
+import from HNBAP_Constants all;
+import from HNBAP_Containers all;
+import from HNBAP_PDU_Contents all;
+import from HNBAP_PDU_Descriptions all;
+
+/*********************************************************************************
+ * 3GPP TS 25.469
+ *********************************************************************************/
+
+template (value) Cause ts_HnbapCause(template (value) CauseRadioNetwork c) := {
+ radioNetwork := c
+}
+
+/* 9.1.3 HNB REGISTER REQUEST */
+template (present) HNBAP_PDU
+tr_HNBAP_HNBRegisterRequest(template (present) octetstring hNB_Identity_Info := ?,
+ template (present) OCT3 plmnid := ?,
+ template (present) BIT28 cell_identity := ?,
+ template (present) OCT2 lac := ?,
+ template (present) OCT1 rac := ?,
+ template (present) OCT2 sac := ?) := {
+ initiatingMessage := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ hNBRegisterRequest := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_HNB_Identity,
+ criticality := reject,
+ value_ := {
+ hNB_Identity := {
+ hNB_Identity_Info := hNB_Identity_Info,
+ iE_Extensions := omit
+ }
+ }
+ }, {
+ id := 8,
+ criticality := reject,
+ value_ := {
+ hNB_Location_Information := {
+ macroCoverageInfo := omit,
+ geographicalCoordinates := omit,
+ iE_Extensions := omit
+ }
+ }
+ }, {
+ id := 9,
+ criticality := reject,
+ value_ := { pLMNidentity := plmnid }
+ }, {
+ id := 11,
+ criticality := reject,
+ value_ := { cellIdentity := cell_identity }
+ }, {
+ id := 6,
+ criticality := reject,
+ value_ := { lAC := lac }
+ }, {
+ id := 7,
+ criticality := reject,
+ value_ := { rAC := rac }
+ }, {
+ id := 10,
+ criticality := reject,
+ value_ := { sAC := sac }
+ }
+ },
+ protocolExtensions := *
+ }
+ }
+ }
+}
+
+template (value) HNBAP_PDU
+ts_HNBAP_HNBRegisterRequest(template (value) octetstring hNB_Identity_Info,
+ template (value) OCT3 plmnid,
+ template (value) BIT28 cell_identity,
+ template (value) OCT2 lac,
+ template (value) OCT1 rac,
+ template (value) OCT2 sac) := {
+ initiatingMessage := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ hNBRegisterRequest := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_HNB_Identity,
+ criticality := reject,
+ value_ := {
+ hNB_Identity := {
+ hNB_Identity_Info := hNB_Identity_Info,
+ iE_Extensions := omit
+ }
+ }
+ }, {
+ id := 8,
+ criticality := reject,
+ value_ := {
+ hNB_Location_Information := {
+ macroCoverageInfo := omit,
+ geographicalCoordinates := omit,
+ iE_Extensions := omit
+ }
+ }
+ }, {
+ id := 9,
+ criticality := reject,
+ value_ := { pLMNidentity := plmnid }
+ }, {
+ id := 11,
+ criticality := reject,
+ value_ := { cellIdentity := cell_identity }
+ }, {
+ id := 6,
+ criticality := reject,
+ value_ := { lAC := lac }
+ }, {
+ id := 7,
+ criticality := reject,
+ value_ := { rAC := rac }
+ }, {
+ id := 10,
+ criticality := reject,
+ value_ := { sAC := sac }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+
+/* 9.1.4 HNB REGISTER ACCEPT */
+template (present) HNBAP_PDU
+tr_HNBAP_HNBRegisterAccept(template (present) uint16_t rnc_id := ?) := {
+ successfulOutcome := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ hNBRegisterAccept := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_RNC_ID,
+ criticality := reject,
+ value_ := { RNC_ID := rnc_id }
+ }
+ },
+ protocolExtensions := * /* TODO: Mux Port Number (optional) 9.2.29 */
+ }
+ }
+ }
+}
+
+template (value) HNBAP_PDU
+ts_HNBAP_HNBRegisterAccept(template (value) uint16_t rnc_id) := {
+ successfulOutcome := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ hNBRegisterAccept := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_RNC_ID,
+ criticality := reject,
+ value_ := { RNC_ID := rnc_id }
+ }
+ },
+ protocolExtensions := omit /* TODO: Mux Port Number (optional) 9.2.29 */
+ }
+ }
+ }
+}
+
+/* 9.1.5 HNB REGISTER REJECT */
+template (present) HNBAP_PDU
+tr_HNBAP_HNBRegisterReject(template (present) Cause cause := ?) := {
+ unsuccessfulOutcome := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ HNBRegisterReject := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_Cause,
+ criticality := ignore,
+ value_ := { Cause := cause }
+ }
+ },
+ protocolExtensions := * /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+template (value) HNBAP_PDU
+ts_HNBAP_HNBRegisterReject(template (value) Cause cause) := {
+ unsuccessfulOutcome := {
+ procedureCode := id_HNBRegister,
+ criticality := reject,
+ value_ := {
+ HNBRegisterReject := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_Cause,
+ criticality := ignore,
+ value_ := { Cause := cause }
+ }
+ },
+ protocolExtensions := omit /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+/* 9.1.6 UE REGISTER REQUEST */
+template (present) HNBAP_PDU
+tr_HNBAP_UERegisterRequest(template (present) UE_Identity ue_id) := {
+ initiatingMessage := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterRequest := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Registration_Cause,
+ criticality := ignore,
+ value_ := { Registration_Cause := normal }
+ }, {
+ id := HNBAP_Constants.id_UE_Capabilities,
+ criticality := ignore,
+ value_ := {
+ UE_Capabilities := {
+ access_stratum_release_indicator := ?,
+ csg_capability := ?
+ }
+ }
+ }
+ },
+ protocolExtensions := * /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+template (value) HNBAP_PDU
+ts_HNBAP_UERegisterRequest(template (value) UE_Identity ue_id) := {
+ initiatingMessage := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterRequest := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Registration_Cause,
+ criticality := ignore,
+ value_ := { Registration_Cause := normal }
+ }, {
+ id := HNBAP_Constants.id_UE_Capabilities,
+ criticality := ignore,
+ value_ := {
+ UE_Capabilities := {
+ access_stratum_release_indicator := rel_8_and_beyond,
+ csg_capability := not_csg_capable,
+ iE_Extensions := omit
+ }
+ }
+ }
+ },
+ protocolExtensions := omit /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+/* 9.1.7 UE REGISTER ACCEPT */
+template (present) HNBAP_PDU
+tr_HNBAP_UERegisterAccept(template (present) UE_Identity ue_id) := {
+ successfulOutcome := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterAccept := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Context_ID,
+ criticality := reject,
+ value_ := { Context_ID := ? }
+ }, *
+ },
+ protocolExtensions := * /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+template (value) HNBAP_PDU
+ts_HNBAP_UERegisterAccept(template (value) UE_Identity ue_id,
+ template (value) BIT24 context_id) := {
+ successfulOutcome := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterAccept := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Context_ID,
+ criticality := reject,
+ value_ := { Context_ID := context_id }
+ }
+ },
+ protocolExtensions := omit /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+/* 9.1.8 UE REGISTER REJECT */
+template (present) HNBAP_PDU
+tr_HNBAP_UERegisterReject(template (present) UE_Identity ue_id, template (present) Cause cause := ?) := {
+ unsuccessfulOutcome := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterReject := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Cause,
+ criticality := ignore,
+ value_ := { Cause := cause }
+ }, *
+ },
+ protocolExtensions := * /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+template (value) HNBAP_PDU
+ts_HNBAP_UERegisterReject(template (value) UE_Identity ue_id, template (value) Cause cause) := {
+ unsuccessfulOutcome := {
+ procedureCode := id_UERegister,
+ criticality := reject,
+ value_ := {
+ uERegisterReject := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_UE_Identity,
+ criticality := reject,
+ value_ := { UE_Identity := ue_id }
+ }, {
+ id := HNBAP_Constants.id_Cause,
+ criticality := ignore,
+ value_ := { Cause := cause }
+ }
+ },
+ protocolExtensions := omit /* TODO: CriticalityDiagnostics, BackoffTimer */
+ }
+ }
+ }
+}
+
+/* 9.1.9 HNB DE-REGISTER */
+template (value) HNBAP_PDU
+ts_HNBAP_HNBDe_Register(template (value) Cause cause) := {
+ initiatingMessage := {
+ procedureCode := id_HNBDe_Register,
+ criticality := reject,
+ value_ := {
+ HNBDe_Register := {
+ protocolIEs := {
+ {
+ id := HNBAP_Constants.id_Cause,
+ criticality := ignore,
+ value_ := { Cause := cause }
+ }
+ },
+ protocolExtensions := omit /* TODO: BackoffTimer */
+ }
+ }
+ }
+}
+
+}
diff --git a/library/mncc.h b/library/mncc.h
index 9aff9481..f70f9bda 100644
--- a/library/mncc.h
+++ b/library/mncc.h
@@ -5,6 +5,7 @@
*/
#include <stdint.h>
+#include <netinet/in.h>
/* GSM 04.08 Bearer Capability: Rate Adaption */
enum gsm48_bcap_ra {
@@ -229,6 +230,7 @@ enum {
#define MNCC_F_CCCAP 0x0800
#define MNCC_F_KEYPAD 0x1000
#define MNCC_F_SIGNAL 0x2000
+#define MNCC_F_GCR 0x4000
struct gsm_mncc {
/* context based information */
@@ -266,7 +268,15 @@ struct gsm_mncc {
unsigned char lchan_type;
unsigned char lchan_mode;
- char sdp[1024];
+ union {
+ struct {
+ char sdp[1024];
+ } v7;
+ struct {
+ uint8_t gcr[16];
+ char sdp[1024];
+ } v8;
+ };
};
struct gsm_data_frame {
@@ -275,7 +285,7 @@ struct gsm_data_frame {
unsigned char data[0];
};
-#define MNCC_SOCK_VERSION 5
+#define MNCC_SOCK_VERSION 7
struct gsm_mncc_hello {
uint32_t msg_type;
uint32_t version;
@@ -294,8 +304,7 @@ struct gsm_mncc_hello {
struct gsm_mncc_rtp {
uint32_t msg_type;
uint32_t callref;
- uint32_t ip;
- uint16_t port;
+ struct sockaddr_storage addr;
uint32_t payload_type;
uint32_t payload_msg_type;
diff --git a/library/ranap/RANAP_Templates.ttcn b/library/ranap/RANAP_Templates.ttcn
index a1b0a593..8e6c8f37 100644
--- a/library/ranap/RANAP_Templates.ttcn
+++ b/library/ranap/RANAP_Templates.ttcn
@@ -1,6 +1,8 @@
module RANAP_Templates {
import from General_Types all;
+import from Misc_Helpers all;
+import from Native_Functions all;
import from RANAP_IEs all;
import from RANAP_CommonDataTypes all;
@@ -10,6 +12,8 @@ import from RANAP_PDU_Contents all;
import from RANAP_PDU_Descriptions all;
template (value) Cause ts_RanapCause_om_intervention := { misc := 113 };
+template (value) Cause ts_RanapCause_nas_normal := { nAS := 83 };
+template (value) Cause ts_RanapCause_radio_conn_lost := { radioNetwork := 46 };
/*****************************************************************************************************
* Reset
@@ -449,7 +453,7 @@ ts_RANAP_IuReleaseRequest(template (value) Cause cause,
protocolIEs := {
{
id := id_Cause,
- criticality := reject,
+ criticality := ignore,
value_ := {
cause := cause
}
@@ -471,7 +475,7 @@ tr_RANAP_IuReleaseRequest(template Cause cause,
protocolIEs := {
{
id := id_Cause,
- criticality := reject,
+ criticality := ignore,
value_ := {
cause := cause
}
@@ -487,6 +491,24 @@ tr_RANAP_IuReleaseRequest(template Cause cause,
* RAB Release
*****************************************************************************************************/
+template (value) RAB_ID
+t_RAB_id(integer rab_id) := int2bit(rab_id, 8);
+
+template (value) TransportLayerAddress ts_RAB_TLA4(OCT4 ip) := hex2bit('350001'H & oct2hex(ip) & '00000000000000000000000000'H);
+template (value) TransportLayerAddress ts_RAB_TLA6(OCT16 ip) := hex2bit('350000'H & oct2hex(ip) & '00'H);
+function f_ts_RAB_TLA(charstring addr) return template (value) TransportLayerAddress {
+ if (f_addr_is_ipv6(addr)) {
+ var OCT16 ip6 := f_inet6_addr(addr);
+ return ts_RAB_TLA6(ip6);
+ } else {
+ var OCT4 ip4 := f_inet_addr(addr);
+ return ts_RAB_TLA4(ip4);
+ }
+}
+
+template (value) BindingID
+t_RAB_binding_port(integer prt) := int2oct(prt, 2) & '0000'O;
+
template (value) RANAP_PDU
ts_RANAP_RabReleaseRequest(template (value) RAB_ID rab_id, template (value) Cause cause,
template (omit) RAB_ReleaseRequest.protocolExtensions exts := omit) := {
@@ -522,7 +544,7 @@ ts_RANAP_RabReleaseRequest(template (value) RAB_ID rab_id, template (value) Caus
}
}
template RANAP_PDU
-tr_RANAP_RabReleaseRequest(template RAB_ID rab_id, template Cause cause,
+tr_RANAP_RabReleaseRequest(template (present) RAB_ID rab_id, template Cause cause,
template RAB_ReleaseRequest.protocolExtensions exts := *) := {
initiatingMessage := {
procedureCode := id_RAB_ReleaseRequest,
@@ -641,7 +663,6 @@ tr_RANAP_IuReleaseComplete(template Iu_ReleaseComplete.protocolIEs ies := *,
template (value) RANAP_PDU
ts_RANAP_Paging(template (value) CN_DomainIndicator dom, template (value) IMSI imsi,
- template (omit) TemporaryUE_ID temp_id := omit,
template (omit) Paging.protocolExtensions exts := omit) := {
initiatingMessage := {
procedureCode := id_Paging,
@@ -701,6 +722,47 @@ tr_RANAP_Paging(template CN_DomainIndicator dom, template IMSI imsi,
}
}
+template (value) TemporaryUE_ID ts_RANAP_TemporaryUE_ID_TMSI(octetstring tmsi) := {
+ tMSI := tmsi
+}
+
+template (value) RANAP_PDU
+ts_RANAP_Paging_temp_id(template (value) CN_DomainIndicator dom, template (value) IMSI imsi,
+ template (value) TemporaryUE_ID temp_id,
+ template (omit) Paging.protocolExtensions exts := omit) := {
+ initiatingMessage := {
+ procedureCode := id_Paging,
+ criticality := ignore,
+ value_ := {
+ paging := {
+ protocolIEs := {
+ {
+ id := id_CN_DomainIndicator,
+ criticality := ignore,
+ value_ := {
+ cN_DomainIndicator := dom
+ }
+ }, {
+ id := id_PermanentNAS_UE_ID,
+ criticality := ignore,
+ value_ := {
+ permanentNAS_UE_ID := {
+ iMSI := imsi
+ }
+ }
+ }, {
+ id := id_TemporaryUE_ID,
+ criticality := ignore,
+ value_ := {
+ temporaryUE_ID := temp_id
+ }
+ }
+ },
+ protocolExtensions := exts
+ }
+ }
+ }
+}
/*****************************************************************************************************
@@ -1239,7 +1301,7 @@ template (value) RAB_SetupOrModifyList ts_RAB_SML(template (value) RAB_ID rab_id
}
}
} }
-template RAB_SetupOrModifyList tr_RAB_SML(template RAB_ID rab_id,
+template RAB_SetupOrModifyList tr_RAB_SML(template (present) RAB_ID rab_id,
template TransportLayerAddress tla,
template BindingID binding_id) := { {
{
@@ -1271,106 +1333,496 @@ template RAB_SetupOrModifyList tr_RAB_SML(template RAB_ID rab_id,
}
} }
+/* Like ts_RAB_SML(), but more control on presence/absence of individual IEs */
+template (value) RAB_SetupOrModifyList ts_RAB_SML2(
+ template (value) RAB_ID rab_id,
+ template (omit) RAB_Parameters rab_params,
+ template (omit) UserPlaneInformation user_plane_info,
+ template (omit) TransportLayerInformation transport_layer_info
+ ) := { {
+ {
+ id := id_RAB_SetupOrModifyItem,
+ firstCriticality := reject,
+ firstValue := {
+ rAB_SetupOrModifyItemFirst := {
+ rAB_ID := rab_id,
+ nAS_SynchronisationIndicator := omit,
+ rAB_Parameters := rab_params,
+ userPlaneInformation := user_plane_info,
+ transportLayerInformation := transport_layer_info,
+ service_Handover := omit,
+ iE_Extensions := omit
+ }
+ },
+ secondCriticality := ignore,
+ secondValue := {
+ rAB_SetupOrModifyItemSecond := {
+ pDP_TypeInformation := omit,
+ dataVolumeReportingIndication := omit,
+ dl_GTP_PDU_SequenceNumber := omit,
+ ul_GTP_PDU_SequenceNumber := omit,
+ dl_N_PDU_SequenceNumber := omit,
+ ul_N_PDU_SequenceNumber := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
-template (value) RANAP_PDU
-ts_RANAP_RabAssReq(template (value) RAB_SetupOrModifyList rab_sml,
- template (omit) RAB_AssignmentRequest.protocolExtensions exts := omit) := {
- initiatingMessage := {
+template (value) TransportLayerInformation ts_TLI_ps(template (value) TransportLayerAddress tla,
+ template (value) GTP_TEI gtp_tei) := {
+ transportLayerAddress := tla,
+ iuTransportAssociation := {
+ gTP_TEI := gtp_tei
+ },
+ iE_Extensions := omit
+}
+template TransportLayerInformation tr_TLI_ps(template TransportLayerAddress tla,
+ template (value) GTP_TEI gtp_tei) := {
+ transportLayerAddress := tla,
+ iuTransportAssociation := {
+ gTP_TEI := gtp_tei
+ },
+ iE_Extensions := *
+}
+
+template (value) RAB_SetupOrModifyList ts_RAB_SML_ps(template (value) RAB_ID rab_id,
+ template (value) TransportLayerAddress tla,
+ template (value) GTP_TEI gtp_tei) := { {
+ {
+ id := id_RAB_SetupOrModifyItem,
+ firstCriticality := reject,
+ firstValue := {
+ rAB_SetupOrModifyItemFirst := {
+ rAB_ID := rab_id,
+ nAS_SynchronisationIndicator := omit,
+ rAB_Parameters := ts_RabParams,
+ userPlaneInformation := ts_UserPlaneInfo,
+ transportLayerInformation := ts_TLI_ps(tla, gtp_tei),
+ service_Handover := omit,
+ iE_Extensions := omit
+ }
+ },
+ secondCriticality := ignore,
+ secondValue := {
+ rAB_SetupOrModifyItemSecond := {
+ pDP_TypeInformation := omit,
+ dataVolumeReportingIndication := omit,
+ dl_GTP_PDU_SequenceNumber := omit,
+ ul_GTP_PDU_SequenceNumber := omit,
+ dl_N_PDU_SequenceNumber := omit,
+ ul_N_PDU_SequenceNumber := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+template RAB_SetupOrModifyList tr_RAB_SML_ps(template (present) RAB_ID rab_id,
+ template TransportLayerAddress tla,
+ template (value) GTP_TEI gtp_tei) := { {
+ {
+ id := id_RAB_SetupOrModifyItem,
+ firstCriticality := reject,
+ firstValue := {
+ rAB_SetupOrModifyItemFirst := {
+ rAB_ID := rab_id,
+ nAS_SynchronisationIndicator := *,
+ rAB_Parameters := ts_RabParams,
+ userPlaneInformation := ts_UserPlaneInfo,
+ transportLayerInformation := tr_TLI_ps(tla, gtp_tei),
+ service_Handover := *,
+ iE_Extensions := *
+ }
+ },
+ secondCriticality := ignore,
+ secondValue := {
+ rAB_SetupOrModifyItemSecond := {
+ pDP_TypeInformation := omit,
+ dataVolumeReportingIndication := omit,
+ dl_GTP_PDU_SequenceNumber := omit,
+ ul_GTP_PDU_SequenceNumber := omit,
+ dl_N_PDU_SequenceNumber := omit,
+ ul_N_PDU_SequenceNumber := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template (value) RAB_SetupOrModifiedList ts_RAB_SMdL(template (value) RAB_ID rab_id,
+ template (value) TransportLayerAddress tla,
+ template (value) BindingID binding_id) := { {
+ {
+ id := id_RAB_SetupOrModifiedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedItem := {
+ rAB_ID := rab_id,
+ transportLayerAddress := tla,
+ iuTransportAssociation := {
+ bindingID := binding_id
+ },
+ dl_dataVolumes := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template (value) RAB_SetupOrModifiedList ts_RAB_SMdL_no_tla(template (value) RAB_ID rab_id) := { {
+ {
+ id := id_RAB_SetupOrModifiedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedItem := {
+ rAB_ID := rab_id,
+ transportLayerAddress := omit,
+ iuTransportAssociation := omit,
+ dl_dataVolumes := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template (value) RAB_SetupOrModifiedList ts_RAB_SMdL_ps(template (value) RAB_ID rab_id,
+ template (value) TransportLayerAddress tla,
+ template (value) GTP_TEI gtp_tei) := { {
+ {
+ id := id_RAB_SetupOrModifiedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedItem := {
+ rAB_ID := rab_id,
+ transportLayerAddress := tla,
+ iuTransportAssociation := {
+ gTP_TEI := gtp_tei
+ },
+ dl_dataVolumes := omit,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template RAB_SetupOrModifiedList tr_RAB_SMdL(template (present) RAB_ID rab_id,
+ template TransportLayerAddress tla,
+ template BindingID binding_id) := { {
+ {
+ id := id_RAB_SetupOrModifiedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedItem := {
+ rAB_ID := rab_id,
+ transportLayerAddress := tla,
+ iuTransportAssociation := {
+ bindingID := binding_id
+ },
+ dl_dataVolumes := *,
+ iE_Extensions := *
+ }
+ }
+ }
+} }
+
+template (value) RAB_FailedList ts_RAB_FL(template (value) RAB_ID rab_id,
+ template (value) Cause cause) := { {
+ {
+ id := id_RAB_FailedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_FailedItem := {
+ rAB_ID := rab_id,
+ cause := cause,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template RAB_FailedList tr_RAB_FL(template RAB_ID rab_id,
+ template Cause cause) := { {
+ {
+ id := id_RAB_FailedItem,
+ criticality := ignore,
+ value_ := {
+ rAB_FailedItem := {
+ rAB_ID := rab_id,
+ cause := cause,
+ iE_Extensions := *
+ }
+ }
+ }
+} }
+
+template (value) RAB_ReleaseList ts_RAB_RL(template (value) RAB_ID rab_id,
+ template (value) Cause cause) := { {
+ {
+ id := id_RAB_ReleaseItem,
+ criticality := ignore,
+ value_ := {
+ rAB_ReleaseItem := {
+ rAB_ID := rab_id,
+ cause := cause,
+ iE_Extensions := omit
+ }
+ }
+ }
+} }
+
+template RAB_ReleaseList tr_RAB_RL(template (present) RAB_ID rab_id,
+ template Cause cause := ?) := { {
+ {
+ id := id_RAB_ReleaseItem,
+ criticality := ignore,
+ value_ := {
+ rAB_ReleaseItem := {
+ rAB_ID := rab_id,
+ cause := cause,
+ iE_Extensions := *
+ }
+ }
+ }
+} }
+
+
+function
+ts_RANAP_RabAssReq(template (omit) RAB_SetupOrModifyList rab_sml := omit,
+ template (omit) RAB_ReleaseList rab_rl := omit,
+ template (omit) RAB_AssignmentRequest.protocolExtensions exts := omit) return template RANAP_PDU {
+ var template RANAP_PDU ret;
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs := {};
+ var integer ie_pos := 0;
+
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs_rab_sml;
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs_rab_rl;
+
+ /* RAB-SetupOrModifyList */
+ if (istemplatekind(rab_sml, "value")) {
+ protocolIEs_rab_sml := {
+ {
+ id := id_RAB_SetupOrModifyList,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifyList := rab_sml
+ }
+ }
+ };
+ protocolIEs[ie_pos] := protocolIEs_rab_sml[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* RAB-ReleaseList */
+ if (istemplatekind(rab_rl, "value")) {
+ protocolIEs_rab_rl := {
+ {
+ id := id_RAB_ReleaseList,
+ criticality := ignore,
+ value_ := {
+ rAB_ReleaseList := rab_rl
+ }
+ }
+ };
+ protocolIEs[ie_pos] := protocolIEs_rab_rl[0];
+ ie_pos := ie_pos + 1;
+ }
+
+
+ ret.initiatingMessage := {
procedureCode := id_RAB_Assignment,
criticality := reject,
value_ := {
rAB_AssignmentRequest := {
- protocolIEs := {
- {
- id := id_RAB_SetupOrModifyList,
- criticality := reject,
- value_ := {
- rAB_SetupOrModifyList := rab_sml
- }
- }
- },
+ protocolIEs := protocolIEs,
protocolExtensions := exts
}
}
}
+
+ return ret;
}
-template RANAP_PDU
-tr_RANAP_RabAssReq(template RAB_SetupOrModifyList rab_sml,
- template RAB_AssignmentRequest.protocolExtensions exts := *) := {
- initiatingMessage := {
+
+function
+tr_RANAP_RabAssReq(template RAB_SetupOrModifyList rab_sml := omit,
+ template RAB_ReleaseList rab_rl := omit,
+ template RAB_AssignmentRequest.protocolExtensions exts := *) return template RANAP_PDU {
+ var template RANAP_PDU ret;
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs := {};
+ var integer ie_pos := 0;
+
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs_rab_sml;
+ var template RAB_AssignmentRequest.protocolIEs protocolIEs_rab_rl;
+
+ /* RAB-SetupOrModifyList */
+ if (not istemplatekind(rab_sml, "omit")) {
+ protocolIEs_rab_sml := {
+ {
+ id := id_RAB_SetupOrModifyList,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifyList := rab_sml
+ }
+ }
+ };
+ protocolIEs[ie_pos] := protocolIEs_rab_sml[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* RAB-ReleaseList */
+ if (not istemplatekind(rab_rl, "omit")) {
+ protocolIEs_rab_rl := {
+ {
+ id := id_RAB_ReleaseList,
+ criticality := ignore,
+ value_ := {
+ rAB_ReleaseList := rab_rl
+ }
+ }
+ };
+ protocolIEs[ie_pos] := protocolIEs_rab_rl[0];
+ ie_pos := ie_pos + 1;
+ }
+
+
+ ret.initiatingMessage := {
procedureCode := id_RAB_Assignment,
criticality := reject,
value_ := {
rAB_AssignmentRequest := {
- protocolIEs := {
- {
- id := id_RAB_SetupOrModifyList,
- criticality := ignore,
- value_ := {
- rAB_SetupOrModifyList := rab_sml
- }
- }
- },
+ protocolIEs := protocolIEs,
protocolExtensions := exts
}
}
}
+
+ return ret;
}
+function
+ts_RANAP_RabAssResp(template (omit) RAB_SetupOrModifiedList rab_sml := omit,
+ template (omit) RAB_FailedList rab_fl := omit,
+ template (omit) RAB_AssignmentResponse.protocolExtensions exts := omit) return template RANAP_PDU {
+ var template RANAP_PDU ret;
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs := {};
+ var integer ie_pos := 0;
-template (value) RANAP_PDU
-ts_RANAP_RabAssResp(template (value) RAB_SetupOrModifiedList rab_sml,
- template (omit) RAB_AssignmentResponse.protocolExtensions exts := omit) := {
- outcome := {
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs_rab_sml;
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs_rab_fl;
+
+ /* RAB-SetupOrModifiedList */
+ if (istemplatekind(rab_sml, "value")) {
+ protocolIEs_rab_sml := {
+ {
+ id := id_RAB_SetupOrModifiedList,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedList := rab_sml
+ }
+ }
+ }
+
+ protocolIEs[ie_pos] := protocolIEs_rab_sml[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* TODO: RAB-ReleasedList */
+ /* TODO: RAB-QueuedList */
+
+ /* RAB-FailedList */
+ if (istemplatekind(rab_fl, "value")) {
+ protocolIEs_rab_fl := {
+ {
+ id := id_RAB_FailedList,
+ criticality := ignore,
+ value_ := {
+ rAB_FailedList := rab_fl
+ }
+ }
+ }
+
+ protocolIEs[ie_pos] := protocolIEs_rab_fl[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* TODO: RAB-ReleaseFailedList */
+
+ ret.outcome := {
procedureCode := id_RAB_Assignment,
criticality := reject,
value_ := {
rAB_AssignmentResponse := {
- protocolIEs := {
- {
- id := id_RAB_SetupOrModifiedList,
- criticality := ignore,
- value_ := {
- rAB_SetupOrModifiedList := rab_sml
- }
- }
- /* RAB-ReleasedList */
- /* RAB-QueuedList */
- /* RAB-FailedList */
- /* RAB-ReleaseFailedList */
- },
+ protocolIEs := protocolIEs,
protocolExtensions := exts
}
}
}
+
+ return ret;
}
-template RANAP_PDU
-tr_RANAP_RabAssResp(template RAB_SetupOrModifiedList rab_sml,
- template RAB_AssignmentResponse.protocolExtensions exts := *) := {
- outcome := {
+
+function
+tr_RANAP_RabAssResp(template RAB_SetupOrModifiedList rab_sml := omit,
+ template RAB_FailedList rab_fl := omit,
+ template RAB_AssignmentResponse.protocolExtensions exts := *) return template RANAP_PDU {
+ var template RANAP_PDU ret;
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs := {};
+ var integer ie_pos := 0;
+
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs_rab_sml;
+ var template RAB_AssignmentResponse.protocolIEs protocolIEs_rab_fl;
+
+ /* RAB-SetupOrModifiedList */
+ if (not istemplatekind(rab_sml, "omit")) {
+ protocolIEs_rab_sml := {
+ {
+ id := id_RAB_SetupOrModifiedList,
+ criticality := ignore,
+ value_ := {
+ rAB_SetupOrModifiedList := rab_sml
+ }
+ }
+ }
+
+ protocolIEs[ie_pos] := protocolIEs_rab_sml[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* TODO: RAB-ReleasedList */
+ /* TODO: RAB-QueuedList */
+
+ /* RAB-FailedList */
+ if (not istemplatekind(rab_fl, "omit")) {
+ protocolIEs_rab_fl := {
+ {
+ id := id_RAB_FailedList,
+ criticality := ignore,
+ value_ := {
+ rAB_FailedList := rab_fl
+ }
+ }
+ }
+
+ protocolIEs[ie_pos] := protocolIEs_rab_fl[0];
+ ie_pos := ie_pos + 1;
+ }
+
+ /* TODO: RAB-ReleaseFailedList */
+
+ protocolIEs[ie_pos] := *;
+
+ ret.outcome := {
procedureCode := id_RAB_Assignment,
criticality := reject,
value_ := {
rAB_AssignmentResponse := {
- protocolIEs := {
- {
- id := id_RAB_SetupOrModifiedList,
- criticality := ignore,
- value_ := {
- rAB_SetupOrModifiedList := rab_sml
- }
- }, *
- /* RAB-ReleasedList */
- /* RAB-QueuedList */
- /* RAB-FailedList */
- /* RAB-ReleaseFailedList */
- },
+ protocolIEs := protocolIEs,
protocolExtensions := exts
}
}
}
-}
+ return ret;
+}
/*****************************************************************************************************
*
diff --git a/library/regen-DIAMETER_Types_ttcn.sh b/library/regen-DIAMETER_Types_ttcn.sh
new file mode 100755
index 00000000..e64cc88a
--- /dev/null
+++ b/library/regen-DIAMETER_Types_ttcn.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+
+SELF_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" # dirname of this script (library/)
+AVP_SH_DIR="$SELF_DIR/../deps/titan.ProtocolModules.DIAMETER_ProtocolModule_Generator/src"
+AVP_SH_PATH="$AVP_SH_DIR/AVP.sh"
+cd $AVP_SH_DIR
+$AVP_SH_PATH \
+ Base_IETF_RFC3588.ddf \
+ BaseTypes_IETF_RFC3588.ddf \
+ MobileIPv4_Application_IETF_RFC4004.ddf \
+ NetworkAccessServer_IETF_RFC4005.ddf \
+ CreditControl_IETF_RFC4006.ddf \
+ MobileIPv6_NAS_IETF_RFC5447.ddf \
+ MobileIPv6_HA_IETF_RFC5778.ddf \
+ AAAInterface_3GPP_TS29272_f10.ddf \
+ GxInterface_PCC_3GPP_TS29212_f10.ddf \
+ S6Interfaces_3GPP_TS29336_f00.ddf \
+ RxInterface_PCC_3GPP_TS29214_f20.ddf \
+ CxDxInterface_3GPP_TS29229_c30.ddf \
+ GiSGiInterface_3GPP_TS29061_d70.ddf \
+ ChargingApplications_3GPP_TS32299_d90.ddf \
+ AAAInterface_3GPP_TS29273_f00.ddf
+
+mv -v $AVP_SH_DIR/DIAMETER_Types.ttcn $SELF_DIR/
diff --git a/library/rua/RUA_Emulation.ttcn b/library/rua/RUA_Emulation.ttcn
new file mode 100644
index 00000000..a9c445e0
--- /dev/null
+++ b/library/rua/RUA_Emulation.ttcn
@@ -0,0 +1,404 @@
+module RUA_Emulation {
+
+/* RUA_Emulation runs on top of Iuh_Emulation. It multiplexes/demultiplexes
+ * the individuao connections, so there can be separate TTCN-3 components
+ * handling each of the connections (one connection per UE).
+ *
+ * The RUA_Emulation.main() function processes RUA messages from the Iuh stack
+ * via the RUA_PT, and dispatches them to the per-connection components.
+ *
+ * Outbound RUA connections are initiated by sending a FIXME primitive to the
+ * RUA_Emulation component.
+ *
+ * For each new inbound connection, the RuaOps.create_cb() is called. It can create
+ * or resolve a TTCN-3 component, and returns a component reference to which that inbound
+ * connection is routed/dispatched.
+ *
+ * If a pre-existing component wants to register to handle future inbound connection,
+ * it can do so by registering an "expect" with the expected RANAP payload.
+
+ * (C) 2022 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from Iuh_Emulation all;
+
+import from RUA_Templates all;
+//import from RUA_Constants all;
+import from RUA_PDU_Descriptions all;
+import from RUA_IEs all;
+
+import from RANAP_PDU_Descriptions all;
+//import from RANAP_Constants all;
+import from RANAP_IEs all;
+import from RANAP_Types all;
+import from RANAP_Templates all;
+
+modulepar {
+ integer mp_max_context_id := hex2int('FFFFFF'H);
+}
+
+
+/* General "base class" component definition, of which specific implementations
+ * derive themselves by means of the "extends" feature */
+type component RUA_ConnHdlr {
+ port RUA_Conn_PT RUA;
+}
+
+/* port between individual per-connection components and this dispatcher */
+type port RUA_Conn_PT message {
+ inout RANAP_PDU,
+ RUA_Conn_Req,
+ RUA_Disc_Req,
+ RUA_Disc_Ind;
+} with { extension "internal" };
+
+type record RUA_Conn_Req {
+ boolean ps_domain,
+ RANAP_PDU ranap
+};
+
+type record RUA_Disc_Req {
+ RANAP_PDU ranap,
+ RUA_IEs.Cause cause
+};
+
+type record RUA_Disc_Ind {
+ RUA_IEs.Cause cause
+};
+
+type bitstring ContextId length(24); // with { variant "FIELDLENGTH(24)" };
+
+/* represents a single RANAP connection over RUA */
+type record ConnectionData {
+ RUA_ConnHdlr comp_ref,
+ RUA_IEs.CN_DomainIndicator domain,
+ integer context_id
+}
+
+type component RUA_Emulation_CT {
+ /* port to the bottom side (Iuh) */
+ port RUA_PT RUA;
+
+ /* ports to the upper side (per-connection components) */
+ port RUA_Conn_PT CLIENT;
+
+ /* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
+ var ConnectionData ConnectionTable[16];
+
+ /* pending expected incoming connections */
+ //var ExpectData ExpectTable[8];
+
+ /* tables for mapping inbound unitdata (like paging) */
+ //var ImsiMapping ImsiTable[16];
+
+ /* procedure based port to register for incoming connections */
+ //port RUA_PROC_PT PROC;
+
+ var charstring g_rua_id;
+ var RuaOps g_rua_ops;
+}
+
+type function RanapCreateCallback(ContextId context_id, RUA_IEs.CN_DomainIndicator domain, charstring id)
+runs on RUA_Emulation_CT return RUA_ConnHdlr;
+
+type function RanapUnitdataCallback(RANAP_PDU ranap)
+runs on RUA_Emulation_CT return template RANAP_PDU;
+
+type record RuaOps {
+ RanapCreateCallback create_cb optional,
+ RanapUnitdataCallback unitdata_cb optional
+ //boolean deode_dtap
+ //boolean role_ms
+};
+
+private function f_context_id_known(ContextId context_id)
+runs on RUA_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].context_id == bit2int(context_id)){
+ return true;
+ }
+ }
+ return false;
+}
+
+private function f_comp_known(RUA_ConnHdlr client)
+runs on RUA_Emulation_CT return boolean {
+ var integer i;
+ for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* resolve connection ID by component reference */
+private function f_context_id_by_comp(RUA_ConnHdlr client)
+runs on RUA_Emulation_CT return ContextId {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return int2bit(ConnectionTable[i].context_id, 24);
+ }
+ }
+ setverdict(fail, "RAN Connection table not found by component ", client);
+ mtc.stop;
+}
+
+/* resolve ConnectionTable index component reference */
+private function f_idx_by_comp(RUA_ConnHdlr client)
+runs on RUA_Emulation_CT return integer {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].comp_ref == client) {
+ return i;
+ }
+ }
+ setverdict(fail, "RAN Connection table not found by component ", client);
+ mtc.stop;
+}
+
+private function f_gen_context_id()
+runs on RUA_Emulation_CT return ContextId {
+ var ContextId context_id;
+
+ do {
+ context_id := int2bit(float2int(rnd()*int2float(mp_max_context_id)), 24);
+ } while (f_context_id_known(context_id) == true);
+
+ return context_id;
+}
+
+private function f_conn_table_init()
+runs on RUA_Emulation_CT {
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ ConnectionTable[i].comp_ref := null;
+ ConnectionTable[i].context_id := -1;
+ }
+/*
+ for (var integer i := 0; i < sizeof(ImsiTable); i := i+1) {
+ ImsiTable[i].comp_ref := null;
+ ImsiTable[i].imsi := omit;
+ ImsiTable[i].tmsi := 'FFFFFFFF'O;
+ }
+*/
+}
+
+private function f_conn_table_add(RUA_ConnHdlr comp_ref, RUA_IEs.CN_DomainIndicator domain, ContextId context_id)
+runs on RUA_Emulation_CT {
+ var integer int_context_id := bit2int(context_id);
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].context_id == -1) {
+ ConnectionTable[i].comp_ref := comp_ref;
+ ConnectionTable[i].domain := domain;
+ ConnectionTable[i].context_id := int_context_id;
+ log("Added conn table entry ", i, comp_ref, int_context_id);
+ return;
+ }
+ }
+ testcase.stop("RUA Connection table full!");
+}
+
+private function f_conn_table_del(ContextId context_id)
+runs on RUA_Emulation_CT {
+ var integer int_context_id := bit2int(context_id);
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].context_id == int_context_id) {
+ log("Deleted conn table entry ", i,
+ ConnectionTable[i].comp_ref, int_context_id);
+ ConnectionTable[i].context_id := -1;
+ return
+ }
+ }
+ setverdict(fail, "RUA Connection table attempt to delete non-existant ", int_context_id);
+ mtc.stop;
+}
+
+
+/* resolve component reference by connection ID */
+private function f_comp_by_context_id(ContextId context_id)
+runs on RUA_Emulation_CT return RUA_ConnHdlr {
+ var integer int_context_id := bit2int(context_id);
+ for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
+ if (ConnectionTable[i].context_id == int_context_id) {
+ return ConnectionTable[i].comp_ref;
+ }
+ }
+ setverdict(fail, "RUA Connection table not found by RUA Context ID ", int_context_id);
+ mtc.stop;
+}
+
+private function CommonRanapUnitdataCallback(RANAP_PDU ranap)
+runs on RUA_Emulation_CT return template RANAP_PDU {
+ /* TODO: paging */
+ return g_rua_ops.unitdata_cb.apply(ranap);
+}
+
+private function f_handle_userData_RANAP(RUA_ConnHdlr client, RANAP_PDU ranap)
+runs on RUA_Emulation_CT {
+ /* TODO: L3 decoding, if requested */
+ CLIENT.send(ranap) to client;
+}
+
+
+private altstep as_reset_ack() runs on RUA_Emulation_CT {
+ var RUA_PDU rua_clt;
+ [] RUA.receive(tr_RUA_ConnectionlessTransfer(decmatch tr_RANAP_Reset)) -> value rua_clt {
+ var RANAP_PDU rx := dec_RANAP_PDU(rua_clt.initiatingMessage.value_.connectionlessTransfer.protocolIEs[0].value_.rANAP_Message);
+ var RANAP_IEs.CN_DomainIndicator dom;
+ dom := rx.initiatingMessage.value_.Reset.protocolIEs[1].value_.cN_DomainIndicator;
+ RUA.send(ts_RUA_ConnectionlessTransfer(enc_RANAP_PDU(valueof(ts_RANAP_ResetAck(dom)))));
+ }
+}
+
+private altstep as_main_rua() runs on RUA_Emulation_CT {
+ var RANAP_PDU ranap;
+ var RUA_PDU rua;
+ var octetstring ranap_enc;
+ var ContextId context_id;
+ var RUA_IEs.CN_DomainIndicator domain_ind;
+ var RUA_ConnHdlr vc_conn;
+ var RUA_Conn_Req creq;
+ var RUA_Disc_Req dreq;
+ var RUA_IEs.Cause cause;
+
+ /* RUA -> Client: UNIT-DATA (connectionless RUA) from CN */
+ [] RUA.receive(tr_RUA_ConnectionlessTransfer) -> value rua {
+ ranap := dec_RANAP_PDU(rua.initiatingMessage.value_.connectionlessTransfer.protocolIEs[0].value_.rANAP_Message);
+ var template RANAP_PDU resp;
+ resp := CommonRanapUnitdataCallback(ranap);
+ if (isvalue(resp)) {
+ RUA.send(ts_RUA_ConnectionlessTransfer(enc_RANAP_PDU(valueof(resp))));
+ }
+ }
+
+ /* RUA -> Client: new connection from CN */
+ [] RUA.receive(tr_RUA_Connect) -> value rua {
+ domain_ind := rua.initiatingMessage.value_.connect_.protocolIEs[0].value_.cN_DomainIndicator;
+ context_id := rua.initiatingMessage.value_.connect_.protocolIEs[1].value_.context_ID;
+ ranap_enc := rua.initiatingMessage.value_.connect_.protocolIEs[3].value_.rANAP_Message;
+ ranap := dec_RANAP_PDU(ranap_enc);
+ vc_conn := g_rua_ops.create_cb.apply(context_id, domain_ind, g_rua_id);
+ /* store mapping between client components and RUA contextId */
+ f_conn_table_add(vc_conn, domain_ind, context_id);
+ /* TODO: notify user about incoming connection? */
+ /* handle user payload */
+ f_handle_userData_RANAP(vc_conn, ranap);
+ }
+
+ /* RUA -> Client: connection-oriented data in existing connection */
+ [] RUA.receive(tr_RUA_DirectTransfer) -> value rua {
+ context_id := rua.initiatingMessage.value_.directTransfer.protocolIEs[1].value_.context_ID;
+ vc_conn := f_comp_by_context_id(context_id);
+ ranap_enc := rua.initiatingMessage.value_.directTransfer.protocolIEs[2].value_.rANAP_Message;
+ f_handle_userData_RANAP(vc_conn, dec_RANAP_PDU(ranap_enc));
+ }
+
+ /* RUA -> Client: disconnect of an existing connection */
+ [] RUA.receive(tr_RUA_Disconnect_opt_ranap) -> value rua {
+ cause := rua.initiatingMessage.value_.disconnect_.protocolIEs[2].value_.cause;
+ context_id := rua.initiatingMessage.value_.disconnect_.protocolIEs[1].value_.context_ID;
+ vc_conn := f_comp_by_context_id(context_id);
+ /* send contained RANAP message to user */
+ if (lengthof(rua.initiatingMessage.value_.disconnect_.protocolIEs) > 3) {
+ ranap_enc := rua.initiatingMessage.value_.disconnect_.protocolIEs[3].value_.rANAP_Message;
+ f_handle_userData_RANAP(vc_conn, dec_RANAP_PDU(ranap_enc));
+ }
+ /* notify user of disconnect */
+ if (CLIENT.checkstate("Connected")) {
+ CLIENT.send(RUA_Disc_Ind:{cause});
+ }
+ f_conn_table_del(context_id);
+ }
+
+ /* RANAP from client through an existing RANAP connection */
+ [] CLIENT.receive(RANAP_PDU:?) -> value ranap sender vc_conn {
+ var integer idx := f_idx_by_comp(vc_conn);
+ context_id := int2bit(ConnectionTable[idx].context_id, 24);
+ domain_ind := ConnectionTable[idx].domain;
+ RUA.send(ts_RUA_DirectTransfer(domain_ind, context_id, enc_RANAP_PDU(ranap)));
+ }
+
+ /* Disconnect request from client */
+ [] CLIENT.receive(RUA_Disc_Req:?) -> value dreq sender vc_conn {
+ var octetstring enc_ranap := enc_RANAP_PDU(dreq.ranap);
+ var integer idx := f_idx_by_comp(vc_conn);
+ context_id := int2bit(ConnectionTable[idx].context_id, 24);
+ domain_ind := ConnectionTable[idx].domain;
+ RUA.send(ts_RUA_Disconnect(domain_ind, context_id, dreq.cause, enc_ranap));
+ f_conn_table_del(context_id);
+ }
+
+ /* RANAP from client, for a new RANAP connection */
+ [] CLIENT.receive(RUA_Conn_Req:?) -> value creq sender vc_conn {
+ var octetstring enc_ranap := enc_RANAP_PDU(creq.ranap);
+
+ if (f_comp_known(vc_conn) == false) {
+ /* unknown client, create new connection */
+ context_id := f_gen_context_id();
+ if (creq.ps_domain) {
+ domain_ind := ps_domain;
+ } else {
+ domain_ind := cs_domain;
+ }
+
+ f_conn_table_add(vc_conn, domain_ind, context_id);
+ RUA.send(ts_RUA_Connect(domain_ind, context_id, normal_call, enc_ranap));
+ } else {
+ /* known client, send via existing component */
+ context_id := f_context_id_by_comp(vc_conn);
+ RUA.send(ts_RUA_DirectTransfer(domain_ind, context_id, enc_ranap));
+ }
+ }
+
+}
+
+
+
+function f_ranap_reset(RANAP_IEs.CN_DomainIndicator dom) runs on RUA_Emulation_CT {
+ timer T := 5.0;
+
+ var RANAP_PDU tx := valueof(ts_RANAP_Reset(ts_RanapCause_om_intervention,dom));
+ RUA.send(ts_RUA_ConnectionlessTransfer(enc_RANAP_PDU(tx)));
+ T.start;
+ alt {
+ [] RUA.receive(tr_RUA_ConnectionlessTransfer(decmatch tr_RANAP_ResetAck)) {
+ log("RUA-RANAP: Received RESET-ACK in response to RESET, we're reay to go!");
+ }
+ [] as_reset_ack();
+ [] RUA.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "RUA-RANAP: Timeout waiting for RESET-ACK after sending RESET");
+ mtc.stop;
+ }
+ }
+}
+
+function main(RuaOps ops, charstring id) runs on RUA_Emulation_CT {
+ g_rua_id := id;
+ g_rua_ops := ops;
+ f_conn_table_init();
+ //f_expect_table_init();
+
+ while (true) {
+ alt {
+ [] as_main_rua();
+
+ /*
+ [] PROC.getcall(RUA_Register:{?,?}) -> param(l3_info, vc_hdlr) {
+ f_create_expect(l3_info, vc_hdlr);
+ PROC.reply(RUA_register:{l3_info, vc_hdlr}) to vc_hdlr;
+ }
+ */
+ }
+ }
+}
+
+
+}
diff --git a/library/rua/RUA_Templates.ttcn b/library/rua/RUA_Templates.ttcn
new file mode 100644
index 00000000..738042ea
--- /dev/null
+++ b/library/rua/RUA_Templates.ttcn
@@ -0,0 +1,306 @@
+/* RUA Templates in TTCN-3
+ * (C) 2021 Pau Espin Pedrol <pespin@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 RUA_Templates {
+
+import from RUA_IEs all;
+import from RUA_CommonDataTypes all;
+import from RUA_Constants all;
+import from RUA_Containers all;
+import from RUA_PDU_Contents all;
+import from RUA_PDU_Descriptions all;
+
+/*********************************************************************************
+ * 3GPP TS 25.468
+ *********************************************************************************/
+
+template (value) Cause ts_RUA_Cause(template (value) CauseRadioNetwork c) := {
+ radioNetwork := c
+}
+
+/* 9.1.3 CONNECT */
+template (value) RUA_PDU
+ts_RUA_Connect(template (value) CN_DomainIndicator domain,
+ template (value) bitstring context_id,
+ template (value) Establishment_Cause est_cause,
+ template (value) octetstring ranap_msg) := {
+ initiatingMessage := {
+ procedureCode := id_Connect,
+ criticality := reject,
+ value_ := {
+ connect_ := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 6,
+ criticality := reject,
+ value_ := { establishment_Cause := est_cause }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := {
+ rANAP_Message := ranap_msg
+ }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (present) RUA_PDU
+tr_RUA_Connect(template (present) CN_DomainIndicator domain := ?,
+ template (present) bitstring context_id := ?,
+ template (present) Establishment_Cause est_cause := ?,
+ template (present) octetstring ranap_msg := ?) := {
+ initiatingMessage := {
+ procedureCode := id_Connect,
+ criticality := reject,
+ value_ := {
+ connect_ := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 6,
+ criticality := reject,
+ value_ := { establishment_Cause := est_cause }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := {
+ rANAP_Message := ranap_msg
+ }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 9.1.4 DIRECT TRANSFER */
+template (value) RUA_PDU
+ts_RUA_DirectTransfer(template (value) CN_DomainIndicator domain,
+ template (value) bitstring context_id,
+ template (value) octetstring ranap_msg) := {
+ initiatingMessage := {
+ procedureCode := id_DirectTransfer,
+ criticality := reject,
+ value_ := {
+ directTransfer := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+template (present) RUA_PDU
+tr_RUA_DirectTransfer(template (present) CN_DomainIndicator domain := ?,
+ template (present) bitstring context_id := ?,
+ template (present) octetstring ranap_msg := ?) := {
+ initiatingMessage := {
+ procedureCode := id_DirectTransfer,
+ criticality := reject,
+ value_ := {
+ directTransfer := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 9.1.5 DISCONNECT */
+template (value) RUA_PDU
+ts_RUA_Disconnect(template (value) CN_DomainIndicator domain,
+ template (value) bitstring context_id,
+ template (value) Cause cause,
+ template (value) octetstring ranap_msg) := {
+ initiatingMessage := {
+ procedureCode := 3,
+ criticality := reject,
+ value_ := {
+ disconnect_ := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 1,
+ criticality := reject,
+ value_ := { cause := cause }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (present) RUA_PDU
+tr_RUA_Disconnect(template (present) CN_DomainIndicator domain := ?,
+ template (present) bitstring context_id := ?,
+ template (present) Cause cause := ?,
+ template (present) octetstring ranap_msg := ?) := {
+ initiatingMessage := {
+ procedureCode := 3,
+ criticality := reject,
+ value_ := {
+ disconnect_ := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 1,
+ criticality := reject,
+ value_ := { cause := cause }
+ }, {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* Same as tr_RUA_Disconnect() but without a ranap arg: match also a RUA Disconnect without any RANAP payload. */
+template (present) RUA_PDU
+tr_RUA_Disconnect_opt_ranap(template (present) CN_DomainIndicator domain := ?,
+ template (present) bitstring context_id := ?,
+ template (present) Cause cause := ?) := {
+ initiatingMessage := {
+ procedureCode := 3,
+ criticality := reject,
+ value_ := {
+ disconnect_ := {
+ protocolIEs := {
+ {
+ id := 7,
+ criticality := reject,
+ value_ := { cN_DomainIndicator := domain }
+ }, {
+ id := 3,
+ criticality := reject,
+ value_ := { context_ID := context_id }
+ }, {
+ id := 1,
+ criticality := reject,
+ value_ := { cause := cause }
+ },
+ *
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 9.1.6 CONNECTIONLESS TRANSFER */
+template (value) RUA_PDU
+ts_RUA_ConnectionlessTransfer(template (value) octetstring ranap_msg) := {
+ initiatingMessage := {
+ procedureCode := id_ConnectionlessTransfer,
+ criticality := reject,
+ value_ := {
+ connectionlessTransfer := {
+ protocolIEs := {
+ {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (present) RUA_PDU
+tr_RUA_ConnectionlessTransfer(template (present) octetstring ranap_msg := ?) := {
+ initiatingMessage := {
+ procedureCode := id_ConnectionlessTransfer,
+ criticality := reject,
+ value_ := {
+ connectionlessTransfer := {
+ protocolIEs := {
+ {
+ id := 4,
+ criticality := reject,
+ value_ := { rANAP_Message := ranap_msg }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+};
diff --git a/library/s1ap/S1AP_Templates.ttcn b/library/s1ap/S1AP_Templates.ttcn
index 6c5dbce6..26e1ae1c 100644
--- a/library/s1ap/S1AP_Templates.ttcn
+++ b/library/s1ap/S1AP_Templates.ttcn
@@ -22,7 +22,7 @@ import from S1AP_PDU_Descriptions all;
*********************************************************************************/
/*********************************************************************************
- * 9.1.8 Management Messages
+ * 9.1.8 Management Messages
*********************************************************************************/
/* 9.1.8.4 S1 SETUP REQUEST */
@@ -69,7 +69,7 @@ tr_S1AP_SetupReq(template (present) Global_ENB_ID p_global_ENB_ID := ?,
id := S1AP_Constants.id_Global_ENB_ID,
criticality := ignore,
value_ := { Global_ENB_ID := p_global_ENB_ID }
- }, {
+ }, *, {
id := S1AP_Constants.id_SupportedTAs,
criticality := reject,
value_ := {SupportedTAs := p_supportedTAs}
@@ -113,7 +113,7 @@ tr_S1AP_SetupResp(template (present) ServedGUMMEIs served_gummeis := ?,
value_ := {
S1SetupResponse := {
protocolIEs := {
- {
+ *, {
id := S1AP_Constants.id_ServedGUMMEIs,
criticality := reject,
value_ := { ServedGUMMEIs := served_gummeis }
@@ -203,7 +203,7 @@ tr_S1AP_Reset(template (present) Cause cause := ?,
id := S1AP_Constants.id_Cause,
criticality := ignore,
value_ := { Cause := cause }
- } , {
+ }, {
id := S1AP_Constants.id_ResetType,
criticality := reject,
value_ := { resetType := reset_type }
@@ -251,8 +251,18 @@ tr_S1AP_ResetAck(template (present) UE_associatedLogicalS1_ConnectionListResAck
}
}
}
-
-
+template (present) S1AP_PDU
+tr_S1AP_ResetAck_any := {
+ successfulOutcome := {
+ procedureCode := id_Reset,
+ criticality := reject,
+ value_ := {
+ ResetAcknowledge := {
+ protocolIEs := ?
+ }
+ }
+ }
+}
/*********************************************************************************
@@ -568,11 +578,30 @@ tr_S1AP_IntialCtxSetupReq(template (present) MME_UE_S1AP_ID mme_id := ?,
}
/* 9.1.4.3 INITIAL CONTEXT SETUP RESPONSE */
+template (value) E_RABSetupItemCtxtSURes
+ts_S1AP_RABSetupItemCtxtSURes(template (value) E_RAB_ID rab_id := 5,
+ template (value) TransportLayerAddress tla := '00001010000101110001100000000100'B,
+ template (value) GTP_TEID gtp_teid := '00000002'O) := {
+ e_RAB_ID := rab_id,
+ transportLayerAddress := tla,
+ gTP_TEID := gtp_teid,
+ iE_Extensions := omit
+}
+template (value) E_RABSetupListCtxtSURes
+ts_S1AP_RABSetupListCtxtSURes(template (value) E_RABSetupItemCtxtSURes it := ts_S1AP_RABSetupItemCtxtSURes()) := {
+ {
+ id := S1AP_Constants.id_E_RABSetupItemCtxtSURes,
+ criticality := ignore,
+ value_ := { E_RABSetupItemCtxtSURes := it }
+ }
+}
+
template (value) S1AP_PDU
ts_S1AP_InitialCtxSetupResp(template (value) MME_UE_S1AP_ID mme_id,
template (value) ENB_UE_S1AP_ID enb_id,
- template (value) E_RABSetupListCtxtSURes rab_setup_items,
- template (value) E_RABList rab_items) := {
+ template (value) E_RABSetupListCtxtSURes rab_setup_items
+ /*OPTIONAL: template (value) E_RABList rab_items */
+ ) := {
successfulOutcome := {
procedureCode := id_InitialContextSetup,
criticality := reject,
@@ -588,14 +617,15 @@ ts_S1AP_InitialCtxSetupResp(template (value) MME_UE_S1AP_ID mme_id,
criticality := reject,
value_ := {ENB_UE_S1AP_ID := enb_id}
}, {
- id := S1AP_Constants.id_E_RABSetupListBearerSURes,
+ id := S1AP_Constants.id_E_RABSetupListCtxtSURes,
criticality := ignore,
value_ := {E_RABSetupListCtxtSURes := rab_setup_items}
- }, {
+ }
+ /*, {
id := S1AP_Constants.id_E_RABFailedToSetupListBearerSURes,
criticality := ignore,
value_ := {E_RABList := rab_items}
- }
+ }*/
}
}
}
@@ -628,7 +658,7 @@ tr_S1AP_InitialCtxSetupResp(template (present) MME_UE_S1AP_ID mme_id := ?,
id := S1AP_Constants.id_E_RABFailedToSetupListBearerSURes,
criticality := ignore,
value_ := {E_RABList := rab_items}
- }
+ }, *
}
}
}
@@ -895,13 +925,50 @@ tr_S1AP_ConnEstInd(template (present) MME_UE_S1AP_ID mme_id := ?,
}
}
+/* 9.1.14 eNB DIRECT INFORMATION TRANSFER */
+template (value) S1AP_PDU
+ts_S1AP_eNBDirectInfTrans(template (value) Inter_SystemInformationTransferType inf) := {
+ initiatingMessage := {
+ procedureCode := id_eNBDirectInformationTransfer,
+ criticality := reject,
+ value_ := {
+ eNBDirectInformationTransfer := {
+ protocolIEs := {
+ {
+ id := S1AP_Constants.id_Inter_SystemInformationTransferTypeEDT,
+ criticality := ignore,
+ value_ := {Inter_SystemInformationTransferType := inf}
+ }
+ }
+ }
+ }
+ }
+}
+/* 9.1.15 MME DIRECT INFORMATION TRANSFER */
+template (present) S1AP_PDU
+tr_S1AP_MMEDirectInfTrans(template (present) Inter_SystemInformationTransferType inf := ?) := {
+ initiatingMessage := {
+ procedureCode := id_MMEDirectInformationTransfer,
+ criticality := ignore,
+ value_ := {
+ MMEDirectInformationTransfer := {
+ protocolIEs := {
+ {
+ id := S1AP_Constants.id_Inter_SystemInformationTransferTypeMDT,
+ criticality := reject,
+ value_ := {Inter_SystemInformationTransferType := inf}
+ }, *
+ }
+ }
+ }
+ }
+}
/* all non-UE-related S1AP messages */
template (present) S1AP_PDU
tr_S1AP_nonUErelated := (tr_S1AP_SetupReq, tr_S1AP_SetupResp, tr_S1AP_SetupFail,
- tr_S1AP_Reset, tr_S1AP_ResetAck
+ tr_S1AP_Reset, tr_S1AP_ResetAck, tr_S1AP_ResetAck_any, tr_S1AP_MMEDirectInfTrans
);
-
}
diff --git a/library/SABP_Adapter.ttcn b/library/sabp/SABP_Adapter.ttcn
index e94e91cb..046f597c 100644
--- a/library/SABP_Adapter.ttcn
+++ b/library/sabp/SABP_Adapter.ttcn
@@ -20,7 +20,7 @@ import from SABP_CodecPort all;
import from SABP_CodecPort_CtrlFunct all;
import from IPL4asp_Types all;
import from IPL4asp_PortType all;
-//import from Socket_API_Definitions all;
+import from Socket_API_Definitions all;
const integer SABP_HDR_LEN := 3;
@@ -72,7 +72,7 @@ private function f_aper_len_det(in octetstring stream, out integer len_len) retu
* If the callback function detects that the it will be impossible to determine the length of the message,
* even receiving more octets, should return "-2". In this case the connection will be closed and the
* length calculation error will be reported. */
-private function f_APER_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
+private function f_APER_getMsgLen(in octetstring stream, inout Socket_API_Definitions.ro_integer args) return integer {
var integer stream_len := lengthof(stream);
var integer hdr_len := args[0];
var octetstring stream_nohdr;
diff --git a/library/SABP_CodecPort.ttcn b/library/sabp/SABP_CodecPort.ttcn
index 65fb5420..65fb5420 100644
--- a/library/SABP_CodecPort.ttcn
+++ b/library/sabp/SABP_CodecPort.ttcn
diff --git a/library/SABP_CodecPort_CtrlFunct.ttcn b/library/sabp/SABP_CodecPort_CtrlFunct.ttcn
index 814c7017..814c7017 100644
--- a/library/SABP_CodecPort_CtrlFunct.ttcn
+++ b/library/sabp/SABP_CodecPort_CtrlFunct.ttcn
diff --git a/library/SABP_CodecPort_CtrlFunctDef.cc b/library/sabp/SABP_CodecPort_CtrlFunctDef.cc
index f146d6d2..f146d6d2 100644
--- a/library/SABP_CodecPort_CtrlFunctDef.cc
+++ b/library/sabp/SABP_CodecPort_CtrlFunctDef.cc
diff --git a/library/sabp/SABP_Selftest.ttcn b/library/sabp/SABP_Selftest.ttcn
new file mode 100644
index 00000000..1f6ecb51
--- /dev/null
+++ b/library/sabp/SABP_Selftest.ttcn
@@ -0,0 +1,180 @@
+module SABP_Selftest {
+
+/* This is testing the SABP code, specifically re-creating the SABP messages from within
+ * the TCP stream using SABP_Adapter.f_APER_getMsgLen() for the various possible APER
+ * length determinant cases */
+
+import from Osmocom_Types all;
+
+import from SABP_Adapter all;
+import from SABP_Templates all;
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+
+modulepar {
+ charstring mp_bind_ip := "127.0.0.1";
+ integer mp_bind_port := 12345;
+}
+
+type component test_CT extends SABP_Adapter_CT {
+ port IPL4asp_PT TCP;
+ var integer g_tcp_conn_id;
+ timer Tguard := 10.0;
+}
+
+template (value) ASP_Send ts_AS(integer conn_id, octetstring msg) := {
+ connId := conn_id,
+ proto := omit,
+ msg := msg
+}
+
+private altstep as_Tguard() runs on test_CT {
+ [] Tguard.timeout {
+ setverdict(fail, "Tguard timeout");
+ mtc.stop;
+ }
+}
+
+private function f_init() runs on test_CT {
+ var IPL4asp_Types.Result res;
+ var ASP_Event asp_evt;
+
+ activate(as_Tguard());
+ Tguard.start;
+
+ f_bind(mp_bind_ip, mp_bind_port, 0);
+
+ map(self:TCP, system:TCP);
+ res := f_IPL4_connect(TCP, mp_bind_ip, mp_bind_port, "", -1, 0, { tcp:={} });
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not connect to SABP TCP port");
+ mtc.stop;
+ }
+ g_tcp_conn_id := res.connId;
+
+ SABP[0].receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
+ g_sabp_conn_id[0] := asp_evt.connOpened.connId;
+ }
+}
+
+/* send a given input octetstring 'stream' in chunks of 'chunk_size', spaced at 'delay' intervals */
+private function tcp_send_segmented(octetstring stream, integer chunk_size := 1, float delay := 0.05)
+runs on test_CT {
+ var integer i;
+
+ for (i := 0; i < lengthof(stream); i := i+chunk_size) {
+ var integer size := chunk_size;
+ if (lengthof(stream) - i < chunk_size) {
+ size := lengthof(stream) - i;
+ }
+ TCP.send(ts_AS(g_tcp_conn_id, substr(stream, i, size)));
+ f_sleep(delay);
+ }
+}
+
+/* a simple SABP-RESTART message with single-byte length dteerminant (shorter than 128 byte) */
+const octetstring c_restart := '00044010000001000F0009000062F22400230042'O;
+
+/* test whether a message with 1-byte length determinant is parsed */
+testcase TC_1byte_len() runs on test_CT {
+ f_init();
+ TCP.send(ts_AS(g_tcp_conn_id, c_restart));
+ f_sabp_exp(tr_SABP_Restart(?));
+ setverdict(pass);
+}
+
+/* test whether a message with 1-byte length determinant is parsed if each byte is received separately */
+testcase TC_1byte_len_bytewise() runs on test_CT {
+ f_init();
+ tcp_send_segmented(c_restart, 1, 0.05);
+ f_sabp_exp(tr_SABP_Restart(?));
+ setverdict(pass);
+}
+
+/* send three concatenated RESTART in one segment */
+testcase TC_1byte_len_chained() runs on test_CT {
+ var octetstring chain := c_restart & c_restart & c_restart;
+ f_init();
+ TCP.send(ts_AS(g_tcp_conn_id, chain));
+ f_sabp_exp(tr_SABP_Restart(?));
+ f_sabp_exp(tr_SABP_Restart(?));
+ f_sabp_exp(tr_SABP_Restart(?));
+ setverdict(pass);
+}
+
+
+/* SABP write-replace with length determinant encoded over two bytes ('8093'O) */
+const octetstring c_wrepl := '00000080930000080006000211120007000240C0000F0010000113F0030282EC0613F0030282EC070001400100000D0002012A000900020000000400010100000056029F01B4D90D064297D9EC37E8FE96B3C9A0303BDD68341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D168341A8D46A3D10012'O;
+
+/* test whether a message with 2-byte length determinant is parsed */
+testcase TC_2byte_len() runs on test_CT {
+ f_init();
+ TCP.send(ts_AS(g_tcp_conn_id, c_wrepl));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ f_sabp_send(ts_SABP_Reset({ { pLMNidentity := '09F107'O, lac := '0000'O, sac := '0000'O } }));
+ setverdict(pass);
+}
+
+/* test whether a message with 2-byte length determinant is parsed if each byte is received separately */
+testcase TC_2byte_len_bytewise() runs on test_CT {
+ f_init();
+ tcp_send_segmented(c_wrepl, 1, 0.05);
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ setverdict(pass);
+}
+
+/* send three concatenated WRITE-REPLACE in one segment */
+testcase TC_2byte_len_chained() runs on test_CT {
+ var octetstring chain := c_wrepl & c_wrepl & c_wrepl;
+ f_init();
+ TCP.send(ts_AS(g_tcp_conn_id, chain));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ setverdict(pass);
+}
+
+/* send three concatenated WRITE-REPLACE in segments of 10 bytes */
+testcase TC_2byte_len_chained_bytewise() runs on test_CT {
+ var octetstring chain := c_wrepl & c_wrepl & c_wrepl;
+ f_init();
+ tcp_send_segmented(chain, 10, 0.05);
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ setverdict(pass);
+}
+
+/* SABP write-replace with length determinant encoded over multiple chunks ('Cx'O case) */
+const octetstring c_chunked := '000000C1000007000600020002000700020002000F00C109C462F2241000004262F2242000000062F2242000000162F2242000000262F2242000000362F2242000000462F2242000000562F2242000000662F2242000000762F2242000000862F2242000000962F2242000000A62F2242000000B62F2242000000C62F2242000000D62F2242000000E62F2242000000F62F2242000001062F2242000001162F2242000001262F2242000001362F2242000001462F2242000001562F2242000001662F2242000001762F2242000001862F2242000001962F2242000001A62F2242000001B62F2242000001C62F2242000001D62F2242000001E62F2242000001F62F2242000002062F2242000002162F2242000002262F2242000002362F2242000002462F2242000002562F2242000002662F2242000002762F2242000002862F2242000002962F2242000002A62F2242000002B62F2242000002C62F2242000002D62F2242000002E62F2242000002F62F2242000003062F2242000003162F2242000003262F2242000003362F2242000003462F2242000003562F2242000003662F2242000003762F2242000003862F2242000003962F2242000003A62F2242000003B62F2242000003C62F2242000003D62F2242000003E62F2242000003F62F2242000004062F2242000004162F2242000004262F2242000004362F2242000004462F2242000004562F2242000004662F2242000004762F2242000004862F2242000004962F2242000004A62F2242000004B62F2242000004C62F2242000004D62F2242000004E62F2242000004F62F2242000005062F2242000005162F2242000005262F2242000005362F2242000005462F2242000005562F2242000005662F2242000005762F2242000005862F2242000005962F2242000005A62F2242000005B62F2242000005C62F2242000005D62F2242000005E62F2242000005F62F2242000006062F2242000006162F2242000006262F2242000006362F2242000006462F2242000006562F2242000006662F2242000006762F2242000006862F2242000006962F2242000006A62F2242000006B62F2242000006C62F2242000006D62F2242000006E62F2242000006F62F2242000007062F2242000007162F2242000007262F2242000007362F2242000007462F2242000007562F2242000007662F2242000007762F2242000007862F2242000007962F2242000007A62F2242000007B62F2242000007C62F2242000007D62F2242000007E62F2242000007F62F2242000008062F2242000008162F2242000008262F2242000008362F2242000008462F2242000008562F2242000008662F2242000008762F2242000008862F2242000008962F2242000008A62F2242000008B62F2242000008C62F2242000008D62F2242000008E62F2242000008F62F2242000009062F2242000009162F2242000009262F2242000009362F2242000009462F2242000009562F2242000009662F2242000009762F2242000009862F2242000009962F2242000009A62F2242000009B62F2242000009C62F2242000009D62F2242000009E62F2242000009F62F224200000A062F224200000A162F224200000A262F224200000A362F224200000A462F224200000A562F224200000A662F224200000A762F224200000A862F224200000A962F224200000AA62F224200000AB62F224200000AC62F224200000AD62F224200000AE62F224200000AF62F224200000B062F224200000B162F224200000B262F224200000B362F224200000B462F224200000B562F224200000B662F224200000B762F224200000B862F224200000B962F224200000BA62F224200000BB62F224200000BC62F224200000BD62F224200000BE62F224200000BF62F224200000C062F224200000C162F224200000C262F224200000C362F224200000C462F224200000C562F224200000C662F224200000C762F224200000C862F224200000C962F224200000CA62F224200000CB62F224200000CC62F224200000CD62F224200000CE62F224200000CF62F224200000D062F224200000D162F224200000D262F224200000D362F224200000D462F224200000D562F224200000D662F224200000D762F224200000D862F224200000D962F224200000DA62F224200000DB62F224200000DC62F224200000DD62F224200000DE62F224200000DF62F224200000E062F224200000E162F224200000E262F224200000E362F224200000E462F224200000E562F224200000E662F224200000E762F224200000E862F224200000E962F224200000EA62F224200000EB62F224200000EC62F224200000ED62F224200000EE62F224200000EF62F224200000F062F224200000F162F224200000F262F224200000F362F224200000F462F224200000F562F224200000F662F224200000F762F224200000F862F224200000F962F224200000FA62F224200000FB62F224200000FC62F224200000FD62F224200000FE62F224200000FF62F2242000010062F2242000010162F2242000010262F2242000010362F2242000010462F2242000010562F2242000010662F2242000010762F2242000010862F2242000010962F2242000010A62F2242000010B62F2242000010C62F2242000010D62F2242000010E62F2242000010F62F2242000011062F2242000011162F2242000011262F2242000011362F2242000011462F2242000011562F2242000011662F2242000011762F2242000011862F2242000011962F2242000011A62F2242000011B62F2242000011C62F2242000011D62F2242000011E62F2242000011F62F2242000012062F2242000012162F2242000012262F2242000012362F2242000012462F2242000012562F2242000012662F2242000012762F2242000012862F2242000012962F2242000012A62F2242000012B62F2242000012C62F2242000012D62F2242000012E62F2242000012F62F2242000013062F2242000013162F2242000013262F2242000013362F2242000013462F2242000013562F2242000013662F2242000013762F2242000013862F2242000013962F2242000013A62F2242000013B62F2242000013C62F2242000013D62F2242000013E62F2242000013F62F2242000014062F2242000014162F2242000014262F2242000014362F2242000014462F2242000014562F2242000014662F2242000014762F2242000014862F2242000014962F2242000014A62F2242000014B62F2242000014C62F2242000014D62F2242000014E62F2242000014F62F2242000015062F2242000015162F2242000015262F2242000015362F2242000015462F2242000015562F2242000015662F2242000015762F2242000015862F2242000015962F2242000015A62F2242000015B62F2242000015C62F2242000015D62F2242000015E62F2242000015F62F2242000016062F2242000016162F2242000016262F2242000016362F2242000016462F2242000016562F2242000016662F2242000016762F2242000016862F2242000016962F2242000016A62F2242000016B62F2242000016C62F2242000016D62F2242000016E62F2242000016F62F2242000017062F2242000017162F2242000017262F2242000017362F2242000017462F2242000017562F2242000017662F2242000017762F2242000017862F2242000017962F2242000017A62F2242000017B62F2242000017C62F2242000017D62F2242000017E62F2242000017F62F2242000018062F2242000018162F2242000018262F2242000018362F2242000018462F2242000018562F2242000018662F2242000018762F2242000018862F2242000018962F2242000018A62F2242000018B62F2242000018C62F2242000018D62F2242000018E62F2242000018F62F2242000019062F2242000019162F2242000019262F2242000019362F2242000019462F2242000019562F2242000019662F2242000019762F2242000019862F2242000019962F2242000019A62F2242000019B62F2242000019C62F2242000019D62F2242000019E62F2242000019F62F224200001A062F224200001A162F224200001A262F224200001A362F224200001A462F224200001A562F224200001A662F224200001A762F224200001A862F224200001A962F224200001AA62F224200001AB62F224200001AC62F224200001AD62F224200001AE62F224200001AF62F224200001B062F224200001B162F224200001B262F224200001B362F224200001B462F224200001B562F224200001B662F224200001B762F224200001B862F224200001B962F224200001BA62F224200001BB62F224200001BC62F224200001BD62F224200001BE62F224200001BF62F224200001C062F224200001C162F224200001C262F224200001C362F224200001C462F224200001C562F224200001C662F224200001C762F224200001C862F224200001C962F224200001CA62F224200001CB62F224200001CC62F224200001CD62F224200001CE62F224200001CF62F224200001D062F224200001D162F224200001D262F224200001D362F224200001D462F224200001D562F224200001D662F224200001D762F224200001D862F224200001D962F224200001DA62F224200001DB62F224200001DC62F224200001DD62F224200001DE62F224200001DF62F224200001E062F224200001E162F224200001E262F224200001E362F224200001E462F224200001E562F224200001E662F224200001E762F224200001E862F224200001E962F224200001EA62F224200001EB62F224200001EC62F224200001ED62F224200001EE62F224200001EF62F224200001F062F224200001F162F224200001F262F224200001F362F224200001F462F224200001F562F224200001F662F224200001F762F224200001F862F224200001F962F224200001FA62F224200001FB62F224200001FC62F224200001FD62F224200001FE62F224200001FF62F2242000020062F2242000020162F2242000020262F2242000020362F2242000020462F2242000020562F2242000020662F2242000020762F2242000020862F2242000020962F2242000020A62F2242000020B62F2242000020C62F2242000020D62F2242000020E62F2242000020F62F2242000021062F2242000021162F2242000021262F2242000021362F2242000021462F2242000021562F2242000021662F2242000021762F2242000021862F2242000021962F2242000021A62F2242000021B62F2242000021C62F2242000021D62F2242000021E62F2242000021F62F2242000022062F2242000022162F2242000022262F2242000022362F2242000022462F2242000022562F2242000022662F2242000022762F2242000022862F2242000022962F2242000022A62F2242000022B62F2242000022C62F2242000022D62F2242000022E62F2242000022F62F2242000023062F2242000023162F2242000023262F2242000023362F2242000023462F2242000023562F2242000023662F2242000023762F2242000023862F2242000023962F2242000023A62F2242000023B62F2242000023C62F2242000023D62F2242000023E62F2242000023F62F2242000024062F2242000024162F2242000024262F2242000024362F2242000024462F2242000024562F2242000024662F2242000024762F2242000024862F2242000024962F2242000024A62F2242000024B62F2242000024C62F2242000024D62F2242000024E62F2242000024F62F2242000025062F2242000025162F2242000025262F2242000025362F2242000025462F2242000025562F2242000025662F2242000025762F2242000025862F2242000025962F2242000025A62F2242000025B62F2242000025C62F2242000025D62F2242000025E62F2242000025F62F2242000026062F2242000026162F2242000026262F2242000026362F2242000026462F2242000026562F2242000026662F2242000026762F2242000026862F2242000026962F2242000026A62F2242000026B62F2242000026C62F2242000026D62F2242000026E62F2242000026F62F2242000027062F2242000027162F2242000027262F2242000027362F2242000027462F2242000027562F2242000027662F2242000027762F2242000027862F2242000027962F2242000027A62F2242000027B62F2242000027C62F2242000027D62F2242000027E62F2242000027F62F2242000028062F2242000028162F2242000028262F2242000028362F2242000028462F2242000028562F2242000028662F2242000028762F2242000028862F2242000028962F2242000028A62F2242000028B62F2242000028C62F2242000028D62F2242000028E62F2242000028F62F2242000029062F2242000029162F2242000029262F2242000029362F2242000029462F2242000029562F2242000029662F2242000029762F2242000029862F2242000029962F2242000029A62F2242000029B62F2242000029C62F2242000029D62F2242000029E62F2242000029F62F224200002A062F224200002A162F224200002A262F224200002A362F224200002A462F224200002A562F224200002A662F224200002A762F224200002A862F224200002A962F224200002AA62F224200002AB62F224200002AC62F224200002AD62F224200002AE62F224200002AF62F224200002B062F224200002B162F224200002B262F224200002B362F224200002B462F224200002B562F224200002B662F224200002B762F224200002B862F224200002B962F224200002BA62F224200002BB62F224200002BC62F224200002BD62F224200002BE62F224200002BF62F224200002C062F224200002C162F224200002C262F224200002C362F224200002C462F224200002C562F224200002C662F224200002C762F224200002C862F224200002C962F224200002CA62F224200002CB62F224200002CC62F224200002CD62F224200002CE62F224200002CF62F224200002D062F224200002D162F224200002D262F224200002D362F224200002D462F224200002D562F224200002D662F224200002D762F224200002D862F224200002D962F224200002DA62F224200002DB62F224200002DC62F224200002DD62F224200002DE62F224200002DF62F224200002E062F224200002E162F224200002E262F224200002E362F224200002E462F224200002E562F224200002E662F224200002E762F224200002E862F224200002E962F224200002EA62F224200002EB62F224200002EC62F224200002ED62F224200002EE62F224200002EF62F224200002F062F224200002F162F224200002F262F224200002F362F224200002F462F224200002F562F224200002F662F224200002F762F224200002F862F224200002F962F224200002FA62F224200002FB62F224200002FC62F224200002FD62F224200002FE62F224200002FF62F2242000030062F2242000030162F2242000030262F2242000030362F2242000030462F2242000030562F2242000030662F2242000030762F2242000030862F2242000030962F2242000030A62F2242000030B62F2242000030C62F2242000030D62F2242000030E62F2242000030F62F2242000031062F2242000031162F2242000031262F2242000031362F2242000031462F2242000031562F2242000031662F2242000031762F2242000031862F2242000031962F2242000031A62F2242000031B62F2242000031C62F2242000031D62F2242000031E62F2242000031F62F2242000032062F2242000032162F2242000032262F2242000032362F2242000032462F2242000032562F2242000032662F2242000032762F2242000032862F2242000032962F2242000032A62F2242000032B62F2242000032C62F2242000032D62F2242000032E62F2242000032F62F2242000033062F2242000033162F2242000033262F2242000033362F2242000033462F2242000033562F2242000033662F2242000033762F2242000033862F2242000033962F2242000033A62F2242000033B62F2242000033C62F2242000033D62F2242000033E62F2242000033F62F2242000034062F2242000034162F2242000034262F2242000034362F2242000034462F2242000034562F2242000034662F2242000034762F2242000034862F2242000034962F2242000034A62F2242000034B62F2242000034C62F2242000034D62F2242000034E62F2242000034F62F2242000035062F2242000035162F2242000035262F2242000035362F2242000035462F2242000035562F2242000035662F2242000035762F2242000035862F2242000035962F2242000035A62F2242000035B62F2242000035C62F2242000035D62F2242000035E62F2242000035F62F2242000036062F2242000036162F2242000036262F2242000036362F2242000036462F2242000036562F2242000036662F2242000036762F2242000036862F2242000036962F2242000036A62F2242000036B62F2242000036C62F2242000036D62F2242000036E62F2242000036F62F2242000037062F2242000037162F2242000037262F2242000037362F2242000037462F2242000037562F2242000037662F2242000037762F2242000037862F2242000037962F2242000037A62F2242000037B62F2242000037C62F2242000037D62F2242000037E62F2242000037F62F2242000038062F2242000038162F2242000038262F2242000038362F2242000038462F2242000038562F2242000038662F2242000038762F2242000038862F2242000038962F2242000038A62F2242000038B62F2242000038C62F2242000038D62F2242000038E62F2242000038F62F2242000039062F2242000039162F2242000039262F2242000039362F2242000039462F2242000039562F2242000039662F2242000039762F2242000039862F2242000039962F2242000039A62F2242000039B62F2242000039C62F2242000039D62F2242000039E62F2242000039F62F224200003A062F224200003A162F224200003A262F224200003A362F224200003A462F224200003A562F224200003A662F224200003A762F224200003A862F224200003A962F224200003AA62F224200003AB62F224200003AC62F224200003AD62F224200003AE62F224200003AF62F224200003B062F224200003B162F224200003B262F224200003B362F224200003B462F224200003B562F224200003B662F224200003B762F224200003B862F224200003B962F224200003BA62F224200003BB62F224200003BC62F224200003BD62F224200003BE62F224200003BF62F224200003C062F224200003C162F224200003C262F224200003C362F224200003C462F224200003C562F224200003C662F224200003C762F224200003C862F224200003C962F224200003CA62F224200003CB62F224200003CC62F224200003CD62F224200003CE62F224200003CF62F224200003D062F224200003D162F224200003D262F224200003D362F224200003D462F224200003D562F224200003D662F224200003D762F224200003D862F224200003D962F224200003DA62F224200003DB62F224200003DC62F224200003DD62F224200003DE62F224200003DF62F224200003E062F224200003E162F224200003E262F224200003E362F224200003E462F224200003E562F224200003E662F224200003E762F224200003E862F224200003E962F224200003EA62F224200003EB62F224200003EC62F224200003ED62F224200003EE62F224200003EF62F224200003F062F224200003F162F224200003F262F224200003F362F224200003F462F224200003F562F224200003F662F224200003F762F224200003F862F224200003F962F224200003FA62F224200003FB62F224200003FC62F224200003FD62F224200003FE62F224200003FF62F2242000040062F2242000040162F2242000040262F2242000040362F2242000040462F2242000040562F2242000040662F2242000040762F2242000040862F2242000040962F2242000040A62F2242000040B62F2242000040C62F2242000040D62F2242000040E62F2242000040F62F2242000041062F2242000041162F2242000041262F2242000041362F2242000041462F2242000041562F2242000041662F2242000041762F2242000041862F2242000041962F2242000041A62F2242000041B62F2242000041C62F2242000041D62F2242000041E62F2242000041F62F2242000042062F2242000042162F2242000042262F2242000042362F2242000042462F2242000042562F2242000042662F2242000042762F2242000042862F2242000042962F2242000042A62F2242000042B62F2242000042C62F2242000042D62F2242000042E62F2242000042F62F2242000043062F2242000043162F2242000043262F2242000043362F2242000043462F2242000043562F2242000043662F2242000043762F2242000043862F2242000043962F2242000043A62F2242000043B62F2242000043C62F2242000043D62F2242000043E62F2242000043F62F2242000044062F2242000044162F2242000044262F2242000044362F2242000044462F2242000044562F2242000044662F2242000044762F2242000044862F2242000044962F2242000044A62F2242000044B62F2242000044C62F2242000044D62F2242000044E62F2242000044F62F2242000045062F2242000045162F2242000045262F2242000045362F2242000045462F2242000045562F2242000045662F2242000045762F2242000045862F2242000045962F2242000045A62F2242000045B62F2242000045C62F2242000045D62F2242000045E62F2242000045F62F2242000046062F2242000046162F2242000046262F2242000046362F2242000046462F2242000046562F2242000046662F2242000046762F2242000046862F2242000046962F2242000046A62F2242000046B62F2242000046C62F2242000046D62F2242000046E62F2242000046F62F2242000047062F2242000047162F2242000047262F2242000047362F2242000047462F2242000047562F2242000047662F2242000047762F2242000047862F2242000047962F2242000047A62F2242000047B62F2242000047C62F2242000047D62F2242000047E62F2242000047F62F2242000048062F2242000048162F2242000048262F2242000048362F2242000048462F2242000048562F2242000048662F2242000048762F2242000048862F2242000048962F2242000048A62F2242000048B62F2242000048C62F2242000048D62F2242000048E62F2242000048F62F2242000049062F2242000049162F2242000049262F2242000049362F2242000049462F2242000049562F2242000049662F2242000049762F2242000049862F2242000049962F2242000049A62F2242000049B62F2242000049C62F2242000049D62F2242000049E62F2242000049F62F224200004A062F224200004A162F224200004A262F224200004A362F224200004A462F224200004A562F224200004A662F224200004A762F224200004A862F224200004A962F224200004AA62F224200004AB62F224200004AC62F224200004AD62F224200004AE62F224200004AF62F224200004B062F224200004B162F224200004B262F224200004B362F224200004B462F224200004B562F224200004B662F224200004B762F224200004B862F224200004B962F224200004BA62F224200004BB62F224200004BC62F224200004BD62F224200004BE62F224200004BF62F224200004C062F224200004C162F224200004C262F224200004C362F224200004C462F224200004C562F224200004C662F224200004C762F224200004C862F224200004C962F224200004CA62F224200004CB62F224200004CC62F224200004CD62F224200004CE62F224200004CF62F224200004D062F224200004D162F224200004D262F224200004D362F224200004D462F224200004D562F224200004D662F224200004D762F224200004D862F224200004D962F224200004DA62F224200004DB62F224200004DC62F224200004DD62F224200004DE62F224200004DF62F224200004E062F224200004E162F224200004E262F224200004E362F224200004E462F224200004E562F224200004E662F224200004E762F224200004E862F224200004E962F224200004EA62F224200004EB62F224200004EC62F224200004ED62F224200004EE62F224200004EF62F224200004F062F224200004F162F224200004F262F224200004F362F224200004F462F224200004F562F224200004F662F224200004F762F224200004F862F224200004F962F224200004FA62F224200004FB62F224200004FC62F224200004FD62F224200004FE62F224200004FF62F2242000050062F2242000050162F2242000050262F2242000050362F2242000050462F2242000050562F2242000050662F2242000050762F2242000050862F2242000050962F2242000050A62F2242000050B62F2242000050C62F2242000050D62F2242000050E62F2242000050F62F2242000051062F2242000051162F2242000051262F2242000051362F2242000051462F2242000051562F2242000051662F2242000051762F2242000051862F2242000051962F2242000051A62F2242000051B62F2242000051C62F2242000051D62F2242000051E62F2242000051F62F2242000052062F2242000052162F2242000052262F2242000052362F2242000052462F2242000052562F2242000052662F2242000052762F2242000052862F2242000052962F2242000052A62F2242000052B62F2242000052C62F2242000052D62F2242000052E62F2242000052F62F2242000053062F2242000053162F2242000053262F2242000053362F2242000053462F2242000053562F2242000053662F2242000053762F2242000053862F2242000053962F2242000053A62F2242000053B62F2242000053C62F2242000053D62F2242000053E62F2242000053F62F2242000054062F2242000054162F2242000054262F2242000054362F2242000054462F2242000054562F2242000054662F2242000054762F2242000054862F2242000054962F2242000054A62F2242000054B62F2242000054C62F2242000054D62F2242000054E62F2242000054F62F2242000055062F2242000055162F2242000055262F2242000055362F2242000055462F2242000055562F2242000055662F2242000055762F2242000055862F2242000055962F2242000055A62F2242000055B62F2242000055C62F2242000055D62F2242000055E62F2242000055F62F2242000056062F2242000056162F2242000056262F2242000056362F2242000056462F2242000056562F2242000056662F2242000056762F2242000056862F2242000056962F2242000056A62F2242000056B62F2242000056C62F2242000056D62F2242000056E62F2242000056F62F2242000057062F2242000057162F2242000057262F2242000057362F2242000057462F2242000057562F2242000057662F2242000057762F2242000057862F2242000057962F2242000057A62F2242000057B62F2242000057C62F2242000057D62F2242000057E62F2242000057F62F2242000058062F2242000058162F2242000058262F2242000058362F2242000058462F2242000058562F2242000058662F2242000058762F2242000058862F2242000058962F2242000058A62F2242000058B62F2242000058C62F2242000058D62F2242000058E62F2242000058F62F2242000059062F2242000059162F2242000059262F2242000059362F2242000059462F2242000059562F2242000059662F2242000059762F2242000059862F2242000059962F2242000059A62F2242000059B62F2242000059C62F2242000059D62F2242000059E62F2242000059F62F224200005A062F224200005A162F224200005A262F224200005A362F224200005A462F224200005A562F224200005A662F224200005A762F224200005A862F224200005A962F224200005AA62F224200005AB62F224200005AC62F224200005AD62F224200005AE62F224200005AF62F224200005B062F224200005B162F224200005B262F224200005B362F224200005B462F224200005B562F224200005B662F224200005B762F224200005B862F224200005B962F224200005BA62F224200005BB62F224200005BC62F224200005BD62F224200005BE62F224200005BF62F224200005C062F224200005C162F224200005C262F224200005C362F224200005C462F224200005C562F224200005C662F224200005C762F224200005C862F224200005C962F224200005CA62F224200005CB62F224200005CC62F224200005CD62F224200005CE62F224200005CF62F224200005D062F224200005D162F224200005D262F224200005D362F224200005D462F224200005D562F224200005D662F224200005D762F224200005D862F224200005D962F224200005DA62F224200005DB62F224200005DC62F224200005DD62F224200005DE62F224200005DF62F224200005E062F224200005E162F224200005E262F224200005E362F224200005E462F224200005E562F224200005E662F224200005E762F224200005E862F224200005E962F224200005EA62F224200005EB62F224200005EC62F224200005ED62F224200005EE62F224200005EF62F224200005F062F224200005F162F224200005F262F224200005F362F224200005F462F224200005F562F224200005F662F224200005F762F224200005F862F224200005F962F224200005FA62F224200005FB62F224200005FC62F224200005FD62F224200005FE62F224200005FF62F2242000060062F2242000060162F2242000060262F2242000060362F2242000060462F2242000060562F2242000060662F2242000060762F2242000060862F2242000060962F2242000060A62F2242000060B62F2242000060C62F2242000060D62F2242000060E62F2242000060F62F2242000061062F2242000061162F2242000061262F2242000061362F2242000061462F2242000061562F2242000061662F2242000061762F2242000061862F2242000061962F2242000061A62F2242000061B62F2242000061C62F2242000061D62F2242000061E62F2242000061F62F2242000062062F2242000062162F2242000062262F2242000062362F2242000062462F2242000062562F2242000062662F2242000062762F2242000062862F2242000062962F2242000062A62F2242000062B62F2242000062C62F2242000062D62F2242000062E62F2242000062F62F2242000063062F2242000063162F2242000063262F2242000063362F2242000063462F2242000063562F2242000063662F2242000063762F2242000063862F2242000063962F2242000063A62F2242000063B62F2242000063C62F2242000063D62F2242000063E62F2242000063F62F2242000064062F2242000064162F2242000064262F2242000064362F2242000064462F2242000064562F2242000064662F2242000064762F2242000064862F2242000064962F2242000064A62F2242000064B62F2242000064C62F2242000064D62F2242000064E62F2242000064F62F2242000065062F2242000065162F2242000065262F2242000065362F2242000065462F2242000065562F2242000065662F2242000065762F2242000065862F2242000065962F2242000065A62F2242000065B62F2242000065C62F2242000065D62F2242000065E62F2242000065F62F2242000066062F2242000066162F2242000066262F2242000066362F2242000066462F2242000066562F2242000066662F2242000066762F2242000066862F2242000066962F2242000066A62F2242000066B62F2242000066C62F2242000066D62F2242000066E62F2242000066F62F2242000067062F2242000067162F2242000067262F2242000067362F2242000067462F2242000067562F2242000067662F2242000067762F2242000067862F2242000067962F2242000067A62F2242000067B62F2242000067C62F2242000067D62F2242000067E62F2242000067F62F2242000068062F2242000068162F2242000068262F2242000068362F2242000068462F2242000068562F2242000068662F2242000068762F2242000068862F2242000068962F2242000068A62F2242000068B62F2242000068C62F2242000068D62F2242000068E62F2242000068F62F2242000069062F2242000069162F2242000069262F2242000069362F2242000069462F2242000069562F2242000069662F2242000069762F2242000069862F2242000069962F2242000069A62F2242000069B62F2242000069C62F2242000069D62F2242000069E62F2242000069F62F224200006A062F224200006A162F224200006A262F224200006A362F224200006A462F224200006A562F224200006A662F224200006A762F224200006A862F224200006A962F224200006AA62F224200006AB62F224200006AC62F224200006AD62F224200006AE62F224200006AF62F224200006B062F224200006B162F224200006B262F224200006B362F224200006B462F224200006B562F224200006B662F224200006B762F224200006B862F224200006B962F224200006BA62F224200006BB62F224200006BC62F224200006BD62F224200006BE62F224200006BF62F224200006C062F224200006C162F224200006C262F224200006C362F224200006C462F224200006C562F224200006C662F224200006C762F224200006C862F224200006C962F224200006CA62F224200006CB62F224200006CC62F224200006CD62F224200006CE62F224200006CF62F224200006D062F224200006D162F224200006D262F224200006D362F224200006D462F224200006D562F224200006D662F224200006D762F224200006D862F224200006D962F224200006DA62F224200006DB62F224200006DC62F224200006DD62F224200006DE62F224200006DF62F224200006E062F224200006E162F224200006E262F224200006E362F224200006E462F224200006E562F224200006E662F224200006E762F224200006E862F224200006E962F224200006EA62F224200006EB62F224200006EC62F224200006ED62F224200006EE62F224200006EF62F224200006F062F224200006F162F224200006F262F224200006F362F224200006F462F224200006F562F224200006F662F224200006F762F224200006F862F224200006F962F224200006FA62F224200006FB62F224200006FC62F224200006FD62F224200006FE62F224200006FF62F2242000070062F2242000070162F2242000070262F2242000070362F2242000070462F2242000070562F2242000070662F2242000070762F2242000070862F2242000070962F2242000070A62F2242000070B62F2242000070C62F2242000070D62F2242000070E62F2242000070F62F2242000071062F2242000071162F2242000071262F2242000071362F2242000071462F2242000071562F2242000071662F2242000071762F2242000071862F2242000071962F2242000071A62F2242000071B62F2242000071C62F2242000071D62F2242000071E62F2242000071F62F2242000072062F2242000072162F2242000072262F2242000072362F2242000072462F2242000072562F2242000072662F2242000072762F2242000072862F2242000072962F2242000072A62F2242000072B62F2242000072C62F2242000072D62F2242000072E62F2242000072F62F2242000073062F2242000073162F2242000073262F2242000073362F2242000073462F2242000073562F2242000073662F2242000073762F2242000073862F2242000073962F2242000073A62F2242000073B62F2242000073C62F2242000073D62F2242000073E62F2242000073F62F2242000074062F2242000074162F2242000074262F2242000074362F2242000074462F2242000074562F2242000074662F2242000074762F2242000074862F2242000074962F2242000074A62F2242000074B62F2242000074C62F2242000074D62F2242000074E62F2242000074F62F2242000075062F2242000075162F2242000075262F2242000075362F2242000075462F2242000075562F2242000075662F2242000075762F2242000075862F2242000075962F2242000075A62F2242000075B62F2242000075C62F2242000075D62F2242000075E62F2242000075F62F2242000076062F2242000076162F2242000076262F2242000076362F2242000076462F2242000076562F2242000076662F2242000076762F2242000076862F2242000076962F2242000076A62F2242000076B62F2242000076C62F2242000076D62F2242000076E62F2242000076F62F2242000077062F2242000077162F2242000077262F2242000077362F2242000077462F2242000077562F2242000077662F2242000077762F2242000077862F2242000077962F2242000077A62F2242000077B62F2242000077C62F2242000077D62F2242000077E62F2242000077F62F2242000078062F2242000078162F2242000078262F2242000078362F2242000078462F2242000078562F2242000078662F2242000078762F2242000078862F2242000078962F2242000078A62F2242000078B62F2242000078C62F2242000078D62F2242000078E62F2242000078F62F2242000079062F2242000079162F2242000079262F2242000079362F2242000079462F2242000079562F2242000079662F2242000079762F2242000079862F2242000079962F2242000079A62F2242000079B62F2242000079C62F2242000079D62F2242000079E62F2242000079F62F224200007A062F224200007A162F224200007A262F224200007A362F224200007A462F224200007A562F224200007A662F224200007A762F224200007A862F224200007A962F224200007AA62F224200007AB62F224200007AC62F224200007AD62F224200007AE62F224200007AF62F224200007B062F224200007B162F224200007B262F224200007B362F224200007B462F224200007B562F224200007B662F224200007B762F224200007B862F224200007B962F224200007BA62F224200007BB62F224200007BC62F224200007BD62F224200007BE62F224200007BF62F224200007C062F224200007C162F224200007C262F224200007C362F224200007C462F224200007C562F224200007C662F224200007C762F224200007C862F224200007C962F224200007CA62F224200007CB62F224200007CC62F224200007CD62F224200007CE62F224200007CF62F224200007D062F224200007D162F224200007D262F224200007D362F224200007D462F224200007D562F224200007D662F224200007D762F224200007D862F224200007D962F224200007DA62F224200007DB62F224200007DC62F224200007DD62F224200007DE62F224200007DF62F224200007E062F224200007E162F224200007E262F224200007E362F224200007E462F224200007E562F224200007E662F224200007E762F224200007E862F224200007E962F224200007EA62F224200007EB62F224200007EC62F224200007ED62F224200007EE62F224200007EF62F224200007F062F224200007F162F224200007F262F224200007F362F224200007F462F224200007F562F224200007F662F224200007F762F224200007F862F224200007F962F224200007FA62F224200007FB62F224200007FC62F224200007FD62F224200007FE62F224200007FF62F2242000080062F2242000080162F2242000080262F2242000080362F2242000080462F2242000080562F2242000080662F2242000080762F2242000080862F2242000080962F2242000080A62F2242000080B62F2242000080C62F2242000080D62F2242000080E62F2242000080F62F2242000081062F2242000081162F2242000081262F2242000081362F2242000081462F2242000081562F2242000081662F2242000081762F2242000081862F2242000081962F2242000081A62F2242000081B62F2242000081C62F2242000081D62F2242000081E62F2242000081F62F2242000082062F2242000082162F2242000082262F2242000082362F2242000082462F2242000082562F2242000082662F2242000082762F2242000082862F2242000082962F2242000082A62F2242000082B62F2242000082C62F2242000082D62F2242000082E62F2242000082F62F2242000083062F2242000083162F2242000083262F2242000083362F2242000083462F2242000083562F2242000083662F2242000083762F2242000083862F2242000083962F2242000083A62F2242000083B62F2242000083C62F2242000083D62F2242000083E62F2242000083F62F2242000084062F2242000084162F2242000084262F2242000084362F2242000084462F2242000084562F2242000084662F2242000084762F2242000084862F2242000084962F2242000084A62F2242000084B62F2242000084C62F2242000084D62F2242000084E62F2242000084F62F2242000085062F2242000085162F2242000085262F2242000085362F2242000085462F2242000085562F2242000085662F2242000085762F2242000085862F2242000085962F2242000085A62F2242000085B62F2242000085C62F2242000085D62F2242000085E62F2242000085F62F2242000086062F2242000086162F2242000086262F2242000086362F2242000086462F2242000086562F2242000086662F2242000086762F2242000086862F2242000086962F2242000086A62F2242000086B62F2242000086C62F2242000086D62F2242000086E62F2242000086F62F2242000087062F2242000087162F2242000087262F2242000087362F2242000087462F2242000087562F2242000087662F2242000087762F2242000087862F2242000087962F2242000087A62F2242000087B62F2242000087C62F2242000087D62F2242000087E62F2242000087F62F2242000088062F2242000088162F2242000088262F2242000088362F2242000088462F2242000088562F2242000088662F2242000088762F2242000088862F2242000088962F2242000088A62F2242000088B62F2242000088C62F2242000088D62F2242000088E62F2242000088F62F2242000089062F2242000089162F2242000089262F2242000089362F2242000089462F2242000089562F2242000089662F2242000089762F2242000089862F2242000089962F2242000089A62F2242000089B62F2242000089C62F2242000089D62F2242000089E62F2242000089F62F224200008A062F224200008A162F224200008A262F224200008A362F224200008A462F224200008A562F224200008A662F224200008A762F224200008A862F224200008A962F224200008AA62F224200008AB62F224200008AC62F224200008AD62F224200008AE62F224200008AF62F224200008B062F224200008B162F224200008B262F224200008B362F224200008B462F224200008B562F224200008B662F224200008B762F224200008B862F224200008B962F224200008BA62F224200008BB62F224200008BC62F224200008BD62F224200008BE62F224200008BF62F224200008C062F224200008C162F224200008C262F224200008C362F224200008C462F224200008C562F224200008C662F224200008C762F224200008C862F224200008C962F224200008CA62F224200008CB62F224200008CC62F224200008CD62F224200008CE62F224200008CF62F224200008D062F224200008D162F224200008D262F224200008D362F224200008D462F224200008D562F224200008D662F224200008D762F224200008D862F224200008D962F224200008DA62F224200008DB62F224200008DC62F224200008DD62F224200008DE62F224200008DF62F224200008E062F224200008E162F224200008E262F224200008E362F224200008E462F224200008E562F224200008E662F224200008E762F224200008E862F224200008E962F224200008EA62F224200008EB62F224200008EC62F224200008ED62F224200008EE62F224200008EF62F224200008F062F224200008F162F224200008F262F224200008F362F224200008F462F224200008F562F224200008F662F224200008F762F224200008F862F224200008F962F224200008FA62F224200008FB62F224200008FC62F224200008FD62F224200008FE62F224200008FF62F2242000090062F2242000090162F2242000090262F2242000090362F2242000090462F2242000090562F2242000090662F2242000090762F2242000090862F2242000090962F2242000090A62F2242000090B62F2242000090C62F2242000090D62F2242000090E62F2242000090F62F2242000091062F2242000091162F2242000091262F2242000091362F2242000091462F2242000091562F2242000091662F2242000091762F2242000091862F2242000091962F2242000091A62F2242000091B62F2242000091C62F2242000091D62F2242000091E62F2242000091F62F22420849200092062F2242000092162F2242000092262F28465242000092362F2242000092462F2242000092562F2242000092662F2242000092762F2242000092862F2242000092962F2242000092A62F2242000092B62F2242000092C62F2242000092D62F2242000092E62F2242000092F62F2242000093062F2242000093162F2242000093262F2242000093362F2242000093462F2242000093562F2242000093662F2242000093762F2242000093862F2242000093962F2242000093A62F2242000093B62F2242000093C62F2242000093D62F2242000093E62F2242000093F62F2242000094062F2242000094162F2242000094262F2242000094362F2242000094462F2242000094562F2242000094662F2242000094762F2242000094862F2242000094962F2242000094A62F2242000094B62F2242000094C62F2242000094D62F2242000094E62F2242000094F62F2242000095062F2242000095162F2242000095262F2242000095362F2242000095462F2242000095562F2242000095662F2242000095762F2242000095862F2242000095962F2242000095A62F2242000095B62F2242000095C62F2242000095D62F2242000095E62F2242000095F62F2242000096062F2242000096162F2242000096262F2242000096362F2242000096462F2242000096562F2242000096662F2242000096762F2242000096862F2242000096962F2242000096A62F2242000096B62F2242000096C62F2242000096D62F2242000096E62F2242000096F62F2242000097062F2242000097162F2242000097262F2242000097362F2242000097462F2242000097562F2242000097662F2242000097762F2242000097862F2242000097962F2242000097A62F2242000097B62F2242000097C62F2242000097D62F2242000097E62F2242000097F62F2242000098062F2242000098162F2242000098262F2242000098362F2242000098462F2242000098562F2242000098662F2242000098762F2242000098862F2242000098962F2242000098A62F2242000098B62F2242000098C62F2242000098D62F2242000098E62F2242000098F62F2242000099062F2242000099162F2242000099262F2242000099362F2242000099462F2242000099562F2242000099662F2242000099762F2242000099862F2242000099962F2242000099A62F2242000099B62F2242000099C62F2242000099D62F2242000099E62F2242000099F62F224200009A062F224200009A162F224200009A262F224200009A362F224200009A462F224200009A562F224200009A662F224200009A762F224200009A862F224200009A962F224200009AA62F224200009AB62F224200009AC62F224200009AD62F224200009AE62F224200009AF62F224200009B062F224200009B162F224200009B262F224200009B362F224200009B462F224200009B562F224200009B662F224200009B762F224200009B862F224200009B962F224200009BA62F224200009BB62F224200009BC62F224200009BD62F224200009BE62F224200009BF62F224200009C062F224200009C162F224200009C262F224200009C3000D0002001600090002002A00040001000000000300075A'O;
+
+/* test whether a message with chnked length determinant is parsed */
+testcase TC_chunked_len() runs on test_CT {
+ f_init();
+ TCP.send(ts_AS(g_tcp_conn_id, c_chunked));
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ setverdict(pass);
+}
+
+/* test whether a message with chunked length determinant is parsed if each byte is received separately */
+testcase TC_chunked_len_bytewise() runs on test_CT {
+ f_init();
+ tcp_send_segmented(c_chunked, 100, 0.05);
+ f_sabp_exp(tr_SABP_Write(?, ?));
+ setverdict(pass);
+}
+
+control {
+ execute( TC_1byte_len() );
+ execute( TC_1byte_len_bytewise() );
+ execute( TC_1byte_len_chained() );
+ execute( TC_2byte_len() );
+ execute( TC_2byte_len_bytewise() );
+ execute( TC_2byte_len_chained() );
+ execute( TC_2byte_len_chained_bytewise() );
+ execute( TC_chunked_len() );
+ execute( TC_chunked_len_bytewise() );
+}
+
+
+}
diff --git a/library/sabp/regen_makefile.sh b/library/sabp/regen_makefile.sh
new file mode 100755
index 00000000..382fbd58
--- /dev/null
+++ b/library/sabp/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+FILES="*.asn *.ttcn SABP_EncDec.cc"
+
+../../regen-makefile.sh $FILES
+
+sed -i -e '/^CPPFLAGS/ s/$/ `pkg-config --cflags libfftranscode`/' Makefile
+sed -i -e '/^LDFLAGS/ s/$/ `pkg-config --libs libfftranscode`/' Makefile
+sed -i -e '/^LINUX_LIBS/ s/$/ `pkg-config --libs libfftranscode`/' Makefile
diff --git a/library/sbcap/SBC_AP_Adapter.ttcn b/library/sbcap/SBC_AP_Adapter.ttcn
new file mode 100644
index 00000000..515a723e
--- /dev/null
+++ b/library/sbcap/SBC_AP_Adapter.ttcn
@@ -0,0 +1,108 @@
+module SBC_AP_Adapter {
+
+/* SBC_AP Adapter layer, sitting on top of SBC_AP_CodecPort.
+ * test suites can 'inherit' in order to have a SBC_AP connection to the IUT which they're testing
+ *
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+
+import from Osmocom_Types all;
+import from General_Types all;
+import from SBC_AP_Types all;
+import from SBC_AP_PDU_Descriptions all;
+import from SBC_AP_Templates all;
+import from SBC_AP_CodecPort all;
+import from SBC_AP_CodecPort_CtrlFunct all;
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+import from Socket_API_Definitions all;
+import from Misc_Helpers all;
+
+
+const integer SBC_AP_HDR_LEN := 3;
+
+const integer NUM_SBC_AP := 3;
+
+type component SBC_AP_Adapter_CT {
+ /* down-facing port to SBC_AP Codec port */
+ port SBC_AP_CODEC_PT SBC_AP[NUM_SBC_AP];
+ var IPL4asp_Types.ConnectionId g_SBC_AP_conn_id[NUM_SBC_AP] := { -1, -1, -1 };
+}
+
+private template Socket_API_Definitions.PortEvent tr_SctpAssocChange_COMM_UP(IPL4asp_Types.ConnectionId id) := {
+ sctpEvent := {
+ sctpAssocChange := {
+ clientId := id,
+ proto := {
+ sctp := ?
+ },
+ sac_state := SCTP_COMM_UP
+ }
+ }
+}
+
+function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
+ charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on SBC_AP_Adapter_CT {
+ var IPL4asp_Types.Result res;
+ map(self:SBC_AP[idx], system:SBC_AP);
+ res := SBC_AP_CodecPort_CtrlFunct.f_IPL4_connect(SBC_AP[idx], remote_host, remote_port,
+ local_host, local_port, 0, { sctp := valueof(ts_SBC_AP_SctpTuple) });
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not connect to SBC_AP port, check your configuration");
+ mtc.stop;
+ }
+ g_SBC_AP_conn_id[idx] := res.connId;
+ timer Tcommup := 10.0;
+ Tcommup.start;
+ alt {
+ [] SBC_AP[idx].receive(tr_SctpAssocChange_COMM_UP(g_SBC_AP_conn_id[idx])) {}
+ [] Tcommup.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting SCTP_COMM_UP");
+ }
+ }
+}
+
+/* Function to use to bind to a local port as IPA server, accepting remote clients */
+function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
+runs on SBC_AP_Adapter_CT {
+ var IPL4asp_Types.Result res;
+ map(self:SBC_AP[idx], system:SBC_AP);
+ res := SBC_AP_CodecPort_CtrlFunct.f_IPL4_listen(SBC_AP[idx], local_host, local_port, { sctp := valueof(ts_SBC_AP_SctpTuple) });
+ g_SBC_AP_conn_id[idx] := res.connId;
+}
+
+function f_wait_client_connect(integer idx := 0) runs on SBC_AP_Adapter_CT {
+ var IPL4asp_Types.PortEvent rx_event;
+ SBC_AP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
+ log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
+ /* we want to store the client's connId, not the 'bind socket' one */
+ g_SBC_AP_conn_id[idx] := rx_event.connOpened.connId;
+ }
+ timer Tcommup := 10.0;
+ Tcommup.start;
+ alt {
+ [] SBC_AP[idx].receive(tr_SctpAssocChange_COMM_UP(g_SBC_AP_conn_id[idx])) {}
+ [] Tcommup.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting SCTP_COMM_UP");
+ }
+ }
+}
+
+function f_SBC_AP_send(template (value) SBC_AP_PDU pdu, integer idx := 0) runs on SBC_AP_Adapter_CT {
+ SBC_AP[idx].send(ts_SBC_AP_Send(g_SBC_AP_conn_id[idx], pdu));
+}
+
+function f_SBC_AP_exp(template SBC_AP_PDU exp, integer idx := 0) runs on SBC_AP_Adapter_CT return SBC_AP_PDU {
+ var SBC_AP_RecvFrom rf;
+ SBC_AP[idx].receive(tr_SBC_AP_Recv(g_SBC_AP_conn_id[idx], exp)) -> value rf;
+ return rf.msg;
+}
+
+
+}
diff --git a/library/sbcap/SBC_AP_CodecPort.ttcn b/library/sbcap/SBC_AP_CodecPort.ttcn
new file mode 100644
index 00000000..bd170312
--- /dev/null
+++ b/library/sbcap/SBC_AP_CodecPort.ttcn
@@ -0,0 +1,84 @@
+module SBC_AP_CodecPort {
+
+/* Simple SBC AP Codec Port, translating between raw SCTP primitives with
+ * octetstring payload towards the IPL4asp provider, and SBC-AP primitives
+ * which carry the decoded SBC-AP data types as payload.
+ *
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * 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
+ */
+
+ import from IPL4asp_PortType all;
+ import from IPL4asp_Types all;
+ import from SBC_AP_PDU_Descriptions all;
+ import from SBC_AP_Types all;
+
+ type record SBC_AP_RecvFrom {
+ ConnectionId connId,
+ HostName remName,
+ PortNumber remPort,
+ HostName locName,
+ PortNumber locPort,
+ SBC_AP_PDU msg
+ };
+
+ type record SBC_AP_Send {
+ ConnectionId connId,
+ SBC_AP_PDU msg
+ };
+
+ template (value) SctpTuple ts_SBC_AP_SctpTuple := {
+ sinfo_stream := omit,
+ sinfo_ppid := c_SBC_AP_PPID,
+ remSocks := omit,
+ assocId := omit
+ };
+
+ template (value) SBC_AP_Send ts_SBC_AP_Send(ConnectionId connId, template (value) SBC_AP_PDU msg) := {
+ connId := connId,
+ msg := msg
+ }
+
+ template (present) SBC_AP_RecvFrom tr_SBC_AP_Recv(template ConnectionId connId, template SBC_AP_PDU msg) := {
+ connId := connId,
+ remName := ?,
+ remPort := ?,
+ locName := ?,
+ locPort := ?,
+ msg := msg
+ }
+
+ private function IPL4_to_SBC_AP_RecvFrom(in ASP_RecvFrom pin, out SBC_AP_RecvFrom pout) {
+ pout.connId := pin.connId;
+ pout.remName := pin.remName;
+ pout.remPort := pin.remPort;
+ pout.locName := pin.locName;
+ pout.locPort := pin.locPort;
+ pout.msg := dec_SBC_AP_PDU(pin.msg);
+ } with { extension "prototype(fast)" };
+
+ private function SBC_AP_to_IPL4_Send(in SBC_AP_Send pin, out ASP_Send pout) {
+ pout.connId := pin.connId;
+ pout.proto := {
+ sctp := valueof(ts_SBC_AP_SctpTuple)
+ };
+ pout.msg := enc_SBC_AP_PDU(pin.msg);
+ } with { extension "prototype(fast)" };
+
+ type port SBC_AP_CODEC_PT message {
+ out SBC_AP_Send;
+ in SBC_AP_RecvFrom,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+ } with { extension "user IPL4asp_PT
+ out(SBC_AP_Send -> ASP_Send:function(SBC_AP_to_IPL4_Send))
+ in(ASP_RecvFrom -> SBC_AP_RecvFrom: function(IPL4_to_SBC_AP_RecvFrom);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)"
+ }
+}
diff --git a/library/sbcap/SBC_AP_CodecPort_CtrlFunct.ttcn b/library/sbcap/SBC_AP_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..bdf1eec1
--- /dev/null
+++ b/library/sbcap/SBC_AP_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,44 @@
+module SBC_AP_CodecPort_CtrlFunct {
+
+ import from SBC_AP_CodecPort all;
+ import from IPL4asp_Types all;
+
+ external function f_IPL4_listen(
+ inout SBC_AP_CODEC_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_connect(
+ inout SBC_AP_CODEC_PT portRef,
+ in HostName remName,
+ in PortNumber remPort,
+ in HostName locName,
+ in PortNumber locPort,
+ in ConnectionId connId,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_close(
+ inout SBC_AP_CODEC_PT portRef,
+ in ConnectionId id,
+ in ProtoTuple proto := { unspecified := {} }
+ ) return Result;
+
+ external function f_IPL4_setUserData(
+ inout SBC_AP_CODEC_PT portRef,
+ in ConnectionId id,
+ in UserData userData
+ ) return Result;
+
+ external function f_IPL4_getUserData(
+ inout SBC_AP_CODEC_PT portRef,
+ in ConnectionId id,
+ out UserData userData
+ ) return Result;
+
+}
+
diff --git a/library/sbcap/SBC_AP_CodecPort_CtrlFunctDef.cc b/library/sbcap/SBC_AP_CodecPort_CtrlFunctDef.cc
new file mode 100644
index 00000000..4eb00c65
--- /dev/null
+++ b/library/sbcap/SBC_AP_CodecPort_CtrlFunctDef.cc
@@ -0,0 +1,55 @@
+#include "IPL4asp_PortType.hh"
+#include "SBC_AP_CodecPort.hh"
+#include "IPL4asp_PT.hh"
+
+namespace SBC__AP__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__IPL4__listen(
+ SBC__AP__CodecPort::SBC__AP__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__connect(
+ SBC__AP__CodecPort::SBC__AP__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& remName,
+ const IPL4asp__Types::PortNumber& remPort,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+ locName, locPort, connId, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__close(
+ SBC__AP__CodecPort::SBC__AP__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto)
+ {
+ return f__IPL4__PROVIDER__close(portRef, connId, proto);
+ }
+
+ IPL4asp__Types::Result f__IPL4__setUserData(
+ SBC__AP__CodecPort::SBC__AP__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+ }
+
+ IPL4asp__Types::Result f__IPL4__getUserData(
+ SBC__AP__CodecPort::SBC__AP__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+ }
+
+}
diff --git a/library/sbcap/SBC_AP_CommonDataTypes.asn b/library/sbcap/SBC_AP_CommonDataTypes.asn
new file mode 100644
index 00000000..e11f3175
--- /dev/null
+++ b/library/sbcap/SBC_AP_CommonDataTypes.asn
@@ -0,0 +1,35 @@
+-- SBC-AP-CommonDataTypes.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.6 Common Definitions
+--
+
+-- **************************************************************
+--
+-- Common definitions
+--
+-- **************************************************************
+
+SBC-AP-CommonDataTypes {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-CommonDataTypes (3)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+Criticality ::= ENUMERATED { reject, ignore, notify }
+
+Presence ::= ENUMERATED { optional, conditional, mandatory }
+
+ProcedureCode ::= INTEGER (0..255)
+
+ProtocolExtensionID ::= INTEGER (0..65535)
+
+ProtocolIE-ID ::= INTEGER (0..65535)
+
+TriggeringMessage ::= ENUMERATED {initiating-message, successful-outcome, unsuccessful-outcome, outcome}
+
+END
diff --git a/library/sbcap/SBC_AP_Constants.asn b/library/sbcap/SBC_AP_Constants.asn
new file mode 100644
index 00000000..447e1c42
--- /dev/null
+++ b/library/sbcap/SBC_AP_Constants.asn
@@ -0,0 +1,127 @@
+-- SBC-AP-Constants.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.7 Constant Definitions
+--
+-- **************************************************************
+--
+-- Constant definitions
+--
+-- **************************************************************
+
+SBC-AP-Constants {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-Constants (4)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- Elementary Procedures
+--
+-- **************************************************************
+
+id-Write-Replace-Warning INTEGER ::= 0
+id-Stop-Warning INTEGER ::= 1
+id-Error-Indication INTEGER ::= 2
+id-Write-Replace-Warning-Indication INTEGER ::= 3
+id-Stop-Warning-Indication INTEGER ::= 4
+id-PWS-Restart-Indication INTEGER ::= 5
+id-PWS-Failure-Indication INTEGER ::= 6
+
+-- **************************************************************
+--
+-- IEs
+--
+-- **************************************************************
+
+id-Broadcast-Message-Content INTEGER ::= 0
+id-Cause INTEGER ::= 1
+id-Criticality-Diagnostics INTEGER ::=2
+id-Data-Coding-Scheme INTEGER ::= 3
+id-Failure-List INTEGER ::= 4
+id-Message-Identifier INTEGER ::= 5
+id-Number-of-Broadcasts-Completed-List INTEGER ::= 6
+id-Number-of-Broadcasts-Requested INTEGER ::= 7
+id-Radio-Resource-Loading-List INTEGER ::= 8
+id-Recovery-Indication INTEGER ::= 9
+id-Repetition-Period INTEGER ::= 10
+id-Serial-Number INTEGER ::= 11
+id-Service-Areas-List INTEGER ::= 12
+id-TypeOfError INTEGER ::= 13
+id-List-of-TAIs INTEGER ::= 14
+id-Warning-Area-List INTEGER ::= 15
+id-Warning-Message-Content INTEGER ::= 16
+id-Warning-Security-Information INTEGER ::= 17
+id-Warning-Type INTEGER ::= 18
+id-Omc-Id INTEGER ::= 19
+id-Concurrent-Warning-Message-Indicator INTEGER ::= 20
+id-Extended-Repetition-Period INTEGER ::= 21
+id-Unknown-Tracking-Area-List INTEGER ::= 22
+id-Broadcast-Scheduled-Area-List INTEGER ::= 23
+id-Send-Write-Replace-Warning-Indication INTEGER ::= 24
+id-Broadcast-Cancelled-Area-List INTEGER ::= 25
+id-Send-Stop-Warning-Indication INTEGER ::= 26
+id-Stop-All-Indicator INTEGER ::= 27
+id-Global-ENB-ID INTEGER ::= 28
+id-Broadcast-Empty-Area-List INTEGER ::= 29
+id-Restarted-Cell-List INTEGER ::= 30
+id-List-of-TAIs-Restart INTEGER ::= 31
+id-List-of-EAIs-Restart INTEGER ::= 32
+id-Failed-Cell-List INTEGER ::= 33
+id-List-of-5GS-TAIs INTEGER ::= 34
+id-Warning-Area-List-5GS INTEGER ::= 35
+id-Global-RAN-Node-ID INTEGER ::= 36
+id-Global-GNB-ID INTEGER ::= 37
+id-RAT-Selector-5GS INTEGER ::= 38
+id-Unknown-5GS-Tracking-Area-List INTEGER ::= 39
+id-Broadcast-Scheduled-Area-List-5GS INTEGER ::= 40
+id-Broadcast-Cancelled-Area-List-5GS INTEGER ::= 41
+id-Broadcast-Empty-Area-List-5GS INTEGER ::= 42
+id-Restarted-Cell-List-NR INTEGER ::= 43
+id-Failed-Cell-List-NR INTEGER ::= 44
+id-List-of-5GS-TAI-for-Restart INTEGER ::= 45
+id-Warning-Area-Coordinates INTEGER ::= 46
+
+
+
+-- **************************************************************
+--
+-- Extension constants
+--
+-- **************************************************************
+
+-- **************************************************************
+--
+-- Lists
+--
+-- **************************************************************
+
+maxNrOfErrors INTEGER ::= 256
+maxnoofCellID INTEGER ::= 65535
+maxnoofCellinEAI INTEGER ::= 65535
+maxnoofCellinTAI INTEGER ::= 65535
+maxNrOfTAIs INTEGER ::= 65535
+maxnoofEmergencyAreaID INTEGER ::= 65535
+maxnoofTAIforWarning INTEGER ::= 65535
+
+maxProtocolExtensions INTEGER ::= 65535
+maxProtocolIEs INTEGER ::= 65535
+maxnoofeNBIds INTEGER ::= 256
+maxnoofRestartedCells INTEGER ::= 256
+maxnoofRestartTAIs INTEGER ::= 2048
+maxnoofRestartEAIs INTEGER ::= 256
+maxnoofFailedCells INTEGER ::= 256
+maxnoof5GSTAIs INTEGER ::= 2048
+maxnoofCellsingNB INTEGER ::= 16384
+maxnoofCellsin5GS INTEGER ::= 16776960
+maxnoofCellsin5GSTAI INTEGER ::= 65535
+maxnoofRANNodes INTEGER ::= 65535
+maxnoofRestart5GSTAIs INTEGER ::= 2048maxnoofCellsforRestartNR INTEGER ::= 16384
+
+
+END
diff --git a/library/sbcap/SBC_AP_Containers.asn b/library/sbcap/SBC_AP_Containers.asn
new file mode 100644
index 00000000..8b71821c
--- /dev/null
+++ b/library/sbcap/SBC_AP_Containers.asn
@@ -0,0 +1,121 @@
+-- SBC-AP-Containers.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.8 Container Definitions
+--
+
+-- **************************************************************
+--
+-- Container definitions
+--
+-- **************************************************************
+
+SBC-AP-Containers {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-Containers (5)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+ Criticality,
+ Presence,
+ ProtocolExtensionID,
+ ProtocolIE-ID
+FROM SBC-AP-CommonDataTypes
+
+ maxProtocolExtensions,
+ maxProtocolIEs
+FROM SBC-AP-Constants;
+
+-- **************************************************************
+--
+-- Class Definition for Protocol IEs
+--
+-- **************************************************************
+
+SBC-AP-PROTOCOL-IES ::= CLASS {
+ &id ProtocolIE-ID UNIQUE,
+ &criticality Criticality DEFAULT ignore,
+ &Value,
+ &presence Presence
+}
+WITH SYNTAX {
+ ID &id
+ CRITICALITY &criticality
+ TYPE &Value
+ PRESENCE &presence
+}
+
+-- **************************************************************
+--
+-- Class Definition for Protocol Extensions
+--
+-- **************************************************************
+
+SBC-AP-PROTOCOL-EXTENSION ::= CLASS {
+ &id ProtocolExtensionID UNIQUE,
+ &criticality Criticality DEFAULT ignore,
+ &Extension,
+ &presence Presence
+}
+WITH SYNTAX {
+ ID &id
+ CRITICALITY &criticality
+ EXTENSION &Extension
+ PRESENCE &presence
+}
+
+-- **************************************************************
+--
+-- Container for Protocol IEs
+--
+-- **************************************************************
+
+ProtocolIE-Container {SBC-AP-PROTOCOL-IES : IEsSetParam} ::=
+ SEQUENCE (SIZE (0..maxProtocolIEs)) OF
+ ProtocolIE-Field {{IEsSetParam}}
+
+ProtocolIE-Field {SBC-AP-PROTOCOL-IES : IEsSetParam} ::= SEQUENCE {
+ id SBC-AP-PROTOCOL-IES.&id ({IEsSetParam}),
+ criticality SBC-AP-PROTOCOL-IES.&criticality ({IEsSetParam}{@id}),
+ value SBC-AP-PROTOCOL-IES.&Value ({IEsSetParam}{@id})
+}
+
+-- **************************************************************
+--
+-- Container Lists for Protocol IE Containers
+--
+-- **************************************************************
+
+ProtocolIE-ContainerList {INTEGER : lowerBound, INTEGER : upperBound, SBC-AP-PROTOCOL-IES : IEsSetParam} ::=
+ SEQUENCE (SIZE (lowerBound..upperBound)) OF
+ ProtocolIE-Container {{IEsSetParam}}
+
+-- **************************************************************
+--
+-- Container for Protocol Extensions
+--
+-- **************************************************************
+
+ProtocolExtensionContainer {SBC-AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::=
+ SEQUENCE (SIZE (1..maxProtocolExtensions)) OF
+ ProtocolExtensionField {{ExtensionSetParam}}
+
+ProtocolExtensionField {SBC-AP-PROTOCOL-EXTENSION : ExtensionSetParam} ::= SEQUENCE {
+ id SBC-AP-PROTOCOL-EXTENSION.&id ({ExtensionSetParam}),
+ criticality SBC-AP-PROTOCOL-EXTENSION.&criticality ({ExtensionSetParam}{@id}),
+ extensionValue SBC-AP-PROTOCOL-EXTENSION.&Extension ({ExtensionSetParam}{@id})
+}
+
+
+END
diff --git a/library/sbcap/SBC_AP_EncDec.cc b/library/sbcap/SBC_AP_EncDec.cc
new file mode 100644
index 00000000..08ee75fe
--- /dev/null
+++ b/library/sbcap/SBC_AP_EncDec.cc
@@ -0,0 +1,64 @@
+
+#include <string.h>
+#include <stdarg.h>
+#include "SBC_AP_PDU_Descriptions.hh"
+
+extern "C" {
+#include <fftranscode/transcode.h>
+}
+
+namespace SBC__AP__Types {
+
+TTCN_Module SBC__AP__EncDec("SBC_AP_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__SBC__AP__PDU(const SBC__AP__PDU__Descriptions::SBC__AP__PDU &pdu)
+{
+ uint8_t *aper_buf;
+ int aper_buf_len;
+ TTCN_Buffer TTCN_buf;
+ TTCN_buf.clear();
+
+ /* Encode from abstract data type into BER/DER */
+ pdu.encode(SBC__AP__PDU__Descriptions::SBC__AP__PDU_descr_, TTCN_buf,
+ TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+
+ aper_buf_len = fftranscode_ber2aper(FFTRANSC_T_SBCAP, &aper_buf, TTCN_buf.get_data(), TTCN_buf.get_len());
+ if (aper_buf_len < 0) {
+ TTCN_error("fftranscode failed.");
+ }
+
+ /* make octetstring from output buffer */
+ OCTETSTRING ret_val(aper_buf_len, aper_buf);
+
+ /* release dynamically-allocated output buffer */
+ fftranscode_free(aper_buf);
+
+ return ret_val;
+}
+
+SBC__AP__PDU__Descriptions::SBC__AP__PDU dec__SBC__AP__PDU(const OCTETSTRING &stream)
+{
+ uint8_t *ber_buf;
+ int ber_buf_len;
+
+ /* First, decode APER + re-encode as BER */
+ ber_buf_len = fftranscode_aper2ber(FFTRANSC_T_SBCAP, &ber_buf, (const unsigned char *)stream, stream.lengthof());
+ if (ber_buf_len < 0) {
+ TTCN_error("fftranscode failed.");
+ }
+
+ /* Then, re-encode from BER to TITAN representation */
+ SBC__AP__PDU__Descriptions::SBC__AP__PDU ret_dcc;
+ TTCN_Buffer TTCN_buf;
+ TTCN_buf.clear();
+ TTCN_buf.put_s(ber_buf_len, ber_buf);
+
+ ret_dcc.decode(SBC__AP__PDU__Descriptions::SBC__AP__PDU_descr_, TTCN_buf,
+ TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+
+ fftranscode_free(ber_buf);
+
+ return ret_dcc;
+}
+
+}
diff --git a/library/sbcap/SBC_AP_IEs.asn b/library/sbcap/SBC_AP_IEs.asn
new file mode 100644
index 00000000..3cfa8472
--- /dev/null
+++ b/library/sbcap/SBC_AP_IEs.asn
@@ -0,0 +1,650 @@
+-- SBC-AP-IEs.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.5 Information Element Definitions
+--
+
+-- **************************************************************
+--
+-- Information Element Definitions
+--
+-- **************************************************************
+
+SBC-AP-IEs {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-IEs (2)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+IMPORTS
+ maxNrOfErrors,
+ maxNrOfTAIs,
+ maxnoofTAIforWarning,
+ maxnoofCellID,
+ maxnoofEmergencyAreaID,
+
+ id-TypeOfError,
+ maxnoofCellinEAI,
+ maxnoofCellinTAI,
+ maxnoofeNBIds,
+ maxnoofRestartTAIs,
+ maxnoofRestartEAIs,
+ maxnoofRestartedCells,
+ maxnoofFailedCells,
+ maxnoof5GSTAIs,
+ maxnoofCellsingNB,
+ maxnoofCellsin5GS,
+ maxnoofCellsforRestartNR,
+ maxnoofRANNodes,
+ maxnoofRestart5GSTAIs,
+ maxnoofCellsin5GSTAI
+
+FROM SBC-AP-Constants
+
+ Criticality,
+ ProcedureCode,
+ TriggeringMessage,
+ ProtocolIE-ID
+FROM SBC-AP-CommonDataTypes
+
+ ProtocolExtensionContainer{},
+
+ SBC-AP-PROTOCOL-EXTENSION
+FROM SBC-AP-Containers;
+
+
+-- A
+
+-- B
+
+Broadcast-Scheduled-Area-List ::= SEQUENCE {
+ cellId-Broadcast-List CellId-Broadcast-List OPTIONAL,
+ tAI-Broadcast-List TAI-Broadcast-List OPTIONAL,
+ emergencyAreaID-Broadcast-List EmergencyAreaID-Broadcast-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer {{Broadcast-Scheduled-Area-List-ExtIEs}} OPTIONAL,
+ ...
+}
+
+Broadcast-Scheduled-Area-List-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Broadcast-Scheduled-Area-List-5GS ::= SEQUENCE {
+ cellId-Broadcast-List-5GS CellId-Broadcast-List-5GS OPTIONAL,
+ tAI-Broadcast-List-5GS TAI-Broadcast-List-5GS OPTIONAL,
+ emergencyAreaID-Broadcast-List EmergencyAreaID-Broadcast-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer {{Broadcast-Scheduled-Area-List-5GS-ExtIEs}} OPTIONAL,
+ ...
+}
+
+Broadcast-Scheduled-Area-List-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Broadcast-Cancelled-Area-List ::= SEQUENCE {
+ cellID-Cancelled-List CellID-Cancelled-List OPTIONAL,
+ tAI-Cancelled-List TAI-Cancelled-List OPTIONAL,
+ emergencyAreaID-Cancelled-List EmergencyAreaID-Cancelled-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer {{Broadcast-Cancelled-Area-List-ExtIEs}} OPTIONAL,
+ ...
+}
+
+Broadcast-Cancelled-Area-List-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Broadcast-Cancelled-Area-List-5GS ::= SEQUENCE {
+ cellID-Cancelled-List-5GS CellID-Cancelled-List-5GS OPTIONAL,
+ tAI-Cancelled-List-5GS TAI-Cancelled-List-5GS OPTIONAL,
+ emergencyAreaID-Cancelled-List EmergencyAreaID-Cancelled-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer {{Broadcast-Cancelled-Area-List-5GS-ExtIEs}} OPTIONAL,
+ ...
+}
+
+Broadcast-Cancelled-Area-List-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+Broadcast-Empty-Area-List ::= SEQUENCE (SIZE (1.. maxnoofeNBIds)) OF Global-ENB-ID
+
+Broadcast-Empty-Area-List-5GS ::= SEQUENCE (SIZE (1.. maxnoofRANNodes)) OF Global-RAN-Node-ID
+
+
+-- C
+
+CancelledCellinEAI ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF CancelledCellinEAI-Item
+
+CancelledCellinEAI-Item ::= SEQUENCE {
+ eCGI EUTRAN-CGI,
+ numberOfBroadcasts NumberOfBroadcasts,
+ iE-Extensions ProtocolExtensionContainer { {CancelledCellinEAI-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CancelledCellinEAI-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+CancelledCellinTAI ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF CancelledCellinTAI-Item
+
+CancelledCellinTAI-Item ::= SEQUENCE{
+ eCGI EUTRAN-CGI,
+ numberOfBroadcasts NumberOfBroadcasts,
+ iE-Extensions ProtocolExtensionContainer { {CancelledCellinTAI-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CancelledCellinTAI-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+CancelledCellinTAI-5GS ::= SEQUENCE (SIZE(1..maxnoofCellsin5GSTAI)) OF
+ SEQUENCE{
+ nR-CGI NR-CGI,
+ numberOfBroadcasts NumberOfBroadcasts,
+ iE-Extensions ProtocolExtensionContainer { {CancelledCellinTAI-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CancelledCellinTAI-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Cause ::= INTEGER {
+ message-accepted (0),
+ parameter-not-recognised (1),
+ parameter-value-invalid (2),
+ valid-message-not-identified (3),
+ tracking-area-not-valid (4),
+ unrecognised-message (5),
+ missing-mandatory-element (6),
+ mME-capacity-exceeded (7),
+ mME-memory-exceeded (8),
+ warning-broadcast-not-supported (9),
+ warning-broadcast-not-operational (10),
+ message-reference-already-used (11),
+ unspecifed-error (12),
+ transfer-syntax-error (13),
+ semantic-error (14),
+ message-not-compatible-with-receiver-state (15),
+ abstract-syntax-error-reject (16),
+ abstract-syntax-error-ignore-and-notify (17),
+ abstract-syntax-error-falsely-constructed-message (18)
+} (0..255)
+
+CellId-Broadcast-List ::= SEQUENCE (SIZE(1..maxnoofCellID)) OF CellId-Broadcast-List-Item
+
+CellId-Broadcast-List-Item ::= SEQUENCE {
+ eCGI EUTRAN-CGI,
+ iE-Extensions ProtocolExtensionContainer { {CellId-Broadcast-List-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CellId-Broadcast-List-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+CellId-Broadcast-List-5GS ::= SEQUENCE (SIZE(1..maxnoofCellsin5GS)) OF
+ SEQUENCE {
+ nR-CGI NR-CGI,
+ iE-Extensions ProtocolExtensionContainer { {CellId-Broadcast-List-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CellId-Broadcast-List-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+CellID-Cancelled-List ::= SEQUENCE (SIZE(1..maxnoofCellID)) OF CellID-Cancelled-Item
+
+CellID-Cancelled-Item ::= SEQUENCE {
+ eCGI EUTRAN-CGI,
+ numberOfBroadcasts NumberOfBroadcasts,
+ iE-Extensions ProtocolExtensionContainer { {CellID-Cancelled-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CellID-Cancelled-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+CellID-Cancelled-List-5GS ::= SEQUENCE (SIZE(1..maxnoofCellsin5GS)) OF
+ SEQUENCE {
+ nR-CGI NR-CGI,
+ numberOfBroadcasts NumberOfBroadcasts,
+ iE-Extensions ProtocolExtensionContainer { {CellID-Cancelled-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CellID-Cancelled-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+
+CellIdentity ::= BIT STRING (SIZE (28))
+
+Concurrent-Warning-Message-Indicator ::= ENUMERATED {true}
+
+Criticality-Diagnostics ::= SEQUENCE {
+ procedureCode ProcedureCode OPTIONAL,
+ triggeringMessage TriggeringMessage OPTIONAL,
+ procedureCriticality Criticality OPTIONAL,
+ iE-CriticalityDiagnostics CriticalityDiagnostics-IE-List OPTIONAL,
+ iE-Extensions ProtocolExtensionContainer { {CriticalityDiagnostics-ExtIEs} } OPTIONAL,
+ ...
+}
+
+CriticalityDiagnostics-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+CriticalityDiagnostics-IE-List ::= SEQUENCE (SIZE (1..maxNrOfErrors)) OF
+ SEQUENCE {
+ iECriticality Criticality,
+ iE-ID ProtocolIE-ID,
+ typeOfError TypeOfError,
+ iE-Extensions ProtocolExtensionContainer {{CriticalityDiagnostics-IE-Item-ExtIEs}} OPTIONAL,
+ ...
+}
+
+CriticalityDiagnostics-IE-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+
+-- D
+
+Data-Coding-Scheme ::= BIT STRING (SIZE (8))
+
+-- E
+
+ECGIList ::= SEQUENCE (SIZE(1..maxnoofCellID)) OF EUTRAN-CGI
+
+Emergency-Area-ID-List ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF Emergency-Area-ID
+
+Emergency-Area-ID ::= OCTET STRING (SIZE (3))
+
+EmergencyAreaID-Broadcast-List ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaID-Broadcast-List-Item
+
+EmergencyAreaID-Broadcast-List-Item ::= SEQUENCE {
+ emergencyAreaID Emergency-Area-ID,
+ scheduledCellinEAI ScheduledCellinEAI,
+ iE-Extensions ProtocolExtensionContainer { {EmergencyAreaID-Broadcast-List-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+EmergencyAreaID-Broadcast-List-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+EmergencyAreaID-Cancelled-List ::= SEQUENCE (SIZE(1..maxnoofEmergencyAreaID)) OF EmergencyAreaID-Cancelled-Item
+
+EmergencyAreaID-Cancelled-Item ::= SEQUENCE {
+ emergencyAreaID Emergency-Area-ID,
+ cancelledCellinEAI CancelledCellinEAI,
+ iE-Extensions ProtocolExtensionContainer { {EmergencyAreaID-Cancelled-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+EmergencyAreaID-Cancelled-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+EUTRAN-CGI ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ cell-ID CellIdentity,
+ iE-Extensions ProtocolExtensionContainer { {EUTRAN-CGI-ExtIEs} } OPTIONAL,
+ ...
+}
+
+EUTRAN-CGI-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Extended-Repetition-Period ::= INTEGER (4096..131071)
+
+ENB-ID ::= CHOICE {
+ macroENB-ID BIT STRING (SIZE(20)),
+ homeENB-ID BIT STRING (SIZE(28)),
+ ...,
+ short-macroENB-ID BIT STRING (SIZE(18)),
+ long-macroENB-ID BIT STRING (SIZE(21))
+}
+
+
+-- F
+
+Failed-Cell-List ::= SEQUENCE (SIZE(1..maxnoofFailedCells)) OF EUTRAN-CGI
+
+Failed-Cell-List-NR ::= SEQUENCE (SIZE(1..maxnoofCellsingNB)) OF NR-CGI
+
+-- G
+
+Global-ENB-ID ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ eNB-ID ENB-ID,
+ iE-Extensions ProtocolExtensionContainer { {GlobalENB-ID-ExtIEs} } OPTIONAL,
+ ...
+}
+
+GlobalENB-ID-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Global-RAN-Node-ID ::= CHOICE {
+ global-GNB-ID Global-GNB-ID,
+ global-NgENB-ID Global-NgENB-ID,
+ ...
+}
+
+Global-GNB-ID ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ gNB-ID GNB-ID,
+ iE-Extensions ProtocolExtensionContainer { {Global-GNB-ID-ExtIEs} } OPTIONAL,
+ ...
+}
+
+Global-GNB-ID-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+GNB-ID ::= CHOICE {
+ gNB-ID BIT STRING (SIZE(22..32)),
+ ...
+}
+Global-NgENB-ID ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ ngENB-ID ENB-ID,
+ iE-Extensions ProtocolExtensionContainer { {Global-NgENB-ID-ExtIEs} } OPTIONAL,
+ ...
+}
+
+Global-NgENB-ID-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+
+-- H
+
+-- I
+
+-- J
+
+-- K
+
+-- L
+
+List-of-TAIs ::= SEQUENCE (SIZE (1..maxNrOfTAIs)) OF
+ SEQUENCE {
+ tai TAI
+}
+
+List-of-TAIs-Restart ::= SEQUENCE (SIZE (1..maxnoofRestartTAIs)) OF
+ SEQUENCE {
+ tai TAI
+}
+
+
+List-of-EAIs-Restart ::= SEQUENCE (SIZE(1..maxnoofRestartEAIs)) OF Emergency-Area-ID
+
+List-of-5GS-TAIs ::= SEQUENCE (SIZE (1..maxnoof5GSTAIs)) OF TAI-5GS
+
+List-of-5GS-Cells-for-Failure ::= SEQUENCE ( SIZE(1..maxnoofCellsingNB)) OF NR-CGI
+
+List-of-5GS-TAI-for-Restart ::= SEQUENCE (SIZE (1..maxnoofRestart5GSTAIs)) OF TAI-5GS
+
+
+-- M
+
+Message-Identifier ::= BIT STRING (SIZE (16))
+
+-- N
+
+Number-of-Broadcasts-Requested ::= INTEGER (0..65535)
+
+-- For Number-of-Broadcasts-Requested = 0 and Repetition-Period = 0, then eNB action is no broadcast
+-- for ETWS Secondary and CMAS.
+--
+-- For Number-of-Broadcasts-Requested = 1 and Repetition-Period = 0, then eNB action is broadcast
+-- only once for ETWS and CMAS.
+--
+-- For Number-of-Broadcasts-Requested = 0 and Repetition-Period > 0, then eNB action is no broadcast
+-- for the ETWS Secondary, and broadcast until further notice for the CMAS.
+--
+-- For Number-of-Broadcasts-Requested > 0 and Repetition-Period > 0, then eNB action is normal
+-- broadcast.
+-- All other combinations of Number-of-Broadcasts-Requested and Repetition-Period are considered
+-- invalid.
+
+NumberOfBroadcasts ::= INTEGER (0..65535)
+
+NR-CGIList ::= SEQUENCE (SIZE(1..maxnoofCellsingNB)) OF NR-CGI
+
+NR-CGI ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ nRCellIdentity NRCellIdentity,
+ iE-Extensions ProtocolExtensionContainer { {NR-CGI-ExtIEs} } OPTIONAL,
+ ...
+}
+
+NR-CGI-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+NRCellIdentity ::= BIT STRING (SIZE(36))
+
+NgENB-ID ::= CHOICE {
+ macroNgENB-ID BIT STRING (SIZE(20)),
+ shortMacroNgENB-ID BIT STRING (SIZE(18)),
+ longMacroNgENB-ID BIT STRING (SIZE(21)),
+ ...
+}
+
+-- O
+Omc-Id ::= OCTET STRING (SIZE (1..20))
+
+
+-- P
+PLMNidentity ::= TBCD-STRING
+
+-- Q
+
+-- R
+
+Repetition-Period ::= INTEGER (0..4096)
+-- 1 to 4096: Each unit represents a repetition of one second to a maximum of
+-- once per 4096 seconds (~1 hour).
+-- 0: no repetition
+-- A CBC compliant to this version or later of this specification shall not send a repetition period
+-- greater than 4095.
+-- For backwards compatibility with a CBC compliant to an earlier version of this specification the
+-- maximum value of the repetition period defined in ASN.1 remains at 4096.
+-- If the value of the Repetition Period IE received in the WRITE-REPLACE WARNING REQUEST message is
+-- set to 4096, the MME shall set the Repetition Period IE to the maximum value 4095 supported on
+-- the S1-MME interface as defined in [7] before forwarding to the selected eNBs.
+
+Restarted-Cell-List ::= SEQUENCE (SIZE(1.. maxnoofRestartedCells)) OF EUTRAN-CGI
+
+RAT-Selector-5GS ::= ENUMERATED {true}
+
+Restarted-Cell-List-NR ::= SEQUENCE (SIZE(1.. maxnoofCellsforRestartNR)) OF NR-CGI
+
+
+
+-- S
+
+ScheduledCellinEAI ::= SEQUENCE (SIZE(1..maxnoofCellinEAI)) OF ScheduledCellinEAI-Item
+
+ScheduledCellinEAI-Item ::= SEQUENCE {
+ eCGI EUTRAN-CGI,
+ iE-Extensions ProtocolExtensionContainer { {ScheduledCellinEAI-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+ScheduledCellinEAI-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+ScheduledCellinTAI ::= SEQUENCE (SIZE(1..maxnoofCellinTAI)) OF ScheduledCellinTAI-Item
+
+ScheduledCellinTAI-Item ::= SEQUENCE{
+ eCGI EUTRAN-CGI,
+ iE-Extensions ProtocolExtensionContainer { {ScheduledCellinTAI-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+ScheduledCellinTAI-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+ScheduledCellinTAI-5GS ::= SEQUENCE (SIZE(1..maxnoofCellsin5GSTAI)) OF
+ SEQUENCE{
+ nR-CGI NR-CGI,
+ iE-Extensions ProtocolExtensionContainer { {ScheduledCellinTAI-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+ScheduledCellinTAI-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+Send-Write-Replace-Warning-Indication ::= ENUMERATED {true}
+
+Send-Stop-Warning-Indication ::= ENUMERATED {true}
+
+Serial-Number ::= BIT STRING (SIZE (16))
+
+Stop-All-Indicator ::= ENUMERATED {true}
+
+-- T
+
+TAC ::= OCTET STRING (SIZE (2))
+
+TAC-5GS ::= OCTET STRING (SIZE (3))
+
+TAI-Broadcast-List ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAI-Broadcast-List-Item
+
+TAI-Broadcast-List-Item ::= SEQUENCE {
+ tAI TAI,
+ scheduledCellinTAI ScheduledCellinTAI,
+ iE-Extensions ProtocolExtensionContainer { {TAI-Broadcast-List-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+TAI-Broadcast-List-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+TAI-Broadcast-List-5GS ::= SEQUENCE (SIZE(1..maxnoof5GSTAIs)) OF
+ SEQUENCE {
+ tAI-5GS TAI-5GS,
+ scheduledCellinTAI-5GS ScheduledCellinTAI-5GS,
+ iE-Extensions ProtocolExtensionContainer { {TAI-Broadcast-List-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+TAI-Broadcast-List-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+TAI-Cancelled-List ::= SEQUENCE (SIZE(1..maxnoofTAIforWarning)) OF TAI-Cancelled-List-Item
+
+TAI-Cancelled-List-Item ::= SEQUENCE {
+ tAI TAI,
+ cancelledCellinTAI CancelledCellinTAI,
+ iE-Extensions ProtocolExtensionContainer { {TAI-Cancelled-List-Item-ExtIEs} } OPTIONAL,
+ ...
+}
+
+TAI-Cancelled-List-Item-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+TAI-Cancelled-List-5GS ::= SEQUENCE (SIZE(1..maxnoof5GSTAIs)) OF
+ SEQUENCE {
+ tAI-5GS TAI-5GS,
+ cancelledCellinTAI-5GS CancelledCellinTAI-5GS,
+ iE-Extensions ProtocolExtensionContainer { {TAI-Cancelled-List-5GS-ExtIEs} } OPTIONAL,
+ ...
+}
+
+TAI-Cancelled-List-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+TAI-List-for-Warning ::= SEQUENCE (SIZE(1.. maxnoofTAIforWarning)) OF TAI
+
+TAI ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ tAC TAC,
+ iE-Extensions ProtocolExtensionContainer { {TAI-ExtIEs} } OPTIONAL
+}
+
+TAI-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+TBCD-STRING ::= OCTET STRING (SIZE (3))
+
+TypeOfError ::= ENUMERATED {
+ not-understood,
+ missing,
+ ...
+}
+TAI-5GS ::= SEQUENCE {
+ pLMNidentity PLMNidentity,
+ tAC-5GS TAC-5GS,
+ iE-Extensions ProtocolExtensionContainer { {TAI-5GS-ExtIEs} } OPTIONAL
+}
+
+TAI-5GS-ExtIEs SBC-AP-PROTOCOL-EXTENSION ::= {
+ ...
+}
+
+
+-- U
+
+Unknown-Tracking-Area-List ::= SEQUENCE (SIZE(1.. maxNrOfTAIs)) OF TAI
+
+Unknown-5GS-Tracking-Area-List ::= SEQUENCE (SIZE(1.. maxnoof5GSTAIs)) OF TAI-5GS
+
+
+-- V
+
+-- W
+
+Warning-Area-List ::= CHOICE {
+ cell-ID-List ECGIList,
+ tracking-Area-List-for-Warning TAI-List-for-Warning,
+ emergency-Area-ID-List Emergency-Area-ID-List,
+ ...
+}
+
+Warning-Message-Content ::= OCTET STRING (SIZE (1..9600))
+Warning-Area-Coordinates ::= OCTET STRING (SIZE (1..1024))
+Warning-Security-Information ::= OCTET STRING (SIZE (50))
+Warning-Type ::= OCTET STRING (SIZE (2))
+
+Warning-Area-List-5GS ::= CHOICE {
+ cell-ID-List ECGIList,
+ nR-CGIList NR-CGIList,
+ tAIList-5GS TAI-5GS,
+ emergencyAreaIDList Emergency-Area-ID-List,
+ ...
+}
+
+
+
+-- X
+
+-- Y
+
+END
diff --git a/library/sbcap/SBC_AP_PDU_Contents.asn b/library/sbcap/SBC_AP_PDU_Contents.asn
new file mode 100644
index 00000000..11174328
--- /dev/null
+++ b/library/sbcap/SBC_AP_PDU_Contents.asn
@@ -0,0 +1,374 @@
+-- SBC-AP-PDU-Contents.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.4 PDU Definitions
+--
+
+-- **************************************************************
+--
+-- PDU definitions for SBC-AP.
+--
+-- **************************************************************
+
+SBC-AP-PDU-Contents {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-PDU-Contents (1)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+
+ Cause,
+ Concurrent-Warning-Message-Indicator,
+ Criticality-Diagnostics,
+ Data-Coding-Scheme,
+ Message-Identifier,
+ Serial-Number,
+ List-of-TAIs,
+ Warning-Area-List,
+ Omc-Id,
+ Repetition-Period,
+ Extended-Repetition-Period,
+ Number-of-Broadcasts-Requested,
+ Warning-Type,
+ Warning-Security-Information,
+ Warning-Message-Content,
+ Warning-Area-Coordinates,
+ Send-Write-Replace-Warning-Indication,
+ Broadcast-Scheduled-Area-List,
+ Unknown-Tracking-Area-List,
+ Send-Stop-Warning-Indication,
+ Broadcast-Cancelled-Area-List,
+ Stop-All-Indicator,
+ Broadcast-Empty-Area-List,
+ Restarted-Cell-List,
+ Global-ENB-ID,
+ List-of-TAIs-Restart,
+ List-of-EAIs-Restart,
+ Failed-Cell-List,
+ List-of-5GS-TAIs,
+ Warning-Area-List-5GS,
+ Global-RAN-Node-ID,
+ Global-GNB-ID,
+ RAT-Selector-5GS,
+ Unknown-5GS-Tracking-Area-List,
+ Broadcast-Scheduled-Area-List-5GS,
+ Broadcast-Cancelled-Area-List-5GS,
+ Broadcast-Empty-Area-List-5GS,
+ Restarted-Cell-List-NR,
+ Failed-Cell-List-NR,
+ List-of-5GS-TAI-for-Restart
+
+FROM SBC-AP-IEs
+
+ ProtocolExtensionContainer{},
+ ProtocolIE-Container{},
+ SBC-AP-PROTOCOL-EXTENSION,
+ SBC-AP-PROTOCOL-IES
+FROM SBC-AP-Containers
+
+ id-Concurrent-Warning-Message-Indicator,
+ id-Criticality-Diagnostics,
+ id-Cause,
+ id-Data-Coding-Scheme,
+ id-List-of-TAIs,
+ id-Message-Identifier,
+ id-Serial-Number,
+ id-Number-of-Broadcasts-Requested,
+ id-Omc-Id,
+ id-Radio-Resource-Loading-List,
+ id-Recovery-Indication,
+ id-Repetition-Period,
+ id-Extended-Repetition-Period,
+ id-Warning-Area-List,
+ id-Warning-Message-Content,
+ id-Warning-Area-Coordinates,
+ id-Warning-Security-Information,
+ id-Warning-Type,
+ id-Send-Write-Replace-Warning-Indication,
+ id-Broadcast-Scheduled-Area-List,
+ id-Unknown-Tracking-Area-List,
+ id-Send-Stop-Warning-Indication,
+ id-Broadcast-Cancelled-Area-List,
+ id-Stop-All-Indicator,
+ id-Broadcast-Empty-Area-List,
+ id-Global-ENB-ID,
+ id-Restarted-Cell-List,
+ id-List-of-TAIs-Restart,
+ id-List-of-EAIs-Restart,
+ id-Failed-Cell-List,
+ id-List-of-5GS-TAIs,
+ id-Warning-Area-List-5GS,
+ id-Global-RAN-Node-ID,
+ id-Global-GNB-ID,
+ id-RAT-Selector-5GS,
+ id-Unknown-5GS-Tracking-Area-List,
+ id-Broadcast-Scheduled-Area-List-5GS,
+ id-Broadcast-Cancelled-Area-List-5GS,
+ id-Broadcast-Empty-Area-List-5GS,
+ id-Restarted-Cell-List-NR,
+ id-Failed-Cell-List-NR,
+ id-List-of-5GS-TAI-for-Restart
+
+FROM SBC-AP-Constants;
+
+-- **************************************************************
+--
+-- Write-Replace-Warning-Request
+--
+-- **************************************************************
+
+Write-Replace-Warning-Request ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Write-Replace-Warning-Request-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Write-Replace-Warning-Request-Extensions} } OPTIONAL,
+ ...
+}
+
+Write-Replace-Warning-Request-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-List-of-TAIs CRITICALITY reject TYPE List-of-TAIs PRESENCE optional } |
+ { ID id-Warning-Area-List CRITICALITY ignore TYPE Warning-Area-List PRESENCE optional } |
+ { ID id-Repetition-Period CRITICALITY reject TYPE Repetition-Period PRESENCE mandatory } |
+ { ID id-Extended-Repetition-Period CRITICALITY reject TYPE Extended-Repetition-Period PRESENCE optional } |
+
+ { ID id-Number-of-Broadcasts-Requested
+ CRITICALITY reject TYPE Number-of-Broadcasts-Requested PRESENCE mandatory } |
+ { ID id-Warning-Type CRITICALITY ignore TYPE Warning-Type PRESENCE optional } |
+ { ID id-Warning-Security-Information CRITICALITY ignore TYPE Warning-Security-Information PRESENCE optional } |
+ { ID id-Data-Coding-Scheme CRITICALITY ignore TYPE Data-Coding-Scheme PRESENCE optional } |
+ { ID id-Warning-Message-Content
+ CRITICALITY ignore TYPE Warning-Message-Content PRESENCE optional } |
+ { ID id-Omc-Id CRITICALITY ignore TYPE Omc-Id PRESENCE optional } |
+ { ID id-Concurrent-Warning-Message-Indicator CRITICALITY reject TYPE Concurrent-Warning-Message-Indicator PRESENCE optional } |
+ { ID id-Send-Write-Replace-Warning-Indication CRITICALITY ignore TYPE Send-Write-Replace-Warning-Indication PRESENCE optional } |
+ { ID id-Global-ENB-ID CRITICALITY ignore TYPE Global-ENB-ID PRESENCE optional },
+ ... ,
+ {ID id-Warning-Area-Coordinates CRITICALITY ignore TYPE Warning-Area-Coordinates PRESENCE optional}
+}
+
+Write-Replace-Warning-Request-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-List-of-5GS-TAIs CRITICALITY ignore EXTENSION List-of-5GS-TAIs PRESENCE optional }|
+ { ID id-Warning-Area-List-5GS CRITICALITY ignore EXTENSION Warning-Area-List-5GS PRESENCE optional }|
+ { ID id-Global-RAN-Node-ID CRITICALITY ignore EXTENSION Global-RAN-Node-ID PRESENCE optional }|
+ { ID id-RAT-Selector-5GS CRITICALITY ignore EXTENSION RAT-Selector-5GS PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- Write-Replace-Warning-Response
+--
+-- **************************************************************
+
+Write-Replace-Warning-Response ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Write-Replace-Warning-Response-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Write-Replace-Warning-Response-Extensions} } OPTIONAL,
+ ...
+}
+
+Write-Replace-Warning-Response-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-Cause CRITICALITY reject TYPE Cause PRESENCE mandatory } |
+ { ID id-Criticality-Diagnostics CRITICALITY ignore TYPE Criticality-Diagnostics PRESENCE optional } |
+ { ID id-Unknown-Tracking-Area-List CRITICALITY ignore TYPE List-of-TAIs PRESENCE optional },
+ ...
+}
+
+Write-Replace-Warning-Response-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Unknown-5GS-Tracking-Area-List CRITICALITY ignore EXTENSION Unknown-5GS-Tracking-Area-List PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- Stop-Warning-Request
+--
+-- **************************************************************
+
+Stop-Warning-Request ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Stop-Warning-Request-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Stop-Warning-Request-Extensions} } OPTIONAL,
+ ...
+}
+
+Stop-Warning-Request-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-List-of-TAIs CRITICALITY reject TYPE List-of-TAIs PRESENCE optional } |
+ { ID id-Warning-Area-List CRITICALITY ignore TYPE Warning-Area-List PRESENCE optional }|
+ { ID id-Omc-Id CRITICALITY ignore TYPE Omc-Id PRESENCE optional } |
+ { ID id-Send-Stop-Warning-Indication CRITICALITY ignore TYPE Send-Stop-Warning-Indication PRESENCE optional } |
+ { ID id-Stop-All-Indicator CRITICALITY reject TYPE Stop-All-Indicator PRESENCE optional},
+ ...
+}
+
+Stop-Warning-Request-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-List-of-5GS-TAIs CRITICALITY ignore EXTENSION List-of-5GS-TAIs PRESENCE optional }|
+ { ID id-Warning-Area-List-5GS CRITICALITY ignore EXTENSION Warning-Area-List-5GS PRESENCE optional } | { ID id-RAT-Selector-5GS CRITICALITY ignore EXTENSION RAT-Selector-5GS PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- Stop-Warning-Response
+--
+-- **************************************************************
+
+Stop-Warning-Response ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Stop-Warning-Response-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Stop-Warning-Response-Extensions} } OPTIONAL,
+ ...
+}
+
+Stop-Warning-Response-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-Cause CRITICALITY reject TYPE Cause PRESENCE mandatory } |
+ { ID id-Criticality-Diagnostics CRITICALITY ignore TYPE Criticality-Diagnostics PRESENCE optional } |
+ { ID id-Unknown-Tracking-Area-List CRITICALITY ignore TYPE List-of-TAIs PRESENCE optional },
+ ...
+}
+
+Stop-Warning-Response-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Unknown-5GS-Tracking-Area-List CRITICALITY ignore EXTENSION Unknown-5GS-Tracking-Area-List PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- Write-Replace-Warning-Indication
+--
+-- **************************************************************
+
+Write-Replace-Warning-Indication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Write-Replace-Warning-Indication-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Write-Replace-Warning-Indication-Extensions} } OPTIONAL,
+ ...
+}
+
+Write-Replace-Warning-Indication-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-Broadcast-Scheduled-Area-List CRITICALITY reject TYPE Broadcast-Scheduled-Area-List PRESENCE optional },
+ ...
+}
+
+Write-Replace-Warning-Indication-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Broadcast-Scheduled-Area-List-5GS CRITICALITY ignore EXTENSION Broadcast-Scheduled-Area-List-5GS PRESENCE optional },
+
+ ...
+}
+
+-- **************************************************************
+--
+-- Stop-Warning-Indication
+--
+-- **************************************************************
+
+Stop-Warning-Indication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {Stop-Warning-Indication-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {Stop-Warning-Indication-Extensions} } OPTIONAL,
+ ...
+}
+
+Stop-Warning-Indication-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Message-Identifier CRITICALITY reject TYPE Message-Identifier PRESENCE mandatory } |
+ { ID id-Serial-Number CRITICALITY reject TYPE Serial-Number PRESENCE mandatory } |
+ { ID id-Broadcast-Cancelled-Area-List CRITICALITY reject TYPE Broadcast-Cancelled-Area-List PRESENCE optional }|
+ { ID id-Broadcast-Empty-Area-List CRITICALITY ignore TYPE Broadcast-Empty-Area-List PRESENCE optional },
+ ...
+}
+
+Stop-Warning-Indication-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Broadcast-Cancelled-Area-List-5GS CRITICALITY ignore EXTENSION Broadcast-Cancelled-Area-List-5GS PRESENCE optional }|
+ { ID id-Broadcast-Empty-Area-List-5GS CRITICALITY ignore EXTENSION Broadcast-Empty-Area-List-5GS PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- PWS-Restart-Indication
+--
+-- **************************************************************
+
+PWS-Restart-Indication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {PWS-Restart-Indication-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {PWS-Restart-Indication-Extensions} } OPTIONAL,
+ ...
+}
+
+PWS-Restart-Indication-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Restarted-Cell-List CRITICALITY reject TYPE Restarted-Cell-List PRESENCE mandatory }|
+ { ID id-Global-ENB-ID CRITICALITY reject TYPE Global-ENB-ID PRESENCE mandatory } |
+ { ID id-List-of-TAIs-Restart CRITICALITY reject TYPE List-of-TAIs-Restart PRESENCE mandatory } |
+ { ID id-List-of-EAIs-Restart CRITICALITY reject TYPE List-of-EAIs-Restart PRESENCE optional },
+ ...
+}
+
+PWS-Restart-Indication-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Restarted-Cell-List-NR CRITICALITY ignore EXTENSION Restarted-Cell-List-NR PRESENCE optional }|
+ { ID id-List-of-5GS-TAI-for-Restart CRITICALITY ignore EXTENSION List-of-5GS-TAI-for-Restart PRESENCE optional }|
+{ ID id-Global-GNB-ID CRITICALITY ignore EXTENSION Global-GNB-ID PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- PWS-Failure-Indication
+--
+-- **************************************************************
+
+PWS-Failure-Indication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container { {PWS-Failure-Indication-IEs} },
+ protocolExtensions ProtocolExtensionContainer { {PWS-Failure-Indication-Extensions} } OPTIONAL,
+ ...
+}
+
+PWS-Failure-Indication-IEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Failed-Cell-List CRITICALITY reject TYPE Failed-Cell-List PRESENCE mandatory }|
+ { ID id-Global-ENB-ID CRITICALITY reject TYPE Global-ENB-ID PRESENCE mandatory },
+ ...
+}
+
+PWS-Failure-Indication-Extensions SBC-AP-PROTOCOL-EXTENSION ::= {
+ { ID id-Failed-Cell-List-NR CRITICALITY ignore EXTENSION Failed-Cell-List-NR PRESENCE optional }|
+ { ID id-Global-GNB-ID CRITICALITY ignore EXTENSION Global-GNB-ID PRESENCE optional },
+ ...
+}
+
+-- **************************************************************
+--
+-- ERROR INDICATION ELEMENTARY PROCEDURE
+--
+-- **************************************************************
+
+-- **************************************************************
+--
+-- Error Indication
+--
+-- **************************************************************
+
+Error-Indication ::= SEQUENCE {
+ protocolIEs ProtocolIE-Container {{ErrorIndicationIEs}},
+ ...
+}
+
+ErrorIndicationIEs SBC-AP-PROTOCOL-IES ::= {
+ { ID id-Cause CRITICALITY ignore TYPE Cause PRESENCE optional } |
+ { ID id-Criticality-Diagnostics CRITICALITY ignore TYPE Criticality-Diagnostics PRESENCE optional } ,
+ ...
+}
+
+END
diff --git a/library/sbcap/SBC_AP_PDU_Descriptions.asn b/library/sbcap/SBC_AP_PDU_Descriptions.asn
new file mode 100644
index 00000000..fbb80d53
--- /dev/null
+++ b/library/sbcap/SBC_AP_PDU_Descriptions.asn
@@ -0,0 +1,179 @@
+-- SBC-AP-PDU-Descriptions.asn
+--
+-- Taken from 3GPP TS 29.168 V15.1.0 (2018-09)
+-- http://www.3gpp.org/ftp/Specs/archive/29_series/29.168/29168-930.zip
+--
+-- 4.4.3 Elementary Procedure Definitions
+--
+
+-- **************************************************************
+--
+-- Elementary Procedure definitions
+--
+-- **************************************************************
+
+SBC-AP-PDU-Descriptions {
+itu-t (0) identified-organization (4) etsi (0) mobileDomain (0)
+eps-Access (21) modules (3) sbc-AP (3) version1 (1) sbc-AP-PDU-Descriptions (0)}
+
+DEFINITIONS AUTOMATIC TAGS ::=
+
+BEGIN
+
+-- **************************************************************
+--
+-- IE parameter types from other modules.
+--
+-- **************************************************************
+
+IMPORTS
+ Criticality,
+ ProcedureCode
+FROM SBC-AP-CommonDataTypes
+
+ Write-Replace-Warning-Request,
+ Write-Replace-Warning-Response,
+ Stop-Warning-Request,
+ Stop-Warning-Response,
+ Error-Indication,
+ Write-Replace-Warning-Indication,
+ Stop-Warning-Indication,
+ PWS-Restart-Indication,
+ PWS-Failure-Indication
+FROM SBC-AP-PDU-Contents
+
+ id-Write-Replace-Warning,
+ id-Stop-Warning,
+ id-Error-Indication,
+ id-Write-Replace-Warning-Indication,
+ id-Stop-Warning-Indication,
+ id-PWS-Restart-Indication,
+ id-PWS-Failure-Indication
+FROM SBC-AP-Constants;
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure Class
+--
+-- **************************************************************
+
+SBC-AP-ELEMENTARY-PROCEDURE ::= CLASS {
+ &InitiatingMessage ,
+ &SuccessfulOutcome OPTIONAL,
+ &UnsuccessfulOutcome OPTIONAL,
+ &procedureCode ProcedureCode UNIQUE,
+ &criticality Criticality DEFAULT ignore
+}
+WITH SYNTAX {
+ INITIATING MESSAGE &InitiatingMessage
+ [SUCCESSFUL OUTCOME &SuccessfulOutcome]
+ [UNSUCCESSFUL OUTCOME &UnsuccessfulOutcome]
+ PROCEDURE CODE &procedureCode
+ [CRITICALITY &criticality]
+}
+
+-- **************************************************************
+--
+-- Interface PDU Definition
+--
+-- **************************************************************
+
+SBC-AP-PDU ::= CHOICE {
+ initiatingMessage InitiatingMessage,
+ successfulOutcome SuccessfulOutcome,
+ unsuccessfulOutcome UnsuccessfulOutcome,
+ ...
+}
+
+InitiatingMessage ::= SEQUENCE {
+ procedureCode SBC-AP-ELEMENTARY-PROCEDURE.&procedureCode ({SBC-AP-ELEMENTARY-PROCEDURES}),
+ criticality SBC-AP-ELEMENTARY-PROCEDURE.&criticality ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value SBC-AP-ELEMENTARY-PROCEDURE.&InitiatingMessage ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+SuccessfulOutcome ::= SEQUENCE {
+ procedureCode SBC-AP-ELEMENTARY-PROCEDURE.&procedureCode ({SBC-AP-ELEMENTARY-PROCEDURES}),
+ criticality SBC-AP-ELEMENTARY-PROCEDURE.&criticality ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value SBC-AP-ELEMENTARY-PROCEDURE.&SuccessfulOutcome ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+UnsuccessfulOutcome ::= SEQUENCE {
+ procedureCode SBC-AP-ELEMENTARY-PROCEDURE.&procedureCode ({SBC-AP-ELEMENTARY-PROCEDURES}),
+ criticality SBC-AP-ELEMENTARY-PROCEDURE.&criticality ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode}),
+ value SBC-AP-ELEMENTARY-PROCEDURE.&UnsuccessfulOutcome ({SBC-AP-ELEMENTARY-PROCEDURES}{@procedureCode})
+}
+
+-- **************************************************************
+--
+-- Interface Elementary Procedure List
+--
+-- **************************************************************
+
+SBC-AP-ELEMENTARY-PROCEDURES SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ SBC-AP-ELEMENTARY-PROCEDURES-CLASS-1 |
+ SBC-AP-ELEMENTARY-PROCEDURES-CLASS-2 ,
+ ...
+}
+
+SBC-AP-ELEMENTARY-PROCEDURES-CLASS-1 SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ write-Replace-Warning |
+ stop-Warning ,
+ ...
+}
+
+SBC-AP-ELEMENTARY-PROCEDURES-CLASS-2 SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ error-Indication |
+ write-Replace-Warning-Indication |
+ stop-Warning-Indication |
+ pws-Restart-Indication |
+ pws-Failure-Indication,
+ ...
+ }
+
+write-Replace-Warning SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Write-Replace-Warning-Request
+ SUCCESSFUL OUTCOME Write-Replace-Warning-Response
+
+ PROCEDURE CODE id-Write-Replace-Warning
+ CRITICALITY reject
+}
+
+stop-Warning SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Stop-Warning-Request
+ SUCCESSFUL OUTCOME Stop-Warning-Response
+
+ PROCEDURE CODE id-Stop-Warning
+ CRITICALITY reject
+}
+
+error-Indication SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Error-Indication
+ PROCEDURE CODE id-Error-Indication
+ CRITICALITY ignore
+}
+
+write-Replace-Warning-Indication SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Write-Replace-Warning-Indication
+ PROCEDURE CODE id-Write-Replace-Warning-Indication
+ CRITICALITY ignore
+}
+
+stop-Warning-Indication SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE Stop-Warning-Indication
+ PROCEDURE CODE id-Stop-Warning-Indication
+ CRITICALITY ignore
+}
+
+pws-Restart-Indication SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE PWS-Restart-Indication
+ PROCEDURE CODE id-PWS-Restart-Indication
+ CRITICALITY ignore
+}
+
+pws-Failure-Indication SBC-AP-ELEMENTARY-PROCEDURE ::= {
+ INITIATING MESSAGE PWS-Failure-Indication
+ PROCEDURE CODE id-PWS-Failure-Indication
+ CRITICALITY ignore
+}
+
+END
diff --git a/library/sbcap/SBC_AP_Templates.ttcn b/library/sbcap/SBC_AP_Templates.ttcn
new file mode 100644
index 00000000..b0022868
--- /dev/null
+++ b/library/sbcap/SBC_AP_Templates.ttcn
@@ -0,0 +1,435 @@
+module SBC_AP_Templates {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from SBC_AP_IEs all;
+import from SBC_AP_Constants all;
+import from SBC_AP_Containers all;
+import from SBC_AP_PDU_Contents all;
+import from SBC_AP_PDU_Descriptions all;
+
+import from SBC_AP_Types all;
+
+/* 3GPP TS 36.413 9.2.1.38 */
+template (value) EUTRAN_CGI ts_SBCAP_ECGI(PLMNidentity plmn_id := '09F107'O, integer cell_id := 1) := {
+ pLMNidentity := plmn_id,
+ cell_ID := int2bit(cell_id, 28),
+ iE_Extensions := omit
+}
+
+/* 3GPP TS 36.413 9.2.3.16 */
+template (value) TAI ts_SBCAP_TAI(PLMNidentity plmn_id := '09F107'O, uint16_t tac := 1) := {
+ pLMNidentity := plmn_id,
+ tAC := int2oct(tac, 2),
+ iE_Extensions := omit
+}
+
+/* 3GPP TS 36.413 9.2.1.54 */
+template (value) CellId_Broadcast_List_Item ts_SBCAP_CellId_Broadcast_List_Item(
+ template (value) EUTRAN_CGI ecgi := ts_SBCAP_ECGI()) := {
+ eCGI := ecgi,
+ iE_Extensions := omit
+}
+template (value) Broadcast_Scheduled_Area_List ts_SBCAP_Broadcast_Scheduled_Area_List(
+ template (value) CellId_Broadcast_List cell_id_li := {ts_SBCAP_CellId_Broadcast_List_Item()})
+:= {
+ cellId_Broadcast_List := cell_id_li,
+ tAI_Broadcast_List := omit,
+ emergencyAreaID_Broadcast_List := omit,
+ iE_Extensions := omit
+}
+
+template (value) Global_ENB_ID ts_Global_ENB_ID_MACRO(PLMNidentity plmn_id,
+ integer macro_enb_id)
+
+:= {
+ pLMNidentity := plmn_id,
+ eNB_ID := {
+ macroENB_ID := int2bit(macro_enb_id, 20)
+ },
+ iE_Extensions := omit
+}
+
+template (value) SBC_AP_PDU
+ts_SBCAP_PWS_RESTART(
+ template (value) Restarted_Cell_List restart_cl,
+ template (value) Global_ENB_ID global_enb_id) := {
+ initiatingMessage := {
+ procedureCode := id_PWS_Restart_Indication,
+ criticality := reject,
+ value_ := {
+ PWS_Restart_Indication := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Restarted_Cell_List,
+ criticality := reject,
+ value_ := { Restarted_Cell_List := restart_cl }
+ }, {
+ id := SBC_AP_Constants.id_Global_ENB_ID,
+ criticality := reject,
+ value_ := { Global_ENB_ID := global_enb_id }
+ }
+ /* List of TAIs (mandatory) */
+ /* List of EAIs (optional) */
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (value) SBC_AP_PDU
+ts_SBCAP_PWS_FAILURE(
+ template (value) Failed_Cell_List fail_cl,
+ template (value) Global_ENB_ID global_enb_id) := {
+ initiatingMessage := {
+ procedureCode := id_PWS_Failure_Indication,
+ criticality := reject,
+ value_ := {
+ PWS_Failure_Indication := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Failed_Cell_List,
+ criticality := reject,
+ value_ := { Failed_Cell_List := fail_cl }
+ }, {
+ id := SBC_AP_Constants.id_Global_ENB_ID,
+ criticality := reject,
+ value_ := { Global_ENB_ID := global_enb_id }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.1 WRITE-REPLACE WARNING REQUEST */
+template (value) SBC_AP_PDU
+ts_SBCAP_WRITE_WARNING(template (value) BIT16 p_msg_id, template (value) BIT16 p_ser_nr,
+ template (value) uint12_t p_rep_per, template (value) uint16_t p_num_bcast,
+ template (value) OCT2 p_w_type, OCT1 p_dcs,
+ template (value) octetstring p_msg_content) := {
+ initiatingMessage := {
+ procedureCode := id_Write_Replace_Warning,
+ criticality := reject,
+ value_ := {
+ write_Replace_Warning_Request := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ /* List of TAIs */
+ /* Warning Area List */
+ }, {
+ id := SBC_AP_Constants.id_Repetition_Period,
+ criticality := reject,
+ value_ := { Repetition_Period := p_rep_per }
+ /* Extended Repetition Period */
+ }, {
+ id := SBC_AP_Constants.id_Number_of_Broadcasts_Requested,
+ criticality := reject,
+ value_ := { Number_of_Broadcasts_Requested := p_num_bcast }
+ }, {
+ id := SBC_AP_Constants.id_Warning_Type,
+ criticality := ignore,
+ value_ := { Warning_Type := p_w_type }
+ }, {
+ /* Warning Security Info */
+ /* Data Coding Scheme */
+ id := SBC_AP_Constants.id_Data_Coding_Scheme,
+ criticality := ignore,
+ value_ := { Data_Coding_Scheme := oct2bit(p_dcs) }
+ }, {
+ /* Warning Message Content */
+ id := SBC_AP_Constants.id_Warning_Message_Content,
+ criticality := ignore,
+ value_ := { Warning_Message_Content := p_msg_content }
+ }
+ /* OMC ID */
+ /* Concurrent Warning Message Indicator */
+ /* Send Write Replace Warning Indication */
+ /* Global eNB ID */
+ /* Warning Area Coordinates */
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.1 WRITE-REPLACE WARNING REQUEST */
+template (present) SBC_AP_PDU
+tr_SBCAP_WRITE_WARNING_REQ_CBS(template (present) BIT16 p_msg_id, template (present) BIT16 p_ser_nr,
+ template (present) uint12_t p_rep_per,
+ template (present) uint16_t p_num_bcast,
+ template (present) BIT8 dcs := ?,
+ template (present) octetstring p_msg_content := ?,
+ template (present) Send_Write_Replace_Warning_Indication send_ind := ?,
+ template (present) Concurrent_Warning_Message_Indicator concurrent_ind := ?
+ ) := {
+ initiatingMessage := {
+ procedureCode := id_Write_Replace_Warning,
+ criticality := reject,
+ value_ := {
+ write_Replace_Warning_Request := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ /* List of TAIs */
+ /* Warning Area List */
+ }, {
+ id := SBC_AP_Constants.id_Repetition_Period,
+ criticality := reject,
+ value_ := { Repetition_Period := p_rep_per }
+ /* Extended Repetition Period */
+ }, {
+ id := SBC_AP_Constants.id_Number_of_Broadcasts_Requested,
+ criticality := reject,
+ value_ := { Number_of_Broadcasts_Requested := p_num_bcast }
+ }, {
+ id := SBC_AP_Constants.id_Data_Coding_Scheme,
+ criticality := ignore,
+ value_ := { Data_Coding_Scheme := dcs }
+ }, {
+ /* Warning Message Content */
+ id := SBC_AP_Constants.id_Warning_Message_Content,
+ criticality := ignore,
+ value_ := { Warning_Message_Content := p_msg_content }
+ /* OMC ID */
+ /* Concurrent Warning Message Indicator */
+ }, {
+ id := SBC_AP_Constants.id_Concurrent_Warning_Message_Indicator,
+ criticality := reject,
+ value_ := { Concurrent_Warning_Message_Indicator := concurrent_ind }
+ }, {
+ id := SBC_AP_Constants.id_Send_Write_Replace_Warning_Indication,
+ criticality := ignore,
+ value_ := { Send_Write_Replace_Warning_Indication := send_ind }
+ }
+ /* Global eNB ID */
+ /* Warning Area Coordinates */
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (present) SBC_AP_PDU
+tr_SBCAP_WRITE_WARNING_REQ_ETWS(template (present) BIT16 p_msg_id, template (present) BIT16 p_ser_nr,
+ template (present) uint12_t p_rep_per,
+ template (present) uint16_t p_num_bcast,
+ template (present) Warning_Type warn_type := ?,
+ template (present) Send_Write_Replace_Warning_Indication send_ind := ?
+ ) := {
+ initiatingMessage := {
+ procedureCode := id_Write_Replace_Warning,
+ criticality := reject,
+ value_ := {
+ write_Replace_Warning_Request := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ /* List of TAIs */
+ /* Warning Area List */
+ }, {
+ id := SBC_AP_Constants.id_Repetition_Period,
+ criticality := reject,
+ value_ := { Repetition_Period := p_rep_per }
+ /* Extended Repetition Period */
+ }, {
+ id := SBC_AP_Constants.id_Number_of_Broadcasts_Requested,
+ criticality := reject,
+ value_ := { Number_of_Broadcasts_Requested := p_num_bcast }
+ }, {
+ id := SBC_AP_Constants.id_Warning_Type,
+ criticality := ignore,
+ value_ := { Warning_Type := warn_type }
+ }, {
+ id := SBC_AP_Constants.id_Warning_Security_Information,
+ criticality := ignore,
+ value_ := { Warning_Security_Information := ? }
+ }, {
+ id := SBC_AP_Constants.id_Send_Write_Replace_Warning_Indication,
+ criticality := ignore,
+ value_ := { Send_Write_Replace_Warning_Indication := send_ind }
+ }
+ /* Global eNB ID */
+ /* Warning Area Coordinates */
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.5 WRITE REPLACE WARNING INDICATION */
+template (value) SBC_AP_PDU
+ts_SBCAP_WRITE_WARNING_IND(template (value) BIT16 p_msg_id, template (value) BIT16 p_ser_nr,
+ template (value) SBC_AP_Cause cause := SBC_AP_Cause_message_accepted,
+ template (value) CellId_Broadcast_List bcast_cell_id_li := {ts_SBCAP_CellId_Broadcast_List_Item()}) := {
+ initiatingMessage := {
+ procedureCode := id_Write_Replace_Warning_Indication,
+ criticality := ignore,
+ value_ := {
+ write_Replace_Warning_Indication := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ }, {
+ id := SBC_AP_Constants.id_Broadcast_Scheduled_Area_List,
+ criticality := reject,
+ value_ := { broadcast_Scheduled_Area_List := ts_SBCAP_Broadcast_Scheduled_Area_List(bcast_cell_id_li) }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.2 WRITE-REPLACE WARNING RESPONSE */
+template (value) SBC_AP_PDU
+ts_SBCAP_WRITE_WARNING_RESP(template (value) BIT16 p_msg_id, template (value) BIT16 p_ser_nr,
+ template (value) SBC_AP_Cause cause := SBC_AP_Cause_message_accepted) := {
+ successfulOutcome := {
+ procedureCode := id_Write_Replace_Warning,
+ criticality := reject,
+ value_ := {
+ write_Replace_Warning_Response := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ }, {
+ id := SBC_AP_Constants.id_Cause,
+ criticality := reject,
+ value_ := { Cause := enum2int(valueof(cause)) }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+template (value) SBC_AP_PDU
+ts_SBCAP_WRITE_WARNING_RESP_UNKNOWN_TAI(template (value) BIT16 p_msg_id, template (value) BIT16 p_ser_nr,
+ template (value) SBC_AP_Cause cause := SBC_AP_Cause_message_accepted,
+ template (value) List_of_TAIs unknown_tai_list := {{ts_SBCAP_TAI}})
+modifies ts_SBCAP_WRITE_WARNING_RESP := {
+ successfulOutcome := {
+ value_ := {
+ write_Replace_Warning_Response := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ }, {
+ id := SBC_AP_Constants.id_Cause,
+ criticality := reject,
+ value_ := { Cause := enum2int(valueof(cause)) }
+ }, {
+ id := SBC_AP_Constants.id_Unknown_Tracking_Area_List,
+ criticality := ignore,
+ value_ := { List_of_TAIs := unknown_tai_list }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.3 STOP WARNING REQUEST */
+template (present) SBC_AP_PDU
+tr_SBCAP_STOP_WARNING(template (present) BIT16 p_msg_id, template (present) BIT16 p_ser_nr) := {
+ initiatingMessage := {
+ procedureCode := id_Stop_Warning,
+ criticality := reject,
+ value_ := {
+ stop_Warning_Request := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ /* List of TAIs */
+ /* Warning Area List */
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+/* 4.3.4.2.4 STOP WARNING RESPONSE */
+template (value) SBC_AP_PDU
+ts_SBCAP_STOP_WARNING_RESP(template (value) BIT16 p_msg_id, template (value) BIT16 p_ser_nr,
+ template (value) SBC_AP_Cause cause := SBC_AP_Cause_message_accepted) := {
+ successfulOutcome := {
+ procedureCode := id_Stop_Warning,
+ criticality := reject,
+ value_ := {
+ stop_Warning_Response := {
+ protocolIEs := {
+ {
+ id := SBC_AP_Constants.id_Message_Identifier,
+ criticality := reject,
+ value_ := { Message_Identifier := p_msg_id }
+ }, {
+ id := SBC_AP_Constants.id_Serial_Number,
+ criticality := reject,
+ value_ := { Serial_Number := p_ser_nr }
+ }, {
+ id := SBC_AP_Constants.id_Cause,
+ criticality := reject,
+ value_ := { Cause := enum2int(valueof(cause)) }
+ }
+ },
+ protocolExtensions := omit
+ }
+ }
+ }
+}
+
+}
diff --git a/library/sbcap/SBC_AP_Types.ttcn b/library/sbcap/SBC_AP_Types.ttcn
new file mode 100644
index 00000000..4020c960
--- /dev/null
+++ b/library/sbcap/SBC_AP_Types.ttcn
@@ -0,0 +1,33 @@
+module SBC_AP_Types {
+
+ import from SBC_AP_PDU_Descriptions language "ASN.1:1997" all;
+
+ external function enc_SBC_AP_PDU(in SBC_AP_PDU pdu) return octetstring;
+ external function dec_SBC_AP_PDU(in octetstring stream) return SBC_AP_PDU;
+
+ const integer c_SBC_AP_PPID := 24;
+ const integer c_SBC_AP_PORT := 29168;
+
+ /* 3GPP TS 29.168 4.3.4.3.2 Cause */
+ type enumerated SBC_AP_Cause {
+ SBC_AP_Cause_message_accepted ('00'O),
+ SBcAP_Cause_parameter_not_recognised ('01'O),
+ SBcAP_Cause_parameter_value_invalid ('02'O),
+ SBcAP_Cause_valid_message_not_identified ('03'O),
+ SBcAP_Cause_tracking_area_not_valid ('04'O),
+ SBcAP_Cause_unrecognised_message ('05'O),
+ SBcAP_Cause_missing_mandatory_element ('06'O),
+ SBcAP_Cause_mME_capacity_exceeded ('07'O),
+ SBcAP_Cause_mME_memory_exceeded ('08'O),
+ SBcAP_Cause_warning_broadcast_not_supported ('09'O),
+ SBcAP_Cause_warning_broadcast_not_operational ('0A'O),
+ SBcAP_Cause_message_reference_already_used ('0B'O),
+ SBcAP_Cause_unspecifed_error ('0C'O),
+ SBcAP_Cause_transfer_syntax_error ('0D'O),
+ SBcAP_Cause_semantic_error ('0E'O),
+ SBcAP_Cause_message_not_compatible_with_receiver_state ('0F'O),
+ SBcAP_Cause_abstract_syntax_error_reject ('10'O),
+ SBcAP_Cause_abstract_syntax_error_ignore_and_notify ('11'O),
+ SBcAP_Cause_abstract_syntax_error_falsely_constructed_message ('12'O)
+ }
+}
diff --git a/library/sbcap/regen_makefile.sh b/library/sbcap/regen_makefile.sh
new file mode 100755
index 00000000..0cd60832
--- /dev/null
+++ b/library/sbcap/regen_makefile.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+FILES="*.asn *.ttcn SBC_AP_EncDec.cc"
+
+../../regen-makefile.sh $FILES
+
+sed -i -e '/^CPPFLAGS/ s/$/ `pkg-config --cflags libfftranscode`/' Makefile
+sed -i -e '/^LDFLAGS/ s/$/ `pkg-config --libs libfftranscode`/' Makefile
+sed -i -e '/^LINUX_LIBS/ s/$/ `pkg-config --libs libfftranscode`/' Makefile
diff --git a/mgw/MGCP_Test.default b/mgw/MGCP_Test.default
index 4336033d..54bf9afe 100644
--- a/mgw/MGCP_Test.default
+++ b/mgw/MGCP_Test.default
@@ -11,12 +11,21 @@ FileMask := LOG_ALL | TTCN_MATCHING;
*.MGWVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
*.MGWVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
*.MGWVTY.PROMPT1 := "OsmoMGW> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4243"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoMGW> "
[MODULE_PARAMETERS]
mp_local_udp_port := 2727;
-mp_local_ip:= "127.0.0.1";
+mp_local_ipv4:= "127.0.0.1";
mp_remote_udp_port := 2427;
-mp_remote_ip:= "127.0.0.1";
+mp_remote_ipv4:= "127.0.0.1";
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoMGW";
[MAIN_CONTROLLER]
diff --git a/mgw/MGCP_Test.ttcn b/mgw/MGCP_Test.ttcn
index 6caef795..7090b340 100644
--- a/mgw/MGCP_Test.ttcn
+++ b/mgw/MGCP_Test.ttcn
@@ -10,19 +10,23 @@
*/
module MGCP_Test {
+ import from Misc_Helpers all;
import from Osmocom_Types all;
import from MGCP_Types all;
import from MGCP_Templates all;
import from SDP_Types all;
+ import from SDP_Templates all;
import from MGCP_CodecPort all;
import from MGCP_CodecPort_CtrlFunct all;
import from RTP_CodecPort all;
import from RTP_CodecPort_CtrlFunct all;
import from RTP_Emulation all;
+ import from IuUP_Emulation all;
import from OSMUX_Types all;
import from OSMUX_CodecPort all;
import from OSMUX_CodecPort_CtrlFunct all;
import from OSMUX_Emulation all;
+ import from AMR_Types all;
import from IPL4asp_Types all;
import from General_Types all;
import from Native_Functions all;
@@ -30,6 +34,13 @@ module MGCP_Test {
import from IP_Types all;
import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType all;
+ import from StatsD_Types all;
+ import from StatsD_CodecPort all;
+ import from StatsD_CodecPort_CtrlFunct all;
+ import from StatsD_Checker all;
+ import from Osmocom_CTRL_Functions all;
+ import from Osmocom_CTRL_Types all;
+ import from Osmocom_CTRL_Adapter all;
const charstring c_mgw_domain := "mgw";
const charstring c_mgw_ep_rtpbridge := "rtpbridge/";
@@ -37,7 +48,7 @@ module MGCP_Test {
/* any variables declared in the component will be available to
* all functions that 'run on' the named component, similar to
* class members in C++ */
- type component dummy_CT {
+ type component dummy_CT extends StatsD_ConnHdlr, CTRL_Adapter_CT {
port MGCP_CODEC_PT MGCP;
var boolean initialized := false;
var ConnectionId g_mgcp_conn_id := -1;
@@ -50,6 +61,8 @@ module MGCP_Test {
port OsmuxEM_CTRL_PT OsmuxEM;
port TELNETasp_PT MGWVTY;
+
+ var StatsD_Checker_CT vc_STATSD;
};
function get_next_trans_id() runs on dummy_CT return MgcpTransId {
@@ -64,11 +77,17 @@ module MGCP_Test {
* default values assigned below are used */
modulepar {
PortNumber mp_local_udp_port := 2727;
- charstring mp_local_ip := "127.0.0.1";
+ charstring mp_local_ipv4 := "127.0.0.1";
+ charstring mp_local_ipv6 := "::1";
PortNumber mp_remote_udp_port := 2427;
- charstring mp_remote_ip := "127.0.0.1";
+ charstring mp_remote_ipv4 := "127.0.0.1";
+ charstring mp_remote_ipv6 := "::1";
PortNumber mp_local_rtp_port_base := 10000;
PortNumber mp_local_osmux_port := 1985;
+ PortNumber mp_mgw_statsd_port := 8125;
+ PortNumber mp_mgw_ctrl_port := 4267;
+ /* Maximum number of available endpoints in osmo-mgw.cfg ("number endpoints"): */
+ integer mp_num_endpoints := 300;
}
private function f_vty_enable_osmux(boolean osmux_on) runs on dummy_CT {
@@ -124,7 +143,7 @@ module MGCP_Test {
/* connect the MGCP test port using the given
* source/destionation ip/port and store the connection id in g_mgcp_conn_id
* */
- res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, mp_remote_ip, mp_remote_udp_port, mp_local_ip, mp_local_udp_port, 0, { udp := {} });
+ res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, mp_remote_ipv4, mp_remote_udp_port, mp_local_ipv4, mp_local_udp_port, 0, { udp := {} });
if (not ispresent(res.connId)) {
setverdict(fail, "Could not connect MGCP, check your configuration");
mtc.stop;
@@ -139,8 +158,15 @@ module MGCP_Test {
f_osmuxem_init(vc_OsmuxEM);
connect(vc_OsmuxEM:CTRL, self:OsmuxEM);
}
+
+ f_init_statsd("VirtCallAgent", vc_STATSD, mp_local_ipv4, mp_mgw_statsd_port);
+ connect(self:STATSD_PROC, vc_STATSD:STATSD_PROC);
+
+ f_statsd_reset();
}
+ f_ipa_ctrl_start_client(mp_remote_ipv4, mp_mgw_ctrl_port);
+
if (isvalue(ep)) {
/* do a DLCX on all connections of the EP */
f_dlcx_ignore(valueof(ep));
@@ -224,9 +250,9 @@ module MGCP_Test {
function tr_MGCP_RecvFrom_R(template MgcpResponse resp) runs on dummy_CT return template MGCP_RecvFrom {
var template MGCP_RecvFrom mrf := {
connId := g_mgcp_conn_id,
- remName := mp_remote_ip,
+ remName := mp_remote_ipv4,
remPort := mp_remote_udp_port,
- locName := mp_local_ip,
+ locName := mp_local_ipv4,
locPort := mp_local_udp_port,
msg := { response := resp }
}
@@ -311,18 +337,100 @@ module MGCP_Test {
charstring hostname,
integer portnr optional
}
+ type record RtpOsmuxFlowData {
+ boolean local_cid_sent, /* whther non wildcarded CID was already sent to MGW */
+ MgcpOsmuxCID local_cid optional,
+ MgcpOsmuxCID remote_cid optional,
+ OsmuxemConfig cfg optional
+ }
+ type record RtpCodecDescr {
+ uint7_t pt,
+ charstring codec,
+ charstring fmtp optional
+ }
type record RtpFlowData {
HostPort em, /* emulation side */
HostPort mgw, /* mgw side */
- uint7_t pt,
- charstring codec,
MgcpConnectionId mgcp_conn_id optional,
+ record of RtpCodecDescr codec_descr,
RtpemConfig rtp_cfg optional,
- boolean osmux_cid_sent, /* whther non wildcarded CID was already sent to MGW */
- MgcpOsmuxCID osmux_cid optional,
- MgcpOsmuxCID osmux_cid_response optional,
- OsmuxemConfig osmux_cfg optional,
- charstring fmtp optional
+ RtpOsmuxFlowData osmux
+ }
+
+ template RtpFlowData t_RtpFlow(charstring host_a, charstring host_b, uint7_t pt,
+ charstring codec, template charstring fmtp := omit) := {
+ em := {
+ hostname := host_a,
+ portnr := omit
+ },
+ mgw := {
+ hostname := host_b,
+ portnr := omit
+ },
+ codec_descr := {{
+ pt := pt,
+ codec := codec,
+ fmtp := fmtp
+ }},
+ osmux:= {
+ local_cid_sent := false,
+ local_cid := omit,
+ remote_cid := omit,
+ cfg := omit
+ }
+ }
+
+ /* To be used with f_flow_create/modify... functions */
+ function f_gen_sdp(RtpFlowData flow) runs on dummy_CT return SDP_Message {
+ var template SDP_Message sdp;
+ var SDP_fmt_list fmt_list := {};
+ var SDP_attribute_list attributes := {};
+
+ /* Add SDP RTMAP attributes (codec type, referenced by PT) */
+ for (var integer i := 0; i < lengthof(flow.codec_descr); i := i + 1) {
+ attributes := attributes & { valueof(ts_SDP_rtpmap(flow.codec_descr[i].pt,
+ flow.codec_descr[i].codec)) };
+ }
+
+ /* Add SDP PTIME attribute, regardless of which codec, the packet intervall remains the same */
+ attributes := attributes & { valueof(ts_SDP_ptime(20)) };
+
+ /* Add SDP FMTP attributes (codec parameters for each codec, referenced by PT) */
+ for (var integer i := 0; i < lengthof(flow.codec_descr); i := i + 1) {
+ if (isvalue(flow.codec_descr[i].fmtp) and flow.codec_descr[i].fmtp != "") {
+ attributes := attributes & { valueof(ts_SDP_fmtp(flow.codec_descr[i].pt,
+ flow.codec_descr[i].fmtp)) };
+ }
+ }
+
+ /* Final step: Generate SDP */
+ for (var integer i := 0; i < lengthof(flow.codec_descr); i := i + 1) {
+ fmt_list := fmt_list & {int2str(flow.codec_descr[i].pt)};
+ }
+ sdp := ts_SDP(flow.em.hostname, flow.em.hostname, "23", "42", flow.em.portnr, fmt_list, attributes);
+
+ return valueof(sdp);
+ }
+
+ /* Generate a valid RTP emulation config from the payload type numbers configured in the flow description and
+ * the the default configuration of the RTP emulation module. */
+ function f_gen_rtpem_config_from_flow(RtpFlowData flow) return RtpemConfig {
+ var RtpemConfig rtp_cfg := c_RtpemDefaultCfg;
+
+ for (var integer i := 0; i < lengthof(flow.codec_descr); i := i + 1) {
+ var RtpemConfigPayload tx_cfg_payload;
+ var RtpemConfigPayload rx_cfg_payload;
+
+ tx_cfg_payload.payload_type := flow.codec_descr[i].pt;
+ tx_cfg_payload.fixed_payload := c_RtpemDefaultCfg.tx_payloads[0].fixed_payload;
+ rx_cfg_payload.payload_type := flow.codec_descr[i].pt;
+ rx_cfg_payload.fixed_payload := c_RtpemDefaultCfg.rx_payloads[0].fixed_payload;
+
+ rtp_cfg.tx_payloads := rtp_cfg.tx_payloads & {tx_cfg_payload};
+ rtp_cfg.rx_payloads := rtp_cfg.rx_payloads & {rx_cfg_payload};
+ }
+
+ return rtp_cfg;
}
/* Create an RTP flow (bidirectional, or receive-only) */
@@ -331,12 +439,6 @@ module MGCP_Test {
runs on dummy_CT {
var template MgcpCommand cmd;
var MgcpResponse resp;
- var SDP_attribute_list attributes;
-
- attributes := { valueof(ts_SDP_rtpmap(flow.pt, flow.codec)), valueof(ts_SDP_ptime(20)) };
- if (isvalue(flow.fmtp)) {
- attributes := attributes & { valueof(ts_SDP_fmtp(flow.pt, flow.fmtp)) };
- }
/* bind local RTP emulation socket */
f_rtpem_bind(pt, flow.em.hostname, flow.em.portnr);
@@ -345,9 +447,7 @@ module MGCP_Test {
if (ispresent(flow.rtp_cfg)) {
f_rtpem_configure(pt, flow.rtp_cfg);
} else {
- var RtpemConfig rtp_cfg := c_RtpemDefaultCfg;
- rtp_cfg.tx_payload_type := flow.pt
- f_rtpem_configure(pt, rtp_cfg);
+ f_rtpem_configure(pt, f_gen_rtpem_config_from_flow(flow));
}
if (one_phase) {
@@ -357,8 +457,7 @@ module MGCP_Test {
* one go. */
cmd := ts_CRCX(get_next_trans_id(), ep, mode, call_id);
- cmd.sdp := ts_SDP(flow.em.hostname, flow.em.hostname, "23", "42",
- flow.em.portnr, { int2str(flow.pt) }, attributes);
+ cmd.sdp := f_gen_sdp(flow);
resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
flow.mgcp_conn_id := extract_conn_id(resp);
@@ -389,27 +488,21 @@ module MGCP_Test {
runs on dummy_CT {
var template MgcpCommand cmd;
var MgcpResponse resp;
- var SDP_attribute_list attributes;
var OsmuxTxHandle tx_hdl;
var OsmuxRxHandle rx_hdl;
var charstring cid_response;
var OsmuxCID cid_resp_parsed
- attributes := { valueof(ts_SDP_rtpmap(flow.pt, flow.codec)), valueof(ts_SDP_ptime(20)) };
- if (isvalue(flow.fmtp)) {
- attributes := attributes & { valueof(ts_SDP_fmtp(flow.pt, flow.fmtp)) };
- }
-
/* bind local Osmux emulation socket */
f_osmuxem_bind(pt, flow.em.hostname, flow.em.portnr);
/* configure osmux-emulation */
- if (ispresent(flow.osmux_cfg)) {
- f_osmuxem_configure(pt, flow.osmux_cfg);
+ if (ispresent(flow.osmux.cfg)) {
+ f_osmuxem_configure(pt, flow.osmux.cfg);
} else {
var OsmuxemConfig osmux_cfg := c_OsmuxemDefaultCfg;
f_osmuxem_configure(pt, osmux_cfg);
- flow.osmux_cfg := osmux_cfg
+ flow.osmux.cfg := osmux_cfg
}
if (one_phase) {
@@ -417,13 +510,15 @@ module MGCP_Test {
* part that tells the MGW where we are listening for Osmux streams
* that come from the MGW. We get a fully working connection in
* one go. */
- rx_hdl := c_OsmuxemDefaultRxHandle;
- rx_hdl.cid := flow.osmux_cid;
- f_osmuxem_register_rxhandle(pt, rx_hdl);
- flow.osmux_cid_sent := true;
- cmd := ts_CRCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.osmux_cid);
- cmd.sdp := ts_SDP(flow.em.hostname, flow.em.hostname, "23", "42",
- flow.em.portnr, { int2str(flow.pt) }, attributes);
+ if (flow.osmux.local_cid != -1) {
+ /* We may still want to negotiate osmux CID later at MDCX */
+ rx_hdl := c_OsmuxemDefaultRxHandle;
+ rx_hdl.cid := flow.osmux.local_cid;
+ f_osmuxem_register_rxhandle(pt, rx_hdl);
+ flow.osmux.local_cid_sent := true;
+ }
+ cmd := ts_CRCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.osmux.local_cid);
+ cmd.sdp := f_gen_sdp(flow);
resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK_osmux);
flow.mgcp_conn_id := extract_conn_id(resp);
/* extract port number from response */
@@ -436,7 +531,7 @@ module MGCP_Test {
* data back to us. In order to turn the connection in a fully
* bi-directional one, a separate MDCX is needed. */
- cmd := ts_CRCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.osmux_cid);
+ cmd := ts_CRCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.osmux.local_cid);
resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK_osmux);
flow.mgcp_conn_id := extract_conn_id(resp);
@@ -456,12 +551,12 @@ module MGCP_Test {
}
/* Make sure response is no wildcard */
- flow.osmux_cid_response := f_mgcp_osmux_cid_decode(cid_response);
- if (flow.osmux_cid_response == -1) {
+ flow.osmux.remote_cid := f_mgcp_osmux_cid_decode(cid_response);
+ if (flow.osmux.remote_cid == -1) {
setverdict(fail, "Osmux CID in MGCP response contains unexpected wildcard");
mtc.stop;
}
- tx_hdl := valueof(t_TxHandleAMR590(flow.osmux_cid_response));
+ tx_hdl := valueof(t_TxHandleAMR590(flow.osmux.remote_cid));
f_osmuxem_register_txhandle(pt, tx_hdl);
/* finally, connect the emulation-side RTP socket to the MGW */
@@ -473,12 +568,6 @@ module MGCP_Test {
runs on dummy_CT {
var template MgcpCommand cmd;
var MgcpResponse resp;
- var SDP_attribute_list attributes;
-
- attributes := { valueof(ts_SDP_rtpmap(flow.pt, flow.codec)), valueof(ts_SDP_ptime(20)) };
- if (isvalue(flow.fmtp)) {
- attributes := attributes & { valueof(ts_SDP_fmtp(flow.pt, flow.fmtp)) };
- }
/* rebind local RTP emulation socket to the new address */
f_rtpem_bind(pt, flow.em.hostname, flow.em.portnr);
@@ -487,15 +576,12 @@ module MGCP_Test {
if (ispresent(flow.rtp_cfg)) {
f_rtpem_configure(pt, flow.rtp_cfg);
} else {
- var RtpemConfig rtp_cfg := c_RtpemDefaultCfg;
- rtp_cfg.tx_payload_type := flow.pt
- f_rtpem_configure(pt, rtp_cfg);
+ f_rtpem_configure(pt, f_gen_rtpem_config_from_flow(flow));
}
/* connect MGW side RTP socket to the emulation-side RTP socket using SDP */
cmd := ts_MDCX(get_next_trans_id(), ep, mode, call_id, flow.mgcp_conn_id);
- cmd.sdp := ts_SDP(flow.em.hostname, flow.em.hostname, "23", "42",
- flow.em.portnr, { int2str(flow.pt) }, attributes);
+ cmd.sdp := f_gen_sdp(flow);
resp := mgcp_transceive_mgw(cmd, tr_MDCX_ACK);
/* extract MGW-side port number from response. (usually this
@@ -512,39 +598,32 @@ module MGCP_Test {
runs on dummy_CT {
var template MgcpCommand cmd;
var MgcpResponse resp;
- var SDP_attribute_list attributes;
var OsmuxRxHandle rx_hdl;
var charstring cid_response;
var OsmuxCID cid_resp_parsed
- attributes := { valueof(ts_SDP_rtpmap(flow.pt, flow.codec)), valueof(ts_SDP_ptime(20)) };
- if (isvalue(flow.fmtp)) {
- attributes := attributes & { valueof(ts_SDP_fmtp(flow.pt, flow.fmtp)) };
- }
-
/* rebind local Osmux emulation socket to the new address */
f_osmuxem_bind(pt, flow.em.hostname, flow.em.portnr);
/* configure osmux-emulation */
- if (ispresent(flow.osmux_cfg)) {
- f_osmuxem_configure(pt, flow.osmux_cfg);
+ if (ispresent(flow.osmux.cfg)) {
+ f_osmuxem_configure(pt, flow.osmux.cfg);
} else {
var OsmuxemConfig osmux_cfg := c_OsmuxemDefaultCfg;
f_osmuxem_configure(pt, osmux_cfg);
}
/* We didn't send a non-wildcarded Osmux CID yet. If caller wants to submit it, register handler */
- if (flow.osmux_cid_sent == false and flow.osmux_cid != -1) {
+ if (flow.osmux.local_cid_sent == false and flow.osmux.local_cid != -1) {
rx_hdl := c_OsmuxemDefaultRxHandle;
- rx_hdl.cid := flow.osmux_cid;
+ rx_hdl.cid := flow.osmux.local_cid;
f_osmuxem_register_rxhandle(pt, rx_hdl);
- flow.osmux_cid_sent := true;
+ flow.osmux.local_cid_sent := true;
}
/* connect MGW side Osmux socket to the emulation-side Osmux socket using SDP */
- cmd := ts_MDCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.mgcp_conn_id, flow.osmux_cid);
- cmd.sdp := ts_SDP(flow.em.hostname, flow.em.hostname, "23", "42",
- flow.em.portnr, { int2str(flow.pt) }, attributes);
+ cmd := ts_MDCX_osmux(get_next_trans_id(), ep, mode, call_id, flow.mgcp_conn_id, flow.osmux.local_cid);
+ cmd.sdp := f_gen_sdp(flow);
resp := mgcp_transceive_mgw(cmd, tr_MDCX_ACK);
/* extract MGW-side port number from response. (usually this
@@ -568,7 +647,7 @@ module MGCP_Test {
setverdict(fail, "Osmux CID in MGCP response contains unexpected wildcard");
mtc.stop;
}
- if (cid_resp_parsed != flow.osmux_cid_response) {
+ if (cid_resp_parsed != flow.osmux.remote_cid) {
setverdict(fail, "Osmux CID in MGCP MDCX response changed from prev value");
mtc.stop;
}
@@ -609,6 +688,18 @@ module MGCP_Test {
}
}
+ /* Send an AuditEndpoint message to the MGW */
+ function f_auep(charstring ep_prefix) runs on dummy_CT {
+ var MgcpEndpoint ep := ep_prefix & "@" & c_mgw_domain;
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+
+ f_init(ep);
+
+ cmd := ts_AUEP(get_next_trans_id(), ep);
+ resp := mgcp_transceive_mgw(cmd, tr_AUEP_ACK);
+ }
+
function f_crcx(charstring ep_prefix) runs on dummy_CT {
var MgcpEndpoint ep := ep_prefix & "2@" & c_mgw_domain;
var template MgcpCommand cmd;
@@ -694,6 +785,12 @@ module MGCP_Test {
f_dlcx_ok(ep, call_id);
}
+ /* test valid AUEP towards "null" endpoint */
+ testcase TC_auep_null() runs on dummy_CT {
+ f_auep("null");
+ setverdict(pass);
+ }
+
/* test valid CRCX without SDP */
testcase TC_crcx() runs on dummy_CT {
f_crcx(c_mgw_ep_rtpbridge);
@@ -727,6 +824,35 @@ module MGCP_Test {
setverdict(pass);
}
+ /* Test CRCX with X-Osmo-IGN, using same message as SYS#5063 to make sure it doesn't cause a crash. */
+ testcase TC_crcx_osmo_ign() runs on dummy_CT {
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var MgcpEndpoint ep := "7@" & c_mgw_domain;
+ var MgcpCallId call_id := '3'H;
+
+ f_init(ep);
+
+ /* CRCX 1 7@mgw MGCP 1.0
+ C: 3
+ L: p:20, a:GSM-EFR, nt:IN
+ M: recvonly
+ X-Osmo-IGN: C
+ */
+
+ cmd := ts_CRCX(get_next_trans_id(), ep, "netwtest", call_id);
+ cmd.params := {ts_MgcpParCallId(call_id),
+ t_MgcpParLocConnOpt("p:20, a:GSM-EFR, nt:IN"),
+ t_MgcpParConnMode("recvonly"),
+ t_MgcpParOsmoIGN("C")};
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ extract_conn_id(resp);
+
+ /* clean-up */
+ f_dlcx_ok(ep, call_id);
+ setverdict(pass);
+ }
+
/* test CRCX with early bi-directional mode, expect 527 as
* bi-diretional media can only be established once both local and
* remote side are specified, see MGCP RFC */
@@ -884,18 +1010,19 @@ module MGCP_Test {
}
/* test valid wildcarded CRCX */
+ type record of MgcpEndpoint MgcpEndpointList;
testcase TC_crcx_wildcarded_exhaust() runs on dummy_CT {
- const integer n_endpoints := 31;
var integer i;
var template MgcpCommand cmd;
var MgcpResponse resp;
var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "*@" & c_mgw_domain;
var MgcpCallId call_id := '1234'H;
- var MgcpEndpoint ep_assigned[n_endpoints];
+ var MgcpEndpoint ep_assigned;
+ var MgcpEndpointList ep_assigned_li := {};
f_init();
/* Exhaust all endpoint resources on the virtual trunk */
- for (i := 0; i < n_endpoints; i := i+1) {
+ for (i := 0; i < mp_num_endpoints; i := i+1) {
cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
@@ -905,10 +1032,11 @@ module MGCP_Test {
var MgcpMessage resp_msg := {
response := resp
}
- if (f_mgcp_find_param(resp_msg, "Z", ep_assigned[i]) == false) {
+ if (f_mgcp_find_param(resp_msg, "Z", ep_assigned) == false) {
setverdict(fail, "No SpecificEndpointName in MGCP response", resp);
mtc.stop;
}
+ ep_assigned_li := ep_assigned_li & {ep_assigned}
}
/* Try to allocate one more endpoint, which should fail */
@@ -918,8 +1046,8 @@ module MGCP_Test {
setverdict(pass);
/* clean-up */
- for (i := 0; i < n_endpoints; i := i+1) {
- f_dlcx_ok(ep_assigned[i], call_id);
+ for (i := 0; i < mp_num_endpoints; i := i+1) {
+ f_dlcx_ok(ep_assigned_li[i], call_id);
}
setverdict(pass);
}
@@ -979,6 +1107,28 @@ module MGCP_Test {
setverdict(pass);
}
+ /* DLCX to non existing endpoint */
+ testcase TC_dlcx_non_existant_ep() runs on dummy_CT {
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var charstring non_existant_ep := hex2str(int2hex(mp_num_endpoints + 1, 4))
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & non_existant_ep & "@" & c_mgw_domain;
+ var template MgcpResponse rtmpl := {
+ line := {
+ code := ("500"),
+ string := ?
+ },
+ params:= { },
+ sdp := omit
+ };
+
+ f_init(ep);
+
+ cmd := ts_DLCX(get_next_trans_id(), ep, '41234'H);
+ resp := mgcp_transceive_mgw(cmd, rtmpl);
+ setverdict(pass);
+ }
+
/* test valid wildcarded MDCX */
testcase TC_mdcx_wildcarded() runs on dummy_CT {
/* Note: A wildcarded MDCX is not allowed, so we expect the
@@ -1009,25 +1159,53 @@ module MGCP_Test {
/* test valid wildcarded DLCX */
testcase TC_dlcx_wildcarded() runs on dummy_CT {
- /* Note: A wildcarded DLCX is specified, but our MGW does not
- * support this feature so we expect the MGW to reject the
- * request */
var template MgcpCommand cmd;
var MgcpResponse resp;
var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "*@" & c_mgw_domain;
+ var integer i;
+ var MgcpCallId call_id := '1234'H;
+ var StatsDExpects expect;
+ f_init(ep);
+
+ /* Allocate a few endpoints */
+ for (i := 0; i < mp_num_endpoints; i := i+1) {
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ }
+
+ /* Wait until the stats items have seteled and then check if we get the expected number (all) of
+ * occupied endpoints */
+ f_sleep(1.0)
+ expect := {
+ { name := "TTCN3.trunk.virtual-0.common.endpoints.used", mtype := "g", min := mp_num_endpoints, max := mp_num_endpoints}
+ };
+ f_statsd_expect(expect);
+
+ /* Send wildcarded DLCX */
var template MgcpResponse rtmpl := {
line := {
- code := "507",
+ code := "200",
string := ?
},
params:= { },
sdp := omit
};
+ cmd := ts_DLCX(get_next_trans_id(), ep);
+ mgcp_transceive_mgw(cmd, rtmpl);
- f_init(ep);
+ /* Query a the statsd once to ensure that intermediate results are pulled from the
+ * pipeline. The second query (below) will return the actual result. */
+ expect := {
+ { name := "TTCN3.trunk.virtual-0.common.endpoints.used", mtype := "g", min := 0, max := mp_num_endpoints}
+ };
+ f_statsd_expect(expect);
+
+ /* The second query must resturn a result with 0 endpoints in use. */
+ expect := {
+ { name := "TTCN3.trunk.virtual-0.common.endpoints.used", mtype := "g", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
- cmd := ts_DLCX(get_next_trans_id(), ep, '41234'H);
- resp := mgcp_transceive_mgw(cmd, rtmpl);
setverdict(pass);
}
@@ -1067,6 +1245,51 @@ module MGCP_Test {
setverdict(pass);
}
+ /* test Creating 257 concurrent osmux conns. It should fail since maximum is 256. */
+ testcase TC_crcx_osmux_257() runs on dummy_CT {
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "*@" & c_mgw_domain;
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var charstring cid_response;
+ var integer i;
+
+ f_init(ep, true);
+
+ for (i := 0; i < 256; i := i + 1) {
+
+ cmd := ts_CRCX_osmux(get_next_trans_id(), ep, "recvonly", int2hex(i, 4), -1);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK_osmux);
+ extract_conn_id(resp);
+
+ /* extract Osmux CID we got assigned by the MGW */
+ var MgcpMessage resp_msg := {
+ response := resp
+ }
+
+ if (f_mgcp_find_param(resp_msg, "X-OSMUX", cid_response) == false) {
+ setverdict(fail, "No Osmux CID in MGCP response", resp);
+ mtc.stop;
+ }
+
+ /* Make sure response is no wildcard */
+ if (f_mgcp_osmux_cid_decode(cid_response) == -1) {
+ setverdict(fail, "Osmux CID in MGCP response contains unexpected wildcard");
+ mtc.stop;
+ }
+ }
+
+ /* Now conn num 257, it should fail due to all Osmux conns already allocated: */
+ cmd := ts_CRCX_osmux(get_next_trans_id(), ep, "recvonly", int2hex(i, 4), -1);
+ resp := mgcp_transceive_mgw(cmd, tr_MgcpResp_Err("400"));
+
+ setverdict(pass);
+
+ /* Clean up */
+ for (i := 0; i < 256; i := i + 1) {
+ f_dlcx_ok(ep, int2hex(i, 4));
+ }
+ }
+
/* Create one half open connection in receive-only mode. The MGW must accept
* the packets but must not send any. */
testcase TC_one_crcx_receive_only_osmux() runs on dummy_CT {
@@ -1077,9 +1300,9 @@ module MGCP_Test {
var OsmuxTxHandle tx_hdl;
f_init(ep, true);
- flow := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000/1"));
+ flow := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 112, "AMR/8000/1"));
flow.em.portnr := mp_local_osmux_port;
- flow.osmux_cid := -1;
+ flow.osmux.local_cid := -1;
f_flow_create_osmux(OsmuxEM, ep, call_id, "recvonly", flow, false);
/* create a transmitter not yet known by MGW */
@@ -1092,10 +1315,10 @@ module MGCP_Test {
stats := f_osmuxem_stats_get(OsmuxEM);
- if (stats.num_pkts_tx < 40 / flow.osmux_cfg.batch_size) {
+ if (stats.num_pkts_tx < 40 / flow.osmux.cfg.batch_size) {
setverdict(fail);
}
- if (stats.bytes_payload_tx < stats.num_pkts_tx * f_amrft_payload_len(tx_hdl.amr_ft) * flow.osmux_cfg.batch_size) {
+ if (stats.bytes_payload_tx < stats.num_pkts_tx * f_amrft_payload_len(tx_hdl.amr_ft) * flow.osmux.cfg.batch_size) {
setverdict(fail);
}
@@ -1114,9 +1337,9 @@ module MGCP_Test {
var OsmuxTxHandle tx_hdl;
f_init(ep, true);
- flow := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 111, "GSM-HR-08/8000/1"));
+ flow := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 111, "GSM-HR-08/8000/1"));
flow.em.portnr := mp_local_osmux_port;
- flow.osmux_cid := 2;
+ flow.osmux.local_cid := 2;
f_flow_create_osmux(OsmuxEM, ep, call_id, "loopback", flow);
f_osmuxem_mode(OsmuxEM, OSMUXEM_MODE_BIDIR);
@@ -1183,7 +1406,9 @@ module MGCP_Test {
return true;
}
- function f_TC_two_crcx_and_rtp_osmux(boolean bidir) runs on dummy_CT {
+ function f_TC_two_crcx_and_rtp_osmux(boolean bidir, boolean rtp_amr_oa,
+ charstring local_ip_rtp, charstring remote_ip_rtp,
+ charstring local_ip_osmux, charstring remote_ip_osmux) runs on dummy_CT {
var RtpFlowData flow[2];
var RtpemStats stats_rtp;
var OsmuxemStats stats_osmux;
@@ -1192,24 +1417,44 @@ module MGCP_Test {
var MgcpCallId call_id := '1226'H;
var integer tolerance := 0;
+ var octetstring amr_payload;
+ var charstring fmtp;
+
f_init(ep, true);
+ var AMRFT cmr := AMR_FT_0;
+ var AMRFT ft := AMR_FT_2;
+ if (rtp_amr_oa) {
+ fmtp := "octet-align=1";
+ var RTP_AMR_Hdr amr_oa_hdr := valueof(ts_RTP_AMR_Hdr(enum2int(cmr), enum2int(ft)));
+ amr_payload := enc_RTP_AMR_Hdr(amr_oa_hdr) &
+ f_osmux_gen_expected_rx_rtp_payload(enum2int(ft), c_OsmuxemDefaultCfg.tx_fixed_payload);
+ } else {
+ fmtp := "octet-align=0";
+ /* Convert OA to BWE: */
+ var RTP_AMR_BWE_Hdr amr_bwe_hdr := valueof(ts_RTP_AMR_BWE_Hdr(enum2int(cmr), enum2int(ft)));
+ var bitstring amr_bwe_hdr_bits := substr(oct2bit(enc_RTP_AMR_BWE_Hdr(amr_bwe_hdr)), 0 , 10);
+ var bitstring amr_data_bits := oct2bit(f_osmux_gen_expected_rx_rtp_payload(enum2int(ft), c_OsmuxemDefaultCfg.tx_fixed_payload));
+ var bitstring amr_payload_bits := amr_bwe_hdr_bits & substr(amr_data_bits, 0, f_amrft_payload_bits_len(enum2int(ft)));
+ amr_payload := bit2oct(f_pad_bit(amr_payload_bits, (lengthof(amr_payload_bits)+7)/8*8, '0'B));
+ };
+
/* from us to MGW */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000"));
+ flow[0] := valueof(t_RtpFlow(local_ip_rtp, remote_ip_rtp, 112, "AMR/8000", fmtp));
flow[0].rtp_cfg := c_RtpemDefaultCfg
- flow[0].rtp_cfg.tx_payload_type := flow[0].pt;
- /* 0014 is the ToC (CMR=AMR4.75) in front of AMR Payload in RTP Payload */
- flow[0].rtp_cfg.rx_fixed_payload := '0014'O & f_osmux_gen_expected_rx_rtp_payload(2 /* AMR_FT_2, 5.90 */, c_OsmuxemDefaultCfg.tx_fixed_payload);
- flow[0].rtp_cfg.tx_fixed_payload := flow[0].rtp_cfg.rx_fixed_payload;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := amr_payload;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := amr_payload;
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* from MGW back to us */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 110, "AMR/8000"));
+ flow[1] := valueof(t_RtpFlow(local_ip_osmux, remote_ip_osmux, 110, "AMR/8000"));
flow[1].em.portnr := mp_local_osmux_port;
- flow[1].osmux_cid := 2;
- flow[1].osmux_cfg := c_OsmuxemDefaultCfg;
+ flow[1].osmux.local_cid := 2;
+ flow[1].osmux.cfg := c_OsmuxemDefaultCfg;
f_flow_create_osmux(OsmuxEM, ep, call_id, "sendrecv", flow[1]);
if (bidir) {
@@ -1238,7 +1483,7 @@ module MGCP_Test {
stats_rtp := f_rtpem_stats_get(RTPEM[0]);
stats_osmux := f_osmuxem_stats_get(OsmuxEM);
- if (not f_rtp_osmux_stats_compare(stats_rtp, stats_osmux, flow[1].osmux_cfg.batch_size, tolerance)) {
+ if (not f_rtp_osmux_stats_compare(stats_rtp, stats_osmux, flow[1].osmux.cfg.batch_size, tolerance)) {
setverdict(fail, "RTP and Osmux endpoint statistics don't match");
mtc.stop;
}
@@ -1251,51 +1496,81 @@ module MGCP_Test {
/* create one RTP and one OSmux emulations; create two connections on MGW EP, exchange some data */
testcase TC_two_crcx_and_rtp_osmux() runs on dummy_CT {
- f_TC_two_crcx_and_rtp_osmux(false);
+ f_TC_two_crcx_and_rtp_osmux(false, true, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
}
/* create one RTP and one OSmux emulations; create two connections on MGW EP,
* exchange some data in both directions */
testcase TC_two_crcx_and_rtp_osmux_bidir() runs on dummy_CT {
- f_TC_two_crcx_and_rtp_osmux(true);
+ f_TC_two_crcx_and_rtp_osmux(true, true, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* create one RTP and one OSmux emulations; create two connections on MGW EP,
+ * exchange some data in both directions. RTP side is configured to
+ * rx/rx AMR in bandwidth-efficient mode. */
+ testcase TC_two_crcx_and_rtp_osmux_bidir_amr_bwe() runs on dummy_CT {
+ f_TC_two_crcx_and_rtp_osmux(true, false, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
}
- function f_two_crcx_mdcx_and_rtp_osmux(boolean crcx_osmux_wildcard) runs on dummy_CT {
+ /* Same as TC_two_crcx_and_rtp_osmux_bidir, but using IPv6 */
+ testcase TC_two_crcx_and_rtp_osmux_bidir_ipv6() runs on dummy_CT {
+ f_TC_two_crcx_and_rtp_osmux(true, true, mp_local_ipv6, mp_remote_ipv6,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+ /* Same as TC_two_crcx_and_rtp_osmux_bidir, but using IPv4 (RTP) and IPv6 (Osmux) */
+ testcase TC_two_crcx_and_rtp_osmux_bidir_ipv4_ipv6() runs on dummy_CT {
+ f_TC_two_crcx_and_rtp_osmux(true, true, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+ /* Same as TC_two_crcx_and_rtp_osmux_bidir, but using IPv6 (RTP) and IPv4 (Osmux) */
+ testcase TC_two_crcx_and_rtp_osmux_bidir_ipv6_ipv4() runs on dummy_CT {
+ f_TC_two_crcx_and_rtp_osmux(true, true, mp_local_ipv6, mp_remote_ipv6,
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+
+ function f_two_crcx_mdcx_and_rtp_osmux(boolean crcx_osmux_wildcard,
+ charstring local_ip_rtp, charstring remote_ip_rtp,
+ charstring local_ip_osmux, charstring remote_ip_osmux) runs on dummy_CT {
var RtpFlowData flow[2];
var RtpemStats stats_rtp;
var OsmuxemStats stats_osmux;
var MgcpResponse resp;
var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
var MgcpCallId call_id := '1227'H;
- var integer num_pkts_tx[2];
+ var integer num_pkts_tx[2], num_pkts_rx[2];
var integer temp;
f_init(ep, true);
/* Create the first connection in receive only mode */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000"));
+ flow[0] := valueof(t_RtpFlow(local_ip_rtp, remote_ip_rtp, 112, "AMR/8000"));
flow[0].rtp_cfg := c_RtpemDefaultCfg
- flow[0].rtp_cfg.tx_payload_type := flow[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
/* 0014 is the ToC (CMR=AMR4.75) in front of AMR Payload in RTP Payload */
- flow[0].rtp_cfg.rx_fixed_payload := '0014'O & f_osmux_gen_expected_rx_rtp_payload(2 /* AMR_FT_2, 5.90 */, c_OsmuxemDefaultCfg.tx_fixed_payload);
- flow[0].rtp_cfg.tx_fixed_payload := flow[0].rtp_cfg.rx_fixed_payload;
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := '0014'O & f_osmux_gen_expected_rx_rtp_payload(2 /* AMR_FT_2, 5.90 */, c_OsmuxemDefaultCfg.tx_fixed_payload);
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := flow[0].rtp_cfg.rx_payloads[0].fixed_payload;
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
- f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow[0], false);
+ f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow[0], true);
/* Create the second connection. This connection will be also
* in receive only mode */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 110, "AMR/8000"));
+ flow[1] := valueof(t_RtpFlow(local_ip_osmux, remote_ip_osmux, 110, "AMR/8000"));
flow[1].em.portnr := mp_local_osmux_port;
if (crcx_osmux_wildcard) {
- flow[1].osmux_cid := -1;
+ flow[1].osmux.local_cid := -1;
} else {
- flow[1].osmux_cid := 2;
+ flow[1].osmux.local_cid := 2;
}
- flow[1].osmux_cfg := c_OsmuxemDefaultCfg;
- f_flow_create_osmux(OsmuxEM, ep, call_id, "recvonly", flow[1], false);
+ flow[1].osmux.cfg := c_OsmuxemDefaultCfg;
+ f_flow_create_osmux(OsmuxEM, ep, call_id, "recvonly", flow[1], true);
/* The first leg starts transmitting */
@@ -1328,52 +1603,69 @@ module MGCP_Test {
/* The first leg will now be switched into bidirectional
* mode, but we do not expect any data comming back yet. */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
f_flow_modify(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
+ /* At this point in time, flow[1](Osmux)->MGW->flow[0](RTP) is active,
+ * hence if local CID was provided during CRCX we should already be seeing packets
+ * flowing in one direction, aka stats_rtp.num_pkts_rx sould be >0 after a while: */
f_sleep(0.5);
stats_rtp := f_rtpem_stats_get(RTPEM[0]);
if (stats_rtp.num_pkts_rx_err_disabled != 0) {
setverdict(fail, "received packets from RTP MGW on recvonly connection");
mtc.stop;
}
+ if (not crcx_osmux_wildcard and stats_rtp.num_pkts_rx == 0) {
+ setverdict(fail, "received 0 packets Osmux->MGW->RTP");
+ mtc.stop;
+ }
+
stats_osmux := f_osmuxem_stats_get(OsmuxEM);
if (stats_osmux.num_pkts_rx_err_disabled != 0) {
setverdict(fail, "received packets from Osmux MGW on recvonly connection");
mtc.stop;
}
+ if (stats_osmux.num_pkts_rx > 0) {
+ setverdict(fail, "received unexpected ", stats_osmux.num_pkts_rx, " packets RTP->MGW->Osmux");
+ mtc.stop;
+ }
/* When the second leg is switched into bidirectional mode
* as well, then the MGW will connect the two together and
* we should see RTP streams passing through from both ends. */
- f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
f_osmuxem_mode(OsmuxEM, OSMUXEM_MODE_BIDIR);
- stats_rtp := f_rtpem_stats_get(RTPEM[0]);
- num_pkts_tx[0] := stats_rtp.num_pkts_tx
- stats_osmux := f_osmuxem_stats_get(OsmuxEM);
- num_pkts_tx[1] := stats_osmux.num_pkts_tx
-
if (crcx_osmux_wildcard) {
- /* For now we must set same CID as the MGW recvCID,
- * having sendCID!=recvCID is not yet supported. */
- flow[1].osmux_cid := flow[1].osmux_cid_response;
+ /* We set now the local CID in MDCX: */
+ flow[1].osmux.local_cid := 2;
}
f_flow_modify_osmux(OsmuxEM, ep, call_id, "sendrecv", flow[1]);
+ stats_rtp := f_rtpem_stats_get(RTPEM[0]);
+ stats_osmux := f_osmuxem_stats_get(OsmuxEM);
+ num_pkts_tx[0] := stats_rtp.num_pkts_tx;
+ num_pkts_tx[1] := stats_osmux.num_pkts_tx;
+ num_pkts_rx[0] := stats_rtp.num_pkts_rx;
+ num_pkts_rx[1] := stats_osmux.num_pkts_rx;
f_sleep(2.0);
stats_rtp := f_rtpem_stats_get(RTPEM[0]);
stats_osmux := f_osmuxem_stats_get(OsmuxEM);
- temp := stats_rtp.num_pkts_tx - num_pkts_tx[0] - stats_osmux.num_pkts_rx * flow[1].osmux_cfg.batch_size;
- if (temp > 3 * flow[1].osmux_cfg.batch_size or temp < -3 * flow[1].osmux_cfg.batch_size) {
+ temp := (stats_rtp.num_pkts_tx - num_pkts_tx[0]) -
+ (stats_osmux.num_pkts_rx - num_pkts_rx[1]) * flow[1].osmux.cfg.batch_size;
+ if (temp > 3 * flow[1].osmux.cfg.batch_size or temp < -3 * flow[1].osmux.cfg.batch_size) {
log("stats_rtp: ", stats_rtp);
log("stats_osmux: ", stats_osmux);
log("old_rtp_tx: ", num_pkts_tx[0]);
- setverdict(fail, "number of packets not within normal parameters (" & int2str(temp) & ")");
+ setverdict(fail, "RTP-Tx vs OSmux-Rx number of packets not within normal parameters (" & int2str(temp) & ")");
mtc.stop;
}
- temp := stats_osmux.num_pkts_tx - num_pkts_tx[1] - stats_rtp.num_pkts_rx / flow[1].osmux_cfg.batch_size;
+ temp := (stats_osmux.num_pkts_tx - num_pkts_tx[1]) -
+ ((stats_rtp.num_pkts_rx - num_pkts_rx[0])/ flow[1].osmux.cfg.batch_size);
if (temp > 3 or temp < -3) {
- setverdict(fail, "number of packets not within normal parameters (" & int2str(temp) & ")");
+ log("stats_rtp: ", stats_rtp);
+ log("stats_osmux: ", stats_osmux);
+ log("old_osmux_tx: ", num_pkts_tx[1]);
+ setverdict(fail, "Osmux-Tx vs RTP-Rx number of packets not within normal parameters (" & int2str(temp) & ")");
mtc.stop;
}
@@ -1390,14 +1682,32 @@ module MGCP_Test {
directions. Create CRCX with wildcard Osmux CID and set it later
during MDCX. This is similar to how MSC sets up the call in AoIP. */
testcase TC_two_crcx_mdcx_and_rtp_osmux_wildcard() runs on dummy_CT {
- f_two_crcx_mdcx_and_rtp_osmux(true);
+ f_two_crcx_mdcx_and_rtp_osmux(true, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
}
/* create one RTP and one OSmux emulations and pass data in both
directions. Create CRCX with fixed Osmux CID and keep it during
MDCX. This is similar to how BSC sets up the call in AoIP. */
testcase TC_two_crcx_mdcx_and_rtp_osmux_fixed() runs on dummy_CT {
- f_two_crcx_mdcx_and_rtp_osmux(false);
+ f_two_crcx_mdcx_and_rtp_osmux(false, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* Same as TC_two_crcx_mdcx_and_rtp_osmux_wildcard, but using IPv6. */
+ testcase TC_two_crcx_mdcx_and_rtp_osmux_ipv6() runs on dummy_CT {
+ f_two_crcx_mdcx_and_rtp_osmux(false, mp_local_ipv6, mp_remote_ipv6,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+ /* Same as TC_two_crcx_mdcx_and_rtp_osmux_wildcard, but using IPv4 (RTP) and IPv6 (Osmux). */
+ testcase TC_two_crcx_mdcx_and_rtp_osmux_ipv4_ipv6() runs on dummy_CT {
+ f_two_crcx_mdcx_and_rtp_osmux(false, mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+ /* Same as TC_two_crcx_mdcx_and_rtp_osmux_wildcard, but using IPv6 (RTP) and IPv4 (Osmux). */
+ testcase TC_two_crcx_mdcx_and_rtp_osmux_ipv6_ipv4() runs on dummy_CT {
+ f_two_crcx_mdcx_and_rtp_osmux(false, mp_local_ipv6, mp_remote_ipv6,
+ mp_local_ipv4, mp_remote_ipv4);
}
function f_crcx_and_dlcx_ep_callid_connid(MgcpEndpoint ep, MgcpCallId call_id) runs on dummy_CT {
@@ -1528,21 +1838,6 @@ module MGCP_Test {
setverdict(pass);
}
- template (value) RtpFlowData t_RtpFlow(charstring host_a, charstring host_b, uint7_t pt,
- charstring codec) := {
- em := {
- hostname := host_a,
- portnr := omit
- },
- mgw := {
- hostname := host_b,
- portnr := omit
- },
- pt := pt,
- codec := codec,
- osmux_cid_sent := false
- }
-
/* transmit RTP streams between two RTP Emulations back-to-back; expect no loss */
testcase TC_rtpem_selftest() runs on dummy_CT {
var RtpemStats stats[2];
@@ -1588,9 +1883,9 @@ module MGCP_Test {
var RtpemStats stats;
f_init(ep);
- flow := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000/1"));
+ flow := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 112, "AMR/8000/1"));
flow.em.portnr := 10000;
- f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow, false);
+ f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow, true);
f_rtpem_mode(RTPEM[0], RTPEM_MODE_TXONLY);
f_sleep(1.0);
@@ -1619,16 +1914,16 @@ module MGCP_Test {
/* Create one connection in loopback mode, test if the RTP packets are
* actually reflected */
- testcase TC_one_crcx_loopback_rtp() runs on dummy_CT {
+ function f_TC_one_crcx_loopback_rtp(charstring local_ip, charstring remote_ip, boolean one_phase := true) runs on dummy_CT {
var RtpFlowData flow;
var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "1@" & c_mgw_domain;
var MgcpCallId call_id := '1225'H;
var RtpemStats stats;
f_init(ep);
- flow := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 111, "GSM-HR-08/8000/1"));
+ flow := valueof(t_RtpFlow(local_ip, remote_ip, 112, "GSM-HR-08/8000/1"));
flow.em.portnr := 10000;
- f_flow_create(RTPEM[0], ep, call_id, "loopback", flow);
+ f_flow_create(RTPEM[0], ep, call_id, "loopback", flow, one_phase := one_phase);
f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
f_sleep(1.0);
@@ -1636,11 +1931,22 @@ module MGCP_Test {
stats := f_rtpem_stats_get(RTPEM[0]);
- if (stats.num_pkts_tx != stats.num_pkts_rx) {
- setverdict(fail);
- }
- if (stats.bytes_payload_tx != stats.bytes_payload_rx) {
- setverdict(fail);
+ if (one_phase) {
+ /* osmo-mgw knows both local and remote RTP address. Expect all packets to be reflected. */
+ if (stats.num_pkts_tx != stats.num_pkts_rx) {
+ setverdict(fail);
+ }
+ if (stats.bytes_payload_tx != stats.bytes_payload_rx) {
+ setverdict(fail);
+ }
+ } else {
+ /* osmo-mgw knows only the local RTP address. Expect no packets to be reflected. */
+ if (stats.num_pkts_rx > 0) {
+ setverdict(fail, "stats.num_pkts_rx=", stats.num_pkts_rx, ": osmo-mgw should not send RTP packets to an arbitrary peer");
+ }
+ if (stats.bytes_payload_rx > 0) {
+ setverdict(fail);
+ }
}
f_rtpem_stats_err_check(stats);
@@ -1648,6 +1954,24 @@ module MGCP_Test {
setverdict(pass);
}
+ /* Create one connection in loopback mode, test if the RTP packets are
+ * actually reflected */
+ testcase TC_one_crcx_loopback_rtp() runs on dummy_CT {
+ f_TC_one_crcx_loopback_rtp(mp_local_ipv4, mp_remote_ipv4, one_phase := true)
+ }
+ testcase TC_one_crcx_loopback_rtp_ipv6() runs on dummy_CT {
+ f_TC_one_crcx_loopback_rtp(mp_local_ipv6, mp_remote_ipv6, one_phase := true)
+ }
+
+ /* Same as above, but we will intenionally not tell the MGW where to
+ * send the outgoing traffic. The connection is still created in
+ * loopback mode, so the MGW should take the originating address from
+ * the incoming RTP packet and send it back to the source */
+ testcase TC_one_crcx_loopback_rtp_implicit() runs on dummy_CT {
+ f_TC_one_crcx_loopback_rtp(mp_local_ipv6, mp_remote_ipv6, one_phase := false)
+ }
+
+
function f_TC_two_crcx_and_rtp(boolean bidir, charstring codec_name_a, integer pt_a,
charstring codec_name_b, integer pt_b) runs on dummy_CT {
var RtpFlowData flow[2];
@@ -1660,13 +1984,13 @@ module MGCP_Test {
f_init(ep);
/* from us to MGW */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, pt_a, codec_name_a));
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, pt_a, codec_name_a));
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* from MGW back to us */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, pt_b, codec_name_b));
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, pt_b, codec_name_b));
flow[1].em.portnr := 20000;
f_flow_create(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
@@ -1724,7 +2048,10 @@ module MGCP_Test {
}
/* create two local RTP emulations and pass data in both directions */
- testcase TC_two_crcx_mdcx_and_rtp() runs on dummy_CT {
+ function f_tc_two_crcx_mdcx_and_rtp(charstring local_ip_a, charstring remote_ip_a,
+ charstring local_ip_b, charstring remote_ip_b,
+ uint7_t payload_type := 3,
+ charstring codec_name := "GSM/8000/1") runs on dummy_CT {
var RtpFlowData flow[2];
var RtpemStats stats[2];
var MgcpResponse resp;
@@ -1736,27 +2063,27 @@ module MGCP_Test {
f_init(ep);
/* Create the first connection in receive only mode */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 3, "GSM/8000/1"));
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, payload_type, codec_name));
flow[0].em.portnr := 10000;
- f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow[0], false);
+ f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow[0], true);
/* Create the second connection. This connection will be also
* in receive only mode */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 3, "GSM/8000/1"));
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, payload_type, codec_name));
flow[1].em.portnr := 20000;
- f_flow_create(RTPEM[1], ep, call_id, "recvonly", flow[1], false);
+ f_flow_create(RTPEM[1], ep, call_id, "recvonly", flow[1], true);
/* The first leg starts transmitting */
f_rtpem_mode(RTPEM[0], RTPEM_MODE_TXONLY);
f_sleep(0.5);
stats[0] := f_rtpem_stats_get(RTPEM[0]);
if (stats[0].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
mtc.stop;
}
stats[1] := f_rtpem_stats_get(RTPEM[1]);
if (stats[1].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
mtc.stop;
}
@@ -1765,40 +2092,39 @@ module MGCP_Test {
f_sleep(1.0);
stats[0] := f_rtpem_stats_get(RTPEM[0]);
if (stats[0].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
mtc.stop;
}
stats[1] := f_rtpem_stats_get(RTPEM[1]);
if (stats[1].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
mtc.stop;
}
/* The first leg will now be switched into bidirectional
* mode, but we do not expect any data comming back yet. */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ num_pkts_tx[1] := stats[1].num_pkts_tx;
f_flow_modify(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
f_sleep(0.5);
stats[0] := f_rtpem_stats_get(RTPEM[0]);
- if (stats[1].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ if (stats[0].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
mtc.stop;
}
stats[1] := f_rtpem_stats_get(RTPEM[1]);
if (stats[1].num_pkts_rx_err_disabled != 0) {
- setverdict(fail, "received packets from MGW on recvonly connection");
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
mtc.stop;
}
/* When the second leg is switched into bidirectional mode
* as well, then the MGW will connect the two together and
* we should see RTP streams passing through from both ends. */
- f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
f_rtpem_mode(RTPEM[1], RTPEM_MODE_BIDIR);
stats[0] := f_rtpem_stats_get(RTPEM[0]);
- num_pkts_tx[0] := stats[0].num_pkts_tx
- stats[1] := f_rtpem_stats_get(RTPEM[1]);
- num_pkts_tx[1] := stats[1].num_pkts_tx
-
+ num_pkts_tx[0] := stats[0].num_pkts_tx;
f_flow_modify(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
f_sleep(2.0);
@@ -1807,13 +2133,13 @@ module MGCP_Test {
temp := stats[0].num_pkts_tx - num_pkts_tx[0] - stats[1].num_pkts_rx;
if (temp > 3 or temp < -3) {
- setverdict(fail, "number of packets not within normal parameters");
+ setverdict(fail, "number of packets not within normal parameters:", temp);
mtc.stop;
}
temp := stats[1].num_pkts_tx - num_pkts_tx[1] - stats[0].num_pkts_rx;
if (temp > 3 or temp < -3) {
- setverdict(fail, "number of packets not within normal parameters");
+ setverdict(fail, "number of packets not within normal parameters:", temp);
mtc.stop;
}
@@ -1826,6 +2152,28 @@ module MGCP_Test {
setverdict(pass);
}
+ testcase TC_two_crcx_mdcx_and_rtp() runs on dummy_CT {
+ f_tc_two_crcx_mdcx_and_rtp(mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ testcase TC_two_crcx_mdcx_and_rtp_ipv6() runs on dummy_CT {
+ f_tc_two_crcx_mdcx_and_rtp(mp_local_ipv6, mp_remote_ipv6,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+
+ testcase TC_two_crcx_mdcx_and_rtp_ipv4_ipv6() runs on dummy_CT {
+ f_tc_two_crcx_mdcx_and_rtp(mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv6, mp_remote_ipv6);
+ }
+
+ testcase TC_two_crcx_mdcx_and_rtp_clearmode() runs on dummy_CT {
+ f_tc_two_crcx_mdcx_and_rtp(mp_local_ipv4, mp_remote_ipv4,
+ mp_local_ipv4, mp_remote_ipv4,
+ 120, /* 3GPP TS 48.103 table 5.4.2.2.1 */
+ "CLEARMODE/8000");
+ }
+
/* Test what happens when two RTP streams from different sources target
* a single connection. Is the unsolicited stream properly ignored? */
testcase TC_two_crcx_and_unsolicited_rtp() runs on dummy_CT {
@@ -1839,13 +2187,13 @@ module MGCP_Test {
f_init(ep);
/* from us to MGW */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 98, "AMR/8000"));
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 98, "AMR/8000"));
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* from MGW back to us */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 98, "AMR/8000"));
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 98, "AMR/8000"));
flow[1].em.portnr := 20000;
f_flow_create(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
@@ -1855,8 +2203,8 @@ module MGCP_Test {
f_sleep(0.5);
/* Start inserting unsolicited RTP packets */
- f_rtpem_bind(RTPEM[2], mp_local_ip, unsolicited_port);
- f_rtpem_connect(RTPEM[2], mp_remote_ip, flow[0].mgw.portnr);
+ f_rtpem_bind(RTPEM[2], mp_local_ipv4, unsolicited_port);
+ f_rtpem_connect(RTPEM[2], mp_remote_ipv4, flow[0].mgw.portnr);
f_rtpem_mode(RTPEM[2], RTPEM_MODE_TXONLY);
f_sleep(0.5);
@@ -1892,13 +2240,13 @@ module MGCP_Test {
f_init(ep);
/* First connection (BTS) */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 110, "GSM-EFR/8000"));
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 110, "GSM-EFR/8000"));
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* Second connection (PBX) */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 110, "GSM-EFR/8000"));
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 110, "GSM-EFR/8000"));
flow[1].em.portnr := 20000;
f_flow_create(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
@@ -1918,8 +2266,8 @@ module MGCP_Test {
* transmitting for a while. We simulate this by injecting
* some unsolicited packets on the behalf of the old source,
* (old remote port) */
- f_rtpem_bind(RTPEM[2], mp_local_ip, port_old);
- f_rtpem_connect(RTPEM[2], mp_remote_ip, flow[0].mgw.portnr);
+ f_rtpem_bind(RTPEM[2], mp_local_ipv4, port_old);
+ f_rtpem_connect(RTPEM[2], mp_remote_ipv4, flow[0].mgw.portnr);
f_rtpem_mode(RTPEM[2], RTPEM_MODE_TXONLY);
f_sleep(1.0);
f_rtpem_mode(RTPEM[2], RTPEM_MODE_NONE);
@@ -1948,10 +2296,62 @@ module MGCP_Test {
setverdict(pass);
}
+ testcase TC_two_crcx_confecho_sendonly_rtp() runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1225'H;
+ var RtpemStats stats[2];
+
+ f_init(ep);
+
+ /* "Talker" is sending to MGW and receives echo. */
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 112, "GSM-HR-08/8000/1"));
+ flow[0].em.portnr := 10000;
+ f_flow_create(RTPEM[0], ep, call_id, "confecho", flow[0]);
+
+ /* "Listener" receives from MGW. */
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 112, "GSM-HR-08/8000/1"));
+ flow[1].em.portnr := 20000;
+ f_flow_create(RTPEM[1], ep, call_id, "sendonly", flow[1]);
+
+
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_BIDIR);
+ f_sleep(1.0);
+ f_flow_delete(RTPEM[0]);
+ f_flow_delete(RTPEM[1], ep, call_id);
+
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+
+ /* The "Talker" will receive his RTP, so TX must match RX.
+ * As RTP from "Listener" is ignored, no extra packets shall be received. */
+ if (stats[0].num_pkts_tx != stats[0].num_pkts_rx) {
+ setverdict(fail, "Talker does not receive as many packets as it transmits!");
+ }
+ if (stats[0].bytes_payload_tx != stats[0].bytes_payload_rx) {
+ setverdict(fail, "Talker does not receive as many payload as it transmits!");
+ }
+
+ /* The "Listener" will also receive RTP of the "Talker",
+ * so TX of "Talker" must match RX of "Listener". */
+ if (stats[0].num_pkts_tx != stats[1].num_pkts_rx) {
+ setverdict(fail, "Listener does not receive as many packets as talker transmits!");
+ }
+ if (stats[0].bytes_payload_tx != stats[1].bytes_payload_rx) {
+ setverdict(fail, "Listener does not receive as many payload as talker transmits!");
+ }
+
+ f_rtpem_stats_err_check(stats[0]);
+ f_rtpem_stats_err_check(stats[1]);
+
+ setverdict(pass);
+ }
+
/* create two local RTP emulations; create two connections on MGW EP, see if
- * exchanged data is converted bwtween ts101318 and rfc5993 */
- testcase TC_ts101318_rfc5993_rtp_conversion() runs on dummy_CT {
+ * exchanged data is converted between ts101318 and rfc5993 */
+ function f_ts101318_rfc5993_rtp_conversion(octetstring pl0, octetstring pl1, charstring fmtp0, charstring fmtp1) runs on dummy_CT {
var RtpFlowData flow[2];
var RtpemStats stats[2];
var MgcpResponse resp;
@@ -1966,22 +2366,24 @@ module MGCP_Test {
f_vty_transceive(MGWVTY, "rtp-patch rfc5993hr");
/* Connection #0 (Bidirectional) */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 111, "GSM-HR-08/8000"));
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 111, "GSM-HR-08/8000", fmtp0));
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
flow[0].rtp_cfg := c_RtpemDefaultCfg;
- flow[0].rtp_cfg.tx_payload_type := flow[0].pt;
- flow[0].rtp_cfg.rx_fixed_payload := '0b11b3eede60be4e3ec68838c7b5'O;
- flow[0].rtp_cfg.tx_fixed_payload := '0b11b3eede60be4e3ec68838c7b5'O;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := pl0;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := pl0;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* Connection #1 (Bidirectional) */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 111, "GSM-HR-08/8000"));
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 111, "GSM-HR-08/8000", fmtp1));
flow[1].em.portnr := 20000;
flow[1].rtp_cfg := c_RtpemDefaultCfg;
- flow[1].rtp_cfg.tx_payload_type := flow[1].pt;
- flow[1].rtp_cfg.rx_fixed_payload := '000b11b3eede60be4e3ec68838c7b5'O;
- flow[1].rtp_cfg.tx_fixed_payload := '000b11b3eede60be4e3ec68838c7b5'O;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.rx_payloads[0].fixed_payload := pl1;
+ flow[1].rtp_cfg.tx_payloads[0].fixed_payload := pl1;
f_flow_create(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
/* Send RTP packets to connection #0, receive on connection #1 */
@@ -2018,10 +2420,23 @@ module MGCP_Test {
setverdict(pass);
}
+ const octetstring rtp_hr_gsm_ts101318 := '0b11b3eede60be4e3ec68838c7b5'O;
+ const octetstring rtp_hr_gsm_rfc5993 := '000b11b3eede60be4e3ec68838c7b5'O;
+
+ testcase TC_ts101318_rfc5993_rtp_conversion() runs on dummy_CT {
+ f_ts101318_rfc5993_rtp_conversion(rtp_hr_gsm_ts101318, rtp_hr_gsm_rfc5993, "", "");
+ }
+
+ testcase TC_ts101318_rfc5993_rtp_conversion_fmtp() runs on dummy_CT {
+ f_ts101318_rfc5993_rtp_conversion(rtp_hr_gsm_ts101318, rtp_hr_gsm_rfc5993, "gsm-hr-format=ts101318", "gsm-hr-format=rfc5993");
+ }
+
/* create two local RTP emulations; create two connections on MGW EP, see if
- * exchanged data is converted between AMR octet-aligned and bandwith
+ * exchanged data is converted between AMR octet-aligned and bandwidth
* efficient-mode */
- function f_TC_amr_x_x_rtp_conversion(octetstring pl0, octetstring pl1, charstring fmtp0, charstring fmtp1) runs on dummy_CT {
+ function f_TC_amr_x_x_rtp_conversion(charstring fmtp0, octetstring pl0,
+ charstring fmtp1a, octetstring pl1a,
+ charstring fmtp1b, octetstring pl1b) runs on dummy_CT {
var RtpFlowData flow[2];
var RtpemStats stats[2];
var MgcpResponse resp;
@@ -2031,24 +2446,36 @@ module MGCP_Test {
f_init(ep);
/* Connection #0 (Bidirectional) */
- flow[0] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000"));
+ flow[0] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 96, "AMR/8000", fmtp0));
/* bind local RTP emulation sockets */
flow[0].em.portnr := 10000;
flow[0].rtp_cfg := c_RtpemDefaultCfg;
- flow[0].rtp_cfg.tx_payload_type := flow[0].pt;
- flow[0].rtp_cfg.rx_fixed_payload := pl0;
- flow[0].rtp_cfg.tx_fixed_payload := pl0;
- flow[0].fmtp := fmtp0;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := pl0;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := pl0;
f_flow_create(RTPEM[0], ep, call_id, "sendrecv", flow[0]);
/* Connection #1 (Bidirectional) */
- flow[1] := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 112, "AMR/8000"));
+ flow[1] := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 112, "AMR/8000", fmtp1a));
flow[1].em.portnr := 20000;
flow[1].rtp_cfg := c_RtpemDefaultCfg;
- flow[1].rtp_cfg.tx_payload_type := flow[1].pt;
- flow[1].rtp_cfg.rx_fixed_payload := pl1;
- flow[1].rtp_cfg.tx_fixed_payload := pl1;
- flow[1].fmtp := fmtp1;
+ flow[1].rtp_cfg.rx_payloads := {};
+ flow[1].rtp_cfg.tx_payloads := {};
+ if (pl1a != ''O) {
+ flow[1].rtp_cfg.rx_payloads := flow[1].rtp_cfg.rx_payloads & {{112, pl1a}};
+ flow[1].rtp_cfg.tx_payloads := flow[1].rtp_cfg.tx_payloads & {{112, pl1a}};
+ }
+
+ /* The second fmtp parameter is to simulate a call agent that offers the transmission both modes. */
+ if (fmtp1b != "") {
+ flow[1].codec_descr := flow[1].codec_descr & {{113, "AMR/8000", fmtp1b}};
+ if (pl1b != ''O) {
+ flow[1].rtp_cfg.rx_payloads := flow[1].rtp_cfg.rx_payloads & {{113, pl1b}};
+ flow[1].rtp_cfg.tx_payloads := flow[1].rtp_cfg.tx_payloads & {{113, pl1b}};
+ }
+ }
+
f_flow_create(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
/* Send RTP packets to connection #0, receive on connection #1 */
@@ -2086,16 +2513,46 @@ module MGCP_Test {
* functions are real world AMR RTP payloads including AMR header. The
* payloads were extracted from a trace with known good payloads. */
+ const octetstring rtp_amr_5_90k_oa := '2014e959f35fdfe5e9667ffbc088818088'O;
+ const octetstring rtp_amr_5_90k_bwe := '217a567cd7f7f97a599ffef022206022'O;
+ const octetstring rtp_amr_5_15k_oa := '100c4e9ba850e30d5d53d04de41e7c'O;
+ const octetstring rtp_amr_5_15k_bwe := '10d3a6ea1438c35754f41379079f'O;
+
+ /* Only one codec on each side */
testcase TC_amr_oa_bwe_rtp_conversion() runs on dummy_CT {
- f_TC_amr_x_x_rtp_conversion('2014e959f35fdfe5e9667ffbc088818088'O, '217a567cd7f7f97a599ffef022206022'O, "octet-align=1", "octet-align=0");
+ f_TC_amr_x_x_rtp_conversion("octet-align=1", rtp_amr_5_90k_oa, "octet-align=0", rtp_amr_5_90k_bwe, "", ''O);
}
-
testcase TC_amr_oa_oa_rtp_conversion() runs on dummy_CT {
- f_TC_amr_x_x_rtp_conversion('100c4e9ba850e30d5d53d04de41e7c'O, '100c4e9ba850e30d5d53d04de41e7c'O, "octet-align=1", "octet-align=1");
+ f_TC_amr_x_x_rtp_conversion("octet-align=1", rtp_amr_5_15k_oa, "octet-align=1", rtp_amr_5_15k_oa, "", ''O);
}
-
testcase TC_amr_bwe_bwe_rtp_conversion() runs on dummy_CT {
- f_TC_amr_x_x_rtp_conversion('10d3a6ea1438c35754f41379079f'O, '10d3a6ea1438c35754f41379079f'O, "octet-align=0", "octet-align=0");
+ f_TC_amr_x_x_rtp_conversion("octet-align=0", rtp_amr_5_15k_bwe, "octet-align=0", rtp_amr_5_15k_bwe, "", ''O);
+ }
+
+ /* Only one codec on one side, two codecs (compatibility) on other side. The payloads are the same on both
+ * sides, so the expectation is that conversion must not be performed. Each test is done with both formats in
+ * two different configurations.*/
+ testcase TC_amr_oa_oa_no_bwe_rtp_conversion() runs on dummy_CT {
+ f_TC_amr_x_x_rtp_conversion("octet-align=1", rtp_amr_5_15k_oa,
+ "octet-align=1", rtp_amr_5_15k_oa,
+ "octet-align=0", ''O); /* We expect to see NO bandwidth efficient packets! */
+ }
+ testcase TC_amr_oa_no_bwe_oa_rtp_conversion() runs on dummy_CT {
+ /* (Same as above but flipped on the opposite side) */
+ f_TC_amr_x_x_rtp_conversion("octet-align=1", rtp_amr_5_15k_oa,
+ "octet-align=0", ''O, /* We expect to see NO bandwidth efficient packets! */
+ "octet-align=1", rtp_amr_5_15k_oa);
+ }
+ testcase TC_amr_bwe_bwe_no_oa_rtp_conversion() runs on dummy_CT {
+ f_TC_amr_x_x_rtp_conversion("octet-align=0", rtp_amr_5_15k_bwe,
+ "octet-align=0", rtp_amr_5_15k_bwe,
+ "octet-align=1", ''O); /* We expect to see NO octet aligned packets! */
+ }
+ testcase TC_amr_bwe_no_oa_bwe_rtp_conversion() runs on dummy_CT {
+ /* (Same as above but flipped on the opposite side) */
+ f_TC_amr_x_x_rtp_conversion("octet-align=0", rtp_amr_5_15k_bwe,
+ "octet-align=1", ''O, /* We expect to see NO octet aligned packets! */
+ "octet-align=0", rtp_amr_5_15k_bwe);
}
/* TODO: Double-DLCX (no retransmission) */
@@ -2118,10 +2575,10 @@ module MGCP_Test {
f_init(ep);
log("Setting conn-timeout to 1s");
- f_vty_config(MGWVTY, "mgcp", "conn-timeout 1"); /* reset in f_init_vty() */
+ f_vty_config(MGWVTY, "mgcp", "conn-timeout 1");
log("Sending RTP data for 1.5s");
- flow := valueof(t_RtpFlow(mp_local_ip, mp_remote_ip, 111, "GSM-HR-08/8000/1"));
+ flow := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 111, "GSM-HR-08/8000/1"));
flow.em.portnr := 10000;
f_flow_create(RTPEM[0], ep, call_id, "loopback", flow);
f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
@@ -2143,15 +2600,695 @@ module MGCP_Test {
f_sleep(0.2);
f_rtpem_conn_refuse_verify(RTPEM[0]);
+ log("Setting conn-timeout back to 0 (disabled)");
+ f_vty_config(MGWVTY, "mgcp", "conn-timeout 0");
+
+ setverdict(pass);
+ }
+
+ /* Test (valid) CRCX followed by (valid) DLCX containing EP (E1) */
+ testcase TC_e1_crcx_and_dlcx_ep() runs on dummy_CT {
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var MgcpEndpoint ep := "ds/e1-1/s-1/su16-0@" & c_mgw_domain;
+ var MgcpCallId call_id := '8376F297'H;
+
+ f_init(ep);
+
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+
+ f_dlcx_ok(ep);
+
+ setverdict(pass);
+ }
+
+ /* Test what happens when overlapping endpoints are selected (E1) */
+ testcase TC_e1_crcx_with_overlap() runs on dummy_CT {
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var MgcpEndpoint ep_1 := "ds/e1-1/s-1/su8-0@" & c_mgw_domain;
+ var MgcpEndpoint ep_2 := "ds/e1-1/s-1/su16-0@" & c_mgw_domain;
+ var MgcpCallId call_id_1 := '8376F297'H;
+ var MgcpCallId call_id_2 := '837AF2A7'H;
+
+ f_init();
+
+ /* ep_1 and ep_2 are overlapping, selecting both one after
+ * another should work fine: */
+ cmd := ts_CRCX(get_next_trans_id(), ep_1, "recvonly", call_id_1);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ f_dlcx_ok(ep_1);
+ cmd := ts_CRCX(get_next_trans_id(), ep_2, "recvonly", call_id_2);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ f_dlcx_ok(ep_2);
+
+ /* When ep_1 is serving a call we can not select ep_2 becaus
+ * it is overlapping with ep_1 */
+ cmd := ts_CRCX(get_next_trans_id(), ep_1, "recvonly", call_id_1);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ cmd := ts_CRCX(get_next_trans_id(), ep_2, "recvonly", call_id_2);
+ resp := mgcp_transceive_mgw(cmd, ?);
+ if (resp.line.code != "501") {
+ setverdict(fail, "unexpected CRCX returncode, CRCX should fail!");
+ }
+ f_dlcx_ok(ep_1);
+
setverdict(pass);
}
+ /* Create one connection in loopback mode, test if the RTP packets are
+ * actually reflected */
+ testcase TC_e1_crcx_loopback() runs on dummy_CT {
+ var RtpFlowData flow;
+ var MgcpEndpoint ep := "ds/e1-1/s-1/su16-0@" & c_mgw_domain;
+ var MgcpCallId call_id := '12250989'H;
+ var RtpemStats stats;
+
+ f_init(ep);
+ flow := valueof(t_RtpFlow(mp_local_ipv4, mp_remote_ipv4, 111, "GSM-HR-08/8000/1"));
+ flow.em.portnr := 10000;
+ f_flow_create(RTPEM[0], ep, call_id, "loopback", flow);
+
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
+ f_sleep(1.0);
+ f_flow_delete(RTPEM[0], ep, call_id);
+
+ stats := f_rtpem_stats_get(RTPEM[0]);
+
+ if (stats.num_pkts_tx != stats.num_pkts_rx) {
+ setverdict(fail);
+ }
+ if (stats.bytes_payload_tx != stats.bytes_payload_rx) {
+ setverdict(fail);
+ }
+
+ f_rtpem_stats_err_check(stats);
+
+ setverdict(pass);
+ }
+
+ /* test valid wildcarded DLCX on an E1 trunk */
+ testcase TC_e1_dlcx_wildcarded() runs on dummy_CT {
+ var template MgcpCommand cmd;
+ var MgcpEndpoint ep;
+ var MgcpCallId call_id := '8376F297'H;
+ var integer n_e1_ts := 4;
+ var StatsDExpects expect;
+
+ f_init();
+
+ /* Open a few E1 timeslots */
+ for (var integer i := 0; i < n_e1_ts; i := i+1) {
+ ep := "ds/e1-1/s-" & int2str(i+1) & "/su16-0@" & c_mgw_domain;
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ ep := "ds/e1-1/s-" & int2str(i+1) & "/su16-2@" & c_mgw_domain;
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ ep := "ds/e1-1/s-" & int2str(i+1) & "/su16-4@" & c_mgw_domain;
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ ep := "ds/e1-1/s-" & int2str(i+1) & "/su16-6@" & c_mgw_domain;
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ }
+
+ /* Wait until the stats items have settled and then check if we get the expected number (all) of
+ * occupied endpoints */
+ f_sleep(1.0)
+ expect := {
+ { name := "TTCN3.trunk.e1-1.common.endpoints.used", mtype := "g", min := n_e1_ts * 4, max := n_e1_ts * 4}
+ };
+ f_statsd_expect(expect);
+
+ /* Send wildcarded DLCX */
+ var template MgcpResponse rtmpl := {
+ line := {
+ code := "200",
+ string := ?
+ },
+ params:= { },
+ sdp := omit
+ };
+ ep := "ds/e1-1/*@" & c_mgw_domain;
+ cmd := ts_DLCX(get_next_trans_id(), ep);
+ mgcp_transceive_mgw(cmd, rtmpl);
+
+ /* Query the statsd once to ensure that intermediate results are pulled from the
+ * pipeline. The second query (below) will return the actual result. */
+ expect := {
+ { name := "TTCN3.trunk.e1-1.common.endpoints.used", mtype := "g", min := 0, max := n_e1_ts * 4}
+ };
+ f_statsd_expect(expect);
+
+ /* The second query must return a result with 0 endpoints in use. */
+ expect := {
+ { name := "TTCN3.trunk.e1-1.common.endpoints.used", mtype := "g", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
+ setverdict(pass);
+ }
+
+ /* test valid CRCX then MDCX with IPv4 address, MGW provides a local IPv4 too */
+ testcase TC_crcx_mdcx_ip4() runs on dummy_CT {
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var MgcpCallId call_id := '1234'H;
+ var MgcpConnectionId conn_id;
+
+ f_init(ep);
+
+ /* create the connection on the MGW */
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ conn_id := extract_conn_id(resp);
+
+ cmd := ts_MDCX(get_next_trans_id(), ep, "sendrecv", call_id, conn_id);
+ cmd.sdp := ts_SDP("127.0.0.2", "127.0.0.1", "23", "42", 2344, { "98" },
+ { valueof(ts_SDP_rtpmap(98, "AMR/8000")),
+ valueof(ts_SDP_ptime(20)) });
+ resp := mgcp_transceive_mgw(cmd, tr_MDCX_ACK);
+
+ if (not ispresent(resp.sdp) or not ispresent(resp.sdp.connection)) {
+ setverdict(fail, "No RemoteConnection info found in MDCX ACK!");
+ }
+ if (not match(resp.sdp.connection, ts_SDP_connection_IP("127.0.0.1", "IP4"))) {
+ setverdict(fail, "Wrong RemoteConnection in MDCX ACK!", resp.sdp.connection);
+ }
+
+ /* clean-up */
+ f_dlcx_ok(ep, call_id);
+ setverdict(pass);
+ }
+
+ /* test valid CRCX then MDCX with IPv6 address, MGW provides a local IPv6 too */
+ testcase TC_crcx_mdcx_ip6() runs on dummy_CT {
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var template MgcpCommand cmd;
+ var MgcpResponse resp;
+ var MgcpCallId call_id := '1234'H;
+ var MgcpConnectionId conn_id;
+
+ f_init(ep);
+
+ /* create the connection on the MGW */
+ cmd := ts_CRCX(get_next_trans_id(), ep, "recvonly", call_id);
+ resp := mgcp_transceive_mgw(cmd, tr_CRCX_ACK);
+ conn_id := extract_conn_id(resp);
+
+ cmd := ts_MDCX(get_next_trans_id(), ep, "sendrecv", call_id, conn_id);
+ cmd.sdp := ts_SDP("::2", "::1", "23", "42", 2344, { "98" },
+ { valueof(ts_SDP_rtpmap(98, "AMR/8000")),
+ valueof(ts_SDP_ptime(20)) });
+ resp := mgcp_transceive_mgw(cmd, tr_MDCX_ACK);
+
+ if (not ispresent(resp.sdp) or not ispresent(resp.sdp.connection)) {
+ setverdict(fail, "No RemoteConnection info found in MDCX ACK!");
+ }
+ if (not match(resp.sdp.connection, ts_SDP_connection_IP("::1", "IP6"))) {
+ setverdict(fail, "Wrong RemoteConnection in MDCX ACK!", resp.sdp.connection);
+ }
+
+ /* clean-up */
+ f_dlcx_ok(ep, call_id);
+ setverdict(pass);
+ }
+
+ /* create two local emulations and pass data in both directions */
+ function f_two_crcx_mdcx_data_transfer(MgcpEndpoint ep, MgcpCallId call_id, inout RtpFlowData flow_a,
+ inout RtpFlowData flow_b, boolean tear_down_rtp := true) runs on dummy_CT {
+ var RtpemStats stats[2];
+ var MgcpResponse resp;
+ var integer num_pkts_tx[2];
+ var integer temp;
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ f_flow_create(RTPEM[0], ep, call_id, "recvonly", flow_a, true);
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_RXONLY);
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, regular RTP) */
+ f_flow_create(RTPEM[1], ep, call_id, "recvonly", flow_b, true);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_RXONLY);
+
+ /* The first leg starts transmitting */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_TXONLY);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ if (stats[0].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
+ mtc.stop;
+ }
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ if (stats[1].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
+ mtc.stop;
+ }
+
+ /* The second leg starts transmitting a little later */
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_TXONLY);
+ f_sleep(1.0);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ if (stats[0].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
+ mtc.stop;
+ }
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ if (stats[1].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
+ mtc.stop;
+ }
+
+ /* The first leg will now be switched into bidirectional
+ * mode, but we do not expect any data coming back yet. */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ num_pkts_tx[1] := stats[1].num_pkts_tx;
+ f_flow_modify(RTPEM[0], ep, call_id, "sendrecv", flow_a);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ if (stats[0].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 0");
+ mtc.stop;
+ }
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ if (stats[1].num_pkts_rx_err_disabled != 0) {
+ setverdict(fail, "received packets from MGW on recvonly connection 1");
+ mtc.stop;
+ }
+
+ /* When the second leg is switched into bidirectional mode
+ * as well, then the MGW will connect the two together and
+ * we should see RTP streams passing through from both ends. */
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_BIDIR);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ num_pkts_tx[0] := stats[0].num_pkts_tx;
+ f_flow_modify(RTPEM[1], ep, call_id, "sendrecv", flow_b);
+ f_sleep(2.0);
+
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+
+ temp := stats[0].num_pkts_tx - num_pkts_tx[0] - stats[1].num_pkts_rx;
+ if (temp > 3 or temp < -3) {
+ setverdict(fail, "number of packets not within normal parameters:", temp);
+ mtc.stop;
+ }
+
+ temp := stats[1].num_pkts_tx - num_pkts_tx[1] - stats[0].num_pkts_rx;
+ if (temp > 3 or temp < -3) {
+ setverdict(fail, "number of packets not within normal parameters:", temp);
+ mtc.stop;
+ }
+
+ f_rtpem_stats_err_check(stats[0]);
+ f_rtpem_stats_err_check(stats[1]);
+
+ /* Tear down */
+ if (tear_down_rtp) {
+ f_flow_delete(RTPEM[0]);
+ f_flow_delete(RTPEM[1], ep, call_id);
+ }
+ setverdict(pass);
+ }
+
+ /* create two local RTP+IuUP emulations and pass data in both directions */
+ function f_tc_two_crcx_mdcx_and_iuup(charstring local_ip_a, charstring remote_ip_a,
+ IuUP_RabFlowCombinationList rfcl_a,
+ charstring local_ip_b, charstring remote_ip_b) runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1227'H;
+
+ f_init(ep);
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, 96, "VND.3GPP.IUFP/16000"));
+ flow[0].em.portnr := 10000;
+ flow[0].rtp_cfg := c_RtpemDefaultCfg;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.iuup_mode := true;
+ flow[0].rtp_cfg.iuup_cfg.active_init := true;
+ flow[0].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, IuUP-Init passive) */
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, 96, "VND.3GPP.IUFP/16000"));
+ flow[1].em.portnr := 20000;
+ flow[1].rtp_cfg := c_RtpemDefaultCfg;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.iuup_mode := true;
+ flow[1].rtp_cfg.iuup_cfg.active_init := false;
+
+ f_two_crcx_mdcx_data_transfer(ep, call_id, flow[0], flow[1], true);
+ setverdict(pass);
+ }
+ testcase TC_two_crcx_mdcx_and_iuup() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(0),
+ t_IuUP_RFC_AMR_SID(1),
+ t_IuUP_RFC_AMR_NO_DATA(2)
+ };
+ f_tc_two_crcx_mdcx_and_iuup(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+ /* Same as TC_two_crcx_mdcx_and_iuup, but passing unordered RFCI list (ID != position) */
+ testcase TC_two_crcx_mdcx_and_iuup_rfci_unordered() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(1),
+ t_IuUP_RFC_AMR_SID(2),
+ t_IuUP_RFC_AMR_NO_DATA(0)
+ };
+ f_tc_two_crcx_mdcx_and_iuup(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* Test that once IuUP->RTP has been set up, if the RTP/IuUP conn is set
+ * as "recvonly", no more RTP/IuUP packets get out of the MGW. */
+ function f_tc_two_crcx_mdcx_and_iuup_mdcx_recvonly(charstring local_ip_a, charstring remote_ip_a,
+ IuUP_RabFlowCombinationList rfcl_a,
+ charstring local_ip_b, charstring remote_ip_b) runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1227'H;
+ var RtpemStats stats[2];
+
+ f_init(ep);
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, 96, "VND.3GPP.IUFP/16000"));
+ flow[0].em.portnr := 10000;
+ flow[0].rtp_cfg := c_RtpemDefaultCfg;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.iuup_mode := true;
+ flow[0].rtp_cfg.iuup_cfg.active_init := true;
+ flow[0].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, IuUP-Init passive) */
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, 96, "VND.3GPP.IUFP/16000"));
+ flow[1].em.portnr := 20000;
+ flow[1].rtp_cfg := c_RtpemDefaultCfg;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.iuup_mode := true;
+ flow[1].rtp_cfg.iuup_cfg.active_init := false;
+
+ f_two_crcx_mdcx_data_transfer(ep, call_id, flow[0], flow[1], false);
+
+ /* Now validate we don't receive more RTP packets after setting it to recvonly: */
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_RXONLY);
+ f_flow_modify(RTPEM[1], ep, call_id, "recvonly", flow[1]);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[1]);
+ f_sleep(0.5);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ if (stats[1].num_pkts_rx > stats[0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("received ", stats[1].num_pkts_rx - stats[0].num_pkts_rx, " RTP packets from MGW on recvonly connection 1"));
+ }
+
+ /* Now do the same on the IuUP port: */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_RXONLY);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_TXONLY);
+ f_flow_modify(RTPEM[0], ep, call_id, "recvonly", flow[0]);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ f_sleep(0.5);
+ stats[1] := f_rtpem_stats_get(RTPEM[0]);
+ if (stats[1].num_pkts_rx > stats[0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("received ", stats[1].num_pkts_rx - stats[0].num_pkts_rx, " IuUP packets from MGW on recvonly connection 1"));
+ }
+
+ /* Tear down */
+ f_flow_delete(RTPEM[0]);
+ f_flow_delete(RTPEM[1], ep, call_id);
+ setverdict(pass);
+ }
+ testcase TC_two_crcx_mdcx_and_iuup_mdcx_recvonly() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(0),
+ t_IuUP_RFC_AMR_SID(1),
+ t_IuUP_RFC_AMR_NO_DATA(2)
+ };
+ f_tc_two_crcx_mdcx_and_iuup_mdcx_recvonly(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* create two local emulations (1 RTP, 1 RTP+IuUP) and pass data in both directions */
+ function f_tc_two_crcx_mdcx_and_iuup_rtp(charstring local_ip_a, charstring remote_ip_a,
+ IuUP_RabFlowCombinationList rfcl_a,
+ charstring local_ip_b, charstring remote_ip_b) runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1227'H;
+
+ f_init(ep);
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, 96, "VND.3GPP.IUFP/16000"));
+ flow[0].em.portnr := 10000;
+ flow[0].rtp_cfg := c_RtpemDefaultCfg;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := '4f28959ffeb80181f5c4e83d176c897b4a4e333298333419a493ca63ded6e0'O;
+ /* flow[1].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-BE-RTP->AMR-IUUP*/
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := '08556d944c71a1a081e7ead204244480000ecd82b81118000097c4794e7740'O;
+ flow[0].rtp_cfg.iuup_mode := true;
+ flow[0].rtp_cfg.iuup_cfg.active_init := true;
+ flow[0].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, regular RTP) */
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, 112, "AMR/8000"));
+ flow[1].em.portnr := 20000;
+ flow[1].rtp_cfg := c_RtpemDefaultCfg;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].fixed_payload := '0382155b65131c68682079fab4810911200003b360ae0446000025f11e539dd0'O;
+ /* flow[0].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-IuUP->AMR-BE-RTP*/
+ flow[1].rtp_cfg.rx_payloads[0].fixed_payload := 'f3d3ca2567ffae00607d713a0f45db225ed2938ccca60ccd066924f298f7b5b8'O;
+ flow[1].rtp_cfg.iuup_mode := false;
+
+ f_two_crcx_mdcx_data_transfer(ep, call_id, flow[0], flow[1], true);
+ setverdict(pass);
+ }
+ testcase TC_two_crcx_mdcx_and_iuup_rtp() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(0),
+ t_IuUP_RFC_AMR_SID(1),
+ t_IuUP_RFC_AMR_NO_DATA(2)
+ };
+ f_tc_two_crcx_mdcx_and_iuup_rtp(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+ /* Same as TC_two_crcx_mdcTC_two_crcx_mdcx_and_iuup_rtpx_and_iuup, but passing unordered RFCI list (ID != position) */
+ testcase TC_two_crcx_mdcx_and_iuup_rtp_rfci_unordered() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(1),
+ t_IuUP_RFC_AMR_SID(2),
+ t_IuUP_RFC_AMR_NO_DATA(0)
+ };
+ f_tc_two_crcx_mdcx_and_iuup_rtp(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* Test that once IuUP->RTP has been set up, if the RTP/IuUP conn is set
+ * as "recvonly", no more RTP/IuUP packets get out of the MGW. */
+ function f_tc_two_crcx_mdcx_and_iuup_rtp_mdcx_recvonly(charstring local_ip_a, charstring remote_ip_a,
+ IuUP_RabFlowCombinationList rfcl_a,
+ charstring local_ip_b, charstring remote_ip_b) runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1227'H;
+ var RtpemStats stats[2];
+
+ f_init(ep);
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, 96, "VND.3GPP.IUFP/16000"));
+ flow[0].em.portnr := 10000;
+ flow[0].rtp_cfg := c_RtpemDefaultCfg;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := '4f28959ffeb80181f5c4e83d176c897b4a4e333298333419a493ca63ded6e0'O;
+ /* flow[1].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-BE-RTP->AMR-IUUP*/
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := '08556d944c71a1a081e7ead204244480000ecd82b81118000097c4794e7740'O;
+ flow[0].rtp_cfg.iuup_mode := true;
+ flow[0].rtp_cfg.iuup_cfg.active_init := true;
+ flow[0].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, regular RTP) */
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, 112, "AMR/8000"));
+ flow[1].em.portnr := 20000;
+ flow[1].rtp_cfg := c_RtpemDefaultCfg;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].fixed_payload := '0382155b65131c68682079fab4810911200003b360ae0446000025f11e539dd0'O;
+ /* flow[0].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-IuUP->AMR-BE-RTP*/
+ flow[1].rtp_cfg.rx_payloads[0].fixed_payload := 'f3d3ca2567ffae00607d713a0f45db225ed2938ccca60ccd066924f298f7b5b8'O;
+ flow[1].rtp_cfg.iuup_mode := false;
+
+ f_two_crcx_mdcx_data_transfer(ep, call_id, flow[0], flow[1], false);
+
+ /* Now validate we don't receive more RTP packets after setting it to recvonly: */
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_RXONLY);
+ f_flow_modify(RTPEM[1], ep, call_id, "recvonly", flow[1]);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[1]);
+ f_sleep(0.5);
+ stats[1] := f_rtpem_stats_get(RTPEM[1]);
+ if (stats[1].num_pkts_rx > stats[0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("received ", stats[1].num_pkts_rx - stats[0].num_pkts_rx, " RTP packets from MGW on recvonly connection 1"));
+ }
+
+ /* Now do the same on the IuUP port: */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_RXONLY);
+ f_flow_modify(RTPEM[0], ep, call_id, "recvonly", flow[0]);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_TXONLY);
+ f_flow_modify(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
+ f_sleep(0.5);
+ stats[0] := f_rtpem_stats_get(RTPEM[0]);
+ f_sleep(0.5);
+ stats[1] := f_rtpem_stats_get(RTPEM[0]);
+ if (stats[1].num_pkts_rx > stats[0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("received ", stats[1].num_pkts_rx - stats[0].num_pkts_rx, " IuUP packets from MGW on recvonly connection 1"));
+ }
+
+ /* Tear down */
+ f_flow_delete(RTPEM[0]);
+ f_flow_delete(RTPEM[1], ep, call_id);
+ setverdict(pass);
+ }
+ testcase TC_two_crcx_mdcx_and_iuup_rtp_mdcx_recvonly() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(0),
+ t_IuUP_RFC_AMR_SID(1),
+ t_IuUP_RFC_AMR_NO_DATA(2)
+ };
+ f_tc_two_crcx_mdcx_and_iuup_rtp_mdcx_recvonly(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
+
+ /* Set up Endpoint with 1 IuUP conn and 1 RTP-AMR conn, then MDCX the later to become IuUP. */
+ function f_tc_two_crcx_mdcx_and_iuup_rtp_mdcx_to_iuup(charstring local_ip_a, charstring remote_ip_a,
+ IuUP_RabFlowCombinationList rfcl_a,
+ charstring local_ip_b, charstring remote_ip_b) runs on dummy_CT {
+ var RtpFlowData flow[2];
+ var MgcpEndpoint ep := c_mgw_ep_rtpbridge & "2@" & c_mgw_domain;
+ var MgcpCallId call_id := '1227'H;
+ var RtpemStats stats[2][2];
+
+ f_init(ep);
+
+ /* Create the first connection in receive only mode (RNC side, IuUP-Init active) */
+ flow[0] := valueof(t_RtpFlow(local_ip_a, remote_ip_a, 96, "VND.3GPP.IUFP/16000"));
+ flow[0].em.portnr := 10000;
+ flow[0].rtp_cfg := c_RtpemDefaultCfg;
+ flow[0].rtp_cfg.tx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.rx_payloads[0].payload_type := flow[0].codec_descr[0].pt;
+ flow[0].rtp_cfg.tx_payloads[0].fixed_payload := '4f28959ffeb80181f5c4e83d176c897b4a4e333298333419a493ca63ded6e0'O;
+ /* flow[1].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-BE-RTP->AMR-IUUP*/
+ flow[0].rtp_cfg.rx_payloads[0].fixed_payload := '08556d944c71a1a081e7ead204244480000ecd82b81118000097c4794e7740'O;
+ flow[0].rtp_cfg.iuup_mode := true;
+ flow[0].rtp_cfg.iuup_cfg.active_init := true;
+ flow[0].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+
+ /* Create the second connection. This connection will be also
+ * in receive only mode (CN side, regular RTP) */
+ flow[1] := valueof(t_RtpFlow(local_ip_b, remote_ip_b, 112, "AMR/8000"));
+ flow[1].em.portnr := 20000;
+ flow[1].rtp_cfg := c_RtpemDefaultCfg;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ flow[1].rtp_cfg.tx_payloads[0].fixed_payload := '0382155b65131c68682079fab4810911200003b360ae0446000025f11e539dd0'O;
+ /* flow[0].rtp_cfg.rx_payloads[0].fixed_payload converted AMR-IuUP->AMR-BE-RTP*/
+ flow[1].rtp_cfg.rx_payloads[0].fixed_payload := 'f3d3ca2567ffae00607d713a0f45db225ed2938ccca60ccd066924f298f7b5b8'O;
+ flow[1].rtp_cfg.iuup_mode := false;
+
+ f_two_crcx_mdcx_data_transfer(ep, call_id, flow[0], flow[1], false);
+ setverdict(pass);
+
+ /* Stop sending further pkts to RTPEM[1], to avoid race conditions where RTP is sent while we
+ * reconfigure MGW (and our RTPEM) for IuUP:
+ */
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_RXONLY);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_RXONLY);
+ f_sleep(0.5);
+
+ /* Modify the AMR side to also do IuUP */
+ flow[1].codec_descr := {{
+ pt := 96,
+ codec := "VND.3GPP.IUFP/16000",
+ fmtp := omit
+ }};
+ flow[1].rtp_cfg.iuup_mode := true;
+ flow[1].rtp_cfg.iuup_cfg.active_init := false;
+ flow[1].rtp_cfg.iuup_cfg.rab_flow_combs := rfcl_a;
+ flow[1].rtp_cfg.tx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ /* Send whatever payload is expected by the other RTPEM, now without AMR-BE_RTP<->AMR-IUUP conversion: */
+ flow[1].rtp_cfg.tx_payloads[0].fixed_payload := flow[0].rtp_cfg.rx_payloads[0].fixed_payload;
+ flow[1].rtp_cfg.rx_payloads[0].payload_type := flow[1].codec_descr[0].pt;
+ /* Expect whatever payload is sent by the other RTPEM, now without AMR-BE_RTP<->AMR-IUUP conversion: */
+ flow[1].rtp_cfg.rx_payloads[0].fixed_payload := flow[0].rtp_cfg.tx_payloads[0].fixed_payload;
+ f_flow_modify(RTPEM[1], ep, call_id, "sendrecv", flow[1]);
+ f_rtpem_mode(RTPEM[0], RTPEM_MODE_BIDIR);
+ f_sleep(1.0);
+ f_rtpem_mode(RTPEM[1], RTPEM_MODE_BIDIR);
+
+ /* Now, if MGW would keep sending RTP instead of expected IuUP, then that would make the RTPEM[1]
+ * component to fail, since it would error trying to decode an RTP pkt as IuUP.
+ * We simply need to make sure some packets are being forwarded to it:
+ */
+ stats[0][0] := f_rtpem_stats_get(RTPEM[0]);
+ stats[1][0] := f_rtpem_stats_get(RTPEM[1]);
+ f_sleep(1.0);
+ stats[0][1] := f_rtpem_stats_get(RTPEM[0]);
+ stats[1][1] := f_rtpem_stats_get(RTPEM[1]);
+
+ f_rtpem_stats_err_check(stats[0][1]);
+ f_rtpem_stats_err_check(stats[1][1]);
+ if (stats[0][1].num_pkts_rx == stats[0][0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No packets received in connection 0 after MDCX"));
+ }
+ if (stats[1][1].num_pkts_rx == stats[1][0].num_pkts_rx) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("No packets received in connection 1 after MDCX"));
+ }
+
+ /* Tear down */
+ f_flow_delete(RTPEM[0]);
+ f_flow_delete(RTPEM[1], ep, call_id);
+ setverdict(pass);
+ }
+ testcase TC_two_crcx_mdcx_and_iuup_rtp_mdcx_to_iuup() runs on dummy_CT {
+ var template (value) IuUP_RabFlowCombinationList rfcl := {
+ t_IuUP_RFC_AMR_12_2(0),
+ t_IuUP_RFC_AMR_SID(1),
+ t_IuUP_RFC_AMR_NO_DATA(2)
+ };
+ f_tc_two_crcx_mdcx_and_iuup_rtp_mdcx_to_iuup(mp_local_ipv4, mp_remote_ipv4, valueof(rfcl),
+ mp_local_ipv4, mp_remote_ipv4);
+ }
control {
execute(TC_selftest());
+ execute(TC_auep_null());
execute(TC_crcx());
execute(TC_crcx_no_lco());
execute(TC_crcx_noprefix());
execute(TC_crcx_unsupp_mode());
+ execute(TC_crcx_osmo_ign());
execute(TC_crcx_early_bidir_mode());
execute(TC_crcx_unsupp_param());
execute(TC_crcx_missing_callid());
@@ -2163,6 +3300,7 @@ module MGCP_Test {
execute(TC_crcx_wildcarded_exhaust());
execute(TC_mdcx_without_crcx());
execute(TC_dlcx_without_crcx());
+ execute(TC_dlcx_non_existant_ep());
execute(TC_mdcx_wildcarded());
execute(TC_dlcx_wildcarded());
execute(TC_crcx_and_dlcx_ep_callid_connid());
@@ -2175,10 +3313,12 @@ module MGCP_Test {
execute(TC_crcx_osmux_wildcard());
execute(TC_crcx_osmux_fixed());
execute(TC_crcx_osmux_fixed_twice());
+ execute(TC_crcx_osmux_257());
execute(TC_one_crcx_receive_only_osmux());
execute(TC_one_crcx_loopback_osmux());
execute(TC_two_crcx_and_rtp_osmux());
execute(TC_two_crcx_and_rtp_osmux_bidir());
+ execute(TC_two_crcx_and_rtp_osmux_bidir_amr_bwe());
execute(TC_two_crcx_mdcx_and_rtp_osmux_wildcard());
execute(TC_two_crcx_mdcx_and_rtp_osmux_fixed());
@@ -2188,6 +3328,7 @@ module MGCP_Test {
execute(TC_one_crcx_receive_only_rtp());
execute(TC_one_crcx_loopback_rtp());
+ execute(TC_one_crcx_loopback_rtp_ipv6());
execute(TC_two_crcx_and_rtp());
execute(TC_two_crcx_and_rtp_bidir());
execute(TC_two_crcx_diff_pt_and_rtp());
@@ -2195,11 +3336,49 @@ module MGCP_Test {
execute(TC_two_crcx_mdcx_and_rtp());
execute(TC_two_crcx_and_unsolicited_rtp());
execute(TC_two_crcx_and_one_mdcx_rtp_ho());
+ execute(TC_two_crcx_confecho_sendonly_rtp());
execute(TC_ts101318_rfc5993_rtp_conversion());
+ execute(TC_ts101318_rfc5993_rtp_conversion_fmtp());
execute(TC_amr_oa_bwe_rtp_conversion());
execute(TC_amr_oa_oa_rtp_conversion());
execute(TC_amr_bwe_bwe_rtp_conversion());
+ execute(TC_amr_oa_oa_no_bwe_rtp_conversion());
+ execute(TC_amr_oa_no_bwe_oa_rtp_conversion());
+ execute(TC_amr_bwe_bwe_no_oa_rtp_conversion());
+ execute(TC_amr_bwe_no_oa_bwe_rtp_conversion());
execute(TC_conn_timeout());
+
+ execute(TC_e1_crcx_and_dlcx_ep());
+ execute(TC_e1_crcx_with_overlap());
+ execute(TC_e1_crcx_loopback());
+ execute(TC_e1_dlcx_wildcarded());
+
+ execute(TC_crcx_mdcx_ip4());
+ execute(TC_crcx_mdcx_ip6());
+ execute(TC_two_crcx_mdcx_and_rtp_ipv4_ipv6());
+ execute(TC_two_crcx_mdcx_and_rtp_ipv6());
+ execute(TC_two_crcx_and_rtp_osmux_bidir_ipv6());
+ execute(TC_two_crcx_and_rtp_osmux_bidir_ipv4_ipv6());
+ execute(TC_two_crcx_and_rtp_osmux_bidir_ipv6_ipv4());
+ execute(TC_two_crcx_mdcx_and_rtp_osmux_ipv6());
+ execute(TC_two_crcx_mdcx_and_rtp_osmux_ipv4_ipv6());
+ execute(TC_two_crcx_mdcx_and_rtp_osmux_ipv6_ipv4());
+
+ execute(TC_two_crcx_mdcx_and_iuup());
+ execute(TC_two_crcx_mdcx_and_iuup_rfci_unordered());
+ execute(TC_two_crcx_mdcx_and_iuup_mdcx_recvonly());
+ execute(TC_two_crcx_mdcx_and_iuup_rtp());
+ execute(TC_two_crcx_mdcx_and_iuup_rtp_rfci_unordered());
+ execute(TC_two_crcx_mdcx_and_iuup_rtp_mdcx_recvonly());
+ execute(TC_two_crcx_mdcx_and_iuup_rtp_mdcx_to_iuup());
+
+ execute(TC_two_crcx_mdcx_and_rtp_clearmode());
+
+ /* Note: This testcase will trigger an OSMO_ASSERT() bug in
+ * older versions of osmo-mgw. This eventually leads into
+ * a failure of all subsequent testcases, so it is important
+ * not to add new testcaes after this one. */
+ execute(TC_one_crcx_loopback_rtp_implicit());
}
}
diff --git a/mgw/expected-results.xml b/mgw/expected-results.xml
index 0a1bdacd..d9b9a155 100644
--- a/mgw/expected-results.xml
+++ b/mgw/expected-results.xml
@@ -1,10 +1,12 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='49' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='84' failures='5' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='MGCP_Test' name='TC_selftest' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_auep_null' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_no_lco' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_noprefix' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_unsupp_mode' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_crcx_osmo_ign' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_early_bidir_mode' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_unsupp_param' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_missing_callid' time='MASKED'/>
@@ -16,6 +18,7 @@
<testcase classname='MGCP_Test' name='TC_crcx_wildcarded_exhaust' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_mdcx_without_crcx' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_dlcx_without_crcx' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_dlcx_non_existant_ep' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_mdcx_wildcarded' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_dlcx_wildcarded' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_and_dlcx_ep_callid_connid' time='MASKED'/>
@@ -27,16 +30,19 @@
<testcase classname='MGCP_Test' name='TC_crcx_osmux_wildcard' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_osmux_fixed' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_osmux_fixed_twice' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_crcx_osmux_257' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_one_crcx_receive_only_osmux' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_one_crcx_loopback_osmux' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux_bidir' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux_bidir_amr_bwe' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_osmux_wildcard' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_osmux_fixed' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_crcx_dlcx_30ep' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_rtpem_selftest' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_one_crcx_receive_only_rtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_one_crcx_loopback_rtp' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_one_crcx_loopback_rtp_ipv6' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_bidir' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_diff_pt_and_rtp' time='MASKED'/>
@@ -44,9 +50,58 @@
<testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_unsolicited_rtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_two_crcx_and_one_mdcx_rtp_ho' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_confecho_sendonly_rtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_ts101318_rfc5993_rtp_conversion' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_ts101318_rfc5993_rtp_conversion_fmtp' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_amr_oa_bwe_rtp_conversion' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_amr_oa_oa_rtp_conversion' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_amr_bwe_bwe_rtp_conversion' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_amr_oa_oa_no_bwe_rtp_conversion' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_amr_oa_no_bwe_oa_rtp_conversion' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_amr_bwe_bwe_no_oa_rtp_conversion' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_amr_bwe_no_oa_bwe_rtp_conversion' time='MASKED'/>
<testcase classname='MGCP_Test' name='TC_conn_timeout' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_e1_crcx_and_dlcx_ep' time='MASKED'>
+ <failure type='fail-verdict'>Response didn't match template
+ MGCP_Test.ttcn:MASKED MGCP_Test control part
+ MGCP_Test.ttcn:MASKED TC_e1_crcx_and_dlcx_ep testcase
+ </failure>
+ </testcase>
+ <testcase classname='MGCP_Test' name='TC_e1_crcx_with_overlap' time='MASKED'>
+ <failure type='fail-verdict'>Response didn't match template
+ MGCP_Test.ttcn:MASKED MGCP_Test control part
+ MGCP_Test.ttcn:MASKED TC_e1_crcx_with_overlap testcase
+ </failure>
+ </testcase>
+ <testcase classname='MGCP_Test' name='TC_e1_crcx_loopback' time='MASKED'>
+ <failure type='fail-verdict'>Response didn't match template
+ MGCP_Test.ttcn:MASKED MGCP_Test control part
+ MGCP_Test.ttcn:MASKED TC_e1_crcx_loopback testcase
+ </failure>
+ </testcase>
+ <testcase classname='MGCP_Test' name='TC_e1_dlcx_wildcarded' time='MASKED'>
+ <failure type='fail-verdict'>Response didn't match template
+ MGCP_Test.ttcn:MASKED MGCP_Test control part
+ MGCP_Test.ttcn:MASKED TC_e1_dlcx_wildcarded testcase
+ </failure>
+ </testcase>
+ <testcase classname='MGCP_Test' name='TC_crcx_mdcx_ip4' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_crcx_mdcx_ip6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_ipv4_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux_bidir_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux_bidir_ipv4_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_and_rtp_osmux_bidir_ipv6_ipv4' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_osmux_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_osmux_ipv4_ipv6' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_osmux_ipv6_ipv4' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_rfci_unordered' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_mdcx_recvonly' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_rtp' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_rtp_rfci_unordered' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_rtp_mdcx_recvonly' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_iuup_rtp_mdcx_to_iuup' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_two_crcx_mdcx_and_rtp_clearmode' time='MASKED'/>
+ <testcase classname='MGCP_Test' name='TC_one_crcx_loopback_rtp_implicit' time='MASKED'/>
</testsuite>
diff --git a/mgw/gen_links.sh b/mgw/gen_links.sh
index 8893954c..2fd2b0da 100755
--- a/mgw/gen_links.sh
+++ b/mgw/gen_links.sh
@@ -38,13 +38,18 @@ FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn SDP_Templates.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn
MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc "
+FILES+="AMR_Types.ttcn "
FILES+="RTP_CodecPort.ttcn RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_Emulation.ttcn IuUP_EncDec.cc "
FILES+="OSMUX_CodecPort.ttcn OSMUX_Emulation.ttcn OSMUX_Types.ttcn OSMUX_CodecPort_CtrlFunct.ttcn OSMUX_CodecPort_CtrlFunctDef.cc "
FILES+="Native_Functions.ttcn Native_FunctionDefs.cc IPCP_Types.ttcn "
FILES+="Osmocom_VTY_Functions.ttcn "
FILES+="RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc "
+FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
+
gen_links $DIR $FILES
ignore_pp_results
diff --git a/mgw/osmo-mgw.cfg b/mgw/osmo-mgw.cfg
index edc81904..2af7dffc 100644
--- a/mgw/osmo-mgw.cfg
+++ b/mgw/osmo-mgw.cfg
@@ -2,11 +2,17 @@
! OsmoMGW (1.2.0.17-52e3) configuration saved from vty
!!
!
+log gsmtap 127.0.0.1
+ logging level set-all debug
+ logging filter all 1
+!
log stderr
logging filter all 1
logging color 1
+ logging print level 1
logging print category 1
logging timestamp 1
+ logging print file basename last
logging print extended-timestamp 1
logging level set-all notice
logging level lmgcp debug
@@ -16,14 +22,30 @@ stats interval 5
line vty
no login
bind 127.0.0.1
+ctrl
+ bind 127.0.0.1
+!
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level global
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
+!
+e1_input
+ e1_line 0 driver ipa
!
mgcp
bind ip 127.0.0.1
bind port 2427
rtp port-range 4002 16000
rtp bind-ip 127.0.0.1
+ rtp bind-ip-v6 ::1
rtp ip-probing
- rtp ip-dscp 184
+ rtp ip-dscp 46
no rtp keep-alive
no rtcp-omit
no rtp-patch
@@ -33,6 +55,17 @@ mgcp
sdp audio-payload send-name
conn-timeout 0
loop 0
- number endpoints 31
+ number endpoints 300
allow-transcoding
osmux off
+ osmux bind-ip 127.0.0.1
+ osmux bind-ip-v6 ::1
+ trunk 1
+ sdp audio-payload send-ptime
+ sdp audio-payload send-name
+ no rtp keep-alive
+ loop 0
+ no rtcp-omit
+ no rtp-patch
+ allow-transcoding
+ line 0
diff --git a/mgw/regen_makefile.sh b/mgw/regen_makefile.sh
index 4662933d..921956ca 100755
--- a/mgw/regen_makefile.sh
+++ b/mgw/regen_makefile.sh
@@ -1,5 +1,30 @@
#!/bin/sh
-FILES="*.ttcn SDP_EncDec.cc *.c MGCP_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc RTP_CodecPort_CtrlFunctDef.cc OSMUX_CodecPort_CtrlFunctDef.cc IuUP_EncDec.cc Native_FunctionDefs.cc TELNETasp_PT.cc IP_EncDec.cc "
+NAME=MGCP_Test
-../regen-makefile.sh MGCP_Test.ttcn $FILES
+FILES="
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IP_EncDec.cc
+ IuUP_EncDec.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ OSMUX_CodecPort_CtrlFunctDef.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SDP_EncDec.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/mme/LTE_CryptoFunctionDefs.cc b/mme/LTE_CryptoFunctionDefs.cc
index da2d521d..7f822245 100644
--- a/mme/LTE_CryptoFunctionDefs.cc
+++ b/mme/LTE_CryptoFunctionDefs.cc
@@ -184,6 +184,14 @@ OCTETSTRING f__kdf__nh(const OCTETSTRING &kasme, const OCTETSTRING &sync_inp)
return OCTETSTRING(sizeof(kenb), kenb);
}
+OCTETSTRING f__kdf__nas__token(const OCTETSTRING &kasme, const INTEGER &ul_count)
+{
+ TTCN_Buffer ttcn_buf_kasme(kasme);
+ uint8_t nas_token[32];
+
+ mme_kdf_nas_token(ttcn_buf_kasme.get_data(), (int)ul_count, nas_token);
+ return OCTETSTRING(sizeof(nas_token), nas_token);
+}
} // namespace
diff --git a/mme/LTE_CryptoFunctions.ttcn b/mme/LTE_CryptoFunctions.ttcn
index 687caabe..f0ea990f 100644
--- a/mme/LTE_CryptoFunctions.ttcn
+++ b/mme/LTE_CryptoFunctions.ttcn
@@ -12,6 +12,7 @@
module LTE_CryptoFunctions {
import from General_Types all;
+import from Misc_Helpers all;
import from S1AP_Types all;
import from S1AP_PDU_Descriptions all;
@@ -39,6 +40,8 @@ external function f_kdf_enb(in OCT16 kasme, in integer ul_count) return OCT32;
external function f_kdf_nh(in OCT16 kasme, in OCT32 sync_inp) return OCT32;
+external function f_kdf_nas_token(in OCT16 kasme, in integer ul_count) return OCT32;
+
/*********************************************************************************
* mid-level API
*********************************************************************************/
@@ -53,8 +56,8 @@ function f_nas_mac_calc(NAS_ALG_INT alg, octetstring k_nas_int, integer seq_nr,
return f_snow_3g_f9(k_nas_int, seq_nr, bearer, is_downlink, data);
}
case else {
- setverdict(fail, "Unsupported EIA: ", alg);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unsupported EIA: ", alg));
+ return '00000000'O; /* never reached */
}
}
}
@@ -67,8 +70,7 @@ function f_nas_encrypt(NAS_ALG_ENC alg, octetstring k_nas_enc, integer count,
f_snow_3g_f8(k_nas_enc, count, bearer, is_downlink, data);
}
case else {
- setverdict(fail, "Unsupported EEA: ", alg);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unsupported EEA: ", alg));
}
}
}
@@ -143,9 +145,15 @@ private function f_nas_check_ip(inout NAS_UE_State nus,
var octetstring data_with_seq := int2oct(secp_nas.sequenceNumber, 1) & secp_nas.nAS_Message;
var OCT4 exp_mac := f_nas_mac_calc(nus.alg_int, nus.k_nas_int, nus.rx_count, 0,
f_rx_is_downlink(nus), data_with_seq);
+
+ if (nus.rx_count != secp_nas.sequenceNumber) {
+ setverdict(fail, "Received NAS SeqNr ", secp_nas.sequenceNumber,
+ " doesn't match expected SeqNr ", nus.rx_count, ": ", secp_nas, " | nus: ", nus);
+ return false;
+ }
if (exp_mac != secp_nas.messageAuthenticationCode) {
setverdict(fail, "Received NAS MAC ", secp_nas.messageAuthenticationCode,
- " doesn't match expected MAC ", exp_mac, ": ", secp_nas);
+ " doesn't match expected MAC ", exp_mac, ": ", secp_nas, " | nus: ", nus);
return false;
}
return true;
@@ -168,20 +176,23 @@ function f_nas_try_decaps(inout NAS_UE_State nus, PDU_NAS_EPS nas) return PDU_NA
nus.rx_count := 0;
nus.alg_int := NAS_ALG_IP_EIA1; /* FIXME: from decoded inner message! */
if (not f_nas_check_ip(nus, secp_nas)) {
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "f_nas_check_ip() failed");
}
+ nus.rx_count := nus.rx_count + 1;
return dec_PDU_NAS_EPS(secp_nas.nAS_Message);
}
case ('0001'B) { /* IP only */
if (not f_nas_check_ip(nus, secp_nas)) {
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "f_nas_check_ip() failed");
}
+ nus.rx_count := nus.rx_count + 1;
return dec_PDU_NAS_EPS(secp_nas.nAS_Message);
}
case ('0010'B) { /* IP + ciphered */
if (not f_nas_check_ip(nus, secp_nas)) {
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "f_nas_check_ip() failed");
}
+ nus.rx_count := nus.rx_count + 1;
f_nas_encrypt(nus.alg_enc, nus.k_nas_enc, nus.rx_count, 0,
f_rx_is_downlink(nus), secp_nas.nAS_Message);
return dec_PDU_NAS_EPS(secp_nas.nAS_Message);
@@ -189,17 +200,18 @@ function f_nas_try_decaps(inout NAS_UE_State nus, PDU_NAS_EPS nas) return PDU_NA
case ('0100'B) { /* IP + ciphered; new EPS security context */
nus.rx_count := 0;
if (not f_nas_check_ip(nus, secp_nas)) {
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "f_nas_check_ip() failed");
}
f_nas_encrypt(nus.alg_enc, nus.k_nas_enc, nus.rx_count, 0,
f_rx_is_downlink(nus), secp_nas.nAS_Message);
+ nus.rx_count := nus.rx_count + 1;
return dec_PDU_NAS_EPS(secp_nas.nAS_Message);
}
//case ('0101'B) { /* IP + partially ciphered */ }
//case ('1100'B) { /* Service Request Message */ }
case else {
- setverdict(fail, "Implement SecHdrType for ", secp_nas);
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Implement SecHdrType for ", secp_nas));
+ mtc.stop; /* make compiler happy about not returning. */
}
}
}
@@ -218,8 +230,8 @@ return BIT4
} else if (encrypt == true and authenticate == true and new_ctx == false) {
return '0010'B;
} else {
- setverdict(fail, "invalid sec_hdr conditions");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Invalid sec_hdr conditions");
+ return '0000'B; /* never reached, make compiler happy */
}
}
diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn
index f9bcf6d2..3ea17ddb 100644
--- a/mme/MME_Tests.ttcn
+++ b/mme/MME_Tests.ttcn
@@ -11,29 +11,44 @@
module MME_Tests {
import from General_Types all;
-
+import from Native_Functions all;
+import from IPL4asp_Types all;
+import from Misc_Helpers all;
import from S1AP_Types all;
import from S1AP_Templates all;
import from S1AP_Emulation all;
import from S1AP_PDU_Descriptions all;
import from S1AP_IEs all;
+import from S1AP_PDU_Contents all;
+import from S1AP_Constants all;
import from NAS_EPS_Types all;
import from NAS_Templates all;
import from DIAMETER_Types all;
import from DIAMETER_Templates all;
+import from DIAMETER_ts29_272_Templates all;
import from DIAMETER_Emulation all;
import from SGsAP_Types all;
import from SGsAP_Templates all;
import from SGsAP_Emulation all;
+import from GTP_Emulation all;
+import from GTPC_Types all;
+import from GTPv1C_CodecPort all;
+import from GTPv1C_Templates all;
+
import from LTE_CryptoFunctions all;
import from L3_Templates all;
import from DNS_Helpers all;
import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+
+import from GTPv2_Types all;
+import from GTPv2_Templates all;
+import from GTPv2_Emulation all;
friend module MME_Tests_SGsAP;
@@ -50,9 +65,36 @@ type record EnbParams {
SupportedTAs supported_tas
}
+type record BearerConfig {
+ /* EPS Bearer ID */
+ uint4_t ebi optional,
+ /* TEI (Data) local side, S11 (SGW) */
+ OCT4 s11_teid_local optional,
+ /* TEI (Data) remote side, S11 (SGW) */
+ OCT4 s11_teid_remote optional,
+ /* TEI (Data) local side, S5c (PGW) */
+ OCT4 s5c_teid_local optional,
+ /* TEI (Data) remote side, S5c (PGW) */
+ OCT4 s5c_teid_remote optional
+};
+
/* parameters of emulated UE */
type record UeParams {
- hexstring imsi
+ hexstring imsi,
+ charstring ue_ip,
+ NAS_EPS_Types.GUTI guti optional,
+ octetstring kasme optional,
+
+ /* TEI (Control) local side, S11 (SGW) */
+ OCT4 s11_teic_local,
+ /* TEI (Control) remote side, S11 (SGW) */
+ OCT4 s11_teic_remote optional,
+ /* TEI (Control) local side, S5c (PGW) */
+ OCT4 s5c_teic_local,
+ /* TEI (Control) remote side, S5c (PGW) */
+ OCT4 s5c_teic_remote optional,
+
+ BearerConfig bearer optional
}
type component MTC_CT {
@@ -72,12 +114,50 @@ type component MTC_CT {
port SGsAP_PT SGsAP_UNIT;
port SGsAPEM_PROC_PT SGsAP_PROC;
+ /* Gn interface (GTPv1C) of emulated SGSN (Rel. 7) */
+ var GTP_Emulation_CT vc_GTP;
+
+ /* S11 interface (GTPv2C) of emulated SGW-C */
+ var GTPv2_Emulation_CT vc_GTP2;
+ port GTP2EM_PT TEID0;
+
var UeParams g_ue_pars[NUM_UE];
}
-type component ConnHdlr extends S1AP_ConnHdlr, SGsAP_ConnHdlr, DIAMETER_ConnHdlr {
+/* Encode an S1AP Global-ENB-ID into an octetstring */
+private function enc_S1AP_Global_ENB_ID(Global_ENB_ID global_enb_id) return octetstring {
+
+ /* Due to the limitations of libfftranscode, we can not define encoders (or decoders) for individual
+ * information elements (in S1AP_Types.cc). Unfortuantely Global-ENB-ID also appears in BSSGP in its
+ * encoded form. (see also: GTP-C 3GPP TS 48.018, section 11.3.70). To encode a given Global-ENB-ID
+ * we craft a full S1AP PDU and encode it. Then we can cut out the encoded Global-ENB-ID from the
+ * generated octetstring. */
+
+ var SupportedTAs supported_tas_dummy := {{
+ tAC := '0000'O,
+ broadcastPLMNs := { '00f000'O },
+ iE_Extensions := omit
+ }};
+ var octetstring encoded;
+ var integer global_enb_id_len;
+
+ if (ispresent(global_enb_id.eNB_ID.macroENB_ID)) {
+ global_enb_id_len := 8;
+ } else {
+ /* All other ENB ID types fit into 8 byte (homeENB_ID, short_macroENB_ID, long_macroENB_ID) */
+ global_enb_id_len := 9;
+ }
+
+ encoded := enc_S1AP_PDU(valueof(ts_S1AP_SetupReq(global_enb_id, supported_tas_dummy, v32)));
+
+ return substr(encoded, 11, global_enb_id_len);
+}
+
+type component ConnHdlr extends S1AP_ConnHdlr, SGsAP_ConnHdlr, DIAMETER_ConnHdlr, GTP_ConnHdlr, GTP2_ConnHdlr {
var ConnHdlrPars g_pars;
timer g_Tguard := 30.0;
+
+ var Gtp1cPeer g_gn_iface_peer := { connId := 1, remName := mp_gn_remote_ip, remPort := mp_gn_remote_port };
}
type record ConnHdlrPars {
@@ -99,12 +179,36 @@ modulepar {
/* S6 interface */
charstring mp_s6_local_ip := "127.0.0.4";
integer mp_s6_local_port := 3868;
+ charstring mp_s6_diam_realm := "localdomain";
+ charstring mp_s6_local_diam_host := "hss.localdomain";
+ charstring mp_s6_remote_diam_host := "mme.localdomain";
/* SGs interface */
charstring mp_sgs_local_ip := "127.0.0.1";
integer mp_sgs_local_port := 29118;
charstring mp_vlr_name := "vlr.example.net";
charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
+
+ /* Gn interface (GTPv1C) */
+ charstring mp_gn_local_ip := "127.0.0.22";
+ integer mp_gn_local_port := 2123;
+ charstring mp_gn_remote_ip := "127.0.0.2";
+ /* RAI+CI served from emulated peer SGSN: */
+ integer mp_gn_remote_port := 2123;
+ hexstring mp_gn_local_mcc := '262'H;
+ hexstring mp_gn_local_mnc := 'f42'H;
+ uint16_t mp_gn_local_lac := 39594;
+ uint8_t mp_gn_local_rac := 187;
+ uint16_t mp_gn_local_ci := 1223;
+
+ /* S11 interface (GTPv2C, interface between MME and SGW) */
+ charstring mp_s11_local_ip := "127.0.0.3";
+ integer mp_s11_local_port := 2123;
+ charstring mp_s11_remote_ip := "127.0.0.2";
+ integer mp_s11_remote_port := 2123;
+
+ /* PGW information announced by SGWC. MME never really interacts with these. */
+ charstring mp_s5c_pgw_ip := "1.2.3.4";
}
/* send incoming unit data messages (like reset) to global SGsAP_UNIT port */
@@ -141,18 +245,10 @@ runs on S1AP_Emulation_CT return template S1AP_PDU {
return omit;
}
-friend function S1apCreateCallback(S1AP_PDU msg, template (omit) MME_UE_S1AP_ID mme_id,
- template (omit) ENB_UE_S1AP_ID enb_id, charstring id)
-runs on S1AP_Emulation_CT return S1AP_ConnHdlr
-{
- setverdict(fail, "implement this");
- mtc.stop;
-}
-
friend function f_init_one_enb(charstring id, integer num := 0) runs on MTC_CT {
id := id & "-S1AP" & int2str(num);
var S1APOps ops := {
- create_cb := refers(S1apCreateCallback),
+ create_cb := refers(S1AP_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(S1apForwardUnitdataCallback)
}
var S1AP_conn_parameters pars := {
@@ -191,7 +287,21 @@ friend function f_init_one_enb(charstring id, integer num := 0) runs on MTC_CT {
}
friend function f_init_one_ue(inout UeParams uep, integer imsi_suffix) {
uep := {
- imsi := f_gen_imsi(imsi_suffix)
+ imsi := f_gen_imsi(imsi_suffix),
+ ue_ip := "192.168.123.50",
+ guti := omit,
+ kasme := omit,
+ s11_teic_local := '00000000'O,
+ s11_teic_remote := omit,
+ s5c_teic_local := '00000000'O,
+ s5c_teic_remote := omit,
+ bearer := {
+ ebi := omit,
+ s11_teid_local := omit,
+ s11_teid_remote := omit,
+ s5c_teid_local := omit,
+ s5c_teid_remote := omit
+ }
}
}
friend function f_init_s1ap(charstring id, integer imsi_suffix) runs on MTC_CT {
@@ -213,7 +323,8 @@ runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
friend function f_init_diameter(charstring id) runs on MTC_CT {
var DIAMETEROps ops := {
create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
- unitdata_cb := refers(DiameterForwardUnitdataCallback)
+ unitdata_cb := refers(DiameterForwardUnitdataCallback),
+ raw := false /* handler mode (IMSI based routing) */
};
var DIAMETER_conn_parameters pars := {
remote_ip := mp_mme_ip,
@@ -222,6 +333,7 @@ friend function f_init_diameter(charstring id) runs on MTC_CT {
local_sctp_port := mp_s6_local_port,
origin_host := "hss.localdomain",
origin_realm := "localdomain",
+ auth_app_id := omit,
vendor_app_id := c_DIAMETER_3GPP_S6_AID
};
vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
@@ -233,7 +345,42 @@ friend function f_init_diameter(charstring id) runs on MTC_CT {
f_diameter_wait_capability(DIAMETER_UNIT);
}
-friend template (value) TAI ts_enb_S1AP_TAI(EnbParams enb) := {
+friend function f_init_gtp(charstring id) runs on MTC_CT {
+ id := id & "-GTP";
+
+ var GtpEmulationCfg gtp_cfg := {
+ gtpc_bind_ip := mp_gn_local_ip,
+ gtpc_bind_port := mp_gn_local_port,
+ gtpu_bind_ip := omit,
+ gtpu_bind_port := omit,
+ sgsn_role := true
+ };
+
+ vc_GTP := GTP_Emulation_CT.create(id);
+ vc_GTP.start(GTP_Emulation.main(gtp_cfg));
+}
+
+friend function f_init_gtpv2_s11(charstring id) runs on MTC_CT {
+ id := id & "-GTPV2";
+
+ var Gtp2EmulationCfg cfg := {
+ gtpc_bind_ip := mp_s11_local_ip,
+ 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
+ };
+
+ vc_GTP2 := GTPv2_Emulation_CT.create(id);
+ map(vc_GTP2:GTP2C, system:GTP2C);
+ connect(vc_GTP2:TEID0, self:TEID0);
+ vc_GTP2.start(GTPv2_Emulation.main(cfg));
+}
+
+friend template (value) S1AP_IEs.TAI ts_enb_S1AP_TAI(EnbParams enb) := {
pLMNidentity := enb.global_enb_id.pLMNidentity,
tAC := enb.supported_tas[0].tAC,
iE_Extensions := omit
@@ -278,6 +425,14 @@ runs on MTC_CT return ConnHdlr {
connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);
}
+ if (isbound(vc_GTP)) {
+ connect(vc_conn:GTP, vc_GTP:CLIENT);
+ connect(vc_conn:GTP_PROC, vc_GTP:CLIENT_PROC);
+ }
+ if (isbound(vc_GTP2)) {
+ connect(vc_conn:GTP2, vc_GTP2:CLIENT);
+ connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC);
+ }
/* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
* a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
@@ -300,7 +455,7 @@ friend function f_init_handler(ConnHdlrPars pars, float t_guard := 30.0) runs on
g_Tguard.start(t_guard);
activate(as_Tguard());
if (DIAMETER_PROC.checkstate("Connected")) {
- f_diameter_expect(g_pars.ue_pars.imsi);
+ f_diameter_expect_imsi(g_pars.ue_pars.imsi);
}
if (SGsAP_PROC.checkstate("Connected")) {
/* Route all SGsAP mesages for our IMSIto us */
@@ -310,8 +465,8 @@ friend function f_init_handler(ConnHdlrPars pars, float t_guard := 30.0) runs on
-friend function f_s1ap_setup(integer idx := 0, template Cause cause := omit) runs on MTC_CT {
- var template (present) Cause exp_cause;
+friend function f_s1ap_setup(integer idx := 0, template S1AP_IEs.Cause cause := omit) runs on MTC_CT {
+ var template (present) S1AP_IEs.Cause exp_cause;
var boolean exp_fail := false;
timer T := 5.0;
if (not istemplatekind(cause, "omit")) {
@@ -434,11 +589,11 @@ private altstep as_s1ap_handle_auth() runs on ConnHdlr {
const OCT3 plmn_id := '00F110'O;
const OCT6 sqn := '000000000020'O;
const OCT6 ak := substr(autn, 0, 6) xor4b sqn;
- var octetstring kasme := f_kdf_kasme(ck, ik, plmn_id, sqn, ak);
+ g_pars.ue_pars.kasme := f_kdf_kasme(ck, ik, plmn_id, sqn, ak);
var S1APEM_Config cfg := {
set_nas_keys := {
- k_nas_int := f_kdf_nas_int(1, kasme),
- k_nas_enc := f_kdf_nas_enc(1, kasme)
+ k_nas_int := f_kdf_nas_int(1, g_pars.ue_pars.kasme),
+ k_nas_enc := f_kdf_nas_enc(1, g_pars.ue_pars.kasme)
}
};
S1AP.send(cfg);
@@ -463,6 +618,102 @@ private altstep as_s1ap_handle_sec_mode() runs on ConnHdlr {
}
}
+
+private altstep as_s1ap_handle_IntialCtxSetupReq_Attach_Accept() runs on ConnHdlr {
+ var S1AP_PDU rx_msg;
+ var PDU_NAS_EPS rx_nas;
+ [] S1AP.receive(tr_S1AP_IntialCtxSetupReq) -> value rx_msg {
+ var template (omit) MME_UE_S1AP_ID mme_ue_id := f_S1AP_get_MME_UE_S1AP_ID(rx_msg);
+ var template (omit) ENB_UE_S1AP_ID enb_ue_id := f_S1AP_get_ENB_UE_S1AP_ID(rx_msg);
+ var template (value) E_RABSetupItemCtxtSURes rab_setup_it;
+ var template (value) E_RABSetupListCtxtSURes rab_setup_items;
+ var octetstring esm_enc;
+ var template (value) PDU_NAS_EPS nas;
+ var EPS_MobileIdentityTLV mi_tlv;
+
+ S1AP.receive(tr_NAS_AttachAccept()) -> value rx_nas;
+ mi_tlv := rx_nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_AttachAccept.gUTI;
+ if (mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.typeOfIdentity != '110'B) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx GUTI of unexpected MI type: ", mi_tlv));
+ }
+ g_pars.ue_pars.guti := mi_tlv.ePS_MobileIdentity.ePS_MobileIdentity.oddEvenInd_identity.guti
+
+ rab_setup_it := ts_S1AP_RABSetupItemCtxtSURes(rab_id := 5,
+ tla := oct2bit(f_inet_addr(mp_mme_ip)),
+ gtp_teid := '00000002'O);
+ rab_setup_items := ts_S1AP_RABSetupListCtxtSURes(rab_setup_it);
+ S1AP.send(ts_S1AP_InitialCtxSetupResp(valueof(mme_ue_id), valueof(enb_ue_id), rab_setup_items));
+
+ nas := ts_NAS_ActDefEpsBearCtxAck(int2bit(g_pars.ue_pars.bearer.ebi, 4), '00000000'B, omit);
+ esm_enc := enc_PDU_NAS_EPS(valueof(nas));
+ S1AP.send(ts_NAS_AttachComplete(esm_enc));
+
+ /* Optional from the network: */
+ S1AP.receive(tr_NAS_EMMInformation);
+ }
+ [] S1AP.receive(PDU_NAS_EPS:?) -> value rx_nas {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx Unexpected NAS PDU msg: ", rx_nas));
+ }
+}
+
+private altstep as_s1ap_handle_IntialCtxSetupReq_TAU_Accept() runs on ConnHdlr {
+ var S1AP_PDU rx_msg;
+ var PDU_NAS_EPS rx_nas;
+ [] S1AP.receive(tr_S1AP_IntialCtxSetupReq) -> value rx_msg {
+ /* 3GPP TS 23.401 D.3.6 step 22: */
+ var template (omit) MME_UE_S1AP_ID mme_ue_id := f_S1AP_get_MME_UE_S1AP_ID(rx_msg);
+ var template (omit) ENB_UE_S1AP_ID enb_ue_id := f_S1AP_get_ENB_UE_S1AP_ID(rx_msg);
+ var template (value) E_RABSetupItemCtxtSURes rab_setup_it;
+ var template (value) E_RABSetupListCtxtSURes rab_setup_items;
+ var S1APEM_Config cfg;
+
+ S1AP.receive(tr_PDU_NAS_EPS_TrackingAreaUpdateAccept)-> value rx_nas;
+
+ /* Configure integrity protection: */
+ cfg := {
+ set_nas_alg_int := NAS_ALG_IP_EIA1
+ };
+ S1AP.send(cfg);
+
+ rab_setup_it := ts_S1AP_RABSetupItemCtxtSURes(rab_id := 5,
+ tla := oct2bit(f_inet_addr(mp_mme_ip)),
+ gtp_teid := '00000002'O);
+ rab_setup_items := ts_S1AP_RABSetupListCtxtSURes(rab_setup_it);
+ S1AP.send(ts_S1AP_InitialCtxSetupResp(valueof(mme_ue_id), valueof(enb_ue_id), rab_setup_items));
+
+ /* 3GPP TS 23.401 D.3.6 step 23: */
+ /* Integrity Protection: TS 24.301 Section 4.4.4.3*/
+ S1AP.send(ts_PDU_NAS_EPS_TrackingAreaUpdateComplete(c_EPS_SEC_IP));
+ }
+ [] S1AP.receive(PDU_NAS_EPS:?) -> value rx_nas {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx Unexpected NAS PDU msg: ", rx_nas));
+ }
+}
+
+private altstep as_s1ap_handle_UeContextReleaseCmd(template S1AP_IEs.Cause cause := ?) runs on ConnHdlr {
+ var S1AP_PDU rx_msg;
+ var PDU_NAS_EPS rx_nas;
+ [] S1AP.receive(tr_S1AP_UeContextReleaseCmd(?, cause)) -> value rx_msg {
+ var template MME_UE_S1AP_ID mme_ue_id;
+ var template ENB_UE_S1AP_ID enb_ue_id;
+ if (not ispresent(rx_msg.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair)) {
+ /* TODO: The UE CONTEXT RELEASE COMMAND (see also: 3GPP TS 36.413, section 9.1.4.6), may identify the
+ * context by either an uE_S1AP_ID_pair (MME_UE_S1AP_ID and ENB_UE_S1AP_ID) or an MME_UE_S1AP_ID alone.
+ * The latter case is not implemented here yet. */
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("complete implementation of UeContextReleaseCmd handling"));
+ return;
+ }
+
+ mme_ue_id := rx_msg.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.mME_UE_S1AP_ID;
+ enb_ue_id := rx_msg.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_S1AP_IDs.uE_S1AP_ID_pair.eNB_UE_S1AP_ID;
+
+ S1AP.send(ts_S1AP_UeContextReleaseCompl(mme_ue_id, enb_ue_id));
+ }
+ [] S1AP.receive(PDU_NAS_EPS:?) -> value rx_nas {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Rx Unexpected NAS PDU msg: ", rx_nas));
+ }
+}
+
/* Exepect AuthInfoReq (AIR) from HSS; respond with AuthInforAnswer (AIA) */
private altstep as_DIA_AuthInfo() runs on ConnHdlr {
var PDU_DIAMETER rx_dia;
@@ -483,8 +734,9 @@ private altstep as_DIA_AuthInfo() runs on ConnHdlr {
/* compute tuple */
auth_info_content := { ts_AVP_EutranVec(1, '20080c3818183b522614162c07601d0d'O, '6a91970e838fd079'O, 'f11b89a2a8be00001f9c526f3d75d44c'O, '95AFAD9A0D29AFAA079A9451DF7161D7EE4CBF2AF9387F766D058BB6B44B905D'O) };
- DIAMETER.send(ts_DIA_AIA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id,
- sess_id, auth_info_content));
+ DIAMETER.send(ts_DIA_AIA(auth_info_content, sess_id,
+ hbh_id := rx_dia.hop_by_hop_id,
+ ete_id := rx_dia.end_to_end_id));
}
}
@@ -493,14 +745,12 @@ private altstep as_DIA_UpdLoc() runs on ConnHdlr {
var PDU_DIAMETER rx_dia;
[] DIAMETER.receive(tr_DIA_ULR(g_pars.ue_pars.imsi)) -> value rx_dia {
var template (omit) AVP avp;
- var octetstring sess_id;
var hexstring imsi;
var template (value) AVP_list sub_data;
/* retrieve input data */
imsi := valueof(f_DIAMETER_get_imsi(rx_dia));
avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
- sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
sub_data := {
ts_AVP_3GPP_SubscriberStatus(SERVICE_GRANTED),
@@ -513,20 +763,247 @@ private altstep as_DIA_UpdLoc() runs on ConnHdlr {
})
};
- DIAMETER.send(ts_DIA_ULA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id, sub_data));
+ DIAMETER.send(ts_DIA_ULA(sub_data, avp.avp_data.avp_BASE_NONE_Session_Id,
+ hbh_id := rx_dia.hop_by_hop_id,
+ ete_id := rx_dia.end_to_end_id));
}
}
-private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
+private function f_DIA_CancelLocation(integer idx := 0, template S1AP_IEs.Cause cause := omit) runs on ConnHdlr {
- f_init_handler(pars);
- var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
+ var UINT32 hbh_id := f_rnd_octstring(4);
+ var UINT32 ete_id := f_rnd_octstring(4);
+ var PDU_DIAMETER rx_dia;
+
+ /* Unlike CLR, CLA contains no IMSI. Register ete_id in DIAMETER_Emulation,
+ * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT.
+ */
+ f_diameter_expect_eteid(ete_id);
+
+ DIAMETER.send(ts_DIA_CLR(g_pars.ue_pars.imsi, SGSN_UPDATE_PROCEDURE,
+ orig_host := mp_s6_local_diam_host,
+ orig_realm := mp_s6_diam_realm,
+ dest_host := mp_s6_remote_diam_host,
+ dest_realm := mp_s6_diam_realm,
+ hbh_id := hbh_id,
+ ete_id := ete_id));
+
+ alt {
+ [] DIAMETER.receive(tr_DIA_CLA) -> value rx_dia {}
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter S6b msg rx: ", rx_dia));
+ }
+ }
+}
+
+private altstep as_GTP2C_CreateSession_success() runs on ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var BearerContextIEs rx_bctx_ies;
+ var template (value) FullyQualifiedTEID s11_fteid_c_ie, s11_fteid_u_ie, s5c_fteid_c_ie, s5c_fteid_u_ie;
+ var template (value) PDN_AddressAllocation paa;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_CreateSessionReq(g_pars.ue_pars.imsi)) -> value rx_msg {
+ /* Parse TEIC and Bearer EBI and TEID and store it in g_pars */
+ g_pars.ue_pars.s11_teic_remote := rx_msg.gtpcv2_pdu.createSessionRequest.fullyQualifiedTEID[0].tEID_GRE_Key;
+ g_pars.ue_pars.s5c_teic_remote := rx_msg.gtpcv2_pdu.createSessionRequest.fullyQualifiedTEID[1].tEID_GRE_Key;
+
+ rx_bctx_ies := rx_msg.gtpcv2_pdu.createSessionRequest.bearerContextGrouped[0].bearerContextIEs;
+ 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.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.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,
+ f_inet_addr(mp_s11_local_ip), omit);
+ s5c_fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_PGW_GTPC, g_pars.ue_pars.s5c_teic_local, 1,
+ f_inet_addr(mp_s5c_pgw_ip), omit);
+ s11_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S1U_SGW_GTPU, g_pars.ue_pars.bearer.s11_teid_local, 0,
+ f_inet_addr(mp_s11_local_ip), omit);
+ s5c_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_PGW_GTPU, g_pars.ue_pars.bearer.s5c_teid_local, 2,
+ f_inet_addr(mp_s5c_pgw_ip), omit);
+ paa := ts_GTP2C_PdnAddrAlloc_v4(f_inet_addr(g_pars.ue_pars.ue_ip));
+ bctx_ies := ts_GTP2C_BcContextIE(ebi := g_pars.ue_pars.bearer.ebi,
+ teid_list := { s11_fteid_u_ie, s5c_fteid_u_ie },
+ qos := ts_GTP2C_BearerQos('09'O, 0, 0, 0, 0),
+ charging_id := ts_GTP2C_ChargingID(g_pars.ue_pars.bearer.s11_teid_local));
+
+ GTP2.send(ts_GTP2C_CreateSessionResp(g_pars.ue_pars.s11_teic_remote,
+ rx_msg.sequenceNumber,
+ Request_accepted,
+ { s11_fteid_c_ie, s5c_fteid_c_ie },
+ paa, { ts_GTP2C_BcGrouped(bctx_ies) } ));
+ setverdict(pass);
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected GTPv2/S11 message from MME"));
+ }
+}
+
+private altstep as_GTP2C_ModifyBearer_success() runs on ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+ var BearerContextIEs rx_bctx_ies;
+ var template (value) FullyQualifiedTEID s11_fteid_c_ie, s11_fteid_u_ie, s5c_fteid_c_ie, s5c_fteid_u_ie;
+ var template (value) BearerContextIEs bctx_ies;
+
+ [] GTP2.receive(tr_GTP2C_ModifyBearerReq(g_pars.ue_pars.s11_teic_local)) -> value rx_msg {
+
+ rx_bctx_ies := rx_msg.gtpcv2_pdu.modifyBearerRequest.bearerContextGrouped[0].bearerContextIEs;
+
+ /* TODO: validate the S1-U fullyQualifiedTEID announces the IP address provided by the ENB in InitialCtxSetupResp */
+ // rx_bctx_ies.fullyQualifiedTEID[0]. == f_inet_addr(mp_mme_ip)
+
+ /* Update S11 TEID */
+ g_pars.ue_pars.bearer.s11_teid_remote := rx_bctx_ies.fullyQualifiedTEID[0].tEID_GRE_Key;
+
+ s11_fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S1U_SGW_GTPU, g_pars.ue_pars.bearer.s11_teid_local, 0,
+ f_inet_addr(mp_s11_local_ip), omit);
+ bctx_ies := ts_GTP2C_BcContextIE(ebi := g_pars.ue_pars.bearer.ebi,
+ teid_list := { s11_fteid_u_ie },
+ qos := ts_GTP2C_BearerQos('09'O, 0, 0, 0, 0),
+ charging_id := ts_GTP2C_ChargingID(g_pars.ue_pars.bearer.s11_teid_local));
+
+ GTP2.send(ts_GTP2C_ModifyBearerResp(g_pars.ue_pars.s11_teic_remote,
+ rx_msg.sequenceNumber,
+ Request_accepted,
+ g_pars.ue_pars.bearer.ebi,
+ { ts_GTP2C_BcGrouped(bctx_ies) } ));
+ setverdict(pass);
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected GTPv2/S11 message from MME"));
+ }
+}
+
+private altstep as_GTP2C_DeleteSession_success(template Indication ind_flags := *) runs on ConnHdlr {
+ var PDU_GTPCv2 rx_msg;
+
+ [] GTP2.receive(tr_GTP2C_DeleteSessionReq(g_pars.ue_pars.s11_teic_local, indicationFlags := ind_flags)) -> value rx_msg {
+ GTP2.send(ts_GTP2C_DeleteSessionResp(g_pars.ue_pars.s11_teic_remote,
+ rx_msg.sequenceNumber,
+ Request_accepted));
+ setverdict(pass);
+ }
+ [] GTP2.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unexpected GTPv2/S11 message from MME"));
+ }
+}
+
+
+/* 3GPP TS 23.401 D.3.5, TS 23.003 2.8.2.1 */
+private function guti2rai_ptmsi(in NAS_EPS_Types.GUTI guti, in OCT2 truncated_nas_token, out RoutingAreaIdentity rai, out OCT4 ptmsi, out OCT3 ptmsi_sig) runs on ConnHdlr {
+ var bitstring mtmsi_bits := oct2bit(guti.mTMSI);
+ var bitstring ptmsi_bits;
+ var bitstring ptmsi_sig_bits;
+
+ rai := valueof(ts_RoutingAreaIdentity(guti.mccDigit1 & guti.mccDigit2 & guti.mccDigit3,
+ guti.mncDigit3 & guti.mncDigit1 & guti.mncDigit2,
+ guti.mMEGI, guti.mMEC));
+ /* 3GPP TS 23.003 2.8.2.0: "P-TMSI shall be of 32 bits length where the two topmost bits are
+ * reserved and always set to '11'. Hence, for a UE which may handover to GERAN/UTRAN (based on
+ * subscription and UE capabilities), the corresponding bits in the M-TMSI are set to '11'"
+ */
+ ptmsi_bits := '11'B & substr(mtmsi_bits, 2, 6) & oct2bit(guti.mMEC) & substr(mtmsi_bits, 16, 16);
+ ptmsi_sig_bits := substr(mtmsi_bits, 8, 8) & oct2bit(truncated_nas_token);
+ ptmsi := bit2oct(ptmsi_bits);
+ ptmsi_sig := bit2oct(ptmsi_sig_bits);
+ /* TODO: The UE shall fill the remaining 2 octets of the <P-TMSI signature> according to clauses 9.1.1, 9.4.1, 10.2.1, or
+ * 10.5.1 of 3GPP TS.33.401 [89] , as appropriate, for RAU/Attach procedures.*/
+}
+
+/* Test UE attached to EUTRAN reselecting a GERAN cell. In this scenario, the
+ * new SGSN will attempt to obtain information of the UE from the old SGSN (MME)
+ * through Gn interface using SGSN Context Request/Response procedure (OS#6294). */
+private function f_gtp_sgsn_context_4g_to_2g(OCT4 new_sgsn_local_teid := '12345678'O) runs on ConnHdlr {
+ var template (value) GTPC_PDUs SGSNContextReqPDU;
+ var RoutingAreaIdentity rai;
+ var OCT4 ptmsi;
+ var OCT3 ptmsi_sig;
+ var Gtp1cUnitdata gtpc_pdu;
+ var OCT4 old_mme_local_teid;
+ var uint16_t gtpc_seq_nr := f_rnd_int(65535);
+
+ /* Derive NAS Token (and post-increment ul_count): */
+ var OCT32 nas_token := f_s1apem_derive_nas_token(g_pars.ue_pars.kasme);
+ var OCT2 truncated_nas_token := substr(nas_token, 30, 2);
+
+ guti2rai_ptmsi(g_pars.ue_pars.guti, truncated_nas_token, rai, ptmsi, ptmsi_sig);
+
+ SGSNContextReqPDU := ts_SGSNContextReqPDU(rai, new_sgsn_local_teid, f_inet_addr(mp_gn_local_ip),
+ ptmsi := ts_PTMSI(ptmsi), ptmsi_sig := ts_PTMSI_sig(ptmsi_sig));
+ GTP.send(ts_GTPC_SGSNContextReq(g_gn_iface_peer, gtpc_seq_nr, SGSNContextReqPDU));
+
+ timer T := 5.0;
+ T.start;
+ alt {
+ [] GTP.receive(tr_GTPC_SGSNContextResp(g_gn_iface_peer, new_sgsn_local_teid,
+ tr_SGSNContextRespPDU(GTP_CAUSE_REQUEST_ACCEPTED,
+ g_pars.ue_pars.imsi))) -> value gtpc_pdu {
+ old_mme_local_teid := gtpc_pdu.gtpc.gtpc_pdu.sgsn_ContextResponse.teidControlPlane.teidControlPlane;
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("unexpected GTPC message from MME"));
+ }
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("no SGSN Context Response from MME"));
+ }
+ }
+
+ GTP.send(ts_GTPC_SGSNContextAck(g_gn_iface_peer, old_mme_local_teid,
+ oct2int(gtpc_pdu.gtpc.opt_part.sequenceNumber),
+ ts_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED)));
+
+}
+
+private altstep as_gtp_sgsn_context_2g_to_4g(OCT4 new_sgsn_teid := 'ABABABAB'O, GTPv1C_Templates.GTP_RATType rat_type := GTP_RAT_TYPE_EUTRAN) runs on ConnHdlr {
+ var Gtp1cUnitdata gtpc_pdu;
+
+ [] GTP.receive(tr_GTPC_SGSNContextReq(g_gn_iface_peer, tr_SGSNContextReqPDU(rat_type := int2oct(enum2int(rat_type), 1)))) -> value gtpc_pdu {
+ var template (value) PDP_Context_GTPC pdp_ctx;
+ var template (value) GTPC_PDUs SGSNContextRespPDU;
+ var Gtp1cUnitdata gtpc_pdu_ack;
+ var OCT4 old_mme_remote_teid := gtpc_pdu.gtpc.gtpc_pdu.sgsn_ContextRequest.teidControlPlane.teidControlPlane;
+
+ const OCT16 ck := '740d62df9803eebde5120acf358433d0'O;
+ const OCT16 ik := '11329aae8e8d2941bb226b2061137c58'O;
+
+ pdp_ctx := ts_PDP_Context_GTPC(f_inet_addr(g_pars.ue_pars.ue_ip),
+ f_inet_addr(mp_gn_local_ip),
+ c_NAS_defaultAPN,
+ ggsn_teic := '12345678'O,
+ ggsn_teid := '87654321'O);
+ SGSNContextRespPDU := ts_SGSNContextRespPDU(GTP_CAUSE_REQUEST_ACCEPTED,
+ g_pars.ue_pars.imsi,
+ new_sgsn_teid,
+ f_inet_addr(mp_gn_local_ip),
+ ts_MM_ContextUMTS(ck, ik),
+ { pdp_ctx });
+ GTP.send(ts_GTPC_SGSNContextResp(g_gn_iface_peer,
+ old_mme_remote_teid,
+ oct2int(gtpc_pdu.gtpc.opt_part.sequenceNumber),
+ SGSNContextRespPDU));
+
+ GTP.receive(tr_GTPC_SGSNContextAck(g_gn_iface_peer, new_sgsn_teid,
+ tr_SGSNContextAckPDU(GTP_CAUSE_REQUEST_ACCEPTED))) -> value gtpc_pdu;
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ setverdict(fail, "unexpected GTPC message from MME");
+ }
+}
+
+private function f_attach() runs on ConnHdlr {
+ var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(g_pars.ue_pars.imsi);
var template (value) PDU_NAS_EPS nas_esm, nas_emm;
-/*
- nas_esm := ts_NAS_ActDefEpsBearCtxReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
- qos := c_NAS_defaultQoS, apn := c_NAS_defaultAPN,
- addr_type := '000'B, addr_info := ''O);
-*/
+ timer T := 5.0;
+
nas_esm := ts_NAS_PdnConnReq(bearer_id := '0000'B, proc_tid := int2bit(1,8),
pdn_type := NAS_PDN_T_IPv4, req_type := '001'B);
nas_emm := ts_NAS_AttachRequest(att_type := '000'B, kset_id := '000'B, mobile_id := mi,
@@ -550,7 +1027,32 @@ private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
}
}
- f_sleep(10.0);
+ /* We now expect the MME to send a Create Session Request to the SGW-C */
+ f_gtp2_register_udmsg('20'O);
+ T.start;
+ alt {
+ [] as_GTP2C_CreateSession_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ T.start;
+ alt {
+ [] as_s1ap_handle_IntialCtxSetupReq_Attach_Accept();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ /* We now expect the MME to send a Modify Bearer Request to the SGW-C */
+ f_gtp2_register_udmsg('22'O);
+ T.start;
+ alt {
+ [] as_GTP2C_ModifyBearer_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+}
+
+private function f_TC_attach(ConnHdlrPars pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_attach();
}
testcase TC_s1ap_attach() runs on MTC_CT {
var charstring id := testcasename();
@@ -558,6 +1060,7 @@ testcase TC_s1ap_attach() runs on MTC_CT {
f_init_diameter(id);
f_sleep(10.0);
f_init_s1ap(id, 4);
+ f_init_gtpv2_s11(id);
f_s1ap_setup(0);
var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
@@ -566,11 +1069,508 @@ testcase TC_s1ap_attach() runs on MTC_CT {
vc_conn.done;
}
+private function f_TC_gn_echo_request(ConnHdlrPars pars) runs on ConnHdlr {
+ timer T := 5.0;
+ f_init_handler(pars);
+ f_gtp_register_teid('00000000'O);
+
+ GTP.send(ts_GTPC_PING(g_gn_iface_peer, 1));
+ T.start;
+ alt {
+ [] GTP.receive(tr_GTPC_PONG(?)) {
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ setverdict(fail, "unexpected GTPC message from MME");
+ }
+ [] T.timeout {
+ setverdict(fail, "no GTPC ECHO RESPONSE from MME");
+ }
+ }
+}
+testcase TC_gn_echo_request() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 0);
+ f_s1ap_setup(0);
+ f_init_gtp(id);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_gn_echo_request), pars);
+ vc_conn.done;
+}
+
+external function enc_PDU_GTPC_RAN_INF_REQ(in PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC gtpc_pdu) return octetstring
+with { extension "prototype(convert)"
+ extension "encode(RAW)"
+ }
+
+external function enc_PDU_GTPC_RAN_INF(in PDU_BSSGP_RAN_INFORMATION_GTPC gtpc_pdu) return octetstring
+with { extension "prototype(convert)"
+ extension "encode(RAW)"
+ }
+
+function f_convert_plmn(OCT3 pLMNidentity) return hexstring {
+ var hexstring pLMNidentity_hex := oct2hex(pLMNidentity);
+ var hexstring pLMNidentity_hex_swapped;
+ pLMNidentity_hex_swapped[0] := pLMNidentity_hex[1];
+ pLMNidentity_hex_swapped[1] := pLMNidentity_hex[0];
+ pLMNidentity_hex_swapped[2] := pLMNidentity_hex[3];
+ pLMNidentity_hex_swapped[3] := pLMNidentity_hex[2];
+ pLMNidentity_hex_swapped[4] := pLMNidentity_hex[5];
+ pLMNidentity_hex_swapped[5] := pLMNidentity_hex[4];
+ return pLMNidentity_hex_swapped;
+}
+
+/* Make a template for a GTPC BSSGP container that contains a RAN INFORMATION REQUEST. The template can be used to
+ * craft the request for the S1AP/S1-MME interface and also to verfify the contents of the coresponding request on
+ * the GTPC/Gn interface */
+private function f_make_ts_GTPC_RAN_Information_Request(GTP_CellId geran_gtp_ci)
+ runs on ConnHdlr return template (value) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC {
+ var template (value) RIM_Routing_Address_GTPC gtpc_dst_addr, gtpc_src_addr;
+ var template (value) RAN_Information_Request_RIM_Container_GTPC gtpc_rim_req_cont;
+ var template (value) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC gtpc_bssgp_cont;
+ var octetstring gnbid;
+ var GTP_CellId eutran_gtp_ci;
+ eutran_gtp_ci.ra_id.lai.mcc_mnc := f_convert_plmn(g_pars.enb_pars[g_pars.mme_idx].global_enb_id.pLMNidentity);
+
+ gnbid := enc_S1AP_Global_ENB_ID(g_pars.enb_pars[g_pars.mme_idx].global_enb_id);
+ gtpc_dst_addr := t_GTPC_RIM_Routing_Address_cid(geran_gtp_ci);
+ gtpc_src_addr := t_GTPC_RIM_Routing_Address_enbid(eutran_gtp_ci,
+ oct2int(g_pars.enb_pars[g_pars.mme_idx].supported_tas[0].tAC),
+ gnbid);
+
+ gtpc_rim_req_cont := ts_GTPC_RAN_Information_Request_RIM_Container(
+ ts_GTPC_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_GTPC_RIM_Sequence_Number(1),
+ ts_GTPC_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_GTPC_RIM_Protocol_Version_Number(1),
+ tsu_GTPC_RAN_Information_Request_Application_Container_NACC(geran_gtp_ci),
+ omit);
+ gtpc_bssgp_cont := ts_GTPC_RAN_Information_Request(
+ ts_GTPC_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, gtpc_dst_addr),
+ ts_GTPC_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, gtpc_src_addr),
+ gtpc_rim_req_cont);
+
+ return gtpc_bssgp_cont;
+}
+
+private function f_make_tr_GTPC_RAN_Information_Request(GTP_CellId geran_gtp_ci)
+ runs on ConnHdlr return template (present) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC {
+ var template (present) RIM_Routing_Address_GTPC gtpc_dst_addr, gtpc_src_addr;
+ var template (present) RAN_Information_Request_RIM_Container_GTPC gtpc_rim_req_cont;
+ var template (present) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC gtpc_bssgp_cont;
+ var octetstring gnbid;
+ var GTP_CellId eutran_gtp_ci;
+ eutran_gtp_ci.ra_id.lai.mcc_mnc := f_convert_plmn(g_pars.enb_pars[g_pars.mme_idx].global_enb_id.pLMNidentity);
+
+ gnbid := enc_S1AP_Global_ENB_ID(g_pars.enb_pars[g_pars.mme_idx].global_enb_id);
+ gtpc_dst_addr := t_GTPC_RIM_Routing_Address_cid(geran_gtp_ci);
+ gtpc_src_addr := t_GTPC_RIM_Routing_Address_enbid(eutran_gtp_ci,
+ oct2int(g_pars.enb_pars[g_pars.mme_idx].supported_tas[0].tAC),
+ gnbid);
+
+ gtpc_rim_req_cont := tr_GTPC_RAN_Information_Request_RIM_Container(
+ ts_GTPC_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_GTPC_RIM_Sequence_Number(1),
+ ts_GTPC_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_GTPC_RIM_Protocol_Version_Number(1),
+ tru_GTPC_RAN_Information_Request_Application_Container_NACC(geran_gtp_ci));
+ gtpc_bssgp_cont := tr_GTPC_RAN_Information_Request(
+ tr_GTPC_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, gtpc_dst_addr),
+ tr_GTPC_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, gtpc_src_addr),
+ gtpc_rim_req_cont);
+
+ return gtpc_bssgp_cont;
+}
+
+/* Make initial RAN INFORMATION REQUEST message that is sent on the S1AP/S1-MME interface */
+private function f_make_ts_S1AP_eNBDirectInfTrans(GTP_CellId geran_gtp_ci)
+ runs on ConnHdlr return template (value) S1AP_PDU {
+ var template (value) Inter_SystemInformationTransferType inf;
+
+ inf.rIMTransfer.rIMInformation := enc_PDU_GTPC_RAN_INF_REQ(valueof(f_make_ts_GTPC_RAN_Information_Request(geran_gtp_ci)));
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.lAI.pLMNidentity := hex2oct(f_convert_plmn(hex2oct(geran_gtp_ci.ra_id.lai.mcc_mnc)));
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.lAI.lAC := int2oct(geran_gtp_ci.ra_id.lai.lac, 2);
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.lAI.iE_Extensions := omit;
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.rAC := int2oct(geran_gtp_ci.ra_id.rac, 1);
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.cI := int2oct(geran_gtp_ci.cell_id, 2);
+ inf.rIMTransfer.rIMRoutingAddress.gERAN_Cell_ID.iE_Extensions := omit;
+ inf.rIMTransfer.iE_Extensions := omit;
+
+ return ts_S1AP_eNBDirectInfTrans(inf);
+}
+
+/* Make RAN INFORMATION (response) message that is sent on the GTPC/Gn interface */
+private function f_make_ts_GTPC_RANInfoRelay(template Gtp1cUnitdata req_gtpc_pdu,
+ GTP_CellId geran_gtp_ci, octetstring geran_si)
+ runs on ConnHdlr return template (value) Gtp1cUnitdata {
+ var template Gtp1cUnitdata res_gtpc_pdu;
+ var template RAN_Information_RIM_Container_GTPC gtpc_rim_res_cont;
+ var template PDU_BSSGP_RAN_INFORMATION_GTPC gtpc_bssgp_rim_res_pdu;
+ var template RIM_Routing_Information_GTPC gtpc_rim_dst_cell_id, gtpc_rim_src_cell_id;
+ var template RIM_RoutingAddress gtpc_rim_ra;
+ var template RIM_RoutingAddress_Discriminator gtpc_rim_ra_discr;
+
+ /* Assemble GTPC RAN Information */
+ gtpc_rim_res_cont := ts_GTPC_RAN_Information_RIM_Container(ts_GTPC_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_GTPC_RIM_Sequence_Number(2),
+ ts_GTPC_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_GTPC_RIM_Protocol_Version_Number(1),
+ tsu_GTPC_ApplContainer_or_ApplErrContainer_NACC(tsu_GTPC_ApplContainer_NACC(geran_gtp_ci, false, 3, geran_si)),
+ omit);
+
+ /* The source becomes the destination and vice versa */
+ gtpc_rim_dst_cell_id := req_gtpc_pdu.gtpc.gtpc_pdu.ranInformationRelay.transparentContainer.
+ rANTransparentContainerField.pDU_BSSGP_RAN_INFORMATION_REQUEST.source_Cell_Identifier
+ gtpc_rim_src_cell_id := req_gtpc_pdu.gtpc.gtpc_pdu.ranInformationRelay.transparentContainer.
+ rANTransparentContainerField.pDU_BSSGP_RAN_INFORMATION_REQUEST.destination_Cell_Identifier
+ gtpc_bssgp_rim_res_pdu := ts_GTPC_RAN_Information(gtpc_rim_dst_cell_id,
+ gtpc_rim_src_cell_id,
+ gtpc_rim_res_cont);
+
+ /* Assemble RIM Routing Address (essentially a copy of the destination cell identifier)*/
+ gtpc_rim_ra := ts_RIM_RoutingAddress(enc_RIM_Routing_Address_GTPC(valueof(gtpc_rim_dst_cell_id.rIM_Routing_Address)));
+ gtpc_rim_ra_discr := ts_RIM_RoutingAddress_Discriminator(hex2bit(valueof(gtpc_rim_dst_cell_id.rIMRoutingAddressDiscriminator)));
+
+ res_gtpc_pdu := ts_GTPC_RANInfoRelay(g_gn_iface_peer,
+ ts_RANTransparentContainer_RAN_INFO(gtpc_bssgp_rim_res_pdu),
+ gtpc_rim_ra, gtpc_rim_ra_discr);
+
+ return res_gtpc_pdu;
+}
+
+/* Make template to verify the RAN INFORMATION REQUEST as it appears on the GTPC/Gn interface */
+private function f_make_tr_GTPC_MsgType(GTP_CellId geran_gtp_ci)
+ runs on ConnHdlr return template (present) Gtp1cUnitdata {
+ var template Gtp1cUnitdata msg;
+ var template GTPC_PDUs pdus;
+ var template RANTransparentContainer ran_transp_cont;
+
+ ran_transp_cont := tr_RANTransparentContainer_RAN_INFO_REQ(
+ f_make_tr_GTPC_RAN_Information_Request(geran_gtp_ci));
+ pdus := tr_RANInfoRelay(ran_transp_cont);
+ msg := tr_GTPC_MsgType(g_gn_iface_peer, rANInformationRelay, '00000000'O, pdus);
+
+ return msg;
+}
+
+/* Make template to verify the RAN INFORMATION (response) as it appears on the S1AP/S1-MME interface */
+private function f_make_tr_S1AP_MMEDirectInfTrans(Gtp1cUnitdata ran_information_gtpc_pdu)
+ runs on ConnHdlr return template (present) S1AP_PDU {
+ var template S1AP_PDU msg;
+ var template Inter_SystemInformationTransferType inf;
+
+ inf.rIMTransfer.rIMInformation := enc_PDU_GTPC_RAN_INF(
+ ran_information_gtpc_pdu.gtpc.gtpc_pdu.ranInformationRelay.
+ transparentContainer.rANTransparentContainerField.
+ pDU_BSSGP_RAN_INFORMATION);
+ inf.rIMTransfer.rIMRoutingAddress := omit;
+ inf.rIMTransfer.iE_Extensions := omit;
+ msg := tr_S1AP_MMEDirectInfTrans(inf);
+
+ return msg;
+}
+
+private function f_TC_RIM_RAN_INF(ConnHdlrPars pars) runs on ConnHdlr {
+ timer T := 5.0;
+ f_init_handler(pars);
+ f_gtp_register_teid('00000000'O);
+ var Gtp1cUnitdata req_gtpc_pdu;
+ var Gtp1cUnitdata resp_gtpc_pdu;
+ var GTP_CellId geran_gtp_ci;
+
+ /* Assemble data of a fictitiously GERAN cell */
+ geran_gtp_ci.ra_id.rac := mp_gn_local_rac;
+ geran_gtp_ci.ra_id.lai.mcc_mnc := mp_gn_local_mcc & mp_gn_local_mnc;
+ geran_gtp_ci.ra_id.lai.lac := mp_gn_local_lac;
+ geran_gtp_ci.cell_id := mp_gn_local_ci;
+ const octetstring geran_si1 := '198fb100000000000000000000000000007900002b'O;
+ const octetstring geran_si3 := '1b753000f110236ec9033c2747407900003c0b2b2b'O;
+ const octetstring geran_si13 := '009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O;
+ const octetstring geran_si := geran_si1 & geran_si3 & geran_si13;
+
+ /* Send initial RAN information request via S1AP to MME and expect the MME to forward the request on GTP-C
+ * (eNB -> MME -> SGSN) */
+ S1AP.send(f_make_ts_S1AP_eNBDirectInfTrans(geran_gtp_ci));
+ T.start;
+ alt {
+ [] GTP.receive(f_make_tr_GTPC_MsgType(geran_gtp_ci)) -> value req_gtpc_pdu {
+ setverdict(pass);
+ }
+ [] GTP.receive {
+ setverdict(fail, "unexpected GTPC message from MME");
+ }
+ [] T.timeout {
+ setverdict(fail, "no GTPC RAN INFORMATION REQUEST from MME");
+ }
+ }
+
+ /* Send RAN information response via GTP-C to MME and expect the MME to forward the respnse on S1AP
+ * (SGSN -> MME -> eNB) */
+ f_create_s1ap_expect_proc(id_MMEDirectInformationTransfer, self);
+ resp_gtpc_pdu := valueof(f_make_ts_GTPC_RANInfoRelay(req_gtpc_pdu, geran_gtp_ci, geran_si));
+ GTP.send(resp_gtpc_pdu);
+ T.start;
+ alt {
+ [] S1AP.receive(f_make_tr_S1AP_MMEDirectInfTrans(resp_gtpc_pdu)) {
+ setverdict(pass);
+ }
+ [] S1AP.receive {
+ setverdict(fail, "unexpected S1AP message from MME");
+ }
+ [] T.timeout {
+ setverdict(fail, "no S1AP RAN INFORMATION from MME");
+ }
+ }
+
+ setverdict(pass);
+}
+
+testcase TC_RIM_RAN_INF() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 0);
+ f_s1ap_setup(0);
+ f_init_gtp(id);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_RIM_RAN_INF), pars);
+
+ vc_conn.done;
+}
+
+/* Successful RESET procedure from eNB to MME */
+testcase TC_s1ap_reset() runs on MTC_CT {
+ var charstring id := testcasename();
+ f_init_s1ap(id, 0);
+ f_s1ap_setup(0);
+
+ var template (value) S1AP_IEs.Cause reset_cause := {misc := om_intervention};
+ var template (value) ResetType reset_type := {s1_Interface := reset_all};
+ timer T := 5.0;
+
+ S1AP_UNIT[0].send(ts_S1AP_Reset(reset_cause, reset_type));
+ T.start;
+ alt {
+ [] S1AP_UNIT[0].receive(tr_S1AP_ResetAck_any) {
+ setverdict(pass);
+ }
+ [] S1AP_UNIT[0].receive {
+ setverdict(fail, "Received unexpected S1AP");
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for S1AP Setup result");
+ }
+ }
+}
+
+/* Tracking area update with a GUTI (TMSI) that is unknown to the MME. The MME is expected to reject this TAU
+ * request. */
+private function f_TC_tau_unknown_guti(ConnHdlrPars pars) runs on ConnHdlr {
+
+ f_init_handler(pars);
+ var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
+ var template (value) S1AP_PDU tx;
+ var template (value) PDU_NAS_EPS nas_tau;
+ timer T := 5.0;
+
+ var hexstring mcc_mnc := f_convert_plmn(g_pars.enb_pars[g_pars.mme_idx].global_enb_id.pLMNidentity);
+ var EPS_MobileIdentityLV old_guti := valueof(ts_EPS_MobileId_GUTI(mcc_mnc, '0001'O, '01'O, 'AABBCCDD'O));
+ nas_tau := ts_PDU_NAS_EPS_TrackingAreaUpdateRequest(old_guti);
+
+ tx := ts_S1AP_InitialUE(p_eNB_value := 0, p_nasPdu := enc_PDU_NAS_EPS(valueof(nas_tau)),
+ p_tAI := ts_enb_S1AP_TAI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_eUTRAN_CGI := ts_enb_S1AP_CGI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_rrcCause := mo_Signalling);
+
+ S1AP.send(tx);
+
+ T.start;
+ alt {
+ [] S1AP.receive(tr_PDU_NAS_EPS_TrackingAreaUpdateReject) {
+ setverdict(pass);
+ }
+ [] S1AP.receive {
+ setverdict(fail, "unexpected S1AP message from MME");
+ }
+ [] T.timeout {
+ setverdict(fail, "no message from MME");
+ }
+ }
+
+ as_s1ap_handle_UeContextReleaseCmd();
+}
+testcase TC_s1ap_tau_unknown_guti() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 5);
+ f_s1ap_setup(0);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_tau_unknown_guti), pars);
+ vc_conn.done;
+}
+
+private function f_TC_ue_cell_reselect_eutran_to_geran(ConnHdlrPars pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_gtp_register_imsi(g_pars.ue_pars.imsi);
+ f_attach();
+
+ /* TS 23.401 Figure D.3.5-1 Steps 1,2,3,4: */
+ f_gtp_sgsn_context_4g_to_2g();
+
+ /* TS 23.401 Figure D.3.5-1 Step 8: */
+ f_DIA_CancelLocation();
+
+ /* TS 23.401 Figure D.3.5-1 Step 13:
+ * Upon rx of SGSN Context Acknowledge, MME released the ENB/UE context:
+ */
+ as_s1ap_handle_UeContextReleaseCmd();
+
+ /* TS 23.401 Figure D.3.5-1 Step 13:
+ * After Gn timer triggers, the SGW session is deleted.
+ * Make sure Operation Indication is set to 0, to tell the SGW to keep the Session up at the PGW.
+ */
+ as_GTP2C_DeleteSession_success(tr_GTP2C_Indication(oI := '0'B));
+ /* Let MME some time to handle the Create Session Response: */
+ f_sleep(3.0);
+}
+testcase TC_ue_cell_reselect_eutran_to_geran() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 6);
+ f_init_gtpv2_s11(id);
+ f_s1ap_setup(0);
+ f_init_gtp(id);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_ue_cell_reselect_eutran_to_geran), pars);
+ vc_conn.done;
+}
+
+/* 3GPP TS 23.401 D.3.6, TS 23.003 2.8.2.2 */
+private function rai_ptmsi2_guti(in RoutingAreaIdentity rai, in OCT4 ptmsi, in OCT3 ptmsi_sig, out NAS_EPS_Types.GUTI guti) runs on ConnHdlr {
+
+
+ var bitstring ptmsi_bits := oct2bit(ptmsi);
+ var bitstring ptmsi_sig_bits := oct2bit(ptmsi_sig);
+ var bitstring mtmsi_bits := '11'B &
+ substr(ptmsi_bits, 2, 6) &
+ substr(ptmsi_sig_bits, 0, 8) &
+ substr(ptmsi_bits, 16, 16);
+ guti := valueof(ts_NAS_GUTI(mcc_mnc := rai.mcc_digits & rai.mnc_digits,
+ mmegi := rai.lac,
+ mmec := rai.rac,
+ tmsi := bit2oct(mtmsi_bits)));
+}
+/* Test UE attached to GERAN reselecting a EUTRAN cell. In this scenario, the
+ * new MME will attempt to obtain information of the UE from the old SGSN
+ * through Gn interface using SGSN Context Request/Response procedure (OS#6294). */
+/* 3GPP TS 23.401 D.3.6, TS 23.003 2.8.2.1 */
+private function f_TC_ue_cell_reselect_geran_to_eutran(ConnHdlrPars pars) runs on ConnHdlr {
+ f_init_handler(pars);
+ f_gtp_register_imsi(g_pars.ue_pars.imsi);
+ f_gtp2_register_imsi(g_pars.ue_pars.imsi);
+ /* SGSN Context Req doesn't necessarily contain IMSI, hence expect it through TEID=0 */
+ f_gtp_register_teid('00000000'O);
+ /* passed in SGSN Context Resp to MME, will be used by MME when answering with SGSN Context Ack: */
+ const OCT4 new_sgsn_teid := 'ABABABAB'O;
+ f_gtp_register_teid(new_sgsn_teid);
+
+ var template (value) EPS_MobileIdentityV mi := ts_NAS_MobileId_IMSI(pars.ue_pars.imsi);
+ var template (value) S1AP_PDU tx;
+ var template (value) PDU_NAS_EPS nas_tau;
+ var RoutingAreaIdentity rai;
+ var OCT4 ptmsi := f_gen_tmsi(suffix := 0, nri_v := 0, nri_bitlen := 8);
+ var OCT3 ptmsi_sig := f_rnd_octstring(3);
+ var NAS_EPS_Types.GUTI guti_val;
+ var template (value) EPS_MobileIdentityLV old_guti;
+ var S1APEM_Config cfg;
+ timer T := 5.0;
+
+ rai := valueof(ts_RoutingAreaIdentity(mp_gn_local_mcc, mp_gn_local_mnc,
+ int2oct(mp_gn_local_lac, 2), int2oct(mp_gn_local_rac, 1)));
+ rai_ptmsi2_guti(rai, ptmsi, ptmsi_sig, guti_val);
+ old_guti := ts_EPS_MobileId_GUTI_(guti_val);
+
+ nas_tau := ts_PDU_NAS_EPS_TrackingAreaUpdateRequest(old_guti,
+ ts_PTMSI_SignatureTV(ptmsi_sig),
+ ts_GUTI_TypeTV(GUTI_TYPE_MAPPED),
+ ts_NonceTV('12345678'O),
+ ts_CipheringKeySequenceNumberTV('000'B));
+ tx := ts_S1AP_InitialUE(p_eNB_value := 0, p_nasPdu := enc_PDU_NAS_EPS(valueof(nas_tau)),
+ p_tAI := ts_enb_S1AP_TAI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_eUTRAN_CGI := ts_enb_S1AP_CGI(g_pars.enb_pars[g_pars.mme_idx]),
+ p_rrcCause := mo_Signalling);
+
+ S1AP.send(tx);
+
+ /* NAS counts are reset to zero when a mapped security context is created. */
+ cfg := {
+ reset_nas_counts := {}
+ };
+ S1AP.send(cfg);
+
+ as_gtp_sgsn_context_2g_to_4g(new_sgsn_teid);
+
+ /* We now expect the MME to send a Create Session Request to the SGW-C */
+ T.start;
+ alt {
+ [] as_GTP2C_CreateSession_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ /* 3GPP TS 23.401 D.3.6 steps 14-21: */
+ as_DIA_UpdLoc();
+
+ /* 3GPP TS 23.401 D.3.6 step 22, 23: */
+ as_s1ap_handle_IntialCtxSetupReq_TAU_Accept();
+
+ /* We now expect the MME to send a Modify Bearer Request to the SGW-C */
+ T.start;
+ alt {
+ [] as_GTP2C_ModifyBearer_success();
+ [] T.timeout { Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No message from MME")); }
+ }
+
+ /* Leave some time for MME to handle Modify Bearer Response: */
+ f_sleep(1.0);
+}
+testcase TC_ue_cell_reselect_geran_to_eutran() runs on MTC_CT {
+ var charstring id := testcasename();
+
+ f_init_diameter(id);
+ f_init_s1ap(id, 7);
+ f_init_gtpv2_s11(id);
+ f_s1ap_setup(0);
+ f_init_gtp(id);
+
+ var ConnHdlrPars pars := f_init_pars(ue_idx := 0);
+ var ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_TC_ue_cell_reselect_geran_to_eutran), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_s1ap_setup_wrong_plmn() );
execute( TC_s1ap_setup_wrong_tac() );
execute( TC_s1ap_setup() );
execute( TC_s1ap_attach() );
+ execute( TC_s1ap_tau_unknown_guti() );
+ execute( TC_gn_echo_request() );
+ execute( TC_RIM_RAN_INF() );
+ execute( TC_s1ap_reset() );
+ execute( TC_ue_cell_reselect_eutran_to_geran() );
+ execute( TC_ue_cell_reselect_geran_to_eutran() );
}
diff --git a/mme/expected-results.xml b/mme/expected-results.xml
new file mode 100644
index 00000000..48496a45
--- /dev/null
+++ b/mme/expected-results.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='71' failures='8' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='MME_Tests' name='TC_s1ap_setup_wrong_plmn' time='MASKED'/>
+ <testcase classname='MME_Tests' name='TC_s1ap_setup_wrong_tac' time='MASKED'/>
+ <testcase classname='MME_Tests' name='TC_s1ap_setup' time='MASKED'/>
+ <testcase classname='MME_Tests' name='TC_s1ap_attach' time='MASKED'/>
+</testsuite>
diff --git a/mme/gen_links.sh b/mme/gen_links.sh
index b0ecf861..be088706 100755
--- a/mme/gen_links.sh
+++ b/mme/gen_links.sh
@@ -40,7 +40,23 @@ FILES="GTPv2_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"
+FILES="GTPC_EncDec.cc GTPC_Types.ttcn GTPU_EncDec.cc GTPU_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.GTPv2_v13.7.0/src
+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
@@ -54,12 +70,17 @@ FILES+="S1AP_EncDec.cc S1AP_Types.ttcn S1AP_Templates.ttcn "
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 "
+FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPCP_Types.ttcn "
FILES+="SGsAP_Templates.ttcn SGsAP_CodecPort.ttcn SGsAP_CodecPort_CtrlFunct.ttcn SGsAP_CodecPort_CtrlFunctDef.cc SGsAP_Emulation.ttcn DNS_Helpers.ttcn "
FILES+="L3_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn "
FILES+="S1AP_CodecPort.ttcn S1AP_CodecPort_CtrlFunctDef.cc S1AP_CodecPort_CtrlFunct.ttcn S1AP_Emulation.ttcn "
FILES+="NAS_Templates.ttcn GTPv2_PrivateExtensions.ttcn GTPv2_Templates.ttcn "
-FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn DIAMETER_Templates.ttcn "
+FILES+="DIAMETER_Types.ttcn DIAMETER_CodecPort.ttcn DIAMETER_CodecPort_CtrlFunct.ttcn DIAMETER_CodecPort_CtrlFunctDef.cc DIAMETER_Emulation.ttcn "
+FILES+="DIAMETER_Templates.ttcn DIAMETER_ts29_272_Templates.ttcn "
+FILES+="GTPv1C_CodecPort.ttcn GTPv1C_CodecPort_CtrlFunct.ttcn GTPv1C_CodecPort_CtrlFunctDef.cc GTPv1U_CodecPort.ttcn GTPv1U_CodecPort_CtrlFunct.ttcn GTPv1U_CodecPort_CtrlFunctDef.cc GTP_Emulation.ttcn GTPv1C_Templates.ttcn Osmocom_Gb_Types.ttcn "
+FILES+="GTPv2_PrivateExtensions.ttcn GTPv2_Templates.ttcn "
+FILES+="GTPv2_CodecPort.ttcn GTPv2_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunct.ttcn GTPv2_Emulation.ttcn "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
gen_links $DIR $FILES
ignore_pp_results
diff --git a/mme/key_derivation.c b/mme/key_derivation.c
index 36e4c915..8d5d8a40 100644
--- a/mme/key_derivation.c
+++ b/mme/key_derivation.c
@@ -80,3 +80,19 @@ void hss_auc_kasme(const uint8_t *ck, const uint8_t *ik, const uint8_t plmn_id[3
gnutls_hmac_fast(GNUTLS_MAC_SHA256, k, 32, s, 14, kasme);
}
+
+/* TS33.401 Annex A.9: NAS token derivation for inter-RAT mobility */
+void mme_kdf_nas_token(const uint8_t *kasme, uint32_t ul_count, uint8_t *nas_token)
+{
+ uint8_t s[7];
+
+ s[0] = 0x17; /* FC Value */
+
+ ul_count = htonl(ul_count);
+ memcpy(s+1, &ul_count, 4);
+
+ s[5] = 0x00;
+ s[6] = 0x04;
+
+ gnutls_hmac_fast(GNUTLS_MAC_SHA256, kasme, 32, s, 7, nas_token);
+}
diff --git a/mme/key_derivation.h b/mme/key_derivation.h
index 496f52bc..ae15b658 100644
--- a/mme/key_derivation.h
+++ b/mme/key_derivation.h
@@ -19,3 +19,5 @@ void mme_kdf_nas(uint8_t algorithm_type_distinguishers,
void mme_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb);
void mme_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *kenb);
+
+void mme_kdf_nas_token(const uint8_t *kasme, uint32_t ul_count, uint8_t *nas_token);
diff --git a/mme/regen_makefile.sh b/mme/regen_makefile.sh
index 2d3bf591..6e86346e 100755
--- a/mme/regen_makefile.sh
+++ b/mme/regen_makefile.sh
@@ -1,9 +1,37 @@
#!/bin/sh
-FILES="*.ttcn *.asn *.c IPL4asp_PT.cc IPL4asp_discovery.cc Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc S1AP_CodecPort_CtrlFunctDef.cc TCCConversion.cc TCCEncoding.cc TCCInterface.cc TELNETasp_PT.cc S1AP_EncDec.cc LTE_CryptoFunctionDefs.cc GTPU_EncDec.cc GTPC_EncDec.cc DIAMETER_EncDec.cc DIAMETER_CodecPort_CtrlFunctDef.cc "
+NAME=MME_Tests
-export CPPFLAGS_TTCN3=""
+FILES="
+ *.asn
+ *.c
+ *.ttcn
+ 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
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LTE_CryptoFunctionDefs.cc
+ Native_FunctionDefs.cc
+ S1AP_CodecPort_CtrlFunctDef.cc
+ S1AP_EncDec.cc
+ SGsAP_CodecPort_CtrlFunctDef.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ UECUPS_CodecPort_CtrlFunctDef.cc
+"
-../regen-makefile.sh MME_Tests.ttcn $FILES
-sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode -lgnutls/' Makefile
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp -lfftranscode -lgnutls/' Makefile
diff --git a/msc/BSC_ConnectionHandler.ttcn b/msc/BSC_ConnectionHandler.ttcn
index cc69a68f..658923e3 100644
--- a/msc/BSC_ConnectionHandler.ttcn
+++ b/msc/BSC_ConnectionHandler.ttcn
@@ -12,9 +12,11 @@
module BSC_ConnectionHandler {
+import from TCCOpenSecurity_Functions all;
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
+import from Misc_Helpers all;
import from GSM_Types all;
import from IPL4asp_Types all;
import from SCCPasp_Types all;
@@ -29,6 +31,7 @@ import from RANAP_PDU_Descriptions all;
import from RANAP_Templates all;
import from GSUP_Types all;
+import from GSUP_Templates all;
import from GSUP_Emulation all;
import from MNCC_Types all;
@@ -38,6 +41,7 @@ import from MGCP_Types all;
import from MGCP_Emulation all;
import from MGCP_Templates all;
import from SDP_Types all;
+import from SDP_Templates all;
import from MobileL3_Types all;
import from MobileL3_CommonIE_Types all;
@@ -61,16 +65,39 @@ import from SGsAP_Emulation all;
import from TCCConversion_Functions { function f_strstr };
+type port BSC_ConnHdlr_Coord_PT message
+{
+ inout charstring, CallParameters;
+} with { extension "internal" };
+
+
/* this component represents a single subscriber connection */
type component BSC_ConnHdlr extends RAN_ConnHdlr, MNCC_ConnHdlr, GSUP_ConnHdlr, MGCP_ConnHdlr, SMPP_ConnHdlr, CTRL_Adapter_CT, SGsAP_ConnHdlr {
var BSC_ConnHdlrPars g_pars;
timer g_Tguard := 60.0;
port TELNETasp_PT MSCVTY;
+ port BSC_ConnHdlr_Coord_PT COORD;
}
type record BSC_ConnHdlrNetworkPars {
+ /* Bitmask of expected A5 levels; in Ciphering, will expect use of the highest A5 remaining after masking this
+ * with A5 supported by the MS */
OCT1 kc_support,
+ /* osmo-msc VTY cfg under 'network': If a test wants to temporarily modify auth and encr config, this is the
+ * original config to return to for this test (is *not* sent to vty before the test, but maybe it should).
+ * For example: { "authentication optional", "encryption a5 0 3" } */
+ rof_charstring net_config,
+ /* expect_attach_success == true: expect Location Updating / CM Service Request to succeed.
+ * expect_attach_success == false: expect the MSC to reject LU / CM Service. */
+ boolean expect_attach_success,
+ /* expect_tmsi == true: expect MSC to allocate a new TMSI.
+ * expect_tmsi == false: expect no TMSI to be assigned, operate with IMSI Mobile Identity. */
boolean expect_tmsi,
+ /* expect_auth == true overrides expect_auth_attempt == false */
+ boolean expect_auth_attempt,
+ /* hlr_has_auth_info has an effect only when (expect_auth_attempt or expect_auth) == true.
+ * hlr_has_auth_info == false means the HLR responds to Send Auth Info Request with a NACK. */
+ boolean hlr_has_auth_info,
boolean expect_auth,
boolean expect_ciph,
boolean expect_imei,
@@ -91,6 +118,9 @@ type record BSC_ConnHdlrPars {
BSSMAP_IE_ClassmarkInformationType2 cm2,
BSSMAP_IE_ClassmarkInformationType3 cm3 optional,
AuthVector vec optional,
+ /* BSC_ConnectionHandler generates an auth vector in as_GSUP_SAI(). For tests that want control over which
+ * vector is used, pass vec_keep := true to not regenerate a new auth vector in as_GSUP_SAI(). */
+ boolean vec_keep,
BSC_ConnHdlrNetworkPars net,
boolean send_early_cm,
charstring ipa_ctrl_ip,
@@ -104,11 +134,14 @@ type record BSC_ConnHdlrPars {
boolean use_umts_aka,
boolean ran_is_geran,
boolean use_osmux,
- boolean verify_cell_id
+ boolean use_ipv6,
+ boolean use_csd,
+ boolean verify_cell_id,
+ OCT3 common_id_last_eutran_plmn optional
};
/* get a one-octet bitmaks of supported algorithms based on Classmark information */
-function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2) return OCT1 {
+function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2, template (omit) BSSMAP_IE_ClassmarkInformationType3 cm3 := omit) return OCT1 {
var BIT8 res := '00000001'B; /* A5/0 always supported */
if (cm2.a5_1 == '0'B) {
@@ -120,7 +153,12 @@ function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2) return OCT1
if (cm2.classmarkInformationType2_oct5.a5_3 == '1'B) {
res := res or4b '00001000'B;
}
- /* TODO: CM3 for A5/4 and beyond */
+ if (not istemplatekind(cm3, "omit")) {
+ var BSSMAP_IE_ClassmarkInformationType3 v := valueof(cm3);
+ var BIT8 tmp := oct2bit(v.classmark3ValuePart[0]) and4b '00001111'B;
+ res := res or4b (tmp << 4);
+ }
+
return bit2oct(res);
}
@@ -152,6 +190,15 @@ function f_alg_from_mask(OCT1 mask_in) return integer {
return -1;
}
+/* return true for A5/x supported by OCT1 bitmask */
+function f_alg_supported_by_mask(OCT1 mask_in, integer whicha5) return boolean {
+ var BIT8 mask := oct2bit(mask_in);
+ if (mask and4b ('00000001'B << whicha5) != '00000000'B) {
+ return true;
+ }
+ return false;
+}
+
/* altstep for the global guard timer */
private altstep as_Tguard() runs on BSC_ConnHdlr {
[] g_Tguard.timeout {
@@ -176,7 +223,7 @@ function f_init_handler(BSC_ConnHdlrPars pars, float t_guard := 60.0) runs on BS
}
if (g_pars.ipa_ctrl_enable == true) {
- f_ipa_ctrl_start(g_pars.ipa_ctrl_ip, g_pars.ipa_ctrl_port);
+ f_ipa_ctrl_start_client(g_pars.ipa_ctrl_ip, g_pars.ipa_ctrl_port);
}
map(self:MSCVTY, system:MSCVTY);
@@ -232,6 +279,7 @@ const RanOps BSC_RanOps := {
protocol := RAN_PROTOCOL_BSSAP,
transport := BSSAP_TRANSPORT_AoIP,
use_osmux := false,
+ bssap_reset_retries := 1,
sccp_addr_local := omit,
sccp_addr_peer := omit
}
@@ -330,7 +378,10 @@ type enumerated EstablishType {
EST_TYPE_EMERG_CALL,
EST_TYPE_PAG_RESP,
EST_TYPE_MO_SMS,
- EST_TYPE_SS_ACT
+ EST_TYPE_SS_ACT,
+ EST_TYPE_MO_CSD,
+ EST_TYPE_VGCS,
+ EST_TYPE_VBS
};
/* helper function to fully establish a dedicated channel */
@@ -350,6 +401,9 @@ runs on BSC_ConnHdlr {
case (EST_TYPE_MO_CALL) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
}
+ case (EST_TYPE_MO_CSD) {
+ l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
+ }
case (EST_TYPE_EMERG_CALL) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
}
@@ -362,6 +416,12 @@ runs on BSC_ConnHdlr {
case (EST_TYPE_SS_ACT) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, mi));
}
+ case (EST_TYPE_VGCS) {
+ l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VGCS, mi));
+ }
+ case (EST_TYPE_VBS) {
+ l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_VBS, mi));
+ }
}
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
@@ -375,7 +435,11 @@ runs on BSC_ConnHdlr {
} else {
if (etype != EST_TYPE_PAG_RESP) {
/* explicit CM SERVICE ACCEPT */
- BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC));
+ if (g_pars.net.expect_attach_success) {
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC));
+ } else {
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ));
+ }
}
}
}
@@ -407,30 +471,43 @@ private function f_build_lu(MobileIdentityLV mi) runs on BSC_ConnHdlr return PDU
altstep as_GSUP_SAI() runs on BSC_ConnHdlr {
var GSUP_IE auth_tuple;
[] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)) {
- if (g_pars.use_umts_aka) {
- g_pars.vec := f_gen_auth_vec_3g();
- auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
- g_pars.vec.sres,
- g_pars.vec.kc,
- g_pars.vec.ik,
- g_pars.vec.ck,
- g_pars.vec.autn,
- g_pars.vec.res));
- GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+ if (g_pars.net.hlr_has_auth_info) {
+ if (g_pars.use_umts_aka) {
+ if (not g_pars.vec_keep) {
+ g_pars.vec := f_gen_auth_vec_3g();
+ }
+ auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
+ g_pars.vec.sres,
+ g_pars.vec.kc,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.res));
+ GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+ } else {
+ if (not g_pars.vec_keep) {
+ g_pars.vec := f_gen_auth_vec_2g();
+ }
+ auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
+ g_pars.vec.sres,
+ g_pars.vec.kc));
+ GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+ }
} else {
- g_pars.vec := f_gen_auth_vec_2g();
- auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
- g_pars.vec.sres,
- g_pars.vec.kc));
- GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+ log("XXX ts_GSUP_SAI_ERR");
+ /* HLR knows the IMSI but has no authentication info; osmo-hlr responds with GMM_CAUSE_IMSI_UNKNOWN=2 in
+ * this case, for SAI this merely means there is no auth entry for this IMSI. */
+ GSUP.send(ts_GSUP_SAI_ERR(g_pars.imsi, 2));
}
}
}
function f_mm_auth() runs on BSC_ConnHdlr
{
- if (g_pars.net.expect_auth) {
+ if (g_pars.net.expect_auth or g_pars.net.expect_auth_attempt) {
as_GSUP_SAI();
+ }
+ if (g_pars.net.expect_auth) {
if (g_pars.use_umts_aka) {
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn)));
var OCT4 res := substr(g_pars.vec.res, 0, 4);
@@ -519,57 +596,145 @@ function f_mm_imei_early() runs on BSC_ConnHdlr
}
}
-function f_mm_common() runs on BSC_ConnHdlr
+function f_expect_common_id() runs on BSC_ConnHdlr
{
- f_mm_auth();
if (g_pars.ran_is_geran) {
- if (g_pars.net.expect_ciph) {
- var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
- var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
- alt {
- [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
- var OCT1 a5_chosen := f_best_alg_from_mask(a5_intersect);
- var integer a5_nr := f_alg_from_mask(a5_chosen);
- BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(a5_nr+1, 1)));
- }
- [] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
- setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
- mtc.stop;
- }
- }
- /* FIXME: Send the best available algorithm */
+ BSSAP.receive(tr_BSSMAP_CommonId(g_pars.imsi,
+ f_tr_BSSMAP_LastUsedEUTRANPLMNId(g_pars.common_id_last_eutran_plmn)));
+ } else {
+ BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)));
+ }
+}
+
+/* For UMTS AKA on GERAN, calculate the specific kc from the UMTS AKA ck and ik vectors. */
+function f_auth3g_kc(AuthVector vec) return OCT8 {
+ var integer i;
+ var octetstring res := vec.ck[0] xor4b vec.ck[0 + 8] xor4b vec.ik[0] xor4b vec.ik[0 + 8];
+ for (i := 1; i < 8; i := i + 1) {
+ var octetstring a := vec.ck[i] xor4b vec.ck[i + 8] xor4b vec.ik[i] xor4b vec.ik[i + 8];
+ res := res & a;
+ }
+
+ return res;
+}
+
+function f_get_expected_encryption(
+ out template BSSMAP_IE_EncryptionInformation encryptionInformation,
+ out template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm,
+ out template BSSMAP_IE_KC128 kC128,
+ out OCT1 a5_perm_alg) runs on BSC_ConnHdlr
+{
+ var OCT1 a5_ms := f_alg_mask_from_cm(g_pars.cm2, g_pars.cm3);
+ a5_perm_alg := g_pars.net.kc_support and4b a5_ms;
+
+ if (not g_pars.net.expect_ciph) {
+ encryptionInformation := *;
+ chosenEncryptionAlgorithm := *;
+ kC128 := *;
+ return;
+ }
+
+ var OCT8 kc;
+ if (g_pars.use_umts_aka) {
+ kc := f_auth3g_kc(g_pars.vec);
+ } else {
+ kc := g_pars.vec.kc;
+ }
+ encryptionInformation := tr_BSSMAP_IE_EncrInfo(kc, a5_perm_alg);
+
+ var OCT1 chosen_alg := int2oct(f_alg_from_mask(f_best_alg_from_mask(a5_perm_alg)) + 1, 1);
+ chosenEncryptionAlgorithm := tr_BSSMAP_IE_ChosenEncryptionAlgorithm(chosen_alg);
+
+ if (g_pars.use_umts_aka and f_alg_supported_by_mask(a5_perm_alg, 4)) {
+ /* A5/4 is permitted, expecting kc128 to be present */
+ var OCT32 full_sha256 := f_calculate_HMAC_SHA256(g_pars.vec.ck & g_pars.vec.ik, '32'O, 32);
+ var OCT16 expect_kc128 := substr(full_sha256, 0, 16);
+ kC128 := tr_BSSMAP_IE_Kc128(expect_kc128);
+ } else {
+ kC128 := omit
+ }
+}
+
+
+private function f_mm_ciph_geran() runs on BSC_ConnHdlr
+{
+ var template BSSMAP_IE_EncryptionInformation encryptionInformation;
+ var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
+ var template BSSMAP_IE_KC128 kC128;
+ var OCT1 a5_perm_alg;
+ var PDU_BSSAP pdu;
+
+ if (not g_pars.net.expect_ciph) {
+ /* There is nothing to do */
+ return;
+ }
+
+ f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
+ alt {
+ [] BSSAP.receive(tr_BSSMAP_CipherModeCmd2(encryptionInformation, kC128)) -> value pdu {
+ var OCT1 a5_chosen := f_best_alg_from_mask(a5_perm_alg);
+ var integer a5_nr := f_alg_from_mask(a5_chosen);
+ BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(a5_nr+1, 1)));
+ }
+ [] BSSAP.receive(tr_BSSMAP_CipherModeCmd2) -> value pdu {
+ log("Error: Ciphering Mode Command with unexpected content. Expected: ",
+ tr_BSSMAP_CipherModeCmd2(encryptionInformation, kC128), " got: ", pdu);
+ setverdict(fail, "Ciphering Mode Command with unexpected content.");
+ mtc.stop;
}
- } else { /* UTRAN */
- alt {
- [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(uia_algs := ?,
- uia_key := oct2bit(g_pars.vec.ik),
- key_sts := ?,
- uea_algs := ?,
- uea_key := oct2bit(g_pars.vec.ck))) {
- var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1*/
- var EncryptionAlgorithm uea_chosen := 1; /*standard_UMTS_encryption_algorith_UEA1*/
- BSSAP.send(ts_RANAP_SecurityModeCompleteEnc(uia_chosen, uea_chosen));
- BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)));
- }
- [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(?,?,?,?,?)) {
- setverdict(fail, "Invalid SecurityModeCommand (ciphering case)");
- mtc.stop;
- }
- [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?,
- uia_key := oct2bit(g_pars.vec.ik),
- key_sts := ?)) {
- var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1;*/
- BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
- BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)));
- }
- [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(?,?,?)) {
- setverdict(fail, "Invalid SecurityModeCommand (non-ciphering case)");
- mtc.stop;
- }
+ [] BSSAP.receive(tr_BSSMAP_ClassmarkRequest) {
+ BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3))
+ repeat;
+ }
+ }
+ /* FIXME: Send the best available algorithm */
+}
+
+private function f_mm_ciph_utran() runs on BSC_ConnHdlr
+{
+ alt {
+ [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(uia_algs := ?,
+ uia_key := oct2bit(g_pars.vec.ik),
+ key_sts := ?,
+ uea_algs := ?,
+ uea_key := oct2bit(g_pars.vec.ck))) {
+ var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1*/
+ var EncryptionAlgorithm uea_chosen := 1; /*standard_UMTS_encryption_algorith_UEA1*/
+ BSSAP.send(ts_RANAP_SecurityModeCompleteEnc(uia_chosen, uea_chosen));
+ }
+ [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(?,?,?,?,?)) {
+ setverdict(fail, "Invalid SecurityModeCommand (ciphering case)");
+ mtc.stop;
+ }
+ [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?,
+ uia_key := oct2bit(g_pars.vec.ik),
+ key_sts := ?)) {
+ var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1;*/
+ BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
+ }
+ [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(?,?,?)) {
+ setverdict(fail, "Invalid SecurityModeCommand (non-ciphering case)");
+ mtc.stop;
}
}
}
+function f_mm_common() runs on BSC_ConnHdlr
+{
+ f_mm_auth();
+
+ if (g_pars.ran_is_geran) {
+ f_mm_ciph_geran();
+ } else {
+ f_mm_ciph_utran();
+ }
+
+ if (not g_pars.net.expect_attach_success) {
+ return;
+ }
+ f_expect_common_id();
+}
+
function f_expect_mm_info() runs on BSC_ConnHdlr {
if (g_pars.mm_info == true) {
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_Info));
@@ -662,13 +827,21 @@ function f_verify_vty_lac_ci(boolean verify_vlr := true) runs on BSC_ConnHdlr {
}
if (not verify_vlr and not connection_present) {
- setverdict(fail, "f_verify_vty_lac_ci(verify_vlr := false) called, which requires an active connection, but there is no 'Connection:' part to verify in ", result);
+ /* If the Compl L3 was done by TMSI, the VLR has no IMSI until the ID Request / Response for IMSI has
+ * been answered. So if verify_vlr == false, a "missing" connection is one of the expected scenarios. */
+ setverdict(pass);
}
}
-function f_perform_lu()
+function f_perform_lu(template (omit) MobileIdentityLV use_mi := omit)
runs on BSC_ConnHdlr {
- var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
+ var MobileIdentityLV mi;
+ if (istemplatekind(use_mi, "omit")) {
+ mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ } else {
+ mi := valueof(use_mi);
+ }
+ var PDU_ML3_MS_NW l3_lu := f_build_lu(mi);
var PDU_DTAP_MT dtap_mt;
/* tell GSUP dispatcher to send this IMSI to us */
@@ -692,15 +865,18 @@ runs on BSC_ConnHdlr {
f_mm_common();
f_msc_lu_hlr();
f_mm_imei();
- f_accept_reject_lu();
+ as_accept_reject_lu(g_pars.net.expect_attach_success);
/* FIXME: there could be pending SMS or other common procedures by the MSC, let's ignore them */
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id := g_pars.net.expect_attach_success);
setverdict(pass);
}
function f_msc_lu_hlr() runs on BSC_ConnHdlr
{
+ if (not g_pars.net.expect_attach_success) {
+ return;
+ }
/* Expect MSC to perform LU with HLR */
GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
@@ -708,11 +884,10 @@ function f_msc_lu_hlr() runs on BSC_ConnHdlr
GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
}
-function f_accept_reject_lu() runs on BSC_ConnHdlr {
+altstep as_accept_reject_lu(boolean expect_accept := true) runs on BSC_ConnHdlr {
var PDU_DTAP_MT dtap_mt;
- alt {
- [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {
+ [expect_accept] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {
var PDU_ML3_LocationUpdateAccept lu_acc := dtap_mt.dtap.msgs.mm.locationUpdateAccept;
if (g_pars.net.expect_tmsi) {
if (not ispresent(lu_acc.mobileIdentityTLV) or
@@ -730,23 +905,30 @@ function f_accept_reject_lu() runs on BSC_ConnHdlr {
mtc.stop;
}
}
- }
- [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
+
+ /* Wait for MM-Information (if enabled) */
+ f_expect_mm_info();
+ setverdict(pass);
+ }
+ [expect_accept] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
setverdict(fail, "Expected LU ACK, but received LU REJ");
mtc.stop;
- }
}
- /* Wait for MM-Information (if enabled) */
- f_expect_mm_info();
- setverdict(pass);
+ [not expect_accept] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
+ setverdict(pass);
+ }
+ [not expect_accept] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {
+ setverdict(fail, "Expected LU REJ, but received LU ACK");
+ mtc.stop;
+ }
}
-function f_expect_lu_reject(template OCT1 cause := ?) runs on BSC_ConnHdlr {
+function f_expect_lu_reject(template OCT1 cause := ?, float Tval := 5.0) runs on BSC_ConnHdlr {
var PDU_DTAP_MT dtap_mt;
- timer T := 5.0;
+ timer T;
- T.start;
+ T.start(Tval);
alt {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(cause))) {
setverdict(pass);
@@ -792,10 +974,13 @@ type record CallParameters {
important to set the TI flag properly */
BearerCapability_TLV bearer_cap, /* which bearer capabilities to claim */
boolean emergency, /* is this an emergency call? */
+ boolean csd, /* is this a circuit switched data call? */
/* MNCC related parameters */
uint32_t mncc_callref optional, /* call reference on the MNCC side */
MNCC_bearer_cap mncc_bearer_cap optional, /* MNCC-side bearer capabilities */
+ HostName mncc_rtp_ip optional, /* MNCC Side RTP IP */
+ PortNumber mncc_rtp_port optional, /* MNCC Side RTP port */
/* RTP related parameters */
HostName bss_rtp_ip optional, /* BSS Side RTP IP */
@@ -826,8 +1011,11 @@ template (value) CallParameters t_CallParams(hexstring called := '12345'H, integ
mo_call := false,
bearer_cap := valueof(ts_Bcap_voice),
emergency := false,
+ csd := false,
mncc_callref := omit,
mncc_bearer_cap := valueof(ts_MNCC_bcap_voice),
+ mncc_rtp_ip := "42.23.11.5",
+ mncc_rtp_port := 423,
bss_rtp_ip := "9.8.7.6",
bss_rtp_port := 9000,
mss_rtp_ip := omit,
@@ -841,7 +1029,7 @@ template (value) CallParameters t_CallParams(hexstring called := '12345'H, integ
},
mgw_conn_2 := {
resp := 1,
- mgw_rtp_ip := "1.1.1.1",
+ mgw_rtp_ip := "2.2.2.2",
mgw_rtp_port := 11000,
mgcp_connection_id := '22222'H
},
@@ -857,13 +1045,45 @@ template (value) CallParameters t_CallParams(hexstring called := '12345'H, integ
got_osmux_count := 0
};
+template CallParameters tr_CallParams := {
+ called_party := ?,
+ transaction_id := ?,
+ mo_call := ?,
+ bearer_cap := ?,
+ emergency := ?,
+ csd := ?,
+ mncc_callref := *,
+ mncc_bearer_cap := ?,
+ mncc_rtp_ip := ?,
+ mncc_rtp_port := ?,
+ bss_rtp_ip := ?,
+ bss_rtp_port := ?,
+ mss_rtp_ip := *,
+ mss_rtp_port := *,
+ got_crcx_count := ?,
+ mgw_conn_1 := ?,
+ mgw_conn_2 := ?,
+ rtp_payload_type := ?,
+ rtp_sdp_format := ?,
+ mgw_drop_dlcx := ?,
+ stop_after_cc_setup := ?,
+ ran_clear_when_alerting := ?,
+ expect_release := ?,
+ mgcp_call_id := *,
+ mgcp_ep := ?,
+ use_osmux := ?,
+ got_osmux_count := ?
+};
+
/* Allocate a call reference and send SETUP via MNCC to MSC */
-function f_mt_call_initate(inout CallParameters cpars)
+function f_mt_call_initiate(inout CallParameters cpars)
runs on BSC_ConnHdlr {
cpars.mo_call := false;
cpars.mncc_callref := f_rnd_int(2147483648);
+
MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
- hex2str(cpars.called_party), hex2str(g_pars.imsi)));
+ hex2str(cpars.called_party), hex2str(g_pars.imsi),
+ cpars.mncc_bearer_cap));
}
private template (value) SDP_Message ts_SDP_CRCX_CN(CallParameters cpars) :=
@@ -915,8 +1135,10 @@ runs on BSC_ConnHdlr {
if (g_pars.ran_is_geran) {
- var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
- tr_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_conn_1.mgw_rtp_ip), ?);
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass1 :=
+ f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?);
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass2 :=
+ f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_2.mgw_rtp_ip, ?);
interleave {
/* Second MGCP CRCX (this time for MSS/CN side) */
@@ -933,14 +1155,26 @@ runs on BSC_ConnHdlr {
}
/* expect the MSC to trigger a BSSMAP ASSIGNMENT */
- [] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass)) -> value bssap {
+ [] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, (tla_ass1, tla_ass2))) -> value bssap {
var template BSSMAP_IE_AoIP_TransportLayerAddress tla;
var BSSMAP_IE_SpeechCodec codec;
var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
log("f_mt_call_complete 6");
- tla := valueof(ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.bss_rtp_ip), cpars.bss_rtp_port));
- codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
+ if (cpars.csd and not match(bssap.pdu.bssmap.assignmentRequest.codecList.codecElements,
+ {ts_CodecCSData})) {
+ setverdict(fail, "MSC sent Assignment Request with unexpected codec list for CSD ",
+ bssap.pdu.bssmap.assignmentRequest.codecList);
+ mtc.stop;
+ }
+
+ tla := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port);
+
+ if (cpars.csd) {
+ codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecCSData}));
+ } else {
+ codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
+ }
if (cpars.use_osmux) {
if (not ispresent(bssap.pdu.bssmap.assignmentRequest.osmuxCID)) {
@@ -963,18 +1197,25 @@ runs on BSC_ConnHdlr {
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7");
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mt_call_complete 8");
- var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
+ var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
- cpars.mgw_conn_2.mgw_rtp_port,
+ cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
@@ -987,21 +1228,35 @@ runs on BSC_ConnHdlr {
}
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
- mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp);
+ mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
/* MDCX setting up the CN side remote RTP address received from MNCC CONNECT */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
+ var SDP_Message sdp;
log("f_mt_call_complete 9");
- var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
- hex2str(cpars.mgcp_call_id), "42",
- cpars.mgw_conn_2.mgw_rtp_port,
- { int2str(cpars.rtp_payload_type) },
- { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
- cpars.rtp_sdp_format)),
- valueof(ts_SDP_ptime(20)) }));
+
+ if (isvalue(mgcp_cmd.sdp)) {
+ sdp := mgcp_cmd.sdp;
+ if (sdp.media_list[0].media_field.ports.port_number != cpars.mncc_rtp_port) {
+ setverdict(fail, "Wrong MDCX Connection port received, expected ", cpars.mncc_rtp_port, " and received ", sdp.media_list[0].media_field.ports.port_number)
+ mtc.stop;
+ }
+ if (sdp.connection.conn_addr.addr != cpars.mncc_rtp_ip) {
+ setverdict(fail, "Wrong MDCX Connection address received, expected ", cpars.mncc_rtp_ip, " and received ", sdp.connection.conn_addr.addr)
+ mtc.stop;
+ }
+ }
+
+ sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
+ hex2str(cpars.mgcp_call_id), "42",
+ cpars.mgw_conn_2.mgw_rtp_port,
+ { int2str(cpars.rtp_payload_type) },
+ { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
+ cpars.rtp_sdp_format)),
+ valueof(ts_SDP_ptime(20)) }));
MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
}
@@ -1048,18 +1303,25 @@ runs on BSC_ConnHdlr {
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7.iu");
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mt_call_complete 8.iu");
- var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
+ var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
- cpars.mgw_conn_2.mgw_rtp_port,
+ cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
@@ -1072,7 +1334,7 @@ runs on BSC_ConnHdlr {
}
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
- mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp);
+ mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
@@ -1103,20 +1365,58 @@ runs on BSC_ConnHdlr {
log("f_mt_call_complete DONE");
}
-function f_expect_paging(boolean by_tmsi := true)
+/* expect BSSMAP/RANAP Paging for any IMSI and/or TMSI */
+altstep as_paging_any()
runs on BSC_ConnHdlr {
- if (g_pars.ran_is_geran) {
- BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
- } else {
- BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi)));
+ [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(?, *));
+ [not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(?, ?));
+}
+
+/* expect BSSMAP/RANAP Paging for registered IMSI and the given TMSI */
+altstep as_paging_tmsi(template OCT4 tmsi := *)
+runs on BSC_ConnHdlr {
+ [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi, tmsi));
+ [not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi)));
+}
+
+/* convenience wrapper for as_paging_tmsi() using g_pars.tmsi */
+altstep as_paging()
+runs on BSC_ConnHdlr {
+ [] as_paging_tmsi(g_pars.tmsi);
+}
+
+/* expect BSSMAP/RANAP Paging for registered IMSI and the given TMSI
+ * fail on BSSMAP/RANAP Paging for non-matching IMSI/TMSI
+ * wait up to Tval seconds before declaring timeout */
+function f_expect_paging_tmsi(template OCT4 tmsi := *, float Tval := 4.0)
+runs on BSC_ConnHdlr {
+ timer T;
+
+ T.start(Tval);
+ alt {
+ [] as_paging_tmsi(tmsi) { setverdict(pass); }
+ [] as_paging_any() {
+ setverdict(fail, "Paging message doesn't match expectations");
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for paging");
+ mtc.stop;
+ }
}
}
+/* convenience wrapper for f_expect_paging_tmsi() using g_pars.tmsi */
+function f_expect_paging(float Tval := 4.0)
+runs on BSC_ConnHdlr {
+ f_expect_paging_tmsi(g_pars.tmsi, Tval);
+}
+
function f_mt_call_establish(inout CallParameters cpars)
runs on BSC_ConnHdlr {
/* Initiate the call via MNCC */
- f_mt_call_initate(cpars);
+ f_mt_call_initiate(cpars);
/* BSC <- MSC: Expect paging. FIXME: By TMSI or not? */
f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
@@ -1128,6 +1428,33 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
+function f_call_keep_open(inout CallParameters cpars, float open_time := 5.0)
+runs on BSC_ConnHdlr {
+ log("Hold the call for some time");
+
+ timer T := open_time;
+ T.start;
+ alt {
+ [] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref));
+ [] MNCC.receive(tr_MNCC_REL_ind(cpars.mncc_callref));
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
+ [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
+ [] BSSAP.receive(tr_BSSMAP_ClearCommand);
+ [] BSSAP.receive(tr_BSSMAP_ClearCommandCSFB);
+ [] BSSAP.receive(tr_RANAP_IuReleaseCommand(?));
+
+ [] T.timeout {
+ log("Call stayed open for ", open_time, " seconds, all is well.")
+ setverdict(pass);
+ return;
+ }
+ }
+
+ setverdict(fail, "An unexpected release event disconnected the active call prematurely");
+ mtc.stop;
+}
+
/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
* Return true when an OK reply was sent, false otherwise.
* Count occurence of Osmux, include Osmux parameters in the reply if necessary. */
@@ -1238,7 +1565,7 @@ altstep as_optional_mgcp_crcx(CallParameters cpars) runs on BSC_ConnHdlr {
}
}
-private altstep as_optional_mgcp_mdcx(HostName mgw_rtp_ip, PortNumber mgw_rtp_port) runs on BSC_ConnHdlr {
+altstep as_optional_mgcp_mdcx(HostName mgw_rtp_ip, PortNumber mgw_rtp_port) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("as_optional_mgcp_mdcx: rx MDCX");
@@ -1261,7 +1588,7 @@ private altstep as_optional_mgcp_mdcx(HostName mgw_rtp_ip, PortNumber mgw_rtp_po
}
}
-private altstep as_optional_mgcp_dlcx(CallParameters cpars) runs on BSC_ConnHdlr {
+altstep as_optional_mgcp_dlcx(CallParameters cpars) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
var boolean respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx));
[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
@@ -1290,6 +1617,8 @@ runs on BSC_ConnHdlr {
if (cpars.emergency) {
f_establish_fully(EST_TYPE_EMERG_CALL);
+ } else if (cpars.csd) {
+ f_establish_fully(EST_TYPE_MO_CSD);
} else {
f_establish_fully(EST_TYPE_MO_CALL);
}
@@ -1301,15 +1630,18 @@ runs on BSC_ConnHdlr {
if (cpars.emergency) {
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_EMERG_SETUP(cpars.transaction_id)));
} else {
- BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party,
+ cpars.bearer_cap)));
}
if (cpars.stop_after_cc_setup) {
return;
}
- var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
- tr_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.mgw_conn_1.mgw_rtp_ip), ?);
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass1 :=
+ f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?);
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass2 :=
+ f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_2.mgw_rtp_ip, ?);
var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
var boolean got_mncc_setup_compl_ind := false;
@@ -1355,15 +1687,33 @@ runs on BSC_ConnHdlr {
var BSSMAP_IE_SpeechCodec codec;
var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
- if (not match(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer, tla_ass)) {
- log("Expected:", tla_ass);
+ if (not ispresent(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer)) {
+ setverdict(fail, "MSC sent Assignment Request without AoIP Transport Layer IE");
+ mtc.stop;
+ }
+ if (not match(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer, tla_ass1)
+ and not match(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer, tla_ass2)) {
+ log("Expected one of: 1:", tla_ass1, " 2:", tla_ass2);
log("Got:", bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer);
setverdict(fail, "MSC sent Assignment Request with unexpected AoIP Transport Layer IE");
mtc.stop;
}
- tla := valueof(ts_BSSMAP_IE_AoIP_TLA4(f_inet_addr(cpars.bss_rtp_ip), cpars.bss_rtp_port));
- codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
+ if (cpars.csd and not match(bssap.pdu.bssmap.assignmentRequest.codecList.codecElements,
+ {ts_CodecCSData})) {
+ setverdict(fail, "MSC sent Assignment Request with unexpected codec list for CSD ",
+ bssap.pdu.bssmap.assignmentRequest.codecList);
+ mtc.stop;
+ }
+
+ tla := valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
+
+ if (cpars.csd) {
+ codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecCSData}));
+ } else {
+ codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
+ }
+
if (cpars.use_osmux) {
if (not ispresent(bssap.pdu.bssmap.assignmentRequest.osmuxCID)) {
setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE");
@@ -1407,9 +1757,9 @@ runs on BSC_ConnHdlr {
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mo_call_establish 5: rx MDCX for the RAN side");
- var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
+ var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
- cpars.mgw_conn_2.mgw_rtp_port,
+ cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
@@ -1423,7 +1773,7 @@ runs on BSC_ConnHdlr {
}
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
- mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp);
+ mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
@@ -1442,9 +1792,16 @@ runs on BSC_ConnHdlr {
cpars.mncc_callref := mncc.u.signal.callref;
/* Call Proceeding */
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
MNCC.send(ts_MNCC_SETUP_rsp(cpars.mncc_callref));
}
@@ -1526,8 +1883,10 @@ runs on BSC_ConnHdlr {
/* A-side (PLMN) Release of call */
MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(42))));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
- log("f_call_hangup 4: rx DTAP CC RELEASE");
+ log("f_call_hangup 2.a: rx DTAP CC RELEASE");
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
+ log("f_call_hangup 3.a: rx MNCC REL cnf");
+ MNCC.receive(tr_MNCC_REL_cnf(cpars.mncc_callref, cause := *));
}
respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx));
@@ -1561,27 +1920,28 @@ runs on BSC_ConnHdlr {
deactivate(dlcx);
}
-function f_mt_call(inout CallParameters cpars)
+function f_mt_call(inout CallParameters cpars, float open_time := 5.0)
runs on BSC_ConnHdlr {
f_mt_call_establish(cpars);
- log("Hold the call for some time");
- f_sleep(3.0);
+ f_call_keep_open(cpars, open_time);
log("Hangup");
f_call_hangup(cpars, true);
+ /* Unregister the IMSI that was registered in f_mt_call_establish */
+ f_ran_unregister_imsi(g_pars.imsi);
+
setverdict(pass);
}
-function f_mo_call(inout CallParameters cpars)
+function f_mo_call(inout CallParameters cpars, float open_time := 5.0)
runs on BSC_ConnHdlr {
f_mo_call_establish(cpars);
- log("Hold the call for some time");
- f_sleep(3.0);
+ f_call_keep_open(cpars, open_time);
log("Hangup");
f_call_hangup(cpars, false);
@@ -1652,8 +2012,8 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
-/* expect a clear command */
-altstep as_clear_cmd_compl_disc(float t := 5.0) runs on BSC_ConnHdlr {
+/* expect a clear command (for GERAN only!) */
+altstep as_clear_cmd_compl_disc() runs on BSC_ConnHdlr {
var PDU_BSSAP bssap;
[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
BSSAP.send(ts_BSSMAP_ClearComplete);
@@ -1673,28 +2033,33 @@ altstep as_clear_cmd_compl_disc(float t := 5.0) runs on BSC_ConnHdlr {
}
}
+/* expect a BSSMAP Clear Command (for GERAN) or an Iu-ReleaseCommand (for UTRAN) */
+altstep as_expect_clear() runs on BSC_ConnHdlr {
+ [g_pars.ran_is_geran] as_clear_cmd_compl_disc();
+ [not g_pars.ran_is_geran] as_iu_release_compl_disc();
+}
+
function f_expect_clear(float t := 5.0, boolean verify_vlr_cell_id := true) runs on BSC_ConnHdlr {
timer T := t;
T.start;
alt {
- [g_pars.ran_is_geran] as_clear_cmd_compl_disc(t) { }
- [not g_pars.ran_is_geran] as_iu_release_compl_disc(t) { }
+ [] as_expect_clear() {
+ if (verify_vlr_cell_id) {
+ /* Now the conn is gone, but the VLR reflects the cell ID */
+ f_verify_vty_lac_ci();
+ }
+ }
[] T.timeout {
setverdict(fail, "Timeout waiting for ClearCommand/Release");
mtc.stop;
}
}
-
- if (verify_vlr_cell_id) {
- /* Now the conn is gone, but the VLR reflects the cell ID */
- f_verify_vty_lac_ci();
- }
}
-function f_create_bssmap_exp_handoverRequest(integer targetPointCode) runs on BSC_ConnHdlr {
- BSSAP_PROC.call(RAN_register_handoverRequest:{targetPointCode, self}) {
- [] BSSAP_PROC.getreply(RAN_register_handoverRequest:{?, ?}) {};
+function f_create_bssmap_exp_n_connect(integer targetPointCode) runs on BSC_ConnHdlr {
+ BSSAP_PROC.call(RAN_register_n_connect:{targetPointCode, self}) {
+ [] BSSAP_PROC.getreply(RAN_register_n_connect:{?, ?}) {};
}
}
diff --git a/msc/MSC_Tests.cfg b/msc/MSC_Tests.cfg
index b852bac9..1676e707 100644
--- a/msc/MSC_Tests.cfg
+++ b/msc/MSC_Tests.cfg
@@ -16,51 +16,5 @@
[EXECUTE]
MSC_Tests.control
-#MSC_Tests.TC_cr_before_reset
-#MSC_Tests.TC_lu_imsi_noauth_tmsi
-#MSC_Tests.TC_lu_imsi_noauth_notmsi
-#MSC_Tests.TC_lu_imsi_reject
-#MSC_Tests.TC_lu_imsi_timeout_gsup
-#MSC_Tests.TC_lu_imsi_auth_tmsi
-#MSC_Tests.TC_cmserv_imsi_unknown
-#MSC_Tests.TC_lu_and_mo_call
-#MSC_Tests.TC_lu_auth_sai_timeout
-#MSC_Tests.TC_lu_auth_sai_err
-#MSC_Tests.TC_lu_clear_request
-#MSC_Tests.TC_lu_disconnect
-#MSC_Tests.TC_lu_by_imei
-#MSC_Tests.TC_lu_by_tmsi_noauth_unknown
-#MSC_Tests.TC_imsi_detach_by_imsi
-#MSC_Tests.TC_imsi_detach_by_tmsi
-#MSC_Tests.TC_imsi_detach_by_imei
-#MSC_Tests.TC_emerg_call_imei_reject
-#MSC_Tests.TC_emerg_call_imsi
-#MSC_Tests.TC_cm_serv_req_vgcs_reject
-#MSC_Tests.TC_cm_serv_req_vbs_reject
-#MSC_Tests.TC_cm_serv_req_lcs_reject
-#MSC_Tests.TC_cm_reest_req_reject
-#MSC_Tests.TC_lu_auth_2G_fail
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_13_13
-#MSC_Tests.TC_cl3_no_payload
-#MSC_Tests.TC_cl3_rnd_payload
-#MSC_Tests.TC_establish_and_nothing
-#MSC_Tests.TC_mo_setup_and_nothing
-#MSC_Tests.TC_mo_crcx_ran_timeout
-#MSC_Tests.TC_mo_crcx_ran_reject
-#MSC_Tests.TC_mt_crcx_ran_reject
-#MSC_Tests.TC_mt_t310
-#MSC_Tests.TC_gsup_cancel
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_1_13
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_3_13
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_3_1
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_3_1_no_cm
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_13_2
-#MSC_Tests.TC_lu_imsi_auth_tmsi_encr_013_2
-#MSC_Tests.TC_mo_release_timeout
-#MSC_Tests.TC_lu_and_mt_call_no_dlcx_resp
-#MSC_Tests.TC_reset_two
-#MSC_Tests.TC_lu_and_mt_call
-#MSC_Tests.TC_cipher_complete_with_invalid_cipher
-#MSC_Tests.TC_cipher_complete_1_without_cipher
-#MSC_Tests.TC_cipher_complete_3_without_cipher
-#MSC_Tests.TC_cipher_complete_13_without_cipher
+MSC_Tests_Iu.control
+MSC_Tests_ASCI.control
diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn
index d59d1651..09004e83 100644
--- a/msc/MSC_Tests.ttcn
+++ b/msc/MSC_Tests.ttcn
@@ -13,9 +13,11 @@ module MSC_Tests {
*/
friend module MSC_Tests_Iu;
+friend module MSC_Tests_ASCI;
import from General_Types all;
import from Osmocom_Types all;
+import from GSM_Types all;
import from M3UA_Types all;
import from M3UA_Emulation all;
@@ -44,9 +46,11 @@ import from MGCP_Emulation all;
import from MGCP_Types all;
import from MGCP_Templates all;
import from SDP_Types all;
+import from SDP_Templates all;
-import from GSUP_Emulation all;
import from GSUP_Types all;
+import from GSUP_Templates all;
+import from GSUP_Emulation all;
import from IPA_Emulation all;
import from BSSAP_Types all;
@@ -139,11 +143,7 @@ modulepar {
charstring mp_smpp_password := "osmocom1";
charstring mp_mme_name := "mmec01.mmegi0001.mme.epc.mnc070.mcc901.3gppnetwork.org";
charstring mp_vlr_name := "vlr.example.net";
-
- /* Whether to enable osmux tests. Can be dropped completely and enable
- unconditionally once new version of osmo-msc is released (current
- version: 1.3.1) */
- boolean mp_enable_osmux_test := true;
+ integer mp_bssap_reset_retries := 1;
RAN_Configurations mp_bssap_cfg := {
{
@@ -167,8 +167,6 @@ modulepar {
rctx := 1
}
};
-
- boolean mp_enable_cell_id_test := true;
}
/* altstep for the global guard timer (only used when BSSAP_DIRECT
@@ -182,14 +180,15 @@ private altstep as_Tguard_direct() runs on MTC_CT {
private altstep as_optional_cc_rel(CallParameters cpars, boolean respond := false) runs on BSC_ConnHdlr {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
- if (respond) {
- var BIT1 tid_remote := '1'B;
- if (cpars.mo_call) {
- tid_remote := '0'B;
- }
- BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, tid_remote)));
+ if (respond) {
+ var BIT1 tid_remote := '1'B;
+ if (cpars.mo_call) {
+ tid_remote := '0'B;
}
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, tid_remote)));
}
+ repeat;
+ }
}
function f_init_smpp(charstring id) runs on MTC_CT {
@@ -210,7 +209,7 @@ function f_init_smpp(charstring id) runs on MTC_CT {
vc_SMPP := SMPP_Emulation_CT.create(id);
map(vc_SMPP:SMPP_PORT, system:SMPP_PORT);
- vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", -1));
+ vc_SMPP.start(SMPP_Emulation.main_client(pars, mp_msc_ip, mp_msc_smpp_port, "", 0));
}
@@ -310,10 +309,34 @@ function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := tr
testcase.stop("excess number of BSC instances requested");
}
+ f_ipa_ctrl_start_client(mp_msc_ip, mp_msc_ctrl_port);
+
+ map(self:MSCVTY, system:MSCVTY);
+ f_vty_set_prompts(MSCVTY);
+ f_vty_transceive(MSCVTY, "enable");
+
+ /* set some defaults */
+ f_vty_config(MSCVTY, "network", "authentication optional");
+ f_vty_config(MSCVTY, "msc", "assign-tmsi");
+ f_vty_config(MSCVTY, "msc", "check-imei-rqd 0");
+ f_vty_config(MSCVTY, "network", "encryption a5 0");
+ f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer ias " & int2str(g_msc_sccp_timer_ias));
+ f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer iar " & int2str(g_msc_sccp_timer_iar));
+ if (osmux) {
+ f_vty_config(MSCVTY, "msc", "osmux on");
+ } else {
+ f_vty_config(MSCVTY, "msc", "osmux off");
+ }
+
+ /* Configure the MGCP timeout so that a failure to set up all RTP streams triggers within the time that we keep
+ * an otherwise established call open. */
+ f_vty_config(MSCVTY, "msc", "timer mgw X2 3");
+
for (var integer i := 0; i < num_bsc; i := i + 1) {
if (isbound(mp_bssap_cfg[i])) {
var RanOps ranops := BSC_RanOps;
ranops.use_osmux := osmux;
+ ranops.bssap_reset_retries := mp_bssap_reset_retries;
f_ran_adapter_init(g_bssap[i], mp_bssap_cfg[i], "MSC_Test_" & int2str(i), ranops);
f_ran_adapter_start(g_bssap[i]);
} else {
@@ -321,7 +344,6 @@ function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := tr
}
}
- f_ipa_ctrl_start(mp_msc_ip, mp_msc_ctrl_port);
f_init_mncc("MSC_Test");
f_init_mgcp("MSC_Test");
@@ -334,24 +356,6 @@ function f_init(integer num_bsc := 1, boolean sgsap := false, boolean gsup := tr
f_init_sgsap("MSC_Test");
}
- map(self:MSCVTY, system:MSCVTY);
- f_vty_set_prompts(MSCVTY);
- f_vty_transceive(MSCVTY, "enable");
-
- /* set some defaults */
- f_vty_config(MSCVTY, "network", "authentication optional");
- f_vty_config(MSCVTY, "msc", "assign-tmsi");
- f_vty_config(MSCVTY, "msc", "check-imei-rqd 0");
- f_vty_config(MSCVTY, "network", "encryption a5 0");
- f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer ias " & int2str(g_msc_sccp_timer_ias));
- f_vty_config(MSCVTY, "cs7 instance 0", "sccp-timer iar " & int2str(g_msc_sccp_timer_iar));
- if (mp_enable_osmux_test) {
- if (osmux) {
- f_vty_config(MSCVTY, "msc", "osmux on");
- } else {
- f_vty_config(MSCVTY, "msc", "osmux off");
- }
- }
}
/* Initialize for a direct connection to BSSAP. This function is an alternative
@@ -375,7 +379,11 @@ function f_init_pars(integer imsi_suffix, boolean sgsap := false, boolean gsup :
runs on MTC_CT return BSC_ConnHdlrPars {
var BSC_ConnHdlrNetworkPars net_pars := {
kc_support := '0A'O, /* A5/1 and A5/3 enabled */
+ net_config := { "authentication optional", "encryption a5 0" },
+ expect_attach_success := true,
expect_tmsi := true,
+ expect_auth_attempt := false,
+ hlr_has_auth_info := true,
expect_auth := false,
expect_ciph := false,
expect_imei := false,
@@ -395,6 +403,7 @@ runs on MTC_CT return BSC_ConnHdlrPars {
cm2 := valueof(ts_CM2_default),
cm3 := omit,
vec := omit,
+ vec_keep := false,
net := net_pars,
send_early_cm := true,
ipa_ctrl_ip := mp_msc_ip,
@@ -408,7 +417,10 @@ runs on MTC_CT return BSC_ConnHdlrPars {
use_umts_aka := false,
ran_is_geran := ran_is_geran,
use_osmux := use_osmux,
- verify_cell_id := mp_enable_cell_id_test and verify_cell_id
+ use_ipv6 := false,
+ use_csd := false,
+ verify_cell_id := verify_cell_id,
+ common_id_last_eutran_plmn := omit
};
if (not ran_is_geran) {
pars.use_umts_aka := true;
@@ -417,14 +429,15 @@ runs on MTC_CT return BSC_ConnHdlrPars {
return pars;
}
-function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars, integer bssap_idx := 0) runs on MTC_CT return BSC_ConnHdlr {
+function f_start_handler_create(BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
var BSC_ConnHdlr vc_conn;
- var charstring id := testcasename() & int2str(bssap_idx);
+ var charstring id := testcasename() & int2str(pars.ran_idx);
vc_conn := BSC_ConnHdlr.create(id);
+
/* BSSMAP part / A interface */
- connect(vc_conn:BSSAP, g_bssap[pars.ran_idx + bssap_idx].vc_RAN:CLIENT);
- connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx + bssap_idx].vc_RAN:PROC);
+ connect(vc_conn:BSSAP, g_bssap[pars.ran_idx].vc_RAN:CLIENT);
+ connect(vc_conn:BSSAP_PROC, g_bssap[pars.ran_idx].vc_RAN:PROC);
/* MNCC part */
connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
@@ -444,10 +457,20 @@ function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars, integer bs
connect(vc_conn:SGsAP, vc_SGsAP:SGsAP_CLIENT);
connect(vc_conn:SGsAP_PROC, vc_SGsAP:SGsAP_PROC);
}
+ return vc_conn;
+}
+function f_start_handler_run(BSC_ConnHdlr vc_conn, void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT {
+ var charstring id := testcasename() & int2str(pars.ran_idx);
/* We cannot use vc_conn.start(f_init_handler(fn, id, pars)); as we cannot have
* a stand-alone 'derefers()' call, see https://www.eclipse.org/forums/index.php/t/1091364/ */
vc_conn.start(derefers(fn)(id, pars));
+}
+
+function f_start_handler_with_pars(void_fn fn, BSC_ConnHdlrPars pars) runs on MTC_CT return BSC_ConnHdlr {
+ var BSC_ConnHdlr vc_conn;
+ vc_conn := f_start_handler_create(pars);
+ f_start_handler_run(vc_conn, fn, pars);
return vc_conn;
}
@@ -658,7 +681,7 @@ runs on BSC_ConnHdlr {
mtc.stop;
}
[] T.timeout {
- setverdict(fail, "Timeout waiting for CM SERV REQ");
+ setverdict(fail, "Timeout waiting for CM SERV REJ");
mtc.stop;
}
}
@@ -673,6 +696,87 @@ testcase TC_cmserv_imsi_unknown() runs on MTC_CT {
}
+/* Send CM SERVICE REQ for TMSI that has never performed LU before */
+friend function f_tc_cmserv_tmsi_unknown(charstring id, BSC_ConnHdlrPars pars)
+runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('57111111'O));
+ var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
+
+ /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
+ f_cl3_or_initial_ue(l3_info);
+ f_mm_auth();
+
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ)) { }
+ [] BSSAP.receive {
+ setverdict(fail, "Received unexpected BSSAP");
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for CM SERV REJ");
+ mtc.stop;
+ }
+ }
+
+ f_expect_clear();
+}
+testcase TC_cmserv_tmsi_unknown() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_cmserv_tmsi_unknown), 57, verify_cell_id := false);
+ vc_conn.done;
+}
+
+/* Send Paging Response for IMSI that has never performed LU before */
+friend function f_tc_paging_response_imsi_unknown(charstring id, BSC_ConnHdlrPars pars)
+runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_PAG_RESP(mi));
+
+ /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
+ f_cl3_or_initial_ue(l3_info);
+
+ /* The Paging Response gets rejected by a direct Clear Command */
+ f_expect_clear();
+}
+testcase TC_paging_response_imsi_unknown() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_paging_response_imsi_unknown), 58, verify_cell_id := false);
+ vc_conn.done;
+}
+
+/* Send Paging Response for TMSI that has never performed LU before */
+friend function f_tc_paging_response_tmsi_unknown(charstring id, BSC_ConnHdlrPars pars)
+runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV('59111111'O));
+ var BSSMAP_IE_CellIdentifier cell_id := valueof(ts_CellId_CGI('262'H, '42'H, 23, 42));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_PAG_RESP(mi));
+
+ /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
+ f_cl3_or_initial_ue(l3_info);
+
+ /* The Paging Response gets rejected by a direct Clear Command */
+ f_expect_clear();
+}
+testcase TC_paging_response_tmsi_unknown() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_paging_response_tmsi_unknown), 59, verify_cell_id := false);
+ vc_conn.done;
+}
+
+
friend function f_tc_lu_and_mo_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
f_init_handler(pars);
var CallParameters cpars := valueof(t_CallParams);
@@ -686,6 +790,22 @@ testcase TC_lu_and_mo_call() runs on MTC_CT {
vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call), 7);
vc_conn.done;
}
+friend function f_tc_lu_and_mo_call_ipv6(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+ var CallParameters cpars := valueof(t_CallParams);
+ cpars.mgw_conn_1.mgw_rtp_ip := "::1";
+ cpars.mgw_conn_2.mgw_rtp_ip := "::2";
+ cpars.bss_rtp_ip := "::3";
+ f_perform_lu();
+ f_mo_call(cpars);
+}
+testcase TC_lu_and_mo_call_ipv6() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_tc_lu_and_mo_call_ipv6), 7);
+ vc_conn.done;
+}
/* Verify T(iar) triggers and releases the channel */
friend function f_lu_and_mo_call_sccp_tiar_timeout(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
@@ -702,12 +822,15 @@ friend function f_lu_and_mo_call_sccp_tiar_timeout(charstring id, BSC_ConnHdlrPa
T_wait_iar.stop
setverdict(pass);
}
- [] MGCP.receive(tr_DLCX(?)) { repeat; }
[] T_wait_iar.timeout {
setverdict(fail, "Timeout waiting for T(iar) triggered SCCP RSLD");
mtc.stop;
}
}
+ /* DLCX for both directions; if we don't do this, we might receive either of the two during
+ * shutdown causing race conditions */
+ MGCP.receive(tr_DLCX(?));
+ MGCP.receive(tr_DLCX(?));
setverdict(pass);
}
@@ -807,6 +930,7 @@ private function f_tc_lu_clear_request(charstring id, BSC_ConnHdlrPars pars) run
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
f_cl3_or_initial_ue(l3_lu);
+ f_expect_common_id();
/* Send Early Classmark, just for the fun of it */
BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
@@ -838,6 +962,66 @@ testcase TC_lu_clear_request() runs on MTC_CT {
vc_conn.done;
}
+/* Test reaction on Clear Request during a MO Call */
+friend function f_TC_mo_mt_call_clear_request(charstring id, BSC_ConnHdlrPars pars)
+runs on BSC_ConnHdlr {
+ var CallParameters cpars := valueof(t_CallParams);
+ var MNCC_PDU mncc_pdu;
+ timer T := 2.0;
+
+ f_init_handler(pars);
+
+ f_perform_lu();
+
+ /* HACK: reducing code duplication ('66'H - MO, '68'H - MT) */
+ if (pars.imsi == '262420002532766'H)
+ { f_mo_call_establish(cpars); }
+ else
+ { f_mt_call_establish(cpars); }
+
+ /* Hold the line for a while... */
+ f_sleep(2.0);
+
+ /* BSC sends BSSMAP Clear Request (e.g. due to RR failure) */
+ BSSAP.send(ts_BSSMAP_ClearRequest(1));
+
+ /* Expect (optional) CC RELEASE and Clear Command */
+ var default ccrel := activate(as_optional_cc_rel(cpars));
+ f_expect_clear();
+ deactivate(ccrel);
+
+ /* Expect RELease indication on the MNCC socket */
+ T.start;
+ alt {
+ [] MNCC.receive(tr_MNCC_REL_ind(cpars.mncc_callref)) -> value mncc_pdu {
+ log("Rx MNCC REL.ind, cause := ", mncc_pdu.u.signal.cause);
+ setverdict(pass);
+ }
+ [] MNCC.receive(MNCC_PDU:?) -> value mncc_pdu {
+ setverdict(fail, "Rx unexpected MNCC PDU: ", mncc_pdu);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for MNCC REL.ind");
+ }
+ }
+}
+testcase TC_mo_call_clear_request() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_TC_mo_mt_call_clear_request), 2532766); // '66'H - MO
+ vc_conn.done;
+}
+testcase TC_mt_call_clear_request() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_TC_mo_mt_call_clear_request), 2532768); // '68'H - MT
+ vc_conn.done;
+}
+
/* Test LU but BSC will send a clear request in the middle */
friend function f_tc_lu_disconnect(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
f_init_handler(pars);
@@ -926,6 +1110,7 @@ private function f_tc_lu_tmsi_noauth_unknown(charstring id, BSC_ConnHdlrPars par
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(overlong_imsi))); /* test for OS#2864 */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
+ f_expect_common_id();
/* Expect MSC to do UpdateLocation to HLR; respond to it */
GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
@@ -957,23 +1142,115 @@ testcase TC_lu_by_tmsi_noauth_unknown() runs on MTC_CT {
vc_conn.done;
}
-
-/* Test IMSI DETACH (MI=IMSI) */
-friend function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+/* Test LU by unknown TMSI, while the IMSI is already attached: osmo-msc should switch to the attached vlr_subscr. */
+private function f_tc_attached_imsi_lu_unknown_tmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
f_init_handler(pars);
+ var PDU_ML3_MS_NW l3_lu := f_build_lu_tmsi('56111111'O);
+ var PDU_DTAP_MT dtap_mt;
+
+ /* tell GSUP dispatcher to send this IMSI to us */
+ f_create_gsup_expect(hex2str(g_pars.imsi));
+
+ /* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
+ f_cl3_or_initial_ue(l3_lu);
+
+ /* Send Early Classmark, just for the fun of it */
+ BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
+
+ /* Wait for + respond to ID REQ (IMSI) */
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
+ f_expect_common_id();
+
+ /* Expect MSC to do UpdateLocation to HLR; respond to it */
+ GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
+ GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
+ GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
+ GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
+
+ alt {
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
+ setverdict(fail, "Expected LU ACK, but received REJ");
+ mtc.stop;
+ }
+ }
+
+ /* Wait for MM-Information (if enabled) */
+ f_expect_mm_info();
+
+ /* wait for normal teardown */
+ f_expect_clear(verify_vlr_cell_id := false);
+
+ /* Now the same IMSI is still attached in the VLR, and a LU with an unknown TMSI reveals the same IMSI only
+ * later during ID Response. osmo-msc first creates a new vlr_subscr for the unknown TMSI, and as soon as the
+ * IMSI becomes known, must notice that this IMSI is still regarded as attached, and must not create evil twins.
+ */
+
+ /* (since the TMSI Reallocation happened, we could do this with exactly the same TMSI as above, but for test
+ * readability just use a different one.) */
+ l3_lu := f_build_lu_tmsi('56222222'O);
+ f_cl3_or_initial_ue(l3_lu);
+
+ /* Wait for + respond to ID REQ (IMSI) */
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp_IMSI(g_pars.imsi)));
+ f_expect_common_id();
+
+ /* Expect MSC to do UpdateLocation to HLR; respond to it */
+ GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
+ GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
+ GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
+ GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
+
+ alt {
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) {
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
+ setverdict(fail, "Expected LU ACK, but received REJ");
+ mtc.stop;
+ }
+ }
+
+ /* Wait for MM-Information (if enabled) */
+ f_expect_mm_info();
+
+ /* wait for normal teardown */
+ f_expect_clear(verify_vlr_cell_id := false);
+}
+testcase TC_attached_imsi_lu_unknown_tmsi() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_tc_attached_imsi_lu_unknown_tmsi), 56);
+ vc_conn.done;
+}
+
+friend function f_imsi_detach_by_imsi() runs on BSC_ConnHdlr {
var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
f_cl3_or_initial_ue(valueof(ts_ML3_MO_MM_IMSI_DET_Ind(mi)));
/* Send Early Classmark, just for the fun of it? */
- if (pars.ran_is_geran) {
+ if (g_pars.ran_is_geran) {
BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
}
/* wait for normal teardown */
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id := false);
+}
+
+
+/* Test IMSI DETACH (MI=IMSI) */
+friend function f_tc_imsi_detach_by_imsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ f_imsi_detach_by_imsi();
}
testcase TC_imsi_detach_by_imsi() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -1153,7 +1430,9 @@ private function f_tc_cm_reest_req_reject(charstring id, BSC_ConnHdlrPars pars)
var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REEST_REQ(0, mi));
f_cl3_or_initial_ue(l3_info);
- BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ(int2oct(32,1))));
+ /* Older osmo-msc returns: GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
+ * newer osmo-msc with CM Re-Establish support returns: GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38 */
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ( (int2oct(32,1), int2oct(38,1)) )));
f_expect_clear();
}
testcase TC_cm_reest_req_reject() runs on MTC_CT {
@@ -1473,8 +1752,8 @@ friend function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) ru
repeat;
}
[] MGCP.receive { repeat; }
- [] as_clear_cmd_compl_disc();
- [] as_optional_cc_rel(cpars);
+ [] as_optional_cc_rel(cpars); /* repeats internally */
+ [] as_expect_clear() { setverdict(pass); }
}
}
testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
@@ -1489,46 +1768,89 @@ testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
/* Test MT Call T310 timer */
friend function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
- f_init_handler(pars, 200.0);
var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
- var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
+ var PDU_BSSAP bssap;
+ timer T310;
+
+ f_init_handler(pars);
+ /* Make sure X2 does not fire in this test. This test does not send a CN RTP port to osmo-msc, which will
+ * trigger X2 timeout. We want to test T310, so make X2 significantly longer than T310=30s. */
+ f_vty_config(MSCVTY, "msc", "timer mgw X2 40");
+
+ /* Initiate a MT call, establish connection */
f_mt_call_start(cpars);
/* MS->MSC: CALL CONFIRMED */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
- MGCP.receive(tr_CRCX) -> value mgcp_cmd;
- cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
- cpars.mgcp_ep := mgcp_cmd.line.ep;
- /* FIXME: Respond to CRCX */
+ /* NOTE: MSC is expected to start T310 here */
- /* old libosmocore T310 default timeout is 180s. so let's wait 190 */
- timer T := 190.0;
- T.start;
+ interleave {
+ /* MSC->MGW: CRCX (first) */
+ [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+ f_handle_crcx(cpars, mgcp_cmd); /* MSC<-MGW: OK */
+ }
+
+ /* BSC->BSC: BSSMAP ASSIGNMENT REQ */
+ [] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, ?)) -> value bssap {
+ BSSAP.send(ts_BSSMAP_AssignmentComplete(omit,
+ aoip := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port),
+ speechCodec := ts_BSSMAP_IE_SpeechCodec({ ts_CodecFR })));
+ }
+
+ /* MSC->MGW: MDCX */
+ [] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
+ MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id,
+ sdp := omit));
+ }
+
+ /* MSC->MGW: CRCX (second) */
+ [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
+ f_handle_crcx(cpars, mgcp_cmd); /* MSC<-MGW: OK */
+ }
+
+ [] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref));
+ }
+
+ /* Reschedule the guard timeout */
+ g_Tguard.start(30.0 + 10.0);
+
+ /* NOTE: the BSC is expected to respond with CC ALERTING at this state, so
+ * the MSC would stop T310. However, the idea is to verify T310 expiration
+ * here, so grab some popcorn and wait for MNCC DISC.ind. */
+ T310.start(30.0 + 2.0);
+ var MNCC_PDU mncc_rx;
alt {
- [] T.timeout {
- setverdict(fail, "Timeout waiting for T310");
+ [] T310.timeout {
+ setverdict(fail, "Timeout waiting for MNCC DISC.ind due to T310");
mtc.stop;
}
[] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
+ log("Rx MNCC DISC.ind, T310.read yields ", T310.read);
+ setverdict(pass);
}
+ [] MNCC.receive(MNCC_PDU:?) -> value mncc_rx {
+ log("Rx ", mncc_rx);
+ setverdict(fail, "Expected MNCC DISC.ind, got some other MNCC message instead");
+ mtc.stop;
}
+ }
+
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
- /* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
- BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, '1'B)));
alt {
[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
- f_create_mgcp_delete_ep(cpars.mgcp_ep);
+ // FIXME: f_create_mgcp_delete_ep(cpars.mgcp_ep);
repeat;
}
- [] as_clear_cmd_compl_disc();
+ [] as_expect_clear() { setverdict(pass); }
}
}
testcase TC_mt_t310() runs on MTC_CT {
@@ -1735,6 +2057,84 @@ testcase TC_lu_imsi_auth_tmsi_encr_13_2() runs on MTC_CT {
vc_conn.done;
}
+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with only A5/1 support */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ pars.net.expect_auth := true;
+ pars.net.expect_ciph := true;
+ pars.net.kc_support := '03'O; /* A5/0 + A5/1 */
+ pars.cm1.a5_1 := '0'B;
+ pars.cm2.a5_1 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_3 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
+ pars.cm3 := omit;
+ pars.use_umts_aka := true;
+
+ f_init_handler(pars, 15.0);
+ f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_1() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ f_vty_config(MSCVTY, "network", "authentication required");
+ f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
+
+ vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_1), 39);
+ vc_conn.done;
+}
+
+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 + A5/4 support */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_34(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ pars.net.expect_auth := true;
+ pars.net.expect_ciph := true;
+ pars.net.kc_support := '19'O; /* A5/3 + A5/4 */
+ pars.cm1.a5_1 := '1'B;
+ pars.cm2.a5_1 := '1'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
+ pars.cm3 := valueof(ts_CM3_default);
+ pars.use_umts_aka := true;
+
+ f_init_handler(pars, 15.0);
+ f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_34() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ f_vty_config(MSCVTY, "network", "authentication required");
+ f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
+
+ vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34), 40);
+ vc_conn.done;
+}
+
+/* A5/0 + A5/1 + A5/3 + a5/4 only permitted on network side, and MS with A5/3 support but no CM3 */
+private function f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ pars.net.expect_auth := true;
+ pars.net.expect_ciph := true;
+ pars.net.kc_support := '19'O; /* A5/3 + A5/4 */
+ pars.cm1.a5_1 := '1'B;
+ pars.cm2.a5_1 := '1'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.cm3 := '0'B;
+ pars.cm3 := omit;
+ pars.use_umts_aka := true;
+
+ f_init_handler(pars, 15.0);
+ f_perform_lu();
+}
+testcase TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ f_vty_config(MSCVTY, "network", "authentication required");
+ f_vty_config(MSCVTY, "network", "encryption a5 0 1 3 4");
+
+ vc_conn := f_start_handler(refers(f_tc_lu_imsi_auth_tmsi_encr_0134_34_no_cm3), 41);
+ vc_conn.done;
+}
+
/* A5/0 + A5/1 + A5/3 only permitted on network side, and MS with only A5/2 support */
private function f_tc_lu_imsi_auth_tmsi_encr_013_2(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
pars.net.expect_auth := true;
@@ -1782,6 +2182,25 @@ testcase TC_lu_and_mt_call_osmux() runs on MTC_CT {
vc_conn.done;
}
+/* LU followed by MT call (including paging) */
+friend function f_tc_lu_and_mt_call_ipv6(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+ var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ cpars.mgw_conn_1.mgw_rtp_ip := "::1";
+ cpars.mgw_conn_2.mgw_rtp_ip := "::2";
+ cpars.bss_rtp_ip := "::3";
+ cpars.mncc_rtp_ip := "::9";
+ f_perform_lu();
+ f_mt_call(cpars);
+}
+testcase TC_lu_and_mt_call_ipv6() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_tc_lu_and_mt_call_ipv6), 39);
+ vc_conn.done;
+}
+
/* MT call while already Paging */
friend function f_tc_lu_and_mt_call_already_paging(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
@@ -1808,7 +2227,7 @@ friend function f_tc_lu_and_mt_call_already_paging(charstring id, BSC_ConnHdlrPa
f_expect_paging();
log("MNCC signals MT call, before Paging Response");
- f_mt_call_initate(cpars);
+ f_mt_call_initiate(cpars);
f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
f_sleep(0.5);
@@ -2121,11 +2540,7 @@ friend function f_tc_lu_and_mt_sms_paging_and_nothing(charstring id, BSC_ConnHdl
timer T := 20.0;
T.start
alt {
- [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
- setverdict(fail, "paging seems not to stop!");
- mtc.stop;
- }
- [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
+ [] as_paging_any() {
setverdict(fail, "paging seems not to stop!");
mtc.stop;
}
@@ -2178,13 +2593,18 @@ friend function f_tc_lu_and_mt_sms_paging_repeated(charstring id, BSC_ConnHdlrPa
timer T := 5.0;
T.start;
alt {
- [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
- setverdict(fail, "GERAN should not repeat Paging, but received a second Paging");
- mtc.stop;
+ [] as_paging() {
+ if (g_pars.ran_is_geran) {
+ setverdict(fail, "GERAN should not repeat Paging, but received a second Paging");
+ mtc.stop;
+ } else {
+ log("UTRAN: second Paging received, as expected");
+ setverdict(pass);
}
- [not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
- log("UTRAN: second Paging received, as expected");
- setverdict(pass);
+ }
+ [] as_paging_any() {
+ setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
+ mtc.stop;
}
[] T.timeout {
if (g_pars.ran_is_geran) {
@@ -2373,8 +2793,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2429,8 +2848,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2517,8 +2935,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2580,8 +2997,7 @@ runs on BSC_ConnHdlr {
mtc.stop;
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2641,24 +3057,20 @@ runs on BSC_ConnHdlr {
/* Both transaction IDs shall be different */
if (spars1.tid == spars2.tid) {
- log("Both DTAP transaction IDs shall be different");
- setverdict(fail);
+ setverdict(fail, "Both DTAP transaction IDs shall be different");
}
/* Both SM-RP-MR values shall be different */
if (spars1.rp.msg_ref == spars2.rp.msg_ref) {
- log("Both SM-RP-MR values shall be different");
- setverdict(fail);
+ setverdict(fail, "Both SM-RP-MR values shall be different");
}
/* Both SM-RP-MR values shall be assigned */
if (spars1.rp.msg_ref == 'FF'O) {
- log("Unassigned SM-RP-MR value for the 1st SMS");
- setverdict(fail);
+ setverdict(fail, "Unassigned SM-RP-MR value for the 1st SMS");
}
if (spars2.rp.msg_ref == 'FF'O) {
- log("Unassigned SM-RP-MR value for the 2nd SMS");
- setverdict(fail);
+ setverdict(fail, "Unassigned SM-RP-MR value for the 2nd SMS");
}
/* Send the 1st RP-ACK and expect MT-forwardSM-Res on GSUP */
@@ -2672,8 +3084,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2689,8 +3100,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2745,8 +3155,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2762,14 +3171,12 @@ runs on BSC_ConnHdlr {
/* Both SM-RP-MR values shall be different */
if (spars_mo.rp.msg_ref == spars_mt.rp.msg_ref) {
- log("Both SM-RP-MR values shall be different");
- setverdict(fail);
+ setverdict(fail, "Both SM-RP-MR values shall be different");
}
/* SM-RP-MR value for MT SMS shall be assigned */
if (spars_mt.rp.msg_ref == 'FF'O) {
- log("Unassigned SM-RP-MR value for the MT SMS");
- setverdict(fail);
+ setverdict(fail, "Unassigned SM-RP-MR value for the MT SMS");
}
/* Trigger RP-ACK for MO SMMA by sending MO-forwardSM-Res */
@@ -2790,8 +3197,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -2854,8 +3260,7 @@ runs on BSC_ConnHdlr {
setverdict(pass);
}
[] GSUP.receive {
- log("RX unexpected GSUP message");
- setverdict(fail);
+ setverdict(fail, "Rx unexpected GSUP message");
mtc.stop;
}
}
@@ -3174,13 +3579,11 @@ runs on BSC_ConnHdlr {
GSUP.send(gsup_req);
T.start;
alt {
- [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
- setverdict(pass);
- }
- [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
- setverdict(pass);
+ [] as_paging() { setverdict(pass); }
+ [] as_paging_any() {
+ setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
+ mtc.stop;
}
- /* We don't expect anything else */
[] as_unexp_gsup_or_bssap_msg();
[] T.timeout {
setverdict(fail, "Timeout waiting for Paging Request");
@@ -3789,13 +4192,11 @@ runs on BSC_ConnHdlr {
/* Send it to MSC and expect Paging Request */
TP.start;
alt {
- [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
- setverdict(pass);
- }
- [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
- setverdict(pass);
+ [] as_paging() { setverdict(pass); }
+ [] as_paging_any() {
+ setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
+ mtc.stop;
}
- /* We don't expect anything else */
[] as_unexp_gsup_or_bssap_msg();
[] TP.timeout {
setverdict(fail, "Timeout waiting for Paging Request");
@@ -3863,13 +4264,11 @@ runs on BSC_ConnHdlr {
/* Expect Paging Request */
TP.start;
alt {
- [pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)) {
- setverdict(pass);
- }
- [not pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
- setverdict(pass);
+ [] as_paging() { setverdict(pass); }
+ [] as_paging_any() {
+ setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
+ mtc.stop;
}
- /* We don't expect anything else */
[] as_unexp_gsup_or_bssap_msg();
[] TP.timeout {
setverdict(fail, "Timeout waiting for Paging Request");
@@ -3972,6 +4371,7 @@ private function f_tc_cipher_complete_with_invalid_cipher(charstring id, BSC_Con
mtc.stop;
}
}
+ f_expect_common_id();
/* Expect LU reject from MSC. */
alt {
@@ -4008,6 +4408,7 @@ friend function f_tc_lu_with_invalid_mcc_mnc(charstring id, BSC_ConnHdlrPars par
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
f_cl3_or_initial_ue(l3_lu);
+ f_expect_common_id();
/* Expect LU reject from MSC. */
alt {
@@ -4019,7 +4420,7 @@ friend function f_tc_lu_with_invalid_mcc_mnc(charstring id, BSC_ConnHdlrPars par
mtc.stop;
}
}
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id:=false);
}
testcase TC_lu_with_invalid_mcc_mnc() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -4066,11 +4467,12 @@ private function f_tc_cipher_complete_without_alg(charstring id, BSC_ConnHdlrPar
mtc.stop;
}
}
+ f_expect_common_id();
/* TODO: Verify MSC is using the best cipher available! How? */
f_msc_lu_hlr();
- f_accept_reject_lu();
+ as_accept_reject_lu();
f_expect_clear();
setverdict(pass);
}
@@ -4163,11 +4565,16 @@ private function f_ctrl_subscr_in_vlr(charstring imsi_or_msisdn) runs on BSC_Con
return true;
}
-/* Perform a location updatye at the A-Interface and run some checks to confirm
+/* Perform a Location Update at the A-Interface and run some checks to confirm
* that everything is back to normal. */
private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
var SmsParameters spars := valueof(t_SmsPars);
+ /* From now on, since we initiated LU from A-Interface, we expect no
+ * LastEutranPLMNId on Common Id, since the SGs interface should be gone
+ */
+ g_pars.common_id_last_eutran_plmn := omit;
+
/* Perform a location update, the SGs association is expected to fall
* back to NULL */
f_perform_lu();
@@ -4180,11 +4587,10 @@ private function f_sgsap_bssmap_screening() runs on BSC_ConnHdlr {
f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
alt {
- [g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi)); {
- setverdict(pass);
- }
- [not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi))) {
- setverdict(pass);
+ [] as_paging() { setverdict(pass); }
+ [] as_paging_any() {
+ setverdict(fail, "Rx unexpected BSSMAP/RANAP Paging");
+ mtc.stop;
}
[] SGsAP.receive {
setverdict(fail, "Received unexpected message on SGs");
@@ -4242,12 +4648,19 @@ function f_sgs_perform_lu() runs on BSC_ConnHdlr {
var PDU_SGsAP lua;
var PDU_SGsAP mm_info;
var octetstring mm_info_dtap;
+ var GsmMcc mcc;
+ var GsmMnc mnc;
+ var template (omit) TrackingAreaIdentityValue tai := omit;
/* tell GSUP dispatcher to send this IMSI to us */
f_create_gsup_expect(hex2str(g_pars.imsi));
-
+ if (g_pars.common_id_last_eutran_plmn != omit) {
+ f_dec_mcc_mnc(g_pars.common_id_last_eutran_plmn, mcc, mnc);
+ tai := ts_SGsAP_TAI(mcc, mnc, 555);
+ }
lur := valueof(ts_SGsAP_LU_REQ(g_pars.imsi, mme_name, IMSI_attach,
- ts_SGsAP_LAI('901'H, '70'H, 2342)));
+ ts_SGsAP_LAI('901'H, '70'H, 2342),
+ tai));
/* Old LAI, if MS sends it */
/* TMSI status, if MS has no valid TMSI */
/* IMEISV, if it supports "automatic device detection" */
@@ -4307,6 +4720,7 @@ testcase TC_sgsap_lu() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11811, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_lu), pars);
vc_conn.done;
}
@@ -4434,6 +4848,7 @@ testcase TC_sgsap_expl_imsi_det_eps() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11814, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_eps), pars);
vc_conn.done;
}
@@ -4458,6 +4873,7 @@ testcase TC_sgsap_impl_imsi_det_eps() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11814, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_eps), pars);
vc_conn.done;
}
@@ -4485,6 +4901,7 @@ testcase TC_sgsap_expl_imsi_det_noneps() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11815, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_expl_imsi_det_noneps), pars);
vc_conn.done;
}
@@ -4512,6 +4929,7 @@ testcase TC_sgsap_impl_imsi_det_noneps() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11815, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_impl_imsi_det_noneps), pars);
vc_conn.done;
}
@@ -4563,6 +4981,7 @@ testcase TC_sgsap_paging_rej() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11816, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_rej), pars);
vc_conn.done;
}
@@ -4612,6 +5031,7 @@ testcase TC_sgsap_paging_subscr_rej() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11817, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_subscr_rej), pars);
vc_conn.done;
}
@@ -4656,6 +5076,7 @@ testcase TC_sgsap_paging_ue_unr() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11818, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_ue_unr), pars);
vc_conn.done;
}
@@ -4715,6 +5136,7 @@ testcase TC_sgsap_paging_and_nothing() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11819, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_nothing), pars);
vc_conn.done;
}
@@ -4773,6 +5195,7 @@ testcase TC_sgsap_paging_and_lu() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11820, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_paging_and_lu), pars);
vc_conn.done;
}
@@ -4823,6 +5246,9 @@ private function f_tc_sgsap_unsol_ud(charstring id, BSC_ConnHdlrPars pars) runs
f_sgsap_bssmap_screening();
+ /* clean-up VLR state about this subscriber */
+ f_imsi_detach_by_imsi();
+
setverdict(pass);
}
testcase TC_sgsap_unsol_ud() runs on MTC_CT {
@@ -4978,6 +5404,7 @@ testcase TC_sgsap_mt_sms() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11823, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms), pars);
vc_conn.done;
}
@@ -5008,6 +5435,7 @@ testcase TC_sgsap_mo_sms() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11824, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mo_sms), pars);
vc_conn.done;
}
@@ -5071,6 +5499,7 @@ testcase TC_sgsap_mt_sms_and_nothing() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11825, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_nothing), pars);
vc_conn.done;
}
@@ -5131,11 +5560,12 @@ testcase TC_sgsap_mt_sms_and_reject() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1, true);
pars := f_init_pars(11826, true);
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
vc_conn := f_start_handler_with_pars(refers(f_tc_sgsap_mt_sms_and_reject), pars);
vc_conn.done;
}
-/* Perform an MT CSDB call including LU */
+/* Perform an MT CSFB call including LU */
private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boolean bssmap_lu) runs on BSC_ConnHdlr {
f_init_handler(pars);
@@ -5147,6 +5577,7 @@ private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boo
if (bssmap_lu) {
f_perform_lu();
}
+ pars.common_id_last_eutran_plmn := f_enc_mcc_mnc('901'H, '70'H);
f_sgs_perform_lu();
f_sleep(1.0);
@@ -5155,7 +5586,7 @@ private function f_mt_lu_and_csfb_call(charstring id, BSC_ConnHdlrPars pars, boo
var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
/* Initiate a call via MNCC interface */
- f_mt_call_initate(cpars);
+ f_mt_call_initiate(cpars);
/* Expect a paging request and respond accordingly with a service request */
SGsAP.receive(tr_SGsAP_PAGING_REQ(pars.imsi, vlr_name, CS_call_indicator, omit));
@@ -5295,33 +5726,57 @@ testcase TC_ho_inter_bsc_unknown_cell() runs on MTC_CT {
private altstep as_mgcp_ack_all_mdcx(CallParameters cpars) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
- var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
- hex2str(cpars.mgcp_call_id), "42",
- cpars.mgw_conn_2.mgw_rtp_port,
- { int2str(cpars.rtp_payload_type) },
- { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
- cpars.rtp_sdp_format)),
- valueof(ts_SDP_ptime(20)) }));
- MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
- repeat;
- }
+ var charstring conn_id;
+ f_mgcp_find_param_entry(mgcp_cmd.params, "I", conn_id);
+ var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
+ hex2str(cpars.mgcp_call_id), "42",
+ cpars.mgw_conn_2.mgw_rtp_port,
+ { int2str(cpars.rtp_payload_type) },
+ { valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
+ cpars.rtp_sdp_format)),
+ valueof(ts_SDP_ptime(20)) }));
+ MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, str2hex(conn_id), sdp));
+ repeat;
+ }
+}
+
+private altstep as_mgcp_ack_all_dlcx(CallParameters cpars) runs on BSC_ConnHdlr {
+ var MgcpCommand mgcp_cmd;
+ [] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
+ MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
+ repeat;
+ }
}
private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
- var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ var CallParameters cpars;
+
+ cpars := valueof(t_CallParams('12345'H, 0));
+ if (pars.use_ipv6) {
+ cpars.mgw_conn_1.mgw_rtp_ip := "::1";
+ cpars.mgw_conn_2.mgw_rtp_ip := "::2";
+ cpars.bss_rtp_ip := "::3";
+ }
+ if (pars.use_csd) {
+ f_set_cpars_csd(cpars, "BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ }
f_init_handler(pars);
f_vty_transceive(MSCVTY, "configure terminal");
f_vty_transceive(MSCVTY, "msc");
f_vty_transceive(MSCVTY, "neighbor a cgi 262 42 23 42 ran-pc 0.24.1");
- f_vty_transceive(MSCVTY, "neighbor a lac 5 ran-pc 0.24.2");
+ f_vty_transceive(MSCVTY, "neighbor a cgi 023 42 5 6 ran-pc 0.24.2");
f_vty_transceive(MSCVTY, "exit");
f_vty_transceive(MSCVTY, "exit");
f_perform_lu();
f_mo_call_establish(cpars);
+ /* Remember the last n_sd (sequence number),
+ * we will need it when the other BSS hands over back to us. */
+ var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
+
f_sleep(1.0);
var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
@@ -5330,7 +5785,7 @@ private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs o
var BssmapCause cause := enum2int(cause_val);
var template BSSMAP_FIELD_CellIdentificationList cil;
- cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('023'H, '42'H, 5) } };
+ cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('023'H, '42'H, 5, 6) } };
/* old BSS sends Handover Required */
BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
@@ -5355,15 +5810,32 @@ private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs o
/* Ok, that went well, now the other BSC is handovering back here --
* from now on this here is the new BSS. */
- f_create_bssmap_exp_handoverRequest(193);
-
+ f_create_bssmap_exp_n_connect(193);
+
+ var template BSSMAP_IE_EncryptionInformation encryptionInformation;
+ var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
+ var template BSSMAP_IE_KC128 kC128;
+ var OCT1 a5_perm_alg;
+ f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
+ var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
+ chosenEncryptionAlgorithm,
+ kC128, codecList := ?);
var PDU_BSSAP ho_request;
- BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request;
+ alt {
+ [] BSSAP.receive(expect_ho_request);
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
+ log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
+ " got ", ho_request);
+ setverdict(fail, "Wrong handoverRequest received");
+ mtc.stop;
+ }
+ }
/* new BSS composes a RR Handover Command */
var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
- var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
+ var BSSMAP_IE_AoIP_TransportLayerAddress tla tla :=
+ valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
@@ -5381,13 +5853,11 @@ private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs o
deactivate(ack_mdcx);
- var default ccrel := activate(as_optional_cc_rel(cpars, true));
-
- /* blatant cheating */
- var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
- last_n_sd[0] := 3;
+ /* Use the n_sd (sequence number) we stored before the first handover.
+ * Otherwise the MSC may treat our DTAP messages as duplicates and discard them. */
f_bssmap_continue_after_n_sd(last_n_sd);
+ var default ccrel := activate(as_optional_cc_rel(cpars, true));
f_call_hangup(cpars, true);
f_sleep(1.0);
deactivate(ccrel);
@@ -5395,16 +5865,38 @@ private function f_tc_ho_inter_bsc0(charstring id, BSC_ConnHdlrPars pars) runs o
setverdict(pass);
}
private function f_tc_ho_inter_bsc1(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ var charstring bss_rtp_ip;
+ if (pars.use_ipv6) {
+ bss_rtp_ip := "::8";
+ } else {
+ bss_rtp_ip := "1.2.3.4";
+ }
f_init_handler(pars);
- f_create_bssmap_exp_handoverRequest(194);
-
+ f_create_bssmap_exp_n_connect(194);
+
+ var template BSSMAP_IE_EncryptionInformation encryptionInformation;
+ var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
+ var template BSSMAP_IE_KC128 kC128;
+ var OCT1 a5_perm_alg;
+ f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
+ var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
+ chosenEncryptionAlgorithm,
+ kC128, codecList := ?);
var PDU_BSSAP ho_request;
- BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request;
-
+ alt {
+ [] BSSAP.receive(expect_ho_request);
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
+ log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
+ " got ", ho_request);
+ setverdict(fail, "Wrong handoverRequest received");
+ mtc.stop;
+ }
+ }
/* new BSS composes a RR Handover Command */
var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
- var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
+ var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
+ valueof(f_ts_BSSMAP_IE_AoIP_TLA(bss_rtp_ip, 2342));
BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
@@ -5427,7 +5919,7 @@ private function f_tc_ho_inter_bsc1(charstring id, BSC_ConnHdlrPars pars) runs o
var BssmapCause cause := enum2int(cause_val);
var template BSSMAP_FIELD_CellIdentificationList cil;
- cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('262'H, '42'H, 23) } };
+ cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('262'H, '42'H, 23, 42) } };
/* old BSS sends Handover Required */
BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
@@ -5446,19 +5938,70 @@ private function f_tc_ho_inter_bsc1(charstring id, BSC_ConnHdlrPars pars) runs o
f_expect_clear();
setverdict(pass);
}
-testcase TC_ho_inter_bsc() runs on MTC_CT {
+function f_tc_ho_inter_bsc_main(boolean use_ipv6 := false, integer a5_n := 0, boolean use_csd := false) runs on MTC_CT {
var BSC_ConnHdlr vc_conn0;
var BSC_ConnHdlr vc_conn1;
f_init(2);
var BSC_ConnHdlrPars pars0 := f_init_pars(53);
+ pars0.use_ipv6 := use_ipv6;
+ pars0.use_csd := use_csd;
+ pars0.net.expect_ciph := a5_n > 0;
+ pars0.net.expect_auth := pars0.net.expect_ciph;
+ pars0.net.kc_support := bit2oct('00000001'B << a5_n);
+ pars0.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+ pars0.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+ pars0.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
+ pars0.cm3 := valueof(ts_CM3_default);
+ pars0.use_umts_aka := true;
+ pars0.vec := f_gen_auth_vec_3g();
+ pars0.vec_keep := true;
+ pars0.ran_idx := 0;
+
var BSC_ConnHdlrPars pars1 := f_init_pars(53);
+ pars1.use_ipv6 := use_ipv6;
+ pars1.use_csd := use_csd;
+ pars1.net.expect_ciph := pars0.net.expect_ciph;
+ pars1.net.expect_auth := pars0.net.expect_ciph;
+ pars1.net.kc_support := bit2oct('00000001'B << a5_n);
+ pars1.cm2 := pars0.cm2;
+ pars1.cm3 := pars0.cm3;
+ pars1.use_umts_aka := true;
+ /* Both components need the same auth vector info because we expect f_tc_ho_inter_bsc0's ciphering key to be
+ * identical to the one that shows up in f_tc_ho_inter_bsc1. Can only do that by feeding in a vector to both
+ * components and then not overwriting it in BSC_ConnectionHandler. */
+ pars1.vec := pars0.vec;
+ pars1.vec_keep := true;
+ pars1.ran_idx := 1;
+
+ if (a5_n > 0) {
+ f_vty_config(MSCVTY, "network", "authentication required");
+ }
+ f_vty_config(MSCVTY, "network", "encryption a5 " & int2str(a5_n));
- vc_conn0 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc0), pars0, 0);
- vc_conn1 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc1), pars1, 1);
+ vc_conn0 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc0), pars0);
+ vc_conn1 := f_start_handler_with_pars(refers(f_tc_ho_inter_bsc1), pars1);
vc_conn0.done;
vc_conn1.done;
}
+testcase TC_ho_inter_bsc() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(false, a5_n := 0);
+}
+testcase TC_ho_inter_bsc_a5_1() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(false, a5_n := 1);
+}
+testcase TC_ho_inter_bsc_a5_3() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(false, a5_n := 3);
+}
+testcase TC_ho_inter_bsc_a5_4() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(false, a5_n := 4);
+}
+testcase TC_ho_inter_bsc_ipv6() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(true);
+}
+testcase TC_ho_inter_bsc_csd() runs on MTC_CT {
+ f_tc_ho_inter_bsc_main(use_csd := true);
+}
function f_ML3_patch_seq_nr_MS_NW(in uint2_t seq_nr, inout octetstring enc_l3) {
log("MS_NW patching N(SD)=", seq_nr, " into dtap ", enc_l3);
@@ -5467,7 +6010,18 @@ function f_ML3_patch_seq_nr_MS_NW(in uint2_t seq_nr, inout octetstring enc_l3) {
}
private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
- var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ var CallParameters cpars;
+ var PDU_BSSAP ho_request;
+
+ cpars := valueof(t_CallParams('12345'H, 0));
+ if (pars.use_ipv6) {
+ cpars.mgw_conn_1.mgw_rtp_ip := "::1";
+ cpars.mgw_conn_2.mgw_rtp_ip := "::2";
+ cpars.bss_rtp_ip := "::3";
+ }
+ if (pars.use_csd) {
+ f_set_cpars_csd(cpars, "BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ }
var hexstring ho_number := f_gen_msisdn(99999);
f_init_handler(pars);
@@ -5491,7 +6045,7 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
var BssmapCause cause := enum2int(cause_val);
var template BSSMAP_FIELD_CellIdentificationList cil;
- cil := { cIl_LAI := { ts_BSSMAP_CI_LAI('017'H, '017'H, 1) } };
+ cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('017'H, '017'H, 1, 1) } };
/* old BSS sends Handover Required */
BSSAP.send(ts_BSSMAP_HandoverRequired(cause, cil));
@@ -5499,21 +6053,47 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
/* The target cell 017-017 LAC 1 is configured to be a remote MSC of name "msc-017-017-1".
* This MSC tries to reach the other MSC via GSUP. */
+ var template BSSMAP_IE_EncryptionInformation encryptionInformation;
+ var template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm;
+ var template BSSMAP_IE_KC128 kC128;
+ var OCT1 a5_perm_alg;
+ f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
+ var template PDU_BSSAP expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
+ chosenEncryptionAlgorithm,
+ kC128, codecList := ?);
+
var octetstring remote_msc_name := '6D73632D3031372D3031372D3100'O; /* "msc-017-017-1\0" as octetstring */
var GSUP_PDU prep_ho_req;
- GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST,
- pars.imsi, destination_name := remote_msc_name)) -> value prep_ho_req;
+ alt {
+ [] GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST,
+ pars.imsi, destination_name := remote_msc_name,
+ an_apdu := t_GSUP_AN_APDU(OSMO_GSUP_AN_PROTO_48006, pdu := ?))) -> value prep_ho_req;
+ [] GSUP.receive(tr_GSUP_E_AN_APDU(OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST)) {
+ setverdict(fail, "Wrong OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST message received");
+ mtc.stop;
+ }
+ }
var GSUP_IeValue source_name_ie;
f_gsup_find_ie(prep_ho_req, OSMO_GSUP_SOURCE_NAME_IE, source_name_ie);
var octetstring local_msc_name := source_name_ie.source_name;
+ /* Decode PDU to 1) match with expect_ho_request and 2) to forward the actual chosen encryption algorithm. */
+ var GSUP_IeValue an_apdu_ie;
+ f_gsup_find_ie(prep_ho_req, OSMO_GSUP_AN_APDU_IE, an_apdu_ie);
+ ho_request := dec_PDU_BSSAP(an_apdu_ie.an_apdu.pdu);
+ if (not match(ho_request, expect_ho_request)) {
+ setverdict(fail, "Wrong PDU in OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST message received");
+ mtc.stop;
+ }
+
/* Remote MSC has figured out its BSC and signals success */
var PDU_ML3_NW_MS rr_ho_cmd := valueof(ts_RR_HandoverCommand);
var octetstring rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
var PDU_BSSAP ho_req_ack := valueof(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
- aoIPTransportLayer := omit,
- speechCodec := ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
+ aoIPTransportLayer := omit,
+ speechCodec := ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}),
+ chosenEncryptionAlgorithm := ho_request.pdu.bssmap.handoverRequest.chosenEncryptionAlgorithm));
GSUP.send(ts_GSUP_E_PrepareHandoverResult(
pars.imsi,
ho_number,
@@ -5635,7 +6215,7 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
/* inter-MSC handover back to the first MSC */
- f_create_bssmap_exp_handoverRequest(193);
+ f_create_bssmap_exp_n_connect(193);
cil := { cIl_CGI := { ts_BSSMAP_CI_CGI('262'H, '42'H, 23, 42) } };
/* old BSS sends Handover Required, via inter-MSC E link: like
@@ -5649,7 +6229,19 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
));
/* MSC asks local BSS to prepare Handover to it */
- BSSAP.receive(tr_BSSMAP_HandoverRequest);
+ f_get_expected_encryption(encryptionInformation, chosenEncryptionAlgorithm, kC128, a5_perm_alg);
+ expect_ho_request := tr_BSSMAP_HandoverRequest(encryptionInformation,
+ chosenEncryptionAlgorithm,
+ kC128, codecList := ?);
+ alt {
+ [] BSSAP.receive(expect_ho_request) -> value ho_request;
+ [] BSSAP.receive(tr_BSSMAP_HandoverRequest) -> value ho_request {
+ log("Error: Wrong handoverRequest received. Expected: ", expect_ho_request,
+ " got ", ho_request);
+ setverdict(fail, "Wrong handoverRequest received");
+ mtc.stop;
+ }
+ }
/* Make sure the new BSSAP conn continues with the correct N_SD sequence numbers */
f_bssmap_continue_after_n_sd(last_n_sd);
@@ -5657,9 +6249,11 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
/* new BSS composes a RR Handover Command */
rr_ho_cmd := valueof(ts_RR_HandoverCommand);
rr_ho_cmd_enc := enc_PDU_ML3_NW_MS(rr_ho_cmd);
- var BSSMAP_IE_AoIP_TransportLayerAddress tla := valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
+ var BSSMAP_IE_AoIP_TransportLayerAddress tla :=
+ valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
BSSAP.send(ts_BSSMAP_HandoverRequestAcknowledge(rr_ho_cmd_enc, lengthof(rr_ho_cmd_enc),
- tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR})));
+ tla, ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}),
+ chosenEncryptionAlgorithm := ho_request.pdu.bssmap.handoverRequest.chosenEncryptionAlgorithm));
/* HandoverCommand goes out via remote MSC-I */
var GSUP_PDU prep_subsq_ho_res;
@@ -5696,13 +6290,58 @@ private function f_tc_ho_inter_msc_out(charstring id, BSC_ConnHdlrPars pars) run
setverdict(pass);
}
+function f_tc_ho_inter_msc_out_a5(integer a5_n) runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init(1);
+
+ var BSC_ConnHdlrPars pars := f_init_pars(54);
+ pars.net.expect_ciph := a5_n > 0;
+ pars.net.expect_auth := pars.net.expect_ciph;
+ pars.net.kc_support := bit2oct('00000001'B << a5_n);
+ pars.cm2.classmarkInformationType2_oct5.a5_3 := '1'B;
+ pars.cm2.classmarkInformationType2_oct5.a5_2 := '0'B;
+ pars.cm2.classmarkInformationType2_oct5.cm3 := '1'B;
+ pars.cm3 := valueof(ts_CM3_default);
+ pars.use_umts_aka := true;
+
+ if (a5_n > 0) {
+ f_vty_config(MSCVTY, "network", "authentication required");
+ }
+ f_vty_config(MSCVTY, "network", "encryption a5 " & int2str(a5_n));
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
+ vc_conn.done;
+}
testcase TC_ho_inter_msc_out() runs on MTC_CT {
+ f_tc_ho_inter_msc_out_a5(0);
+}
+testcase TC_ho_inter_msc_out_a5_1() runs on MTC_CT {
+ f_tc_ho_inter_msc_out_a5(1);
+}
+testcase TC_ho_inter_msc_out_a5_3() runs on MTC_CT {
+ f_tc_ho_inter_msc_out_a5(3);
+}
+testcase TC_ho_inter_msc_out_a5_4() runs on MTC_CT {
+ f_tc_ho_inter_msc_out_a5(4);
+}
+testcase TC_ho_inter_msc_out_ipv6() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init(1);
var BSC_ConnHdlrPars pars := f_init_pars(54);
+ pars.use_ipv6 := true;
- vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars, 0);
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
+ vc_conn.done;
+}
+testcase TC_ho_inter_msc_out_csd() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init(1);
+
+ var BSC_ConnHdlrPars pars := f_init_pars(54);
+ pars.use_csd := true;
+
+ vc_conn := f_start_handler_with_pars(refers(f_tc_ho_inter_msc_out), pars);
vc_conn.done;
}
@@ -5787,7 +6426,7 @@ private function f_tc_lu_imsi_auth_tmsi_check_imei_nack(charstring id, BSC_ConnH
f_msc_lu_hlr();
f_mm_imei();
f_expect_lu_reject();
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id:=false);
}
testcase TC_lu_imsi_auth_tmsi_check_imei_nack() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -5817,7 +6456,7 @@ private function f_tc_lu_imsi_auth_tmsi_check_imei_err(charstring id, BSC_ConnHd
f_msc_lu_hlr();
f_mm_imei();
f_expect_lu_reject();
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id:=false);
}
testcase TC_lu_imsi_auth_tmsi_check_imei_err() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -5908,7 +6547,7 @@ private function f_tc_lu_imsi_auth_tmsi_check_imei_early_nack(charstring id, BSC
f_mm_imei_early();
f_expect_lu_reject();
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id:=false);
}
testcase TC_lu_imsi_auth_tmsi_check_imei_early_nack() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -5936,7 +6575,7 @@ private function f_tc_lu_imsi_auth_tmsi_check_imei_early_err(charstring id, BSC_
f_mm_imei_early();
f_expect_lu_reject();
- f_expect_clear();
+ f_expect_clear(verify_vlr_cell_id:=false);
}
testcase TC_lu_imsi_auth_tmsi_check_imei_early_err() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
@@ -5971,15 +6610,13 @@ testcase TC_invalid_mgcp_crash() runs on MTC_CT {
vc_conn.done;
}
+/* Test how the MSC handles a malformed MM IDENTITY RESPONSE with no identity. */
friend function f_tc_mm_id_resp_no_identity(charstring id, BSC_ConnHdlrPars pars)
runs on BSC_ConnHdlr {
- pars.tmsi := 'FFFFFFFF'O;
f_init_handler(pars);
- f_create_gsup_expect(hex2str(g_pars.imsi));
-
/* Initiate Location Updating using an unknown TMSI */
- f_bssap_compl_l3(f_build_lu_tmsi(pars.tmsi));
+ f_bssap_compl_l3(f_build_lu_tmsi('FFFFFFFF'O));
/* Expect an Identity Request, send response with no identity */
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI)));
@@ -5996,7 +6633,10 @@ runs on BSC_ConnHdlr {
}
})));
- f_expect_lu_reject();
+ /* XXX: Current osmo-msc does not react on bad/malformed MM IDENTITY RESPONSE immediately.
+ * It instead relies on expiry of timer X1, which is set to 5.0 seconds by default. This
+ * is not good (DoS vector) and should ideally be fixed, but for now just work it around. */
+ f_expect_lu_reject(Tval := 5.0 + 1.0);
f_expect_clear();
}
testcase TC_mm_id_resp_no_identity() runs on MTC_CT {
@@ -6046,24 +6686,698 @@ testcase TC_lu_and_expire_while_paging() runs on MTC_CT {
vc_conn.done;
}
+private altstep as_mncc_rx_rtp_create(CallParameters cpars) runs on BSC_ConnHdlr {
+ [] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref));
+}
+
+const charstring REEST_LOST_CONNECTION := "REEST_LOST_CONNECTION";
+const charstring REEST_CLEARED := "REEST_CLEARED";
+
+friend function f_tc_call_re_establishment_1(charstring id, BSC_ConnHdlrPars pars)
+ runs on BSC_ConnHdlr {
+ f_init_handler(pars, t_guard := 30.0);
+
+ f_perform_lu();
+
+ var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ f_mo_call_establish(cpars);
+ f_sleep(3.0);
+ COORD.send(REEST_LOST_CONNECTION);
+ COORD.send(cpars);
+ f_expect_clear(verify_vlr_cell_id := false);
+ COORD.send(REEST_CLEARED);
+}
+
+friend function f_tc_call_re_establishment_2(charstring id, BSC_ConnHdlrPars pars)
+ runs on BSC_ConnHdlr {
+ f_init_handler(pars, t_guard := 30.0);
+ var CallParameters cpars;
+
+ COORD.receive(REEST_LOST_CONNECTION);
+ COORD.receive(tr_CallParams) -> value cpars;
+
+ f_gsup_change_connhdlr(hex2str(g_pars.imsi));
+ f_create_smpp_expect(hex2str(pars.msisdn));
+
+ /* The MS has lost the first channel and decides to show up on a new conn (on a nearby neighbor cell) to ask for
+ * CM Re-Establishment. Send a Complete Layer 3 to osmo-msc with a CM Re-Establishment Request. */
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ var PDU_ML3_MS_NW l3_info := valueof(ts_CM_REESTABL_REQ(mi));
+ f_cl3_or_initial_ue(l3_info);
+
+ /* At this point the other test component should receive the Clear Command for the first A connection. */
+
+ /* This new connection continues with Authentication... */
+ f_mm_common();
+
+ /* ...and with Assignment of a voice channel. */
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
+ (f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?),
+ f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_2.mgw_rtp_ip, ?));
+ BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass));
+ /* By this Assignment Request, the CM Re-Establishment Request is implicitly accepted. */
+
+ /* Send Assignment Complete from BSC */
+ var template BSSMAP_IE_AoIP_TransportLayerAddress tla;
+ tla := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port);
+ var BSSMAP_IE_SpeechCodec codec;
+ codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
+
+ /* Make really sure the other component is done with its MGCP */
+ COORD.receive(REEST_CLEARED);
+
+ /* Transfer state for this call over to this test component so we can resolve MNCC and MGCP in this function. */
+ f_mncc_change_connhdlr(cpars.mncc_callref);
+ f_mgcp_change_connhdlr(cpars.mgcp_ep);
+
+ /* osmo-msc may redirect the MGW endpoint to the newly allocated channel.
+ * Apparently osmo-msc currently also sends an MDCX to the CN side, just repeating the same configuration that
+ * is already in use. This test accepts any number of or even lack of MDCX. */
+ var default ack_mdcx := activate(as_mgcp_ack_all_mdcx(cpars));
+ var default optional_rtp_create := activate(as_mncc_rx_rtp_create(cpars));
+
+ BSSAP.send(ts_BSSMAP_AssignmentComplete(omit, tla, codec));
+
+ /* The call has been fully re-established.
+ * Let a bit of time pass before hanging up, for everything to settle. */
+ f_sleep(3.0);
+
+ deactivate(optional_rtp_create);
+ deactivate(ack_mdcx);
+
+ /* Hang up the call and clear the new, second A connection */
+ var default ack_dlcx := activate(as_mgcp_ack_all_dlcx(cpars));
+
+ /* CC release. This is the proper MS initiated release sequence as shown by
+ * https://git.osmocom.org/osmo-msc/tree/doc/sequence_charts/voice_call_full.msc?id=e53ecde83e4fb2470209e818e9ad76a2d6a19190
+ * f_call_hangup() seems a bit mixed up, so here a "proper" sequence. Fix of f_call_hangup() pending. */
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_DISC(cpars.transaction_id, '0'B, '0000000'B)));
+ MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref));
+ MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id, '0'B)));
+ MNCC.receive(tr_MNCC_REL_cnf(cpars.mncc_callref, cause := *));
+
+ /* BSSAP clear */
+ interleave {
+ [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
+ BSSAP.send(ts_BSSMAP_ClearComplete);
+ }
+ [] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
+ }
+
+ f_sleep(1.0);
+ deactivate(ack_dlcx);
+}
+
+testcase TC_call_re_establishment() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn1;
+ var BSC_ConnHdlr vc_conn2;
+ f_init();
+
+ var BSC_ConnHdlrPars pars1 := f_init_pars(91);
+ var BSC_ConnHdlrPars pars2 := pars1;
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+}
+
+testcase TC_call_re_establishment_auth() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn1;
+ var BSC_ConnHdlr vc_conn2;
+ f_init();
+
+ f_vty_config(MSCVTY, "network", "authentication required");
+
+ var BSC_ConnHdlrPars pars1 := f_init_pars(92);
+ pars1.net.expect_auth := true;
+ var BSC_ConnHdlrPars pars2 := pars1;
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+}
+
+testcase TC_call_re_establishment_ciph() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn1;
+ var BSC_ConnHdlr vc_conn2;
+ f_init();
+
+ f_vty_config(MSCVTY, "network", "authentication required");
+ f_vty_config(MSCVTY, "network", "encryption a5 3");
+
+ var BSC_ConnHdlrPars pars1 := f_init_pars(92);
+ pars1.net.expect_auth := true;
+ pars1.net.expect_ciph := true;
+ pars1.net.kc_support := '08'O; /* A5/3 only */
+ var BSC_ConnHdlrPars pars2 := pars1;
+
+ vc_conn1 := f_start_handler_create(pars1);
+ vc_conn2 := f_start_handler_create(pars2);
+ connect(vc_conn1:COORD, vc_conn2:COORD);
+ f_start_handler_run(vc_conn1, refers(f_tc_call_re_establishment_1), pars1);
+ f_start_handler_run(vc_conn2, refers(f_tc_call_re_establishment_2), pars2);
+ vc_conn1.done;
+ vc_conn2.done;
+}
+
+/* Establish a conn with a valid Mobile Identity. Then send a CM Service Request containing a mismatching Mobile
+ * Identity on the same conn. Caused a crash, see OS#5532. */
+friend function f_tc_cm_serv_wrong_mi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ /* Set up a fully identified conn */
+ f_perform_lu();
+ f_establish_fully();
+
+ /* CM Serv Req with mismatching Mobile Identity */
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(f_gen_imsi(99999))); /* ensure it is different from below*/
+ BSSAP.send(ts_PDU_DTAP_MO(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, mi)));
+ BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_REJ));
+
+ /* Cancel the first CM Service from f_establish_fully() */
+ BSSAP.send(ts_BSSMAP_ClearRequest(0));
+
+ f_expect_clear();
+}
+testcase TC_cm_serv_wrong_mi() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_tc_cm_serv_wrong_mi), 94);
+ vc_conn.done;
+}
+
+/* a5 0 a5 0 a5 0 3 a5 0 3 a5 3 a5 3
+ * HLR has auth info no yes no yes no yes
+ *
+ * test case index [0] [1] [2] [3] [4] [5]
+ * authentication optional No auth No auth attempt auth, auth reject auth
+ * (%) fall back to +ciph +ciph
+ * no-auth
+ *
+ * [6] [7] [8] [9] [10] [11]
+ * authentication mandatory reject auth reject auth reject auth
+ * only +ciph +ciph
+ *
+ * (%): Arguably, when HLR has auth info, the MSC should use it. Current behavior of osmo-msc is to not attempt auth at
+ * all. Related: OS#4830.
+ */
+type record of BSC_ConnHdlrNetworkPars rof_netpars;
+
+const rof_netpars auth_options_testcases := {
+ {
+ /* [0] auth optional, encr a5 0: no-auth" */
+ kc_support := '01'O,
+ net_config := { "authentication optional",
+ "encryption a5 0" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := false,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [1] auth optional, encr a5 0, HLR HAS auth info: no-auth */
+ kc_support := '01'O,
+ net_config := { "authentication optional",
+ "encryption a5 0" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := false,
+ hlr_has_auth_info := true,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [2] auth optional, encr a5 0 3, HLR has NO Auth Info: Fall back to no-auth" */
+ kc_support := '09'O,
+ net_config := { "authentication optional",
+ "encryption a5 0 3" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [3] auth optional, encr a5 0 3, HLR HAS Auth Info: Use A5/3 */
+ kc_support := '09'O,
+ net_config := { "authentication optional",
+ "encryption a5 0 3" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := true,
+ expect_auth := true,
+ expect_ciph := true,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [4] auth optional, encr a5 3, HLR has NO Auth Info: reject.
+ * Auth is required implicitly because ciph is required. */
+ kc_support := '08'O,
+ net_config := { "authentication optional",
+ "encryption a5 3" },
+ expect_attach_success := false,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [5] auth optional, encr a5 3, HLR HAS Auth Info: auth + ciph.
+ * Auth is required implicitly because ciph is required. */
+ kc_support := '08'O,
+ net_config := { "authentication optional",
+ "encryption a5 3" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := true,
+ expect_auth := true,
+ expect_ciph := true,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+
+ /* Same as above, but with 'authentication required' */
+
+ {
+ /* [6] auth required, encr a5 0, HLR has NO auth info: reject */
+ kc_support := '01'O,
+ net_config := { "authentication required",
+ "encryption a5 0" },
+ expect_attach_success := false,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [7] auth required, encr a5 0, HLR HAS auth info: do auth, no ciph" */
+ kc_support := '01'O,
+ net_config := { "authentication required",
+ "encryption a5 0" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := true,
+ expect_auth := true,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [8] auth required, encr a5 0 3, HLR has NO Auth Info: reject */
+ kc_support := '09'O,
+ net_config := { "authentication required",
+ "encryption a5 0 3" },
+ expect_attach_success := false,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [9] auth required, encr a5 0 3, HLR HAS Auth Info: Use A5/3 */
+ kc_support := '09'O,
+ net_config := { "authentication required",
+ "encryption a5 0 3" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := true,
+ expect_auth := true,
+ expect_ciph := true,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [10] auth required, encr a5 3, HLR has NO Auth Info: reject. */
+ kc_support := '08'O,
+ net_config := { "authentication required",
+ "encryption a5 3" },
+ expect_attach_success := false,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := false,
+ expect_auth := false,
+ expect_ciph := false,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ },
+ {
+ /* [11] auth required, encr a5 3, HLR HAS Auth Info: auth + ciph. */
+ kc_support := '08'O,
+ net_config := { "authentication required",
+ "encryption a5 3" },
+ expect_attach_success := true,
+ expect_tmsi := true,
+ expect_auth_attempt := true,
+ hlr_has_auth_info := true,
+ expect_auth := true,
+ expect_ciph := true,
+ expect_imei := false,
+ expect_imei_early := false,
+ check_imei_result := OSMO_GSUP_IMEI_RESULT_ACK,
+ check_imei_error := false
+ }
+};
+
+private function f_tc_auth_options(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ /* Location Updating */
+ log(MSCVTY, "f_perform_lu() starting");
+ f_perform_lu();
+ log(MSCVTY, "f_perform_lu() done");
+
+ f_sleep(1.0);
+
+ if (not pars.net.expect_attach_success) {
+ /* Expected above LU to fail. In order to test CM Service Request below, a LU has to succeed first. So
+ * run another LU that will be successful. Careful not to load auth tokens into the VLR that may taint
+ * the test for CM Service Request below. */
+
+ log(MSCVTY, "Running a successful LU so that CM Service Request can be tested");
+ var BSC_ConnHdlrNetworkPars saved_net := g_pars.net;
+ g_pars.net.kc_support := '01'O;
+ g_pars.net.expect_attach_success := true;
+ g_pars.net.expect_auth_attempt := false;
+ g_pars.net.expect_auth := false;
+ g_pars.net.expect_ciph := false;
+ f_vty_config3(MSCVTY, {"network"}, {"authentication optional", "encryption a5 0"});
+ f_perform_lu();
+
+ /* Reconfigure like it was before */
+ g_pars.net := saved_net;
+ f_vty_config3(MSCVTY, {"network"}, g_pars.net.net_config);
+ log(MSCVTY, "Running a successful LU done");
+ }
+
+ /* CM Service Request */
+ log(MSCVTY, "f_establish_fully() starting");
+ f_establish_fully();
+ log(MSCVTY, "f_establish_fully() done");
+ BSSAP.send(ts_BSSMAP_ClearRequest(0));
+ f_expect_clear();
+}
+
+function f_TC_auth_options(integer tc_i) runs on MTC_CT {
+ f_init();
+
+ var BSC_ConnHdlrNetworkPars tc := auth_options_testcases[tc_i];
+
+ f_vty_config3(MSCVTY, {"network"}, tc.net_config);
+
+ var BSC_ConnHdlrPars pars := f_init_pars(42300 + tc_i);
+ pars.net := tc;
+
+ var BSC_ConnHdlr vc_conn;
+ vc_conn := f_start_handler_with_pars(refers(f_tc_auth_options), pars);
+ vc_conn.done;
+}
+
+testcase TC_auth_options_0() runs on MTC_CT {
+ f_TC_auth_options(0);
+}
+
+testcase TC_auth_options_1() runs on MTC_CT {
+ f_TC_auth_options(1);
+}
+
+testcase TC_auth_options_2() runs on MTC_CT {
+ f_TC_auth_options(2);
+}
+
+testcase TC_auth_options_3() runs on MTC_CT {
+ f_TC_auth_options(3);
+}
+
+testcase TC_auth_options_4() runs on MTC_CT {
+ f_TC_auth_options(4);
+}
+
+testcase TC_auth_options_5() runs on MTC_CT {
+ f_TC_auth_options(5);
+}
+
+testcase TC_auth_options_6() runs on MTC_CT {
+ f_TC_auth_options(6);
+}
+
+testcase TC_auth_options_7() runs on MTC_CT {
+ f_TC_auth_options(7);
+}
+
+testcase TC_auth_options_8() runs on MTC_CT {
+ f_TC_auth_options(8);
+}
+
+testcase TC_auth_options_9() runs on MTC_CT {
+ f_TC_auth_options(9);
+}
+
+testcase TC_auth_options_10() runs on MTC_CT {
+ f_TC_auth_options(10);
+}
+
+testcase TC_auth_options_11() runs on MTC_CT {
+ f_TC_auth_options(11);
+}
+
+private function f_set_cpars_csd(inout CallParameters cpars, charstring bs_name, BIT1 async,
+ GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate) {
+ log("-----------------------------------------------");
+ log("CSD Bearer Service: " & bs_name);
+ log("-----------------------------------------------");
+
+ cpars.csd := true;
+
+ cpars.bearer_cap := valueof(ts_Bcap_csd);
+ cpars.bearer_cap.octet6.synchronous_asynchronous := async;
+ cpars.bearer_cap.octet6.connectionElement := int2bit(enum2int(transp), 2);
+ cpars.bearer_cap.octet6.userRate := int2bit(enum2int(user_rate), 4);
+
+ cpars.mncc_bearer_cap := valueof(ts_MNCC_bcap_data);
+ cpars.mncc_bearer_cap.data.async := bit2int(async);
+ cpars.mncc_bearer_cap.data.transp := transp;
+ cpars.mncc_bearer_cap.data.user_rate := user_rate;
+}
+
+friend function f_mo_csd(charstring bs_name, BIT1 async, GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate)
+ runs on BSC_ConnHdlr {
+ var CallParameters cpars := valueof(t_CallParams);
+
+ g_Tguard.start(20.0);
+ f_set_cpars_csd(cpars, bs_name, async, transp, user_rate);
+ f_perform_lu();
+ f_mo_call(cpars, 0.5);
+}
+
+friend function f_tc_lu_and_mo_csd(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ f_mo_csd("BS21T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_300);
+ f_mo_csd("BS22T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
+ f_mo_csd("BS24T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
+ f_mo_csd("BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ f_mo_csd("BS26T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
+
+ f_mo_csd("BS21NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_300);
+ f_mo_csd("BS22NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_1200);
+ f_mo_csd("BS24NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_2400);
+ f_mo_csd("BS25NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_4800);
+ f_mo_csd("BS26NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_9600);
+
+ f_mo_csd("BS31T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
+ f_mo_csd("BS32T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
+ f_mo_csd("BS33T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ f_mo_csd("BS34T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
+}
+testcase TC_lu_and_mo_csd() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_tc_lu_and_mo_csd), 7);
+ vc_conn.done;
+}
+
+friend function f_mt_csd(charstring bs_name, BIT1 async, GSM48_bcap_transp transp, GSM48_bcap_user_rate user_rate)
+ runs on BSC_ConnHdlr {
+ var CallParameters cpars := valueof(t_CallParams);
+
+ g_Tguard.start(20.0);
+ f_set_cpars_csd(cpars, bs_name, async, transp, user_rate);
+ f_perform_lu();
+ f_mt_call(cpars, 0.5);
+}
+friend function f_tc_lu_and_mt_csd(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars);
+
+ f_mt_csd("BS21T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_300);
+ f_mt_csd("BS22T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
+ f_mt_csd("BS24T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
+ f_mt_csd("BS25T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ f_mt_csd("BS26T", '1'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
+
+ f_mt_csd("BS21NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_300);
+ f_mt_csd("BS22NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_1200);
+ f_mt_csd("BS24NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_2400);
+ f_mt_csd("BS25NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_4800);
+ f_mt_csd("BS26NT", '1'B, GSM48_BCAP_TR_RLP, GSM48_BCAP_UR_9600);
+
+ f_mt_csd("BS31T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_1200);
+ f_mt_csd("BS32T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_2400);
+ f_mt_csd("BS33T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_4800);
+ f_mt_csd("BS34T", '0'B, GSM48_BCAP_TR_TRANSP, GSM48_BCAP_UR_9600);
+}
+testcase TC_lu_and_mt_csd() runs on MTC_CT {
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+
+ vc_conn := f_start_handler(refers(f_tc_lu_and_mt_csd), 7);
+ vc_conn.done;
+}
+
+/* MSC <-> BSC: ID req/rsp for IMSI */
+private altstep as_id_req_imsi()
+runs on BSC_ConnHdlr {
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMSI))) {
+ var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp(mi)));
+ repeat;
+ }
+}
+
+/* MSC is configured to not assign a TMSI; MS sends LU Request with a TMSI MI (from another cell), and MSC shall not use
+ * that TMSI. */
+private function f_tc_lu_tmsi_noauth_notmsi(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
+ f_init_handler(pars, t_guard := 20.0);
+
+ /* Perform Location Updating using an unknown TMSI MI. Expect an ID Request to come from the MSC and answer
+ * that with as_id_req_imsi(). */
+ activate(as_id_req_imsi());
+ f_perform_lu(use_mi := ts_MI_TMSI_LV(pars.tmsi));
+
+ f_sleep(1.0);
+
+ /* Attached by invalid TMSI, and the MSC has asked for the IMSI. Initiate Paging and make sure the MSC doesn't
+ * use the invalid TMSI for it. */
+ f_ran_register_imsi(g_pars.imsi, omit);
+ f_vty_transceive(MSCVTY, "subscriber imsi " & hex2str(g_pars.imsi) & " paging");
+ f_expect_paging_tmsi(omit);
+
+ /* Respond to paging, to clean up internal paging state for this subscriber, so we can get a clean second run
+ * out of this test code. Don't use the TMSI in the paging response. */
+ f_cl3_or_initial_ue(valueof(ts_PAG_RESP(ts_MI_IMSI_LV(pars.imsi))));
+ f_mm_common();
+ /* The paging was by VTY, so nothing happens, just a release. */
+ f_expect_clear();
+
+ /* Clean up ttcn state for the second test run to work out. */
+ f_unregister_gsup_imsi(hex2str(pars.imsi));
+ f_ran_unregister_imsi(pars.imsi);
+}
+testcase TC_lu_tmsi_noauth_notmsi() runs on MTC_CT {
+ var BSC_ConnHdlrPars pars;
+ var BSC_ConnHdlr vc_conn;
+ f_init();
+ f_vty_config(MSCVTY, "msc", "no assign-tmsi");
+ pars := f_init_pars(101);
+ pars.net.expect_tmsi := false;
+ pars.tmsi := '0badbad0'O;
+ pars.mm_info := false;
+ vc_conn := f_start_handler_with_pars(refers(f_tc_lu_tmsi_noauth_notmsi), pars);
+ vc_conn.done;
+
+ /* Now run the same test *again*, to test against an evil twin VLR entry:
+ * A vlr_subscr with the correct IMSI is now present in the VLR.
+ * We again ask for a LU with the 0x0bad TMSI. The VLR will initially create another vlr_subsrc(TMSI=0x0bad).
+ * When it learns the IMSI via ID Request, it needs to realize that this IMSI is already present on the first
+ * vsub, and sort out the VLR record so that only one entry for this IMSI exists.
+ */
+ pars := f_init_pars(101);
+ pars.net.expect_tmsi := false;
+ pars.tmsi := '0badbad0'O;
+ pars.mm_info := false;
+ vc_conn := f_start_handler_with_pars(refers(f_tc_lu_tmsi_noauth_notmsi), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_cr_before_reset() );
execute( TC_lu_imsi_noauth_tmsi() );
execute( TC_lu_imsi_noauth_notmsi() );
+ execute( TC_lu_tmsi_noauth_notmsi() );
execute( TC_lu_imsi_reject() );
execute( TC_lu_imsi_timeout_gsup() );
execute( TC_lu_imsi_auth_tmsi() );
execute( TC_lu_imsi_auth3g_tmsi() );
execute( TC_lu_imsi_timeout_tmsi_realloc() );
execute( TC_cmserv_imsi_unknown() );
+ execute( TC_cmserv_tmsi_unknown() );
execute( TC_lu_and_mo_call() );
+ execute( TC_lu_and_mo_call_ipv6() );
execute( TC_lu_and_mo_call_sccp_tiar_timeout() );
execute( TC_lu_auth_sai_timeout() );
execute( TC_lu_auth_sai_err() );
execute( TC_lu_clear_request() );
+ execute( TC_mo_call_clear_request() );
+ execute( TC_mt_call_clear_request() );
execute( TC_lu_disconnect() );
execute( TC_lu_by_imei() );
execute( TC_lu_by_tmsi_noauth_unknown() );
+ execute( TC_attached_imsi_lu_unknown_tmsi() );
execute( TC_imsi_detach_by_imsi() );
execute( TC_imsi_detach_by_tmsi() );
execute( TC_imsi_detach_by_imei() );
@@ -6083,7 +7397,7 @@ control {
execute( TC_mo_crcx_ran_reject() );
execute( TC_mt_crcx_ran_reject() );
execute( TC_mo_setup_and_dtmf_dup() );
- //execute( TC_mt_t310() );
+ execute( TC_mt_t310() );
execute( TC_gsup_cancel() );
execute( TC_lu_imsi_auth_tmsi_encr_1_13() );
execute( TC_lu_imsi_auth_tmsi_encr_3_13() );
@@ -6091,12 +7405,18 @@ control {
execute( TC_lu_imsi_auth_tmsi_encr_3_1_no_cm() );
execute( TC_lu_imsi_auth_tmsi_encr_13_2() );
execute( TC_lu_imsi_auth_tmsi_encr_013_2() );
+ execute( TC_lu_imsi_auth_tmsi_encr_0134_1() );
+ execute( TC_lu_imsi_auth_tmsi_encr_0134_34() );
+ execute( TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3() );
+
execute( TC_mo_release_timeout() );
execute( TC_lu_and_mt_call_no_dlcx_resp() );
execute( TC_reset_two() );
execute( TC_lu_and_mt_call() );
+ execute( TC_lu_and_mt_call_ipv6() );
execute( TC_lu_and_mt_call_already_paging() );
+ execute( TC_lu_and_mt_call_osmux() );
execute( TC_lu_and_mo_sms() );
execute( TC_lu_and_mt_sms() );
@@ -6162,8 +7482,18 @@ control {
execute( TC_ho_inter_bsc_unknown_cell() );
execute( TC_ho_inter_bsc() );
+ execute( TC_ho_inter_bsc_a5_1() );
+ execute( TC_ho_inter_bsc_a5_3() );
+ execute( TC_ho_inter_bsc_a5_4() );
+ execute( TC_ho_inter_bsc_ipv6() );
+ execute( TC_ho_inter_bsc_csd() );
execute( TC_ho_inter_msc_out() );
+ execute( TC_ho_inter_msc_out_a5_1() );
+ execute( TC_ho_inter_msc_out_a5_3() );
+ execute( TC_ho_inter_msc_out_a5_4() );
+ execute( TC_ho_inter_msc_out_ipv6() );
+ execute( TC_ho_inter_msc_out_csd() );
execute( TC_lu_imsi_auth_tmsi_check_imei() );
execute( TC_lu_imsi_auth3g_tmsi_check_imei() );
@@ -6177,16 +7507,36 @@ control {
execute( TC_lu_imsi_noauth_notmsi_check_imei_early() );
execute( TC_lu_imsi_auth_tmsi_check_imei_early_nack() );
execute( TC_lu_imsi_auth_tmsi_check_imei_early_err() );
-
- /* Run this last: at the time of writing this test crashes the MSC */
execute( TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug() );
+
execute( TC_mo_cc_bssmap_clear() );
- if (mp_enable_osmux_test) {
- execute( TC_lu_and_mt_call_osmux() );
- }
execute( TC_invalid_mgcp_crash() );
execute( TC_mm_id_resp_no_identity() );
execute( TC_lu_and_expire_while_paging() );
+ execute( TC_paging_response_imsi_unknown() );
+ execute( TC_paging_response_tmsi_unknown() );
+
+ execute( TC_call_re_establishment() );
+ execute( TC_call_re_establishment_auth() );
+ execute( TC_call_re_establishment_ciph() );
+
+ execute( TC_cm_serv_wrong_mi() );
+
+ execute( TC_auth_options_0() );
+ execute( TC_auth_options_1() );
+ execute( TC_auth_options_2() );
+ execute( TC_auth_options_3() );
+ execute( TC_auth_options_4() );
+ execute( TC_auth_options_5() );
+ execute( TC_auth_options_6() );
+ execute( TC_auth_options_7() );
+ execute( TC_auth_options_8() );
+ execute( TC_auth_options_9() );
+ execute( TC_auth_options_10() );
+ execute( TC_auth_options_11() );
+
+ execute( TC_lu_and_mo_csd() );
+ execute( TC_lu_and_mt_csd() );
}
diff --git a/msc/MSC_Tests_ASCI.ttcn b/msc/MSC_Tests_ASCI.ttcn
new file mode 100644
index 00000000..c8bf2dac
--- /dev/null
+++ b/msc/MSC_Tests_ASCI.ttcn
@@ -0,0 +1,710 @@
+module MSC_Tests_ASCI {
+
+/* Osmocom MSC test suite for ASCI support in TTCN-3
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Andreas Eversberg
+ *
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from BSC_ConnectionHandler all;
+import from MSC_Tests all;
+
+import from Osmocom_VTY_Functions all;
+
+import from GSUP_Emulation all;
+import from RAN_Emulation all;
+import from MGCP_Emulation all;
+
+import from RANAP_Templates all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+
+import from L3_Templates all;
+
+import from MobileL3_CommonIE_Types all;
+
+
+/* Call control for VGCS and VBS
+ *
+ * There are 3 connection:
+ * - "call" = voice group/broadcast call initiated by the calling subscriber
+ * - "control" = VGCS/VBS call control connection
+ * - "channel" = VGCS/VBS channel resource connection
+ *
+ * All 3 connections have their own handlers. They send their test results via
+ * COORD messages to the main test function. There the result is collected and
+ * the outcome of the test is checked.
+ */
+
+/* Test functions */
+const charstring COORD_TEST_NO_CALLREF := "TEST_NO_CALLREF";
+const charstring COORD_TEST_SETUP_REFUSE := "TEST_SETUP_REFUSE";
+const charstring COORD_TEST_ASSIGN_FAIL := "TEST_ASSIGN_FAIL";
+const charstring COORD_TEST_COMPLETE_VGCS := "TEST_COMPLETE_VGCS";
+const charstring COORD_TEST_COMPLETE_VBS := "TEST_COMPLETE_VBS";
+
+/* COORD pipes for each connection */
+type component asci_CT extends MTC_CT {
+ port BSC_ConnHdlr_Coord_PT COORD_call;
+ port BSC_ConnHdlr_Coord_PT COORD_control;
+ port BSC_ConnHdlr_Coord_PT COORD_channel;
+}
+
+/* COORD messages for test events */
+const charstring COORD_SETUP := "SETUP";
+const charstring COORD_VGCS_SETUP := "VGCS_SETUP";
+const charstring COORD_VGCS_ASSIGN := "VGCS_ASSIGN";
+const charstring COORD_UPLINK_SEIZED := "UPLINK_SEIZED";
+const charstring COORD_GCC_CONNECT := "GCC_CONNECT";
+const charstring COORD_BCC_CONNECT := "BCC_CONNECT";
+const charstring COORD_GCC_SET_PARAM := "GCC_SET_PARAM";
+const charstring COORD_BCC_SET_PARAM := "BCC_SET_PARAM";
+const charstring COORD_UPLINK_REQ_ACK := "UPLINK_REQ_ACK";
+const charstring COORD_GCC_TERMINATION := "GCC_TERMINATION";
+const charstring COORD_BCC_TERMINATION := "BCC_TERMINATION";
+const charstring COORD_GCC_TERMINATION_FAIL := "GCC_TERMINATION_FAIL";
+const charstring COORD_BCC_TERMINATION_FAIL := "BCC_TERMINATION_FAIL";
+const charstring COORD_ASSIGNMENT := "ASSIGNMENT";
+const charstring COORD_CLEAR := "CLEAR";
+
+template (value) DescriptiveGroupOrBroadcastCallReference_V
+ ts_BSSMAP_IE_GroupCallRef(integer cr,
+ BIT1 sf,
+ BIT1 af,
+ BIT3 prio,
+ BIT4 ci) := {
+ binaryCodingOfGroupOrBroadcastCallReference := int2bit(cr, 27),
+ sF := sf,
+ aF := af,
+ callPriority := prio,
+ cipheringInformation := ci,
+ spare := '0000'B
+}
+
+function f_gen_asci_ass_res(integer bssap_idx := 0,
+ template (value) BSSMAP_IE_ChannelType ch_type := ts_BSSMAP_IE_ChannelType,
+ template (value) BSSMAP_IE_CellIdentifier cell_id := ts_CellId_CI(0),
+ template (omit) BSSMAP_IE_AoIP_TransportLayerAddress aoip_tla := omit,
+ template (omit) BSSMAP_IE_SpeechCodec codec := omit,
+ template (omit) OCT4 call_id := omit)
+runs on BSC_ConnHdlr return template (value) PDU_BSSAP {
+ if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
+ return ts_BSSMAP_VGCS_VBS_AssignmentRes(ch_type, cell_id, omit, omit, aoip_tla, codec, call_id);
+ } else {
+ var template (value) BSSMAP_IE_CircuitIdentityCode cic := ts_BSSMAP_IE_CIC(0,1);
+ return ts_BSSMAP_VGCS_VBS_AssignmentRes(ch_type, cell_id, omit, cic, omit, omit, omit);
+ }
+}
+
+/* "call" connection handling */
+private function f_tc_vgcs_call(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr
+{
+ /* Receive test case from main function. */
+ var charstring test;
+ COORD.receive(charstring:?) -> value test;
+
+ /* Initialize variables and templates. */
+ var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
+ ts_BSSMAP_IE_GroupCallRef(oct2int('190000'O), '1'B, '0'B, '000'B, '0000'B);
+ if (test == COORD_TEST_COMPLETE_VBS) {
+ callref := ts_BSSMAP_IE_GroupCallRef(oct2int('1a0000'O), '0'B, '0'B, '000'B, '0000'B);
+ }
+ var template BSSMAP_IE_ChannelType tr_ch_type := tr_BSSMAP_IE_ChannelType('0001'B, ChRate_TCHF, Spdi_TCHF_FR);
+ var template PDU_BSSAP tr_assignment_req := tr_BSSMAP_AssignmentReq();
+ tr_assignment_req.pdu.bssmap.assignmentRequest.channelType := tr_ch_type;
+ tr_assignment_req.pdu.bssmap.assignmentRequest.groupCallReference :=
+ tr_BSSMAP_IE_GroupCallRef(bit2oct(encvalue(callref)));
+ /* Due to a bug in dec_PDU_BSSAP(), we do not get the callref IE, so we need to match it with omit. */
+ tr_assignment_req.pdu.bssmap.assignmentRequest.groupCallReference := omit;
+ var template (value) PDU_BSSAP ts_assignment_cpl := ts_BSSMAP_AssignmentComplete(omit, omit, omit, omit);
+ var octetstring xcc_termination_21 := '340121'O;
+ var octetstring xcc_termination_11 := '340111'O;
+ var PDU_BSSAP rx_bssap;
+
+ f_init_handler(pars);
+
+ /* Location Update to make subscriber known. */
+ f_perform_lu();
+
+ /* MGW */
+ f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
+ var default crcx := activate(as_optional_mgcp_crcx(cpars));
+ var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
+ var default dlcx := activate(as_optional_mgcp_dlcx(cpars));
+
+ /* Establish connection using the service type, defined by the test. */
+ if (test == COORD_TEST_COMPLETE_VBS) {
+ f_establish_fully(EST_TYPE_VBS);
+ } else {
+ f_establish_fully(EST_TYPE_VGCS);
+ }
+
+ /* Send incorrect call reference, if selected by test. */
+ log("Sending SETUP.");
+ select (test) {
+ case (COORD_TEST_NO_CALLREF) {
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_GCC(cpars.transaction_id, '3200002900'O)));
+ }
+ case (COORD_TEST_COMPLETE_VBS) {
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_BCC(cpars.transaction_id, '3200001a00'O)));
+ }
+ case else {
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_GCC(cpars.transaction_id, '3200001900'O)));
+ }
+ }
+ COORD.send(COORD_SETUP);
+
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_assignment_req) -> value rx_bssap {
+ /* The MSC sends and Assignment Request to assign the calling subscriber to the VGCS/VBS channel. */
+ log("Got Assignment Request: ", rx_bssap);
+ COORD.send(COORD_ASSIGNMENT);
+ log("Sending Assignment Complete: ", ts_assignment_cpl);
+ BSSAP.send(ts_assignment_cpl);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_GCC(cpars.transaction_id, xcc_termination_21))) {
+ /* The MSC terminates the group call with cause 21 = requested service not subscribed. */
+ log("Got GCC Termination with failure.");
+ COORD.send(COORD_GCC_TERMINATION_FAIL);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_BCC(cpars.transaction_id, xcc_termination_21))) {
+ /* The MSC terminates the broadcast call with cause 21 = requested service not subscribed. */
+ log("Got BCC Termination with failure.");
+ COORD.send(COORD_BCC_TERMINATION_FAIL);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_GCC(cpars.transaction_id, xcc_termination_11))) {
+ /* The MSC terminates the group call with cause 11 = network failure. */
+ log("Got GCC Termination with failure.");
+ COORD.send(COORD_GCC_TERMINATION_FAIL);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_BCC(cpars.transaction_id, xcc_termination_11))) {
+ /* The MSC terminates the broadcast call with cause 11 = network failure. */
+ log("Got BCC Termination with failure.");
+ COORD.send(COORD_BCC_TERMINATION_FAIL);
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
+ /* The SCCP connection is released. */
+ log("Got Clear Command on initial connection.");
+ COORD.send(COORD_CLEAR);
+ repeat;
+ }
+ [] BSSAP.receive {
+ setverdict(fail, "Got unexpected message on initial connection.");
+ }
+ [] COORD.receive(COORD_CLEAR) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for Message");
+ }
+ }
+
+ deactivate(crcx);
+ deactivate(mdcx);
+ deactivate(dlcx);
+}
+
+/* "control" connection handling */
+private function f_tc_vgcs_control(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr
+{
+ /* Receive test case from main function. */
+ var charstring test;
+ COORD.receive(charstring:?) -> value test;
+
+ /* Initialize variables and templates. */
+ var CallParameters cpars := valueof(t_CallParams('12345'H, 0));
+ var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
+ ts_BSSMAP_IE_GroupCallRef(oct2int('190000'O), '1'B, '0'B, '000'B, '0000'B);
+ if (test == COORD_TEST_COMPLETE_VBS) {
+ callref := ts_BSSMAP_IE_GroupCallRef(oct2int('1a0000'O), '0'B, '0'B, '000'B, '0000'B);
+ }
+ var template PDU_BSSAP tr_vgcs_vbs_setup := tr_BSSMAP_VGCS_VBS_Setup(bit2oct(encvalue(callref)));
+ var template (value) PDU_BSSAP ts_vgcs_vbs_setup_ack := ts_BSSMAP_VGCS_VBS_SetupAck(omit);
+ var myBSSMAP_Cause cause_fail := GSM0808_CAUSE_EQUIPMENT_FAILURE;
+ var template (value) PDU_BSSAP ts_vgcs_vbs_setup_refuse := ts_BSSMAP_VGCS_VBS_SetupRefuse(enum2int(cause_fail));
+ var octetstring gcc_connect := '330000190001'O;
+ var octetstring bcc_connect := '3300001a0001'O;
+ var octetstring xcc_set_param := '3A07'O;
+ var octetstring gcc_term_req := '3500001900'O;
+ var octetstring bcc_term_req := '3500001a00'O;
+ var octetstring xcc_termination := '340110'O;
+ /* L3 info carries the mobile identity of the talker requesting the uplink. */
+ var octetstring uplink_req_conf := '061103505902082926240000000033'O;
+ var myBSSMAP_Cause cause_success := GSM0808_CAUSE_CALL_CONTROL;
+ var template (value) PDU_BSSAP ts_uplink_rel_ind := ts_BSSMAP_UplinkRelInd(enum2int(cause_success), omit);
+ var template (value) PDU_BSSAP ts_uplink_req := ts_BSSMAP_UplinkReq;
+ var template (value) PDU_BSSAP ts_uplink_req_conf := ts_BSSMAP_UplinkReqConf(ts_CellId_CI(42), omit, uplink_req_conf);
+ var PDU_BSSAP rx_bssap;
+
+ f_init_handler(pars);
+
+ f_create_bssmap_exp_n_connect(193);
+
+ timer T := 7.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_vgcs_vbs_setup) -> value rx_bssap {
+ /* The MSC sets up call control on the BSC. The test case will send an ack or a refuse. */
+ log("Got VGCS/VBS Setup: ", rx_bssap);
+ COORD.send(COORD_VGCS_SETUP);
+ if (test == COORD_TEST_SETUP_REFUSE) {
+ log("Sending VGCS/VBS Setup Refuse: ", ts_vgcs_vbs_setup_refuse);
+ BSSAP.send(ts_vgcs_vbs_setup_refuse);
+ } else {
+ log("Sending VGCS/VBS Setup Ack: ", ts_vgcs_vbs_setup_ack);
+ BSSAP.send(ts_vgcs_vbs_setup_ack);
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkSeizedCmd(GSM0808_CAUSE_CALL_CONTROL)) -> value rx_bssap {
+ /* After setting up the call, the MSC marks the call as busy. */
+ log("Got Uplink Seized Cmd: ", rx_bssap);
+ COORD.send(COORD_UPLINK_SEIZED);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_GCC(cpars.transaction_id, gcc_connect))) {
+ /* The GCC CONNECT message is sent to the calling MS. */
+ log("Got GCC Connect.");
+ COORD.send(COORD_GCC_CONNECT);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_BCC(cpars.transaction_id, bcc_connect))) {
+ /* The BCC CONNECT message is sent to the calling MS. */
+ log("Got BCC Connect.");
+ COORD.send(COORD_BCC_CONNECT);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_GCC(cpars.transaction_id, xcc_set_param))) {
+ /* The GCC SET PARAMETER message is sent to the calling MS. */
+ log("Got GCC Set Parameter.");
+ COORD.send(COORD_GCC_SET_PARAM);
+ f_sleep(0.2);
+ /* The MS releases the uplink. */
+ log("Sending Uplink Release Ind: ", ts_uplink_rel_ind);
+ BSSAP.send(ts_uplink_rel_ind);
+ f_sleep(0.2);
+ /* The MS requests the uplink again. */
+ log("Sending Uplink Req: ", ts_uplink_req);
+ BSSAP.send(ts_uplink_req);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_BCC(cpars.transaction_id, xcc_set_param))) {
+ /* The BCC SET PARAMETER message is sent to the calling MS. */
+ log("Got BCC Set Parameter");
+ COORD.send(COORD_BCC_SET_PARAM);
+ f_sleep(0.2);
+ /* The MS requests termination of the call. */
+ log("Sending BCC Termination Request: ", bcc_term_req);
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_BCC(cpars.transaction_id, bcc_term_req)));
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_UplinkReqAck(*)) -> value rx_bssap {
+ /* The uplink was granted by the MSC. */
+ log("Got Uplink Request Acknowledge: ", rx_bssap);
+ COORD.send(COORD_UPLINK_REQ_ACK);
+ f_sleep(0.2);
+ /* The BSC confirms the uplink and provides mobile identity to identify originator. */
+ log("Sending Uplink Req Confirm: ", ts_uplink_req_conf);
+ BSSAP.send(ts_uplink_req_conf);
+ /* The MS requests termination of the call. */
+ log("Sending GCC Termination Request: ", gcc_term_req);
+ BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_GCC(cpars.transaction_id, gcc_term_req)));
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_GCC(cpars.transaction_id, xcc_termination))) {
+ /* The MSC terminates the call towards the MS. */
+ log("Got GCC Termination.");
+ COORD.send(COORD_GCC_TERMINATION);
+ repeat;
+ }
+ [] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_BCC(cpars.transaction_id, xcc_termination))) {
+ /* The MSC terminates the call towards the MS. */
+ log("Got BCC Termination.");
+ COORD.send(COORD_BCC_TERMINATION);
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
+ /* The SCCP connection is released. */
+ log("Got Clear Command on control connection.");
+ COORD.send(COORD_CLEAR);
+ repeat;
+ }
+ [] BSSAP.receive(PDU_BSSAP:?) -> value rx_bssap {
+ setverdict(fail, "Got unexpected BSSAP message on control connection: ", rx_bssap);
+ }
+ [] BSSAP.receive {
+ setverdict(fail, "Got unexpected message on control connection.");
+ }
+ [] COORD.receive(COORD_CLEAR) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout on control connection.");
+ }
+ }
+}
+
+/* "channel" connection handling */
+private function f_tc_vgcs_channel(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr
+{
+ /* Receive test case from main function. */
+ var charstring test;
+ COORD.receive(charstring:?) -> value test;
+
+ /* Initialize variables and templates. */
+ var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
+ ts_BSSMAP_IE_GroupCallRef(oct2int('190000'O), '1'B, '0'B, '000'B, '0000'B);
+ if (test == COORD_TEST_COMPLETE_VBS) {
+ callref := ts_BSSMAP_IE_GroupCallRef(oct2int('1a0000'O), '0'B, '0'B, '000'B, '0000'B);
+ }
+ var template (present) BSSMAP_IE_ChannelType tr_ch_type :=
+ tr_BSSMAP_IE_ChannelType('0001'B, ChRate_TCHF, Spdi_TCHF_FR);
+ var template (value) BSSMAP_IE_ChannelType ts_ch_type := valueof(ts_BSSMAP_IE_ChannelTypeCTM);
+ var template (present) BSSMAP_IE_CellIdentifier tr_cell_id := tr_CellId_CI(42);
+ var template (value) BSSMAP_IE_CellIdentifier ts_cell_id := ts_CellId_CI(42);
+ var template (value) BSSMAP_IE_AoIP_TransportLayerAddress ts_tla := f_ts_BSSMAP_IE_AoIP_TLA("1.2.3.4", 2342);
+ var template (value) BSSMAP_IE_SpeechCodec ts_codec := ts_BSSMAP_IE_SpeechCodec({ts_CodecFR});
+ var template PDU_BSSAP tr_vgcs_vbs_ass_req :=
+ tr_BSSMAP_VGCS_VBS_AssignmentReq(tr_ch_type, '01'O, tr_cell_id, bit2oct(encvalue(callref)), *, *, *);
+ var template (value) PDU_BSSAP ts_vgcs_vbs_ass_res :=
+ f_gen_asci_ass_res(0, ts_ch_type, ts_cell_id, ts_tla, ts_codec, '01000000'O);
+ var myBSSMAP_Cause cause_fail := GSM0808_CAUSE_EQUIPMENT_FAILURE;
+ var template (value) PDU_BSSAP ts_vgcs_vbs_ass_fail := ts_BSSMAP_VGCS_VBS_AssignmentFail(enum2int(cause_fail));
+ var PDU_BSSAP rx_bssap;
+
+ f_init_handler(pars);
+
+ /* Wait some time before registering, because this has to be the second connection to be registered. */
+ f_sleep(0.5);
+ f_create_bssmap_exp_n_connect(193);
+
+ timer T := 7.0;
+ T.start;
+ alt {
+ [] BSSAP.receive(tr_vgcs_vbs_ass_req) -> value rx_bssap {
+ /* The MSC allocates channel on the given BTS. The test case will send a result or a failure. */
+ log("Got VGCS/VBS Assignment Request: ", rx_bssap);
+ COORD.send(COORD_VGCS_ASSIGN);
+ if (test == COORD_TEST_ASSIGN_FAIL) {
+ log("Sending VGCS/VBS Assignment Failure: ", ts_vgcs_vbs_ass_fail);
+ BSSAP.send(ts_vgcs_vbs_ass_fail);
+ } else {
+ log("Sending VGCS/VBS Assignment Result: ", ts_vgcs_vbs_ass_res);
+ BSSAP.send(ts_vgcs_vbs_ass_res);
+ }
+ repeat;
+ }
+ [] BSSAP.receive(tr_BSSMAP_ClearCommand) {
+ /* The SCCP connection is released. */
+ log("Got Clear Command on channel connection.");
+ COORD.send(COORD_CLEAR);
+ repeat;
+ }
+ [] BSSAP.receive(PDU_BSSAP:?) -> value rx_bssap {
+ setverdict(fail, "Got unexpected BSSAP message on channel connection: ", rx_bssap);
+ }
+ [] BSSAP.receive {
+ setverdict(fail, "Got unexpected message on channel connection.");
+ }
+ [] COORD.receive(COORD_CLEAR) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout on channel connection.");
+ }
+ }
+}
+
+/* Main function for call test */
+private function f_TC_asci_call(charstring test) runs on asci_CT
+{
+ var BSC_ConnHdlr vc_conn_call, vc_conn_control, vc_conn_channel;
+ var boolean got_vgcs_setup := false;
+ var boolean got_vgcs_assign := false;
+ var boolean got_uplink_seized := false;
+ var boolean got_gcc_connect := false;
+ var boolean got_bcc_connect := false;
+ var boolean got_gcc_set_param := false;
+ var boolean got_bcc_set_param := false;
+ var boolean got_uplink_req_ack := false;
+ var boolean got_gcc_termination := false;
+ var boolean got_bcc_termination := false;
+ var boolean got_gcc_termination_fail := false;
+ var boolean got_bcc_termination_fail := false;
+ var boolean got_assignment := false;
+ var boolean connection_call := false;
+ var boolean connection_control := false;
+ var boolean connection_channel := false;
+ var charstring event;
+
+ f_init();
+
+ /* Enable ASCI in VTY and setup a VGC and a VBS. */
+ f_vty_config(MSCVTY, "asci", "enable");
+ f_vty_config2(MSCVTY, { "asci", "gcr", "vgc 200"}, "cell 0.24.1 42");
+ f_vty_config2(MSCVTY, { "asci", "gcr", "vbc 208"}, "cell 0.24.1 42");
+
+ vc_conn_call := f_start_handler(refers(f_tc_vgcs_call), 33);
+ vc_conn_control := f_start_handler(refers(f_tc_vgcs_control), 34);
+ vc_conn_channel := f_start_handler(refers(f_tc_vgcs_channel), 35);
+
+ connect(self:COORD_call, vc_conn_call:COORD);
+ connect(self:COORD_control, vc_conn_control:COORD);
+ connect(self:COORD_channel, vc_conn_channel:COORD);
+
+ COORD_call.send(test);
+ COORD_control.send(test);
+ COORD_channel.send(test);
+
+ /* Receive the test events until all three connections are released or not established. */
+ timer T := 7.0, Texit := 0.5;
+ T.start;
+ alt {
+ [] COORD_call.receive(COORD_SETUP) -> value event {
+ log("Got test event: ", event);
+ connection_call := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_VGCS_SETUP) -> value event {
+ log("Got test event: ", event);
+ got_vgcs_setup := true;
+ connection_control := true;
+ repeat;
+ }
+ [] COORD_channel.receive(COORD_VGCS_ASSIGN) -> value event {
+ log("Got test event: ", event);
+ got_vgcs_assign := true;
+ connection_channel := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_UPLINK_REQ_ACK) -> value event {
+ log("Got test event: ", event);
+ got_uplink_req_ack := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_GCC_CONNECT) -> value event {
+ log("Got test event: ", event);
+ got_gcc_connect := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_BCC_CONNECT) -> value event {
+ log("Got test event: ", event);
+ got_bcc_connect := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_GCC_SET_PARAM) -> value event {
+ log("Got test event: ", event);
+ got_gcc_set_param := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_BCC_SET_PARAM) -> value event {
+ log("Got test event: ", event);
+ got_bcc_set_param := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_UPLINK_SEIZED) -> value event {
+ log("Got test event: ", event);
+ got_uplink_seized := true;
+ repeat;
+ }
+ [] COORD_call.receive(COORD_GCC_TERMINATION_FAIL) -> value event {
+ log("Got test event: ", event);
+ got_gcc_termination_fail := true;
+ repeat;
+ }
+ [] COORD_call.receive(COORD_BCC_TERMINATION_FAIL) -> value event {
+ log("Got test event: ", event);
+ got_bcc_termination_fail := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_GCC_TERMINATION) -> value event {
+ log("Got test event: ", event);
+ got_gcc_termination := true;
+ repeat;
+ }
+ [] COORD_control.receive(COORD_BCC_TERMINATION) -> value event {
+ log("Got test event: ", event);
+ got_bcc_termination := true;
+ repeat;
+ }
+ [] COORD_call.receive(COORD_ASSIGNMENT) -> value event {
+ log("Got test event: ", event);
+ got_assignment := true;
+ repeat;
+ }
+ [not connection_call] COORD_call.receive(COORD_CLEAR) -> value event {
+ setverdict(fail, "Received CLEAR COMMAND of initial call twice.");
+ }
+ [] COORD_call.receive(COORD_CLEAR) -> value event {
+ log("Got test event: ", event);
+ connection_call := false;
+ if (connection_call or connection_control or connection_channel) {
+ repeat;
+ }
+ Texit.start;
+ repeat;
+ }
+ [not connection_control] COORD_control.receive(COORD_CLEAR) -> value event {
+ setverdict(fail, "Received CLEAR COMMAND control connection twice.");
+ }
+ [] COORD_control.receive(COORD_CLEAR) -> value event {
+ log("Got test event: ", event);
+ connection_control := false;
+ if (connection_call or connection_control or connection_channel) {
+ repeat;
+ }
+ Texit.start;
+ repeat;
+ }
+ [not connection_channel] COORD_channel.receive(COORD_CLEAR) -> value event {
+ setverdict(fail, "Received CLEAR COMMAND of channel connection twice.");
+ }
+ [] COORD_channel.receive(COORD_CLEAR) -> value event {
+ log("Got test event: ", event);
+ connection_channel := false;
+ if (connection_call or connection_control or connection_channel) {
+ repeat;
+ }
+ Texit.start;
+ repeat;
+ }
+ [] COORD_call.receive {
+ setverdict(fail, "Unhandled COORD_call, please fix!");
+ }
+ [] COORD_control.receive {
+ setverdict(fail, "Unhandled COORD_control, please fix!");
+ }
+ [] COORD_channel.receive {
+ setverdict(fail, "Unhandled COORD_channel, please fix!");
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for Test result");
+ }
+ [] Texit.timeout {
+ log("All connection are cleared now.");
+ }
+ }
+
+ /* Tell the connection handlers to exit. */
+ COORD_call.send(COORD_CLEAR);
+ COORD_control.send(COORD_CLEAR);
+ COORD_channel.send(COORD_CLEAR);
+
+ vc_conn_call.done;
+ vc_conn_control.done;
+ vc_conn_channel.done;
+
+ if (getverdict == fail) {
+ return;
+ }
+
+ /* Check if the outcome of each test is as expected. */
+ select (test) {
+ case (COORD_TEST_NO_CALLREF) {
+ if (not got_vgcs_setup and
+ not got_vgcs_assign and
+ got_gcc_termination_fail) {
+ setverdict(pass);
+ }
+ }
+ case (COORD_TEST_SETUP_REFUSE) {
+ if (got_vgcs_setup and
+ not got_vgcs_assign and
+ got_gcc_termination_fail) {
+ setverdict(pass);
+ }
+ }
+ case (COORD_TEST_ASSIGN_FAIL) {
+ if (got_vgcs_setup and
+ got_vgcs_assign and
+ got_gcc_termination_fail) {
+ setverdict(pass);
+ }
+ }
+ case (COORD_TEST_COMPLETE_VGCS) {
+ if (got_vgcs_setup and
+ got_vgcs_assign and
+ got_uplink_req_ack and
+ got_gcc_connect and
+ got_gcc_set_param and
+ got_uplink_seized and
+ got_gcc_termination and
+ got_assignment) {
+ setverdict(pass);
+ }
+ }
+ case (COORD_TEST_COMPLETE_VBS) {
+ if (got_vgcs_setup and
+ got_vgcs_assign and
+ not got_uplink_req_ack and
+ got_bcc_connect and
+ got_bcc_set_param and
+ got_uplink_seized and
+ got_bcc_termination and
+ got_assignment) {
+ setverdict(pass);
+ }
+ }
+ case else {
+ setverdict(fail, "Test case has no check for the outcome, please fix! Test was: ", test);
+ }
+ }
+
+ if (getverdict == pass) {
+ log("All expected events have been received. The test passed.");
+ } else {
+ setverdict(fail, "Not all expected event received.");
+ }
+}
+
+/* A call is tried, but the given call reference does not exit. */
+testcase TC_no_callref() runs on asci_CT
+{
+ f_TC_asci_call(COORD_TEST_NO_CALLREF);
+}
+
+/* The VGCS/VBS is refused by the BSC. */
+testcase TC_setup_refuse() runs on asci_CT
+{
+ f_TC_asci_call(COORD_TEST_SETUP_REFUSE);
+}
+
+/* The VGCS/VBS channel is refused by the BSC. */
+testcase TC_assign_fail() runs on asci_CT
+{
+ f_TC_asci_call(COORD_TEST_ASSIGN_FAIL);
+}
+
+/* The VGCS call is completed and the MS releases and requests the uplink again. Then it terminates the call. */
+testcase TC_complete_vgcs() runs on asci_CT
+{
+ f_TC_asci_call(COORD_TEST_COMPLETE_VGCS);
+}
+
+/* The VBS call is completed and the MS terminates the call. */
+testcase TC_complete_vbs() runs on asci_CT
+{
+ f_TC_asci_call(COORD_TEST_COMPLETE_VBS);
+}
+
+control {
+ execute( TC_no_callref() );
+ execute( TC_setup_refuse() );
+ execute( TC_assign_fail() );
+ execute( TC_complete_vgcs() );
+ execute( TC_complete_vbs() );
+}
+
+}
diff --git a/msc/expected-results.xml b/msc/expected-results.xml
index 93d24c09..aad96a7c 100644
--- a/msc/expected-results.xml
+++ b/msc/expected-results.xml
@@ -1,8 +1,9 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='179' failures='4' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='203' failures='6' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='MSC_Tests' name='TC_cr_before_reset' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_noauth_tmsi' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_noauth_notmsi' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_tmsi_noauth_notmsi' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_reject' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_timeout_gsup' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi' time='MASKED'/>
@@ -14,14 +15,19 @@
</failure>
</testcase>
<testcase classname='MSC_Tests' name='TC_cmserv_imsi_unknown' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_cmserv_tmsi_unknown' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mo_call' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_and_mo_call_ipv6' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mo_call_sccp_tiar_timeout' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_auth_sai_timeout' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_auth_sai_err' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_clear_request' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_mo_call_clear_request' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_mt_call_clear_request' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_disconnect' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_by_imei' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_by_tmsi_noauth_unknown' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_attached_imsi_lu_unknown_tmsi' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_imsi_detach_by_imsi' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_imsi_detach_by_tmsi' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_imsi_detach_by_imei' time='MASKED'/>
@@ -41,6 +47,7 @@
<testcase classname='MSC_Tests' name='TC_mo_crcx_ran_reject' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_mt_crcx_ran_reject' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_mo_setup_and_dtmf_dup' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_mt_t310' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_gsup_cancel' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_1_13' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_3_13' time='MASKED'/>
@@ -48,11 +55,16 @@
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_3_1_no_cm' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_13_2' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_013_2' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_0134_1' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_0134_34' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_0134_34_no_cm3' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_mo_release_timeout' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mt_call_no_dlcx_resp' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_reset_two' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mt_call' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_and_mt_call_ipv6' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mt_call_already_paging' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_and_mt_call_osmux' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mo_sms' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mt_sms' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_mt_sms_already_paging' time='MASKED'/>
@@ -110,7 +122,17 @@
<testcase classname='MSC_Tests' name='TC_sgsap_vlr_failure' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_ho_inter_bsc_unknown_cell' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_ho_inter_bsc' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_bsc_a5_1' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_bsc_a5_3' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_bsc_a5_4' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_bsc_ipv6' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_bsc_csd' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_ho_inter_msc_out' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_msc_out_a5_1' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_msc_out_a5_3' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_msc_out_a5_4' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_msc_out_ipv6' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_ho_inter_msc_out_csd' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_check_imei' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth3g_tmsi_check_imei' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_noauth_tmsi_check_imei' time='MASKED'/>
@@ -125,10 +147,30 @@
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_check_imei_early_err' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_imsi_auth_tmsi_encr_3_1_log_msc_debug' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_mo_cc_bssmap_clear' time='MASKED'/>
- <testcase classname='MSC_Tests' name='TC_lu_and_mt_call_osmux' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_invalid_mgcp_crash' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_mm_id_resp_no_identity' time='MASKED'/>
<testcase classname='MSC_Tests' name='TC_lu_and_expire_while_paging' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_paging_response_imsi_unknown' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_paging_response_tmsi_unknown' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_call_re_establishment' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_call_re_establishment_auth' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_call_re_establishment_ciph' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_cm_serv_wrong_mi' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_0' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_1' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_2' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_3' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_4' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_5' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_6' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_7' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_8' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_9' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_10' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_auth_options_11' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_and_mo_csd' time='MASKED'/>
+ <testcase classname='MSC_Tests' name='TC_lu_and_mt_csd' time='MASKED'/>
+ <!-- MSC_Tests_Iu testcases start here -->
<testcase classname='MSC_Tests_Iu' name='TC_iu_lu_imsi_reject' time='MASKED'/>
<testcase classname='MSC_Tests_Iu' name='TC_iu_lu_imsi_timeout_gsup' time='MASKED'/>
<testcase classname='MSC_Tests_Iu' name='TC_iu_lu_imsi_auth3g_tmsi' time='MASKED'/>
@@ -196,7 +238,18 @@
<testcase classname='MSC_Tests_Iu' name='TC_iu_proc_ss_abort' time='MASKED'/>
<testcase classname='MSC_Tests_Iu' name='TC_iu_multi_lu_and_mo_ussd' time='MASKED'/>
<testcase classname='MSC_Tests_Iu' name='TC_iu_multi_lu_and_mt_ussd' time='MASKED'/>
- <testcase classname='MSC_Tests_Iu' name='TC_iu_lu_with_invalid_mcc_mnc' time='MASKED'/>
+ <testcase classname='MSC_Tests_Iu' name='TC_iu_lu_with_invalid_mcc_mnc' time='MASKED'>
+ <failure type='fail-verdict'>Tguard timeout
+ MSC_Tests_Iu.ttcn:MASKED MSC_Tests_Iu control part
+ MSC_Tests_Iu.ttcn:MASKED TC_iu_lu_with_invalid_mcc_mnc testcase
+ </failure>
+ </testcase>
<testcase classname='MSC_Tests_Iu' name='TC_iu_lu_and_expire_while_paging' time='MASKED'/>
<testcase classname='MSC_Tests_Iu' name='TC_mo_cc_iu_release' time='MASKED'/>
+ <!-- MSC_Tests_ASCI testcases start here -->
+ <testcase classname='MSC_Tests_ASCI' name='TC_no_callref' time='MASKED'/>
+ <testcase classname='MSC_Tests_ASCI' name='TC_setup_refuse' time='MASKED'/>
+ <testcase classname='MSC_Tests_ASCI' name='TC_assign_fail' time='MASKED'/>
+ <testcase classname='MSC_Tests_ASCI' name='TC_complete_vgcs' time='MASKED'/>
+ <testcase classname='MSC_Tests_ASCI' name='TC_complete_vbs' time='MASKED'/>
</testsuite>
diff --git a/msc/gen_links.sh b/msc/gen_links.sh
index 221110ea..a15c42d7 100755
--- a/msc/gen_links.sh
+++ b/msc/gen_links.sh
@@ -11,6 +11,7 @@ gen_links $DIR $FILES
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 " # GSM 7-bit coding
+FILES+=" TCCOpenSecurity_Functions.ttcn TCCOpenSecurity.cc TCCOpenSecurity_Functions.hh"
gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
@@ -92,9 +93,10 @@ gen_links $DIR $FILES
DIR=../library
FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn MNCC_Types.ttcn MNCC_EncDec.cc MNCC_CodecPort.ttcn mncc.h MNCC_Emulation.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "
-FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc GSUP_Types.ttcn GSUP_Emulation.ttcn "
+FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc "
+FILES+="PCO_Types.ttcn GSUP_Types.ttcn GSUP_Templates.ttcn GSUP_Emulation.ttcn "
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn L3_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn L3_Common.ttcn "
-FILES+="RAN_Emulation.ttcnpp BSSAP_CodecPort.ttcn BSSMAP_Templates.ttcn RAN_Adapter.ttcnpp MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_Emulation.ttcn "
+FILES+="RAN_Emulation.ttcnpp BSSAP_CodecPort.ttcn BSSMAP_Templates.ttcn RAN_Adapter.ttcnpp SDP_Templates.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_Emulation.ttcn "
FILES+="RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunctDef.cc "
FILES+="MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunctDef.cc "
FILES+="SMPP_CodecPort.ttcn SMPP_CodecPort_CtrlFunct.ttcn SMPP_CodecPort_CtrlFunctDef.cc SMPP_Emulation.ttcn SMPP_Templates.ttcn "
diff --git a/msc/osmo-msc.cfg b/msc/osmo-msc.cfg
index ddac4cd0..a886565d 100644
--- a/msc/osmo-msc.cfg
+++ b/msc/osmo-msc.cfg
@@ -4,10 +4,15 @@
!
log stderr
logging filter all 1
- logging color 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging level all everything
+ logging color 1
+!
+ logging level set-all notice
logging level rll notice
logging level cc debug
logging level mm debug
@@ -24,23 +29,6 @@ log stderr
logging level ranap debug
logging level vlr debug
logging level iucs debug
- logging level lglobal notice
- logging level llapd notice
- logging level linp notice
- logging level lmux notice
- logging level lmi notice
- logging level lmib notice
- logging level lsms notice
- logging level lctrl info
- logging level lgtp notice
- logging level lstats notice
- logging level lgsup notice
- logging level loap notice
- logging level lss7 notice
- logging level lsccp notice
- logging level lsua notice
- logging level lm3ua notice
- logging level lmgcp debug
!
stats interval 5
!
@@ -54,24 +42,27 @@ cs7 instance 0
point-code 0.23.1
asp asp-clnt-OsmoMSC-A 2905 0 m3ua
remote-ip 127.0.0.1
+ role asp
+ sctp-role client
as as-clnt-OsmoMSC-A m3ua
asp asp-clnt-OsmoMSC-A
- routing-key 2 0.23.1
+ routing-key 3 0.23.1
network
network country code 262
mobile network code 42
short name OsmoMSC
long name OsmoMSC
encryption a5 0
+ encryption uea 0
authentication optional
rrlp mode none
mm info 0
- periodic location update 30
+ mgw 0
+ remote-ip 127.0.0.1
msc
assign-tmsi
cs7-instance-a 0
cs7-instance-iu 0
- mgw remote-ip 127.0.0.1
emergency-call route-to-msisdn 112
mncc external /tmp/mncc.sock
mncc-int
@@ -86,3 +77,4 @@ smpp
hlr
remote-ip 127.0.0.1
#remote-port 4222
+ ipa-name test-MSC
diff --git a/msc/osmo-stp.cfg b/msc/osmo-stp.cfg
index 17e611a5..772b6d17 100644
--- a/msc/osmo-stp.cfg
+++ b/msc/osmo-stp.cfg
@@ -4,27 +4,19 @@
!
log stderr
logging filter all 1
- logging color 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 1
- logging level all everything
- logging level lglobal notice
- logging level llapd notice
- logging level linp notice
- logging level lmux notice
- logging level lmi notice
- logging level lmib notice
- logging level lsms notice
- logging level lctrl notice
- logging level lgtp notice
- logging level lstats notice
- logging level lgsup notice
- logging level loap notice
+ logging color 1
+!
+ logging level set-all notice
logging level lss7 debug
logging level lsccp debug
logging level lsua debug
logging level lm3ua debug
- logging level lmgcp notice
!
line vty
no login
@@ -34,18 +26,31 @@ cs7 instance 0
asp virt-bsc0-0 23906 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as virt-bsc0 m3ua
asp virt-bsc0-0
routing-key 0 0.24.1
asp virt-bsc1-0 23907 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as virt-bsc1 m3ua
asp virt-bsc1-0
routing-key 1 0.24.2
+ asp virt-rnc0-0 23908 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-rnc0 m3ua
+ asp virt-rnc0-0
+ routing-key 2 0.24.3
route-table system
update route 0.24.1 7.255.7 linkset virt-bsc0
update route 0.24.2 7.255.7 linkset virt-bsc1
+ update route 0.24.3 7.255.7 linkset virt-rnc0
listen m3ua 2905
accept-asp-connections dynamic-permitted
listen ipa 5000
diff --git a/msc/regen_makefile.sh b/msc/regen_makefile.sh
index 9278530e..081d2cba 100755
--- a/msc/regen_makefile.sh
+++ b/msc/regen_makefile.sh
@@ -1,9 +1,49 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc SCTPasp_PT.cc TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc RTP_CodecPort_CtrlFunctDef.cc MGCP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc SMPP_EncDec.cc SMPP_CodecPort_CtrlFunctDef.cc MAP_EncDec.cc SS_EncDec.cc TCCEncoding.cc SGsAP_CodecPort_CtrlFunctDef.cc RANAP_EncDec.cc *.c *.asn"
+NAME=MSC_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_MGCP -DIPA_EMULATION_CTRL -DIPA_EMULATION_GSUP -DIPA_EMULATION_SCCP -DRAN_EMULATION_BSSAP -DRAN_EMULATION_MGCP -DRAN_EMULATION_CTRL -DRAN_EMULATION_RANAP -DUSE_MTP3_DISTRIBUTOR"
+FILES="
+ *.asn
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ MAP_EncDec.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ MNCC_EncDec.cc
+ Native_FunctionDefs.cc
+ RANAP_EncDec.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SCCP_EncDec.cc
+ SCTPasp_PT.cc
+ SDP_EncDec.cc
+ SGsAP_CodecPort_CtrlFunctDef.cc
+ SMPP_CodecPort_CtrlFunctDef.cc
+ SMPP_EncDec.cc
+ SS_EncDec.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TCCOpenSecurity.cc
+ TELNETasp_PT.cc
+ UD_PT.cc
+"
-../regen-makefile.sh MSC_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_GSUP
+ -DIPA_EMULATION_MGCP
+ -DIPA_EMULATION_SCCP
+ -DRAN_EMULATION_BSSAP
+ -DRAN_EMULATION_CTRL
+ -DRAN_EMULATION_MGCP
+ -DRAN_EMULATION_RANAP
+ -DUSE_MTP3_DISTRIBUTOR
+"
-sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp -lfftranscode -lssl/' Makefile
diff --git a/ns/NS_Tests.default b/ns/NS_Tests.default
new file mode 100644
index 00000000..1c61bec8
--- /dev/null
+++ b/ns/NS_Tests.default
@@ -0,0 +1,26 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+
+[LOGGING]
+#*.FileMask := LOG_ALL
+ConsoleMask := ERROR | WARNING | TESTCASE | TIMEROP_START | USER
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoNSdummy";
+
+[TESTPORT_PARAMETERS]
+*.NSVTY.CTRL_MODE := "client"
+*.NSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.NSVTY.CTRL_PORTNUM := "4240"
+*.NSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.NSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.NSVTY.CTRL_READMODE := "buffered"
+*.NSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.NSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.NSVTY.PROMPT1 := "OsmoNSdummy> "
+*.STATSVTY.PROMPT1 := "OsmoNSdummy> "
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
diff --git a/ns/NS_Tests.fr.cfg b/ns/NS_Tests.fr.cfg
new file mode 100644
index 00000000..5e387a90
--- /dev/null
+++ b/ns/NS_Tests.fr.cfg
@@ -0,0 +1,57 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./NS_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+NS_Tests.mp_dialect := NS2_DIALECT_STATIC_RESETBLOCK
+NS_Tests.mp_nsconfig := {
+ nsei := 2001,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ fr := {
+ netdev := "hdlc1",
+ dlci := 16
+ }
+ },
+ nsvci := 1
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc2",
+ dlci := 17
+ }
+ },
+ nsvci := 2
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc3",
+ dlci := 18
+ }
+ },
+ nsvci := 3
+ }, {
+ provider := {
+ fr := {
+ netdev := "hdlc4",
+ dlci := 19
+ }
+ },
+ nsvci := 4
+ }
+ }
+}
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+NS_Tests.control
diff --git a/ns/NS_Tests.sgsn.sns.cfg b/ns/NS_Tests.sgsn.sns.cfg
new file mode 100644
index 00000000..360d9f9b
--- /dev/null
+++ b/ns/NS_Tests.sgsn.sns.cfg
@@ -0,0 +1,47 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./NS_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+NS_Tests.mp_nsconfig := {
+ nsei := 1234,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23000
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23001
+ }
+ },
+ nsvci := 1235
+ }
+ }
+}
+NS_Tests.mp_dialect := NS2_DIALECT_SNS
+NS_Tests.mp_sns_role := SNS_ROLE_SGSN;
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+NS_Tests.control
diff --git a/ns/NS_Tests.sns.cfg b/ns/NS_Tests.sns.cfg
new file mode 100644
index 00000000..5ee5e1a0
--- /dev/null
+++ b/ns/NS_Tests.sns.cfg
@@ -0,0 +1,46 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./NS_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+NS_Tests.mp_nsconfig := {
+ nsei := 1234,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23000
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23001
+ }
+ },
+ nsvci := 1235
+ }
+ }
+}
+NS_Tests.mp_dialect := NS2_DIALECT_SNS
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+NS_Tests.control
diff --git a/ns/NS_Tests.ttcn b/ns/NS_Tests.ttcn
new file mode 100644
index 00000000..722f8ecc
--- /dev/null
+++ b/ns/NS_Tests.ttcn
@@ -0,0 +1,1105 @@
+module NS_Tests {
+
+/* Osmocom NS test suite for NS over framerelay or udp ip.access style in TTCN-3
+ * (C) 2021 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Alexander Couzens <lynxis@fe80.eu>
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+import from NS_Types all;
+import from BSSGP_Types all;
+import from UD_Types all;
+import from NS_Emulation all;
+import from Native_Functions all;
+import from IPL4asp_Types all;
+import from RAW_NS all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+type enumerated SnsRole {
+ SNS_ROLE_BSS ('00'H),
+ SNS_ROLE_SGSN ('01'H)
+};
+
+modulepar {
+ SnsRole mp_sns_role := SNS_ROLE_BSS;
+ OsmoNsDialect mp_dialect := NS2_DIALECT_IPACCESS;
+ NSConfiguration mp_nsconfig := {
+ nsei := 96,
+ role_sgsn := false,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21000,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 2,
+ signalling_weight := 2
+ }
+ },
+ nsvci := 97
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21000,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 23001,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 98
+ }
+ }
+ };
+}
+
+type component RAW_Test_CT extends RAW_NS_CT {
+ port TELNETasp_PT NSVTY;
+}
+
+private function f_init_vty() runs on RAW_Test_CT {
+ map(self:NSVTY, system:NSVTY);
+ f_vty_set_prompts(NSVTY);
+ f_vty_transceive(NSVTY, "enable");
+ f_vty_config2(NSVTY, {}, "mirror-mode disable");
+ f_vty_transceive(NSVTY, "nsvc nsei " & int2str(mp_nsconfig.nsei) & " force-unconfigured");
+ if (mp_dialect == NS2_DIALECT_SNS) {
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(mp_nsconfig.nsei)}, "ip-sns-bind local");
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(mp_nsconfig.nsei)}, "no ip-sns-bind local2");
+ f_vty_config2(NSVTY, {"ns", "bind udp local"}, "ip-sns signalling-weight 1 data-weight 1");
+ f_vty_config2(NSVTY, {"ns", "bind udp local2"}, "ip-sns signalling-weight 1 data-weight 1");
+ }
+}
+
+/* ensure no matching message is received within 'tout' */
+function f_ensure_no_ns(integer idx := 0, boolean answer_alive := false, float tout := 3.0)
+runs on RAW_Test_CT {
+ var PDU_NS nrf;
+
+ timer T := tout;
+ var default d := activate(ax_rx_fail_on_any_ns(idx));
+ T.start;
+ alt {
+ [answer_alive] as_rx_alive_tx_ack();
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+ deactivate(d);
+}
+
+function f_fails_except_reset(integer idx := 0, float tout := 15.0)
+runs on RAW_Test_CT {
+ var PDU_NS nrf;
+ timer T := 15.0;
+ T.start;
+ alt {
+ [] NSCP[idx].receive(tr_NS_RESET(*, *, *)) {
+ repeat;
+ }
+ [] NSCP[idx].receive(PDU_NS: ?) -> value nrf {
+ setverdict(fail, "Received unexpected NS: ", nrf);
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+}
+
+testcase TC_tx_reset() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 10.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+testcase TC_tx_reset_tx_alive() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 10.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+
+ /* check outgoing NS procedure */
+ f_outgoing_ns_alive();
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+testcase TC_tx_reset_rx_alive() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 10.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+
+ activate(as_rx_ns_unblock_ack());
+ /* check outgoing NS procedure */
+ as_rx_alive_tx_ack(oneshot := true);
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2.1 transmit a UNIT DATA over a BLOCKED NSVC when ttcn3 blocked it
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: block
+ * TTCN <- NS: block ack
+ * TTCN -> NS: unitdata
+ * TTCN <- NS: status (cause blocked)
+ */
+testcase TC_tx_block_unitdata_over_blocked() runs on RAW_Test_CT {
+ f_tx_block();
+ f_sleep(1.0);
+
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_ns_exp(tr_NS_STATUS(NS_CAUSE_NSVC_BLOCKED));
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2.1 transmit a UNIT DATA over a BLOCKED NSVC when ns2 blocked it
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN <- NS: block
+ * TTCN -> NS: block ack
+ * TTCN -> NS: unitdata
+ * TTCN <- NS: status (cause blocked)
+ */
+testcase TC_rx_block_unitdata_over_blocked() runs on RAW_Test_CT {
+ f_tx_block_by_vty();
+ f_sleep(1.0);
+
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_ns_exp(tr_NS_STATUS(NS_CAUSE_NSVC_BLOCKED));
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 unblock procedure
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ */
+function f_tx_unblock() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+ /* send alive acks */
+ activate(as_rx_alive_tx_ack());
+
+ f_outgoing_ns_unblock();
+ setverdict(pass);
+}
+
+testcase TC_tx_unblock() runs on RAW_Test_CT {
+ f_tx_unblock();
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 tx unblock retries
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ */
+testcase TC_tx_unblock_retries() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+ /* send alive acks */
+ activate(as_rx_alive_tx_ack());
+
+ f_outgoing_ns_unblock();
+ f_outgoing_ns_unblock();
+ f_outgoing_ns_unblock();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 block procedure
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: block
+ * TTCN <- NS: block ack
+ */
+function f_tx_block(float guard_secs := 30.0) runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := guard_secs);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+ activate(as_rx_alive_tx_ack());
+
+ f_outgoing_ns_unblock();
+ f_sleep(1.0);
+
+ f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
+ setverdict(pass);
+ f_sleep(1.0);
+}
+
+testcase TC_tx_block() runs on RAW_Test_CT {
+ f_tx_block()
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 block procedure by vty
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * vty: block nsvc
+ * TTCN <- NS: block
+ * TTCN -> NS: block ack
+ */
+function f_tx_block_by_vty(float guard_secs := 30.0) runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := guard_secs);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+ activate(as_rx_alive_tx_ack());
+
+ f_outgoing_ns_unblock();
+ f_sleep(1.0);
+
+ f_vty_transceive(NSVTY, "nsvc " & int2str(mp_nsconfig.nsvc[0].nsvci) & " block");
+
+ alt {
+ [] as_rx_ns_block_ack(oneshot := true, nsvci := mp_nsconfig.nsvc[0].nsvci);
+ }
+ setverdict(pass);
+}
+
+testcase TC_tx_block_by_vty() runs on RAW_Test_CT {
+ f_tx_block_by_vty(30.0);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 block precedure by vty and reset the NSVC.
+ * The NSVC should be still blocked after the reset.
+ */
+testcase TC_tx_block_by_vty_reset() runs on RAW_Test_CT {
+ timer T := 10.0;
+
+ f_tx_block_by_vty(60.0);
+ f_outgoing_ns_reset();
+
+ var default d := activate(ax_rx_fail_on_any_ns());
+ T.start;
+ alt {
+ [] as_rx_alive_tx_ack();
+ [] T.timeout { setverdict(pass); }
+ }
+ deactivate(d);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.4.1 ignore unexpected NS_ALIVE ACK */
+testcase TC_no_reset_alive_ack() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].send(t_NS_ALIVE_ACK);
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET with wrong nsei */
+testcase TC_reset_wrong_nsei() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].send(ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei + 20));
+ NSCP[0].receive(tr_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET with wrong nsvci */
+testcase TC_reset_wrong_nsvci() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].send(ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig.nsvc[0].nsvci + 20, g_nsconfig.nsei));
+ NSCP[0].receive(tr_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET with wrong nsvci + nsei */
+testcase TC_reset_wrong_nsei_nsvci() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].send(ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig.nsvc[0].nsvci + 20, g_nsconfig.nsei + 20));
+ NSCP[0].receive(tr_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET_ACK with wrong nsei */
+testcase TC_reset_ack_wrong_nsei() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].receive(tr_NS_RESET(*, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ NSCP[0].send(ts_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei + 20));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET_ACK with wrong nsvci */
+testcase TC_reset_ack_wrong_nsvci() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].receive(tr_NS_RESET(*, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ NSCP[0].send(ts_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci + 20, g_nsconfig.nsei));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 NS_RESET_ACK with wrong nsvci + nsei */
+testcase TC_reset_ack_wrong_nsei_nsvci() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ NSCP[0].receive(tr_NS_RESET(*, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ NSCP[0].send(ts_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci + 20, g_nsconfig.nsei + 20));
+ f_fails_except_reset();
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3.1 ignore unexpected NS_RESET_ACK after NS_RESET+ALIVE */
+testcase TC_ignore_reset_ack() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+
+ /* unblock and alive */
+ alt {
+ [] as_rx_ns_unblock_ack(oneshot := true);
+ [] as_rx_alive_tx_ack();
+ }
+
+ NSCP[0].send(ts_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ f_ensure_no_ns(answer_alive := true, tout := 15.0);
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.3 NS_RESET retries */
+testcase TC_reset_retries() runs on RAW_Test_CT {
+ var integer reset := 0;
+
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ alt {
+ [] NSCP[0].receive(tr_NS_RESET(*, *, *)) {
+ reset := reset + 1;
+ if (reset <= 3) {
+ repeat;
+ } else {
+ setverdict(pass);
+ }
+ }
+ }
+
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 behave RESET_ACK got dropped
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN <- NS: unblock
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN <- NS: unblock
+ */
+testcase TC_reset_on_block_reset() runs on RAW_Test_CT {
+ var integer i := 0;
+
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ f_outgoing_ns_reset();
+ activate(as_rx_alive_tx_ack());
+
+ alt {
+ [] NSCP[0].receive(t_NS_UNBLOCK) {
+ NSCP[0].send(ts_NS_RESET(NS_CAUSE_EQUIPMENT_FAILURE, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ i := i + 1;
+ if (i < 3) {
+ repeat;
+ } else {
+ setverdict(pass);
+ }
+ }
+ [] NSCP[0].receive(tr_NS_RESET_ACK(g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei)) { repeat; }
+ }
+
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.4 test procedure for frame relay with a single nsvci */
+function f_alive_retries_single(boolean reset := false) runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 60.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+
+ alt {
+ [] as_rx_ns_unblock_ack(oneshot := true);
+ [] as_rx_alive_tx_ack();
+ }
+
+ /* wait for one alive and answer it */
+ as_rx_alive_tx_ack(oneshot := true);
+ NSCP[0].receive(t_NS_ALIVE);
+ NSCP[0].receive(t_NS_ALIVE);
+ NSCP[0].receive(t_NS_ALIVE);
+ NSCP[0].receive(t_NS_ALIVE);
+ if (reset) {
+ NSCP[0].receive(tr_NS_RESET(*, g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
+ } else {
+ f_ensure_no_ns(tout := 10.0);
+ }
+
+ setverdict(pass);
+ f_sleep(1.0);
+}
+
+testcase TC_alive_retries_single_reset() runs on RAW_Test_CT {
+ f_alive_retries_single(reset := true);
+ f_clean_ns_codec();
+}
+
+testcase TC_alive_retries_single_no_resp() runs on RAW_Test_CT {
+ f_alive_retries_single(reset := false);
+ f_clean_ns_codec();
+}
+
+/* 48.016 SNS test cases */
+
+/* do a succesful SNS configuration */
+testcase TC_sns_bss_config_success() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_bss_change_weight() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "bind udp local"}, "ip-sns signalling-weight 99 data-weight 99");
+ f_incoming_sns_chg_weight();
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* receive 3x SNS_CHG_WEIGHT but never answer on it */
+testcase TC_sns_bss_change_weight_timeout() runs on RAW_Test_CT {
+ var integer i := 0;
+ var template PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg;
+
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "bind udp local"}, "ip-sns signalling-weight 99 data-weight 99");
+
+ nsvc_cfg := g_nsconfig.nsvc[0];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template IP4_Elements v4_elem := { tr_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+
+ rx := tr_SNS_CHG_WEIGHT(g_nsconfig.nsei, ?, v4 := v4_elem);
+ } else {
+ var template IP6_Elements v6_elem := { tr_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port) };
+ rx := tr_SNS_CHG_WEIGHT(g_nsconfig.nsei, ?, v4 := omit, v6 := v6_elem);
+ }
+
+ for (i := 0; i < 3; i := i + 1) {
+ f_ns_exp(rx);
+ }
+
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ /* expect one single SNS-SIZE with RESET flag; 4x v4 EP; no v6 EP */
+ rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := ?,
+ num_v4 := ?, num_v6 := omit), 0);
+ } else {
+ /* expect one single SNS-SIZE with RESET flag; no v4 EP; 4x v6 EP */
+ rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig.nsei, rst_flag := true, max_nsvcs := ?,
+ num_v4 := omit, num_v6 := ?), 0);
+ }
+
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_bss_add() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1);
+ as_rx_alive_tx_ack(oneshot := true, idx := 1);
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_bss_del() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1);
+ as_rx_alive_tx_ack(oneshot := true, idx := 1);
+
+ /* delete the endpoint */
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "no ip-sns-bind local2");
+ f_incoming_sns_del(idx_del := 1);
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* 1. do SNS configuration
+ * 2. add a bind
+ * 3. receive the SNS_ADD
+ * 4. before answering the SNS_ADD, change the weight via vty and remove the bind
+ */
+testcase TC_sns_bss_add_change_del() runs on RAW_Test_CT {
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg;
+
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+
+ /* rx SNS ADD */
+ nsvc_cfg := g_nsconfig.nsvc[1];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4_elem := { ts_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ 1, 1) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, v4 := v4_elem), 0);
+ } else {
+ var template (omit) IP6_Elements v6_elem := { ts_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ 1, 1) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, omit, v6_elem), 0);
+ }
+
+ /* delete the endpoint */
+ f_vty_config2(NSVTY, {"ns", "bind udp local2"}, "ip-sns signalling-weight 99 data-weight 99");
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "no ip-sns-bind local2");
+
+ /* accept the SNS_ADD */
+ NSCP[0].send(ts_SNS_ACK(g_nsconfig.nsei, rx.pDU_SNS_Add.transactionID));
+
+ f_incoming_sns_chg_weight(idx_chg := 1);
+ f_incoming_sns_del(idx_del := 1, w_sig := 99, w_user := 99);
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Ensure the ns2 code doesn't crash when calling force unconfigured while sending SNS SIZE */
+testcase TC_sns_rx_size_force_unconf() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_ns_exp(tr_SNS_SIZE(mp_nsconfig.nsei, rst_flag := true, max_nsvcs := ?,
+ num_v4 := ?, num_v6 := omit));
+ f_vty_transceive(NSVTY, "nsvc nsei " & int2str(mp_nsconfig.nsei) & " force-unconfigured");
+ f_ns_exp(tr_SNS_SIZE(mp_nsconfig.nsei, rst_flag := true, max_nsvcs := ?,
+ num_v4 := ?, num_v6 := omit));
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Test if SNS fails when all signalling NSVCs failes
+ * 3GPP TS 48.016 § 7.4b.1.1
+ * 1. do success SNS configuration
+ * 2. change sig weight of the seconds inactive bind
+ * 3. add second bind to SNS
+ * 4. stop reacting to NS_ALIVE on first NSVC (only NSVC with sig weight)
+ * 5. expect SNS SIZE
+ *
+ * Broken: the test case tests the wrong side. The signalling
+ * and data weight are valid for the other side. The correct
+ * test case needs to add a second bind on the ttcn3 side.
+ */
+testcase TC_sns_bss_all_signalling_nsvcs_failed() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ var default d := activate(as_rx_alive_tx_ack());
+
+ f_vty_config2(NSVTY, {"ns", "bind udp local2"}, "ip-sns signalling-weight 0 data-weight 99");
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1, w_sig := 0, w_user := 99);
+ as_rx_alive_tx_ack(oneshot := true, idx := 1);
+ activate(as_rx_alive_tx_ack(idx := 1));
+ /* 2x NSVCs up, stop first NSVC */
+ deactivate(d);
+ /* libosmocore will rotate the SNS binds on failure */
+ NSCP[0].receive(t_NS_ALIVE);
+ NSCP[0].receive(t_NS_ALIVE);
+ NSCP[0].receive(t_NS_ALIVE);
+ f_incoming_sns_size(idx := 1);
+
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Test if SNS fails when removing a bind which has the last valid connection
+ *
+ * ns2 has 2 binds, ttcn3 1 bind.
+ *
+ * nsvcs:
+ * ns2 ttcn3
+ * 1*-----------*1
+ * /
+ * 2*-broken--/
+ *
+ * remove the 1st ns2 bind.
+ */
+testcase TC_sns_bss_remove_bind_fail_sns() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+ var default d := activate(as_rx_alive_tx_ack());
+
+ f_vty_config2(NSVTY, {"ns", "bind udp local2"}, "ip-sns signalling-weight 1 data-weight 1");
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1, w_sig := 1, w_user := 1);
+ /* 2nd bind won't have a valid connection to the ttcn3 */
+ NSCP[1].receive(t_NS_ALIVE);
+ NSCP[1].receive(t_NS_ALIVE);
+ NSCP[1].receive(t_NS_ALIVE);
+ NSCP[1].receive(t_NS_ALIVE);
+ NSCP[1].receive(t_NS_ALIVE);
+ f_sleep(1.0);
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "no ip-sns-bind local");
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_idle() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig, guard_secs := 30.0);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset();
+ activate(as_rx_alive_tx_ack());
+
+ f_outgoing_ns_unblock();
+ f_sleep(30.0);
+
+ setverdict(pass);
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_sgsn_config_success() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Ensure a SIZE after a success full configuration is handled */
+testcase TC_sns_sgsn_size_after_success() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ NSCP[0].receive(t_NS_ALIVE);
+
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Ensure a SNS SIZE ACK is transmitted from the correct port */
+testcase TC_sns_sgsn_size_correct_port() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_outgoing_sns_size(max_nsvcs := 10);
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ NSCP[0].receive(t_NS_ALIVE);
+ f_outgoing_sns_size(max_nsvcs := 10, idx := 1);
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_sgsn_add() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_outgoing_sns_size(max_nsvcs := 4, num_ip := 4);
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ activate(as_rx_alive_tx_ack());
+
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1);
+ as_rx_alive_tx_ack(oneshot := true, idx := 1);
+
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+testcase TC_sns_sgsn_del() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_outgoing_sns_size(max_nsvcs := 4, num_ip := 4);
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ activate(as_rx_alive_tx_ack());
+
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+ f_incoming_sns_add(idx_add := 1);
+ as_rx_alive_tx_ack(oneshot := true, idx := 1);
+
+ /* delete the endpoint */
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "no ip-sns-bind local2");
+ f_incoming_sns_del(idx_del := 1);
+
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* 1. do SNS configuration
+ * 2. add a bind
+ * 3. receive the SNS_ADD
+ * 4. before answering the SNS_ADD, change the weight via vty and remove the bind
+ */
+testcase TC_sns_sgsn_add_change_del() runs on RAW_Test_CT {
+ var PDU_NS rx;
+ var NSVCConfiguration nsvc_cfg;
+
+ g_handle_rx_alive := true;
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_outgoing_sns_size(max_nsvcs := 4, num_ip := 4);
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ activate(as_rx_alive_tx_ack());
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "ip-sns-bind local2");
+
+ /* rx SNS ADD */
+ nsvc_cfg := g_nsconfig.nsvc[1];
+ if (nsvc_cfg.provider.ip.address_family == AF_INET) {
+ var template (omit) IP4_Elements v4_elem := { ts_SNS_IPv4(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ 1, 1) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, v4 := v4_elem), 0);
+ } else {
+ var template (omit) IP6_Elements v6_elem := { ts_SNS_IPv6(nsvc_cfg.provider.ip.remote_ip,
+ nsvc_cfg.provider.ip.remote_udp_port,
+ 1, 1) };
+ rx := f_ns_exp(tr_SNS_ADD(g_nsconfig.nsei, ?, omit, v6_elem), 0);
+ }
+
+ /* delete the endpoint */
+ f_vty_config2(NSVTY, {"ns", "bind udp local2"}, "ip-sns signalling-weight 99 data-weight 99");
+ f_vty_config2(NSVTY, {"ns", "nse " & int2str(g_nsconfig.nsei)}, "no ip-sns-bind local2");
+
+ /* accept the SNS_ADD */
+ NSCP[0].send(ts_SNS_ACK(g_nsconfig.nsei, rx.pDU_SNS_Add.transactionID));
+
+ f_incoming_sns_chg_weight(idx_chg := 1);
+ f_incoming_sns_del(idx_del := 1, w_sig := 99, w_user := 99);
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 transmit a UNITDATA over an ALIVE connection
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: unitdata
+ * TTCN <- NS: unitdata (mirror)
+ */
+testcase TC_tx_unitdata() runs on RAW_Test_CT {
+ f_tx_unblock();
+
+ f_vty_config2(NSVTY, {}, "mirror-mode enable");
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_ns_exp(tr_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_vty_config2(NSVTY, {}, "mirror-mode disable");
+
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 ensure tx status (blocked) is correctly parsed
+ *
+ * TTCN -> NS: reset
+ * TTCN <- NS: reset ack
+ * TTCN -> NS: unblock
+ * TTCN <- NS: unblock ack
+ * TTCN -> NS: unitdata
+ * TTCN <- NS: unitdata (mirror)
+ * TTCN -> NS: status (blocked)
+ * TTCN -> NS: unitdata
+ * TTCN <- NS: status (blocked)
+ */
+testcase TC_mirror_unitdata_tx_status_blocked() runs on RAW_Test_CT {
+ f_tx_unblock();
+
+ f_vty_config2(NSVTY, {}, "mirror-mode enable");
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ var PDU_NS pdu := f_ns_exp(tr_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+
+ NSCP[0].send(ts_NS_STATUS(NS_CAUSE_NSVC_BLOCKED, pdu));
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_ns_exp(tr_NS_STATUS(NS_CAUSE_NSVC_BLOCKED));
+
+ f_vty_config2(NSVTY, {}, "mirror-mode disable");
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* 48.016 7.2 ensure tx status (blocked) is correctly parsed over a foreign NSVC
+ *
+ * 2x initialize NSVC (RESET/UNBLOCK)
+ * TTCN 0-> NS: block (nsvci 1)
+ * TTCN <-0 NS: block ack (nsvci 1)
+ * TTCN 1-> NS: unit data (nsvci 1)
+ * TTCN <-1 NS: status (blocked)
+ */
+testcase TC_tx_blocked_foreign_nsvc() runs on RAW_Test_CT {
+ f_init_vty();
+ f_vty_config2(NSVTY, {}, "mirror-mode enable");
+ f_init_ns_codec(mp_nsconfig, idx := 0);
+ f_init_ns_codec(mp_nsconfig, idx := 1);
+
+ /* do a NS Reset procedure */
+ f_outgoing_ns_reset(idx := 0);
+ f_outgoing_ns_reset(idx := 1);
+
+ /* send alive acks */
+ activate(as_rx_alive_tx_ack(idx := 0));
+ activate(as_rx_alive_tx_ack(idx := 1));
+
+ f_outgoing_ns_unblock(idx := 0);
+ f_outgoing_ns_unblock(idx := 1);
+
+ /* both NSVC are alive and unblocked */
+ NSCP[0].send(ts_NS_BLOCK(NS_CAUSE_TRANSIT_NETWORK_FAILURE, g_nsconfig.nsvc[1].nsvci));
+ f_ns_exp(tr_NS_BLOCK_ACK(g_nsconfig.nsvc[1].nsvci));
+
+ NSCP[1].send(ts_NS_UNITDATA(t_SduCtrlB, 42, '0011234242230101'O));
+ f_ns_exp(tr_NS_STATUS(NS_CAUSE_NSVC_BLOCKED), idx := 1);
+
+ setverdict(pass);
+ f_clean_ns_codec();
+}
+
+
+control {
+ if (mp_dialect == NS2_DIALECT_STATIC_RESETBLOCK or mp_dialect == NS2_DIALECT_IPACCESS) {
+ execute( TC_tx_reset() );
+
+ /* 48.016 7.2 Block procedure */
+ execute( TC_tx_block() );
+ execute( TC_tx_block_by_vty() );
+ execute( TC_tx_block_by_vty_reset() );
+ execute( TC_tx_block_unitdata_over_blocked() );
+ execute( TC_rx_block_unitdata_over_blocked() );
+ execute( TC_mirror_unitdata_tx_status_blocked() );
+ execute( TC_tx_blocked_foreign_nsvc() );
+ // execute( TC_block_other_nsvc() ); // reset, unblock, sleep(1), block over another nsvci
+ /* 48.016 7.2 Unblock procedure */
+ execute( TC_tx_unblock() );
+ execute( TC_tx_unblock_retries() );
+ // execute( TC_rx_unblock_tx_unblock() ); // wait for an rx unblock pdu, send an unblock pdu, expect unblock ack pdu
+ // execute( TC_unblockable() ); // block a NS-VCI via vty, try block procedure
+
+ /* 48.016 7.2.1 Block Abnormal Condition */
+ /* 48.016 7.2.1 Unblock Abnormal Condition */
+ /* 48.016 7.3.1 Abnormal Condition */
+ execute( TC_reset_wrong_nsei() );
+ execute( TC_reset_wrong_nsvci() );
+ execute( TC_reset_wrong_nsei_nsvci() );
+ execute( TC_reset_ack_wrong_nsei() );
+ execute( TC_reset_ack_wrong_nsvci() );
+ execute( TC_reset_ack_wrong_nsei_nsvci() );
+ execute( TC_reset_retries() );
+ execute( TC_reset_on_block_reset() );
+ execute( TC_ignore_reset_ack() );
+
+ /* 48.016 7.4 Test procedure on frame relay */
+ execute( TC_tx_reset_tx_alive() );
+ execute( TC_tx_reset_rx_alive() );
+
+ /* 48.016 7.4.1 Abnormal Condition */
+ if (mp_dialect == NS2_DIALECT_STATIC_RESETBLOCK) {
+ // execute( TC_alive_retries_multi() ); // check if alive retries works and block over an alive nsvc
+ execute( TC_alive_retries_single_reset() );
+ } else if (mp_dialect == NS2_DIALECT_IPACCESS) {
+ execute( TC_alive_retries_single_no_resp() );
+ }
+
+ execute( TC_no_reset_alive_ack() );
+ execute( TC_tx_unitdata() );
+ }
+
+ if (mp_dialect == NS2_DIALECT_SNS) {
+ if (mp_sns_role == SNS_ROLE_BSS) {
+ /* BSS test cases */
+ execute( TC_sns_bss_config_success() );
+ execute( TC_sns_bss_change_weight() );
+ execute( TC_sns_bss_change_weight_timeout() );
+ execute( TC_sns_bss_add() );
+ execute( TC_sns_bss_del() );
+ execute( TC_sns_bss_add_change_del() );
+ /* execute( TC_sns_bss_all_signalling_nsvcs_failed() ); */
+ execute( TC_sns_rx_size_force_unconf() );
+ execute( TC_sns_bss_remove_bind_fail_sns() );
+ }
+
+ if (mp_sns_role == SNS_ROLE_SGSN) {
+ execute( TC_sns_sgsn_config_success() );
+ execute( TC_sns_sgsn_add() );
+ execute( TC_sns_sgsn_del() );
+ execute( TC_sns_sgsn_add_change_del() );
+ execute( TC_sns_sgsn_size_correct_port() );
+ execute( TC_sns_sgsn_size_after_success() );
+ }
+ }
+}
+
+}
diff --git a/ns/NS_Tests.udp.cfg b/ns/NS_Tests.udp.cfg
new file mode 100644
index 00000000..cdb071df
--- /dev/null
+++ b/ns/NS_Tests.udp.cfg
@@ -0,0 +1,46 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./NS_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+NS_Tests.mp_nsconfig := {
+ nsei := 1234,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23000
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 22001,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 23001
+ }
+ },
+ nsvci := 1235
+ }
+ }
+}
+NS_Tests.mp_dialect := NS2_DIALECT_STATIC_RESETBLOCK
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+NS_Tests.control
diff --git a/ns/expected-results.xml b/ns/expected-results.xml
new file mode 100644
index 00000000..ef0d01f7
--- /dev/null
+++ b/ns/expected-results.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='24' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='NS_Tests' name='TC_tx_reset' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_block' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_block_by_vty' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_block_by_vty_reset' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_block_unitdata_over_blocked' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_rx_block_unitdata_over_blocked' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_mirror_unitdata_tx_status_blocked' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_blocked_foreign_nsvc' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_unblock' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_unblock_retries' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_wrong_nsei' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_wrong_nsvci' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_wrong_nsei_nsvci' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_ack_wrong_nsei' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_ack_wrong_nsvci' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_ack_wrong_nsei_nsvci' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_retries' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_reset_on_block_reset' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_ignore_reset_ack' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_reset_tx_alive' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_reset_rx_alive' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_alive_retries_single_reset' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_no_reset_alive_ack' time='MASKED'/>
+ <testcase classname='NS_Tests' name='TC_tx_unitdata' time='MASKED'/>
+</testsuite>
diff --git a/ns/gen_links.sh b/ns/gen_links.sh
new file mode 100755
index 00000000..8d78ddfd
--- /dev/null
+++ b/ns/gen_links.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+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.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.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.LLC_v7.1.0/src
+FILES="LLC_EncDec.cc LLC_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SNDCP_v7.0.0/src
+FILES="SNDCP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.AF_PACKET/src
+FILES="AF_PACKET_PT.cc AF_PACKET_PT.hh AF_PACKET_PortType.ttcn AF_PACKET_PortTypes.ttcn "
+FILES+="FrameRelay_Types.ttcn FrameRelay_CodecPort.ttcn FrameRelay_Emulation.ttcn Q931_Types.ttcn Q933_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn Osmocom_Types.ttcn "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Provider_FR.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
+FILES+="LLC_Templates.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/ns/osmo-ns.fr.cfg b/ns/osmo-ns.fr.cfg
new file mode 100644
index 00000000..3f941f1b
--- /dev/null
+++ b/ns/osmo-ns.fr.cfg
@@ -0,0 +1,65 @@
+log gsmtap 127.0.0.1
+ logging level set-all debug
+
+log stderr
+ logging filter all 1
+ logging print level 1
+ logging print category 1
+ logging print category-hex 0
+ logging print file basename last
+ logging print extended-timestamp 1
+ logging level set-all debug
+!
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
+
+line vty
+ no login
+ bind 127.0.0.1
+
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 12
+ timer tns-alive 3
+ timer tns-alive-retries 3
+ timer tsns-prov 3
+ timer tsns-size-retries 3
+ timer tsns-config-retries 3
+ bind fr hdlcnet1
+ fr hdlcnet1 frnet
+ bind fr hdlcnet2
+ fr hdlcnet2 frnet
+ bind fr hdlcnet3
+ fr hdlcnet3 frnet
+ bind fr hdlcnet4
+ fr hdlcnet4 frnet
+ bind fr hdlcnet5
+ fr hdlcnet5 frnet
+ bind fr hdlcnet6
+ fr hdlcnet6 frnet
+ bind fr hdlcnet7
+ fr hdlcnet7 frnet
+ bind fr hdlcnet8
+ fr hdlcnet8 frnet
+ nse 2001
+ nsvc fr hdlcnet1 dlci 16 nsvci 1
+ nsvc fr hdlcnet2 dlci 17 nsvci 2
+ nsvc fr hdlcnet3 dlci 18 nsvci 3
+ nsvc fr hdlcnet4 dlci 19 nsvci 4
+ nse 2002
+ nsvc fr hdlcnet5 dlci 20 nsvci 5
+ nsvc fr hdlcnet6 dlci 21 nsvci 6
+ nse 2003
+ nsvc fr hdlcnet7 dlci 22 nsvci 7
+ nsvc fr hdlcnet8 dlci 23 nsvci 8
+
diff --git a/ns/osmo-ns.sgsn.sns.cfg b/ns/osmo-ns.sgsn.sns.cfg
new file mode 100644
index 00000000..bebc87e0
--- /dev/null
+++ b/ns/osmo-ns.sgsn.sns.cfg
@@ -0,0 +1,99 @@
+!
+! OsmoNSdummy (1.4.0.326-f57c-dirty) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 0
+ logging print category-hex 0
+ logging print category 1
+ logging print extended-timestamp 1
+ logging print level 1
+ logging print file basename
+ logging level force-all info
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+log gsmtap 127.0.0.1
+ logging filter all 0
+ logging color 1
+ logging print category-hex 1
+ logging print category 0
+ logging timestamp 0
+ logging print file 1
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+!
+stats reporter statsd
+ disable
+ remote-ip 127.0.0.1
+ remote-port 8125
+ mtu 1024
+ level subscriber
+ prefix TTCN3
+ flush-period 1
+ enable
+stats interval 0
+!
+line vty
+ no login
+!
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 12
+ timer tns-alive 3
+ timer tns-alive-retries 3
+ timer tsns-prov 3
+ timer tsns-size-retries 3
+ timer tsns-config-retries 3
+ bind udp local
+ listen 127.0.0.1 23000
+ ip-sns signalling-weight 2 data-weight 2
+ bind udp local2
+ listen 127.0.0.1 23001
+ ip-sns signalling-weight 1 data-weight 1
+ nse 1234 ip-sns-role-sgsn
+ ip-sns-bind local
+ ip-sns-bind local2
diff --git a/ns/osmo-ns.sns.cfg b/ns/osmo-ns.sns.cfg
new file mode 100644
index 00000000..b342305d
--- /dev/null
+++ b/ns/osmo-ns.sns.cfg
@@ -0,0 +1,101 @@
+!
+! OsmoNSdummy (1.4.0.326-f57c-dirty) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 0
+ logging print category-hex 0
+ logging print category 1
+ logging print extended-timestamp 1
+ logging print level 1
+ logging print file basename
+ logging level force-all info
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+log gsmtap 127.0.0.1
+ logging filter all 0
+ logging color 1
+ logging print category-hex 1
+ logging print category 0
+ logging timestamp 0
+ logging print file 1
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+!
+stats reporter statsd
+ disable
+ remote-ip 127.0.0.1
+ remote-port 8125
+ mtu 1024
+ level subscriber
+ prefix TTCN3
+ flush-period 1
+ enable
+stats interval 0
+!
+line vty
+ no login
+!
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 12
+ timer tns-alive 3
+ timer tns-alive-retries 3
+ timer tsns-prov 3
+ timer tsns-size-retries 3
+ timer tsns-config-retries 3
+ bind udp local
+ listen 127.0.0.1 23000
+ ip-sns signalling-weight 2 data-weight 2
+ accept-ipaccess
+ bind udp local2
+ listen 127.0.0.1 23001
+ ip-sns signalling-weight 1 data-weight 1
+ accept-ipaccess
+ nse 1234
+ ip-sns-remote 127.0.0.1 22000
+ ip-sns-bind local
diff --git a/ns/osmo-ns.udp.cfg b/ns/osmo-ns.udp.cfg
new file mode 100644
index 00000000..b327c32d
--- /dev/null
+++ b/ns/osmo-ns.udp.cfg
@@ -0,0 +1,99 @@
+!
+! OsmoNSdummy (1.4.0.326-f57c-dirty) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 0
+ logging print category-hex 0
+ logging print category 1
+ logging print extended-timestamp 1
+ logging print level 1
+ logging print file basename
+ logging level force-all info
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+log gsmtap 127.0.0.1
+ logging filter all 0
+ logging color 1
+ logging print category-hex 1
+ logging print category 0
+ logging timestamp 0
+ logging print file 1
+ logging level lglobal debug
+ logging level llapd debug
+ logging level linp debug
+ logging level lmux debug
+ logging level lmi debug
+ logging level lmib debug
+ logging level lsms debug
+ logging level lctrl debug
+ logging level lgtp debug
+ logging level lstats debug
+ logging level lgsup debug
+ logging level loap debug
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp debug
+ logging level ljibuf debug
+ logging level lrspro debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp debug
+!
+stats reporter statsd
+ disable
+ remote-ip 127.0.0.1
+ remote-port 8125
+ mtu 1024
+ level subscriber
+ prefix TTCN3
+ flush-period 1
+ enable
+stats interval 0
+!
+line vty
+ no login
+!
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 12
+ timer tns-alive 3
+ timer tns-alive-retries 3
+ timer tsns-prov 3
+ timer tsns-size-retries 3
+ timer tsns-config-retries 3
+ bind udp local
+ listen 127.0.0.1 23000
+ accept-ipaccess
+ bind udp local2
+ listen 127.0.0.1 23001
+ accept-ipaccess
+ nse 1234
+ nsvc ipa local 127.0.0.1 22000 nsvci 1234
+ nsvc ipa local2 127.0.0.1 22001 nsvci 1235
diff --git a/ns/regen_makefile.sh b/ns/regen_makefile.sh
new file mode 100755
index 00000000..ad86d716
--- /dev/null
+++ b/ns/regen_makefile.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+NAME=NS_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ AF_PACKET_PT.cc
+ AF_PACKET_PT.hh
+ BSSGP_EncDec.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ UD_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DBSSGP_EM_L3
+ -DNS_EMULATION_FR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/pcap-client/OPCAP_CLIENT_Tests.cfg b/pcap-client/OPCAP_CLIENT_Tests.cfg
new file mode 100644
index 00000000..3476c2f9
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./OPCAP_CLIENT_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+OPCAP_CLIENT_Tests.control
diff --git a/pcap-client/OPCAP_CLIENT_Tests.default b/pcap-client/OPCAP_CLIENT_Tests.default
new file mode 100644
index 00000000..3fd3ac8d
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.default
@@ -0,0 +1,19 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.VTY.CTRL_MODE := "client"
+*.VTY.CTRL_HOSTNAME := "127.0.0.1"
+*.VTY.CTRL_PORTNUM := "4227"
+*.VTY.CTRL_LOGIN_SKIPPED := "yes"
+*.VTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.VTY.CTRL_READMODE := "buffered"
+*.VTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.VTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.VTY.PROMPT1 := "OsmoPCAPClient> "
+*.TCP.noDelay := "yes" // turn off nagle
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCAPClient"
+
+[EXECUTE]
diff --git a/pcap-client/OPCAP_CLIENT_Tests.ttcn b/pcap-client/OPCAP_CLIENT_Tests.ttcn
new file mode 100644
index 00000000..1efc343b
--- /dev/null
+++ b/pcap-client/OPCAP_CLIENT_Tests.ttcn
@@ -0,0 +1,200 @@
+module OPCAP_CLIENT_Tests {
+
+import from OPCAP_Adapter all;
+import from OPCAP_Types all;
+import from OPCAP_Templates all;
+
+import from IPL4asp_Types all;
+import from IPL4asp_PortType all;
+import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+import from Socket_API_Definitions all;
+
+type record IpPort {
+ charstring ip,
+ integer udp_port
+};
+
+modulepar {
+ /* local IP address listening for OPCAP connections */
+ charstring mp_local_opcap_ip := "127.0.0.1";
+ /* local TCP base port for inbound OPCAP connections */
+ integer mp_local_opcap_port := 5000;
+
+ /* IP + port for simulating user traffic */
+ IpPort mp_traffic_a := { "127.0.0.23", 44423 };
+ IpPort mp_traffic_b := { "127.0.0.42", 44442 };
+};
+
+type component test_CT extends OPCAP_Adapter_CT {
+ timer g_Tguard := 30.0;
+
+ port TELNETasp_PT VTY;
+
+ /* port to generate IP traffic that may or may not be captured */
+ port IPL4asp_PT IP;
+ var integer g_traffic_conn_id;
+};
+
+private altstep as_Tguard() runs on test_CT {
+[] g_Tguard.timeout {
+ setverdict(fail, "global guard timeout");
+ mtc.stop;
+ }
+}
+
+/* initialize one of the OPCAP servers, wait for client to connect */
+private function f_init_one_srv(integer idx, template (present) uint32_t linktype) runs on test_CT {
+ /* start guard timer */
+ activate(as_Tguard());
+ g_Tguard.start;
+ log("Waiting for client-", idx, " connection...");
+ /* wait for connection */
+ f_bind(mp_local_opcap_ip, mp_local_opcap_port+idx, idx);
+ f_wait_client_connect(idx);
+ /* wait for file header */
+ f_opcap_exp(tr_OPCAP_FILE_HDR(linktype), idx);
+};
+
+
+/* global initialization */
+private function f_init() runs on test_CT {
+ map(self:VTY, system:VTY);
+ f_vty_set_prompts(VTY);
+ f_vty_transceive(VTY, "enable");
+
+ map(self:IP, system:IP);
+ var IPL4asp_Types.Result res
+
+ /* 0 -> 1 */
+ res := f_IPL4_connect(IP, mp_traffic_b.ip, mp_traffic_b.udp_port,
+ mp_traffic_a.ip, mp_traffic_a.udp_port, -1, { udp:={} });
+ g_traffic_conn_id := res.connId;
+}
+
+/* generate user traffic from A -> B */
+function f_trafic_pkt_ab(octetstring payload) runs on test_CT {
+ IP.send(ASP_Send:{g_traffic_conn_id, omit, payload})
+}
+
+/* expect a specified UDP payload on the OPCAP connection 'idx' */
+function f_opcap_exp_udp(octetstring udp_payload, integer idx) runs on test_CT {
+ var octetstring rx_tail;
+ var integer udp_payload_len, rx_pdu_len;
+ var OPCAP_PDU rx_pdu;
+
+ udp_payload_len := lengthof(udp_payload);
+
+ /* sadly I couldn't figure out how to create an octetstring template
+ * for 'match an octetstring ending in 'udp_payload' */
+ rx_pdu := f_opcap_exp(tr_OPCAP_PKT(?), idx);
+ rx_pdu_len := lengthof(rx_pdu.u.packet.payload);
+ rx_tail := substr(rx_pdu.u.packet.payload, rx_pdu_len - udp_payload_len, udp_payload_len);
+ if (rx_tail != udp_payload) {
+ log("captured UDP payload: ", rx_tail, " but expected: ", udp_payload);
+ setverdict(fail);
+ } else {
+ setverdict(pass);
+ }
+}
+
+/* create an additional pcap-store-connection via the VTY */
+function f_vty_create_addl_connection(integer idx) runs on test_CT
+{
+ f_vty_config3(VTY, { "client", "pcap-store-connectio second-" & int2str(idx) },
+ { "server ip " & mp_local_opcap_ip,
+ "server port " & int2str(mp_local_opcap_port + idx),
+ "connect" }
+ );
+}
+
+
+
+/* wait for inbound client connection and reception of link header */
+testcase TC_connect_rx_hdr() runs on test_CT
+{
+ f_init();
+ f_init_one_srv(0, ?);
+ setverdict(pass);
+}
+
+/* check if client connection is re-started after a close */
+testcase TC_reconnect(integer idx := 0) runs on test_CT
+{
+ f_init();
+ f_init_one_srv(idx, ?);
+ f_sleep(2.0);
+
+ log("Disconnecting client-", idx);
+ f_disconnect(idx);
+
+ f_wait_client_connect(idx);
+ f_opcap_exp(tr_OPCAP_FILE_HDR(?), idx);
+ setverdict(pass);
+}
+
+/* capture a packet that's within the filter */
+testcase TC_capture() runs on test_CT
+{
+ f_init();
+ f_init_one_srv(0, ?);
+
+ for (var integer i := 0; i < 10; i := i + 1) {
+ var octetstring udp_payload;
+
+ /* we assume 1400 is low enough to avoid IP fragmentation */
+ udp_payload := f_rnd_octstring_rnd_len(1400);
+ f_trafic_pkt_ab(udp_payload);
+
+ f_opcap_exp_udp(udp_payload, 0);
+ }
+}
+
+/* wait for inbound client connections and reception of link header */
+testcase TC_multi_connect_rx_hdr() runs on test_CT
+{
+ f_init();
+ f_init_one_srv(0, ?);
+ f_vty_create_addl_connection(1);
+ f_init_one_srv(1, ?);
+ setverdict(pass);
+}
+
+/* ensure a packet that's within the filter is sent to secondary clients */
+testcase TC_multi_capture() runs on test_CT
+{
+ f_init();
+ f_init_one_srv(0, ?);
+ f_vty_create_addl_connection(1);
+ f_init_one_srv(1, ?);
+
+ for (var integer i := 0; i < 10; i := i + 1) {
+ var octetstring udp_payload;
+
+ /* we assume 1400 is low enough to avoid IP fragmentation */
+ udp_payload := f_rnd_octstring_rnd_len(1400);
+ f_trafic_pkt_ab(udp_payload);
+
+ /* expect packet to arrive on both simulated servers */
+ f_opcap_exp_udp(udp_payload, 0);
+ f_opcap_exp_udp(udp_payload, 1);
+ }
+}
+
+/* TODO: ensure a packet outside the filter is dropped */
+/* TODO: capture of truncated packet */
+/* TODO: stall the receive window */
+/* TODO: different link type (ethernet, not SLL) */
+
+
+control {
+ execute( TC_connect_rx_hdr() );
+ execute( TC_reconnect() );
+ execute( TC_capture() );
+ execute( TC_multi_connect_rx_hdr() );
+ execute( TC_multi_capture() );
+};
+
+
+};
diff --git a/pcap-client/gen_links.sh b/pcap-client/gen_links.sh
new file mode 100755
index 00000000..e4599596
--- /dev/null
+++ b/pcap-client/gen_links.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit 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.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+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 "
+FILES+="Osmocom_VTY_Functions.ttcn "
+FILES+="OPCAP_Types.ttcn OPCAP_Templates.ttcn "
+FILES+="OPCAP_CodecPort.ttcn OPCAP_CodecPort_CtrlFunct.ttcn OPCAP_CodecPort_CtrlFunctdef.cc OPCAP_Adapter.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/pcap-client/osmo-pcap-client.cfg b/pcap-client/osmo-pcap-client.cfg
new file mode 100644
index 00000000..09201fc1
--- /dev/null
+++ b/pcap-client/osmo-pcap-client.cfg
@@ -0,0 +1,15 @@
+!
+! OsmoPCAPClient (UNKNOWN-dirty) configuration saved from vty
+!!
+!
+!
+line vty
+ no login
+ bind 127.0.0.1 4227
+!
+client
+ pcap device lo
+ pcap filter udp port 44423
+ pcap detect-loop 0
+ server ip 127.0.0.1
+ server port 5000
diff --git a/pcap-client/regen_makefile.sh b/pcap-client/regen_makefile.sh
new file mode 100755
index 00000000..81dd1eb7
--- /dev/null
+++ b/pcap-client/regen_makefile.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+NAME=OPCAP_CLIENT_Tests
+
+FILES="
+ *.ttcn
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ OPCAP_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3=""
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/pcu/GPRS_Components.ttcn b/pcu/GPRS_Components.ttcn
index ee2c38fd..849a251d 100644
--- a/pcu/GPRS_Components.ttcn
+++ b/pcu/GPRS_Components.ttcn
@@ -16,11 +16,8 @@ import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
import from GSM_RR_Types all;
+import from GSM_RestOctets all;
-import from Osmocom_VTY_Functions all;
-import from TELNETasp_PortType all;
-
-import from MobileL3_GMM_SM_Types all;
import from RLCMAC_CSN1_Types all;
import from RLCMAC_CSN1_Templates all;
import from RLCMAC_Types all;
@@ -29,20 +26,46 @@ import from RLCMAC_Templates all;
import from MobileL3_CommonIE_Types all;
import from L3_Templates all;
-import from NS_Types all;
-import from BSSGP_Types all;
-import from Osmocom_Gb_Types all;
-
-import from BSSGP_Emulation all; /* BssgpConfig */
-import from NS_Emulation all; /* NSConfiguration */
-
-import from UD_Types all;
import from PCUIF_Types all;
-import from PCUIF_CodecPort all;
import from PCUIF_Components all;
-import from IPL4asp_Types all;
import from Native_Functions all;
-import from SGSN_Components all;
+
+modulepar {
+ /* ARFCN of 1st TRX. Subsequent TRX are allocated incrementing ARFCNs. Nth TRX => base_arfcn + N-1 */
+ GsmArfcn mp_base_arfcn := 871;
+};
+
+type record TsTrxBtsNum {
+ uint3_t ts_nr,
+ uint3_t trx_nr,
+ uint8_t bts_nr,
+ uint8_t blk_nr
+};
+
+/* Useful to store poll FN + BTS+TRX+TS requested by network */
+type record PollFnCtx {
+ TsTrxBtsNum tstrxbts,
+ uint32_t fn
+};
+
+template (value) TsTrxBtsNum ts_TsTrxBtsNum(uint3_t ts_nr := 7,
+ uint3_t trx_nr := 0,
+ uint8_t bts_nr := 0,
+ uint8_t blk_nr := 0) := {
+ ts_nr := ts_nr,
+ trx_nr := trx_nr,
+ bts_nr := bts_nr,
+ blk_nr := blk_nr
+};
+template TsTrxBtsNum tr_TsTrxBtsNum(template uint3_t ts_nr := ?,
+ template uint3_t trx_nr := ?,
+ template uint8_t bts_nr := ?,
+ template uint8_t blk_nr := ?) := {
+ ts_nr := ts_nr,
+ trx_nr := trx_nr,
+ bts_nr := bts_nr,
+ blk_nr := blk_nr
+};
type union PacketDlAssignChan {
PacketDlAssign ccch,
@@ -50,10 +73,13 @@ type union PacketDlAssignChan {
};
type record DlTbf {
- GsmRrMessage rr_imm_ass,
- PacketDlAssignChan ass,
+ GsmRrMessage rr_imm_ass optional,
+ PacketDlAssignChan ass optional,
uint5_t tfi,
- AckNackDescription acknack_desc
+ GsmArfcn arfcn optional,
+ BIT8 ts_mask,
+ AckNackDescription acknack_desc,
+ EgprsAckNackDescription egprs_acknack_desc
};
type union PacketUlAssignChan {
@@ -66,10 +92,13 @@ type record UlTbf {
GsmRrMessage rr_imm_ass optional,
PacketUlAssignChan ass optional,
uint5_t tfi,
+ GsmArfcn arfcn optional,
+ BIT8 ts_mask,
uint3_t usf[8],
boolean is_egprs,
uint14_t bsn,
- CodingScheme tx_cs_mcs
+ CodingScheme tx_cs_mcs,
+ GsmFrameNumber start_time_fn
};
type record GprsMS {
@@ -83,7 +112,7 @@ type record GprsMS {
UlTbf ul_tbf optional, /* TODO: Only 1 UL tbf supported for now */
DlTbf dl_tbf optional /* TODO: Only 1 DL tbf supported for now */
};
-type record of GprsMS GprsMSArray;
+type record of GprsMS GprsMSList;
template AckNackDescription t_AckNackDescription_init := {
final_ack := '0'B,
@@ -91,11 +120,20 @@ template AckNackDescription t_AckNackDescription_init := {
receive_block_bitmap := '0000000000000000000000000000000000000000000000000000000000000000'B
}
+template EgprsAckNackDescription t_EgprsAckNackDescription_init := {
+ final_ack := '0'B,
+ begin_window := '1'B,
+ end_window := '1'B,
+ starting_seq_nr := 1,
+ compressed := '0'B,
+ urbb := '0000000000000000000000000000000000000000000000000000000000000000'B
+}
+
const uint3_t USF_UNUSED := 7; /* used to indicate PRACH */
template (value) GprsMS t_GprsMS_def := {
imsi := f_gen_imsi(42),
- tlli := '00000001'O,
+ tlli := f_gen_tlli(),
ra := bit2int(chan_req_def),
ra_is_11bit := 0,
burst_type := BURST_TYPE_0,
@@ -105,14 +143,27 @@ template (value) GprsMS t_GprsMS_def := {
dl_tbf := omit
};
+template (value) DlTbf t_DlTbf_def := {
+ rr_imm_ass := omit,
+ ass := omit,
+ tfi := 0,
+ arfcn := omit,
+ ts_mask := '00000000'B,
+ acknack_desc := t_AckNackDescription_init,
+ egprs_acknack_desc := t_EgprsAckNackDescription_init
+};
+
template (value) UlTbf t_UlTbf_def := {
rr_imm_ass := omit,
ass := omit,
tfi := 0,
+ arfcn := omit,
+ ts_mask := '00000000'B,
usf := { USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED, USF_UNUSED },
is_egprs := false,
bsn := 0,
- tx_cs_mcs := CS_1
+ tx_cs_mcs := CS_1,
+ start_time_fn := 0
};
type component MS_BTS_IFACE_CT {
@@ -121,16 +172,35 @@ type component MS_BTS_IFACE_CT {
/* Connection to the BTS component (one for now) */
port RAW_PCU_MSG_PT BTS;
- /* Support only 1 ms for now */
- var GprsMS g_ms[1];
+ /* Mobile station(s) involved in a testing scenario */
+ var GprsMSList g_ms := { };
/* Value at which Countdown Procedure starts. Announced by network (GPRS Cell Options as per TS 04.60 Chapter 12.24) */
var uint4_t g_bs_cv_max := 4;
}
-function f_init_gprs_ms(template (value) GprsMS ms_params := t_GprsMS_def) runs on MS_BTS_IFACE_CT
-{
- g_ms[0] := valueof(ms_params);
+/* Generate a list of GprsMS (unique IMSI/TLLI, cyclic RA) of the given size */
+function f_init_gprs_ms(integer num_ms := 1, template (value) GprsMS t_ms := t_GprsMS_def)
+runs on MS_BTS_IFACE_CT {
+ for (var integer i := 0; i < num_ms; i := i + 1 ) {
+ var GprsMS ms := valueof(t_ms);
+
+ /* We assume that num_ms is not a large number */
+ ms.imsi := f_gen_imsi(i + 1);
+ ms.tlli := int2oct(i + 1, 4);
+
+ /* Ensure different RA for siblings */
+ if (ms.ra == bit2int(chan_req_def)) {
+ /* 01111 { 0xx | x0x | xx0 } */
+ f_ms_use_ra(ms, ms.ra + (i mod 7));
+ } else if (ms.ra == bit2int(chan_req_sb)) {
+ /* 01110xxx */
+ f_ms_use_ra(ms, ms.ra + (i mod 8));
+ }
+
+ /* Append to the global list */
+ g_ms := g_ms & { ms };
+ }
}
@@ -154,12 +224,46 @@ runs on MS_BTS_IFACE_CT {
mtc.stop;
}
+function f_arfcn2trxnr(GsmArfcn arfcn) runs on MS_BTS_IFACE_CT return uint3_t {
+ if (arfcn < mp_base_arfcn) {
+ setverdict(fail, "Unable to find TRX NR for arfcn ", arfcn);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ return arfcn - mp_base_arfcn;
+}
+
+function f_trxnr2arfcn(uint3_t trx_nr) return GsmArfcn {
+ return mp_base_arfcn + trx_nr;
+}
+
+/* 3GPP TS 44.018 10.5.2.38 Starting Time */
+function f_tbf_starting_time_2_fn_mod_42432(TbfStartingTime st)
+runs on MS_BTS_IFACE_CT return GsmFrameNumber {
+ return 51 * ((st.t3 - st.t2) mod 26) + st.t3 + 51 * 26 * st.t1;
+}
+
+function fn2bn(GsmFrameNumber fn) return uint32_t {
+ return (fn mod 52) / 4;
+}
+function f_next_pdch_block(GsmFrameNumber fn) return GsmFrameNumber
+{
+ var uint32_t bn := fn2bn(fn) + 1;
+ fn := fn - (fn mod 52);
+ fn := fn + bn * 4 + bn / 3;
+ return fn mod GsmMaxFrameNumber;
+}
+
function f_ultbf_new_from_rr_imm_ass(in GsmRrMessage rr_imm_ass)
runs on MS_BTS_IFACE_CT return UlTbf {
var UlTbf ul_tbf := valueof(t_UlTbf_def);
var uint3_t tn_allocated := rr_imm_ass.payload.imm_ass.pkt_chan_desc.tn;
ul_tbf.rr_imm_ass := rr_imm_ass;
+ if (rr_imm_ass.payload.imm_ass.pkt_chan_desc.presence == '0'B and
+ rr_imm_ass.payload.imm_ass.pkt_chan_desc.zero.hopping == '0'B) {
+ ul_tbf.arfcn := rr_imm_ass.payload.imm_ass.pkt_chan_desc.zero.arfcn;
+ }
+ ul_tbf.ts_mask[tn_allocated] := '1'B;
/* Make sure we received an UL TBF Assignment */
if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_ULAss(?)))) {
@@ -170,8 +274,11 @@ runs on MS_BTS_IFACE_CT return UlTbf {
ul_tbf.tfi := ul_tbf.ass.ccch.dynamic.tfi_assignment;
ul_tbf.tx_cs_mcs := f_rlcmac_block_ChCodingCommand2cs_mcs(ul_tbf.ass.ccch.dynamic.ch_coding_cmd);
ul_tbf.usf[tn_allocated] := ul_tbf.ass.ccch.dynamic.usf;
+ if (ul_tbf.ass.ccch.dynamic.tbf_starting_time_present == '1'B) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch.dynamic.tbf_starting_time);
+ }
} else if (match(ul_tbf.ass.ccch, tr_PacketUlSglAssign)) {
- /* Nothing to do here yet */
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch.single.tbf_starting_time);
}
} else if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := false, rest := tr_IaRestOctets_EGPRSULAss(?)))) {
ul_tbf.ass.ccch_egprs := rr_imm_ass.payload.imm_ass.rest_octets.lh.egprs_ul;
@@ -181,7 +288,11 @@ runs on MS_BTS_IFACE_CT return UlTbf {
ul_tbf.tfi := ul_tbf.ass.ccch_egprs.dynamic.tfi_assignment;
ul_tbf.tx_cs_mcs := f_rlcmac_block_EgprsChCodingCommand2cs_mcs(ul_tbf.ass.ccch_egprs.dynamic.egprs_ch_coding_cmd);
ul_tbf.usf[tn_allocated] := ul_tbf.ass.ccch_egprs.dynamic.usf;
+ if (ul_tbf.ass.ccch_egprs.dynamic.tbf_starting_time_present == '1'B) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch_egprs.dynamic.tbf_starting_time);
+ }
} else if (match(ul_tbf.ass.ccch_egprs, tr_EgprsUlAssMultiblock)) {
+ ul_tbf.start_time_fn := f_tbf_starting_time_2_fn_mod_42432(ul_tbf.ass.ccch_egprs.multiblock.tbf_starting_time);
/* Nothing to do here yet */
}
} else {
@@ -196,6 +307,8 @@ runs on MS_BTS_IFACE_CT return UlTbf {
function f_ultbf_new_from_ass_pacch(RlcmacDlBlock dl_block)
runs on MS_BTS_IFACE_CT return UlTbf {
var UlTbf ul_tbf := valueof(t_UlTbf_def);
+ var boolean freq_par_present := false;
+ var FrequencyParameters freq_par;
ul_tbf.ass.pacch := dl_block.ctrl.payload.u.ul_assignment;
ul_tbf.tx_cs_mcs := f_rlcmac_dl_block_get_assigned_ul_cs_mcs(dl_block);
@@ -205,30 +318,51 @@ runs on MS_BTS_IFACE_CT return UlTbf {
/* TODO: support single block allocation */
if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_GPRS(?, tr_PktUlAssGprsDynamic(tr_DynamicAllocation(?))))) {
ul_tbf.tfi := dl_block.ctrl.payload.u.ul_assignment.gprs.dyn_block_alloc.ul_tfi_assignment;
+ freq_par_present := dl_block.ctrl.payload.u.ul_assignment.gprs.freq_par_present == '1'B;
+ if (freq_par_present) {
+ freq_par := dl_block.ctrl.payload.u.ul_assignment.gprs.freq_par;
+ }
ul_tbf.is_egprs := false;
for (var integer i := 0; i < 8; i := i + 1) {
if (dl_block.ctrl.payload.u.ul_assignment.gprs.dyn_block_alloc.ts_allocation.ts[i].presence == '1'B) {
+ ul_tbf.ts_mask[i] := '1'B;
ul_tbf.usf[i] := dl_block.ctrl.payload.u.ul_assignment.gprs.dyn_block_alloc.ts_allocation.ts[i].usf_tn;
}
}
} else if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS_EGPRS(?, tr_PktUlAssEgprsDynamic(tr_DynamicAllocation(?))))) {
ul_tbf.tfi := dl_block.ctrl.payload.u.ul_assignment.egprs.dyn_block_alloc.ul_tfi_assignment;
+ freq_par_present := dl_block.ctrl.payload.u.ul_assignment.egprs.freq_par_present == '1'B;
+ if (freq_par_present) {
+ freq_par := dl_block.ctrl.payload.u.ul_assignment.egprs.freq_par;
+ }
ul_tbf.is_egprs := true;
for (var integer i := 0; i < 8; i := i + 1) {
if (dl_block.ctrl.payload.u.ul_assignment.egprs.dyn_block_alloc.ts_allocation.ts[i].presence == '1'B) {
+ ul_tbf.ts_mask[i] := '1'B;
ul_tbf.usf[i] := dl_block.ctrl.payload.u.ul_assignment.egprs.dyn_block_alloc.ts_allocation.ts[i].usf_tn;
}
}
}
+
+ /* FIXME: freq_par and arfcn are optional. in that case we need to
+ * infer/reuse from current dl_tbf or ul_tbf */
+ if (freq_par_present and freq_par.presence == '00'B) {
+ ul_tbf.arfcn := freq_par.arfcn;
+ }
+
return ul_tbf;
}
function f_dltbf_new_from_rr_imm_ass(in GsmRrMessage rr_imm_ass, template PacketDlAssign dl_ass := tr_PacketDlAssign(?))
runs on MS_BTS_IFACE_CT return DlTbf {
- var DlTbf dl_tbf;
+ var DlTbf dl_tbf := valueof(t_DlTbf_def);
dl_tbf.rr_imm_ass := rr_imm_ass;
- dl_tbf.acknack_desc := valueof(t_AckNackDescription_init);
+ if (rr_imm_ass.payload.imm_ass.pkt_chan_desc.presence == '0'B and
+ rr_imm_ass.payload.imm_ass.pkt_chan_desc.zero.hopping == '0'B) {
+ dl_tbf.arfcn := rr_imm_ass.payload.imm_ass.pkt_chan_desc.zero.arfcn;
+ }
+ dl_tbf.ts_mask[rr_imm_ass.payload.imm_ass.pkt_chan_desc.tn] := '1'B;
/* Make sure we received a DL TBF Assignment */
if (match(rr_imm_ass, tr_IMM_TBF_ASS(dl := true, rest := tr_IaRestOctets_DLAss(dl_ass)))) {
@@ -251,22 +385,131 @@ runs on MS_BTS_IFACE_CT return DlTbf {
return dl_tbf;
}
-/* TODO: get stuff from f_rx_rlcmac_dl_block_exp_pkt_ass */
function f_dltbf_new_from_ass_pacch(RlcmacDlBlock dl_block)
runs on MS_BTS_IFACE_CT return DlTbf {
- var DlTbf dl_tbf;
+ var DlTbf dl_tbf := valueof(t_DlTbf_def);
+ var boolean freq_par_present := false;
+ var FrequencyParameters freq_par;
dl_tbf.ass.pacch := dl_block.ctrl.payload.u.dl_assignment;
dl_tbf.tfi := f_rlcmac_dl_block_get_tfi(dl_block);
/* TODO: handle GlobalTfiOrTlli tfi_or_tlli from pkt_dl_ass */
- dl_tbf.acknack_desc := valueof(t_AckNackDescription_init);
+
+ if (match(dl_block, tr_RLCMAC_DL_PACKET_ASS(?))) {
+ dl_tbf.tfi := dl_block.ctrl.payload.u.dl_assignment.dl_tfi_assignment;
+ freq_par_present := dl_block.ctrl.payload.u.dl_assignment.freq_par_present == '1'B;
+ if (freq_par_present) {
+ freq_par := dl_block.ctrl.payload.u.dl_assignment.freq_par;
+ }
+ dl_tbf.ts_mask := dl_block.ctrl.payload.u.dl_assignment.timeslot_alloc; /* TODO: is this the correct order ? */
+ /* TODO: check egprs in dl_assignment.rel_additions (PktDlAssR99Additions) */
+ }
+
+ /* FIXME: freq_par and arfcn are optional. in that case we need to
+ * infer/reuse from current dl_tbf or ul_tbf */
+ if (freq_par_present and freq_par.presence == '00'B) {
+ dl_tbf.arfcn := freq_par.arfcn;
+ }
return dl_tbf;
}
+function f_ms_tx_TsTrxBtsNum(inout GprsMS ms)
+runs on MS_BTS_IFACE_CT return TsTrxBtsNum {
+ var uint3_t ts_nr := f_ultbf_next_ts(ms.ul_tbf);
+
+ var uint3_t trx_nr;
+ if (ispresent(ms.ul_tbf.arfcn)) {
+ trx_nr := f_arfcn2trxnr(ms.ul_tbf.arfcn);
+ } else {
+ /* FIXME: implement search by hsn+maio+ma when freq hopping is enabled */
+ setverdict(fail, "Asked for trx_nr but arfcn not available in ms.ul_tbf!");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ return valueof(ts_TsTrxBtsNum(ts_nr, trx_nr));
+}
+
+function f_dltbf_num_slots(DlTbf dl_tbf)
+runs on MS_BTS_IFACE_CT return integer {
+ var integer n := 0;
+ for (var integer i := 0; i < lengthof(dl_tbf.ts_mask); i := i + 1) {
+ if (dl_tbf.ts_mask[i] == '1'B) {
+ n := n + 1;
+ }
+ }
+ return n;
+}
+
+function f_dltbf_ack_block(inout DlTbf dl_tbf, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
+runs on MS_BTS_IFACE_CT {
+ var boolean is_egprs := ischosen(dl_block.data_egprs);
+ if (is_egprs) {
+ f_egprs_acknackdesc_ack_block(dl_tbf.egprs_acknack_desc, dl_block, final_ack);
+ } else {
+ f_acknackdesc_ack_block(dl_tbf.acknack_desc, dl_block, final_ack);
+ }
+}
+
+function f_dltbf_ts_RLCMAC_DL_ACK_NACK(DlTbf dl_tbf, boolean use_egprs := false,
+ template (omit) ChannelReqDescription chreq_desc := omit)
+runs on MS_BTS_IFACE_CT return template (value) RlcmacUlBlock {
+ if (use_egprs) {
+ return ts_RLCMAC_DL_ACK_NACK_EGPRS(dl_tbf.tfi, dl_tbf.egprs_acknack_desc, false, chreq_desc);
+ } else {
+ return ts_RLCMAC_DL_ACK_NACK(dl_tbf.tfi, dl_tbf.acknack_desc, false, chreq_desc);
+ }
+}
+
function f_ultbf_inc_bsn(inout UlTbf ul_tbf)
runs on MS_BTS_IFACE_CT {
ul_tbf.bsn := ul_tbf.bsn + 1;
- ul_tbf.bsn := ul_tbf.bsn mod 128; /* FIXME: EGPRS SNS: 2048 */
+ if (ul_tbf.is_egprs) {
+ ul_tbf.bsn := ul_tbf.bsn mod 2048;
+ } else {
+ ul_tbf.bsn := ul_tbf.bsn mod 128;
+ }
+}
+
+function f_ultbf_next_ts(UlTbf ul_tbf)
+runs on MS_BTS_IFACE_CT return uint3_t {
+ /* FIXME: in the future we probably want to store last used internally
+ /* and continue from there */
+ for (var integer i := 0; i < lengthof(ul_tbf.ts_mask); i := i + 1) {
+ if (ul_tbf.ts_mask[i] == '1'B) {
+ return i;
+ }
+ }
+ setverdict(fail, "No TS available for tx!");
+ f_shutdown(__BFILE__, __LINE__);
+ return 0;
+}
+
+function f_ultbf_num_slots(UlTbf ul_tbf)
+runs on MS_BTS_IFACE_CT return integer {
+ var integer n := 0;
+ for (var integer i := 0; i < lengthof(ul_tbf.ts_mask); i := i + 1) {
+ if (ul_tbf.ts_mask[i] == '1'B) {
+ n := n + 1;
+ }
+ }
+ return n;
+}
+
+function f_ultbf_payload_fill_length(UlTbf ul_tbf, boolean tlli := false, integer li_bytes := 0)
+runs on MS_BTS_IFACE_CT return uint32_t {
+ var uint32_t blk_len := f_rlcmac_cs_mcs2block_len_no_spare_bits(ul_tbf.tx_cs_mcs);
+ var uint32_t payload_fill_len;
+
+ if (f_rlcmac_cs_mcs_is_mcs(ul_tbf.tx_cs_mcs)) {
+ payload_fill_len := blk_len - 5 - li_bytes;
+ } else {
+ /* GPRS: blk_len = 3 Header bytes + payload length. No LI byte in this case. */
+ payload_fill_len := blk_len - 3 - li_bytes;
+ }
+
+ if (tlli) {
+ payload_fill_len := payload_fill_len - 4;
+ }
+ return payload_fill_len;
}
function f_ms_use_ra(inout GprsMS ms, uint16_t ra, uint8_t ra_is_11bit := 0)
@@ -281,122 +524,224 @@ runs on MS_BTS_IFACE_CT {
}
function f_ms_rx_pkt_ass_pacch(inout GprsMS ms, out uint32_t poll_fn,
- template RlcmacDlBlock t_pkt_ass := ?)
+ template RlcmacDlBlock t_pkt_ass := ?,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum,
+ boolean ignore_dummy := true)
runs on MS_BTS_IFACE_CT return RlcmacDlBlock {
var RlcmacDlBlock dl_block;
- var uint32_t dl_fn;
-
- f_rx_rlcmac_dl_block(dl_block, dl_fn);
- if (not match(dl_block, t_pkt_ass)) {
- setverdict(fail, "Failed to match Packet Assignment:", t_pkt_ass);
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] as_ms_rx_pkt_ass_pacch(ms, poll_fn, t_pkt_ass, nr, dl_block);
+ [ignore_dummy] as_ms_rx_ignore_dummy(ms, nr);
+ /* TODO: fail */
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
f_shutdown(__BFILE__, __LINE__);
+ }
}
+ return dl_block;
+}
+
+altstep as_ms_rx_ignore_dummy(inout GprsMS ms, template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL())) -> value data_msg {
+
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+}
- poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
+altstep as_pcuif_rx_ignore_empty(template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+}
- if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS)) {
- ms.ul_tbf := f_ultbf_new_from_ass_pacch(dl_block);
- if (ms.ul_tbf.ass.pacch.identity.tlli.tlli != ms.tlli) {
- setverdict(fail, "Wrong TLLI ", ms.ul_tbf.ass.pacch.identity.tlli, " received vs exp ", ms.tlli);
- f_shutdown(__BFILE__, __LINE__);
- }
- } else if (match(dl_block, tr_RLCMAC_DL_PACKET_ASS)) {
- ms.dl_tbf := f_dltbf_new_from_ass_pacch(dl_block);
- /* TODO: match tlli from ms.dl_tbf.ass.pacch with ms.tlli), or error */
- } else {
- setverdict(fail, "Should not happen:", dl_block);
+altstep as_rx_fail_dummy(template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL())) -> value data_msg {
+ setverdict(fail, "Unexpected Dummy Ctrl block ", data_msg);
f_shutdown(__BFILE__, __LINE__);
}
+}
- return dl_block;
+altstep as_ms_rx_pkt_ass_pacch(inout GprsMS ms, out uint32_t poll_fn,
+ template RlcmacDlBlock t_pkt_ass := ?,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum,
+ out RlcmacDlBlock dl_block)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH),
+ t_pkt_ass)) -> value data_msg {
+ var uint32_t dl_fn := data_msg.raw.fn;
+ dl_block := data_msg.dl_block;
+ poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
+
+ if (match(dl_block, tr_RLCMAC_UL_PACKET_ASS)) {
+ ms.ul_tbf := f_ultbf_new_from_ass_pacch(dl_block);
+ if (ms.ul_tbf.ass.pacch.identity.tlli.tlli != ms.tlli) {
+ setverdict(fail, "Wrong TLLI ", ms.ul_tbf.ass.pacch.identity.tlli, " received vs exp ", ms.tlli);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } else if (match(dl_block, tr_RLCMAC_DL_PACKET_ASS)) {
+ ms.dl_tbf := f_dltbf_new_from_ass_pacch(dl_block);
+ if (ischosen(ms.dl_tbf.ass.pacch.tfi_or_tlli.tlli) and
+ ms.dl_tbf.ass.pacch.tfi_or_tlli.tlli.tlli != ms.tlli) {
+ setverdict(fail, "Wrong TLLI ", ms.dl_tbf.ass.pacch.tfi_or_tlli.tlli.tlli, " received vs exp ", ms.tlli);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } else {
+ setverdict(fail, "Should not happen:", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
}
-function f_ms_establish_ul_tbf(inout GprsMS ms)
+function f_ms_establish_ul_tbf(inout GprsMS ms, template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var GsmRrMessage rr_imm_ass;
- rr_imm_ass := f_pcuif_tx_rach_rx_imm_ass(ms.ra, ms.ra_is_11bit, ms.burst_type, ms.ta);
+ rr_imm_ass := f_pcuif_tx_rach_rx_imm_ass(ms.ra, ms.ra_is_11bit, ms.burst_type, ms.ta, nr := nr);
ms.ul_tbf := f_ultbf_new_from_rr_imm_ass(rr_imm_ass);
}
-function f_ms_exp_dl_tbf_ass_ccch(inout GprsMS ms, template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
- template GsmRrMessage t_imm_ass := tr_IMM_TBF_ASS(true, ?, ?))
+function f_ms_exp_dl_tbf_ass_ccch(inout GprsMS ms, template PCUIF_Sapi sapi := PCU_IF_SAPI_PCH_2,
+ template GsmRrMessage t_imm_ass := tr_IMM_TBF_ASS(true, ?, ?),
+ template (present) TsTrxBtsNum nr := tr_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var GsmRrMessage rr_imm_ass;
- rr_imm_ass := f_pcuif_rx_imm_ass(sapi, t_imm_ass);
+ rr_imm_ass := f_pcuif_rx_imm_ass(sapi, t_imm_ass, nr := nr);
ms.dl_tbf := f_dltbf_new_from_rr_imm_ass(rr_imm_ass, tr_PacketDlAssign(ms.tlli));
}
/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
-function f_ms_tx_data_ind(inout GprsMS ms, octetstring data, uint32_t fn := 0)
+function f_ms_tx_data_ind(inout GprsMS ms, octetstring data, uint32_t fn := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
- f_pcuif_tx_data_ind(data, ms.lqual_cb, fn);
+ f_pcuif_tx_data_ind(data, fn, ms.ta, ms.lqual_cb, nr := nr);
}
-function f_ms_tx_ul_block(inout GprsMS ms, template (value) RlcmacUlBlock ul_data, uint32_t fn := 0, template (omit) CodingScheme force_cs_mcs := omit)
-runs on MS_BTS_IFACE_CT return integer {
+function f_ms_tx_ul_block(inout GprsMS ms, template (value) RlcmacUlBlock ul_data,
+ uint32_t fn := 0, template (omit) CodingScheme force_cs_mcs := omit,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
var octetstring data;
- var integer padding_len;
var CodingScheme cs_mcs;
var uint32_t cs_mcs_len;
/* Encode the payload of DATA.ind */
data := enc_RlcmacUlBlock(valueof(ul_data));
- if (ispresent(force_cs_mcs)) {
- cs_mcs := valueof(force_cs_mcs);
- } else if (ischosen(ul_data.ctrl)) {
- cs_mcs := CS_1; /* CTRL is always CS1 */
- } else {
- /* Add padding to encode payload to minimum required CS/MCS: */
- cs_mcs := f_rlcmac_block_len_required_cs_mcs(lengthof(data), ischosen(ul_data.data_egprs));
- }
-
- cs_mcs_len := f_rlcmac_cs_mcs2block_len(cs_mcs);
- padding_len := cs_mcs_len - lengthof(data);
- if (padding_len < 0) {
- setverdict(fail, "Unable to encode UL block of size ", lengthof(data), " with ", cs_mcs);
- f_shutdown(__BFILE__, __LINE__);
+ if (ischosen(ul_data.ctrl)) {
+ /* Ctrl blocks are right now encoded by RAW encoder, which was
+ * found to have some issue with final padding, so we add it
+ * here manually. This is actually still incorrect because the
+ * remaining bits of last octet with data are not filled with
+ * the padding sequence, but it's good enough since anyway PCU
+ * don't check these. */
+ data := f_pad_oct(data, f_rlcmac_cs_mcs2block_len(CS_1), '2b'O);
}
- data := f_pad_oct(data, cs_mcs_len, '00'O);
-
/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
- f_ms_tx_data_ind(ms, data, fn);
- return padding_len;
+ f_ms_tx_data_ind(ms, data, fn, nr := nr);
}
-/* FIXME: Only supports sending CS-1 so far */
-function f_ms_tx_ul_data_block(inout GprsMS ms, octetstring payload, uint4_t cv := 15, boolean with_tlli := false, uint32_t fn := 0)
-runs on MS_BTS_IFACE_CT return integer {
+function f_ms_tx_ul_data_blocks_gprs(inout GprsMS ms, template (value) LlcBlocks blocks,
+ uint4_t cv := 15, boolean with_tlli := false, uint32_t fn := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
var template (value) RlcmacUlBlock ul_data;
- ul_data := t_RLCMAC_UL_DATA(tfi := ms.ul_tbf.tfi,
+
+ ul_data := t_RLCMAC_UL_DATA(cs := ms.ul_tbf.tx_cs_mcs,
+ tfi := ms.ul_tbf.tfi,
cv := cv,
bsn := ms.ul_tbf.bsn,
- blocks := {t_RLCMAC_LLCBLOCK(payload)});
+ blocks := blocks);
if (with_tlli) {
ul_data.data.mac_hdr.tlli_ind := true;
ul_data.data.tlli := ms.tlli;
}
f_ultbf_inc_bsn(ms.ul_tbf);
- return f_ms_tx_ul_block(ms, ul_data, fn);
+ f_ms_tx_ul_block(ms, ul_data, fn, nr := nr);
+}
+
+function f_ms_tx_ul_data_blocks_egprs(inout GprsMS ms, template (value) EgprsLlcBlocks blocks,
+ uint4_t cv := 15, boolean with_tlli := false, uint32_t fn := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var template (value) RlcmacUlBlock ul_data;
+
+ ul_data := t_RLCMAC_UL_EGPRS_DATA(mcs := ms.ul_tbf.tx_cs_mcs,
+ tfi := ms.ul_tbf.tfi,
+ cv := cv,
+ bsn1 := ms.ul_tbf.bsn,
+ bsn2_offset := 0,
+ blocks := blocks);
+ if (with_tlli) {
+ ul_data.data_egprs.tlli_ind := true;
+ ul_data.data_egprs.tlli := ms.tlli;
+ }
+ f_ultbf_inc_bsn(ms.ul_tbf);
+ f_ms_tx_ul_block(ms, ul_data, fn, nr := nr);
+}
+
+function f_ms_tx_ul_data_block(inout GprsMS ms, octetstring payload,
+ uint4_t cv := 15, boolean with_tlli := false, uint32_t fn := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ var template (value) RlcmacUlBlock ul_data;
+
+ if (f_rlcmac_cs_mcs_is_mcs(ms.ul_tbf.tx_cs_mcs)) {
+ f_ms_tx_ul_data_blocks_egprs(ms, {t_RLCMAC_LLCBLOCK_EGPRS(payload)}, cv, with_tlli, fn, nr)
+ } else {
+ f_ms_tx_ul_data_blocks_gprs(ms, {t_RLCMAC_LLCBLOCK(payload)}, cv, with_tlli, fn, nr);
+ }
}
/* Send random payload for last "num_blocks" blocks in Ul TBF (ending with CV=0). */
-function f_ms_tx_ul_data_block_multi(inout GprsMS ms, integer num_blocks := 1, boolean with_tlli := false)
+function f_ms_tx_ul_data_block_multi(inout GprsMS ms, integer num_blocks := 1, boolean with_tlli := false,
+ uint32_t fn := 0, template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT return octetstring {
var octetstring total_payload := ''O;
+ var uint32_t payload_fill_len := f_ultbf_payload_fill_length(ms.ul_tbf, with_tlli, 0);
for (var integer i := 0; i < num_blocks; i := i + 1) {
- var integer padding_len;
- var octetstring payload := f_rnd_octstring(10);
+ var octetstring payload := f_rnd_octstring(payload_fill_len);
/* Prepare a new UL block (CV, random payload) */
var integer cv := num_blocks - i - 1;
if (cv > g_bs_cv_max) {
cv := 15;
}
- padding_len := f_ms_tx_ul_data_block(ms, payload, cv := cv, with_tlli := with_tlli)
- total_payload := total_payload & payload & f_pad_oct(''O, padding_len, '00'O);
+ if (i == 1) {
+ /* We use FN on i=0 to jump to wanted FN time, then simply submit on next
+ * available frame (fn=0) */
+ fn := 0;
+ }
+ f_ms_tx_ul_data_block(ms, payload, cv := cv, with_tlli := with_tlli, fn := fn, nr := nr);
+ total_payload := total_payload & payload;
}
return total_payload;
}
@@ -423,6 +768,20 @@ runs on MS_BTS_IFACE_CT return uint5_t {
return 0; /* make compiler happy */
}
+function f_rlcmac_dl_block_get_usf(RlcmacDlBlock dl_block)
+runs on MS_BTS_IFACE_CT return uint3_t {
+ if (ischosen(dl_block.data)) {
+ return dl_block.data.mac_hdr.mac_hdr.usf;
+ } else if (ischosen(dl_block.data_egprs)) {
+ return dl_block.data_egprs.mac_hdr.usf;
+ } else { /* Ctrl block */
+ return dl_block.ctrl.mac_hdr.usf;
+ }
+ setverdict(fail, "DlBlock doesn't contain a USF:", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ return 0; /* make compiler happy */
+}
+
/* Get the Chan coding command from a dl block containing PACCH UL Assignment */
function f_rlcmac_dl_block_get_assigned_ul_cs_mcs(RlcmacDlBlock dl_block)
runs on MS_BTS_IFACE_CT return CodingScheme {
@@ -443,19 +802,20 @@ function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl
var uint7_t bsn;
var integer i;
var integer inc;
+ bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
- if (ischosen(dl_block.data)) {
- bsn := dl_block.data.mac_hdr.hdr_ext.bsn;
- } else {
- bsn := dl_block.data_egprs.mac_hdr.bsn1;
- }
-
- inc := bsn - desc.starting_seq_nr + 1;
/* Filling hole? */
if (bsn < desc.starting_seq_nr) {
desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr - bsn)] := int2bit(1, 1);
return;
}
+ /* Filling hole, wraparound: */
+ if (bsn - desc.starting_seq_nr > lengthof(desc.receive_block_bitmap)) {
+ desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - (desc.starting_seq_nr + (218 - bsn))] := int2bit(1, 1);
+ return;
+ }
+
+ inc := bsn - desc.starting_seq_nr + 1;
/* SSN is increased, and so RBB values need to be moved */
for (i := 0; i < lengthof(desc.receive_block_bitmap) - inc; i := i+1) {
@@ -465,74 +825,270 @@ function f_acknackdesc_ack_block(inout AckNackDescription desc, RlcmacDlBlock dl
desc.receive_block_bitmap[i] := int2bit(0, 1);
}
/* Now we can set current bit and update SSN */
- desc.starting_seq_nr := bsn + 1;
+ desc.starting_seq_nr := (bsn + 1) mod 128;
desc.receive_block_bitmap[lengthof(desc.receive_block_bitmap) - 1] := int2bit(1, 1);
/* Finally update the final_ack bit as requested: */
desc.final_ack := final_ack;
}
-/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req.
- * NOTE: it's the responsibility of caller to make sure that pcu_msg contains u.data_req. */
-function f_pcuif_tx_data_cnf(in PCUIF_Message pcu_msg)
+/* TS 44.060 sec 12.3 Ack/Nack Description */
+function f_egprs_acknackdesc_ack_block(inout EgprsAckNackDescription desc, RlcmacDlBlock dl_block, BIT1 final_ack := '0'B)
+{
+ var uint11_t bsn;
+ var integer i;
+ var integer inc;
+ var integer n := 0;
+ var integer v_q := (desc.starting_seq_nr + 2047) mod 2048; /* SSN = V(Q) + 1 */
+
+ bsn := dl_block.data_egprs.mac_hdr.bsn1;
+
+ /* Repetition? */
+ if (bsn < v_q) {
+ /* Filling hole, wraparound: */
+ if (bsn - v_q > lengthof(desc.urbb)) {
+ desc.urbb[lengthof(desc.urbb) - (v_q + (2048 - bsn))] := int2bit(1, 1);
+ return;
+ }
+ return;
+ }
+
+ inc := bsn - v_q + 1;
+ desc.urbb[lengthof(desc.urbb) - inc] := int2bit(1, 1);
+
+ for (i := lengthof(desc.urbb) - 1; i >= lengthof(desc.urbb) - inc; i := i - 1) {
+ if (desc.urbb[i] == '0'B) {
+ break;
+ }
+ n := n + 1;
+ }
+
+ if (n > 0) {
+ /* SSN is increased, and so RBB values need to be moved */
+ for (i := lengthof(desc.urbb) - 1; i >= n; i := i - 1) {
+ desc.urbb[i] := desc.urbb[i - n];
+ }
+ for (i := n - 1; i >= 0; i := i - 1) {
+ desc.urbb[i] := int2bit(0, 1);
+ }
+
+ desc.starting_seq_nr := (desc.starting_seq_nr + n) mod 2048;
+ }
+
+ /* Finally update the final_ack bit as requested: */
+ desc.final_ack := final_ack;
+}
+
+/* This function can be used to send DATA.cnf in response to the IUT originated DATA.req. */
+function f_pcuif_tx_data_cnf(in BTS_CCCH_Block data_msg)
runs on MS_BTS_IFACE_CT {
- var PCUIF_Message pcu_msg_cnf := {
- msg_type := PCU_IF_MSG_DATA_CNF,
- bts_nr := pcu_msg.bts_nr,
- spare := pcu_msg.spare,
- u := { data_cnf := pcu_msg.u.data_req }
+ var PCUIF_data_cnf cnf := {
+ sapi := data_msg.raw.sapi,
+ msg_id := data_msg.msg_id
};
- /* PCU wants DATA.cnf containing basically everything that was in DATA.req,
- * but PCU_IF_SAPI_PCH is a special case - paging group shall be excluded. */
- if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
- pcu_msg_cnf.u.data_cnf.data := substr(pcu_msg.u.data_req.data, 3,
- pcu_msg.u.data_req.len - 3);
- }
+ var PCUIF_Message pcu_msg_cnf := {
+ msg_type := PCU_IF_MSG_DATA_CNF_2,
+ bts_nr := data_msg.bts_nr,
+ spare := '0000'O,
+ u := { data_cnf2 := cnf}
+ };
BTS.send(pcu_msg_cnf);
}
-////////////////////////
-// OLD APIs
-////////////////////////
+private function f_ms_gtfi_tmpl(inout GprsMS ms)
+runs on MS_BTS_IFACE_CT return template (present) GlobalTfi {
+ var template (present) GlobalTfi gtfi;
+ if (ispresent(ms.ul_tbf) and ispresent(ms.dl_tbf)) {
+ gtfi := ({ is_dl_tfi := false, tfi := ms.ul_tbf.tfi },
+ { is_dl_tfi := true, tfi := ms.dl_tbf.tfi });
+ } else if (ispresent(ms.ul_tbf)) {
+ gtfi := { is_dl_tfi := false, tfi := ms.ul_tbf.tfi };
+ } else if (ispresent(ms.dl_tbf)) {
+ gtfi := { is_dl_tfi := true, tfi := ms.dl_tbf.tfi };
+ } else {
+ gtfi := ?;
+ }
+ return gtfi;
+}
-function f_pcuif_rx_imm_ass(template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH,
- template GsmRrMessage t_imm_ass := ?)
-runs on MS_BTS_IFACE_CT return GsmRrMessage {
- var GsmRrMessage rr_imm_ass;
- var PCUIF_Message pcu_msg;
- var octetstring data;
- timer T;
+altstep as_ms_rx_pkt_neighbor_cell_data(inout GprsMS ms, octetstring exp_si,
+ inout uint5_t exp_container_idx /* := 0 */,
+ inout integer si_offset /* := 0 */,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum,
+ boolean single_step := false)
+runs on MS_BTS_IFACE_CT {
+ var integer len;
+ var octetstring exp_si_chunk;
+ var template (present) GlobalTfi gtfi := f_ms_gtfi_tmpl(ms);
+ var BTS_PDTCH_Block data_msg;
+ var boolean do_repeat := true;
+
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr, tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_NEIGH_CELL_DATA(gtfi, exp_container_idx))
+ )) -> value data_msg {
+
+ var PacketNeighbourCellData neigh_data := data_msg.dl_block.ctrl.payload.u.neighbour_cell_data;
+ var PacketNeighbourCellDataContainer cont := neigh_data.container_list[0];
+
+ if (cont.cd_length == 31) { /* continues on next message */
+ len := lengthof(cont.container_data);
+ exp_si_chunk := substr(exp_si, si_offset, len);
+ if (cont.container_data != exp_si_chunk) {
+ setverdict(fail, "Rx unexpected SI chunk at offset ", si_offset, ": ",
+ cont.container_data, " vs exp ", exp_si_chunk);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ si_offset := si_offset + len;
+ } else if (cont.cd_length == 0) {
+ /* we are done */
+ if (si_offset != lengthof(exp_si)) {
+ setverdict(fail, "Rx unexpectd SI length ", si_offset,
+ " vs exp ", lengthof(exp_si));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ do_repeat := false;
+ } else { /* data length, last message */
+ len := cont.cd_length;
+ exp_si_chunk := substr(exp_si, si_offset, len);
+ if (cont.container_data != exp_si_chunk) {
+ setverdict(fail, "Rx unexpected SI chunk at offset ", si_offset, ": ",
+ cont.container_data, " vs exp ", exp_si_chunk);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ si_offset := si_offset + len;
+ /* we are done */
+ if (si_offset != lengthof(exp_si)) {
+ setverdict(fail, "Rx unexpectd SI length ", si_offset,
+ " vs exp ", lengthof(exp_si));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ do_repeat := false;
+ }
- T.start(2.0);
+ exp_container_idx := exp_container_idx + 1;
+
+ if (not single_step and do_repeat) {
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ }
+}
+
+/* Handle groups of PKT NEIGHBOUR CELL DATA packets */
+function f_ms_handle_pkt_neighbor_cell_data(inout GprsMS ms, octetstring exp_si,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum,
+ uint5_t exp_container_idx := 0,
+ integer si_offset := 0,
+ boolean single_step := false)
+runs on MS_BTS_IFACE_CT {
+ var BTS_PDTCH_Block data_msg;
+
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
alt {
- [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
- sapi := sapi, data := ?)) -> value pcu_msg {
- /* On PCH the payload is prefixed with paging group (3 octets): skip it.
- * TODO: add an additional template parameter, so we can match it. */
- if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
- data := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
- } else {
- data := pcu_msg.u.data_req.data;
+ [exp_container_idx == 0] as_ms_rx_ignore_dummy(ms, nr);
+ [exp_container_idx > 0] as_rx_fail_dummy(nr);
+ [] as_ms_rx_pkt_neighbor_cell_data(ms, exp_si, exp_container_idx, si_offset, nr, single_step);
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_CTRL(?, ?))) -> value data_msg {
+ var GlobalTfi gtfi := { is_dl_tfi := false, tfi := ms.ul_tbf.tfi };
+ setverdict(fail, "Rx unexpected DL block: ", data_msg.dl_block, " vs exp ",
+ tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_NEIGH_CELL_DATA(gtfi, exp_container_idx)));
+ f_shutdown(__BFILE__, __LINE__);
}
+ };
+
+ return;
+}
+
+/* Keep receiving & discarding DL blocks until the PCU requests USF for this MS */
+function f_ms_wait_usf(inout GprsMS ms, template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT return uint32_t {
+ var BTS_PDTCH_Block data_msg;
- rr_imm_ass := dec_GsmRrMessage(data);
- if (not match(rr_imm_ass, t_imm_ass)) {
- /* Not for us? Wait for more. */
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] as_pcuif_rx_ignore_empty(nr);
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ ?)) -> value data_msg {
+ var uint3_t rx_usf := f_rlcmac_dl_block_get_usf(data_msg.dl_block);
+ var uint3_t exp_usf := ms.ul_tbf.usf[valueof(nr.ts_nr)];
+ log("Rx DL block USF ", rx_usf, " vs exp USF ", exp_usf);
+ if (rx_usf != exp_usf) {
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
repeat;
}
+ }
+ };
- log("Rx Immediate Assignment: ", rr_imm_ass);
+ return data_msg.raw.fn;
+}
- /* Send DATA.cnf back to the IUT (only needed for PCH) */
- if (pcu_msg.u.data_req.sapi == PCU_IF_SAPI_PCH) {
- f_pcuif_tx_data_cnf(pcu_msg);
+////////////////////////
+// Low level APIs
+////////////////////////
+
+altstep as_rx_ptcch(out BTS_PTCCH_Block ret_msg, template (present) PTCCHDownlinkMsg msg := ?,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum, boolean do_repeat := false)
+runs on MS_BTS_IFACE_CT {
+ [] BTS.receive(tr_PCUIF_DATA_PTCCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PTCCH),
+ msg)) -> value ret_msg {
+ if (do_repeat) {
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PTCCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr))
+ repeat;
}
+ }
+}
- setverdict(pass);
+altstep as_ms_rx_imm_ass(template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH_2,
+ template GsmRrMessage t_imm_ass := ?,
+ template (present) TsTrxBtsNum nr := ts_TsTrxBtsNum,
+ out GsmRrMessage rr_imm_ass)
+runs on MS_BTS_IFACE_CT {
+ var BTS_CCCH_Block data_msg;
+ [] BTS.receive(tr_PCUIF_DATA_RR(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, 0, sapi := sapi),
+ t_imm_ass)) -> value data_msg {
+ rr_imm_ass := data_msg.rr_msg;
+ log("Rx Immediate Assignment: ", rr_imm_ass);
+ /* Send DATA.cnf back to the IUT */
+ if (ispresent(data_msg.confirm) and data_msg.confirm) {
+ f_pcuif_tx_data_cnf(data_msg);
}
- [] BTS.receive { repeat; }
+ setverdict(pass);
+ }
+}
+
+function f_pcuif_rx_imm_ass(template PCUIF_Sapi sapi := PCU_IF_SAPI_AGCH_2,
+ template GsmRrMessage t_imm_ass := ?,
+ template (present) TsTrxBtsNum nr := tr_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT return GsmRrMessage {
+ var GsmRrMessage rr_imm_ass;
+ timer T;
+
+ T.start(2.0);
+ alt {
+ [] as_ms_rx_imm_ass(sapi, t_imm_ass, nr, rr_imm_ass);
+ [] BTS.receive { repeat; } /* TODO: use as_ms_rx_ignore_dummy instead? */
[] T.timeout {
setverdict(fail, "Timeout waiting for Immediate Assignment");
f_shutdown(__BFILE__, __LINE__);
@@ -543,13 +1099,16 @@ runs on MS_BTS_IFACE_CT return GsmRrMessage {
}
/* One phase packet access (see 3GPP TS 44.018, table 9.1.8.1) */
-const BIT8 chan_req_def := '01111000'B;
+const BIT8 chan_req_def := '01111000'B; /* 01111 { 0xx | x0x | xx0 } */
+/* Single block (two phase or RR signalling) packet access */
+const BIT8 chan_req_sb := '01110000'B; /* 01110xxx */
/* Establish an Uplink TBF by sending RACH.ind towards the PCU */
function f_pcuif_tx_rach_rx_imm_ass(uint16_t ra := bit2int(chan_req_def),
uint8_t is_11bit := 0,
PCUIF_BurstType burst_type := BURST_TYPE_0,
- TimingAdvance ta := 0)
+ TimingAdvance ta := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT return GsmRrMessage {
var uint32_t fn;
@@ -558,10 +1117,10 @@ runs on MS_BTS_IFACE_CT return GsmRrMessage {
/* Send RACH.ind */
log("Sending RACH.ind on fn=", fn, " with RA=", ra, ", TA=", ta);
- BTS.send(ts_PCUIF_RACH_IND(bts_nr := 0, trx_nr := 0, ts_nr := 0,
+ BTS.send(ts_PCUIF_RACH_IND(nr.bts_nr, nr.trx_nr, ts_nr := 0,
ra := ra, is_11bit := is_11bit,
burst_type := burst_type,
- fn := fn, arfcn := 871,
+ fn := fn, arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
qta := ta * 4));
/* 3GPP TS 44.018, table 9.1.8.1, note 2b: Request Reference shall be set to 127
@@ -569,17 +1128,20 @@ runs on MS_BTS_IFACE_CT return GsmRrMessage {
* we assume that 11 bit RA always contains EGPRS Packet Channel Request. */
if (is_11bit != 0) { ra := 127; }
- /* Expect Immediate (TBF) Assignment on TS0/AGCH */
- return f_pcuif_rx_imm_ass(PCU_IF_SAPI_AGCH, tr_IMM_TBF_ASS(false, ra, fn));
+ /* Expect Immediate (TBF) Assignment on the same TS/TRX/BTS */
+ return f_pcuif_rx_imm_ass(PCU_IF_SAPI_AGCH_2, tr_IMM_TBF_ASS(false, ra, fn), nr);
}
/* Enqueue DATA.ind (both TDMA frame and block numbers to be patched) */
-function f_pcuif_tx_data_ind(octetstring data, int16_t lqual_cb := 0, uint32_t fn := 0)
+function f_pcuif_tx_data_ind(octetstring data, uint32_t fn := 0,
+ TimingAdvance ta := 0, int16_t lqual_cb := 0,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var template RAW_PCU_EventParam ev_param := {tdma_fn := ? };
- BTS.send(ts_PCUIF_DATA_IND(bts_nr := 0, trx_nr := 0, ts_nr := 7, block_nr := 0,
+ BTS.send(ts_PCUIF_DATA_IND(nr.bts_nr, nr.trx_nr, nr.ts_nr, nr.blk_nr,
sapi := PCU_IF_SAPI_PDTCH, data := data,
- fn := fn, arfcn := 871, lqual_cb := lqual_cb));
+ fn := fn, arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ ta_offs_qbits := ta * 4, lqual_cb := lqual_cb));
if (fn != 0) {
ev_param := {tdma_fn := fn };
}
@@ -587,60 +1149,69 @@ runs on MS_BTS_IFACE_CT {
}
/* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
-function f_pcuif_rx_data_req(out PCUIF_Message pcu_msg)
+function f_pcuif_rx_data_req_pdtch(out BTS_PDTCH_Block data_msg,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
- BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
sapi := PCU_IF_SAPI_PDTCH, fn := 0,
- arfcn := 871, block_nr := 0));
- BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
- sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg;
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), block_nr := nr.blk_nr));
+
+ BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH), *)
+ ) -> value data_msg;
}
/* Expect a Paging Request Type 1 from PCU on PCUIF on specified sapi. */
function f_pcuif_rx_pch_pag_req1(template MobileIdentityV mi1 := ?,
- template integer pag_group := ?)
+ template integer pag_group := ?,
+ template (present) TsTrxBtsNum nr := tr_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT return GsmRrMessage {
var GsmRrMessage rr_pag_req1;
- var PCUIF_Message pcu_msg;
var octetstring imsi_suff_octstr;
var integer pag_group_rx;
- var octetstring macblock;
- BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 0,
- sapi := PCU_IF_SAPI_PCH)) -> value pcu_msg;
+ var BTS_CCCH_Block data_msg;
+ BTS.receive(tr_PCUIF_DATA_RR(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PCH_2),
+ tr_PAG_REQ1(tr_MI_LV(mi1)))) -> value data_msg;
+ rr_pag_req1 := data_msg.rr_msg;
+ log("Rx Paging Request Type1: ", rr_pag_req1);
- /* First 3 bytes contain IMSI suffix to calculate paging group: */
- imsi_suff_octstr := substr(pcu_msg.u.data_req.data, 0, 3);
+ /* The last 3 digits of the IMSI are used to calculate paging group: */
+ imsi_suff_octstr := substr(char2oct(data_msg.imsi), lengthof(data_msg.imsi) - 3, 3);
pag_group_rx := str2int(oct2char(imsi_suff_octstr[0])) * 100 +
str2int(oct2char(imsi_suff_octstr[1])) * 10 +
str2int(oct2char(imsi_suff_octstr[2]));
- /* Make sure we've got RR Paging Request Type 1 for a given MI */
- macblock := substr(pcu_msg.u.data_req.data, 3, pcu_msg.u.data_req.len - 3);
- rr_pag_req1 := dec_GsmRrMessage(macblock);
- if (not match(rr_pag_req1, tr_PAG_REQ1(tr_MI_LV(mi1)))) {
- setverdict(fail, "Failed to match Paging Request Type 1: ", rr_pag_req1);
- f_shutdown(__BFILE__, __LINE__);
- }
-
/* Make sure that received paging froup matches the expected one */
if (not match(pag_group_rx, pag_group)) {
setverdict(fail, "Paging group", pag_group_rx, " does not match expected ", pag_group);
f_shutdown(__BFILE__, __LINE__);
}
- f_pcuif_tx_data_cnf(pcu_msg);
+ /* Send DATA.cnf back to the IUT */
+ if (ispresent(data_msg.confirm) and data_msg.confirm) {
+ f_pcuif_tx_data_cnf(data_msg);
+ }
return rr_pag_req1;
}
-function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn, template (present) CodingScheme exp_cs_mcs := ?)
+function f_rx_rlcmac_dl_block(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
+ template (present) CodingScheme exp_cs_mcs := ?,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
- var PCUIF_Message pcu_msg;
- f_pcuif_rx_data_req(pcu_msg);
- dl_block := dec_RlcmacDlBlock(pcu_msg.u.data_req.data);
- dl_fn := pcu_msg.u.data_req.fn;
+ var BTS_PDTCH_Block data_msg;
+ f_pcuif_rx_data_req_pdtch(data_msg, nr := nr);
- var integer len := lengthof(pcu_msg.u.data_req.data);
+ if (data_msg.dl_block == omit) {
+ setverdict(fail, "Expected RLCMAC block but received idle block (", data_msg.raw.len, ")");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ dl_block := data_msg.dl_block;
+ dl_fn := data_msg.raw.fn;
+
+ var integer len := lengthof(data_msg.raw.data);
var CodingScheme cs_mcs := f_rlcmac_block_len2cs_mcs(len)
if (not match(f_rlcmac_block_len2cs_mcs(len), exp_cs_mcs)) {
setverdict(fail, "Failed to match Coding Scheme exp ", exp_cs_mcs, " vs ", cs_mcs, " (", len, ")");
@@ -650,11 +1221,12 @@ runs on MS_BTS_IFACE_CT {
function f_rx_rlcmac_dl_block_exp_ack_nack(out RlcmacDlBlock dl_block, out uint32_t poll_fn,
template RlcmacDlBlock acknack_tmpl := (tr_RLCMAC_UL_ACK_NACK_GPRS(ul_tfi := ?),
- tr_RLCMAC_UL_ACK_NACK_EGPRS(ul_tfi := ?)))
+ tr_RLCMAC_UL_ACK_NACK_EGPRS(ul_tfi := ?)),
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var uint32_t dl_fn;
- f_rx_rlcmac_dl_block(dl_block, dl_fn);
+ f_rx_rlcmac_dl_block(dl_block, dl_fn, nr := nr);
if (match(dl_block, acknack_tmpl)) {
poll_fn := f_rrbp_ack_fn(dl_fn, dl_block.ctrl.mac_hdr.rrbp);
return;
@@ -663,22 +1235,49 @@ runs on MS_BTS_IFACE_CT {
f_shutdown(__BFILE__, __LINE__);
}
-function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block)
-runs on MS_BTS_IFACE_CT {
+function f_rx_rlcmac_dl_block_exp_dummy(out RlcmacDlBlock dl_block,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT return uint32_t {
var uint32_t dl_fn;
- f_rx_rlcmac_dl_block(dl_block, dl_fn);
- if (not match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
+ f_rx_rlcmac_dl_block(dl_block, dl_fn, nr := nr);
+ if (not match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
setverdict(fail, "Failed to match Packet DUMMY DL");
f_shutdown(__BFILE__, __LINE__);
}
+ return dl_fn;
}
-function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block)
+/* Keep getting dl_block until first non RLCMAC Dummy is received, then return it */
+function f_rx_rlcmac_dl_block_skip_dummy(out RlcmacDlBlock dl_block,
+ integer max_dummy := -1,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT return uint32_t {
+ var integer i := 0;
+ var uint32_t dl_fn;
+
+ while (true) {
+ f_rx_rlcmac_dl_block(dl_block, dl_fn, nr := nr);
+ if (not match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL)) {
+ /* Received first data, starting processing: */
+ break;
+ }
+ i := i + 1;
+ if (max_dummy >= 0 and i > max_dummy) {
+ setverdict(fail, "Didn't receive DL data after receiving ", i, " dummy blocks");
+ f_shutdown(__BFILE__, __LINE__);
+ break;
+ }
+ }
+ return dl_fn;
+}
+
+function f_rx_rlcmac_dl_block_exp_pkt_pag_req(out RlcmacDlBlock dl_block,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
runs on MS_BTS_IFACE_CT {
var uint32_t dl_fn;
- f_rx_rlcmac_dl_block(dl_block, dl_fn);
+ f_rx_rlcmac_dl_block(dl_block, dl_fn, nr := nr);
if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
setverdict(fail, "Failed to match Packet Paging Request: ", dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
f_shutdown(__BFILE__, __LINE__);
@@ -694,6 +1293,7 @@ runs on MS_BTS_IFACE_CT {
if (not match(data_block.mac_hdr.hdr_ext.bsn, exp_bsn)) {
setverdict(fail, "DL block BSN doesn't match: ",
data_block.mac_hdr.hdr_ext.bsn, " vs exp ", exp_bsn);
+ f_shutdown(__BFILE__, __LINE__);
}
if (lengthof(data_block.blocks) < 1) {
@@ -707,14 +1307,10 @@ runs on MS_BTS_IFACE_CT {
f_shutdown(__BFILE__, __LINE__);
}
- /* Check next data blocks contain dummy frames */
- if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
- setverdict(fail, "Second data payload is not a dummy frame: ",
- data_block.blocks[1].payload);
+ if (not match(data_block.cs, exp_cs)) {
+ setverdict(fail, "Failed to match ", data_block.cs, " vs exp ", exp_cs);
f_shutdown(__BFILE__, __LINE__);
}
-
- /* TODO: check exp_cs */
}
/* This function does what could probably be done with templates */
@@ -739,29 +1335,18 @@ runs on MS_BTS_IFACE_CT {
f_shutdown(__BFILE__, __LINE__);
}
- /* Check next data blocks contain dummy frames */
- if (lengthof(data_block.blocks) > 1 and substr(data_block.blocks[1].payload, 0, 3) != '43C001'O) {
- setverdict(fail, "Second data payload is not a dummy frame: ",
- data_block.blocks[1].payload);
+ if (not match(data_block.mcs, exp_cs)) {
+ setverdict(fail, "Failed to match ", data_block.mcs, " vs exp ", exp_cs);
f_shutdown(__BFILE__, __LINE__);
}
-
- /* TODO: Check exp_cs. In the case of EGPRS, first check mac_hdr.header_type and then decode CPS = exp_cs based on mac_hdr.header_type.
- See wireshark's egprs_Header_type1_coding_puncturing_scheme_to_mcs. */
}
-/* High level (task specific) helper for receiving and matching GPRS/EGPRS data blocks */
-function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
+/* High level (task specific) helper for matching GPRS/EGPRS data blocks */
+function f_rlcmac_dl_block_exp_data(in RlcmacDlBlock dl_block,
template (present) octetstring data := ?,
template (present) uint7_t exp_bsn := ?,
template (present) CodingScheme exp_cs := ?)
runs on MS_BTS_IFACE_CT {
- /* FIXME: ideally we should use an alt statement with timeout here, rather than
- * having +100500 layers of abstraction. This would facilitate developing the
- * multi-TBF/-TRX/-BTS tests, where you cannot expect that the first received
- * block is exactly what you need. */
- f_rx_rlcmac_dl_block(dl_block, dl_fn);
-
/* Make sure it's either GPRS or EGPRS data block */
if (not match(dl_block, tr_RLCMAC_DATA)) {
setverdict(fail, "Failed to match DL DATA: ", dl_block, " vs ", tr_RLCMAC_DATA);
@@ -779,6 +1364,22 @@ runs on MS_BTS_IFACE_CT {
}
}
+/* High level (task specific) helper for receiving and matching GPRS/EGPRS data blocks */
+function f_rx_rlcmac_dl_block_exp_data(out RlcmacDlBlock dl_block, out uint32_t dl_fn,
+ template (present) octetstring data := ?,
+ template (present) uint7_t exp_bsn := ?,
+ template (present) CodingScheme exp_cs := ?,
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum)
+runs on MS_BTS_IFACE_CT {
+ /* FIXME: ideally we should use an alt statement with timeout here, rather than
+ * having +100500 layers of abstraction. This would facilitate developing the
+ * multi-TBF/-TRX/-BTS tests, where you cannot expect that the first received
+ * block is exactly what you need. */
+ f_rx_rlcmac_dl_block(dl_block, dl_fn, nr := nr);
+
+ f_rlcmac_dl_block_exp_data(dl_block, data, exp_bsn, exp_cs);
+}
+
function f_dl_block_ack_fn(in RlcmacDlBlock dl_block, uint32_t dl_fn)
runs on MS_BTS_IFACE_CT return uint32_t {
var boolean rrbp_valid;
@@ -786,7 +1387,7 @@ runs on MS_BTS_IFACE_CT return uint32_t {
/* The argument must be either a GPRS or EGPRS data block */
if (ischosen(dl_block.data_egprs)) {
- rrbp_valid := true; /* always valid */
+ rrbp_valid := dl_block.data_egprs.mac_hdr.esp != '00'B;
rrbp := dl_block.data_egprs.mac_hdr.rrbp;
} else if (ischosen(dl_block.data)) {
rrbp_valid := dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
@@ -805,13 +1406,79 @@ runs on MS_BTS_IFACE_CT return uint32_t {
return f_rrbp_ack_fn(dl_fn, rrbp);
}
-function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi)
-runs on MS_BTS_IFACE_CT {
- if (not match(req.repeated_pageinfo.cs.tmsi, tmsi)) {
- setverdict(fail, "Mobile Identity (TMSI/P-TMSI) mismatch: ",
- "expected: ", tmsi, "got: ", req.repeated_pageinfo.cs.tmsi);
+function f_dl_block_rrbp_valid(in RlcmacDlBlock dl_block)
+runs on MS_BTS_IFACE_CT return boolean {
+ if (ischosen(dl_block.data_egprs)) {
+ return dl_block.data_egprs.mac_hdr.esp != '00'B;
+ } else if (ischosen(dl_block.data)) {
+ return dl_block.data.mac_hdr.mac_hdr.rrbp_valid;
+ } else {
+ return dl_block.ctrl.mac_hdr.rrbp_valid;
+ }
+}
+
+/* Return true if a given Packet Paging Request contains the given IMSI, false otherwise */
+function f_pkt_paging_match_imsi(in PacketPagingReq req, template (present) hexstring imsi,
+ boolean cs_domain := true, boolean ps_domain := true)
+runs on MS_BTS_IFACE_CT return boolean {
+ if (not ispresent(req.repeated_pageinfo)) {
+ setverdict(fail, "Packet Paging Request without MIs?!?");
f_shutdown(__BFILE__, __LINE__);
}
+
+ for (var integer i := 0; i < lengthof(req.repeated_pageinfo); i := i + 1) {
+ var PageInfo info := req.repeated_pageinfo[i].item;
+ var MobileIdentityLV_Paging mi_lv;
+
+ if (ischosen(info.cs)) { /* CS domain */
+ if (not ispresent(info.cs.mobile_identity))
+ { continue; }
+ if (not cs_domain)
+ { continue; }
+ mi_lv := info.cs.mobile_identity;
+ } else { /* PS domain */
+ if (not ispresent(info.ps.mobile_identity))
+ { continue; }
+ if (not ps_domain)
+ { continue; }
+ mi_lv := info.ps.mobile_identity;
+ }
+
+ /* Make sure MI contains IMSI before referencing it */
+ if (match(mi_lv.mobile_id, decmatch tr_MI_IMSI(imsi))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Return true if a given Packet Paging Request contains the given P-TMSI, false otherwise */
+function f_pkt_paging_match_tmsi(in PacketPagingReq req, template GsmTmsi tmsi,
+ boolean cs_domain := true, boolean ps_domain := true)
+runs on MS_BTS_IFACE_CT return boolean {
+ if (not ispresent(req.repeated_pageinfo)) {
+ setverdict(fail, "Packet Paging Request without MIs?!?");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ for (var integer i := 0; i < lengthof(req.repeated_pageinfo); i := i + 1) {
+ var PageInfo info := req.repeated_pageinfo[i].item;
+
+ if (cs_domain and ischosen(info.cs)) {
+ if (not ispresent(info.cs.tmsi))
+ { continue; }
+ if (match(info.cs.tmsi, tmsi))
+ { return true; }
+ } else if (ps_domain) {
+ if (not ispresent(info.ps.ptmsi))
+ { continue; }
+ if (match(info.ps.ptmsi, tmsi))
+ { return true; }
+ }
+ }
+
+ return false;
}
}
diff --git a/pcu/GPRS_TBF.ttcn b/pcu/GPRS_TBF.ttcn
index fb420972..3794410b 100644
--- a/pcu/GPRS_TBF.ttcn
+++ b/pcu/GPRS_TBF.ttcn
@@ -14,6 +14,7 @@ module GPRS_TBF {
import from GSM_Types all;
import from Osmocom_Types all;
import from General_Types all;
+import from Misc_Helpers all;
import from RLCMAC_CSN1_Types all;
import from RLCMAC_Types all;
import from RLCMAC_Templates all;
@@ -326,10 +327,10 @@ function f_ul_tbf_get_next_block(out RlcmacUlBlock blk, inout UlTbfState us, ino
/* include TLLI when needed */
if (tlli_needed) {
- blk := valueof(t_RLCMAC_UL_DATA_TLLI(us.tfi, cv, us.et.v_s,
+ blk := valueof(t_RLCMAC_UL_DATA_TLLI(CS_1, us.tfi, cv, us.et.v_s,
llc_blocks, false, mmctx.tlli));
} else {
- blk := valueof(t_RLCMAC_UL_DATA(us.tfi, cv, us.et.v_s, llc_blocks, false));
+ blk := valueof(t_RLCMAC_UL_DATA(CS_1, us.tfi, cv, us.et.v_s, llc_blocks, false));
}
/* Increment Block Sequence Number */
@@ -409,8 +410,9 @@ function f_dl_tbf_mod_sns(DlTbfState ds, integer val) return integer
}
function f_dl_tbf_is_in_window(integer bsn) return boolean {
- setverdict(fail, "pleaes implement me");
- mtc.stop;
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "please implement me");
+ return false;
}
function f_dl_tbf_is_received(inout DlTbfState ds, integer bsn) return boolean {
diff --git a/pcu/PCUIF_Components.ttcn b/pcu/PCUIF_Components.ttcn
index aa2ab422..6e956ba8 100644
--- a/pcu/PCUIF_Components.ttcn
+++ b/pcu/PCUIF_Components.ttcn
@@ -19,6 +19,11 @@ import from UD_Types all;
import from PCUIF_Types all;
import from PCUIF_CodecPort all;
+import from Osmocom_Types all;
+import from General_Types all;
+import from RLCMAC_Types all;
+import from GSM_RR_Types all;
+
/* Component communication diagram:
*
* +-----+ +----------+ +---------+
@@ -119,11 +124,63 @@ template RAW_PCU_Command tr_RAW_PCU_CMD(template RAW_PCU_CommandType cmd := ?,
data := data
}
+/* PCUIF req_data containing decoded rlcmac/rr, for users to be able to match
+ * directly on receive()
+ */
+type record BTS_PDTCH_Block {
+ uint8_t bts_nr,
+ PCUIF_data raw,
+ RlcmacDlBlock dl_block optional
+};
+type record BTS_PTCCH_Block {
+ uint8_t bts_nr,
+ PCUIF_data raw,
+ PTCCHDownlinkMsg dl_block optional
+};
+type record BTS_CCCH_Block {
+ uint8_t bts_nr,
+ PCUIF_data raw,
+ OCT4 msg_id optional,
+ charstring imsi optional,
+ GsmRrMessage rr_msg,
+ boolean confirm optional
+};
+template BTS_PDTCH_Block tr_PCUIF_DATA_PDTCH(template uint8_t bts_nr,
+ template PCUIF_data raw,
+ template RlcmacDlBlock dl_block := ?) := {
+ bts_nr := bts_nr,
+ raw := raw,
+ dl_block := dl_block
+};
+template BTS_PTCCH_Block tr_PCUIF_DATA_PTCCH(template uint8_t bts_nr,
+ template PCUIF_data raw,
+ template PTCCHDownlinkMsg dl_block := ?) := {
+ bts_nr := bts_nr,
+ raw := raw,
+ dl_block := dl_block
+};
+template BTS_CCCH_Block tr_PCUIF_DATA_RR(template uint8_t bts_nr,
+ template PCUIF_data raw,
+ template GsmRrMessage rr_msg := ?,
+ template OCT4 msg_id := *,
+ template charstring imsi := *,
+ template boolean confirm := *) := {
+ bts_nr := bts_nr,
+ raw := raw,
+ msg_id := msg_id,
+ imsi := imsi,
+ rr_msg := rr_msg,
+ confirm := confirm
+};
+
/* Generic port for messages and events */
type port RAW_PCU_MSG_PT message {
inout RAW_PCU_Command;
inout RAW_PCU_Event;
inout PCUIF_Message;
+ inout BTS_PDTCH_Block;
+ inout BTS_PTCCH_Block;
+ inout BTS_CCCH_Block;
} with { extension "internal" };
/* TDMA frame clock generator */
@@ -165,10 +222,12 @@ function f_tdma_ptcch_fn2ss(integer fn) return integer
return ss;
}
-function f_ClckGen_CT_handler()
+function f_ClckGen_CT_handler(integer start_fn := 0)
runs on RAW_PCU_ClckGen_CT {
var integer fn104, fn52, fn13;
+ fn := start_fn;
+
while (true) {
fn104 := fn mod 104;
fn52 := fn mod 52;
@@ -261,6 +320,8 @@ type component RAW_PCU_BTS_CT {
/* Whether to forward PTCCH/U burst events to the TC */
var boolean cfg_ptcch_burst_fwd := false;
+
+ var PCUIF_info_ind g_info_ind;
}
/* Queue received messages from Test Case, they will eventually be scheduled and
@@ -272,7 +333,11 @@ runs on RAW_PCU_BTS_CT {
/* Enqueue DATA.ind and RTS.req messages */
[] TC.receive(tr_PCUIF_MSG(PCU_IF_MSG_DATA_IND, bts_nr)) -> value pcu_msg {
- f_PCUIF_MsgQueue_enqueue(pdtch_data_queue, pcu_msg);
+ if (pcu_msg.u.data_ind.sapi == PCU_IF_SAPI_BCCH) {
+ PCUIF.send(pcu_msg); /* Forward directly ASAP */
+ } else {
+ f_PCUIF_MsgQueue_enqueue(pdtch_data_queue, pcu_msg);
+ }
repeat;
}
[] TC.receive(tr_PCUIF_RTS_REQ(bts_nr, sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg {
@@ -290,6 +355,84 @@ runs on RAW_PCU_BTS_CT {
}
}
+/* Submit empty data on any available TS, to set up initial TDMA clock */
+private function f_tx_first_data_ind(integer bts_nr, PCUIF_info_ind info_ind, integer start_fn)
+runs on RAW_PCU_BTS_CT
+{
+ var PCUIF_Message pcu_msg;
+
+ /* Find an active TS: */
+ for (var uint8_t ts_nr := 0; ts_nr < 8; ts_nr := ts_nr + 1) {
+ for (var integer trx_nr := 0; trx_nr < lengthof(g_info_ind.trx); trx_nr := trx_nr + 1) {
+ if (g_info_ind.trx[trx_nr].pdch_mask[ts_nr] == '0'B) {
+ continue; /* TRX+TS not activated */
+ }
+
+ /* Send empty DATA.ind to set up FN */
+ pcu_msg := valueof(ts_PCUIF_DATA_IND(bts_nr, trx_nr, ts_nr, 0 /* FIXME */,
+ PCU_IF_SAPI_PDTCH, ''O, start_fn,
+ g_info_ind.trx[trx_nr].arfcn,
+ rssi := -80, ber10k := 0,
+ ta_offs_qbits := 0, lqual_cb := 10));
+ PCUIF.send(pcu_msg);
+ return;
+ }
+ }
+}
+
+private function fn2macblock(uint32_t fn) return uint8_t
+{
+ return (fn mod 52) / 4;
+}
+
+/* Get first message from queue. true if non-empty, false otherwise */
+private function f_tx_data_ind_fn(integer bts_nr, integer fn)
+runs on RAW_PCU_BTS_CT
+{
+ var PCUIF_Message pcu_msg;
+ var boolean has_msg, use_msg;
+
+ for (var uint8_t ts_nr := 0; ts_nr < 8; ts_nr := ts_nr + 1) {
+ for (var integer trx_nr := 0; trx_nr < lengthof(g_info_ind.trx); trx_nr := trx_nr + 1) {
+ //var charstring prefix := "BTS=" & int2str(bts_nr) & ",TRX=" & int2str(trx_nr) & ",TS=" & int2str(ts_nr) & ",FN=" & int2str(fn) & ": ";
+ if (g_info_ind.trx[trx_nr].pdch_mask[ts_nr] == '0'B) {
+ //log(prefix, "disabled");
+ continue; /* TRX+TS not activated */
+ }
+
+ /* Check if we reached time to serve the first DATA.ind message in the queue: */
+ has_msg := f_PCUIF_MsgQueue_first(pdtch_data_queue, pcu_msg) and
+ pcu_msg.u.data_ind.trx_nr == trx_nr and
+ pcu_msg.u.data_ind.ts_nr == ts_nr;
+ use_msg := has_msg and (pcu_msg.u.data_ind.fn == 0 or pcu_msg.u.data_ind.fn == fn);
+ if (use_msg) {
+ /* Dequeue a DATA.ind message */
+ f_PCUIF_MsgQueue_dequeue(pdtch_data_queue, pcu_msg);
+ /* Patch TDMA frame / block number */
+ pcu_msg.u.data_ind.fn := fn;
+ pcu_msg.u.data_ind.block_nr := fn2macblock(fn);
+ //log(prefix, "DATA.ind");
+ } else if (has_msg and pcu_msg.u.data_ind.fn < fn) {
+ setverdict(fail, "We are late scheduling the block! ", pcu_msg.u.data_ind.fn, " < ", fn);
+ mtc.stop;
+ } else {
+ /* NOPE.ind: */
+ pcu_msg := valueof(ts_PCUIF_DATA_IND(bts_nr, trx_nr, ts_nr, 0 /* FIXME */,
+ PCU_IF_SAPI_PDTCH, ''O, fn,
+ g_info_ind.trx[trx_nr].arfcn,
+ rssi := -80, ber10k := 0,
+ ta_offs_qbits := 0, lqual_cb := 10));
+ //log(prefix, "DATA.ind (len=0)");
+ }
+
+ PCUIF.send(pcu_msg); /* Send to the PCU and notify the TC */
+ if (use_msg) {
+ TC.send(ts_RAW_PCU_CLCK_EV(TDMA_EV_PDTCH_BLOCK_SENT, fn));
+ }
+ }
+ }
+}
+
/* Handle schedule events and manage actions: Send msgs over PCUIF to PCU,
* advertise Test Case about sent messages, etc. */
private altstep as_BTS_CT_TDMASched(integer bts_nr)
@@ -297,7 +440,6 @@ runs on RAW_PCU_BTS_CT {
var PCUIF_Message pcu_msg;
var RAW_PCU_Event event;
var integer ev_begin_fn;
- var integer next_fn;
[] CLCK.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_BEG)) -> value event {
/* If the RTS queue for PDTCH is not empty, send a message */
@@ -306,7 +448,7 @@ runs on RAW_PCU_BTS_CT {
/* Patch TDMA frame / block number and send */
pcu_msg.u.rts_req.fn := event.data.tdma_fn;
- pcu_msg.u.rts_req.block_nr := 0; /* FIXME! */
+ pcu_msg.u.rts_req.block_nr := fn2macblock(event.data.tdma_fn);
PCUIF.send(pcu_msg);
}
@@ -315,29 +457,10 @@ runs on RAW_PCU_BTS_CT {
PCUIF.send(ts_PCUIF_TIME_IND(bts_nr, event.data.tdma_fn));
repeat;
}
- [lengthof(pdtch_data_queue) > 0] CLCK.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_END)) -> value event {
+ [] CLCK.receive(tr_RAW_PCU_EV(TDMA_EV_PDTCH_BLOCK_END)) -> value event {
/* FN matching the beginning of current block: */
ev_begin_fn := event.data.tdma_fn - 3;
-
- /* Check if we reached time to serve the first DATA.ind message in the queue: */
- f_PCUIF_MsgQueue_first(pdtch_data_queue, pcu_msg);
- next_fn := pcu_msg.u.data_ind.fn;
- if (next_fn != 0 and next_fn != ev_begin_fn) {
- if (next_fn < ev_begin_fn) {
- setverdict(fail, "We are late scheduling the block! ", next_fn, " < ", ev_begin_fn);
- mtc.stop;
- }
- repeat;
- }
- /* Dequeue a DATA.ind message */
- f_PCUIF_MsgQueue_dequeue(pdtch_data_queue, pcu_msg);
-
- /* Patch TDMA frame / block number */
- pcu_msg.u.data_ind.fn := ev_begin_fn;
- pcu_msg.u.data_ind.block_nr := 0; /* FIXME! */
-
- PCUIF.send(pcu_msg); /* Send to the PCU and notify the TC */
- TC.send(ts_RAW_PCU_CLCK_EV(TDMA_EV_PDTCH_BLOCK_SENT, ev_begin_fn));
+ f_tx_data_ind_fn(bts_nr, ev_begin_fn);
repeat;
}
[lengthof(ptcch_rts_queue) > 0] CLCK.receive(tr_RAW_PCU_EV(TDMA_EV_PTCCH_DL_BLOCK)) -> value event {
@@ -348,7 +471,7 @@ runs on RAW_PCU_BTS_CT {
/* Patch TDMA frame / block number and send */
pcu_msg.u.rts_req.fn := ev_begin_fn;
- pcu_msg.u.rts_req.block_nr := 0; /* FIXME! */
+ pcu_msg.u.rts_req.block_nr := fn2macblock(ev_begin_fn);
PCUIF.send(pcu_msg);
repeat;
}
@@ -361,11 +484,16 @@ runs on RAW_PCU_BTS_CT {
[] CLCK.receive(tr_RAW_PCU_CLCK_EV) { repeat; }
}
-function f_BTS_CT_handler(integer bts_nr, PCUIF_info_ind info_ind)
+function f_BTS_CT_handler(integer bts_nr, PCUIF_info_ind info_ind, boolean decode_data_req := false)
runs on RAW_PCU_BTS_CT {
var PCUIF_Message pcu_msg;
var RAW_PCU_Command cmd;
var RAW_PCU_Event event;
+ var BTS_PDTCH_Block pcu_msg_pdtch;
+ var BTS_PTCCH_Block pcu_msg_ptcch;
+ var BTS_CCCH_Block pcu_msg_rr;
+
+ g_info_ind := info_ind;
/* Init TDMA clock generator (so we can stop and start it) */
vc_CLCK_GEN := RAW_PCU_ClckGen_CT.create("ClckGen-" & int2str(bts_nr)) alive;
@@ -387,11 +515,14 @@ runs on RAW_PCU_BTS_CT {
u := { info_ind := info_ind }
});
+ const integer start_fn := 0;
+ f_tx_first_data_ind(bts_nr, info_ind, start_fn);
+
/* Notify the test case that we're done with SI13 */
TC.send(ts_RAW_PCU_EV(BTS_EV_SI13_NEGO));
/* Start feeding clock to the PCU */
- vc_CLCK_GEN.start(f_ClckGen_CT_handler());
+ vc_CLCK_GEN.start(f_ClckGen_CT_handler(start_fn));
repeat;
}
/* PCU -> TS becomes active */
@@ -406,6 +537,59 @@ runs on RAW_PCU_BTS_CT {
"/TS" & int2str(pcu_msg.u.act_req.ts_nr));
repeat;
}
+ [decode_data_req] PCUIF.receive(tr_PCUIF_DATA_REQ(bts_nr, ?, ?, sapi := PCU_IF_SAPI_PCH_2)) -> value pcu_msg {
+ var charstring imsi_filter_regexp := "(\d*)"; /* numbers only */
+ var PCUIF_pch pch;
+
+ pcu_msg_rr.bts_nr := bts_nr;
+ pcu_msg_rr.raw := pcu_msg.u.data_req;
+
+ pch := dec_PCUIF_pch(pcu_msg_rr.raw.data);
+ pcu_msg_rr.msg_id := pch.msg_id;
+ pcu_msg_rr.imsi := regexp(pch.imsi, imsi_filter_regexp, 0);
+ pcu_msg_rr.rr_msg := dec_GsmRrMessage(pch.data);
+ pcu_msg_rr.confirm := pch.confirm;
+
+ TC.send(pcu_msg_rr);
+ repeat;
+ }
+ [decode_data_req] PCUIF.receive(tr_PCUIF_DATA_REQ(bts_nr, ?, ?, sapi := PCU_IF_SAPI_AGCH_2)) -> value pcu_msg {
+ var PCUIF_agch agch;
+
+ pcu_msg_rr.bts_nr := bts_nr;
+ pcu_msg_rr.raw := pcu_msg.u.data_req;
+
+ agch := dec_PCUIF_agch(pcu_msg_rr.raw.data);
+ pcu_msg_rr.imsi := omit;
+ pcu_msg_rr.msg_id := agch.msg_id;
+ pcu_msg_rr.rr_msg := dec_GsmRrMessage(agch.data);
+ pcu_msg_rr.confirm := agch.confirm;
+
+ TC.send(pcu_msg_rr);
+ repeat;
+ }
+ [decode_data_req] PCUIF.receive(tr_PCUIF_DATA_REQ(bts_nr, ?, ?, sapi := PCU_IF_SAPI_PDTCH)) -> value pcu_msg {
+ pcu_msg_pdtch.bts_nr := bts_nr;
+ pcu_msg_pdtch.raw := pcu_msg.u.data_req;
+ if (pcu_msg_pdtch.raw.len != 0) {
+ pcu_msg_pdtch.dl_block := dec_RlcmacDlBlock(pcu_msg_pdtch.raw.data);
+ } else {
+ pcu_msg_pdtch.dl_block := omit;
+ }
+ TC.send(pcu_msg_pdtch);
+ repeat;
+ }
+ [decode_data_req] PCUIF.receive(tr_PCUIF_DATA_REQ(bts_nr, ?, ?, sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
+ pcu_msg_ptcch.bts_nr := bts_nr;
+ pcu_msg_ptcch.raw := pcu_msg.u.data_req;
+ if (pcu_msg_ptcch.raw.len != 0) {
+ pcu_msg_ptcch.dl_block := dec_PTCCHDownlinkMsg(pcu_msg_ptcch.raw.data);
+ } else {
+ pcu_msg_ptcch.dl_block := omit;
+ }
+ TC.send(pcu_msg_ptcch);
+ repeat;
+ }
/* PCU -> test case forwarding (filter by the BTS number) */
[] PCUIF.receive(tr_PCUIF_MSG(?, bts_nr)) -> value pcu_msg {
TC.send(pcu_msg);
diff --git a/pcu/PCU_Tests.cfg b/pcu/PCU_Tests.cfg
index db6f56eb..6d3407de 100644
--- a/pcu/PCU_Tests.cfg
+++ b/pcu/PCU_Tests.cfg
@@ -8,12 +8,52 @@
[MODULE_PARAMETERS]
SGSN_Components.mp_nsconfig := {
- local_ip := "127.0.0.1",
- local_udp_port := 23000,
- remote_ip := "127.0.0.1",
- remote_udp_port := 22000,
- nsvci := 1234,
- nsei := 1234
+ nsei := 1234,
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23001,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23002,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ }
+ }
}
[TESTPORT_PARAMETERS]
diff --git a/pcu/PCU_Tests.default b/pcu/PCU_Tests.default
index 205327dd..c72720b7 100644
--- a/pcu/PCU_Tests.default
+++ b/pcu/PCU_Tests.default
@@ -4,24 +4,32 @@
[LOGGING]
#*.FileMask := LOG_ALL
-ConsoleMask := ERROR | WARNING | TESTCASE | TIMEROP_START | DEBUG_ENCDEC | USER
+ConsoleMask := ERROR | WARNING | TESTCASE | TIMEROP_START | USER
+PCUIF.ConsoleMask := ERROR | TESTCASE | TIMEROP_START | USER
+"ClckGen-0".ConsoleMask := ERROR
[MODULE_PARAMETERS]
SGSN_Components.mp_gb_cfg := {
nsei := 1234,
- bvci := 1234,
- cell_id := {
- ra_id := {
- lai := {
- mcc_mnc := '262F42'H, lac := 13135
+ sgsn_role := true,
+ bvc := {
+ {
+ bvci := 1234,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := '262F42'H, lac := 13135
+ },
+ rac := 0
+ },
+ cell_id := 20960
},
- rac := 0
- },
- cell_id := 20960
- },
- sgsn_role := true
-}
+ depth := BSSGP_DECODE_DEPTH_BSSGP
+ }
+ }
+};
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCU";
+PCUIF_Types.mp_pcuif_version := 12;
[TESTPORT_PARAMETERS]
*.PCU.socket_type := "SEQPACKET"
@@ -34,6 +42,15 @@ Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoPCU";
*.PCUVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
*.PCUVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
*.PCUVTY.PROMPT1 := "OsmoPCU> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4240"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoPCU> "
[MAIN_CONTROLLER]
diff --git a/pcu/PCU_Tests.ttcn b/pcu/PCU_Tests.ttcn
index f919dbef..cab70e8e 100644
--- a/pcu/PCU_Tests.ttcn
+++ b/pcu/PCU_Tests.ttcn
@@ -22,6 +22,7 @@ import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
import from GSM_RR_Types all;
+import from GSM_RestOctets all;
import from Osmocom_VTY_Functions all;
import from TELNETasp_PortType all;
@@ -51,18 +52,35 @@ import from Native_Functions all;
import from SGSN_Components all;
import from GPRS_Components all;
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from IPA_Emulation all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+import from Osmocom_CTRL_Functions all;
+
modulepar {
charstring mp_pcu_sock_path := PCU_SOCK_DEFAULT;
float X2002 := 0.2; /* Timer -2002, IMM ASSIGN confirm delay */
+
+ charstring mp_pcu_statsd_ip := "127.0.0.1";
+ integer mp_pcu_statsd_port := 8125;
+
+ charstring mp_ctrl_neigh_ip := ""; /* Use new PCUIF over IPA multiplex for Neigh Addr Resolution */
+ integer mp_ctrl_neigh_port := 4248;
}
/* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
-friend template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
+friend template (value) PCUIF_info_ind ts_PCUIF_INFO_default(template (value) PCUIF_Flags flags := c_PCUIF_Flags_default)
+:= {
version := PCUIF_Types.mp_pcuif_version,
- flags := c_PCUIF_Flags_default,
- trx := valueof(ts_PCUIF_InfoTrxs_def),
+ flags := flags,
+ trx := ts_PCUIF_InfoTrxs_def(GPRS_Components.mp_base_arfcn),
bsic := 7,
mcc := 262,
mnc := 42,
@@ -75,38 +93,71 @@ friend template (value) PCUIF_info_ind ts_PCUIF_INFO_default := {
cell_id := 20960,
repeat_time := 5 * 50,
repeat_count := 3,
- bvci := mp_gb_cfg.bvci,
+ bvci := mp_gb_cfg.bvc[0].bvci,
t3142 := 20,
t3169 := 5,
t3191 := 5,
t3193_10ms := 160,
t3195 := 5,
- t3101 := 10,
- t3103 := 4,
- t3105 := 8,
+ n3101 := 10,
+ n3103 := 4,
+ n3105 := 8,
cv_countdown := 15,
dl_tbf_ext := 250 * 10, /* ms */
ul_tbf_ext := 250 * 10, /* ms */
initial_cs := 2,
- initial_mcs := 6,
- nsvci := { mp_nsconfig.nsvci, 0 },
- local_pprt := { mp_nsconfig.remote_udp_port, 0 },
- remote_port := { mp_nsconfig.local_udp_port, 0 },
- remote_ip := { f_inet_haddr(mp_nsconfig.local_ip) , '00000000'O }
+ initial_mcs := 1,
+ nsvci := { mp_nsconfig.nsvc[0].nsvci, 0 },
+ local_port := { mp_nsconfig.nsvc[0].provider.ip.remote_udp_port, 0 },
+ remote_port := { mp_nsconfig.nsvc[0].provider.ip.local_udp_port, 0 },
+ remote_addr := f_PCUIF_RemoteAddr(
+ f_PCUIF_AF2addr_type(mp_nsconfig.nsvc[0].provider.ip.address_family), mp_nsconfig.nsvc[0].provider.ip.local_ip),
+ bts_model := PCU_IF_BTS_MODEL_TRX
}
+/* Passed in RAN-INFO message from emulated neighbor using RIM */
+const octetstring si1_default := '198fb100000000000000000000000000007900002b'O;
+const octetstring si3_default := '1b753000f110236ec9033c2747407900003c0b2b2b'O;
+const octetstring si13_default := '009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O;
+const octetstring si_default := si1_default & si3_default & si13_default;
+
+const MultislotCap_GPRS mscap_gprs_def := {
+ gprsmultislotclass := '00011'B,
+ gprsextendeddynalloccap := '0'B
+};
+const MultislotCap_EGPRS mscap_egprs_def := {
+ egprsmultislotclass := '00011'B,
+ egprsextendeddynalloccap := '0'B
+};
+template (value) MSRadioAccessCapabilityV ms_racap_gprs_def := { ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs_def, omit) };
+template (value) MSRadioAccessCapabilityV ms_racap_egprs_def := { ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs_def, mscap_egprs_def) };
+
+const MultislotCap_GPRS_BSSGP bssgp_mscap_gprs_def := {
+ gprsmultislotclass := '00011'B,
+ gprsextendeddynalloccap := '0'B
+};
+const MultislotCap_EGPRS_BSSGP bssgp_mscap_egprs_def := {
+ egprsmultislotclass := '00011'B,
+ egprsextendeddynalloccap := '0'B
+};
+template (value) MSRadioAccessCapabilityV_BSSGP bssgp_ms_racap_gprs_def := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, bssgp_mscap_gprs_def, omit)) };
+template (value) MSRadioAccessCapabilityV_BSSGP bssgp_ms_racap_egprs_def := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, bssgp_mscap_gprs_def, bssgp_mscap_egprs_def)) };
+
type record lqual_range {
/* component reference to the IPA_Client component used for RSL */
uint8_t low,
uint8_t high
}
-type component RAW_PCU_Test_CT extends bssgp_CT, MS_BTS_IFACE_CT {
+type component RAW_PCU_Test_CT extends bssgp_CT, MS_BTS_IFACE_CT, StatsD_ConnHdlr, CTRL_Adapter_CT {
/* PCU interface abstraction component */
var RAW_PCUIF_CT vc_PCUIF;
+ /* StatsD */
+ var StatsD_Checker_CT vc_STATSD;
+
/* Connection to the PCUIF component */
- port RAW_PCU_MSG_PT PCUIF;
+ //port RAW_PCU_MSG_PT PCUIF;
/* VTY connection to the PCU */
port TELNETasp_PT PCUVTY;
@@ -133,7 +184,6 @@ type component RAW_PCU_Test_CT extends bssgp_CT, MS_BTS_IFACE_CT {
var uint8_t g_mcs_max_dl := 9;
var uint8_t g_mcs_max_ul := 9;
- var boolean g_egprs_only := false;
var boolean g_force_two_phase_access := false;
/* Guard timeout */
@@ -178,12 +228,40 @@ private function f_pcuvty_set_link_quality_ranges() runs on RAW_PCU_Test_CT {
f_vty_config2(PCUVTY, {"pcu"}, cmd);
}
-private function f_init_vty(charstring id) runs on RAW_PCU_Test_CT {
+private function f_pcuvty_flush_neigh_caches() runs on RAW_PCU_Test_CT {
+ f_pcuvty_set_neigh_caches(0, 0);
+}
+
+private function f_pcuvty_set_neigh_caches(integer neigh_cache_secs := -1, integer si_cache_secs := -1)
+runs on RAW_PCU_Test_CT {
+ if (neigh_cache_secs == -1) {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X10 default");
+ } else {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X10 " & int2str(neigh_cache_secs));
+ }
+ if (si_cache_secs == -1) {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X11 default");
+ } else {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X11 " & int2str(si_cache_secs));
+ }
+}
+
+private function f_pcuvty_set_timer(integer t, integer val)
+runs on RAW_PCU_Test_CT {
+ if (t >= 0) {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer T" & int2str(t) & " " & int2str(val));
+ } else {
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X" & int2str(t * -1) & " " & int2str(val));
+ }
+}
+
+private function f_init_vty(charstring id, boolean egprs_only) runs on RAW_PCU_Test_CT {
map(self:PCUVTY, system:PCUVTY);
f_vty_set_prompts(PCUVTY);
f_vty_transceive(PCUVTY, "enable");
- if (g_egprs_only) {
+ /* This will be removed soon, not needed. EGPRS support is controlled through pcu_ind flags */
+ if (egprs_only) {
f_vty_config2(PCUVTY, {"pcu"}, "egprs only");
} else {
f_vty_config2(PCUVTY, {"pcu"}, "no egprs");
@@ -203,27 +281,105 @@ runs on RAW_PCU_Test_CT {
activate(as_Tguard_RAW());
/* Init PCU interface component */
- vc_PCUIF := RAW_PCUIF_CT.create("PCUIF-" & id);
- connect(vc_PCUIF:MTC, self:PCUIF);
+ vc_PCUIF := RAW_PCUIF_CT.create("PCUIF") alive;
+ //connect(vc_PCUIF:MTC, self:PCUIF);
map(vc_PCUIF:PCU, system:PCU);
/* Create one BTS component (we may want more some day) */
- vc_BTS := RAW_PCU_BTS_CT.create("BTS-" & id);
+ vc_BTS := RAW_PCU_BTS_CT.create("BTS") alive;
connect(vc_BTS:PCUIF, vc_PCUIF:BTS);
connect(vc_BTS:TC, self:BTS);
- f_init_vty(id);
+ f_init_vty(id, f_pcuif_ind_flags_egprs_enabled(valueof(info_ind.flags)));
+
+ f_init_statsd(id, vc_STATSD, mp_pcu_statsd_ip, mp_pcu_statsd_port);
+ /* This is normally done in the ConnHdlr component, but here
+ * the Test_CT doubles as ConnHdlr */
+ connect(self:STATSD_PROC, vc_STATSD:STATSD_PROC);
vc_PCUIF.start(f_PCUIF_CT_handler(mp_pcu_sock_path));
- vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind)));
+ vc_BTS.start(f_BTS_CT_handler(0, valueof(info_ind), true));
/* Wait until the BTS is ready (SI13 negotiated) */
BTS.receive(tr_RAW_PCU_EV(BTS_EV_SI13_NEGO));
}
+/* Register TLLI of each allocated GprsMS instance */
+private function f_multi_ms_bssgp_register()
+runs on RAW_PCU_Test_CT {
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, g_ms[i].tlli);
+ }
+}
+
+/* Allocate [and activate] an Uplink TBF for each allocated GprsMS instance */
+private function f_multi_ms_establish_tbf(boolean do_activate := false)
+runs on RAW_PCU_Test_CT {
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(g_ms[i]);
+
+ /* Send a random block, so this TBF becomes "active" */
+ if (do_activate) {
+ /* FIXME: use the new APU by Pau to get correct TRX/TS here */
+ var template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum(7, i mod 8);
+ var octetstring dummy := f_rnd_octstring(12);
+ var RlcmacDlBlock dl_block;
+ var uint32_t poll_fn;
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(g_ms[i]);
+
+ f_ms_tx_ul_data_block(g_ms[i], dummy, with_tlli := true, fn := g_ms[i].ul_tbf.start_time_fn, nr := nr);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn, nr := nr);
+ }
+ }
+}
+
+private function f_ms_establish_ul_tbf_2phase_access(inout GprsMS ms,
+ template (omit) RlcmacUlCtrlMsg pkt_res_req := omit)
+runs on RAW_PCU_Test_CT return PollFnCtx {
+ var PollFnCtx pollctx;
+
+ /* Single block (two phase) packet access */
+ var uint16_t ra := bit2int(chan_req_sb);
+ if (g_force_two_phase_access) {
+ /* If 2phase access is enforced by the network, then let's
+ * request a One phase packet access, we'll receive a single block
+ * anyway
+ */
+ ra := bit2int(chan_req_def);
+ }
+
+ /* Establish an Uplink TBF */
+ f_ms_use_ra(ms, ra, ra_is_11bit := 0);
+ f_ms_establish_ul_tbf(ms);
+
+ /* Make sure we've got an Uplink TBF assignment */
+ if (not match(ms.ul_tbf.ass.ccch, tr_PacketUlSglAssign)) {
+ setverdict(fail, "Wrong Packet Uplink Assignment received: ", ms.ul_tbf.ass.ccch, " vs exp: ", tr_PacketUlSglAssign);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Send PACKET RESOURCE REQUEST
+ * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
+ */
+ if (istemplatekind(pkt_res_req, "omit")) {
+ pkt_res_req := ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit);
+ }
+
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(valueof(pkt_res_req)), ms.ul_tbf.start_time_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
+ /* Store 1st UlTBF context before receiving next one, will
+ * overwrite the TS allocation on MS with info from new UL TBF:
+ */
+ pollctx.tstrxbts := f_ms_tx_TsTrxBtsNum(ms);
+ f_ms_rx_pkt_ass_pacch(ms, pollctx.fn, tr_RLCMAC_UL_PACKET_ASS, nr := f_ms_tx_TsTrxBtsNum(ms));
+ return pollctx;
+}
+
testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
- var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.cell_id.ra_id);
- var GprsTlli tlli := 'FFFFFFFF'O;
+ var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.bvc[0].cell_id.ra_id);
+ var GprsTlli tlli := TLLI_UNUSED;
timer T;
/* Initialize NS/BSSGP side */
@@ -239,7 +395,7 @@ testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
T.start(2.0);
alt {
- [] BSSGP_SIG[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.cell_id.ra_id)) {
+ [] BSSGP_GLOBAL[0].receive(tr_BSSGP_SUSPEND(tlli, mp_gb_cfg.bvc[0].cell_id.ra_id)) {
setverdict(pass);
}
[] T.timeout {
@@ -250,6 +406,86 @@ testcase TC_pcuif_suspend() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Make sure TBF is released and no data is sent for in after reciving a Suspend Request from that MS. See OS#4761 */
+testcase TC_pcuif_suspend_active_tbf() runs on RAW_PCU_Test_CT {
+ var octetstring ra_id := enc_RoutingAreaIdentification(mp_gb_cfg.bvc[0].cell_id.ra_id);
+ var BTS_PDTCH_Block data_msg;
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ timer T;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* MS has moved to CS, it sent SUSP REQ to BTS and PCU gets it, TBF is freed: */
+ BTS.send(ts_PCUIF_SUSP_REQ(0, ms.tlli, ra_id, 0));
+
+ T.start(2.0);
+ alt {
+ [] BSSGP_GLOBAL[0].receive(tr_BSSGP_SUSPEND(ms.tlli, mp_gb_cfg.bvc[0].cell_id.ra_id)) {
+ setverdict(pass);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for BSSGP SUSPEND");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Make sure we don't receive data for that TBF since it was released
+ * before. Also check our TBF is not polled for UL. */
+ f_pcuif_rx_data_req_pdtch(data_msg);
+ if (data_msg.dl_block == omit) {
+ /* IDLE block, expected on new PCU versions */
+ } else {
+ setverdict(fail, "Unexpected dl_block", data_msg.dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* New data arrives, PCU should page the MS since no TBF active exists: */
+ /* Send some more data, it will never reach the MS */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
/* Test of correct Timing Advance at the time of TBF establishment
* (derived from timing offset of the Access Burst). */
testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
@@ -259,7 +495,7 @@ testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
f_init_gprs_ms();
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* We cannot send too many TBF requests in a short time because
* at some point the PCU will fail to allocate a new TBF. */
@@ -280,13 +516,70 @@ testcase TC_ta_rach_imm_ass() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Verify Timing Advance value indicated in Packet Uplink ACK/NACK message
+ * sent in response to the first Uplink block after resource allocation. */
+testcase TC_ta_ul_ack_nack_first_block() runs on RAW_PCU_Test_CT {
+ var GprsMS ms := valueof(t_GprsMS_def);
+ var PacketUlAckNack ul_ack_nack;
+ var PacketTimingAdvance pkt_ta;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* In a busy network, there can be a significant delay between resource
+ * allocation (Packet Uplink Assignment above) and the actual time when
+ * the MS is allowed to transmit the first Uplink data block. */
+
+ /* Simulate a delay > 0 */
+ ms.ta := 2;
+
+ /* We're in One-Phase Access contention resolution, include TLLI */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+
+ ul_ack_nack := dl_block.ctrl.payload.u.ul_ack_nack;
+ if (ispresent(ul_ack_nack.gprs.pkt_ta)) {
+ pkt_ta := ul_ack_nack.gprs.pkt_ta;
+ } else if (ispresent(ul_ack_nack.egprs.pkt_ta)) {
+ pkt_ta := ul_ack_nack.egprs.pkt_ta;
+ } else {
+ setverdict(fail, "PacketTimingAdvance IE is not present");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ if (not ispresent(pkt_ta.val)) {
+ setverdict(fail, "Timing Advance value is not present");
+ f_shutdown(__BFILE__, __LINE__);
+ } else if (pkt_ta.val != ms.ta) {
+ setverdict(fail, "Timing Advance mismatch: expected ",
+ ms.ta, ", but received ", pkt_ta.val);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
/* Verify Timing Advance value(s) indicated during the packet Downlink assignment
* procedure as per 3GPP TS 44.018, section 3.5.3. There seems to be a bug in the
* IUT that causes it to send an unreasonable Timing Advance value > 0 despite
* no active TBF exists at the moment of establishment (idle mode). */
testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
- var OCT4 tlli := f_rnd_octstring(4);
- var GsmRrMessage rr_imm_ass;
+ var GprsMS ms := valueof(t_GprsMS_def);
/* Initialize NS/BSSGP side */
f_init_bssgp();
@@ -296,28 +589,27 @@ testcase TC_ta_idle_dl_tbf_ass() runs on RAW_PCU_Test_CT {
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* SGSN sends some DL data, PCU will initiate Packet Downlink
* Assignment on CCCH (PCH). We don't care about the payload. */
- BSSGP[0].send(ts_BSSGP_DL_UD(tlli, f_rnd_octstring(10)));
- rr_imm_ass := f_pcuif_rx_imm_ass(PCU_IF_SAPI_PCH, tr_IMM_TBF_ASS(dl := true));
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, f_rnd_octstring(10), imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Make sure that Timing Advance is 0 (the actual value is not known yet).
* As per 3GPP S 44.018, section 3.5.3.1.2, the network *shall* initiate
* the procedures defined in 3GPP TS 44.060 or use the polling mechanism. */
- if (rr_imm_ass.payload.imm_ass.timing_advance != 0) {
+ if (ms.dl_tbf.rr_imm_ass.payload.imm_ass.timing_advance != 0) {
setverdict(fail, "Timing Advance value doesn't match");
}
f_shutdown(__BFILE__, __LINE__, final := true);
}
-/* Verify that the PCU generates valid PTCCH/D messages
+/* Verify that the PCU generates idle blocks in PTCCH/D
* while neither Uplink nor Downlink TBF is established. */
testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
- var PTCCHDownlinkMsg ptcch_msg;
- var PCUIF_Message pcu_msg;
+ var BTS_PTCCH_Block pcu_msg;
timer T;
/* Initialize the PCU interface abstraction */
@@ -327,28 +619,24 @@ testcase TC_ta_ptcch_idle() runs on RAW_PCU_Test_CT {
BTS.send(ts_PCUIF_RTS_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
sapi := PCU_IF_SAPI_PTCCH, fn := 0,
arfcn := 871, block_nr := 0));
+
T.start(5.0);
alt {
- [] BTS.receive(tr_PCUIF_DATA_REQ(bts_nr := 0, trx_nr := 0, ts_nr := 7,
- sapi := PCU_IF_SAPI_PTCCH)) -> value pcu_msg {
- log("Rx DATA.req message: ", pcu_msg);
- setverdict(pass);
- }
+ [] BTS.receive(tr_PCUIF_DATA_PTCCH(0,
+ tr_PCUIF_DATA(0, 7, sapi := PCU_IF_SAPI_PTCCH),
+ omit)) {
+ }
+ [] as_rx_ptcch(pcu_msg, tr_PTCCHDownlinkMsg) {
+ setverdict(fail, "Expected IDLE block instead of PTCCH/D block");
+ f_shutdown(__BFILE__, __LINE__);
+ }
[] BTS.receive(PCUIF_Message:?) { repeat; }
[] T.timeout {
setverdict(fail, "Timeout waiting for a PTCCH/D block");
f_shutdown(__BFILE__, __LINE__);
}
}
-
- ptcch_msg := dec_PTCCHDownlinkMsg(pcu_msg.u.data_req.data);
- log("Decoded PTCCH/D message: ", ptcch_msg);
-
- /* Make sure the message is encoded correctly
- * TODO: do we expect all TA values to be equal '1111111'B? */
- if (not match(ptcch_msg, tr_PTCCHDownlinkMsg)) {
- setverdict(fail, "Malformed PTCCH/D message");
- }
+ log("Decoded PTCCH/D message: ", pcu_msg.dl_block);
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -539,7 +827,7 @@ testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
f_pcuvty_set_allowed_cs_mcs();
f_pcuvty_set_link_quality_ranges();
@@ -547,6 +835,8 @@ testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
/* The actual / old link quality values. We need to keep track of the old
* (basically previous) link quality value, because OsmoPCU actually
@@ -556,10 +846,10 @@ testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
ms.lqual_cb := 0;
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
+ contention resolution) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -582,7 +872,7 @@ testcase TC_cs_lqual_ul_tbf() runs on RAW_PCU_Test_CT {
/* we will receive UL ACK/NACK from time to time. In that case, check CdCofing increases */
f_rx_rlcmac_dl_block(dl_block, unused_fn);
- if (match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
continue;
}
if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK_GPRS(ul_tfi := ?)) and
@@ -626,7 +916,7 @@ testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Set initial UL CS to 3 */
g_cs_initial_ul := 3;
@@ -639,11 +929,14 @@ testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
+ contention resolution) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -652,7 +945,7 @@ testcase TC_cs_initial_ul() runs on RAW_PCU_Test_CT {
while (true) {
f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 15);
f_rx_rlcmac_dl_block(dl_block, unused_fn);
- if (match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
continue;
}
@@ -701,7 +994,7 @@ testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Set maximum allowed UL CS to 3 */
g_cs_max_ul := 3;
@@ -711,11 +1004,14 @@ testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
+ contention resolution) and make sure it is ACKED fine. */
/* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(16), cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -734,12 +1030,354 @@ testcase TC_cs_max_ul() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Test the initial DL CS set by VTY works fine */
+testcase TC_cs_initial_dl() runs on RAW_PCU_Test_CT {
+ var octetstring data := f_rnd_octstring(10);
+ var CodingScheme exp_dl_cs_mcs;
+ var RlcmacDlBlock dl_block;
+ var uint32_t poll_fn;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Set initial allowed DL CS to 3 */
+ g_cs_initial_dl := 3;
+ exp_dl_cs_mcs := CS_3;
+ /* Set maximum allowed UL CS to 4 */
+ g_cs_max_dl := 4;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, poll_fn, data, 0, exp_dl_cs_mcs);
+
+ /* ACK the DL block */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, poll_fn));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify scheduling of multiple Downlink data blocks, enough to reach CS4 */
+function f_dl_data_exp_cs(template (present) CodingScheme exp_final_cs := ?, template (omit) MSRadioAccessCapabilityV_BSSGP ms_racap := omit) runs on RAW_PCU_Test_CT {
+ var octetstring data := f_rnd_octstring(1400);
+ var RlcmacDlBlock prev_dl_block, dl_block;
+ var uint32_t ack_fn;
+ var uint32_t fn;
+ var GprsMS ms;
+ var integer tx_data_remain := 10;
+ var integer bsn := 0;
+ var boolean using_egprs := f_rlcmac_cs_mcs_is_mcs(valueof(exp_final_cs));
+ var integer bsn_mod;
+ var template (present) CodingScheme exp_tmp_csmcs;
+
+ if (using_egprs) {
+ exp_tmp_csmcs := mcs_egprs_any;
+ bsn_mod := 2048;
+ } else {
+ exp_tmp_csmcs := cs_gprs_any;
+ bsn_mod := 128;
+ }
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+
+ ms := g_ms[0]; /* We only use first MS in this test */
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, ms_racap, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
+ f_sleep(X2002);
+
+ /* Skip potential dummy blocks before X2002 triggers at PCU after us: */
+ fn := f_rx_rlcmac_dl_block_skip_dummy(dl_block, max_dummy := 10);
+
+ for (var integer i := 0; i < 800; i := i + 1) {
+ bsn := i mod bsn_mod;
+
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL)) {
+ /* No more data to receive, done */
+ break;
+ }
+
+ f_rlcmac_dl_block_exp_data(dl_block, ?, bsn, exp_tmp_csmcs);
+
+ /* Keep Ack/Nack description updated */
+ f_dltbf_ack_block(ms.dl_tbf, dl_block);
+
+ /* TDMA frame number on which we are supposed to send the ACK */
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ ack_fn := f_dl_block_ack_fn(dl_block, fn);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, using_egprs), ack_fn);
+ if (tx_data_remain != 0) {
+ /* Submit more data from time to time to keep the TBF ongoing */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+ tx_data_remain := tx_data_remain - 1;
+ }
+ }
+ prev_dl_block := dl_block;
+ f_rx_rlcmac_dl_block(dl_block, fn);
+ }
+
+ bsn := (bsn + (bsn_mod-1)) mod bsn_mod; /* previous bsn: bsn -1 */
+ f_rlcmac_dl_block_exp_data(prev_dl_block, ?, bsn, exp_final_cs);
+
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify DL CS above "cs max" set by VTY is never used */
+testcase TC_cs_max_dl() runs on RAW_PCU_Test_CT {
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Set maximum allowed DL CS to 3 */
+ g_cs_initial_dl := 1;
+ g_cs_max_dl := 3;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ f_dl_data_exp_cs(f_rlcmac_block_int2cs_mcs(g_cs_max_dl, false));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Check DL CS4 is used in good link conditions if allowed by config */
+testcase TC_dl_cs1_to_cs4() runs on RAW_PCU_Test_CT {
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Set initial DL CS to 1 & maximum allowed DL CS to 4 */
+ g_cs_initial_dl := 1;
+ g_cs_max_dl := 4;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ f_dl_data_exp_cs(f_rlcmac_block_int2cs_mcs(g_cs_max_dl, false));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test the initial UL MCS set by VTY works fine */
+testcase TC_mcs_initial_ul() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var PollFnCtx pollctx;
+ var EgprsChCodingCommand last_ch_coding;
+ var uint32_t unused_fn, sched_fn;
+ var GprsMS ms;
+ var CodingScheme exp_ul_mcs;
+
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Set initial UL MCS to 3 */
+ g_mcs_initial_ul := 3;
+ exp_ul_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, true);
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ /* Take lqual (dB->cB) so that we stay in that MCS */
+ ms.lqual_cb := g_mcs_lqual_ranges[2].low * 10;
+
+ /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_egprs_def));
+
+ if (not match(ms.ul_tbf.tx_cs_mcs, exp_ul_mcs)) {
+ setverdict(fail, "Wrong CS_MCS ", ms.ul_tbf.tx_cs_mcs, " received vs exp ", exp_ul_mcs);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Send UL blocks, until we receive UL ACK/NACK and check we are in same initial CS: */
+ while (true) {
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 15);
+ f_rx_rlcmac_dl_block(dl_block, unused_fn);
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
+ continue;
+ }
+
+ if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK_EGPRS(ul_tfi := ?))) {
+ setverdict(fail, "Failed to match Packet Uplink ACK / NACK:", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ break;
+ }
+
+ last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.egprs.ch_coding_cmd;
+ break;
+ }
+ if (f_rlcmac_block_EgprsChCodingCommand2cs_mcs(last_ch_coding) != exp_ul_mcs) {
+ setverdict(fail, "Channel Coding does not match our expectations ", exp_ul_mcs, ": ", last_ch_coding);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Remaining UL blocks are used to make sure regardless of initial
+ * lqual, we can go lower at any time
+ * 0 dB, make sure we downgrade MCS */
+ ms.lqual_cb := 0;
+ /* 5 UL blocks, check we are in same initial MCS: */
+ f_ms_tx_ul_data_block_multi(ms, 5);
+ /* Enqueue RTS.req, expect DATA.req with UL ACK from the PCU */
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
+ last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.egprs.ch_coding_cmd;
+
+ if (last_ch_coding != CH_CODING_MCS1) {
+ setverdict(fail, "Channel Coding does not match our expectations (MCS-1): ", last_ch_coding);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test the maximum UL MCS set by VTY works fine */
+testcase TC_mcs_max_ul() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var EgprsChCodingCommand last_ch_coding;
+ var PollFnCtx pollctx;
+ var uint32_t unused_fn, sched_fn;
+ var GprsMS ms;
+
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Set maximum allowed UL MCS to 5 */
+ g_mcs_max_ul := 5;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_egprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ ms.lqual_cb := 40*10; /* 40 dB */
+ f_ms_tx_ul_data_block_multi(ms, 16);
+
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
+ last_ch_coding := dl_block.ctrl.payload.u.ul_ack_nack.egprs.ch_coding_cmd;
+
+ if (last_ch_coding != CH_CODING_MCS5) {
+ setverdict(fail, "Channel Coding does not match our expectations (MCS-5): ", last_ch_coding);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test the initial DL CS set by VTY works fine */
+testcase TC_mcs_initial_dl() runs on RAW_PCU_Test_CT {
+ var octetstring data := f_rnd_octstring(10);
+ var CodingScheme exp_dl_cs_mcs;
+ var RlcmacDlBlock dl_block;
+ var uint32_t poll_fn;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Set initial allowed DL MCS to 3 */
+ g_mcs_initial_dl := 3;
+ exp_dl_cs_mcs := MCS_3;
+ /* Set maximum allowed DL MCS to 4 */
+ g_mcs_max_dl := 4;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, bssgp_ms_racap_egprs_def, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, poll_fn, data, 0, exp_dl_cs_mcs);
+
+ /* ACK the DL block */
+ f_dltbf_ack_block(ms.dl_tbf, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, ischosen(dl_block.data_egprs)),
+ f_dl_block_ack_fn(dl_block, poll_fn));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify DL MCS above "mcs max" set by VTY is never used */
+testcase TC_mcs_max_dl() runs on RAW_PCU_Test_CT {
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Set maximum allowed DL CS to 3 */
+ g_mcs_initial_dl := 1;
+ g_mcs_max_dl := 3;
+ f_pcuvty_set_allowed_cs_mcs();
+ f_pcuvty_set_link_quality_ranges();
+
+ f_dl_data_exp_cs(f_rlcmac_block_int2cs_mcs(g_mcs_max_dl, true), bssgp_ms_racap_egprs_def);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
/* Verify PCU drops TBF after some time of inactivity. */
-testcase TC_t3169() runs on RAW_PCU_Test_CT {
+testcase TC_t3141() runs on RAW_PCU_Test_CT {
var PCUIF_info_ind info_ind;
- var RlcmacDlBlock dl_block;
- var uint32_t unused_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
var GprsMS ms;
+ var uint3_t rx_usf;
+ timer T_3141 := 1.0;
+ var boolean ul_tbf_usf_req := false;
/* Initialize NS/BSSGP side */
f_init_bssgp();
@@ -747,32 +1385,492 @@ testcase TC_t3169() runs on RAW_PCU_Test_CT {
f_init_gprs_ms();
ms := g_ms[0]; /* We only use first MS in this test */
- info_ind := valueof(ts_PCUIF_INFO_default);
- /* Set timer to 1 sec (default 5) to speedup test: */
- info_ind.t3169 := 1;
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Only use 1 PDCH to simplify test: */
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ f_vty_config2(PCUVTY, {"pcu"}, "timer T3141 1");
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish a one-phase access Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ T_3141.start;
+
+ /* Now we wait for PCU to transmit our USF */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ ?)) -> value data_msg {
+ if (ms.ul_tbf.usf[valueof(nr.ts_nr)] == USF_UNUSED) {
+ setverdict(fail, "Unexpected ts_nr ", valueof(nr.ts_nr), " without USF allocated");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ rx_usf := f_rlcmac_dl_block_get_usf(data_msg.dl_block);
+ if (rx_usf == ms.ul_tbf.usf[valueof(nr.ts_nr)]) {
+ /* PCU requests our USF, transmit WITHOUT tlli to avoid contention resolution success */
+ ul_tbf_usf_req := true;
+ f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 15, with_tlli := false, fn := f_next_pdch_block(data_msg.raw.fn))
+ } else if (rx_usf == USF_UNUSED) {
+ if (data_msg.raw.fn >= ms.ul_tbf.start_time_fn) {
+ if (ul_tbf_usf_req) {
+ /* TBF was dropped by T3141, success */
+ setverdict(pass);
+ break;
+ } else {
+ log("PCU never requested USF, unexpected");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } /* else: Keep waiting for TBF to be active by network */
+ } else {
+ log("PCU requests ", rx_usf, ", we have ", ms.ul_tbf.usf[valueof(nr.ts_nr)]);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* Make sure we don't receive a Ul ACK/NACK with TLLI set: */
+ if (match(data_msg.dl_block,
+ tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
+ tr_UlAckNackGprs(tlli := ?,
+ acknack_desc := ?,
+ rel99 := *))))
+ {
+ log("Received UL ACK/NACK with TLLI set");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [ul_tbf_usf_req] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) {
+ /* TBF was dropped by T3141, and PCU answered with an IDLE block to
+ our last RTS.req because there's no longer any MS listening on
+ the TS. */
+ setverdict(pass);
+ break;
+ }
+ [] T_3141.timeout {
+ log("T_3141 expired but TBF is still active, unexpected");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] BTS.receive {
+ /* We should never receive non-dummy messages, aka UL ACK/NACK,
+ * because we never sent the TLLI to the PCU */
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Validate what happens when RACH to get UL TBF and then PCU receives no UL
+ * data. It should end up in N3101 reaching N3101_MAX and finally triggering
+ * T3169. See OS#5033 */
+testcase TC_n3101_max_t3169() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var GprsMS ms;
+ var uint3_t rx_usf;
+ const integer N3101_MAX := 9; /* N3101 shall be greater than 8 */
+ var integer n3101 := 0;
+ timer T_3169 := 1.0;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ info_ind.n3101 := N3101_MAX;
+ info_ind.t3169 := 1;
f_init_raw(testcasename(), info_ind);
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish UL TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Now we wait for PCU to transmit our USF */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ ?)) -> value data_msg {
+ if (ms.ul_tbf.usf[valueof(nr.ts_nr)] == USF_UNUSED) {
+ setverdict(fail, "Unexpected ts_nr ", valueof(nr.ts_nr), " without USF allocated");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ rx_usf := f_rlcmac_dl_block_get_usf(data_msg.dl_block);
+ if (rx_usf == ms.ul_tbf.usf[valueof(nr.ts_nr)]) {
+ log("PCU requests our USF ", rx_usf, ", n3101=", n3101);
+ n3101 := n3101 + 1;
+ if (n3101 > N3101_MAX + 1) { //+1: DL<->UL FN offset
+ setverdict(fail, "Reached ", n3101, " > ", N3101_MAX + 1, " (N3101_MAX+1) and PCU still sends us USFs");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } else if (rx_usf == USF_UNUSED and n3101 == N3101_MAX + 1) {
+ /* If we already received USFs for us and we don't receive them anymore, that means the TBF entered T3169 */
+ log("PCU stopped requesting USF ", ms.ul_tbf.usf[valueof(nr.ts_nr)]);
+ if (not T_3169.running) {
+ log("T3169 started");
+ T_3169.start;
+ }
+ } else if(rx_usf == USF_UNUSED and n3101 > 0) {
+ setverdict(fail, "PCU stopped requesting USFs too early: ", n3101, " < ", N3101_MAX, " (N3101_MAX)");
+ f_shutdown(__BFILE__, __LINE__);
+ } else {
+ log("PCU requests ", rx_usf, ", we have ", ms.ul_tbf.usf[valueof(nr.ts_nr)]);
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ /* We may already receive empty (idle) blocks before our own TTCN3 timer
+ * triggers due to the TBF being released. Keep going until our T_3169 triggers. */
+ [n3101 == N3101_MAX + 1] as_pcuif_rx_ignore_empty(nr);
+ [] T_3169.timeout {
+ log("T_3169 expired");
+ /* Done in alt */
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Now that T3169 has expired, establishing a Ul TBF should provide same
+ /* USFs as per previous TBF since they were freed at expiration time: */
+ var uint3_t old_usf[8] := ms.ul_tbf.usf;
+ var uint5_t old_tfi := ms.ul_tbf.tfi;
+ f_ms_establish_ul_tbf(ms);
+ if (old_tfi != ms.ul_tbf.tfi) {
+ setverdict(fail, "Unexpected TFI change: ", ms.ul_tbf.tfi, " vs exp ", old_tfi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ for (var integer i := 0; i < 8; i := i +1) {
+ if (ms.ul_tbf.usf[i] != old_usf[i]) {
+ setverdict(fail, "Unexpected USF change: ", ms.ul_tbf.usf[i], " vs exp ", old_usf[i]);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+
+/* Verify after N3103_MAX is reached, T3169 is started and upon timeout TBF is
+ freed and no longer available. Trigger it by sending a few UL blocks CTRL ACKING
+ the final UL ACK sent at us. */
+testcase TC_n3103_max_t3169() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var BTS_PDTCH_Block data_msg;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var template (value) TsTrxBtsNum nr;
+ var template RlcmacDlBlock exp_ul_ack;
+ var template UlAckNackGprs exp_ul_ack_sub;
+ var GprsMS ms;
+ const integer N3103_MAX := 2; /* N3103 is usually somewhere 2-5 */
+ var integer N3103 := 0;
+ timer T_3169 := 1.0;
+
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ info_ind.n3103 := N3103_MAX;
+ info_ind.t3169 := 1;
+ f_init_raw(testcasename(), info_ind);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
- /* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 1, with_tlli := true)
- f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, unused_fn);
- /* UL block should NOT be received in SGSN, since we didn't get CV=0 */
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
- /* Wait until T3169 fires (plus 1 extra sec to make sure) */
- f_sleep(int2float(info_ind.t3169) + 1.0);
+ f_ms_tx_ul_data_block_multi(ms, 5, with_tlli := true);
+ exp_ul_ack_sub := tr_UlAckNackGprs(*, tr_AckNackDescription('1'B), *);
+ exp_ul_ack := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi, exp_ul_ack_sub);
- /* Send an UL block once again, the TBF should be gone by now so no ACK */
- f_ms_tx_ul_data_block(ms, f_rnd_octstring(10), cv := 0)
- f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [N3103 < N3103_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ exp_ul_ack)) -> value data_msg {
+ if (not f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ setverdict(fail, "Unexpected DL BLOCK has no RRBP: ", data_msg.dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ N3103 := N3103 + 1;
+ if (N3103 == N3103_MAX) {
+ /* At this point in time (N3103_MAX reached), PCU is
+ * moving the TBF to RELEASE state so no data/ctrl for
+ * it is tx'ed, hence the dummy blocks: */
+ T_3169.start;
+ }
+ repeat;
+ }
+ [N3103 >= N3103_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ exp_ul_ack)) -> value data_msg {
+ setverdict(fail, "Unexpected UL ACK/NACK after reaching N3103_MAX");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] as_ms_rx_ignore_dummy(ms, nr);
+ [] as_pcuif_rx_ignore_empty(nr);
+ [T_3169.running] T_3169.timeout {
+ log("T_3169 timeout");
+ /* Done in alt, wait for pending RTS initiated previously in
+ * above case before continuing (expect /* Dummy block): */
+ BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL));
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Now that T3169 has expired, establishing a Ul TBF should provide same
+ * USFs as per previous TBF since they were freed at expiration time: */
+ var uint3_t old_usf[8] := ms.ul_tbf.usf;
+ var uint5_t old_tfi := ms.ul_tbf.tfi;
+ f_ms_establish_ul_tbf(ms);
+ if (old_tfi != ms.ul_tbf.tfi) {
+ setverdict(fail, "Unexpected TFI change: ", ms.ul_tbf.tfi, " vs exp ", old_tfi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ for (var integer i := 0; i < 8; i := i +1) {
+ if (ms.ul_tbf.usf[i] != old_usf[i]) {
+ setverdict(fail, "Unexpected USF change: ", ms.ul_tbf.usf[i], " vs exp ", old_usf[i]);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify that a Downlink TBF is kept available until T3191 fires, at which
+ * point the TBF is no longer available. In order to get to start of T3191, we
+ * have to wait for x2031 since that marks the IDLE TBF time, that is, the delay
+ * until TBF release procedure starts after draining DL queue. */
+testcase TC_x2031_t3191() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring data1 := f_rnd_octstring(200);
+ var octetstring data2 := f_rnd_octstring(10);
+ var uint32_t dl_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Set timer to 1 sec (default 5) to speedup test: */
+ info_ind.t3191 := 1;
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data1, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+
+ while (true) {
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, ?, ?);
+
+ /* Keep Ack/Nack description updated (except for last BSN) */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block);
+
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+ break;
+ }
+ }
+
+ /* Now we wait for IDLE TBF timer (X2031) to time out and receive a FINAL ACK */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] as_ms_rx_ignore_dummy(ms, nr);
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ ?)) -> value data_msg {
+ if (data_msg.dl_block.data.mac_hdr.hdr_ext.fbi) {
+ log("Received FINAL_ACK");
+ ms.dl_tbf.acknack_desc.final_ack := '1'B;
+ break;
+ }
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, data_msg.dl_block);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, data_msg.raw.fn));
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* Avoid ACKing the last RLC data block on purpose here, wait for t3191
+ to time out. We simply sleep instead of requesting blocks because
+ otherwise retransmissions would keep restarting the timer. */
+ f_sleep(int2float(info_ind.t3191));
+
+ /* The TBF should be freed now, so new data should trigger an Assignment: */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data2, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data2, 0);
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Same as TC_zero_x2031_t3191, but this time without x2031 (immediate FINAL_ACK). */
+testcase TC_zero_x2031_t3191() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring data1 := f_rnd_octstring(1400);
+ var octetstring data2 := f_rnd_octstring(10);
+ var uint32_t dl_fn;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Set timer to 1 sec (default 5) to speedup test: */
+ info_ind.t3191 := 1;
+ f_init_raw(testcasename(), info_ind);
+
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X2031 0");
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data1, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+
+ /* Send enough DL data to at least be able to DL ACK once (excl the
+ * FINAL_ACK one), so that PCU sees we are listening in PDCH and avoids
+ * other code paths like trying to Imm Assign on CCCH again, etc.. */
+ while (true) {
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, ?, ?);
+
+ if (dl_block.data.mac_hdr.hdr_ext.fbi) {
+ log("Received FINAL_ACK");
+ ms.dl_tbf.acknack_desc.final_ack := '1'B;
+ break;
+ }
+
+ /* Keep Ack/Nack description updated (except for last BSN) */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block);
+
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+ }
+ }
+
+ /* Avoid ACKing the last RLC data block on purpose here, wait for t3191
+ to time out. We simply sleep instead of requesting blocks because
+ otherwise retransmissions would keep restarting the timer. */
+ f_sleep(int2float(info_ind.t3191));
+
+ /* The TBF should be freed now, so new data should trigger an Assignment: */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data2, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data2, 0);
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -798,17 +1896,27 @@ testcase TC_t3193() runs on RAW_PCU_Test_CT {
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ /* Disable "idle DL TBF alive" timer, to make the test easier and avoid
+ * having to keep receiving dummy LLC blocks for a while until the last
+ * block with FBI=1 is set. This way the first and only DL block is already
+ * the FBI one. */
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X2031 0");
+
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* SGSN sends some DL data, PCU will page on CCCH (PCH) */
- BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
f_sleep(X2002);
f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+ if (dl_block.data.mac_hdr.hdr_ext.fbi == false) {
+ setverdict(fail, "Expected DL data block with FBI=1 but got FBI=0");
+ f_shutdown(__BFILE__, __LINE__);
+ }
/* ACK the DL block */
f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
@@ -832,6 +1940,242 @@ testcase TC_t3193() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Verify after N3105_MAX is reached, T3195 is started and upon timeout TBF is
+ freed and no longer available. Trigger it by sending DL blocks and never DL
+ ACKing the data (which are requested through RRBP) */
+testcase TC_n3105_max_t3195() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring data1 := f_rnd_octstring(1000);
+ var octetstring data2 := f_rnd_octstring(10);
+ var uint32_t dl_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var GprsMS ms;
+ const integer N3105_MAX := 2;
+ var integer N3105 := 0;
+ timer T_3195 := 1.0;
+ var integer num_poll_recv := 0;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Speedup test: */
+ info_ind.n3105 := N3105_MAX;
+ info_ind.t3195 := 1;
+ f_init_raw(testcasename(), info_ind);
+
+ /* Disable "MS delay release" timer, to avoid old DL data kept in cached
+ * MS and retransmitted after the TBF is released and later on created
+ * (because the MS is reused) */
+ f_vty_config2(PCUVTY, {"pcu"}, "timer X2030 0");
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data1, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+
+ /* Now we go on receiving DL data and not answering RRBP: */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [not T_3195.running] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DATA)) -> value data_msg {
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ if (num_poll_recv == 0) {
+ /* ACK first one so PCU detects we are there and doesn't retransmit Imm Ass */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, data_msg.dl_block);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(data_msg.dl_block, data_msg.raw.fn));
+ } else {
+ log("Ignoring RRBP ", num_poll_recv);
+ N3105 := N3105 + 1;
+ }
+ num_poll_recv := num_poll_recv + 1;
+ }
+
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ /* At this point in time (N3105_MAX reached), PCU already moved TBF to
+ * RELEASE state so no data for it is tx'ed, hence the dummy/idle blocks:
+ */
+ [N3105 == N3105_MAX] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL)) -> value data_msg {
+ if (not T_3195.running) {
+ T_3195.start;
+ /* We even send some new data, nothing should be sent to MS */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data1));
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ /* We may already receive idle blocks before our own TTCN3 timer
+ * triggers due to the TBF being released. Keep going until our T_3195 triggers. */
+ [N3105 == N3105_MAX] as_pcuif_rx_ignore_empty(nr);
+ [T_3195.running] T_3195.timeout {
+ log("T_3195 timeout");
+ /* Done in alt, wait for pending RTS initiated previously in
+ * above case before continuing (expect empty block): */
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)); /* DONE, continue after altstep. */
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL)) {
+ setverdict(fail, "Rx unexpected DUMMY message, expected empty data block");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ /* after T_3195 timeout, TBF is released */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data2, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data2, 0);
+
+ /* ACK the DL block */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify configured T3172 is properly transmitted as WAIT_INDICATION in Pkt Access Reject in PACCH. */
+function f_TC_t3172(integer t3172_ms, BIT1 wait_ind_size) runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template IARRestOctets rest;
+ var BIT11 ra11;
+ var GprsMS ms;
+ var octetstring data := f_rnd_octstring(10);
+ var RlcmacDlBlock dl_block;
+ var template RlcmacDlBlock rej_tmpl;
+ var uint32_t dl_fn;
+ var uint32_t sched_fn;
+ var uint8_t wait_ind_val;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+
+ /* Only the first TRX is enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ f_pcuvty_set_timer(3172, t3172_ms);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ var EGPRSPktChRequest req := {
+ one_phase := {
+ tag := '0'B,
+ multislot_class := '10101'B,
+ priority := '01'B,
+ random_bits := '101'B
+ }
+ };
+
+ /* We send 7 requests, the IUT gives us all available USFs (0..6) */
+ for (var integer i := 0; i < 7; i := i + 1) {
+ req.one_phase.random_bits := int2bit(f_rnd_int(8), 3);
+ f_TC_egprs_pkt_chan_req(req, tr_IMM_TBF_ASS);
+ }
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* ACK the DL block */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc, false, ts_ChannelReqDescription()),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ /* Since all USF are taken, we should receive a Reject: */
+
+ if (wait_ind_size == '0'B) {
+ wait_ind_val := t3172_ms / 1000;
+ } else {
+ wait_ind_val := t3172_ms / 20;
+ }
+ rej_tmpl := tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_ACC_REJ(
+ tr_PacketAccessRejectStruct_TLLI(ms.tlli,
+ wait_ind_val,
+ wait_ind_size)));
+ template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ rej_tmpl));
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+testcase TC_t3172_wait_ind_size0() runs on RAW_PCU_Test_CT {
+ /* size=0 means value is provided in seconds. Due to value being 8
+ * bit, in the 20ms step case (size=1) the maximum value possible is 20 * 255
+ * = 5100. Hence, values above it should use size=0 to be able to
+ * provide values in range. Let's use 6 seconds, 6000ms
+ */
+ f_TC_t3172(6000, '0'B);
+}
+testcase TC_t3172_wait_ind_size1() runs on RAW_PCU_Test_CT {
+ f_TC_t3172(3000, '1'B);
+}
+
/* Verify PCU handles correctly Countdown Procedure based on BS_CV_MAX */
testcase TC_countdown_procedure() runs on RAW_PCU_Test_CT {
var RlcmacDlBlock dl_block;
@@ -846,20 +2190,23 @@ testcase TC_countdown_procedure() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
- total_payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
+ contention resolution) and make sure it is ACKED fine. */
+ total_payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- f_ms_tx_ul_data_block(ms, total_payload, cv := 15, with_tlli := true)
+ f_ms_tx_ul_data_block(ms, total_payload, cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn)
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -873,7 +2220,9 @@ testcase TC_countdown_procedure() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
/* receive one message on BSSGP with all aggregated data in payload: */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, total_payload));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, total_payload));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Verify PCU handles correctly CS1..4 with all possible LLC payload sizes fitting alone in one RLC block */
@@ -882,6 +2231,10 @@ testcase TC_ul_all_sizes() runs on RAW_PCU_Test_CT {
var uint32_t dl_fn, sched_fn;
var octetstring payload;
var template (value) RlcmacUlBlock ul_data;
+ var template (value) LlcBlockHdr blk_hdr;
+ var template (value) LlcBlocks blocks;
+ var integer blk_len;
+ var CodingScheme tx_cs;
var GprsMS ms;
/* Initialize NS/BSSGP side */
@@ -891,35 +2244,40 @@ testcase TC_ul_all_sizes() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
+ contention resolution) and make sure it is ACKED fine. */
payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
+ blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload),
+ more := false, e := true);
+ blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) };
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
- cv := 15,
- bsn := ms.ul_tbf.bsn,
- blocks := { t_RLCMAC_LLCBLOCK(payload,
- t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload), more := false, e := true))
- },
- tlli := ms.tlli);
+ ul_data := t_RLCMAC_UL_DATA_TLLI(cs := ms.ul_tbf.tx_cs_mcs,
+ tfi := ms.ul_tbf.tfi,
+ cv := 15,
+ bsn := ms.ul_tbf.bsn,
+ blocks := blocks,
+ tlli := ms.tlli);
f_ultbf_inc_bsn(ms.ul_tbf);
- f_ms_tx_ul_block(ms, ul_data);
+ f_ms_tx_ul_block(ms, ul_data, ms.ul_tbf.start_time_fn);
/* ACK and check it was received fine */
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
/* receive one message on BSSGP with all aggregated data in payload: */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, payload));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, payload));
/* Test sending LLC PDUS of incrementing size */
var integer max_size := 49;
@@ -933,23 +2291,27 @@ testcase TC_ul_all_sizes() runs on RAW_PCU_Test_CT {
cv := max_size - i;
}
+ blk_len := 3 + 1 + i; /* 3 Header bytes + LI byte + payload length */
+ tx_cs := f_rlcmac_block_len_required_cs_mcs(blk_len, false);
payload := f_rnd_octstring(i);
+ blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload),
+ more := false, e := true);
+ blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) };
/* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
- ul_data := t_RLCMAC_UL_DATA(tfi := ms.ul_tbf.tfi,
+ ul_data := t_RLCMAC_UL_DATA(cs := tx_cs,
+ tfi := ms.ul_tbf.tfi,
cv := cv,
bsn := ms.ul_tbf.bsn,
- blocks := { t_RLCMAC_LLCBLOCK(payload,
- t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload), more := false, e := true))
- });
+ blocks := blocks);
f_ultbf_inc_bsn(ms.ul_tbf);
f_ms_tx_ul_block(ms, ul_data);
/* receive one message on BSSGP with all aggregated data in payload: */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, payload));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, payload));
/* we will receive UL ACK/NACK from time to time, handle it. */
f_rx_rlcmac_dl_block(dl_block, dl_fn);
- if (match(dl_block, tr_RLCMAC_DUMMY_CTRL())) {
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
continue;
}
if (not match(dl_block, tr_RLCMAC_UL_ACK_NACK_GPRS(ul_tfi := ?)) and
@@ -963,34 +2325,39 @@ testcase TC_ul_all_sizes() runs on RAW_PCU_Test_CT {
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
}
- setverdict(pass);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
function f_TC_ul_data_toolong_fills_padding_cs(inout GprsMS ms, CodingScheme cs, integer cv) runs on RAW_PCU_Test_CT {
var octetstring payload;
var template (value) RlcmacUlBlock ul_data;
+ var template (value) LlcBlockHdr blk_hdr;
+ var template (value) LlcBlocks blocks;
var integer block_len, max_valid_data_len;
timer T;
block_len := f_rlcmac_cs_mcs2block_len(cs);
/* We need to send with TLLI since we are in One-Phase Access Contenion
- * resoultion), so that's -4 bytes of data, -3 for headers, -1 for LI
+ * resolution), so that's -4 bytes of data, -3 for headers, -1 for LI
* indicator, -1 for spare bits octet at the end */
max_valid_data_len := block_len - 4 - 3 - 1 - 1;
payload := f_rnd_octstring(max_valid_data_len + 1); /* +1 to write LLC data on last padding octet */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
- cv := cv,
- bsn := ms.ul_tbf.bsn,
- blocks := { t_RLCMAC_LLCBLOCK(payload,
- t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload), more := false, e := true))
- },
- tlli := ms.tlli);
+ blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload),
+ more := false, e := true);
+ blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) };
+ ul_data := t_RLCMAC_UL_DATA_TLLI(cs := cs,
+ tfi := ms.ul_tbf.tfi,
+ cv := cv,
+ bsn := ms.ul_tbf.bsn,
+ blocks := blocks,
+ tlli := ms.tlli);
f_ultbf_inc_bsn(ms.ul_tbf);
f_ms_tx_data_ind(ms, enc_RlcmacUlBlock(valueof(ul_data)));
T.start(0.5);
alt {
- [] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, ?)) {
+ [] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, ?)) {
setverdict(fail, "LLC PDU in Malformed RLC block was forwarded");
f_shutdown(__BFILE__, __LINE__);
}
@@ -1015,20 +2382,23 @@ testcase TC_ul_data_toolong_fills_padding() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
f_TC_ul_data_toolong_fills_padding_cs(ms, CS_2, 2);
f_TC_ul_data_toolong_fills_padding_cs(ms, CS_3, 1);
f_TC_ul_data_toolong_fills_padding_cs(ms, CS_4, 0);
- setverdict(pass);
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
@@ -1048,28 +2418,31 @@ private function f_TC_mo_ping_pong_1phase_access(template (present) CodingScheme
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine */
- f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+ contention resolution) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
/* UL block should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
/* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
- BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
f_sleep(X2002);
@@ -1087,33 +2460,26 @@ private function f_TC_mo_ping_pong_1phase_access(template (present) CodingScheme
* answered, so TBFs for uplink and later for downlink are created.
*/
testcase TC_mo_ping_pong() runs on RAW_PCU_Test_CT {
- var CodingScheme exp_cs_mcs := CS_1;
+ var template (present) CodingScheme exp_cs_mcs := cs_gprs_any;
f_TC_mo_ping_pong_1phase_access(exp_cs_mcs);
}
/* Test scenario where MS wants to send some data on PDCH against SGSN and it is
* answered, so TBFs for uplink and later for downlink are created.
*/
-private function f_TC_mo_ping_pong_2phase_access(template (value) MSRadioAccessCapabilityV ms_racap,
+private function f_TC_mo_ping_pong_2phase_access(PCUIF_Flags ind_flags,
+ template (value) MSRadioAccessCapabilityV ms_racap,
template (present) CodingScheme exp_ul_cs_mcs := ?,
template (present) CodingScheme exp_dl_cs_mcs := ?)
runs on RAW_PCU_Test_CT {
var RlcmacDlBlock dl_block;
var octetstring data := f_rnd_octstring(10);
+ var PollFnCtx pollctx;
var uint32_t sched_fn;
var uint32_t dl_fn;
var uint32_t unused_fn;
var GprsMS ms;
- /* 0111 0xxx: Single block packet access; one block period on a PDCH is needed for two phase packet access or other RR signalling purpose. */
- var uint16_t ra := oct2int('70'O);
- if (g_force_two_phase_access) {
- /* If 2phase access is enforced by the network, then let's
- request a One phase packet access, we'll receive a single block
- anyway */
- ra := bit2int(chan_req_def);
- }
-
/* Initialize NS/BSSGP side */
f_init_bssgp();
/* Initialize GPRS MS side */
@@ -1121,27 +2487,15 @@ runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(ind_flags));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
-
- /* Establish an Uplink TBF */
- f_ms_use_ra(ms, ra, ra_is_11bit := 0);
- f_ms_establish_ul_tbf(ms);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
- /* Make sure we've got an Uplink TBF assignment */
- if (not match(ms.ul_tbf.ass.ccch, tr_PacketUlSglAssign)) {
- setverdict(fail, "Wrong Packet Uplink Assignment received: ", ms.ul_tbf.ass.ccch, " vs exp: ", tr_PacketUlSglAssign);
- f_shutdown(__BFILE__, __LINE__);
- }
+ /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap));
- /* Send PACKET RESOURCE REQUEST to upgrade to EGPRS
- * (see 3GPP TS 04.60 "7.1.3.1 Initiation of the Packet resource request procedure")
- */
- f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap)), 0);
- f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_UL_PACKET_ASS);
if (not match(ms.ul_tbf.tx_cs_mcs, exp_ul_cs_mcs)) {
setverdict(fail, "Wrong CS_MCS ", ms.ul_tbf.tx_cs_mcs, " received vs exp ", exp_ul_cs_mcs);
f_shutdown(__BFILE__, __LINE__);
@@ -1149,16 +2503,18 @@ runs on RAW_PCU_Test_CT {
/* Send one UL block (without TLLI since we are in Second-Phase Access)
and make sure it is ACKED fine */
- f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true); /* TODO: send using cs_mcs */
+ f_ms_tx_ul_data_block_multi(ms, 1);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
- f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
/* UL block should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
/* Now SGSN sends some DL data, PCU will page on PACCH */
BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+ /* Sleep a bit to make sure PCU received the DL data and hence it will be prioritized by scheduler: */
+ f_sleep(0.5);
f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_DL_PACKET_ASS);
/* DL Ass sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
@@ -1170,63 +2526,91 @@ runs on RAW_PCU_Test_CT {
f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_dl_cs_mcs);
/* ACK the DL block */
- f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
- f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.ul_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dltbf_ack_block(ms.dl_tbf, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, ischosen(dl_block.data_egprs)),
f_dl_block_ack_fn(dl_block, dl_fn));
f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_mo_ping_pong_with_ul_racap() runs on RAW_PCU_Test_CT {
- var MultislotCap_GPRS mscap_gprs := {
- gprsmultislotclass := '00011'B,
- gprsextendeddynalloccap := '0'B
+ var template (present) CodingScheme exp_ul_cs_mcs := cs_gprs_any;
+ var template (present) CodingScheme exp_dl_cs_mcs := cs_gprs_any;
+
+ f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_noMCS, ms_racap_gprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
};
- var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
- var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, false);
- var CodingScheme exp_dl_cs_mcs := CS_2;
+ f_statsd_expect(expect);
- f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_mo_ping_pong_with_ul_racap_egprs_only() runs on RAW_PCU_Test_CT {
- /* Initialize the PCU interface abstraction with EGPRS-only */
- g_egprs_only := true;
-
- var MultislotCap_GPRS mscap_gprs := {
- gprsmultislotclass := '00011'B,
- gprsextendeddynalloccap := '0'B
- };
- var MultislotCap_EGPRS mscap_egprs := {
- egprsmultislotclass := '00011'B,
- egprsextendeddynalloccap := '0'B
+ var template (present) CodingScheme exp_ul_cs_mcs := mcs_egprs_any;
+ var template (present) CodingScheme exp_dl_cs_mcs := mcs_egprs_any;
+
+ f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_default, ms_racap_egprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
};
- var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, mscap_egprs)) };
- var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, true);
- var CodingScheme exp_dl_cs_mcs := MCS_1;
+ f_statsd_expect(expect);
- f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_force_two_phase_access() runs on RAW_PCU_Test_CT {
/* Configure PCU to force two phase access */
g_force_two_phase_access := true;
- var MultislotCap_GPRS mscap_gprs := {
- gprsmultislotclass := '00011'B,
- gprsextendeddynalloccap := '0'B
- };
- var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
var CodingScheme exp_ul_cs_mcs := f_rlcmac_block_int2cs_mcs(g_mcs_initial_ul, false);
- var CodingScheme exp_dl_cs_mcs := CS_2;
+ var template (present) CodingScheme exp_dl_cs_mcs := cs_gprs_any;
+
+ f_TC_mo_ping_pong_2phase_access(c_PCUIF_Flags_noMCS, ms_racap_gprs_def, exp_ul_cs_mcs, exp_dl_cs_mcs);
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
- f_TC_mo_ping_pong_2phase_access(ms_racap, exp_ul_cs_mcs, exp_dl_cs_mcs);
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Test scenario where SGSN wants to send some data against MS and it is
* answered by the MS on PDCH, so TBFs for downlink and later for uplink are created.
*/
-private function f_TC_mt_ping_pong(template (omit) MSRadioAccessCapabilityV_BSSGP ms_racap := omit, template (present) CodingScheme exp_cs_mcs := ?) runs on RAW_PCU_Test_CT {
+private function f_TC_mt_ping_pong(template (omit) MSRadioAccessCapabilityV_BSSGP ms_racap := omit,
+ template (present) CodingScheme exp_cs_mcs := ?)
+runs on RAW_PCU_Test_CT {
var RlcmacDlBlock dl_block;
var octetstring data := f_rnd_octstring(10);
var uint32_t sched_fn;
@@ -1240,56 +2624,54 @@ private function f_TC_mt_ping_pong(template (omit) MSRadioAccessCapabilityV_BSSG
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* SGSN sends some DL data, PCU will page on CCCH (PCH) */
- BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, ms_racap));
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, ms_racap, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
f_sleep(X2002);
- f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, exp_cs_mcs);
+ /* Skip potential dummy blocks before X2002 triggers at PCU after us: */
+ dl_fn := f_rx_rlcmac_dl_block_skip_dummy(dl_block, max_dummy := 10);
+
+ f_rlcmac_dl_block_exp_data(dl_block, data, 0, exp_cs_mcs);
/* ACK the DL block, and request UL TBF at the same time */
- f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
- f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK_CHREQ(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dltbf_ack_block(ms.dl_tbf, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, ischosen(dl_block.data_egprs), c_ChReqDesc_default),
f_dl_block_ack_fn(dl_block, dl_fn));
/* Expect UL ass */
f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_UL_PACKET_ASS);
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine */
+ contention resolution) and make sure it is ACKED fine */
f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
/* UL block should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_mt_ping_pong() runs on RAW_PCU_Test_CT {
- var CodingScheme exp_cs_mcs := CS_1;
+ var template (present) CodingScheme exp_cs_mcs := cs_gprs_any;
f_TC_mt_ping_pong(omit, exp_cs_mcs);
}
/* TC_mt_ping_pong, but DL-UNITDATA contains RA Access capability with (M)CS
/* information about the MS */
testcase TC_mt_ping_pong_with_dl_racap() runs on RAW_PCU_Test_CT {
- var MultislotCap_GPRS_BSSGP mscap_gprs := {
- gprsmultislotclass := '00011'B,
- gprsextendeddynalloccap := '0'B
- } ;
- var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
- var CodingScheme exp_cs_mcs := CS_2;
- f_TC_mt_ping_pong(ms_racap, exp_cs_mcs);
+ var template (present) CodingScheme exp_cs_mcs := cs_gprs_any;
+ f_TC_mt_ping_pong(bssgp_ms_racap_gprs_def, exp_cs_mcs);
}
/* Verify that if PCU doesn't get one of the intermediate UL data blocks in a UL
@@ -1306,6 +2688,7 @@ testcase TC_ul_intermediate_retrans() runs on RAW_PCU_Test_CT {
var octetstring lost_payload;
var uint5_t tfi;
var GprsMS ms;
+ var uint32_t payload_fill_len;
/* Initialize NS/BSSGP side */
f_init_bssgp();
@@ -1314,40 +2697,45 @@ testcase TC_ul_intermediate_retrans() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
tfi := ms.ul_tbf.tfi;
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine. */
- payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
- f_ms_tx_ul_data_block(ms, payload, cv := 15, with_tlli := true);
+ contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true)); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
+ f_ms_tx_ul_data_block(ms, payload, cv := 15, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
total_payload := payload;
+ payload_fill_len := f_ultbf_payload_fill_length(ms.ul_tbf);
+
/* Send 2 packets, skip 1 (inc bsn) and send another one */
- payload := f_rnd_octstring(20); /* 20 bytes fills the CS-1 llc block */
+ payload := f_rnd_octstring(payload_fill_len);
f_ms_tx_ul_data_block(ms, payload, cv := 15);
total_payload := total_payload & payload;
- payload := f_rnd_octstring(20); /* 20 bytes fills the CS-1 llc block */
+ payload := f_rnd_octstring(payload_fill_len);
f_ms_tx_ul_data_block(ms, payload, cv := 15);
total_payload := total_payload & payload;
- lost_payload := f_rnd_octstring(20);
+ lost_payload := f_rnd_octstring(payload_fill_len);
ms.ul_tbf.bsn := ms.ul_tbf.bsn + 1; /* LOST PAYLOAD bsn=3, will be retransmitted, next bsn is increased +2 */
total_payload := total_payload & lost_payload;
- payload := f_rnd_octstring(20); /* 20 bytes fills the CS-1 llc block */
+ payload := f_rnd_octstring(payload_fill_len)
f_ms_tx_ul_data_block(ms, payload, cv := 15);
total_payload := total_payload & payload;
@@ -1357,7 +2745,11 @@ testcase TC_ul_intermediate_retrans() runs on RAW_PCU_Test_CT {
/* On CV=0, we'll receive a UL ACK asking about missing block */
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* TODO: check ack ack bitmap (URBB) */
- ul_data := t_RLCMAC_UL_DATA(tfi := tfi, cv := 15, bsn := 3, blocks := {t_RLCMAC_LLCBLOCK(lost_payload)});
+ ul_data := t_RLCMAC_UL_DATA(cs := ms.ul_tbf.tx_cs_mcs,
+ tfi := tfi,
+ cv := 15,
+ bsn := 3,
+ blocks := {t_RLCMAC_LLCBLOCK(lost_payload)});
f_ms_tx_ul_block(ms, ul_data);
/* Now final ack is recieved */
@@ -1366,7 +2758,9 @@ testcase TC_ul_intermediate_retrans() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
/* receive one message on BSSGP with all aggregated data in payload: */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, total_payload));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, total_payload));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Verify that if PCU doesn't get an ACK for first DL block after IMM ASS, it
@@ -1389,11 +2783,11 @@ testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* SGSN sends some DL data, PCU will page on CCCH (PCH) */
- BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
f_sleep(X2002);
@@ -1402,7 +2796,7 @@ testcase TC_imm_ass_dl_block_retrans() runs on RAW_PCU_Test_CT {
/* Now we don't ack the dl block (emulate MS failed receiveing IMM ASS
* or GPRS DL, or DL ACK was lost for some reason). As a result, PCU
* should retrigger IMM ASS + GPRS DL procedure after poll timeout. */
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
f_sleep(X2002);
@@ -1434,21 +2828,25 @@ testcase TC_dl_flow_more_blocks() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ f_statsd_reset();
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* SGSN sends some DL data, PCU will page on CCCH (PCH) */
- BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
- f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_PCH);
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
/* Wait timer X2002 and DL block is available after CCCH IMM ASS */
f_sleep(X2002);
+ /* Skip potential dummy blocks before X2002 triggers at PCU after us: */
+ fn := f_rx_rlcmac_dl_block_skip_dummy(dl_block, max_dummy := 10);
/* Expect the first (GPRS DL) block with bsn=0 and rrbp_valid=1 */
- f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, 0);
+ f_rlcmac_dl_block_exp_data(dl_block, data, 0);
f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block);
/* TDMA frame number on which we are supposed to send the ACK */
@@ -1485,6 +2883,17 @@ testcase TC_dl_flow_more_blocks() runs on RAW_PCU_Test_CT {
/* Make sure that the next block (after the Ack) is dummy */
f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 0, max := 0},
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 0, max := 0},
+ { name := "TTCN3.bts.0.tbf.dl.alloc", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.tbf.ul.alloc", mtype := "c", min := 0, max := 0},
+ { name := "TTCN3.bts.0.rlc.dl_payload_bytes", mtype := "c", min := 64, max := 64},
+ { name := "TTCN3.bts.0.rlc.ul_payload_bytes", mtype := "c", min := 0, max := 0}
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -1508,15 +2917,18 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Summary of what's transmitted:
* 1- UL RlcDataBlock(dataA) [BSN=0, CV=3]
* 2- UL RlcDataBlock(dataA finished, dataB starts) [BSN=1, CV=2]
@@ -1527,7 +2939,8 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
*/
/* UL RlcDataBlock(dataA) [BSN=0, CV=3] */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
+ ul_data := t_RLCMAC_UL_DATA_TLLI(cs := CS_1,
+ tfi := ms.ul_tbf.tfi,
cv := 3,
bsn := ms.ul_tbf.bsn,
blocks := { t_RLCMAC_LLCBLOCK(substr(dataA, 0, 16)) },
@@ -1536,10 +2949,11 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
* RLCMAC block being sent. */
ul_data.data.mac_hdr.e := true;
f_ultbf_inc_bsn(ms.ul_tbf);
- f_ms_tx_ul_block(ms, ul_data);
+ f_ms_tx_ul_block(ms, ul_data, ms.ul_tbf.start_time_fn);
/* UL RlcDataBlock(dataA finished, dataB starts) [BSN=1, CV=2] */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
+ ul_data := t_RLCMAC_UL_DATA_TLLI(cs := CS_1,
+ tfi := ms.ul_tbf.tfi,
cv := 2,
bsn := ms.ul_tbf.bsn,
blocks := { t_RLCMAC_LLCBLOCK(substr(dataA, 16, 4),
@@ -1551,10 +2965,11 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_block(ms, ul_data);
/* UL block dataA should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataA));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataA));
/* UL RlcDataBlock(dataB finished, dataC starts and finishes, dataD starts) [BSN=2, CV=1] */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
+ ul_data := t_RLCMAC_UL_DATA_TLLI(cs := CS_1,
+ tfi := ms.ul_tbf.tfi,
cv := 1,
bsn := ms.ul_tbf.bsn,
blocks := { t_RLCMAC_LLCBLOCK(substr(dataB, 11, 2),
@@ -1568,11 +2983,13 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_block(ms, ul_data);
/* UL block dataB and dataC should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataB));
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataC));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataB));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataC));
/* UL RlcDataBlock(dataD finishes) [BSN=3, CV=0] */
- ul_data := t_RLCMAC_UL_DATA_TLLI(tfi := ms.ul_tbf.tfi,
+ ul_data := t_RLCMAC_UL_DATA_TLLI(
+ cs := CS_1,
+ tfi := ms.ul_tbf.tfi,
cv := 0,
bsn := ms.ul_tbf.bsn,
blocks := { t_RLCMAC_LLCBLOCK(substr(dataD, 9, 3),
@@ -1583,7 +3000,7 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_block(ms, ul_data);
/* UL block dataB and dataD should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id, dataD));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id, dataD));
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
/* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
@@ -1592,12 +3009,422 @@ testcase TC_ul_flow_multiple_llc_blocks() runs on RAW_PCU_Test_CT {
f_shutdown(__BFILE__, __LINE__, final := true);
}
+/* Validate an Imm Assignment is retransmitted if first RRBP requesting DL
+ * ACK/NACK is not answered */
+testcase TC_dl_no_ack_retrans_imm_ass() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data1 := f_rnd_octstring(200);
+ var octetstring data2 := f_rnd_octstring(10);
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename())
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data1, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+
+ /* Recv DL data until receiving RRBP to DL ACK (because it's last queued DL data) */
+ while (true) {
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, ?, ?);
+
+ /* Keep Ack/Nack description updated (except for last BSN) */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block);
+
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ /* Don't transmit DL ACK here on purpose ignore it */
+ break;
+ }
+ }
+
+ /* PCU starts whole process again */
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+
+ /* Recv DL data until receiving RRBP to DL ACK (because it's last queued
+ /* DL data), after that we receive only DUMMY blocks so we are done */
+ var boolean data_received := false;
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [data_received] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL)) { /* done */ }
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DATA)) -> value data_msg {
+ data_received := true;
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, data_msg.dl_block);
+ if (data_msg.dl_block.data.mac_hdr.hdr_ext.fbi) {
+ log("Received FINAL_ACK");
+ ms.dl_tbf.acknack_desc.final_ack := '1'B;
+ }
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, data_msg.raw.fn));
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* OS#5508: Verify scheduling of LLC frames with SAPI=1 (GMM) takes precedence
+ * over SAPI2/7/8 which in turn take prececende over others */
+testcase TC_dl_llc_sapi_priority() runs on RAW_PCU_Test_CT {
+ var octetstring data_sapi1 := f_pad_oct('01'O, 19, 'ff'O);
+ var octetstring data_sapi2 := f_pad_oct('02'O, 19, 'ff'O);
+ var octetstring data_sapi7 := f_pad_oct('07'O, 19, 'ff'O);
+ var octetstring data_sapi8 := f_pad_oct('08'O, 19, 'ff'O);
+ var octetstring data_sapi_other := f_pad_oct('03'O, 19, 'ff'O);
+ var RlcmacDlBlock dl_block;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ var integer state := 1;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Lock to CS1 to keep same DL RLCMAC data block size: */
+ g_cs_initial_dl := 1;
+ g_mcs_max_dl := 1;
+ f_pcuvty_set_allowed_cs_mcs();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some low prio DL data, PCU will page on CCCH (PCH) */
+ for (var integer i := 0; i < 10; i := i + 1) {
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data_sapi_other, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ }
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data_sapi2, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data_sapi7, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data_sapi8, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data_sapi1, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
+ f_sleep(X2002);
+
+ while (state != 0) {
+ var OCT1 rx_sapi;
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, ?, ?);
+ rx_sapi := dl_block.data.blocks[0].payload[0];
+
+ select (state) {
+ case(1) { /* We expect the first GMM LLC frame here (SAPI=1, highest prio) */
+ if (rx_sapi != '01'O) {
+ setverdict(fail, "Wrong prio: Expected LLC SAPI 1 (GMM) but got ", rx_sapi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ state := 2;
+ }
+ case(2) { /* We expect the second LLC frame here (SAPI=2, middle prio) */
+ if (rx_sapi != '02'O) {
+ setverdict(fail, "Wrong prio: Expected LLC SAPI 2 but got ", rx_sapi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ state := 7;
+ }
+ case(7) { /* We expect the third LLC frame here (SAPI=7, middle prio) */
+ if (rx_sapi != '07'O) {
+ setverdict(fail, "Wrong prio: Expected LLC SAPI 7 but got ", rx_sapi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ state := 8;
+ }
+ case(8) { /* We expect the fourth LLC frame here (SAPI=8, middle prio) */
+ if (rx_sapi != '08'O) {
+ setverdict(fail, "Wrong prio: Expected LLC SAPI 8 but got ", rx_sapi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ state := 3;
+ }
+ case(3) { /* We expect the other LLC frame here (SAPI=3, lower prio) */
+ if (rx_sapi != '03'O) {
+ setverdict(fail, "Wrong prio: Expected LLC SAPI 3 but got ", rx_sapi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ state := 0; /* Done, break */
+ }
+ }
+ /* Keep Ack/Nack description updated (except for last BSN) */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block);
+
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify allocation and use of multislot tbf, triggered by MS class provided in SGSN. SYS#5131 */
+testcase TC_dl_multislot_tbf_ms_class_from_sgsn() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ var octetstring data := f_rnd_octstring(10);
+ var PacketDlAssign dl_tbf_ass;
+ var RlcmacDlBlock dl_block;
+ var uint32_t poll_fn;
+ var uint32_t dl_fn;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+ timer T := 5.0;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Only 1 TRX with 8 PDCH */
+ f_PCUIF_PDCHMask_set(info_ind, '11111111'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF, this way the PCU can send DL Assignment
+ through PDCH (no multiblock assignment possible through PCH) */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ dl_fn := f_ms_wait_usf(ms, nr := f_ms_tx_TsTrxBtsNum(ms));
+ sched_fn := f_next_pdch_block(dl_fn);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block(ms, data, with_tlli := true, fn := sched_fn,
+ nr := f_ms_tx_TsTrxBtsNum(ms));
+ /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* SGSN sends some DL data, PCU will assign DL TBF through PACCH */
+ var MultislotCap_GPRS_BSSGP mscap_gprs := {
+ gprsmultislotclass := '10010'B, /* MS class 18, supports 8 DL and 8 UL */
+ gprsextendeddynalloccap := '0'B
+ };
+ var MSRadioAccessCapabilityV_BSSGP ms_racap := { valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, mscap_gprs, omit)) };
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, ms_racap));
+ dl_block := f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_DL_PACKET_ASS, nr := f_ms_tx_TsTrxBtsNum(ms));
+ if (f_dltbf_num_slots(ms.dl_tbf) != 8) {
+ setverdict(fail, "Expected 8 PDCH slots allocated but got ", f_dltbf_num_slots(ms.dl_tbf));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test DL TBF assignment over PACCH if Multislot class is unknown both at PCU
+ * and SGSN (eg. because MS started 1-phase access and SGSN answered back).
+ * Since the msclass is unknown, it shouldn't assign multiple timeslots since
+ * the MS may not support it. Related OS#6118. */
+testcase TC_dl_multislot_tbf_ms_class_unknown() runs on RAW_PCU_Test_CT
+{
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ var RlcmacDlBlock dl_block;
+ var octetstring payload;
+ var template (value) LlcBlockHdr blk_hdr;
+ var template (value) LlcBlocks blocks;
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var template RlcmacDlBlock acknack_tmpl;
+ var GprsMS ms;
+ var octetstring data := f_rnd_octstring(10);
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Only 1 TRX with 8 PDCH */
+ f_PCUIF_PDCHMask_set(info_ind, '11111111'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF. 1 TS is assigned over AGCH. */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ dl_fn := f_ms_wait_usf(ms, nr := f_ms_tx_TsTrxBtsNum(ms));
+ sched_fn := f_next_pdch_block(dl_fn);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ * contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
+ blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload),
+ more := false, e := true);
+ blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) };
+ /* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
+ f_ms_tx_ul_data_blocks_gprs(ms, blocks, cv := 15, with_tlli := true, fn := sched_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
+ tr_UlAckNackGprs(ms.tlli,
+ tr_AckNackDescription(final_ack := '0'B)))
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, racap := omit));
+ dl_block := f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_DL_PACKET_ASS, nr := f_ms_tx_TsTrxBtsNum(ms));
+ if (f_dltbf_num_slots(ms.dl_tbf) != 1) {
+ setverdict(fail, "Expected 1 PDCH slots allocated but got ", f_dltbf_num_slots(ms.dl_tbf));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_dl_multislot_tbf_ms_class_from_2phase() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+
+ var MultislotCap_GPRS mscap_gprs := {
+ gprsmultislotclass := '10010'B, /* MS class 18, supports 8 DL and 8 UL */
+ gprsextendeddynalloccap := '0'B
+ };
+ var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
+
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Only 1 TRX with 8 PDCH */
+ f_PCUIF_PDCHMask_set(info_ind, '11111111'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST to notify the MultiSlot Class */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap));
+
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+ dl_block := f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_DL_PACKET_ASS, nr := f_ms_tx_TsTrxBtsNum(ms));
+ if (f_dltbf_num_slots(ms.dl_tbf) != 8) {
+ setverdict(fail, "Expected 8 PDCH slot allocated but got ", f_dltbf_num_slots(ms.dl_tbf));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_ul_multislot_tbf_ms_class_from_2phase() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+
+ var MultislotCap_GPRS mscap_gprs := {
+ gprsmultislotclass := '10010'B, /* MS class 18, supports 8 DL and 8 UL */
+ gprsextendeddynalloccap := '0'B
+ };
+ var MSRadioAccessCapabilityV ms_racap := { valueof(ts_RaCapRec('0001'B /* E-GSM */, mscap_gprs, omit)) };
+
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Only 1 TRX with 8 PDCH */
+ f_PCUIF_PDCHMask_set(info_ind, '11111111'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST to notify the MultiSlot Class */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap));
+
+ if (f_ultbf_num_slots(ms.ul_tbf) != 8) {
+ setverdict(fail, "Expected 8 PDCH slot allocated but got ", f_ultbf_num_slots(ms.ul_tbf));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
/* Test scenario where MS wants to request a new TBF once the current one is
* ending, by means of sending a Packet Resource Request on ul slot provided by
* last Pkt Ul ACK's RRBP.
* See 3GPP TS 44.060 sec 9.3.2.4.2 "Non-extended uplink TBF mode" */
testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
- var CodingScheme exp_cs_mcs := CS_1;
var RlcmacDlBlock dl_block;
var octetstring data := f_rnd_octstring(10);
var uint32_t sched_fn;
@@ -1613,20 +3440,24 @@ testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send one UL block (with TLLI since we are in One-Phase Access
- contention resoultion) and make sure it is ACKED fine */
- f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true);
+ contention resolution) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
/* UL block should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
tr_UlAckNackGprs(ms.tlli,
@@ -1647,36 +3478,335 @@ testcase TC_ul_tbf_reestablish_with_pkt_resource_req() runs on RAW_PCU_Test_CT {
f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := false); /* TODO: send using cs_mcs */
/* UL block should be received in SGSN */
- BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.cell_id));
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl);
/* ACK the ACK */
f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pkt.ul_assignment", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
-private function f_pkt_paging_match_imsi(in PacketPagingReq req, hexstring imsi)
-runs on RAW_PCU_Test_CT {
- var MobileIdentityLV_Paging mi_lv := req.repeated_pageinfo.cs.mobile_identity;
- var MobileIdentityV mi := dec_MobileIdentityV(mi_lv.mobile_id);
+/* Test scenario where MS wants to request a new TBF once the current one is
+ * ending, by means of sending a Packet Resource Request on ul slot provided by
+ * last Pkt Ul ACK's RRBP. new Pkt Ul Ass is never confirmed by the MS in this test.
+ * See 3GPP TS 44.060 sec 9.3.2.4.2 "Non-extended uplink TBF mode" */
+testcase TC_ul_tbf_reestablish_with_pkt_resource_req_t3168() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var template RlcmacDlBlock acknack_tmpl;
+ var GprsMS ms;
+ var integer cnt_rrbp := 0;
+ var integer cnt_dummy_after_timeout := 0;
+ /* Maximum T3168 value = 8 * 500 ms = 4s => * 4 retrans = 16s */
+ timer T_3168 := 16.0 + 0.5; /* 0.5: extra offset since we cannot match exactly */
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* TODO: Speedup test by sending a PCU_IF_SAPI_BCCH SI13 with T3168=0 (500ms) */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
- if (mi_lv.len != 8) { /* 8 octets: type of ID (3 bits) + even/odd flag (1 bit) + 15 BCD-encoded digits (60 bits) */
- setverdict(fail, "Mobile Identity length mismatch: ",
- "expected: 8, got: ", mi_lv.len);
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
+ tr_UlAckNackGprs(ms.tlli,
+ tr_AckNackDescription(final_ack := '1'B),
+ tr_UlAckNackGprsAdditionsRel99(tbf_est := true)))
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl);
+
+ /* TODO: verify TBF_EST and FinalACK are both '1' above */
+
+ /* Send PACKET RESOURCE REQUEST to request a new UL TBF */
+ T_3168.start;
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit)), sched_fn);
+
+ /* Now Keep ignoring the Pkt Ul Ass on PACCH: */
+ /* Now we go on receiving DL data and not answering RRBP: */
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_UL_PACKET_ASS)) -> value data_msg {
+ /* We should not be receiving PKT UL ASS anymore after T3168 timeout */
+ if (not T_3168.running) {
+ setverdict(fail, log2str("Unexpected PKT UL ASS after T3168 timeout: ", data_msg));
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ log("Ignoring RRBP ", cnt_rrbp);
+ cnt_rrbp := cnt_rrbp + 1;
+ }
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL)) -> value data_msg {
+ nr := ts_TsTrxBtsNum;
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+
+ /* T3168 expired and we are not receiving blocks anymore, meaning PCU released the TBF. */
+ break;
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
f_shutdown(__BFILE__, __LINE__);
}
+ }
- /* Make sure MI contains IMSI before referencing it */
- if (mi.typeOfIdentity != '001'B) {
- setverdict(fail, "Mobile Identity must be of type IMSI ('001'B), ",
- "got: ", mi.typeOfIdentity);
+ /* Check that we received at least a few PKT UL ASS before T3168 expiration */
+ if (cnt_rrbp <= 3) {
+ setverdict(fail, log2str("Received only ", cnt_rrbp, " before T3168 timeout!"));
f_shutdown(__BFILE__, __LINE__);
- } else if (mi.oddEvenInd_identity.imsi.digits != imsi) {
- setverdict(fail, "Mobile Identity contains unexpected IMSI, ",
- "expected: ", imsi, " got: ", mi.oddEvenInd_identity.imsi.digits);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test scenario where MS wants to request a new UL TBF using a DL (EGPRS) ACK/NACK
+ * transmitted on ul slot provided by its DL TBF.
+ * See 3GPP TS 44.060 sec 9.3.2.4.2 "Non-extended uplink TBF mode" */
+function f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(boolean use_egprs) runs on RAW_PCU_Test_CT {
+ var GprsMS ms;
+ var octetstring data := f_rnd_octstring(10);
+ var RlcmacDlBlock dl_block;
+ var template RlcmacDlBlock rej_tmpl;
+ var uint32_t dl_fn;
+ var uint32_t sched_fn;
+ var template (value) MSRadioAccessCapabilityV_BSSGP racap_tmpl;
+
+ if (use_egprs == true) {
+ racap_tmpl := bssgp_ms_racap_egprs_def;
+ } else {
+ racap_tmpl := bssgp_ms_racap_gprs_def;
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, racap_tmpl, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* ACK the DL block, asking for new UL TBF by including ChanReqDesc */
+ f_dltbf_ack_block(ms.dl_tbf, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, f_dltbf_ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf, use_egprs, ts_ChannelReqDescription()),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ /* We should receive a Pkt Ul ASS */
+ f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_UL_PACKET_ASS);
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+testcase TC_ul_tbf_reestablish_with_pkt_dl_ack_nack() runs on RAW_PCU_Test_CT {
+ f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(false);
+}
+testcase TC_ul_tbf_reestablish_with_pkt_dl_ack_nack_egprs() runs on RAW_PCU_Test_CT {
+ f_TC_ul_tbf_reestablish_with_pkt_dl_ack_nack(true);
+}
+
+/* Test UL data blocks BSN 0..127 and then continue again at BSN 0... up to 300
+ * BSNs in total to test several wrap arounds. */
+testcase TC_ul_tbf_bsn_wraparound_gprs() runs on RAW_PCU_Test_CT
+{
+ var PCUIF_info_ind info_ind;
+ var RlcmacDlBlock dl_block;
+ var octetstring payload;
+ var template (value) LlcBlockHdr blk_hdr;
+ var template (value) LlcBlocks blocks;
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var template (value) TsTrxBtsNum nr;
+ var BTS_PDTCH_Block data_msg;
+ var template RlcmacDlBlock acknack_tmpl;
+ var GprsMS ms;
+ var integer blocks_sent := 0;
+ var integer blocks_received := 0;
+ const integer target_bsn_set := 300;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ dl_fn := f_ms_wait_usf(ms);
+ sched_fn := f_next_pdch_block(dl_fn);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(16); /* 16 bytes fills the llc block (because TLLI takes 4 bytes) */
+ blk_hdr := t_RLCMAC_LLCBLOCK_HDR(length_ind := lengthof(payload),
+ more := false, e := true);
+ blocks := { t_RLCMAC_LLCBLOCK(payload, blk_hdr) };
+ /* Set CV = 15 to signal there's still more than BS_CV_MAX blocks to be sent */
+ f_ms_tx_ul_data_blocks_gprs(ms, blocks, cv := 15, with_tlli := true, fn := sched_fn);
+ blocks_sent := blocks_sent + 1;
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ acknack_tmpl := tr_RLCMAC_UL_ACK_NACK_GPRS(ms.ul_tbf.tfi,
+ tr_UlAckNackGprs(ms.tlli,
+ tr_AckNackDescription(final_ack := '0'B)))
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn, acknack_tmpl);
+
+ nr := f_ms_tx_TsTrxBtsNum(ms);
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_UL_ACK_NACK_GPRS)) -> value data_msg {
+
+ if (f_dl_block_rrbp_valid(data_msg.dl_block)) {
+ var uint32_t ack_fn := f_dl_block_ack_fn(data_msg.dl_block, data_msg.raw.fn)
+ log("ACKING FN ", data_msg.raw.fn, " on FN ", ack_fn);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), ack_fn);
+ }
+ f_ms_tx_ul_data_blocks_gprs(ms, blocks);
+ blocks_sent := blocks_sent + 1;
+
+ if (blocks_sent == target_bsn_set) {
+ break;
+ }
+
+ nr := f_ms_tx_TsTrxBtsNum(ms);
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ tr_RLCMAC_DL_DUMMY_CTRL)) -> value data_msg {
+
+ f_ms_tx_ul_data_blocks_gprs(ms, blocks);
+ blocks_sent := blocks_sent + 1;
+
+ if (blocks_sent == target_bsn_set) {
+ break;
+ }
+
+ nr := f_ms_tx_TsTrxBtsNum(ms);
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+ nr := f_ms_tx_TsTrxBtsNum(ms);
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)),
+ block_nr := nr.blk_nr));
+ repeat;
+ }
+ [] BTS.receive {
+ setverdict(fail, "Unexpected BTS message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id)) {
+ blocks_received := blocks_received + 1;
+ repeat;
+ }
+ }
+
+ /* Validate most part of them were accepted and forwarded: */
+ if (blocks_received < target_bsn_set * 95 / 100) {
+ setverdict(fail, "Forwarded ", blocks_received, " out of ", target_bsn_set, " transmitted");
f_shutdown(__BFILE__, __LINE__);
}
+ log("Forwarded ", blocks_received, " out of ", target_bsn_set, " transmitted");
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Test CS paging over the BTS<->PCU socket.
@@ -1701,15 +3831,18 @@ testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* build mobile Identity */
mi := valueof(ts_MI_IMSI_LV(imsi));
mi_enc_lv := enc_MobileIdentityLV(mi);
@@ -1721,7 +3854,10 @@ testcase TC_paging_cs_from_bts() runs on RAW_PCU_Test_CT {
f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
/* Make sure that Packet Paging Request contains the same IMSI */
- f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
+ var PacketPagingReq req := dl_block.ctrl.payload.u.paging;
+ if (not f_pkt_paging_match_imsi(req, imsi, ps_domain := false)) {
+ setverdict(fail, "Failed to match IMSI ", imsi, " in ", req);
+ }
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -1742,15 +3878,18 @@ runs on RAW_PCU_Test_CT {
ms := g_ms[0]; /* We only use first MS in this test */
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Establish an Uplink TBF */
f_ms_establish_ul_tbf(ms);
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
/* Send paging request with or without TMSI */
if (use_ptmsi) {
tmsi := oct2int(f_rnd_octstring(4)); /* Random P-TMSI */
@@ -1759,14 +3898,27 @@ runs on RAW_PCU_Test_CT {
BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, imsi));
}
- /* Receive it on BTS side towards MS */
- f_rx_rlcmac_dl_block_exp_pkt_pag_req(dl_block);
+ /* Now receive it on BTS side towards MS.
+ * Skip any dummy blocks in case the PCUIF req arrives before the BSSP CS_PAGING:
+ */
+ f_rx_rlcmac_dl_block_skip_dummy(dl_block, max_dummy := 10);
+
+ if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ())) {
+ setverdict(fail, "Failed to match Packet Paging Request: ",
+ dl_block, " vs ", tr_RLCMAC_PACKET_PAG_REQ());
+ f_shutdown(__BFILE__, __LINE__);
+ }
/* Make sure that Packet Paging Request contains the same P-TMSI/IMSI */
+ var PacketPagingReq req := dl_block.ctrl.payload.u.paging;
if (use_ptmsi) {
- f_pkt_paging_match_tmsi(dl_block.ctrl.payload.u.paging, tmsi);
+ if (not f_pkt_paging_match_tmsi(req, tmsi, ps_domain := false)) {
+ setverdict(fail, "Failed to match P-TMSI ", tmsi, " in ", req);
+ }
} else {
- f_pkt_paging_match_imsi(dl_block.ctrl.payload.u.paging, imsi);
+ if (not f_pkt_paging_match_imsi(req, imsi, ps_domain := false)) {
+ setverdict(fail, "Failed to match IMSI ", imsi, " in ", req);
+ }
}
f_shutdown(__BFILE__, __LINE__, final := true);
@@ -1781,7 +3933,7 @@ testcase TC_paging_cs_from_sgsn_sign() runs on RAW_PCU_Test_CT {
}
testcase TC_paging_cs_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
- f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvci);
+ f_tc_paging_cs_from_sgsn(mp_gb_cfg.bvc[0].bvci);
}
/* Test PS paging over Gb (SGSN->PCU->BTS[CCCH]).
@@ -1798,12 +3950,11 @@ runs on RAW_PCU_Test_CT {
f_init_gprs_ms();
ms := g_ms[0]; /* We only use first MS in this test */
- /* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_statsd_reset();
/* Establish BSSGP connection to the PCU */
f_bssgp_establish();
- f_bssgp_client_llgmm_assign('FFFFFFFF'O, ms.tlli);
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
/* Send BSSGP PAGING-PS (with or without TMSI), wait for RR Paging Request Type 1.
* Make sure that both paging group (IMSI suffix) and Mobile Identity match. */
@@ -1816,19 +3967,457 @@ runs on RAW_PCU_Test_CT {
f_pcuif_rx_pch_pag_req1(tr_MI_IMSI(imsi), imsi_suff_tx);
}
- f_shutdown(__BFILE__, __LINE__, final := true);
+ var StatsDExpects expect := {
+ { name := "TTCN3.pcu.sgsn.0.rx_paging_ps", mtype := "c", min := 1, max := 1 },
+ /* After the PCU receives the paging request from SGSN,
+ * and it doesn't have any errors, PCU sends it to the
+ * BTS to do paging over PCH. */
+ { name := "TTCN3.bts.0.pch.requests", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
}
testcase TC_paging_ps_from_sgsn_sign_ptmsi() runs on RAW_PCU_Test_CT {
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
f_tc_paging_ps_from_sgsn(0, true);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_paging_ps_from_sgsn_sign() runs on RAW_PCU_Test_CT {
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
f_tc_paging_ps_from_sgsn(0);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
testcase TC_paging_ps_from_sgsn_ptp() runs on RAW_PCU_Test_CT {
- f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvci);
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvc[0].bvci);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_paging_pch_timeout() runs on RAW_PCU_Test_CT {
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Set T3113 to 1s to shorten the test duration */
+ f_vty_config2(PCUVTY, {"pcu"}, "timer T3113 1");
+
+ /* Reset stats and send paging PS request */
+ f_tc_paging_ps_from_sgsn(mp_gb_cfg.bvc[0].bvci);
+
+ /* Verify that counter increases when T3113 times out (MS did not start
+ * TBF to respond to paging). */
+ f_sleep(1.2);
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.pch.requests.timeout", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+
+ f_vty_config2(PCUVTY, {"pcu"}, "timer T3113 default");
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify osmo-pcu handles DL UNIT_DATA from SGSN with IMSI IE correctly. See OS#4729 */
+testcase TC_bssgp_dl_unitdata_with_valid_imsi() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ f_statsd_reset();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ /* ACK the DL block */
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.tbf.dl.alloc", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.tbf.ul.alloc", mtype := "c", min := 1, max := 1},
+ { name := "TTCN3.bts.0.rlc.dl_payload_bytes", mtype := "c", min := 10, max := 10},
+ { name := "TTCN3.bts.0.rlc.ul_payload_bytes", mtype := "c", min := 26, max := 26}
+ };
+ f_statsd_expect(expect);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify osmo-pcu acts on incorrect IMSI IE content in DL UNIT_DATA from SGSN. See OS#4729 */
+testcase TC_bssgp_dl_unitdata_with_invalid_imsi() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Fake GMM GPRS Attach or similar, PCU doesn't care about upper layers here */
+ f_ms_tx_ul_data_block_multi(ms, 1, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+
+ /* UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+
+ /* Now SGSN sends some DL data with an invalid IMSI */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI('1122'H)));
+
+ BSSGP_GLOBAL[0].receive(tr_BSSGP_STATUS(omit, BSSGP_CAUSE_CONDITIONAL_IE_ERROR, ?));
+
+ /* TODO: make sure no data is sent over PCU -> MS */
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+private function f_tc_dl_data_no_llc_ui_dummy(template (omit) MSRadioAccessCapabilityV_BSSGP ms_racap := omit) runs on RAW_PCU_Test_CT {
+ var AckNackDescription ack_nack_desc := valueof(t_AckNackDescription_init);
+ var octetstring data := f_rnd_octstring(6);
+ var RlcmacDlBlock dl_block;
+ var GprsMS ms;
+ var uint32_t fn;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, ms_racap, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
+ f_sleep(X2002);
+
+ /* Expect the first (GPRS DL) block with bsn=0 and rrbp_valid=1 */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, fn, data, 0);
+
+ if (ischosen(dl_block.data_egprs)) {
+ if (lengthof(dl_block.data_egprs.blocks) != 2) {
+ setverdict(fail, "DL EGPRS block has unexpected number of LLC frames: ", dl_block.data_egprs);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ if (dl_block.data_egprs.blocks[1].hdr.length_ind != 127) {
+ setverdict(fail, "DL EGPRS block 2nd llc frame is not padding!: ", dl_block.data_egprs);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ if (not match(dl_block.data_egprs.blocks[1].payload,
+ f_pad_oct(''O, lengthof(dl_block.data_egprs.blocks[1].payload), '2B'O))) {
+ setverdict(fail, "DL EGPRS block 2nd llc frame is not padding!: ", dl_block.data_egprs);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ } else if (lengthof(dl_block.data.blocks) > 1) {
+ setverdict(fail, "DL GPRS block has extra unexpected LLC frames: ", dl_block.data);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify osmo-pcu Doesn't append LLC UI dummy frames to rlcmac blocks
+ * containing llc data. See OS#4849 */
+testcase TC_dl_gprs_data_no_llc_ui_dummy() runs on RAW_PCU_Test_CT {
+ f_tc_dl_data_no_llc_ui_dummy(omit);
+}
+
+/* Verify osmo-pcu Doesn't append LLC UI dummy frames to rlcmac blocks
+ * containing llc data. See OS#4849 */
+testcase TC_dl_egprs_data_no_llc_ui_dummy() runs on RAW_PCU_Test_CT {
+ f_tc_dl_data_no_llc_ui_dummy(bssgp_ms_racap_egprs_def);
+}
+
+/* Scenario: MS creates one phase access, does contention resolution CV>0 and
+ * finishes sending data (CV=0), which is forwarded to SGSN by PCU. PCU acks with
+ * FINAL_ACK=1 (hence UL TBF moves to FINISHED state). Then SGSN answers and PCU
+ * has to assign a DL TBF (through PCH because of FINISHED state, TS 44.060 9.3.3.3.2).
+ * Make sure the assignment is not done until we receive the PKT CTRL ACK from the MS
+ * (at that time we know the MS is listening on PCH again). OS#5700.
+ */
+testcase TC_ul_tbf_finished_pkt_dl_ass_pch() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ timer T;
+ var octetstring payload;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
+ dl_fn := f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+ f_ms_tx_ul_data_block(ms, payload, cv := 1, with_tlli := true, fn := f_next_pdch_block(dl_fn));
+
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, false));
+ f_ms_tx_ul_data_block(ms, payload, cv := 0);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+
+ /* 1 UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+ /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+
+ /* UL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS: */
+ f_sleep(X2002);
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Scenario: MS creates a UL TBF and
+ * finishes sending data (CV=0), which is forwarded to SGSN by PCU. PCU acks with
+ * FINAL_ACK=1 (hence UL TBF moves to FINISHED state). Then SGSN answers and PCU
+ * has to assign a DL TBF on PCH. While the network is waiting for the MS to
+ * move to PDCH before transmitting DL data (timer X2002), the MS finds out it
+ * needs to send new UL data and hence sends a RACH request to create a new UL
+ * TBF.
+ * Make sure the the MS is assigned a DL TBF through PACCH in that case even if
+ * no new DL data is received from the SGSN. OS#5700.
+ * This test validates the specific case where the 2nd UL TBF is done through
+ * 1phase-access.
+ */
+testcase TC_ul_tbf_1phase_while_dl_ass_pch() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t poll_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ timer T;
+ var octetstring payload;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
+ dl_fn := f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+ f_ms_tx_ul_data_block(ms, payload, cv := 1, with_tlli := true, fn := f_next_pdch_block(dl_fn));
+
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, false));
+ f_ms_tx_ul_data_block(ms, payload, cv := 0);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+
+ /* 1 UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+ /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+
+ /* UL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Now the PCU is waiting for the MS to move to PDCH in order to send data to it (timer X2002).
+ * The MS decides it want to send new Ul TBF so it send RACH req to ask for it: */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ dl_fn := f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ * contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
+ f_ms_tx_ul_data_block(ms, payload, cv := 1, with_tlli := true, fn := f_next_pdch_block(dl_fn));
+
+ /* UL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+
+ /* The PCU considers the MS to have gone over Contention Resolution
+ * after having sent the first UL ACK/NACK to it, hence next it will try to
+ * assign the DL-TBF to send the data it received from the SGSN previously: */
+ f_ms_rx_pkt_ass_pacch(ms, poll_fn, tr_RLCMAC_DL_PACKET_ASS);
+ /* the MS ACKs the PKT_DL_ASS: */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), poll_fn);
+
+ /* We should finally receive the DL-data that was received previously from the SGSN: */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Same as TC_ul_tbf_2phase_while_dl_ass_pch, but this test validates the
+ * specific case where the 2nd UL TBF is done through 2phase-access. */
+testcase TC_ul_tbf_2phase_while_dl_ass_pch() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var octetstring data := f_rnd_octstring(10);
+ var uint32_t sched_fn;
+ var uint32_t poll_fn;
+ var uint32_t dl_fn;
+ var GprsMS ms;
+ timer T;
+ var octetstring payload;
+ var PollFnCtx pollctx;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send one UL block (with TLLI since we are in One-Phase Access
+ contention resolution) and make sure it is ACKED fine. */
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, true));
+ dl_fn := f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+ f_ms_tx_ul_data_block(ms, payload, cv := 1, with_tlli := true, fn := f_next_pdch_block(dl_fn));
+
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+ payload := f_rnd_octstring(f_ultbf_payload_fill_length(ms.ul_tbf, false));
+ f_ms_tx_ul_data_block(ms, payload, cv := 0);
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, sched_fn);
+
+ /* 1 UL block should be received in SGSN */
+ BSSGP[0].receive(tr_BSSGP_UL_UD(ms.tlli, mp_gb_cfg.bvc[0].cell_id));
+ /* Now SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, imsi := ts_BSSGP_IMSI(ms.imsi)));
+
+ /* UL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Now the PCU is waiting for the MS to move to PDCH in order to send data to it (timer X2002).
+ * The MS decides it want to send new Ul TBF so it send RACH req to ask for it: */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Now that MS seized the UL-TBF, PCU sends DL-TBF Assignment on PACCH */
+ f_ms_rx_pkt_ass_pacch(ms, poll_fn, tr_RLCMAC_DL_PACKET_ASS);
+ /* the MS ACKs the PKT_DL_ASS: */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), poll_fn);
+
+ /* We should finally receive the DL-data that was received previously from the SGSN: */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
}
private function f_TC_egprs_pkt_chan_req(in EGPRSPktChRequest req,
@@ -1854,16 +4443,18 @@ testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
signalling := { tag := '110011'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
req.signalling.random_bits := ext_ra;
@@ -1875,6 +4466,19 @@ testcase TC_egprs_pkt_chan_req_signalling() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -1882,16 +4486,18 @@ testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
one_phase := { tag := '0'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
var BIT5 mslot_class := int2bit(f_rnd_int(32), 5);
var BIT2 priority := substr(ext_ra, 0, 2);
@@ -1909,6 +4515,19 @@ testcase TC_egprs_pkt_chan_req_one_phase() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -1916,16 +4535,18 @@ testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
var template GsmRrMessage imm_ass;
var template IaRestOctets rest;
var template EgprsUlAss ul_ass;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
two_phase := { tag := '110000'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
var BIT5 ext_ra := int2bit(f_rnd_int(32), 5);
var BIT2 priority := substr(ext_ra, 0, 2);
var BIT3 rand := substr(ext_ra, 2, 3);
@@ -1941,12 +4562,26 @@ testcase TC_egprs_pkt_chan_req_two_phase() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req(req, imm_ass);
}
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
private function f_TC_egprs_pkt_chan_req_reject(bitstring ra11, uint32_t fn,
template IARRestOctets rest := ?,
- PCUIF_BurstType bt := BURST_TYPE_1)
+ PCUIF_BurstType bt := BURST_TYPE_1,
+ template WaitIndication wi := ?)
runs on RAW_PCU_Test_CT {
var template ReqRefWaitInd tr_ref;
var GsmRrMessage rr_msg;
@@ -1965,7 +4600,7 @@ runs on RAW_PCU_Test_CT {
/* Make sure that Request Reference list contains at least one entry
* with our TDMA frame number, and RA is set to 'reserved' value 127. */
- tr_ref := tr_ReqRefWaitInd(f_compute_ReqRef(127, fn));
+ tr_ref := tr_ReqRefWaitInd(f_compute_ReqRef(127, fn), wi);
if (not match(iar.payload, { *, tr_ref, * })) {
setverdict(fail, "Request Reference list does not match");
f_shutdown(__BFILE__, __LINE__);
@@ -1992,11 +4627,13 @@ runs on RAW_PCU_Test_CT {
testcase TC_egprs_pkt_chan_req_reject_content() runs on RAW_PCU_Test_CT {
var template IARRestOctets rest;
var BIT5 ext_ra;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
ext_ra := int2bit(f_rnd_int(32), 5); /* 5 LSB's of RA11 */
rest := tr_IARRestOctets({ *, tr_ExtRAOpt(ext_ra), * });
@@ -2004,6 +4641,18 @@ testcase TC_egprs_pkt_chan_req_reject_content() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req_reject('111111'B & ext_ra, 1337 + i, rest);
}
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
@@ -2013,16 +4662,18 @@ testcase TC_egprs_pkt_chan_req_reject_emergency() runs on RAW_PCU_Test_CT {
var template IARRestOctets rest;
var BIT5 ext_ra;
var BIT11 ra11;
+ const integer num_req := 6;
/* Initialize the PCU interface abstraction */
f_init_raw(testcasename());
+ f_statsd_reset();
var EGPRSPktChRequest req := {
/* NOTE: other fields are set in the loop */
emergency := { tag := '110111'B }
};
- for (var integer i := 0; i < 6; i := i + 1) {
+ for (var integer i := 0; i < num_req; i := i + 1) {
ext_ra := int2bit(f_rnd_int(32), 5); /* 5 LSB's of RA11 */
rest := tr_IARRestOctets({ *, tr_ExtRAOpt(ext_ra), * });
@@ -2033,16 +4684,37 @@ testcase TC_egprs_pkt_chan_req_reject_emergency() runs on RAW_PCU_Test_CT {
f_TC_egprs_pkt_chan_req_reject(ra11, 1337 + i, rest);
}
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := num_req, max := num_req },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
/* Make sure that IUT responds with RR Immediate Assignment Reject due to exhaustion. */
testcase TC_egprs_pkt_chan_req_reject_exhaustion() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
var template IARRestOctets rest;
var BIT11 ra11;
+ info_ind := valueof(ts_PCUIF_INFO_default);
+ info_ind.t3142 := 3;
+
+ /* Only the first TRX is enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+
/* Initialize the PCU interface abstraction */
- f_init_raw(testcasename());
+ f_init_raw(testcasename(), info_ind);
+ f_statsd_reset();
var EGPRSPktChRequest req := {
one_phase := {
@@ -2064,22 +4736,2742 @@ testcase TC_egprs_pkt_chan_req_reject_exhaustion() runs on RAW_PCU_Test_CT {
rest := tr_IARRestOctets({ *, tr_ExtRAOpt(substr(ra11, 6, 5)), * });
/* At this point, the IUT should run out of free USFs */
+ f_TC_egprs_pkt_chan_req_reject(ra11, 1870, rest, wi := info_ind.t3142);
+
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.rach.requests", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.11bit", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.one_phase", mtype := "c", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.rach.requests.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.rach.requests.unexpected", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_UL", mtype := "c", min := 7, max := 7 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.one_phase", mtype := "c", min := 7, max := 7 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.two_phase", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_ul.contention_resolution_success", mtype := "c", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.immediate.assignment_rej", mtype := "c", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.immediate.assignment_DL", mtype := "c", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Randomly generate a set of hopping parameters for one timeslot */
+private function f_TC_pcuif_fh_params_gen(integer max_ma_len)
+return template (value) PCUIF_InfoTrxTs {
+ /* Pick a random MA length in range 2 .. max_ma_len */
+ var integer ma_len := 2 + f_rnd_int(max_ma_len - 2);
+
+ return ts_PCUIF_InfoTrxTsH1(tsc := f_rnd_int(7),
+ hsn := f_rnd_int(63),
+ maio := f_rnd_int(63),
+ ma := f_rnd_bitstring(ma_len));
+}
+
+private function f_TC_pcuif_fh_check_imm_ass(in PCUIF_info_ind info_ind,
+ in GsmRrMessage rr_msg)
+{
+ var ImmediateAssignment ia := rr_msg.payload.imm_ass;
+ var PCUIF_InfoTrxTs ts := info_ind.trx[0].ts[ia.pkt_chan_desc.tn];
+
+ var template PacketChannelDescription tr_pkt_chan_desc := {
+ channel_Type_spare := ?,
+ tn := ?,
+ tsc := ts.tsc,
+ presence := '1'B,
+ zero := omit,
+ one := {
+ maio := ts.maio,
+ hsn := ts.hsn
+ }
+ };
+
+ if (not match(ia.pkt_chan_desc, tr_pkt_chan_desc)) {
+ setverdict(fail, "Packet Channel Description does not match: ",
+ ia.pkt_chan_desc, " vs ", tr_pkt_chan_desc);
+ }
+
+ /* Mobile Allocation is expected to be octet-aligned */
+ var uint8_t ma_oct_len := (ts.ma_bit_len + 8 - 1) / 8;
+ var template MobileAllocationLV tr_ma := {
+ len := ma_oct_len, /* in bytes */
+ ma := substr(ts.ma, 0, ma_oct_len * 8)
+ };
+
+ if (not match(ia.mobile_allocation, tr_ma)) {
+ setverdict(fail, "Mobile Allocation does not match: ",
+ ia.mobile_allocation, " vs ", tr_ma);
+ }
+
+ setverdict(pass);
+}
+
+/* Make sure that Immediate (UL EGPRS TBF) Assignment contains hopping parameters */
+testcase TC_pcuif_fh_imm_ass_ul_egprs() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default;
+ var GprsMS ms := valueof(t_GprsMS_def);
+
+ /* Enable frequency hopping on TRX0/TS7 */
+ info_ind.trx[0].ts[7] := f_TC_pcuif_fh_params_gen(32);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* EGPRS Packet Channel Request (cause=Signalling) */
+ f_ms_use_ra(ms, bit2int('11001101010'B), ra_is_11bit := 1);
+
+ /* Establish an Uplink EGPRS TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ f_TC_pcuif_fh_check_imm_ass(valueof(info_ind), ms.ul_tbf.rr_imm_ass);
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Make sure that Immediate (UL TBF) Assignment contains hopping parameters */
+testcase TC_pcuif_fh_imm_ass_ul() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS);
+ var GprsMS ms := valueof(t_GprsMS_def);
+
+ /* Enable frequency hopping on TRX0/TS7 */
+ info_ind.trx[0].ts[7] := f_TC_pcuif_fh_params_gen(32);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ f_TC_pcuif_fh_check_imm_ass(valueof(info_ind), ms.ul_tbf.rr_imm_ass);
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Make sure that Immediate (DL TBF) Assignment contains hopping parameters */
+testcase TC_pcuif_fh_imm_ass_dl() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS);
+ var GprsMS ms := valueof(t_GprsMS_def);
+
+ /* Enable frequency hopping on TRX0/TS7 */
+ info_ind.trx[0].ts[7] := f_TC_pcuif_fh_params_gen(16);
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, f_rnd_octstring(12)));
+
+ /* The PCU will send an IMMEDIATE ASSIGNMENT message on the AGCH. It
+ * should be noted that IMMEDIATE ASSIGNMENT messages for DL TBFs are
+ * commonly sent on the PCH. However in this case the IMSI is not
+ * known to the PCU and hence no paging group can be calculated. The
+ * PCU is then forced to use the AGCH.
+ *
+ * As a background information to this it should be noted that this
+ * works because the IMSI is commonly unknown during a GMM ATTACH
+ * REQUEST. In this phase the MS is in non-DRX mode, which means that
+ * it listens on all CCCH blocks (PCH and AGCH)
+ *
+ * See also: 3gpp TS 44.060, section 5.5.1.5 and
+ * 3gpp TS 45.002, section 6.5.3, 6.5.6
+ */
+ f_ms_exp_dl_tbf_ass_ccch(ms, PCU_IF_SAPI_AGCH_2);
+
+ f_TC_pcuif_fh_check_imm_ass(valueof(info_ind), ms.dl_tbf.rr_imm_ass);
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+private function f_TC_pcuif_fh_check_pkt_ass(in PCUIF_info_ind info_ind,
+ in FrequencyParameters fp)
+{
+ /* FIXME: TRX0/TS7 is a hard-coded expectation, make it configurable */
+ var PCUIF_InfoTrxTs ts := info_ind.trx[0].ts[7];
+
+ /* Table 12.8.1: Frequency Parameters information elements */
+ var template FrequencyParameters tr_fp := {
+ tsc := ts.tsc,
+ presence := '10'B, /* Direct encoding 1 */
+ arfcn := omit,
+ indirect := omit,
+ direct1 := {
+ maio := ts.maio,
+ /* Table 12.10a.1: GPRS Mobile Allocation information elements */
+ mobile_allocation := {
+ hsn := ts.hsn,
+ rfl_number_list_present := '0'B,
+ rfl_number_list := omit,
+ ma_present := '0'B, /* inverted logic */
+ ma_length := ts.ma_bit_len,
+ ma_bitmap := substr(ts.ma, 0, ts.ma_bit_len)
+ }
+ },
+ direct2 := omit
+ };
+
+ if (not match(fp, tr_fp)) {
+ setverdict(fail, "Frequency Parameters IE does not match: ",
+ fp, " vs ", tr_fp);
+ }
+
+ setverdict(pass);
+}
+
+/* Make sure that Packet Uplink Assignment contains hopping parameters */
+testcase TC_pcuif_fh_pkt_ass_ul() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS);
+ var GprsMS ms := valueof(t_GprsMS_def);
+ var uint32_t poll_fn;
+
+ /* Enable frequency hopping on TRX0/TS7 */
+ info_ind.trx[0].ts[7] := f_TC_pcuif_fh_params_gen(33);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Single block (two phase) packet access */
+ var uint16_t ra := bit2int(chan_req_sb);
+ f_ms_use_ra(ms, ra, ra_is_11bit := 0);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Send Packet Resource Request, so the network will allocate an Uplink resource */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, omit)),
+ fn := ms.ul_tbf.start_time_fn);
+
+ /* Expect an RLC/MAC block with Packet Uplink Assignment on PACCH (see 11.2.29) */
+ f_ms_rx_pkt_ass_pacch(ms, poll_fn, tr_RLCMAC_UL_PACKET_ASS);
+ var PacketUlAssignment ua := ms.ul_tbf.ass.pacch;
+
+ /* 3GPP TS 44.060, section 12.8 "Frequency Parameters" */
+ var template (omit) FrequencyParameters fp;
+ if (ua.is_egprs == '1'B) {
+ fp := ua.egprs.freq_par;
+ } else {
+ fp := ua.gprs.freq_par;
+ }
+
+ /* This is an optional IE, so it's worth to check its presence */
+ if (istemplatekind(fp, "omit")) {
+ setverdict(fail, "Frequency Parameters IE is not present");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_TC_pcuif_fh_check_pkt_ass(valueof(info_ind), valueof(fp));
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Make sure that Packet Downlink Assignment contains hopping parameters */
+testcase TC_pcuif_fh_pkt_ass_dl() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS);
+ var octetstring data := f_rnd_octstring(10);
+ var GprsMS ms := valueof(t_GprsMS_def);
+ var RlcmacDlBlock dl_block;
+ var uint32_t poll_fn;
+
+ /* Enable frequency hopping on TRX0/TS7 */
+ info_ind.trx[0].ts[7] := f_TC_pcuif_fh_params_gen(33);
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Establish an Uplink TBF */
+ f_ms_establish_ul_tbf(ms);
+
+ /* Wait until PCU starts requesting for UL block on this TBF: */
+ f_ms_wait_usf(ms);
+
+ /* Send an Uplink block, so this TBF becomes "active" */
+ f_ms_tx_ul_data_block(ms, data, with_tlli := true, fn := ms.ul_tbf.start_time_fn);
+
+ /* DL ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_rx_rlcmac_dl_block_exp_ack_nack(dl_block, poll_fn);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), poll_fn);
+
+ /* SGSN sends some DL data, PCU will assign Downlink resource on PACCH */
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+
+ /* Expect an RLC/MAC block with Packet Downlink Assignment on PACCH (see 11.2.29) */
+ f_ms_rx_pkt_ass_pacch(ms, poll_fn, tr_RLCMAC_DL_PACKET_ASS);
+ var PacketDlAssignment da := ms.dl_tbf.ass.pacch;
+
+ /* This is an optional IE, so it's worth to check its presence */
+ if (not ispresent(da.freq_par)) {
+ setverdict(fail, "Frequency Parameters IE is not present");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_TC_pcuif_fh_check_pkt_ass(valueof(info_ind), da.freq_par);
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Check if the IUT handles subsequent INFO.ind messages */
+testcase TC_pcuif_info_ind_subsequent() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default;
+ var BTS_PDTCH_Block data_msg;
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Send 16 conseqtive INFO.ind messages and check that the IUT stays alive */
+ for (var integer i := 0; i < 16; i := i + 1) {
+ BTS.send(ts_PCUIF_INFO_IND(0, info_ind));
+ f_pcuif_rx_data_req_pdtch(data_msg);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify allocation of several MS along PDCH ts of several TRX. See OS#1775, SYS#5030 */
+testcase TC_multitrx_multims_alloc() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var integer i;
+ const integer num_ms := 8;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms(num_ms);
+
+ info_ind := valueof(ts_PCUIF_INFO_default(c_PCUIF_Flags_noMCS));
+ /* Only the 3 first TRX are enabled. The enabled ones all have same
+ amount of resources, hence same amount of initial resources. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (3 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000011'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00001100'B, 1);
+ f_PCUIF_PDCHMask_set(info_ind, '11000000'B, 2);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_multi_ms_bssgp_register();
+
+ /* Establish an Uplink TBF for each GprsMS instance */
+ f_multi_ms_establish_tbf(do_activate := false);
+
+ /* Check if all TBFs are allocated on different TRX in an uniform way */
+ for (i := 0; i < num_ms; i := i + 1) {
+ if (g_ms[i].ul_tbf.arfcn != info_ind.trx[i mod 3].arfcn) {
+ setverdict(fail, "Got assigned ARFCN ", g_ms[i].ul_tbf.arfcn,
+ " vs exp ", info_ind.trx[i mod 3].arfcn);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify concurrent PDCH use of EGPRS and GPRS (EGPRS dl rlcmac blk is
+ * downgraded to CS1-4 so that GPRS can read the USF).
+ * See 3GPP TS 44.060 5.2.4a "Multiplexing of GPRS, EGPRS and EGPRS2 capable mobile stations"
+ */
+testcase TC_multiplex_dl_gprs_egprs() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ const integer num_ms := 2; /* 2 MS, first one is GPRS-only, second one is EGPRS */
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn, dl_fn, ack_fn;
+ var octetstring data := f_rnd_octstring(10);
+ var RlcmacDlBlock dl_block;
+ var integer tx_data_remain := 5;
+ var integer tgt_ms, usf_ms;
+ var integer ms_gprs_usf_count[num_ms] := { 0, 0 };
+ var integer ms_egprs_usf_count[num_ms] := { 0, 0 };
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms(num_ms);
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+ /* Only use 1 PDCH to make sure both end up in the same slot: */
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Set Initial MCS > 4 and maintain it non-variable to simplify test */
+ g_mcs_initial_dl := 5;
+ g_mcs_max_dl := 5;
+ f_pcuvty_set_allowed_cs_mcs();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_multi_ms_bssgp_register();
+
+ /* Establish UL TBF for MS0 (GPRS-only) */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(g_ms[0], ts_RlcMacUlCtrl_PKT_RES_REQ(g_ms[0].tlli, ms_racap_gprs_def));
+ if (not match(g_ms[0].ul_tbf.tx_cs_mcs, cs_gprs_any)) {
+ setverdict(fail, "Wrong CS_MCS ", g_ms[0].ul_tbf.tx_cs_mcs, " received vs exp ", cs_gprs_any);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(g_ms[0], ts_RLCMAC_CTRL_ACK(g_ms[0].tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Establish UL TBF for MS1 (EGPRS) */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(g_ms[1], ts_RlcMacUlCtrl_PKT_RES_REQ(g_ms[1].tlli, ms_racap_egprs_def));
+ if (not match(g_ms[1].ul_tbf.tx_cs_mcs, mcs_egprs_any)) {
+ setverdict(fail, "Wrong CS_MCS ", g_ms[1].ul_tbf.tx_cs_mcs, " received vs exp ", mcs_egprs_any);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(g_ms[1], ts_RLCMAC_CTRL_ACK(g_ms[1].tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Now SGSN sends some DL data to MS0, PCU will assign a GPRS DL TBF on PACCH */
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[0].tlli, data));
+ f_sleep(0.1);
+ f_ms_rx_pkt_ass_pacch(g_ms[0], sched_fn, tr_RLCMAC_DL_PACKET_ASS);
+ /* DL Ass sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(g_ms[0], ts_RLCMAC_CTRL_ACK(g_ms[0].tlli), sched_fn);
+ /* After acking the dl assignment, dl tbf goes into FLOW state and PCU will provide DL data when BTS asks for it */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, cs_gprs_any);
+ /* ACK the DL block */
+ f_dltbf_ack_block(g_ms[0].dl_tbf, dl_block, '0'B);
+ f_ms_tx_ul_block(g_ms[0], f_dltbf_ts_RLCMAC_DL_ACK_NACK(g_ms[0].dl_tbf, false),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ /* Now SGSN sends some DL data to MS1, PCU will assign a EGPRS DL TBF on PACCH */
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[1].tlli, data));
+ f_sleep(0.1);
+ f_ms_rx_pkt_ass_pacch(g_ms[1], sched_fn, tr_RLCMAC_DL_PACKET_ASS);
+ /* DL Ass sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(g_ms[1], ts_RLCMAC_CTRL_ACK(g_ms[1].tlli), sched_fn);
+ /* After acking the dl assignment, dl tbf goes into FLOW state and PCU will provide DL data when BTS asks for it */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0, mcs_egprs_any);
+ /* ACK the DL block */
+ f_dltbf_ack_block(g_ms[1].dl_tbf, dl_block, '0'B);
+ f_ms_tx_ul_block(g_ms[1], f_dltbf_ts_RLCMAC_DL_ACK_NACK(g_ms[1].dl_tbf, true),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ data := f_rnd_octstring(1400);
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[0].tlli, data));
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[1].tlli, data));
+
+ for (var integer i := 0; i < 800; i := i + 1) {
+ f_rx_rlcmac_dl_block(dl_block, dl_fn);
+
+ if (match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL)) {
+ /* No more data to receive, done */
+ break;
+ }
+
+ usf_ms := -1;
+
+ if (ischosen(dl_block.ctrl)) {
+ setverdict(fail, "Unexpected DL CTRL block ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ } else if (ischosen(dl_block.data_egprs)) {
+ if (not match(dl_block.data_egprs.mac_hdr.tfi, g_ms[1].dl_tbf.tfi)) {
+ setverdict(fail, "EGPRS DL DATA not matching EGPRS MS TFI (", g_ms[1].dl_tbf.tfi, "): ", dl_block.data_egprs.mac_hdr.tfi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ tgt_ms := 1;
+ if (match(dl_block.data_egprs.mac_hdr.usf, g_ms[0].ul_tbf.usf[7])) {
+ if (dl_block.data_egprs.mcs > MCS_4) {
+ setverdict(fail, "Signalling USF ", dl_block.data_egprs.mac_hdr.usf, " for GPRS-only MS using MCS > 4: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ usf_ms := 0;
+ ms_egprs_usf_count[usf_ms] := ms_egprs_usf_count[usf_ms] + 1;
+ } else {
+ if (dl_block.data_egprs.mcs <= MCS_4) {
+ setverdict(fail, "Using too-low MCS for EGPRS MS: ", dl_block.data_egprs.mcs);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ if (match(dl_block.data_egprs.mac_hdr.usf, g_ms[1].ul_tbf.usf[7])) {
+ usf_ms := 1;
+ ms_egprs_usf_count[usf_ms] := ms_egprs_usf_count[usf_ms] + 1;
+ }
+ }
+ } else {
+ if (not match(dl_block.data.mac_hdr.hdr_ext.tfi, g_ms[0].dl_tbf.tfi)) {
+ setverdict(fail, "GPRS DL DATA not matching GPRS MS TFI (", g_ms[0].dl_tbf.tfi, "): ", dl_block.data.mac_hdr.hdr_ext.tfi);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ tgt_ms := 0;
+ if (match(dl_block.data.mac_hdr.mac_hdr.usf, g_ms[0].ul_tbf.usf[7])) {
+ usf_ms := 0;
+ ms_gprs_usf_count[usf_ms] := ms_gprs_usf_count[usf_ms] + 1;
+ } else if (match(dl_block.data.mac_hdr.mac_hdr.usf, g_ms[1].ul_tbf.usf[7])) {
+ usf_ms := 1;
+ ms_gprs_usf_count[usf_ms] := ms_gprs_usf_count[usf_ms] + 1;
+ }
+ }
+
+ /* Keep Ack/Nack description updated */
+ f_dltbf_ack_block(g_ms[tgt_ms].dl_tbf, dl_block);
+
+ /* TDMA frame number on which we are supposed to send the ACK */
+ if (f_dl_block_rrbp_valid(dl_block)) {
+ ack_fn := f_dl_block_ack_fn(dl_block, dl_fn);
+ f_ms_tx_ul_block(g_ms[tgt_ms], f_dltbf_ts_RLCMAC_DL_ACK_NACK(g_ms[tgt_ms].dl_tbf, ischosen(dl_block.data_egprs)), ack_fn);
+ if (tx_data_remain != 0) {
+ /* Submit more data from time to time to keep the TBF ongoing */
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[0].tlli, data));
+ BSSGP[0].send(ts_BSSGP_DL_UD(g_ms[1].tlli, data));
+ tx_data_remain := tx_data_remain - 1;
+ }
+ } else if (tx_data_remain != 0) {
+ /* keep sending UL blocks when requested by USF to avoid
+ * UL TBF timeout and hence stop receival of USFs */
+ if (usf_ms != -1) {
+ f_ms_tx_ul_data_block(g_ms[usf_ms], f_rnd_octstring(10), cv := 15);
+ }
+ }
+ }
+
+ log("results: ms_gprs_usf_count=", ms_gprs_usf_count, " / ms_egprs_usf_count=", ms_egprs_usf_count);
+ /* He we check that DL blocks scheduled at GPRS can still request UL
+ * blocks for EGPRS MS, and the other way around. Furthermore, the 2nd
+ * condition also ensures the downgrade to <=MCS4 condition is tested
+ * above */
+ if (ms_gprs_usf_count[1] == 0 or ms_egprs_usf_count[0] == 0) {
+ setverdict(fail, "USF exchange thresholds not met!");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* Here check for some level of fairness between them (at least ~40%): */
+ var integer gprs_usf_cnt := ms_gprs_usf_count[0] + ms_egprs_usf_count[0];
+ var integer egprs_usf_cnt := ms_gprs_usf_count[1] + ms_egprs_usf_count[1];
+ var integer total_usf_cnt := gprs_usf_cnt + egprs_usf_cnt;
+ if (gprs_usf_cnt < total_usf_cnt * 4 / 10) {
+ setverdict(fail, "USF GPRS-only MS ", gprs_usf_cnt, " < ", total_usf_cnt * 4 / 10);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ if (egprs_usf_cnt < total_usf_cnt * 4 / 10) {
+ setverdict(fail, "USF EGPRS MS ", egprs_usf_cnt, " < ", total_usf_cnt * 4 / 10);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+
+private function f_TC_paging_cs_multi_ms(template (value) TsTrxBtsNum nr,
+ boolean exp_imsi, boolean exp_tmsi)
+runs on RAW_PCU_Test_CT {
+ var bitstring mask := f_pad_bit(''B, lengthof(g_ms), '0'B);
+ var integer pending := lengthof(g_ms);
+ var RlcmacDlBlock dl_block;
+ var boolean f1, f2;
+
+ while (pending > 0) {
+ var uint32_t poll_fn;
+
+ /* Obtain a Downlink block and make sure it is a paging request */
+ f_rx_rlcmac_dl_block(dl_block, poll_fn, nr := nr);
+ if (not match(dl_block, tr_RLCMAC_PACKET_PAG_REQ)) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ break;
+ }
+
+ /* This should not happen in general, but who knows... */
+ var PacketPagingReq req := dl_block.ctrl.payload.u.paging;
+ if (not ispresent(req.repeated_pageinfo)) {
+ setverdict(fail, "Repeated Page Info IE is absent?!?");
+ break;
+ }
+
+ /* A single message may contain several MIs depending on their type */
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ f1 := exp_imsi and f_pkt_paging_match_imsi(req, g_ms[i].imsi,
+ ps_domain := false);
+ f2 := exp_tmsi and f_pkt_paging_match_tmsi(req, oct2int(g_ms[i].tlli),
+ ps_domain := false);
+ if (not f1 and not f2)
+ { continue; }
+
+ /* Detect duplicate MIs */
+ if (mask[i] == '1'B) {
+ setverdict(fail, "MS is paged twice: ", g_ms[i].imsi);
+ continue;
+ }
+
+ mask[i] := '1'B;
+ }
+
+ pending := pending - lengthof(req.repeated_pageinfo);
+ }
+
+ for (var integer i := 0; i < lengthof(mask); i := i + 1) {
+ if (mask[i] != '1'B) {
+ setverdict(fail, "MS was not paged at all: ", g_ms[i].imsi);
+ log("===== mask := ", mask);
+ }
+ }
+
+ /* All messages must have been received by now, expect a dummy block */
+ f_rx_rlcmac_dl_block_exp_dummy(dl_block, nr := nr);
+}
+
+private function f_TC_paging_cs_multi_ms_init(BIT8 pdch_mask)
+runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Explicitly set the given PDCH slot-mask to all transceivers */
+ f_PCUIF_PDCHMask_set(info_ind, pdch_mask);
+
+ /* Allocate 56 GprsMS instances (maximum for 8 PDCH slots) */
+ f_init_gprs_ms(7 * 8);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_multi_ms_bssgp_register();
+
+ /* Establish an Uplink TBF for each GprsMS instance */
+ f_multi_ms_establish_tbf(do_activate := true);
+}
+
+testcase TC_paging_cs_multi_ms_imsi() runs on RAW_PCU_Test_CT {
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Common part: send INFO.ind, establish TBFs... */
+ f_TC_paging_cs_multi_ms_init(pdch_mask := '00000001'B);
+
+ /* Enqueue multiple CS PAGING requests at a time (IMSI only) */
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, g_ms[i].imsi));
+ }
+
+ /* FIXME: work around a race condition between PCUIF and BSSGP */
+ f_sleep(0.2); /* i.e. give the IUT some time to process everything */
+
+ /* Check what the IUT sends on PACCH, all GprsMS instances must be paged.
+ * The IUT is expected to page on all PDCH slots of all transceivers. */
+ for (var integer trx_nr := 0; trx_nr < 8; trx_nr := trx_nr + 1) {
+ var template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum(7, trx_nr);
+ f_TC_paging_cs_multi_ms(nr, exp_imsi := true, exp_tmsi := false);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_paging_cs_multi_ms_tmsi() runs on RAW_PCU_Test_CT {
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Common part: send INFO.ind, establish TBFs... */
+ f_TC_paging_cs_multi_ms_init(pdch_mask := '00000001'B);
+
+ /* Enqueue multiple CS PAGING requests at a time (P-TMSI only) */
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ var GsmTmsi tmsi := oct2int(g_ms[i].tlli); /* P-TMSI == TLLI */
+ BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, g_ms[i].imsi, tmsi));
+ }
+
+ /* FIXME: work around a race condition between PCUIF and BSSGP */
+ f_sleep(0.2); /* i.e. give the IUT some time to process everything */
+
+ /* Check what the IUT sends on PACCH, all GprsMS instances must be paged.
+ * The IUT is expected to page on all PDCH slots of all transceivers. */
+ for (var integer trx_nr := 0; trx_nr < 8; trx_nr := trx_nr + 1) {
+ var template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum(7, trx_nr);
+ f_TC_paging_cs_multi_ms(nr, exp_imsi := false, exp_tmsi := true);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_paging_cs_multi_ms_imsi_tmsi() runs on RAW_PCU_Test_CT {
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Common part: send INFO.ind, establish TBFs... */
+ f_TC_paging_cs_multi_ms_init(pdch_mask := '00000001'B);
+
+ /* Enqueue multiple CS PAGING requests at a time (IMSI & P-TMSI) */
+ for (var integer i := 0; i < lengthof(g_ms); i := i + 1) {
+ var GsmTmsi tmsi := oct2int(g_ms[i].tlli); /* P-TMSI == TLLI */
+ if (i mod 3 == 0) { /* One PDU fits: 1 IMSI and 2 P-TMSI MIs */
+ BSSGP[0].send(ts_BSSGP_CS_PAGING_PTMSI(bvci, g_ms[i].imsi, tmsi));
+ } else {
+ BSSGP[0].send(ts_BSSGP_CS_PAGING_IMSI(bvci, g_ms[i].imsi));
+ }
+ }
+
+ /* FIXME: work around a race condition between PCUIF and BSSGP */
+ f_sleep(0.2); /* i.e. give the IUT some time to process everything */
+
+ /* Check what the IUT sends on PACCH, all GprsMS instances must be paged.
+ * The IUT is expected to page on all PDCH slots of all transceivers. */
+ for (var integer trx_nr := 0; trx_nr < 8; trx_nr := trx_nr + 1) {
+ var template (value) TsTrxBtsNum nr := ts_TsTrxBtsNum(7, trx_nr);
+ f_TC_paging_cs_multi_ms(nr, exp_imsi := true, exp_tmsi := true);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+private function f_skip_dummy(integer max_num_iter, out uint32_t sched_fn)
+runs on RAW_PCU_Test_CT return RlcmacDlBlock {
+ var RlcmacDlBlock dl_block;
+ var integer i := 0;
+ while (true) {
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_DUMMY_CTRL())) {
+ break;
+ }
+ if (max_num_iter > 0 and i > max_num_iter) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ i := i + 1;
+ }
+ return dl_block;
+}
+
+private const GsmMcc c_BssgpCellMcc := '623'H; /* MCC: Central African Republic */
+private const GsmMnc c_BssgpCellMnc := '03'H; /* MNC: Celca (Socatel) */
+private template (value) BssgpCellId ts_BssgpCellIdDstAddr_default := {
+ ra_id := {
+ lai := {
+ mcc_mnc := f_build_BcdMccMnc(c_BssgpCellMcc, c_BssgpCellMnc),
+ lac := 423
+ },
+ rac := 2
+ },
+ cell_id := 5
+}
+
+private function f_outbound_nacc_rim_tx_resp(PCUIF_info_ind info_ind)
+runs on RAW_PCU_Test_CT {
+ /* Source Cell Identifier IE is generated by osmo-pcu based on the INFO.ind */
+ var BcdMccMnc src_mcc_mnc := f_build_BcdMccMnc_int(info_ind.mcc, info_ind.mnc, info_ind.mnc_3_digits == 1);
+ var BssgpCellId src := valueof(ts_BssgpCellId(ts_RAI(ts_LAI(src_mcc_mnc, info_ind.lac), info_ind.rac),
+ info_ind.cell_id));
+ /* Destination Cell Identifier IE is resolved by the testsuite itself (emulating BSC) */
+ var BssgpCellId dst := valueof(ts_BssgpCellIdDstAddr_default);
+ var RIM_Routing_Address src_addr := valueof(t_RIM_Routing_Address_cid(src));
+ var RIM_Routing_Address dst_addr := valueof(t_RIM_Routing_Address_cid(dst));
+ var template (value) RAN_Information_RIM_Container res_cont :=
+ ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(2),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_ApplContainer_or_ApplErrContainer_NACC(tsu_ApplContainer_NACC(dst, false, 3, si_default)),
+ omit);
+ RIM.send(ts_PDU_BSSGP_RAN_INFORMATION(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ res_cont));
+}
+
+altstep as_outbound_nacc_rim_resolve(PCUIF_info_ind info_ind, boolean do_answer := true, boolean do_repeat := false)
+runs on RAW_PCU_Test_CT {
+ /* Source Cell Identifier IE is generated by osmo-pcu based on the INFO.ind */
+ var BcdMccMnc src_mcc_mnc := f_build_BcdMccMnc_int(info_ind.mcc, info_ind.mnc, info_ind.mnc_3_digits == 1);
+ var BssgpCellId src := valueof(ts_BssgpCellId(ts_RAI(ts_LAI(src_mcc_mnc, info_ind.lac), info_ind.rac),
+ info_ind.cell_id));
+ /* Destination Cell Identifier IE is resolved by the testsuite itself (emulating BSC) */
+ var BssgpCellId dst := valueof(ts_BssgpCellIdDstAddr_default);
+ var RIM_Routing_Address src_addr := valueof(t_RIM_Routing_Address_cid(src));
+ var RIM_Routing_Address dst_addr := valueof(t_RIM_Routing_Address_cid(dst));
+ [] RIM.receive(tr_RAN_INFORMATION_REQUEST(tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ tr_RAN_Information_Request_RIM_Container)) {
+ if (do_answer) {
+ f_outbound_nacc_rim_tx_resp(info_ind);
+ }
+ if (do_repeat) {
+ repeat;
+ }
+ }
+}
+
+private function f_ctrl_rx_nacc_rac_ci_req(out CtrlMessage ctrl_req,
+ PCUIF_info_ind info_ind,
+ GsmArfcn req_arfcn,
+ uint6_t req_bsic)
+runs on RAW_PCU_Test_CT {
+ var charstring ctrl_var := "neighbor_resolve_cgi_ps_from_lac_ci." &
+ int2str(info_ind.lac) & "." &
+ int2str(info_ind.cell_id) & "." &
+ int2str(req_arfcn) & "." &
+ int2str(req_bsic);
+ f_ipa_ctrl_wait_link_up();
+ IPA_CTRL.receive(tr_CtrlMsgGet(?, ctrl_var)) -> value ctrl_req;
+}
+
+private function f_ctrl_tx_nacc_rac_ci_rsp(in CtrlMessage ctrl_req)
+runs on RAW_PCU_Test_CT {
+ var BssgpCellId addr := valueof(ts_BssgpCellIdDstAddr_default);
+ IPA_CTRL.send(ts_CtrlMsgGetRepl(ctrl_req.cmd.id,
+ ctrl_req.cmd.variable,
+ hex2str(c_BssgpCellMcc) & "-" &
+ hex2str(c_BssgpCellMnc) & "-" &
+ int2str(addr.ra_id.lai.lac) & "-" &
+ int2str(addr.ra_id.rac) & "-" &
+ int2str(addr.cell_id)));
+}
+
+private function f_pcuif_rx_nacc_rac_ci_req(out PCUIF_Message addr_req,
+ PCUIF_info_ind info_ind,
+ GsmArfcn req_arfcn,
+ uint6_t req_bsic)
+runs on RAW_PCU_Test_CT {
+ BTS.receive(tr_PCUIF_NEIGH_ADDR_REQ(0, info_ind.lac, info_ind.cell_id,
+ req_arfcn, req_bsic)) -> value addr_req;
+}
+
+private function f_pcuif_tx_nacc_rac_ci_rsp(in PCUIF_Message addr_req)
+runs on RAW_PCU_Test_CT {
+ var BssgpCellId addr := valueof(ts_BssgpCellIdDstAddr_default);
+ BTS.send(ts_PCUIF_NEIGH_ADDR_CNF(0, addr_req.u.container.u.neigh_addr_req, 0,
+ str2int(hex2str(c_BssgpCellMcc)),
+ str2int(hex2str(c_BssgpCellMnc)),
+ lengthof(c_BssgpCellMnc) - 2,
+ addr.ra_id.lai.lac,
+ addr.ra_id.rac,
+ addr.cell_id));
+}
+
+private function f_handle_nacc_rac_ci_query(PCUIF_info_ind info_ind, GsmArfcn req_arfcn, uint6_t req_bsic,
+ boolean answer := true, boolean use_old_ctrl_iface := false)
+runs on RAW_PCU_Test_CT {
+ if (use_old_ctrl_iface == true) {
+ var CtrlMessage ctrl_req;
+ f_ctrl_rx_nacc_rac_ci_req(ctrl_req, info_ind, req_arfcn, req_bsic);
+ if (answer) {
+ f_ctrl_tx_nacc_rac_ci_rsp(ctrl_req);
+ }
+ } else {
+ var PCUIF_Message pcuif_req;
+ f_pcuif_rx_nacc_rac_ci_req(pcuif_req, info_ind, req_arfcn, req_bsic);
+ if (answer) {
+ f_pcuif_tx_nacc_rac_ci_rsp(pcuif_req);
+ }
+ }
+}
+
+private function f_outbound_nacc_success_no_si(inout GprsMS ms, PCUIF_info_ind info_ind,
+ boolean exp_rac_ci_query := true, boolean exp_si_query := true,
+ boolean skip_final_ctrl_ack := false,
+ boolean use_old_ctrl_iface := false,
+ template (value) RlcmacUlCtrlMsg cell_chg_notif)
+runs on RAW_PCU_Test_CT {
+ var template RlcmacDlCtrlMsg cell_chg_cont;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+
+ /* Start NACC from MS side */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* Obtain a Downlink block and make sure it is a PacketCellChangeContine. We also make sure that this
+ * PacketCellChangeContine message does not contain any ARFCN/BSIC. */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ cell_chg_cont := tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE
+ cell_chg_cont.u.cell_chg_continue.arfcn_bsic_presence := '0'B
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, cell_chg_cont))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (not skip_final_ctrl_ack and dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+}
+
+/* Start NACC from MS side, propose an UTRAN cell */
+private function f_outbound_nacc_success_utran(inout GprsMS ms, PCUIF_info_ind info_ind,
+ boolean exp_rac_ci_query := true, boolean exp_si_query := true,
+ boolean skip_final_ctrl_ack := false,
+ boolean use_old_ctrl_iface := false)
+runs on RAW_PCU_Test_CT {
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var uint14_t req_uarfcn := 1234;
+ var uint10_t req_scrambling_code := 456;
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF_UTRAN(ms.ul_tbf.tfi, req_uarfcn, req_scrambling_code);
+ f_outbound_nacc_success_no_si(ms, info_ind, exp_rac_ci_query, exp_si_query, skip_final_ctrl_ack, use_old_ctrl_iface, cell_chg_notif);
+}
+
+/* Start NACC from MS side, propose an E-UTRAN cell */
+private function f_outbound_nacc_success_eutran(inout GprsMS ms, PCUIF_info_ind info_ind,
+ boolean exp_rac_ci_query := true, boolean exp_si_query := true,
+ boolean skip_final_ctrl_ack := false,
+ boolean use_old_ctrl_iface := false)
+runs on RAW_PCU_Test_CT {
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var uint16_t req_earfcn := 1234;
+ var uint9_t phys_layer_cell_id := 456;
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF_EUTRAN(ms.ul_tbf.tfi, req_earfcn, phys_layer_cell_id);
+ f_outbound_nacc_success_no_si(ms, info_ind, exp_rac_ci_query, exp_si_query, skip_final_ctrl_ack, use_old_ctrl_iface, cell_chg_notif);
+}
+
+/* Start NACC from MS side, propose a GERAN cell */
+private function f_outbound_nacc_success_geran(inout GprsMS ms, PCUIF_info_ind info_ind,
+ boolean exp_rac_ci_query := true, boolean exp_si_query := true,
+ boolean skip_final_ctrl_ack := false,
+ boolean use_old_ctrl_iface := false)
+runs on RAW_PCU_Test_CT {
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var template RlcmacDlCtrlMsg cell_chg_cont;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ if (exp_rac_ci_query == true) {
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ }
+
+ if (exp_si_query == true) {
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+ }
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a PacketCellChangeContinue, also verify that
+ * the PacketCellChangeContinue message contains the ARFCN and BSIC which was proposed in
+ * the PacketCellChangeNotification before. */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ cell_chg_cont := tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE
+ cell_chg_cont.u.cell_chg_continue.arfcn_bsic_presence := '1'B
+ cell_chg_cont.u.cell_chg_continue.arfcn := req_arfcn;
+ cell_chg_cont.u.cell_chg_continue.bsic := req_bsic;
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, cell_chg_cont))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (not skip_final_ctrl_ack and dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+}
+
+type enumerated f_TC_nacc_outbound_success_ran_type {
+ NACC_RAN_GERAN,
+ NACC_RAN_UTRAN,
+ NACC_RAN_EUTRAN
+}
+
+/* Verify PCU handles outbound Network Assisted Cell Change Cell Change (NACC, TS 44.060 sec 8.8). */
+function f_TC_nacc_outbound_success(f_TC_nacc_outbound_success_ran_type ran_type) runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ if (ran_type == NACC_RAN_GERAN) {
+ f_outbound_nacc_success_geran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+ } else if (ran_type == NACC_RAN_UTRAN) {
+ f_outbound_nacc_success_utran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+ } else if (ran_type == NACC_RAN_EUTRAN) {
+ f_outbound_nacc_success_eutran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+testcase TC_nacc_outbound_success() runs on RAW_PCU_Test_CT {
+ f_TC_nacc_outbound_success(NACC_RAN_GERAN);
+}
+
+testcase TC_nacc_outbound_success_utran() runs on RAW_PCU_Test_CT {
+ f_TC_nacc_outbound_success(NACC_RAN_UTRAN);
+}
+
+testcase TC_nacc_outbound_success_eutran() runs on RAW_PCU_Test_CT {
+ f_TC_nacc_outbound_success(NACC_RAN_EUTRAN);
+}
+
+/* Verify Pkt Cell Change Continue is retransmitted if not CTRL ACKed */
+testcase TC_nacc_outbound_success_no_ctrl_ack() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side, avoid sending final CTRL ACK */
+ f_outbound_nacc_success_geran(ms, info_ind, skip_final_ctrl_ack := true,
+ use_old_ctrl_iface := use_old_ctrl_iface);
+
+ /* Wait until we receive something non-dummy */
+ dl_block := f_skip_dummy(0, sched_fn);
+ /* Make sure it is a Pkt Cell Chg Continue (retransmitted)*/
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU handles outbound Network Assisted Cell Change Cell Change (NACC, TS 44.060 sec 8.8) twice, the second time using the caches */
+testcase TC_nacc_outbound_success_twice() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+ /* Set timeout values for caches so that entries will be in cache during second try */
+ f_pcuvty_set_neigh_caches(10, 10);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ f_outbound_nacc_success_geran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+
+ /* First NACC procedure is done, let's try to start a new one now that previous queries are cached: */
+ f_outbound_nacc_success_geran(ms, info_ind, false, false, use_old_ctrl_iface := use_old_ctrl_iface);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU handles outbound Network Assisted Cell Change Cell Change (NACC,
+ * TS 44.060 sec 8.8) twice, the second time after caches timed out
+ */
+testcase TC_nacc_outbound_success_twice_nocache() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+ /* Set timeout values for caches so that entries will be erased before the second try */
+ f_pcuvty_set_neigh_caches(1, 1);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ f_outbound_nacc_success_geran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+
+ /* CTRL client should have disconnected from us */
+ f_ipa_ctrl_wait_link_down();
+ /* wait for cache entries to time out */
+ f_sleep(2.0);
+ /* First NACC procedure is done, let's try to start a new one now that previous queries have timed out: */
+ f_outbound_nacc_success_geran(ms, info_ind, use_old_ctrl_iface := use_old_ctrl_iface);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU transmits Pkt Cell Change Continue if RAC+CI resolution fails during outbound NACC procedure */
+testcase TC_nacc_outbound_rac_ci_resolve_conn_refused() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+
+ /* In here we explicitly avoid starting osmo-bsc emulation neighbor
+ * resolution CTRL port, to trigger Conn Refused by socket:
+ * f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ */
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* Wait until we receive something non-dummy */
+ dl_block := f_skip_dummy(0, sched_fn);
+ /* Make sure it is a Pkt Cell Chg Continue */
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU transmits Pkt Cell Change Continue if RAC+CI resolution fails during outbound NACC procedure */
+testcase TC_nacc_outbound_rac_ci_resolve_timeout() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ /* we receive RAC+CI resolution request, but we never answer to it, timeout should occur */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, false, use_old_ctrl_iface);
+
+ /* Wait until we receive something non-dummy */
+ dl_block := f_skip_dummy(0, sched_fn);
+ /* Make sure it is a Pkt Cell Chg Continue */
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU transmits Pkt Cell Change Continue if RAC+CI resolution fails during outbound NACC procedure */
+testcase TC_nacc_outbound_rac_ci_resolve_fail_parse_response() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_ipa_ctrl_wait_link_up();
+ var charstring ctrl_var := "neighbor_resolve_cgi_ps_from_lac_ci." &
+ int2str(info_ind.lac) & "." &
+ int2str(info_ind.cell_id) & "." &
+ int2str(req_arfcn) & "." &
+ int2str(req_bsic);
+ /* we receive RAC+CI resolution request and we send incorrectly formated response */
+ f_ctrl_exp_get(IPA_CTRL, ctrl_var, "foobar-error");
+
+ /* Wait until we receive something non-dummy */
+ dl_block := f_skip_dummy(0, sched_fn);
+ /* Make sure it is a Pkt Cell Chg Continue */
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU transmits Pkt Cell Change Continue if SI resolution fails during outbound NACC procedure */
+testcase TC_nacc_outbound_si_resolve_timeout() runs on RAW_PCU_Test_CT {
+ var RlcmacDlBlock dl_block;
+ var PollFnCtx pollctx;
+ var uint32_t sched_fn;
+ var GprsMS ms;
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind, do_answer := false);
+ /* We never answer the RIM procude -> PCU timeouts and should send Pkt Cell Chg continue */
+
+ /* Wait until we receive something non-dummy */
+ dl_block := f_skip_dummy(0, sched_fn);
+ /* Make sure it is a Pkt Cell Chg Continue */
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notify twice (duplicate msg) while waiting for CTRL resolution */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_dup() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var charstring ctrl_var;
+ var PCUIF_Message pcu_msg;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ if (use_old_ctrl_iface) {
+ f_ctrl_rx_nacc_rac_ci_req(rx_ctrl, info_ind, req_arfcn, req_bsic);
+ } else {
+ f_pcuif_rx_nacc_rac_ci_req(pcu_msg, info_ind, req_arfcn, req_bsic);
+ }
+
+ /* Before receiving CTRL response, MS retransmits Pkt cell Chg Notif */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_sleep(0.2); /* let some time to avoid race conditons between CTRL and RLCMAC */
+
+ if (use_old_ctrl_iface) {
+ f_ctrl_tx_nacc_rac_ci_rsp(rx_ctrl);
+ } else {
+ f_pcuif_tx_nacc_rac_ci_rsp(pcu_msg);
+ }
+
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] as_outbound_nacc_rim_resolve(info_ind, do_repeat := true);
+ [use_old_ctrl_iface] IPA_CTRL.receive(tr_CtrlMsgGet(?, ctrl_var)) -> value rx_ctrl {
+ setverdict(fail, "Received unexpected CTRL resolution after duplicate Pkt Cell Change Notification:", rx_ctrl);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [not use_old_ctrl_iface] BTS.receive(tr_PCUIF_NEIGH_ADDR_REQ(0, info_ind.lac, info_ind.cell_id, req_arfcn, req_bsic)) -> value pcu_msg {
+ setverdict(fail, "Received unexpected PCUIF resolution after duplicate Pkt Cell Change Notification:", pcu_msg);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notify twice (duplicate msg) while waiting for SI resolution */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_dup2() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ as_outbound_nacc_rim_resolve(info_ind, do_answer := false);
+ /* Before receiving RIM response, MS retransmits Pkt cell Chg Notif */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_sleep(0.2); /* let some time to avoid race conditons between CTRL and RLCMAC */
+ f_outbound_nacc_rim_tx_resp(info_ind);
+ timer T := 1.0;
+ T.start;
+ alt {
+ [] RIM.receive {
+ setverdict(fail, "Received unexpected RIM message");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] T.timeout {
+ setverdict(pass);
+ }
+ }
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification twice (duplicate msg) while sending Pkt Neigh Data Change */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_dup3() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Receive first Pkt Neigh data Change, then trigger a new Pkt Cell Change Notif: */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default, single_step := true);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* It should be ignored, let's continue fetching Pkt Neigh Data Change */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default, f_ms_tx_TsTrxBtsNum(ms), 1, 16);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification twice (duplicate msg) while sending Pkt Cell Change Continue */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_dup4() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* trigger a dup Pkt Cell Change Notif, it should be ignored: */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification twice (duplicate msg) while waiting for Pkt Cell Change Continue CTRL ACK */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_dup5() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* trigger a dup Pkt Cell Change Notif, it should be ignored: */
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notify twice (different tgt cell each time)
+ * while waiting for CTRL resolution */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_twice() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var charstring ctrl_var;
+ var PCUIF_Message pcu_msg;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ if (use_old_ctrl_iface) {
+ f_ctrl_rx_nacc_rac_ci_req(rx_ctrl, info_ind, req_arfcn, req_bsic);
+ } else {
+ f_pcuif_rx_nacc_rac_ci_req(pcu_msg, info_ind, req_arfcn, req_bsic);
+ }
+ /* Before receiving CTRL response, MS retransmits Pkt cell Chg Notif with different tgt arfcn */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn + 1, req_bsic + 1);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_sleep(0.2); /* let some time to avoid race conditons between CTRL and RLCMAC */
+ if (use_old_ctrl_iface) {
+ f_ctrl_tx_nacc_rac_ci_rsp(rx_ctrl);
+ } else {
+ f_pcuif_tx_nacc_rac_ci_rsp(pcu_msg);
+ }
+ /* We should now receive a 2nd CTRL request with the new ARFCN+BSIC */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+
+ /* And finally everything continues as usual with RIN procedure */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notify twice (different tgt cell each time)
+ * while waiting for SI resolution */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_twice2() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ as_outbound_nacc_rim_resolve(info_ind, do_answer := false);
+ /* Before receiving RIM response, MS retransmits Pkt cell Chg Notif with different tgt cell: */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn + 1, req_bsic + 1);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+ f_sleep(0.2); /* let some time to avoid race conditons between CTRL and RLCMAC */
+ f_outbound_nacc_rim_tx_resp(info_ind);
+
+ /* As a result, CTRL + RIM resolution for new tgt cell should now be done: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+
+ /* And finally everything continues as usual with RIN procedure */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notify twice (different tgt cell each time)
+ * while sending Pkt Neigh Data Change */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_twice3() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Receive first Pkt Neigh data Change, then trigger a new Pkt Cell Change Notif (different ARFCN+BSIC): */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default, single_step := true);
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn + 1, req_bsic + 1);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* It should trigger RAC_CI resolution to start again: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+ /* Transmit SI back to MS */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification twice (different tgt cell) while sending Pkt Cell Change Continue */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_twice4() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* trigger a Pkt Cell Change Notif with different tgt cell */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn + 1, req_bsic + 1);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* It should trigger RAC_CI resolution to start again: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+
+ /* PCU TBF NACC state changed, so we should next receive a dummy block: */
+ f_rx_rlcmac_dl_block_exp_dummy(dl_block, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+ /* Transmit SI back to MS */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification twice (different tgt cell) while waiting for Pkt Cell Change Continue CTRL ACK*/
+testcase TC_nacc_outbound_pkt_cell_chg_notif_twice5() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ /* Announce SI back to MS, continue NACC procedure */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+
+ /* trigger a Pkt Cell Change Notif with different tgt cell */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn + 1, req_bsic + 1);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* It should trigger RAC_CI resolution to start again: */
+ /* When using new PCUIF interface for resolution, we must
+ * PCUIF.receive() here since that's the first message in the PCUIF
+ * queue that PCU will have sent. Calling other functions doing
+ * PCUIF.receive() (like f_ms_tx_ul_block() below) will make them fail
+ * due to unexpected message receive. */
+ if (not use_old_ctrl_iface) {
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+ }
+
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ /* When using CTRL interface, we must schedule the ACK before (see
+ * above) blocking here waiting for the resoltion, otherwise we'll be
+ * too late scheduling by the time the resolution is done. */
+ if (use_old_ctrl_iface) {
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn + 1, req_bsic + 1, true, use_old_ctrl_iface);
+ }
+
+ /* PCU TBF NACC state changed, so we should next receive a dummy block: */
+ f_rx_rlcmac_dl_block_exp_dummy(dl_block);
+
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+ /* Transmit SI back to MS */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test MS sending Pkt Cell Change Notification on an MS with an existing but unassigned (no TFI) DL TBF */
+testcase TC_nacc_outbound_pkt_cell_chg_notif_unassigned_dl_tbf() runs on RAW_PCU_Test_CT {
+ var PollFnCtx pollctx;
+ var GprsMS ms;
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ var template (value) RlcmacUlCtrlMsg cell_chg_notif;
+ var RlcmacDlBlock dl_block;
+ var uint32_t sched_fn, dl_fn;
+ var CtrlMessage rx_ctrl;
+ var GsmArfcn req_arfcn := 862;
+ var uint6_t req_bsic := 43;
+ var octetstring data := f_rnd_octstring(10);
+ var boolean use_old_ctrl_iface := mp_ctrl_neigh_ip != "";
+
+ if (use_old_ctrl_iface) {
+ /* Initialize osmo-bsc emulation neighbor resolution CTRL port */
+ f_ipa_ctrl_start_server(mp_ctrl_neigh_ip, mp_ctrl_neigh_port);
+ }
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+ /* Initialize GPRS MS side */
+ f_init_gprs_ms();
+ ms := g_ms[0]; /* We only use first MS in this test */
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Make sure we are not affected by full cache from previous tests */
+ f_pcuvty_flush_neigh_caches();
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* Send PACKET RESOURCE REQUEST */
+ pollctx := f_ms_establish_ul_tbf_2phase_access(ms, ts_RlcMacUlCtrl_PKT_RES_REQ(ms.tlli, ms_racap_gprs_def));
+ /* Pkt Uplink Assignment above sets poll+rrbp requesting PACKET CONTROL ACK */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), pollctx.fn, nr := pollctx.tstrxbts);
+
+ /* Start NACC from MS side */
+ cell_chg_notif := ts_RlcMacUlCtrl_PKT_CELL_CHG_NOTIF(ms.ul_tbf.tfi, req_arfcn, req_bsic);
+ f_ms_tx_ul_block(ms, ts_RLC_UL_CTRL_ACK(cell_chg_notif), 0, nr := f_ms_tx_TsTrxBtsNum(ms));
+
+ /* osmo-pcu should now ask for resolution: */
+ f_handle_nacc_rac_ci_query(info_ind, req_arfcn, req_bsic, true, use_old_ctrl_iface);
+ /* RIM procedure: */
+ as_outbound_nacc_rim_resolve(info_ind);
+
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data));
+ /* Make sure we leave some time for SGSN->PCU data to arrive to PCU */
+ f_sleep(0.1);
+ /* rx DL assignment, don't ack it yet (keep TBF in state ASSIGN): */
+ f_ms_rx_pkt_ass_pacch(ms, sched_fn, tr_RLCMAC_DL_PACKET_ASS);
+
+ /* NACC: scheduler selects tx Pkt Cell Neighbor Data. Receive first one: */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default, single_step := true);
+ /* ACK DL assignment (we do it here on purpose to test tx Pkt Neigh Cell
+ * Data with unassigned DL TBF in line above): */
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ /* Continue receiving Pkt Cell Neighbor Data */
+ f_ms_handle_pkt_neighbor_cell_data(ms, si_default, f_ms_tx_TsTrxBtsNum(ms), 1, 16);
+
+ /* Obtain a Downlink block and make sure it is a Pkt Cell Chg Continue */
+ f_rx_rlcmac_dl_block(dl_block, sched_fn);
+ if (not match(dl_block, tr_RLCMAC_DL_CTRL(?, tr_RlcMacDlCtrl_PKT_CELL_CHG_CONTINUE))) {
+ setverdict(fail, "Rx unexpected DL block: ", dl_block);
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ /* PKT CELL CHG CONTINUE ACK/NACK sets poll+rrbp requesting PACKET CONTROL ACK */
+ if (dl_block.ctrl.mac_hdr.rrbp_valid) {
+ sched_fn := f_rrbp_ack_fn(sched_fn, dl_block.ctrl.mac_hdr.rrbp);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_CTRL_ACK(ms.tlli), sched_fn);
+ }
+
+ /* Now that we confirmed the new assignment in the dl-tbf, lets receive the data and ack it */
+ f_rx_rlcmac_dl_block_exp_data(dl_block, dl_fn, data, 0);
+ f_acknackdesc_ack_block(ms.dl_tbf.acknack_desc, dl_block, '1'B);
+ f_ms_tx_ul_block(ms, ts_RLCMAC_DL_ACK_NACK(ms.dl_tbf.tfi, ms.dl_tbf.acknack_desc),
+ f_dl_block_ack_fn(dl_block, dl_fn));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+
+function f_do_inbound_nacc(template (value) RIM_Routing_Information tx_src_addr, template RIM_Routing_Information rx_dst_addr)
+runs on RAW_PCU_Test_CT
+{
+ var template (value) RAN_Information_Request_RIM_Container req_cont;
+ var template (value) PDU_BSSGP bssgp_rim_pdu;
+ var template PDU_BSSGP bssgp_rim_pdu_expect;
+ var template RAN_Information_RIM_Container rim_cont_expect;
+ var RIM_Routing_Address bts_addr;
+
+ /* Send sysinfo to the PCU */
+ var template PCUIF_Message si1_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '5506'O & si1_default, 0, 0, 0, 0, 32767);
+ BTS.send(si1_data_ind);
+ var template PCUIF_Message si3_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '4906'O & si3_default, 0, 0, 0, 0, 32767);
+ BTS.send(si3_data_ind);
+ var template PCUIF_Message si13_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '0106'O & si13_default, 0, 0, 0, 0, 32767);
+ BTS.send(si13_data_ind);
+ f_sleep(1.0);
+
+ bts_addr := valueof(t_RIM_Routing_Address_cid(mp_gb_cfg.bvc[0].cell_id));
+
+ req_cont := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(1),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_RAN_Information_Request_Application_Container_NACC(mp_gb_cfg.bvc[0].cell_id),
+ omit);
+ bssgp_rim_pdu := ts_RAN_INFORMATION_REQUEST(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, bts_addr),
+ tx_src_addr, req_cont);
+
+ rim_cont_expect := tr_RAN_Information_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(1),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ tr_RIM_Protocol_Version_Number(1),
+ tru_ApplContainer_or_ApplErrContainer_NACC(tru_ApplContainer_NACC(mp_gb_cfg.bvc[0].cell_id, false, 3, si_default)),
+ omit);
+
+ bssgp_rim_pdu_expect := tr_PDU_BSSGP_RAN_INFORMATION(rx_dst_addr,
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, bts_addr),
+ rim_cont_expect);
+ RIM.send(bssgp_rim_pdu);
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] RIM.receive(bssgp_rim_pdu_expect) { }
+ [] RIM.receive {
+ setverdict(fail, "Unexpected BSSGP RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No BSSGP RIM PDU received");
+ mtc.stop;
+ }
+ }
+}
+/* Send a RIM RAN info request to the PCU and verify the response, we expect
+ * getting the system information back which we have transfered to the PCU via
+ * PCUIF on startup. */
+testcase TC_rim_ran_info_req_single_rep() runs on RAW_PCU_Test_CT {
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+
+ var BssgpCellId src_cid := {ra_id := { lai := { mcc_mnc := '262F42'H, lac := 12345}, rac := 0 }, cell_id := 20962 };
+ var RIM_Routing_Address src_addr := valueof(t_RIM_Routing_Address_cid(src_cid));
+
+ f_do_inbound_nacc(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Same as TC_rim_ran_info_req_single_rep, but using an EUTRAN eNodeB ID as
+ * Routing information, to verify PCU handles that kind of address just fine
+ */
+testcase TC_rim_ran_info_req_single_rep_eutran() runs on RAW_PCU_Test_CT {
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename());
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+
+ var BssgpCellId src_cid := {ra_id := { lai := { mcc_mnc := '262F42'H, lac := 12345}, rac := 0 }, cell_id := 20962 };
+ var RIM_Routing_Address src_addr := valueof(t_RIM_Routing_Address_enbid(src_cid, tac := 3, gnbid := '12345678123456'O));
+
+ f_do_inbound_nacc(ts_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, src_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, src_addr));
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Same as above, but in this case we simulate the rare case in which the PCU
+ * has no system information available. We expect getting a response back but
+ * with no system information inside. */
+testcase TC_rim_ran_info_req_single_rep_no_si() runs on RAW_PCU_Test_CT {
+ var template (value) PCUIF_info_ind info_ind := ts_PCUIF_INFO_default;
+ var PCUIF_Message pcu_msg;
+ timer T := 2.0;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+
+ /* Clear sysinfo from the PCU */
+ var template PCUIF_Message si1_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '01'O, 0, 0, 0, 0, 32767);
+ BTS.send(si1_data_ind);
+ var template PCUIF_Message si3_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '03'O, 0, 0, 0, 0, 32767);
+ BTS.send(si3_data_ind);
+ var template PCUIF_Message si16_data_ind := ts_PCUIF_DATA_IND(0, 0, 0, 0, PCU_IF_SAPI_BCCH, '0b'O, 0, 0, 0, 0, 32767);
+ BTS.send(si16_data_ind);
+ f_sleep(1.0);
+
+ var RIM_Routing_Address dst_addr;
+ var RIM_Routing_Address src_addr;
+ var template (value) RAN_Information_Request_RIM_Container req_cont;
+ var template (value) PDU_BSSGP bssgp_rim_pdu;
+ var template PDU_BSSGP bssgp_rim_pdu_expect;
+ var template RAN_Information_RIM_Container rim_cont_expect;
+
+ var BssgpCellId src_cid := {ra_id := { lai := { mcc_mnc := '262F42'H, lac := 12345}, rac := 0 }, cell_id := 20962 };
+ src_addr := valueof(t_RIM_Routing_Address_cid(src_cid));
+ dst_addr := valueof(t_RIM_Routing_Address_cid(mp_gb_cfg.bvc[0].cell_id));
+
+ req_cont := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(1),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_RAN_Information_Request_Application_Container_NACC(mp_gb_cfg.bvc[0].cell_id),
+ omit);
+ bssgp_rim_pdu := ts_RAN_INFORMATION_REQUEST(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ req_cont);
+
+
+ rim_cont_expect := tr_RAN_Information_RIM_Container(tr_RIM_Application_Identity(RIM_APP_ID_NACC),
+ tr_RIM_Sequence_Number(1),
+ tr_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ tr_RIM_Protocol_Version_Number(1),
+ tru_ApplContainer_or_ApplErrContainer_NACC(tru_ApplContainer_NACC(mp_gb_cfg.bvc[0].cell_id, false, 0, ''O)),
+ omit);
+
+ bssgp_rim_pdu_expect := tr_PDU_BSSGP_RAN_INFORMATION(tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ rim_cont_expect);
+ RIM.send(bssgp_rim_pdu);
+ T.start;
+ alt {
+ [] RIM.receive(bssgp_rim_pdu_expect) { }
+ [] RIM.receive {
+ setverdict(fail, "Unexpected BSSGP RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No BSSGP RIM PDU received");
+ mtc.stop;
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Verify PCU schedule idle blocks (len=0) if no TBF attached to it. See OS#4772, SYS#4919 */
+testcase TC_pdch_energy_saving() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template (value) TsTrxBtsNum nr;
+ var RlcmacDlBlock dl_block;
+ var BTS_PDTCH_Block data_msg;
+ var integer ts;
+ timer T;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+ /* The 2 first TRX are enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (2 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 1);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Establish BSSGP connection to the PCU */
+ f_bssgp_establish();
+
+ for (ts := 0; ts < 2; ts := ts + 1) {
+ nr := ts_TsTrxBtsNum(ts_nr := 7, trx_nr := ts, bts_nr := 0, blk_nr := 0);
+
+ BTS.send(ts_PCUIF_RTS_REQ(nr.bts_nr, nr.trx_nr, nr.ts_nr,
+ sapi := PCU_IF_SAPI_PDTCH, fn := 0,
+ arfcn := f_trxnr2arfcn(valueof(nr.trx_nr)), block_nr := nr.blk_nr));
+ T.start(0.5);
+ alt {
+ [] BTS.receive(tr_PCUIF_DATA_PDTCH(nr.bts_nr,
+ tr_PCUIF_DATA(nr.trx_nr, nr.ts_nr, sapi := PCU_IF_SAPI_PDTCH),
+ omit)) -> value data_msg {
+ setverdict(pass);
+ T.stop;
+ }
+ [] as_rx_fail_dummy(nr);
+ [] BTS.receive {
+ setverdict(fail, "Unexpected block from BTS");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ [] T.timeout {
+ setverdict(fail, "Expected IDLE block from BTS");
+ f_shutdown(__BFILE__, __LINE__);
+ }
+ }
+ }
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test stats for available and occupied PDCHs */
+testcase TC_stat_pdch_avail_occ() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Only the 4 first TRX are enabled, each with 2 PDCHs. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000011'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00001100'B, 1);
+ f_PCUIF_PDCHMask_set(info_ind, '11000000'B, 2);
+ f_PCUIF_PDCHMask_set(info_ind, '00110000'B, 3);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (4 .. 7));
+
+ /* Allocate 4 GprsMS instances */
+ f_init_gprs_ms(4);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Reset stats */
+ f_statsd_reset();
+
+ /* Establish BSSGP */
+ f_bssgp_establish();
+
+ /* 8 PDCHs available, 0 occupied */
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.pdch.available", mtype := "g", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.pdch.occupied", mtype := "g", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pdch.occupied.gprs", mtype := "g", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pdch.occupied.egprs", mtype := "g", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
+ /* Establish an Uplink TBF for each GprsMS instance (3x GPRS, 1x EGPRS) */
+ f_multi_ms_bssgp_register();
+ f_ms_establish_ul_tbf(g_ms[0]);
+ f_ms_establish_ul_tbf(g_ms[1]);
+ f_ms_establish_ul_tbf(g_ms[2]);
+ f_ms_establish_ul_tbf_2phase_access(g_ms[3], ts_RlcMacUlCtrl_PKT_RES_REQ(g_ms[3].tlli, ms_racap_egprs_def));
+
+ /* 4 PDCHs occupied */
+ expect := {
+ { name := "TTCN3.bts.0.pdch.available", mtype := "g", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.pdch.occupied", mtype := "g", min := 4, max := 4 },
+ { name := "TTCN3.bts.0.pdch.occupied.gprs", mtype := "g", min := 3, max := 3 },
+ { name := "TTCN3.bts.0.pdch.occupied.egprs", mtype := "g", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+
+/* Test stats for available and occupied PDCHs, for MS which is not known by
+ * the PCU (e.g. because it was forgotten due to no interaction, and old DL
+ * data arrives from SGSN) */
+function f_tc_stat_pdch_avail_occ_ms_not_known(boolean egprs) runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind := valueof(ts_PCUIF_INFO_default);
+ const BssgpBvci bvci := mp_gb_cfg.bvc[0].bvci;
+
+ /* Ensure a deterministic slot allocation of 1 PDCH with MS class 1 */
+ const MultislotCap_GPRS_BSSGP bssgp_mscap_gprs := {
+ gprsmultislotclass := '00001'B,
+ gprsextendeddynalloccap := '0'B
+ };
+ const MultislotCap_EGPRS_BSSGP bssgp_mscap_egprs := {
+ egprsmultislotclass := '00001'B,
+ egprsextendeddynalloccap := '0'B
+ };
+ template (value) MSRadioAccessCapabilityV_BSSGP bssgp_ms_racap_gprs := {
+ valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, bssgp_mscap_gprs, omit)) };
+ template (value) MSRadioAccessCapabilityV_BSSGP bssgp_ms_racap_egprs := {
+ valueof(ts_RaCapRec_BSSGP('0001'B /* E-GSM */, bssgp_mscap_gprs, bssgp_mscap_egprs)) };
+
+ /* Initialize NS/BSSGP side */
+ f_init_bssgp();
+
+ /* Only the 4 first TRX are enabled, each with 2 PDCHs. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000011'B, 0);
+ f_PCUIF_PDCHMask_set(info_ind, '00001100'B, 1);
+ f_PCUIF_PDCHMask_set(info_ind, '11000000'B, 2);
+ f_PCUIF_PDCHMask_set(info_ind, '00110000'B, 3);
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (4 .. 7));
+
+ /* Allocate 1 GprsMS instance */
+ f_init_gprs_ms(1);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+
+ /* Reset stats */
+ f_statsd_reset();
+
+ /* Establish BSSGP */
+ f_bssgp_establish();
+
+ /* 8 PDCHs available, 0 occupied */
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.pdch.available", mtype := "g", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.pdch.occupied", mtype := "g", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pdch.occupied.gprs", mtype := "g", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pdch.occupied.egprs", mtype := "g", min := 0, max := 0 }
+ };
+ f_statsd_expect(expect);
+
+ var GprsMS ms := g_ms[0]; /* We only use first MS in this test */
+ f_bssgp_client_llgmm_assign(TLLI_UNUSED, ms.tlli);
+
+ /* SGSN sends some DL data, PCU will page on CCCH (PCH) */
+ var octetstring data := f_rnd_octstring(1400);
+ if (egprs) {
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, bssgp_ms_racap_egprs, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ } else {
+ BSSGP[0].send(ts_BSSGP_DL_UD(ms.tlli, data, bssgp_ms_racap_gprs, imsi := ts_BSSGP_IMSI(ms.imsi)));
+ }
+ f_ms_exp_dl_tbf_ass_ccch(ms);
+
+ /* Wait timer X2002 and DL block is available after CCCH IMM ASS */
+ f_sleep(X2002);
+
+ /* 1 PDCH occupied */
+ if (egprs) {
+ expect := {
+ { name := "TTCN3.bts.0.pdch.available", mtype := "g", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.pdch.occupied", mtype := "g", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.pdch.occupied.gprs", mtype := "g", min := 0, max := 0 },
+ { name := "TTCN3.bts.0.pdch.occupied.egprs", mtype := "g", min := 1, max := 1 }
+ };
+ } else {
+ expect := {
+ { name := "TTCN3.bts.0.pdch.available", mtype := "g", min := 8, max := 8 },
+ { name := "TTCN3.bts.0.pdch.occupied", mtype := "g", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.pdch.occupied.gprs", mtype := "g", min := 1, max := 1 },
+ { name := "TTCN3.bts.0.pdch.occupied.egprs", mtype := "g", min := 0, max := 0 }
+ };
+ }
+ f_statsd_expect(expect);
+
+ /* Clean up */
+ f_shutdown(__BFILE__, __LINE__, final := true);
+}
+testcase TC_stat_pdch_avail_occ_ms_not_known_gprs() runs on RAW_PCU_Test_CT {
+ f_tc_stat_pdch_avail_occ_ms_not_known(false);
+}
+testcase TC_stat_pdch_avail_occ_ms_not_known_egprs() runs on RAW_PCU_Test_CT {
+ f_tc_stat_pdch_avail_occ_ms_not_known(true);
+}
+
+/* Make sure that bts.0.pdch.all_allocated is set when we allocate all resources */
+testcase TC_ratectr_all_available_allocated() runs on RAW_PCU_Test_CT {
+ var PCUIF_info_ind info_ind;
+ var template IARRestOctets rest;
+ var BIT11 ra11;
+
+ info_ind := valueof(ts_PCUIF_INFO_default);
+
+ /* Only the first TRX is enabled. */
+ f_PCUIF_PDCHMask_set(info_ind, '00000000'B, (1 .. 7));
+ f_PCUIF_PDCHMask_set(info_ind, '00000001'B, 0);
+
+ /* Initialize the PCU interface abstraction */
+ f_init_raw(testcasename(), info_ind);
+ f_statsd_reset();
+
+ var EGPRSPktChRequest req := {
+ one_phase := {
+ tag := '0'B,
+ multislot_class := '10101'B,
+ priority := '01'B,
+ random_bits := '101'B
+ }
+ };
+
+ /* We send 7 requests, the IUT gives us all available USFs (0..6) */
+ for (var integer i := 0; i < 7; i := i + 1) {
+ req.one_phase.random_bits := int2bit(f_rnd_int(8), 3);
+ f_TC_egprs_pkt_chan_req(req, tr_IMM_TBF_ASS);
+ }
+
+ ra11 := enc_EGPRSPktChRequest2bits(req);
+ rest := tr_IARRestOctets({ *, tr_ExtRAOpt(substr(ra11, 6, 5)), * });
+
+ /* At this point, the IUT should run out of free USFs */
f_TC_egprs_pkt_chan_req_reject(ra11, 1870, rest);
+ /* bts.0.pdch.all_allocated is updated once per second, wait some time to make sure it was updated. */
+ f_sleep(2.0);
+ var StatsDExpects expect := {
+ { name := "TTCN3.bts.0.pdch.all_allocated", mtype := "c", min := 1, max := 1 }
+ };
+ f_statsd_expect(expect);
+
f_shutdown(__BFILE__, __LINE__, final := true);
}
control {
execute( TC_pcuif_suspend() );
+ execute( TC_pcuif_suspend_active_tbf() );
execute( TC_ta_ptcch_idle() );
execute( TC_ta_rach_imm_ass() );
+ execute( TC_ta_ul_ack_nack_first_block() );
execute( TC_ta_idle_dl_tbf_ass() );
execute( TC_ta_ptcch_ul_multi_tbf() );
execute( TC_cs_lqual_ul_tbf() );
execute( TC_cs_initial_ul() );
execute( TC_cs_max_ul() );
- execute( TC_t3169() );
+ execute( TC_cs_initial_dl() );
+ execute( TC_cs_max_dl() );
+ execute( TC_dl_cs1_to_cs4() );
+ execute( TC_mcs_initial_ul() );
+ execute( TC_mcs_max_ul() );
+ execute( TC_mcs_initial_dl() );
+ execute( TC_mcs_max_dl() );
+ execute( TC_t3141() );
+ execute( TC_n3101_max_t3169() );
+ execute( TC_n3103_max_t3169() );
+ execute( TC_x2031_t3191() );
+ execute( TC_zero_x2031_t3191() );
execute( TC_t3193() );
+ execute( TC_n3105_max_t3195() );
+ execute( TC_t3172_wait_ind_size0() );
+ execute( TC_t3172_wait_ind_size1() );
execute( TC_countdown_procedure() );
execute( TC_ul_all_sizes() );
execute( TC_ul_data_toolong_fills_padding() );
@@ -2092,6 +7484,9 @@ control {
execute( TC_imm_ass_dl_block_retrans() );
execute( TC_dl_flow_more_blocks() );
execute( TC_ul_flow_multiple_llc_blocks() );
+ execute( TC_dl_no_ack_retrans_imm_ass() );
+ execute( TC_dl_llc_sapi_priority() );
+ execute( TC_ul_tbf_bsn_wraparound_gprs());
execute( TC_paging_cs_from_bts() );
execute( TC_paging_cs_from_sgsn_sign_ptmsi() );
execute( TC_paging_cs_from_sgsn_sign() );
@@ -2099,6 +7494,19 @@ control {
execute( TC_paging_ps_from_sgsn_sign_ptmsi() );
execute( TC_paging_ps_from_sgsn_sign() );
execute( TC_paging_ps_from_sgsn_ptp() );
+ execute( TC_paging_pch_timeout() );
+
+ execute( TC_paging_cs_multi_ms_imsi_tmsi() );
+ execute( TC_paging_cs_multi_ms_imsi() );
+ execute( TC_paging_cs_multi_ms_tmsi() );
+ execute( TC_bssgp_dl_unitdata_with_valid_imsi() );
+ execute( TC_bssgp_dl_unitdata_with_invalid_imsi() );
+ execute( TC_dl_gprs_data_no_llc_ui_dummy() );
+ execute( TC_dl_egprs_data_no_llc_ui_dummy() );
+
+ execute( TC_ul_tbf_finished_pkt_dl_ass_pch() );
+ execute( TC_ul_tbf_1phase_while_dl_ass_pch() );
+ execute( TC_ul_tbf_2phase_while_dl_ass_pch() );
/* EGPRS specific test cases */
execute( TC_egprs_pkt_chan_req_signalling() );
@@ -2109,11 +7517,61 @@ control {
execute( TC_egprs_pkt_chan_req_reject_exhaustion() );
execute( TC_mo_ping_pong_with_ul_racap_egprs_only() );
-}
-
+ /* Immediate Assignment on AGCH/PCH */
+ execute( TC_pcuif_fh_imm_ass_ul_egprs() );
+ execute( TC_pcuif_fh_imm_ass_ul() );
+ execute( TC_pcuif_fh_imm_ass_dl() );
+ /* Packet Uplink/Downlink Assignment on PACCH */
+ execute( TC_pcuif_fh_pkt_ass_ul() );
+ execute( TC_pcuif_fh_pkt_ass_dl() );
+ execute( TC_multitrx_multims_alloc() );
+ execute( TC_dl_multislot_tbf_ms_class_from_sgsn() );
+ execute( TC_dl_multislot_tbf_ms_class_unknown() );
+ execute( TC_dl_multislot_tbf_ms_class_from_2phase() );
+ execute( TC_ul_multislot_tbf_ms_class_from_2phase() );
+ execute( TC_ul_tbf_reestablish_with_pkt_resource_req() );
+ execute( TC_ul_tbf_reestablish_with_pkt_resource_req_t3168() );
+ execute( TC_ul_tbf_reestablish_with_pkt_dl_ack_nack() );
+ execute( TC_ul_tbf_reestablish_with_pkt_dl_ack_nack_egprs() );
+
+ execute( TC_multiplex_dl_gprs_egprs() );
+
+ execute( TC_pcuif_info_ind_subsequent() );
+ execute( TC_nacc_outbound_success() );
+ execute( TC_nacc_outbound_success_utran() );
+ execute( TC_nacc_outbound_success_eutran() );
+ execute( TC_nacc_outbound_success_no_ctrl_ack() );
+ execute( TC_nacc_outbound_success_twice() );
+ execute( TC_nacc_outbound_success_twice_nocache() );
+ execute( TC_nacc_outbound_rac_ci_resolve_timeout() );
+ execute( TC_nacc_outbound_si_resolve_timeout() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_dup() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_dup2() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_dup3() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_dup4() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_dup5() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_twice() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_twice2() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_twice3() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_twice4() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_twice5() );
+ execute( TC_nacc_outbound_pkt_cell_chg_notif_unassigned_dl_tbf() );
+ if (mp_ctrl_neigh_ip != "") { /* PCU using old CTRL neigh addr resolution iface */
+ execute( TC_nacc_outbound_rac_ci_resolve_conn_refused() );
+ execute( TC_nacc_outbound_rac_ci_resolve_fail_parse_response() );
+ }
+ execute( TC_rim_ran_info_req_single_rep() );
+ execute( TC_rim_ran_info_req_single_rep_eutran() );
+ execute( TC_rim_ran_info_req_single_rep_no_si() );
+ execute (TC_pdch_energy_saving() );
+ execute( TC_stat_pdch_avail_occ() );
+ execute( TC_stat_pdch_avail_occ_ms_not_known_gprs() );
+ execute( TC_stat_pdch_avail_occ_ms_not_known_egprs() );
+ execute( TC_ratectr_all_available_allocated() );
+}
}
diff --git a/pcu/PCU_Tests_NS.ttcn b/pcu/PCU_Tests_NS.ttcn
index b1c8f381..eea8d3f5 100644
--- a/pcu/PCU_Tests_NS.ttcn
+++ b/pcu/PCU_Tests_NS.ttcn
@@ -12,43 +12,36 @@ module PCU_Tests_NS {
import from General_Types all;
import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
import from PCU_Tests all;
import from SGSN_Components all;
import from Osmocom_Gb_Types all;
-import from NS_CodecPort all;
import from NS_Types all;
import from BSSGP_Types all;
import from UD_Types all;
-import from NS_CodecPort all;
-import from NS_CodecPort_CtrlFunct all;
import from NS_Emulation all;
import from Native_Functions all;
import from IPL4asp_Types all;
import from PCUIF_Types all;
import from PCUIF_CodecPort all;
-
-type component RAW_NS_CT {
- /* UDP port towards the bottom (IUT) */
- port NS_CODEC_PT NSCP[4];
- var ConnectionId g_ns_conn_id[4] := {-1, -1, -1, -1};
- var NSConfiguration g_nsconfig[4];
- timer g_T_guard;
-}
+import from RAW_NS all;
type component RAW_PCU_CT {
/* PCUIF (we emulate the BTS part) */
port PCUIF_CODEC_PT PCU;
var ConnectionId g_pcu_conn_id := -1;
+ /* VTY connection to the PCU */
+ port TELNETasp_PT PCUVTY;
}
type component RAW_Test_CT extends RAW_NS_CT, RAW_PCU_CT {
}
-private altstep as_Tguard() runs on RAW_NS_CT {
- [] g_T_guard.timeout {
- setverdict(fail, "Timeout of T_guard");
- mtc.stop;
- }
+function f_init_vty(charstring id) runs on RAW_PCU_CT {
+ map(self:PCUVTY, system:PCUVTY);
+ f_vty_set_prompts(PCUVTY);
+ f_vty_transceive(PCUVTY, "enable");
}
function f_init_pcuif() runs on RAW_PCU_CT {
@@ -64,7 +57,7 @@ function f_init_pcuif() runs on RAW_PCU_CT {
/* Wait for PCU_VERSION and return INFO_IND */
PCU.receive(t_SD_PCUIF(g_pcu_conn_id, tr_PCUIF_TXT_IND(0, PCU_VERSION, ?)));
- /* FIXME: make sure to use parameters from mp_gb_cfg.cell_id in the PCU INFO IND */
+ /* FIXME: make sure to use parameters from mp_gb_cfg.bvc[0].cell_id in the PCU INFO IND */
var template PCUIF_Message info_ind_msg := ts_PCUIF_INFO_IND(0, info_ind);
PCU.send(t_SD_PCUIF(g_pcu_conn_id, info_ind_msg));
}
@@ -73,80 +66,13 @@ function f_pcuif_tx(template (value) PCUIF_Message msg) runs on RAW_PCU_CT {
PCU.send(t_SD_PCUIF(g_pcu_conn_id, msg));
}
-function f_init_ns_codec(integer idx := 0, float guard_secs := 60.0) runs on RAW_NS_CT {
- var Result res;
-
- if (not g_T_guard.running) {
- g_T_guard.start(guard_secs);
- activate(as_Tguard());
- }
-
- if (not isbound(g_nsconfig) or not isbound(g_nsconfig[idx])) {
- /* copy most parts from mp_nsconfig */
- g_nsconfig[idx] := mp_nsconfig;
- /* adjust those parts different for each NS-VC */
- g_nsconfig[idx].nsvci := mp_nsconfig.nsvci + idx;
- g_nsconfig[idx].local_udp_port := mp_nsconfig.local_udp_port + idx;
- }
-
- map(self:NSCP[idx], system:NSCP);
- /* Connect the UDP socket */
- log("connecting NSCP[", idx, "] to ", g_nsconfig[idx]);
- res := f_IPL4_connect(NSCP[idx], g_nsconfig[idx].remote_ip, g_nsconfig[idx].remote_udp_port,
- g_nsconfig[idx].local_ip, g_nsconfig[idx].local_udp_port, 0, { udp := {}});
- if (not ispresent(res.connId)) {
- setverdict(fail, "Could not connect NS UDP socket, check your configuration ", g_nsconfig[idx]);
- mtc.stop;
- }
- g_ns_conn_id[idx] := res.connId;
-
-}
-
-function f_ns_exp(template PDU_NS exp_rx, integer idx := 0) runs on RAW_NS_CT return PDU_NS {
- var NS_RecvFrom nrf;
- log("f_ns_exp() expecting ", exp_rx);
- alt {
- [] NSCP[idx].receive(t_NS_RecvFrom(exp_rx)) -> value nrf { }
- [] NSCP[idx].receive {
- setverdict(fail, "Received unexpected NS: ", nrf);
- mtc.stop;
- }
- }
- return nrf.msg;
-}
-
-/* perform outbound NS-ALIVE procedure */
-function f_outgoing_ns_alive(integer idx := 0) runs on RAW_NS_CT {
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
- alt {
- [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK));
- [] NSCP[idx].receive { repeat; }
- }
-}
-
-/* perform outbound NS-ALIVE procedure */
-function f_outgoing_ns_alive_no_ack(integer idx := 0, float tout := 10.0) runs on RAW_NS_CT {
- timer T := tout;
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE));
- T.start;
- alt {
- [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE_ACK)) {
- setverdict(fail, "Received unexpected NS-ALIVE ACK");
- }
- [] NSCP[idx].receive { repeat; }
- [] T.timeout {
- setverdict(pass);
- }
- }
-}
-
/* ensure no matching message is received within 'tout' */
function f_ensure_no_ns(template PDU_NS ns := ?, integer idx := 0, float tout := 3.0)
runs on RAW_Test_CT {
timer T := tout;
T.start;
alt {
- [] NSCP[idx].receive(t_NS_RecvFrom(ns)) {
+ [] NSCP[idx].receive(ns) {
setverdict(fail, "NS-ALIVE from unconfigured (possibly initial) endpoint");
}
[] T.timeout {
@@ -155,215 +81,120 @@ runs on RAW_Test_CT {
}
}
-/* perform outbound NS-BLOCK procedure */
-function f_outgoing_ns_block(NsCause cause, integer idx := 0) runs on RAW_NS_CT {
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_BLOCK(cause, g_nsconfig[idx].nsvci)));
- alt {
- [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_BLOCK_ACK(g_nsconfig[idx].nsvci)));
- [] NSCP[idx].receive { repeat; }
- }
-}
-
-/* receive NS-ALIVE and ACK it */
-altstep as_rx_alive_tx_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_ALIVE)) {
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_ALIVE_ACK));
- if (not oneshot) { repeat; }
- }
-}
-
-/* Transmit BSSGP RESET for given BVCI and expect ACK */
-function f_tx_bvc_reset_rx_ack(BssgpBvci bvci, integer idx := 0, boolean exp_ack := true)
-runs on RAW_NS_CT {
- var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS, bvci,
- mp_gb_cfg.cell_id));
- timer T := 5.0;
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
- T.start;
- alt {
- [exp_ack] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
- decmatch tr_BVC_RESET_ACK(bvci, ?)))) {
- setverdict(pass);
- }
- [exp_ack] T.timeout {
- setverdict(fail, "No response to BVC-RESET");
- }
- [not exp_ack] T.timeout {
- setverdict(pass);
- }
- [] NSCP[idx].receive { repeat; }
- }
-}
-
-/* Receive a BSSGP RESET for given BVCI and ACK it */
-altstep as_rx_bvc_reset_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- var NS_RecvFrom ns_rf;
- /* FIXME: nail down received cell_id in match */
- [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
- decmatch tr_BVC_RESET(?, bvci, ?))))
- -> value ns_rf {
- var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
- var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET_ACK(bvci, mp_gb_cfg.cell_id));
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
- if (not oneshot) { repeat; }
- }
-}
-
-
-/* Receive a BSSGP UNBLOCK for given BVCI and ACK it */
-altstep as_rx_bvc_unblock_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- var NS_RecvFrom ns_rf;
- [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, 0,
- decmatch t_BVC_UNBLOCK(bvci))))
- -> value ns_rf {
- var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
- var PDU_BSSGP bssgp_tx := valueof(t_BVC_UNBLOCK_ACK(bvci));
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx))));
- if (not oneshot) { repeat; }
- }
-}
-
-/* Receive a BSSGP FLOW-CONTROL-BVC and ACK it */
-altstep as_rx_bvc_fc_tx_ack(BssgpBvci bvci, boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- var NS_RecvFrom ns_rf;
- [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_UNITDATA(t_SduCtrlB, bvci,
- decmatch tr_BVC_FC_BVC)))
- -> value ns_rf {
- var PDU_BSSGP bssgp_rx := dec_PDU_BSSGP(ns_rf.msg.pDU_NS_Unitdata.nS_SDU);
- var OCT1 tag := bssgp_rx.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
- var PDU_BSSGP bssgp_tx := valueof(t_BVC_FC_BVC_ACK(tag));
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_UNITDATA(t_SduCtrlB, bvci, enc_PDU_BSSGP(bssgp_tx))));
- if (not oneshot) { repeat; }
- }
-}
-
-/**********************************************************************************
- * Classic Gb/IP bring-up test cases using NS-{RESET,BLOCK,UNBLOCK} and no IP-SNS *
- **********************************************************************************/
-
-/* Receive a NS-RESET and ACK it */
-private altstep as_rx_ns_reset_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- var NS_RecvFrom ns_rf;
- [] NSCP[idx].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION, g_nsconfig[idx].nsvci,
- g_nsconfig[idx].nsei))) -> value ns_rf {
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_NS_RESET_ACK(g_nsconfig[idx].nsvci,
- g_nsconfig[idx].nsei)));
- if (not oneshot) { repeat; }
- }
-}
-/* Receive a NS-UNBLOCK and ACK it */
-private altstep as_rx_ns_unblock_ack(boolean oneshot := false, integer idx := 0) runs on RAW_NS_CT {
- var NS_RecvFrom ns_rf;
- [] NSCP[idx].receive(t_NS_RecvFrom(t_NS_UNBLOCK)) -> value ns_rf {
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], t_NS_UNBLOCK_ACK));
- if (not oneshot) { repeat; }
- }
-}
-
/* test the NS-RESET procedure */
testcase TC_ns_reset() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
setverdict(pass);
+ f_clean_ns_codec();
}
/* ensure NS-RESET are re-transmitted */
testcase TC_ns_reset_retrans() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
var integer i;
for (i := 0; i < 3; i := i+1) {
- NSCP[0].receive(t_NS_RecvFrom(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
- g_nsconfig[0].nsvci, g_nsconfig[0].nsei)));
+ NSCP[0].receive(tr_NS_RESET(NS_CAUSE_OM_INTERVENTION,
+ g_nsconfig.nsvc[0].nsvci, g_nsconfig.nsei));
}
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
setverdict(pass);
+ f_clean_ns_codec();
}
/* test the inbound NS-ALIVE procedure after NS-RESET */
testcase TC_ns_alive() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
+ alt {
/* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
- as_rx_alive_tx_ack(oneshot := true);
- setverdict(pass);
+ [] NSCP[0].receive(t_NS_ALIVE) { setverdict(pass); };
+ [] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
+ }
+ f_clean_ns_codec();
}
/* Test for NS-RESET after NS-ALIVE timeout */
testcase TC_ns_alive_timeout_reset() runs on RAW_Test_CT {
- f_init_ns_codec(guard_secs := 100.0);
+ f_init_ns_codec(mp_nsconfig, guard_secs := 100.0);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
/* wait for at least one NS-ALIVE */
- NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE));
+ alt {
+ [] as_rx_alive_tx_ack(oneshot := true) { };
+ [] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
+ }
/* wait for NS-RESET to re-appear, ignoring any NS-ALIVE until then */
alt {
[] as_rx_ns_reset_ack(oneshot := true) { setverdict(pass); }
- [] NSCP[0].receive(t_NS_RecvFrom(t_NS_ALIVE)) { repeat; }
+ [] NSCP[0].receive(t_NS_ALIVE) { repeat; }
+ [] NSCP[0].receive(t_NS_UNBLOCK) { repeat; }
}
+
+ f_clean_ns_codec();
}
/* test for NS-RESET/NS-ALIVE/NS-UNBLOCK */
testcase TC_ns_unblock() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
- /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
- as_rx_alive_tx_ack(oneshot := true);
+ /* keep it alive */
activate(as_rx_alive_tx_ack());
as_rx_ns_unblock_ack(oneshot := true);
setverdict(pass);
+ f_clean_ns_codec();
}
/* test for NS-UNBLOCK re-transmissions */
testcase TC_ns_unblock_retrans() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
- /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
- as_rx_alive_tx_ack(oneshot := true);
+ /* keep it alive */
activate(as_rx_alive_tx_ack());
/* wait for first NS-UNBLOCK, don't respond */
- NSCP[0].receive(t_NS_RecvFrom(t_NS_UNBLOCK));
+ NSCP[0].receive(t_NS_UNBLOCK);
/* wait for re-transmission of NS-UNBLOCK */
as_rx_ns_unblock_ack(oneshot := true);
setverdict(pass);
+ f_clean_ns_codec();
}
/* full bring-up of the Gb link for NS and BSSGP layer up to BVC-FC */
testcase TC_ns_full_bringup() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
- /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
- as_rx_alive_tx_ack(oneshot := true);
+ /* keep it alive */
activate(as_rx_alive_tx_ack());
as_rx_ns_unblock_ack(oneshot := true);
@@ -371,26 +202,26 @@ testcase TC_ns_full_bringup() runs on RAW_Test_CT {
f_outgoing_ns_alive();
/* Expect BVC-RESET for signaling (0) and ptp BVCI */
- as_rx_bvc_reset_tx_ack(0, oneshot := true);
- as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
- as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+ as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true);
+ as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true);
+ as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
/* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
- as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
- activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
+ as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
+ activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci));
setverdict(pass);
+ f_clean_ns_codec();
}
/* test outbound (SGSN-originated) NS-BLOCK procedure */
testcase TC_ns_so_block() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
/* Expect inbound NS-RESET procedure */
as_rx_ns_reset_ack(oneshot := true);
- /* wait for one ALIVE cycle, then ACK any further ALIVE in the background */
- as_rx_alive_tx_ack(oneshot := true);
+ /* keep it alive */
activate(as_rx_alive_tx_ack());
as_rx_ns_unblock_ack(oneshot := true);
@@ -399,6 +230,7 @@ testcase TC_ns_so_block() runs on RAW_Test_CT {
f_outgoing_ns_block(NS_CAUSE_EQUIPMENT_FAILURE);
setverdict(pass);
+ f_clean_ns_codec();
}
diff --git a/pcu/PCU_Tests_SNS.cfg b/pcu/PCU_Tests_SNS.cfg
index 022f91c5..bd0875bb 100644
--- a/pcu/PCU_Tests_SNS.cfg
+++ b/pcu/PCU_Tests_SNS.cfg
@@ -8,13 +8,53 @@
[MODULE_PARAMETERS]
SGSN_Components.mp_nsconfig := {
- local_ip := "127.0.0.1",
- local_udp_port := 23000,
- remote_ip := "127.0.0.1",
- remote_udp_port := 22000,
- nsvci := 1234,
- nsei := 1234
+ nsei := 1234,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23001,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.1",
+ local_udp_port := 23002,
+ remote_ip := "127.0.0.1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ }
+ }
}
+PCUIF_Types.mp_pcuif_version := 12
[TESTPORT_PARAMETERS]
diff --git a/pcu/PCU_Tests_SNS.ttcn b/pcu/PCU_Tests_SNS.ttcn
index fc98979d..b90fe37e 100644
--- a/pcu/PCU_Tests_SNS.ttcn
+++ b/pcu/PCU_Tests_SNS.ttcn
@@ -11,169 +11,68 @@ module PCU_Tests_SNS {
*/
import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
import from PCU_Tests_NS all;
import from SGSN_Components all;
import from Osmocom_Gb_Types all;
-import from NS_CodecPort all;
+import from NS_Emulation all;
import from NS_Types all;
+import from RAW_NS all;
+import from BSSGP_Types all;
/**********************************************************************************
* Modern Gb/IP bring-up test cases using IP Sub-Network Service (SNS)
**********************************************************************************/
-/* perform inbound SNS-SIZE procedure */
-function f_incoming_sns_size(template (omit) NsCause cause := omit, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_incoming_sns_size(idx=", idx, ")");
- var PDU_NS rx;
- /* expect one single SNS-SIZE with RESET flag; one remote v4 EP; no v6 EP */
- rx := f_ns_exp(tr_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 8,
- num_v4 := 4, num_v6 := omit), idx);
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause)));
-}
-
-/* perform outbound SNS-SIZE procedure */
-function f_outgoing_sns_size(template (omit) NsCause cause := omit, integer idx:= 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_size(idx=", idx, ")");
- var PDU_NS rx;
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_SIZE(g_nsconfig[idx].nsei, rst_flag := true, max_nsvcs := 1,
- num_v4 := 1, num_v6 := omit)
- ));
- /* expect one single SNS-SIZE with RESET flag; one remote v4 EP; no v6 EP */
- rx := f_ns_exp(tr_SNS_SIZE_ACK(g_nsconfig[idx].nsei, cause), idx);
-}
-
-/* perform inbound SNS-CONFIG procedure */
-function f_incoming_sns_config(template (omit) NsCause cause := omit, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_incoming_sns_config(idx=", idx, ")");
- var PDU_NS rx;
- var template IP4_Elements v4_elem := { tr_SNS_IPv4(mp_nsconfig.remote_ip,
- mp_nsconfig.remote_udp_port) };
- rx := f_ns_exp(tr_SNS_CONFIG(g_nsconfig[idx].nsei, end_flag := true, v4 := v4_elem), idx);
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause)));
-}
-
-/* perform outbound SNS-CONFIG procedure */
-function f_outgoing_sns_config(template (omit) NsCause cause := omit, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_config(idx=", idx, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx].local_ip,
- g_nsconfig[idx].local_udp_port) }
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
- rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
-}
-
-/* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
-function f_outgoing_sns_config_1c1u(template (omit) NsCause cause := omit, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_config_1c1u(idx=", idx, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[0].local_ip,
- g_nsconfig[0].local_udp_port, 1, 0),
- ts_SNS_IPv4(g_nsconfig[1].local_ip,
- g_nsconfig[1].local_udp_port, 0, 1) };
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
- rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
-}
-
-/* perform outbound SNS-CONFIG procedure (separate endpoints: 1 for control, 1 for user */
-function f_outgoing_sns_config_1c1u_separate(template (omit) NsCause cause := omit, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_config_1c1u_separate(idx=", idx, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[1].local_ip,
- g_nsconfig[1].local_udp_port, 1, 0),
- ts_SNS_IPv4(g_nsconfig[2].local_ip,
- g_nsconfig[2].local_udp_port, 0, 1) };
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CONFIG(g_nsconfig[idx].nsei, true, v4)));
- rx := f_ns_exp(tr_SNS_CONFIG_ACK(g_nsconfig[idx].nsei, cause), idx);
-}
-
-function f_outgoing_sns_add(integer idx_add, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_add(idx_add=", idx_add, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_add].local_ip,
- g_nsconfig[idx_add].local_udp_port,
- w_sig, w_user) };
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_ADD(g_nsconfig[idx].nsei, 23, v4)));
- rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 23, omit, v4));
-}
-
-function f_outgoing_sns_del(integer idx_del, uint8_t w_sig := 1, uint8_t w_user := 1, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_del(idx_del=", idx_del, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_del].local_ip,
- g_nsconfig[idx_del].local_udp_port,
- w_sig, w_user) };
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_DEL(g_nsconfig[idx].nsei, 24, omit, v4)));
- rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 24, omit, v4));
-}
-
-function f_outgoing_sns_chg_weight(integer idx_chg, uint8_t w_sig, uint8_t w_user, integer idx := 0)
-runs on RAW_NS_CT {
- log("f_outgoing_sns_chg_weight(idx_chg=", idx_chg, ")");
- var PDU_NS rx;
- var template (omit) IP4_Elements v4 := { ts_SNS_IPv4(g_nsconfig[idx_chg].local_ip,
- g_nsconfig[idx_chg].local_udp_port,
- w_sig, w_user) };
- NSCP[idx].send(t_NS_Send(g_ns_conn_id[idx], ts_SNS_CHG_WEIGHT(g_nsconfig[idx].nsei, 25, v4)));
- rx := f_ns_exp(tr_SNS_ACK(g_nsconfig[idx].nsei, 25, omit, v4));
-}
-
-
-
-
-
/* PCU-originated SNS-SIZE: successful case */
testcase TC_sns_po_size_success() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
f_incoming_sns_size();
f_sleep(1.0);
setverdict(pass);
+ f_clean_ns_codec();
}
/* PCU-originated SNS-SIZE: NACK from our side */
testcase TC_sns_po_size_nack() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
- f_incoming_sns_size(NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED);
+ f_incoming_sns_size(NS_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
/* FIXME: ensure we don't get a SNS-CONFIG */
/* FIXME: ensure we get re-transmitted SNS-SIZE attempts */
f_sleep(10.0);
setverdict(pass);
+ f_clean_ns_codec();
}
/* PCU-originated SNS-CONFIG: successful case */
testcase TC_sns_po_config_success() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
f_incoming_sns_size();
f_incoming_sns_config();
f_sleep(1.0);
setverdict(pass);
+ f_clean_ns_codec();
}
/* PCU-originated SNS-CONFIG: successful case */
testcase TC_sns_po_config_nack() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
f_incoming_sns_size();
- f_incoming_sns_config(NS_CAUSE_PROTOCOL_ERROR_UNSPEIFIED);
+ f_incoming_sns_config(NS_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
/* FIXME: ensure we get re-transmitted SNS-CONFIG attempts */
f_sleep(10.0);
setverdict(pass);
+ f_clean_ns_codec();
}
/* SGSN-originated SNS-SIZE: successful case */
testcase TC_sns_so_config_success() runs on RAW_Test_CT {
- f_init_ns_codec();
+ f_init_ns_codec(mp_nsconfig);
f_init_pcuif();
f_incoming_sns_size();
f_incoming_sns_config();
@@ -186,20 +85,21 @@ testcase TC_sns_so_config_success() runs on RAW_Test_CT {
f_outgoing_ns_alive();
/* Expect BVC-RESET for signaling (0) and ptp BVCI */
- as_rx_bvc_reset_tx_ack(0, oneshot := true);
- as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
- as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+ as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true);
+ as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true);
+ as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
/* wait for one FLOW-CONTROL BVC and then ACK any further in the future */
- as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true);
- activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci));
+ as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
+ activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci));
setverdict(pass);
+ f_clean_ns_codec();
}
private function f_sns_bringup_1c1u(boolean sgsn_originated_reset := false) runs on RAW_Test_CT {
/* Activate two NS codec ports */
- f_init_ns_codec();
- f_init_ns_codec(1);
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
f_init_pcuif();
/* Perform Size + BSS-originated config */
f_incoming_sns_size();
@@ -219,33 +119,44 @@ private function f_sns_bringup_1c1u(boolean sgsn_originated_reset := false) runs
f_outgoing_ns_alive(1);
if (sgsn_originated_reset) {
- f_tx_bvc_reset_rx_ack(0);
- f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci);
+ /* Expect BVC-RESET, but ignore it to prevent a race condition of BVC RESETs */
+ var template PDU_NS pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, 0, omit));
+ f_ns_exp(pdu);
+ /* SGSN originated BVC-RESET on an uninitialized signalling BVC */
+ f_tx_bvc_reset_rx_ack(0, omit, omit);
+
+ /* Expect BVC-RESET PTP BVC, but ignore it to prevent a race condition of BVC RESETs */
+ pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id));
+ f_ns_exp(pdu);
+ /* SGSN originated BVC-RESET on an uninitialized PTP BVC */
+ f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id);
} else {
- /* Expect BVC-RESET for signaling (0) and ptp BVCI */
- as_rx_bvc_reset_tx_ack(0, oneshot := true);
- as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+ /* Expect BVC-RESET for signaling BVCI=0 */
+ as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true);
+ /* Expect BVC-RESET from the PCU on PTP BVC */
+ as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true);
}
/* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==0) */
- as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true);
+ as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true);
/* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow
* control happens on the p-t-p BVCI and hence on index 1 */
- as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 1);
- activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, idx := 1));
+ as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1);
+ activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 1));
}
/* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only */
testcase TC_sns_1c1u() runs on RAW_Test_CT {
f_sns_bringup_1c1u();
setverdict(pass);
+ f_clean_ns_codec();
}
private function f_sns_bringup_1c1u_separate(boolean sgsn_originated_reset := false) runs on RAW_Test_CT {
/* Activate two NS codec ports */
- f_init_ns_codec();
- f_init_ns_codec(1);
- f_init_ns_codec(2);
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_init_ns_codec(mp_nsconfig, 2);
f_init_pcuif();
/* Perform Size + BSS-originated config */
f_incoming_sns_size();
@@ -269,20 +180,29 @@ private function f_sns_bringup_1c1u_separate(boolean sgsn_originated_reset := fa
f_outgoing_ns_alive_no_ack(idx := 0);
if (sgsn_originated_reset) {
- f_tx_bvc_reset_rx_ack(0, idx := 1);
- f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci, idx := 1);
+ /* Expect BVC-RESET, but ignore it to prevent a race condition of BVC RESETs */
+ var template PDU_NS pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, 0, omit));
+ f_ns_exp(pdu, idx := 1);
+ /* SGSN originated BVC-RESET on an uninitialized sign BVC */
+ f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 1);
+
+ /* Expect BVC-RESET PTP BVC, but ignore it to prevent a race condition of BVC RESETs */
+ pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id));
+ f_ns_exp(pdu, idx := 1);
+ f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id, idx := 1);
} else {
- /* Expect BVC-RESET for signaling BVCI=0 and ptp BVCI */
- as_rx_bvc_reset_tx_ack(0, oneshot := true, idx := 1);
- as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 1);
+ /* Expect BVC-RESET for signaling BVCI=0 */
+ as_rx_bvc_reset_tx_ack(0, omit, omit, oneshot := true, idx := 1);
+ /* Expect BVC-RESET from the PCU on PTP BVC */
+ as_rx_bvc_reset_tx_ack(mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id, omit, oneshot := true, idx := 1);
}
/* Expect UNBLOCK for ptp BVCI on signaling NS-VC (idx==1) */
- as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 1);
+ as_rx_bvc_unblock_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 1);
/* wait for one FLOW-CONTROL BVC and then ACK any further in the future. Flow
* control happens on the p-t-p BVCI and hence on index 1 */
- as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, oneshot := true, idx := 2);
- activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvci, idx := 2));
+ as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, oneshot := true, idx := 2);
+ activate(as_rx_bvc_fc_tx_ack(mp_gb_cfg.bvc[0].bvci, idx := 2));
}
/* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only - and where
@@ -290,6 +210,7 @@ private function f_sns_bringup_1c1u_separate(boolean sgsn_originated_reset := fa
testcase TC_sns_1c1u_separate() runs on RAW_Test_CT {
f_sns_bringup_1c1u_separate();
setverdict(pass);
+ f_clean_ns_codec();
}
/* Test full IP-SNS bring-up with two NS-VCs, one sig-only and one user-only and use
@@ -297,14 +218,24 @@ testcase TC_sns_1c1u_separate() runs on RAW_Test_CT {
testcase TC_sns_1c1u_so_bvc_reset() runs on RAW_Test_CT {
f_sns_bringup_1c1u_separate(sgsn_originated_reset := true);
setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Test full IP_SNS bring-up over an initial NS-VC with two NS-VCs */
+testcase TC_sns_1c1u_unconfigured_nsvc() runs on RAW_Test_CT {
+ f_init_vty(testcasename());
+ f_sns_bringup_1c1u_separate();
+ f_vty_transceive_not_match(PCUVTY, "show ns entities", pattern "*UNCONFIGURED*");
+ setverdict(pass);
+ f_clean_ns_codec();
}
/* Transmit BVC-RESET before NS-ALIVE of PCU was ACKed: expect no response */
testcase TC_sns_1c1u_so_bvc_reset_too_early() runs on RAW_Test_CT {
/* Activate two NS codec ports */
- f_init_ns_codec();
- f_init_ns_codec(1);
- f_init_ns_codec(2);
+ f_init_ns_codec(mp_nsconfig);
+ f_init_ns_codec(mp_nsconfig, 1);
+ f_init_ns_codec(mp_nsconfig, 2);
f_init_pcuif();
/* Perform Size + BSS-originated config */
f_incoming_sns_size();
@@ -321,16 +252,56 @@ testcase TC_sns_1c1u_so_bvc_reset_too_early() runs on RAW_Test_CT {
f_outgoing_ns_alive_no_ack(idx := 0);
/* Transmit BVC-RESET and expect no ACK*/
- f_tx_bvc_reset_rx_ack(0, idx := 1, exp_ack := false);
- f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvci, idx := 1, exp_ack := false);
+ f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 1, exp_ack := false);
+ f_tx_bvc_reset_rx_ack(mp_gb_cfg.bvc[0].bvci, omit, mp_gb_cfg.bvc[0].cell_id, idx := 1, exp_ack := false);
+ f_clean_ns_codec();
+}
+
+/* Do an SGSN originated BSSGP-Reset of a not-configured BVCI.
+ *
+ * PCU -X SGSN: BVCI 0 BSSGP-RESET (ignores reset)
+ * PCU <- SGSN: BVCI 0 BSSGP-RESET
+ * PCU -> SGSN: BVCI 0 BSSGP-RESET-ACK (with cell information)
+ * PCU -X SGSN: BVCI 23 BSSGP-RESET (ignores reset, 23 is configured on PCU, 24 is not configured)
+ * PCU <- SGSN: BVCI 24 BSSGP-RESET (unconfigured BVCI)
+ * PCU -> SGSN: BVCI 24 BSSGP-STATUS Unknown BVCI
+ */
+testcase TC_sns_so_bvc_reset_unknown_bvci() runs on RAW_Test_CT {
+ g_handle_rx_alive := true;
+ f_init_ns_codec(mp_nsconfig);
+ f_init_pcuif();
+ f_incoming_sns_size();
+ f_incoming_sns_config();
+ f_outgoing_sns_config();
+
+ /* Expect BVC-RESET, but ignore it to prevent a race condition of BVC RESETs */
+ var template PDU_NS pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, 0, omit));
+ f_ns_exp(pdu, idx := 0);
+ /* SGSN originated BVC-RESET on an uninitialized sign BVC */
+ f_tx_bvc_reset_rx_ack(0, omit, omit, idx := 0);
+
+ /* Expect BVC-RESET PTP BVC, but ignore it to prevent a race condition of BVC RESETs */
+ pdu := tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BVC_RESET(?, mp_gb_cfg.bvc[0].bvci, mp_gb_cfg.bvc[0].cell_id));
+ f_ns_exp(pdu);
+
+ /* Send a BVC-RESET on the wrong BVC */
+ var BssgpCellId cell_id := mp_gb_cfg.bvc[0].cell_id;
+ cell_id.cell_id := cell_id.cell_id + 1;
+ var PDU_BSSGP bssgp_tx := valueof(ts_BVC_RESET(BSSGP_CAUSE_NET_SV_CAP_MOD_GT_ZERO_KBPS,
+ mp_gb_cfg.bvc[0].bvci + 1, cell_id));
+ NSCP[0].send(ts_NS_UNITDATA(t_SduCtrlB, 0, enc_PDU_BSSGP(bssgp_tx)));
+ NSCP[0].receive(tr_NS_UNITDATA(t_SduCtrlB, 0, decmatch tr_BSSGP_STATUS(mp_gb_cfg.bvc[0].bvci + 1, BSSGP_CAUSE_BVCI_UNKNOWN, *)));
+ setverdict(pass);
+
+ f_clean_ns_codec();
}
/* Test adding new IP endpoints at runtime */
testcase TC_sns_add() runs on RAW_Test_CT {
f_sns_bringup_1c1u();
- /* crate another NS codec port on the tester side */
- f_init_ns_codec(2);
+ /* create another NS codec port on the tester side */
+ f_init_ns_codec(mp_nsconfig, 2);
f_outgoing_sns_add(idx_add := 2, w_sig := 0, w_user := 1, idx := 0);
@@ -339,8 +310,17 @@ testcase TC_sns_add() runs on RAW_Test_CT {
activate(as_rx_alive_tx_ack(idx := 2));
f_outgoing_ns_alive(2);
- /* TODO: Should we expect FLOW-CONTROL BVC here too? */
setverdict(pass);
+ f_clean_ns_codec();
+}
+
+/* Test adding an already present IP endpoint at runtime */
+testcase TC_sns_add_nack() runs on RAW_Test_CT {
+ f_sns_bringup_1c1u();
+
+ f_outgoing_sns_add(idx_add := 0, w_sig := 0, w_user := 1, idx := 0, cause := NS_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
+ setverdict(pass);
+ f_clean_ns_codec();
}
/* Test deleting IP endpoints at runtime */
@@ -350,6 +330,7 @@ testcase TC_sns_del() runs on RAW_Test_CT {
f_outgoing_sns_del(idx_del := 1, w_sig := 0, w_user := 1, idx := 0);
/* FIXME: ensure we don't receive anything on just-deleted NS-VC anymore */
setverdict(pass);
+ f_clean_ns_codec();
}
/* Test changing weights at runtime */
@@ -359,6 +340,7 @@ testcase TC_sns_chg_weight() runs on RAW_Test_CT {
/* change w_user from 1 to 200 */
f_outgoing_sns_chg_weight(idx_chg := 1, w_sig := 0, w_user := 200, idx := 0);
setverdict(pass);
+ f_clean_ns_codec();
}
import from PCUIF_Types all;
@@ -379,8 +361,9 @@ testcase TC_pcuif_rach() runs on RAW_Test_CT {
fn:=42, arfcn:=871, qta:=0));
PCU.receive(t_SD_PCUIF(g_pcu_conn_id,
tr_PCUIF_DATA_REQ(bts_nr:=0, trx_nr:=0, ts_nr:=0, block_nr:=?, fn:=?,
- sapi:=PCU_IF_SAPI_AGCH, data:=?)));
+ sapi:=PCU_IF_SAPI_AGCH_2, data:=?)));
setverdict(pass);
+ f_clean_ns_codec();
}
@@ -395,7 +378,10 @@ control {
execute( TC_sns_1c1u_separate() );
execute( TC_sns_1c1u_so_bvc_reset() );
execute( TC_sns_1c1u_so_bvc_reset_too_early() );
+ execute( TC_sns_1c1u_unconfigured_nsvc() );
+ execute( TC_sns_so_bvc_reset_unknown_bvci() );
execute( TC_sns_add() );
+ execute( TC_sns_add_nack() );
execute( TC_sns_del() );
execute( TC_sns_chg_weight() );
diff --git a/pcu/PCU_Tests_SNSv6.cfg b/pcu/PCU_Tests_SNSv6.cfg
new file mode 100644
index 00000000..3093c2c4
--- /dev/null
+++ b/pcu/PCU_Tests_SNSv6.cfg
@@ -0,0 +1,36 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./PCU_Tests.default"
+
+[LOGGING]
+
+[MODULE_PARAMETERS]
+SGSN_Components.mp_nsconfig := {
+ nsei := 1234,
+ nsvc : {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET6,
+ local_ip := "::1",
+ local_udp_port := 23000,
+ remote_ip := "::1",
+ remote_udp_port := 22000,
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 1234
+ }
+ }
+}
+PCUIF_Types.mp_pcuif_version := 12
+
+[TESTPORT_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+PCU_Tests_SNS.control
diff --git a/pcu/PCU_selftest.ttcn b/pcu/PCU_selftest.ttcn
index 70138bff..a8bcaee7 100644
--- a/pcu/PCU_selftest.ttcn
+++ b/pcu/PCU_selftest.ttcn
@@ -291,7 +291,7 @@ testcase TC_selftest_rlcmac_egprs() runs on RAW_PCU_Test_CT
data := f_pad_oct(data, f_rlcmac_cs_mcs2block_len(schemes[i]), '00'O);
/* Send to PCU so that we get gsmtap traces to verify with wireshark */
- f_pcuif_tx_data_ind(data, 0, 0);
+ f_pcuif_tx_data_ind(data);
log("Decoding ", schemes[i]);
ul_data := dec_RlcmacUlBlock(data);
diff --git a/pcu/README.md b/pcu/README.md
index a2e439a5..0a1d31f5 100644
--- a/pcu/README.md
+++ b/pcu/README.md
@@ -2,17 +2,94 @@
* external interfaces
* Gb (emulates SGSN side NS/BSSGP)
- * unix pcu socket (emulates BTS)
+ * PCUIF: unix pcu socket (emulates BTS)
* VTY
+ * CTRL
+ * StatsD
-{% dot msc_tests.svg
+{% dot pcu_tests.svg
digraph G {
- rankdir=LR;
- PCU [label="IUT\nosmo-pcu",shape="box"];
- ATS [label="ATS\nPCU_Tests.ttcn"];
+ PCU [label="IUT\nosmo-pcu",shape="box", color=red];
- PCU -> ATS [label="Gb"];
- PCU -> ATS [label="pcu_sock"];
- ATS -> PCU [label="VTY"];
+ subgraph cluster_ats {
+ label = "ATS\n(TTCN-3)";
+
+ system_PCU_PT [label="port system:PCU"];
+
+ subgraph cluster_RAW_PCU_Test_CT {
+ label = "RAW_PCU_Test_CT\n(PCU_Tests.ttcn)";
+
+ RAW_PCU_MSG_PT_PCUIF_A [label="port RAW_PCU_MSG_PT PCUIF\n(unused)"]
+ PCUVTY [label="PCUVTY"];
+ StatsD_ConnHdlr [label="StatsD_ConnHdlr"];
+ CTRL_Adapter_CT [label="CTRL_Adapter_CT"];
+
+ test [label="testcasename()\n(PCU_Tests.ttcn)", color=red];
+
+ subgraph cluster_bssgp_CT {
+ label="bssgp_CT\nSGSN_Components.ttcn";
+ subgraph cluster_BSSGP_Client_CT {
+ label="BSSGP_Client_CT\nBSSGP_Emulation.ttcnpp";
+ BSSGP_PT [label="port BSSGP_PT BSSGP"];
+ }
+ }
+
+ subgraph cluster_MS_BTS_IFACE_CT {
+ label = "MS_BTS_IFACE_CT\n(GPRS_Components.ttcn)";
+
+ RAW_PCU_MSG_PT_BTS_IFACE [label="port RAW_PCU_MSG_PT BTS"];
+ }
+
+ }
+
+ subgraph cluster_RAW_PCUIF_CT {
+ label = "RAW_PCUIF_CT\n(PCUIF_Components.ttcn)";
+
+ PCUIF_CODEC_PT_PCU [label="port PCUIF_CODEC_PT PCU"];
+ RAW_PCU_MSG_PT_BTS [label="port RAW_PCU_MSG_PT BTS"];
+ RAW_PCU_MSG_PT_MTC [label="port RAW_PCU_MSG_PT MTC"];
+
+ PCUIF_CODEC_PT_PCU -> RAW_PCU_MSG_PT_BTS [dir=none];
+ PCUIF_CODEC_PT_PCU -> RAW_PCU_MSG_PT_MTC [dir=none];
+
+ }
+
+ subgraph cluster_RAW_PCU_BTS_CT {
+ label = "RAW_PCU_BTS_CT\n(PCUIF_Components.ttcn)";
+
+ RAW_PCU_MSG_PT_CLCK_A [label="port RAW_PCU_MSG_PT CLCK"];
+ RAW_PCU_MSG_PT_PCUIF_B [label="port RAW_PCU_MSG_PT PCUIF"];
+ RAW_PCU_MSG_PT_TC [label="port RAW_PCU_MSG_PT TC"];
+
+ subgraph cluster_RAW_PCU_ClckGen_CT {
+ label = "RAW_PCU_ClckGen_CT\n(PCUIF_Components.ttcn)";
+
+ RAW_PCU_MSG_PT_CLCK_B [label="port RAW_PCU_MSG_PT CLCK", color=purple];
+ }
+
+ RAW_PCU_MSG_PT_CLCK_A -> RAW_PCU_MSG_PT_CLCK_B [dir=back];
+ RAW_PCU_MSG_PT_PCUIF_B -> RAW_PCU_MSG_PT_TC [dir=none];
+ }
+
+
+ RAW_PCU_MSG_PT_TC -> RAW_PCU_MSG_PT_BTS_IFACE [dir=none];
+ RAW_PCU_MSG_PT_PCUIF_A -> RAW_PCU_MSG_PT_MTC [dir=none];
+ RAW_PCU_MSG_PT_PCUIF_B -> RAW_PCU_MSG_PT_BTS [dir=none];
+
+ PCUIF_CODEC_PT_PCU -> system_PCU_PT [dir=none];
+
+ test -> RAW_PCU_MSG_PT_BTS_IFACE [dir=none];
+ test -> RAW_PCU_MSG_PT_PCUIF_A [label="(unused)", dir=none];
+ test -> BSSGP_PT;
+ test -> PCUVTY;
+ test -> StatsD_ConnHdlr;
+ test -> CTRL_Adapter_CT;
+ }
+
+ PCU -> BSSGP_PT [label="Gb"];
+ PCU -> StatsD_ConnHdlr [label="statsd"];
+ system_PCU_PT -> PCU [label="PCUIF"];
+ PCUVTY -> PCU [label="VTY"];
+ CTRL_Adapter_CT -> PCU [label="CTRL"];
}
%}
diff --git a/pcu/SGSN_Components.ttcn b/pcu/SGSN_Components.ttcn
index 4bbd18ca..bbac9b0d 100644
--- a/pcu/SGSN_Components.ttcn
+++ b/pcu/SGSN_Components.ttcn
@@ -20,29 +20,67 @@ import from GPRS_Context all;
modulepar {
BssgpConfig mp_gb_cfg := {
nsei := 1234,
- bvci := 1234,
- cell_id := {
- ra_id := {
- lai := {
- mcc_mnc := '262F42'H, lac := 13135
- },
- rac := 0
- },
- cell_id := 20960
- },
sgsn_role := true,
- depth := BSSGP_DECODE_DEPTH_BSSGP
+ bvc := {
+ {
+ bvci := 1234,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := '262F42'H, lac := 13135
+ },
+ rac := 0
+ },
+ cell_id := 20960
+ },
+ depth := BSSGP_DECODE_DEPTH_BSSGP,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
};
NSConfiguration mp_nsconfig := {
- local_udp_port := 23000,
- local_ip := "127.0.0.1",
- remote_udp_port := 21000,
- remote_ip := "127.0.0.1",
- nsvci := 0,
nsei := 2342,
role_sgsn := true,
- handle_sns := true
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 23000,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 21000,
+ remote_ip := "127.0.0.1"
+ }
+ },
+ nsvci := 0
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 23001,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 21000,
+ remote_ip := "127.0.0.1"
+ }
+ },
+ nsvci := 0
+ },
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 23002,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 21000,
+ remote_ip := "127.0.0.1"
+ }
+ },
+ nsvci := 0
+ }
+ }
};
}
@@ -50,6 +88,8 @@ modulepar {
type component bssgp_CT extends BSSGP_Client_CT {
var NS_CT ns_component;
var BSSGP_CT bssgp_component;
+ port BSSGP_CT_PROC_PT PROC;
+ port BSSGP_PT RIM;
var boolean g_initialized := false;
}
@@ -68,20 +108,27 @@ function f_init_bssgp() runs on bssgp_CT {
g_initialized := true;
/* create a new NS component */
- ns_component := NS_CT.create;
- bssgp_component := BSSGP_CT.create;
- /* connect our BSSGP port to the BSSGP Emulation */
- connect(self:BSSGP[0], bssgp_component:BSSGP_SP);
- connect(self:BSSGP_SIG[0], bssgp_component:BSSGP_SP_SIG);
- connect(self:BSSGP_PROC[0], bssgp_component:BSSGP_PROC);
+ ns_component := NS_CT.create alive;
+ bssgp_component := BSSGP_CT.create alive;
/* connect lower-end of BSSGP with BSSGP_CODEC_PORT (maps to NS_PT*/
connect(bssgp_component:BSCP, ns_component:NS_SP);
- /* connect lower-end of NS emulation to NS_CODEC_PORT (on top of IPl4) */
- map(ns_component:NSCP, system:NS_CODEC_PORT);
+ connect(self:PROC, bssgp_component:PROC);
ns_component.start(NSStart(mp_nsconfig));
- bssgp_component.start(BssgpStart(mp_gb_cfg));
+ bssgp_component.start(BssgpStart(mp_gb_cfg, testcasename()));
- f_bssgp_client_register(mmctx.imsi, mmctx.tlli, mp_gb_cfg.cell_id);
+ for (var integer i := 0; i < lengthof(mp_gb_cfg.bvc); i := i+1) {
+ var BSSGP_BVC_CT vc_BVC;
+ /* obtain reference for BVC component (created by BssgpStart) */
+ vc_BVC := f_bssgp_get_bvci_ct(mp_gb_cfg.bvc[i].bvci, PROC);
+ /* connect our BSSGP port to the BSSGP Emulation */
+ connect(self:BSSGP[i], vc_BVC:BSSGP_SP);
+ connect(self:BSSGP_SIG[i], vc_BVC:BSSGP_SP_SIG);
+ connect(self:BSSGP_PROC[i], vc_BVC:BSSGP_PROC);
+ f_bssgp_client_register(mmctx.imsi, mmctx.tlli);
+ }
+ /* connect RIM related port */
+ connect(self:RIM, bssgp_component:RIM);
+ connect(self:BSSGP_GLOBAL[0], bssgp_component:GLOBAL);
}
/* Establish BSSGP connection to PCU */
@@ -90,7 +137,7 @@ function f_bssgp_establish() runs on BSSGP_Client_CT {
T.start
alt {
- [] BSSGP[0].receive(t_BssgpStsInd(?, ?, BVC_S_UNBLOCKED)) { }
+ [] BSSGP[0].receive(tr_BssgpStsInd(*, ?, BVC_S_UNBLOCKED)) { }
[] BSSGP[0].receive { repeat; }
[] T.timeout {
setverdict(fail, "Timeout establishing BSSGP connection");
diff --git a/pcu/expected-results.xml b/pcu/expected-results.xml
index ddee7ecf..17d95cc5 100644
--- a/pcu/expected-results.xml
+++ b/pcu/expected-results.xml
@@ -1,8 +1,15 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='34' failures='2' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='117' failures='5' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='PCU_Tests' name='TC_pcuif_suspend' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_suspend_active_tbf' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_ta_ptcch_idle' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_ta_rach_imm_ass' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ta_ul_ack_nack_first_block' time='MASKED'>
+ <failure type='fail-verdict'>Timing Advance mismatch: expected 2, but received 0
+ PCU_Tests.ttcn:MASKED PCU_Tests control part
+ PCU_Tests.ttcn:MASKED TC_ta_ul_ack_nack_first_block testcase
+ </failure>
+ </testcase>
<testcase classname='PCU_Tests' name='TC_ta_idle_dl_tbf_ass' time='MASKED'>
<failure type='fail-verdict'>Timing Advance value doesn't match
PCU_Tests.ttcn:MASKED PCU_Tests control part
@@ -18,14 +25,37 @@
<testcase classname='PCU_Tests' name='TC_cs_lqual_ul_tbf' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_cs_initial_ul' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_cs_max_ul' time='MASKED'/>
- <testcase classname='PCU_Tests' name='TC_t3169' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_cs_initial_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_cs_max_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_cs1_to_cs4' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_mcs_initial_ul' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_mcs_max_ul' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_mcs_initial_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_mcs_max_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_t3141' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_n3101_max_t3169' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_n3103_max_t3169' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_x2031_t3191' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_zero_x2031_t3191' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_t3193' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_n3105_max_t3195' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_t3172_wait_ind_size0' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_t3172_wait_ind_size1' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_countdown_procedure' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_all_sizes' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_data_toolong_fills_padding' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_mo_ping_pong' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_mo_ping_pong_with_ul_racap' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_force_two_phase_access' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_mt_ping_pong' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_mt_ping_pong_with_dl_racap' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_intermediate_retrans' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_imm_ass_dl_block_retrans' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_dl_flow_more_blocks' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_flow_multiple_llc_blocks' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_no_ack_retrans_imm_ass' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_llc_sapi_priority' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_bsn_wraparound_gprs' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_paging_cs_from_bts' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_paging_cs_from_sgsn_sign_ptmsi' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_paging_cs_from_sgsn_sign' time='MASKED'/>
@@ -33,9 +63,77 @@
<testcase classname='PCU_Tests' name='TC_paging_ps_from_sgsn_sign_ptmsi' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_paging_ps_from_sgsn_sign' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_paging_ps_from_sgsn_ptp' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_paging_pch_timeout' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_paging_cs_multi_ms_imsi_tmsi' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_paging_cs_multi_ms_imsi' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_paging_cs_multi_ms_tmsi' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_bssgp_dl_unitdata_with_valid_imsi' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_bssgp_dl_unitdata_with_invalid_imsi' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_gprs_data_no_llc_ui_dummy' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_egprs_data_no_llc_ui_dummy' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_finished_pkt_dl_ass_pch' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_1phase_while_dl_ass_pch' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_2phase_while_dl_ass_pch' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_signalling' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_one_phase' time='MASKED'/>
<testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_two_phase' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_reject_content' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_reject_emergency' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_egprs_pkt_chan_req_reject_exhaustion' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_mo_ping_pong_with_ul_racap_egprs_only' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_fh_imm_ass_ul_egprs' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_fh_imm_ass_ul' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_fh_imm_ass_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_fh_pkt_ass_ul' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_fh_pkt_ass_dl' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_multitrx_multims_alloc' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_dl_multislot_tbf_ms_class_from_sgsn' time='MASKED'>
+ <failure type='fail-verdict'>Expected 8 PDCH slots allocated but got 4
+ PCU_Tests.ttcn:MASKED PCU_Tests control part
+ PCU_Tests.ttcn:MASKED TC_dl_multislot_tbf_ms_class_from_sgsn testcase
+ </failure>
+ </testcase>
+ <testcase classname='PCU_Tests' name='TC_dl_multislot_tbf_ms_class_unknown' time='MASKED'>
+ <failure type='fail-verdict'>Expected 1 PDCH slots allocated but got 4
+ PCU_Tests.ttcn:MASKED PCU_Tests control part
+ PCU_Tests.ttcn:MASKED TC_dl_multislot_tbf_ms_class_unknown testcase
+ </failure>
+ </testcase>
+ <testcase classname='PCU_Tests' name='TC_dl_multislot_tbf_ms_class_from_2phase' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_multislot_tbf_ms_class_from_2phase' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_reestablish_with_pkt_resource_req' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_reestablish_with_pkt_resource_req_t3168' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_reestablish_with_pkt_dl_ack_nack' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ul_tbf_reestablish_with_pkt_dl_ack_nack_egprs' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_multiplex_dl_gprs_egprs' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pcuif_info_ind_subsequent' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success_utran' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success_eutran' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success_no_ctrl_ack' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success_twice' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_success_twice_nocache' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_rac_ci_resolve_timeout' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_si_resolve_timeout' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_dup' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_dup2' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_dup3' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_dup4' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_dup5' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_twice' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_twice2' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_twice3' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_twice4' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_twice5' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_nacc_outbound_pkt_cell_chg_notif_unassigned_dl_tbf' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_rim_ran_info_req_single_rep' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_rim_ran_info_req_single_rep_eutran' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_rim_ran_info_req_single_rep_no_si' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_pdch_energy_saving' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_stat_pdch_avail_occ' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_stat_pdch_avail_occ_ms_not_known_gprs' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_stat_pdch_avail_occ_ms_not_known_egprs' time='MASKED'/>
+ <testcase classname='PCU_Tests' name='TC_ratectr_all_available_allocated' time='MASKED'/>
<testcase classname='PCU_Tests_NS' name='TC_ns_reset' time='MASKED'/>
<testcase classname='PCU_Tests_NS' name='TC_ns_reset_retrans' time='MASKED'/>
<testcase classname='PCU_Tests_NS' name='TC_ns_alive' time='MASKED'/>
diff --git a/pcu/gen_links.sh b/pcu/gen_links.sh
index 3a52c99e..556f02a7 100755
--- a/pcu/gen_links.sh
+++ b/pcu/gen_links.sh
@@ -49,11 +49,15 @@ FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_Types.ttcn RLCMAC_Templates.ttcn RLCMAC_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn RLCMAC_EncDec.cc "
-FILES+="NS_Emulation.ttcn NS_CodecPort.ttcn NS_CodecPort_CtrlFunct.ttcn NS_CodecPort_CtrlFunctDef.cc "
-FILES+="BSSGP_Emulation.ttcn Osmocom_Gb_Types.ttcn "
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc GSM_Types.ttcn GSM_RR_Types.ttcn GSM_RestOctets.ttcn Osmocom_Types.ttcn RLCMAC_Templates.ttcn RLCMAC_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn RLCMAC_EncDec.cc "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
FILES+="LLC_Templates.ttcn L3_Templates.ttcn L3_Common.ttcn "
-FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn "
+FILES+="PCUIF_Types.ttcn PCUIF_CodecPort.ttcn RAW_NS.ttcnpp "
+# IPA_Emulation + dependencies
+FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc "
+FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
gen_links $DIR $FILES
ignore_pp_results
diff --git a/pcu/osmo-pcu-sns.cfg b/pcu/osmo-pcu-sns.cfg
index c2cd58ac..cfe4ccfe 100644
--- a/pcu/osmo-pcu-sns.cfg
+++ b/pcu/osmo-pcu-sns.cfg
@@ -1,8 +1,10 @@
log gsmtap 127.0.0.1
logging level set-all debug
+ logging filter all 1
log stderr
logging filter all 1
+ logging color 1
logging print level 1
logging print category 1
logging print category-hex 0
@@ -21,3 +23,5 @@ pcu
gamma 0
pcu-socket /tmp/pcu_bts
gb-dialect ip-sns
+ns
+ timer tns-test 10
diff --git a/pcu/osmo-pcu.cfg b/pcu/osmo-pcu.cfg
index d6213b51..68ea521b 100644
--- a/pcu/osmo-pcu.cfg
+++ b/pcu/osmo-pcu.cfg
@@ -1,14 +1,26 @@
log gsmtap 127.0.0.1
logging level set-all debug
+ logging filter all 1
log stderr
logging filter all 1
+ logging color 1
logging print level 1
logging print category 1
logging print category-hex 0
logging print file basename last
logging print extended-timestamp 1
logging level set-all debug
+!
+stats interval 0
+stats reporter statsd
+ prefix TTCN3
+ level subscriber
+ remote-ip 127.0.0.1
+ remote-port 8125
+ flush-period 1
+ mtu 1024
+ enable
line vty
no login
@@ -17,6 +29,9 @@ pcu
flow-control-interval 10
cs 2
alloc-algorithm dynamic
- alpha 0
gamma 0
pcu-socket /tmp/pcu_bts
+! By default, use the PCUIF for neighbor resolution
+! neighbor resolution 127.0.0.1
+ gsmtap-remote-host 127.0.0.1
+ gsmtap-category enable-all
diff --git a/pcu/regen_makefile.sh b/pcu/regen_makefile.sh
index 6fd000e0..006c6baa 100755
--- a/pcu/regen_makefile.sh
+++ b/pcu/regen_makefile.sh
@@ -1,5 +1,27 @@
#!/bin/sh
-FILES="*.ttcn BSSGP_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc NS_CodecPort_CtrlFunctDef.cc UD_PT.cc RLCMAC_EncDec.cc LLC_EncDec.cc TELNETasp_PT.cc Native_FunctionDefs.cc"
+NAME=PCU_Tests
-../regen-makefile.sh PCU_Tests.ttcn $FILES
+FILES="
+ *.ttcn
+ *.ttcnpp
+ BSSGP_EncDec.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ RLCMAC_EncDec.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ UD_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DBSSGP_EM_L3
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/pgw/PGW_Tests.ttcn b/pgw/PGW_Tests.ttcn
index 81e3552a..08cd1a0b 100644
--- a/pgw/PGW_Tests.ttcn
+++ b/pgw/PGW_Tests.ttcn
@@ -1,8 +1,11 @@
module PGW_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 GTPv2_Types all;
import from GTPv2_Templates all;
@@ -15,44 +18,95 @@ 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;
modulepar {
- charstring mp_pgw_hostname := "127.0.0.3";
+ charstring mp_pgw_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_run_prog_log_path := "/tmp";
charstring mp_run_prog_as_user := "laforge";
charstring mp_ping_hostname := "10.45.0.1";
- charstring mp_pcrf_local_ip := "127.0.0.5";
+ 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 PGW_Test_CT {
+type component PGW_Test_CT extends GTP2_ConnHdlr {
var GTPv2_Emulation_CT vc_GTP2;
port GTP2EM_PT TEID0;
/* emulated PCRF */
- var DIAMETER_Emulation_CT vc_DIAMETER;
- port DIAMETER_PT DIAMETER_UNIT;
- port DIAMETEREM_PROC_PT DIAMETER_PROC;
+ 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 PGW_Test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+type component DIAMETER_ConnHdlr_CT extends DIAMETER_ConnHdlr {
+ port DIAMETER_Conn_PT DIAMETER_CLIENT;
+}
+
+function f_diam_connhldr_ct_main(hexstring imsi) runs on DIAMETER_ConnHdlr_CT {
+ var PDU_DIAMETER msg;
+
+ if (DIAMETER_PROC.checkstate("Connected")) {
+ f_diameter_expect_imsi(imsi);
+ }
+
+ while (true) {
+ alt {
+ [] DIAMETER_CLIENT.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER.send(msg);
+ }
+ [] DIAMETER.receive(PDU_DIAMETER:?) -> value msg {
+ DIAMETER_CLIENT.send(msg);
+ }
+ }
+ }
}
+
/* per-session component; we typically have 1..N per testcase */
-type component PGW_Session_CT extends GTP2_ConnHdlr, DIAMETER_ConnHdlr {
+type component PGW_Session_CT extends GTP2_ConnHdlr {
var SessionPars g_pars;
- /* TEI (Data) local side */
- var OCT4 g_teid;
- /* TEI (Control) local side */
- var OCT4 g_teic;
- /* TEI (Data) remote side */
- var OCT4 g_teid_remote;
- /* TEI (Control) remote side */
- var OCT4 g_teic_remote;
+ port DIAMETER_Conn_PT Gx;
+ port DIAMETER_Conn_PT Gy;
+ port DIAMETER_Conn_PT S6b;
+
/* GTP-U IPv4 address remote sie */
var OCT4 g_gtpu4_remote;
var OCT16 g_gtpu6_remote;
@@ -61,14 +115,37 @@ type component PGW_Session_CT extends GTP2_ConnHdlr, DIAMETER_ConnHdlr {
var OCT4 g_ip4_addr;
var OCT16 g_ip6_addr;
var integer g_ip6_plen;
+
+ /* Store last received Gy message */
+ var PDU_DIAMETER g_rx_gy;
+
+ /* number of programs started, used as identifier. */
+ var integer g_start_prog_count := 0;
}
+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,
- octetstring msisdn optional,
+ hexstring msisdn optional,
// serving network
- integer rat_type,
+ GTP2C_RAT_Type rat_type,
// flags?
charstring apn,
/* Apn subscribed or non-subscribed */
@@ -79,30 +156,51 @@ type record SessionPars {
/* 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,
charstring tun_dev_name,
- charstring tun_netns_name optional
+ charstring tun_netns_name optional,
+
+ SessionParsGy gy
}
template (value) SessionPars
-t_SessionPars(hexstring imsi, charstring tundev, integer rat_type := 6, charstring apn := "internet",
- boolean selection_mode := false, BIT3 pdn_type := '001'B) := {
+t_SessionPars(hexstring imsi,
+ charstring tundev,
+ template (omit) hexstring msisdn := '1234'H,
+ GTP2C_RAT_Type rat_type := GTP2C_RAT_EUTRAN,
+ charstring apn := "internet",
+ boolean selection_mode := false,
+ BIT3 pdn_type := '001'B) := {
imsi := imsi,
- msisdn := omit,
+ 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
+ },
tun_dev_name := tundev,
- tun_netns_name := tundev
+ tun_netns_name := tundev,
+ gy := {
+ validity_time := 0,
+ cca_res_code := DIAMETER_SUCCESS
+ }
}
-type record BearerConfig {
- integer eps_bearer_id
-}
type function void_fn() runs on PGW_Session_CT;
@@ -115,32 +213,84 @@ runs on DIAMETER_Emulation_CT return template PDU_DIAMETER {
friend function f_init_diameter(charstring id) runs on PGW_Test_CT {
var DIAMETEROps ops := {
create_cb := refers(DIAMETER_Emulation.ExpectedCreateCallback),
- unitdata_cb := refers(DiameterForwardUnitdataCallback)
+ unitdata_cb := refers(DiameterForwardUnitdataCallback),
+ raw := false /* handler mode (IMSI based routing) */
};
- var DIAMETER_conn_parameters pars := {
+ var DIAMETER_conn_parameters pars;
+
+ /* Gx setup: */
+ pars := {
remote_ip := mp_pgw_hostname,
remote_sctp_port := -1,
local_ip := mp_pcrf_local_ip,
local_sctp_port := mp_pcrf_local_port,
- origin_host := "pcrf.localdomain",
- origin_realm := "localdomain",
+ origin_host := "pcrf." & mp_diam_realm,
+ origin_realm := mp_diam_realm,
+ auth_app_id := omit,
vendor_app_id := c_DIAMETER_3GPP_Gx_AID
};
- vc_DIAMETER := DIAMETER_Emulation_CT.create(id);
- map(vc_DIAMETER:DIAMETER, system:DIAMETER_CODEC_PT);
- connect(vc_DIAMETER:DIAMETER_UNIT, self:DIAMETER_UNIT);
- connect(vc_DIAMETER:DIAMETER_PROC, self:DIAMETER_PROC);
- vc_DIAMETER.start(DIAMETER_Emulation.main(ops, pars, id));
-
- f_diameter_wait_capability(DIAMETER_UNIT);
+ 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_pgw_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_pgw_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 watchdong ping-pongs):
+ * RFC6733 sec 5.1
+ * RFC3539 sec 3.4.1 [5]
+ * https://github.com/freeDiameter/freeDiameter/blob/master/libfdcore/p_psm.c#L49
+ */
+ f_sleep(1.0);
}
-private function f_init() runs on PGW_Test_CT {
+private function f_init(float guard_timeout := 60.0) runs on PGW_Test_CT {
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
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
};
@@ -148,6 +298,8 @@ private function f_init() runs on PGW_Test_CT {
vc_GTP2 := GTPv2_Emulation_CT.create("GTP2_EM");
map(vc_GTP2:GTP2C, system:GTP2C);
connect(vc_GTP2:TEID0, self:TEID0);
+ connect(vc_GTP2:CLIENT, self:GTP2);
+ connect(vc_GTP2:CLIENT_PROC, self:GTP2_PROC);
vc_GTP2.start(GTPv2_Emulation.main(cfg));
if (mp_pcrf_local_ip != "") {
@@ -155,31 +307,57 @@ private function f_init() runs on PGW_Test_CT {
}
}
-function f_start_handler(void_fn fn, template (omit) SessionPars pars := omit)
+function f_start_handler(void_fn fn, template (omit) SessionPars pars_tmpl := omit)
runs on PGW_Test_CT return PGW_Session_CT {
var charstring id := testcasename();
+ var DIAMETER_ConnHdlr_CT vc_conn_gx, vc_conn_gy, vc_conn_s6b;
var PGW_Session_CT vc_conn;
+ var SessionPars pars;
+
+ if (isvalue(pars_tmpl)) {
+ pars := valueof(pars_tmpl);
+ } else {
+ /*TODO: set default values */
+ }
+
vc_conn := PGW_Session_CT.create(id);
connect(vc_conn:GTP2, vc_GTP2:CLIENT);
connect(vc_conn:GTP2_PROC, vc_GTP2:CLIENT_PROC);
- if (isbound(vc_DIAMETER)) {
- connect(vc_conn:DIAMETER, vc_DIAMETER:DIAMETER_CLIENT);
- connect(vc_conn:DIAMETER_PROC, vc_DIAMETER:DIAMETER_PROC);
+ if (isbound(vc_Gx)) {
+ vc_conn_gx := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_gx:DIAMETER, vc_Gx:DIAMETER_CLIENT);
+ connect(vc_conn_gx:DIAMETER_PROC, vc_Gx:DIAMETER_PROC);
+ connect(vc_conn:Gx, vc_conn_gx:DIAMETER_CLIENT);
+ vc_conn_gx.start(f_diam_connhldr_ct_main(pars.imsi));
+ }
+
+ if (isbound(vc_Gy)) {
+ vc_conn_gy := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_gy:DIAMETER, vc_Gy:DIAMETER_CLIENT);
+ connect(vc_conn_gy:DIAMETER_PROC, vc_Gy:DIAMETER_PROC);
+ connect(vc_conn:Gy, vc_conn_gy:DIAMETER_CLIENT);
+ vc_conn_gy.start(f_diam_connhldr_ct_main(pars.imsi));
+ }
+
+ if (isbound(vc_S6b)) {
+ vc_conn_s6b := DIAMETER_ConnHdlr_CT.create(id);
+ connect(vc_conn_s6b:DIAMETER, vc_S6b:DIAMETER_CLIENT);
+ connect(vc_conn_s6b:DIAMETER_PROC, vc_S6b:DIAMETER_PROC);
+ connect(vc_conn:S6b, vc_conn_s6b:DIAMETER_CLIENT);
+ vc_conn_s6b.start(f_diam_connhldr_ct_main(pars.imsi));
}
vc_conn.start(f_handler_init(fn, pars));
return vc_conn;
}
-private function f_handler_init(void_fn fn, template (omit) SessionPars pars := omit)
+private function f_handler_init(void_fn fn, SessionPars pars)
runs on PGW_Session_CT {
- if (isvalue(pars)) {
- g_pars := valueof(pars);
- }
- if (DIAMETER_PROC.checkstate("Connected")) {
- f_diameter_expect(g_pars.imsi);
- }
+ 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;
fn.apply();
}
@@ -199,13 +377,31 @@ function f_gen_imsi(integer suffix) return hexstring {
return f_concat_pad(15, '26242'H, suffix);
}
-function f_gen_msisdn(integer suffix) return hexstring {
- return f_concat_pad(12, '49123'H, suffix);
+/* S6b emulation (AAA-Server) */
+private altstep as_DIA_S6b_AAR() runs on PGW_Session_CT {
+ var PDU_DIAMETER rx_dia;
+ [] S6b.receive(tr_DIA_S6b_AAR()) -> value rx_dia {
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+
+ avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+
+ S6b.send(ts_DIA_S6b_AAA(sess_id, "aaa." & mp_diam_realm,
+ mp_diam_realm, mp_diam_realm,
+ rx_dia.hop_by_hop_id, rx_dia.end_to_end_id));
+ setverdict(pass);
+ }
+ [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
+ }
}
-private altstep as_DIA_CCR(DCC_NONE_CC_Request_Type req_type) runs on PGW_Session_CT {
+/* Gx emulation (PCRF)*/
+private altstep as_DIA_Gx_CCR(DCC_NONE_CC_Request_Type req_type) runs on PGW_Session_CT {
var PDU_DIAMETER rx_dia;
- [] DIAMETER.receive(tr_DIA_CCR(req_type := req_type)) -> value rx_dia {
+ [] Gx.receive(tr_DIA_Gx_CCR(req_type := req_type)) -> value rx_dia {
var template (omit) AVP avp;
var octetstring sess_id;
var AVP_Unsigned32 req_num;
@@ -216,15 +412,228 @@ private altstep as_DIA_CCR(DCC_NONE_CC_Request_Type req_type) runs on PGW_Sessio
avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_DCC_NONE_CC_Request_Number);
req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
- DIAMETER.send(ts_DIA_CCA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
+ Gx.send(ts_DIA_Gx_CCA(rx_dia.hop_by_hop_id, rx_dia.end_to_end_id, sess_id,
req_type, req_num));
}
- [] DIAMETER.receive(PDU_DIAMETER:?) -> value rx_dia {
- setverdict(fail, "Received unexpected DIAMETER ", rx_dia);
- self.stop;
+ [] Gx.receive(PDU_DIAMETER:?) -> value rx_dia {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected DIAMETER ", rx_dia));
}
}
+/* Gy emulation (OCS) */
+function f_tr_DIA_Gy_CCR(DCC_NONE_CC_Request_Type req_type)
+runs on PGW_Session_CT return template (present) PDU_DIAMETER
+{
+ var template (present) PDU_DIAMETER tpl;
+ var charstring smf_origin_host := "smf." & mp_diam_realm;
+ var template (present) octetstring imsi := ?;
+ var template (present) octetstring msisdn := ?;
+ var template (present) octetstring rat_type := ?;
+ var template (present) OCT4 charging_char := ?;
+ var template (present) OCT1 nsapi := ?;
+ imsi := char2oct(f_dec_TBCD(imsi_hex2oct(g_pars.imsi)));
+ //msisdn := char2oct(f_dec_TBCD(substr(ctx_val.msisdn, 1, lengthof(ctx_val.msisdn) -1)));
+ rat_type := int2oct(enum2int(g_pars.rat_type), 1);
+ charging_char := char2oct(oct2str('0000'O)); // f_s5s8_create_session() uses hardcoded chg_car := '0000'O
+ nsapi := int2oct(g_pars.bearer.ebi, 1);
+ select (req_type) {
+ case (INITIAL_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(mp_diam_realm),
+ tr_AVP_DestinationRealm(mp_diam_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_MultipleServicesIndicator,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ tr_AVP_Requested_Service_Unit,
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ tr_AVP_3GPP_PDPType((IPv4,IPv6,IPv4v6)),
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pcrf_local_ip))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pgw_hostname))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ /*We don't yet send MS_Tz in CreateSessionReq:
+ tr_AVP_3GPP_MS_TimeZone,*/
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type)/*,
+ We don't yet send IMEI in CreateSessionReq:
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })*/
+ ))
+ ))
+ ));
+ }
+ case (UPDATE_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(mp_diam_realm),
+ tr_AVP_DestinationRealm(mp_diam_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_DestinationHost(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ tr_AVP_Requested_Service_Unit,
+ tr_AVP_Used_Service_Unit,
+ /* tr_AVP_3GPP_Reporting_Reason, can be sometimes inside UsedServiceUnit */
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ /* tr_AVP_3GPP_PDPType, Only in INIT */
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pcrf_local_ip))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pgw_hostname))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ /*We don't yet send MS_Tz in CreateSessionReq:
+ tr_AVP_3GPP_MS_TimeZone,*/
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type)/*,
+ We don't yet send IMEI in CreateSessionReq:
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })*/
+ ))
+ ))
+ ));
+ }
+ case (TERMINATION_REQUEST) {
+ tpl := tr_DIAMETER(flags:='11000000'B, cmd_code:=Credit_Control,
+ avps := superset(
+ tr_AVP_SessionId,
+ tr_AVP_OriginHost(smf_origin_host),
+ tr_AVP_OriginRealm(mp_diam_realm),
+ tr_AVP_DestinationRealm(mp_diam_realm),
+ tr_AVP_AuthAppId(int2oct(c_DIAMETER_CREDIT_CONTROL_AID, 4)),
+ tr_AVP_ServiceContextId,
+ tr_AVP_CcReqType(req_type),
+ tr_AVP_CcReqNum(?),
+ tr_AVP_DestinationHost(?),
+ tr_AVP_EventTimestamp(?),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_IMSI), tr_AVP_SubcrIdData(imsi)}),
+ tr_AVP_SubcrId({tr_AVP_SubcrIdType(END_USER_E164), tr_AVP_SubcrIdData(msisdn)}),
+ tr_AVP_TerminationCause(?),
+ tr_AVP_RequestedAction(DIRECT_DEBITING),
+ tr_AVP_3GPP_AoCRequestType,
+ tr_AVP_Multiple_Services_Credit_Control(content := superset(
+ /* tr_AVP_Requested_Service_Unit, Only in INIT and UPDATE */
+ tr_AVP_Used_Service_Unit,
+ tr_AVP_3GPP_Reporting_Reason(FINAL),
+ tr_AVP_PCC_3GPP_QoS_Information
+ )),
+ tr_AVP_3GPP_ServiceInformation(content := superset(
+ tr_AVP_3GPP_PSInformation(content := superset(
+ tr_AVP_3GPP_ChargingId,
+ /* tr_AVP_3GPP_PDPType, Only in INIT */
+ tr_AVP_3GPP_PDPAddress(tr_AVP_Address((IP,IP6), ?)),
+ tr_AVP_3GPP_SGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pcrf_local_ip))),
+ tr_AVP_3GPP_GGSNAddress(tr_AVP_Address(IP, f_inet_addr(mp_pgw_hostname))),
+ tr_AVP_3GPP_CalledStationId,
+ tr_AVP_3GPP_SelectionMode,
+ tr_AVP_3GPP_ChargingCharacteristics(charging_char),
+ tr_AVP_3GPP_SGSNMCCMNC,
+ tr_AVP_3GPP_NSAPI(nsapi),
+ /*We don't yet send MS_Tz in CreateSessionReq:
+ tr_AVP_3GPP_MS_TimeZone,*/
+ tr_AVP_3GPP_ULI,
+ tr_AVP_GI_3GPP_RatType(rat_type)/*,
+ We don't yet send IMEI in CreateSessionReq:
+ tr_AVP_UserEquipmentInfo({
+ tr_AVP_UserEquipmentInfoType(IMEISV),
+ tr_AVP_UserEquipmentInfoValue(imeisv)
+ })*/
+ ))
+ ))
+ ));
+ }
+ }
+ return tpl;
+}
+
+function f_ts_DIA_Gy_CCA(PDU_DIAMETER rx_gy)
+runs on PGW_Session_CT return template (value) PDU_DIAMETER
+{
+ var template (value) PDU_DIAMETER tx_dia;
+ var template (omit) AVP avp;
+ var octetstring sess_id;
+ var AVP_Unsigned32 req_num;
+ var DCC_NONE_CC_Request_Type req_type;
+ var DIAMETER_Resultcode cca_res_code_success := DIAMETER_SUCCESS;
+
+ avp := f_DIAMETER_get_avp(rx_gy, c_AVP_Code_BASE_NONE_Session_Id);
+ sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id);
+
+ avp := f_DIAMETER_get_avp(rx_gy, c_AVP_Code_DCC_NONE_CC_Request_Type);
+ req_type := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Type);
+
+ avp := f_DIAMETER_get_avp(rx_gy, c_AVP_Code_DCC_NONE_CC_Request_Number);
+ req_num := valueof(avp.avp_data.avp_DCC_NONE_CC_Request_Number);
+
+ if (g_pars.gy.cca_res_code != cca_res_code_success) {
+ tx_dia := ts_DIA_Gy_CCA(rx_gy.hop_by_hop_id, rx_gy.end_to_end_id, sess_id,
+ g_pars.gy.cca_res_code, req_type, req_num);
+ } else if (g_pars.gy.validity_time > 0) {
+ tx_dia := ts_DIA_Gy_CCA_ValidityTime(rx_gy.hop_by_hop_id, rx_gy.end_to_end_id, sess_id,
+ req_type, req_num, g_pars.gy.validity_time);
+ } else {
+ tx_dia := ts_DIA_Gy_CCA(rx_gy.hop_by_hop_id, rx_gy.end_to_end_id, sess_id,
+ g_pars.gy.cca_res_code, req_type, req_num);
+ }
+ return tx_dia;
+}
+
+private altstep as_DIA_Gy_CCR(DCC_NONE_CC_Request_Type req_type)
+runs on PGW_Session_CT {
+ [] Gy.receive(f_tr_DIA_Gy_CCR(req_type := req_type)) -> value g_rx_gy {
+ var template (value) PDU_DIAMETER tx_dia;
+ tx_dia := f_ts_DIA_Gy_CCA(g_rx_gy);
+ Gy.send(tx_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 PGW_Session_CT return boolean {
+ return (g_pars.rat_type == GTP2C_RAT_WLAN or g_pars.rat_type == GTP2C_RAT_Virtual);
+}
/* find TEID of given interface type (and optionally instance) */
private function f_find_teid(FullyQualifiedTEID_List list,
@@ -245,13 +654,24 @@ return template (omit) FullyQualifiedTEID
/* process one to-be-created bearer context */
private function process_bctx_create(BearerContextGrouped bctx) runs on PGW_Session_CT
{
- /* FIXME: EPS Bearer ID */
+ 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_find_teid(bctx.bearerContextIEs.fullyQualifiedTEID, 5, '0010'B));
- g_teid_remote := rx_fteid.tEID_GRE_Key;
+ rx_fteid := valueof(f_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;
}
@@ -260,8 +680,8 @@ private function process_bctx_create(BearerContextGrouped bctx) runs on PGW_Sess
}
var UECUPS_CreateTun uecups_create := {
- tx_teid := oct2int(g_teid_remote),
- rx_teid := oct2int(g_teid),
+ tx_teid := oct2int(g_pars.bearer.teid_remote),
+ rx_teid := oct2int(g_pars.bearer.teid_local),
user_addr_type := IPV4,
user_addr := '00000000'O,
local_gtp_ep := valueof(ts_UECUPS_SockAddr(f_inet_addr(mp_local_hostname_u))),
@@ -283,38 +703,55 @@ private function process_bctx_create(BearerContextGrouped bctx) runs on PGW_Sess
}
/* create a session on the PGW */
-private function f_create_session() runs on PGW_Session_CT {
+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 PGW_Session_CT {
var PDU_GTPCv2 rx;
- /* allocate + register TEID-C on local side */
- g_teic := f_gtp2_allocate_teid();
- g_teid := g_teic;
+ /* 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) FullyQualifiedTEID fteid_c_ie, fteid_u_ie;
- fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_teic, 0,
- f_inet_addr(mp_local_hostname_c), omit);
- fteid_u_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPU, g_teid, 2,
- f_inet_addr(mp_local_hostname_u), omit);
var template (value) PDU_GTPCv2 g2c :=
- ts_GTP2C_CreateSessionReq(imsi := g_pars.imsi, msisdn := omit, rat_type := 6,
+ 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 := g_pars.pdn_type, teid_list := { fteid_u_ie },
- chg_car := '0000'O, bearer_id := 1);
- /* 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 };
- g2c.gtpcv2_pdu.createSessionRequest.userLocationInfo := ts_GTP2C_UserLocInfo(tai := tai, ecgi := ecgi);
+ pdn_type := g_pars.pdn_type,
+ 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 (DIAMETER_PROC.checkstate("Connected")) {
- as_DIA_CCR(INITIAL_REQUEST);
+ if (do_s6b and S6b.checkstate("Connected")) {
+ as_DIA_S6b_AAR();
+ }
+ if (Gx.checkstate("Connected")) {
+ as_DIA_Gx_CCR(INITIAL_REQUEST);
+ }
+ /* FIXME: When on S2b interface, SMF is not using the Gy interface, unknown reason. */
+ if (Gy.checkstate("Connected")) {
+ as_DIA_Gy_CCR(INITIAL_REQUEST);
}
alt {
- [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_teic, cause:='10'O)) -> value rx {
+ [] 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_teic_remote := resp.fullyQualifiedTEID[0].tEID_GRE_Key;
+ 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;
@@ -336,55 +773,102 @@ private function f_create_session() runs on PGW_Session_CT {
process_bctx_create(bctx);
}
case ('0001'B) { // removed
- setverdict(fail, "We don't expect removed bearer contexts yet");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "We don't expect removed bearer contexts yet");
}
}
}
}
- [] GTP2.receive(tr_GTP2C_CreateSessionResp(d_teid:=g_teic, cause:=?)) -> value rx {
- setverdict(fail, "Unexpected CreateSessionResp(cause=",
- rx.gtpcv2_pdu.createSessionResponse.cause.causeValue, ")");
+ [] 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 {
- setverdict(fail, "Unexpected GTPv2 while waiting for CreateSessionResp");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected GTPv2 while waiting for CreateSessionResp");
}
}
}
+/* create a session on the PGW on a S5/S8 interface (from SGW )*/
+private function f_s5s8_create_session() runs on PGW_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 PGW on a S2b interface (from ePDG)*/
+private function f_s2b_create_session(template (omit) APCO apco := omit,
+ template APCO exp_apco := *) runs on PGW_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 PGW */
-private function f_delete_session(template (omit) OCT1 tx_cause := omit,
- template (present) OCT4 exp_teid,
- template (present) OCT1 exp_cause) runs on PGW_Session_CT {
+private function f_delete_session(template (omit) GTP2C_Cause tx_cause := omit,
+ template (present) GTP2C_Cause exp_cause,
+ boolean expect_diameter := true) runs on PGW_Session_CT {
var template (value) FullyQualifiedTEID fteid_c_ie
- fteid_c_ie := ts_GTP2C_FTEID(FTEID_IF_S5S8_SGW_GTPC, g_teic, 0,
+ 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_teic_remote, cause := tx_cause,
+ ts_GTP2C_DeleteSessionReq(d_teid := g_pars.teic_remote, cause := tx_cause,
sender_fteid := fteid_c_ie,
- teid_list := {}, bearer_id := 1);
+ teid_list := {}, bearer_id := g_pars.bearer.ebi);
GTP2.send(g2c);
- if (DIAMETER_PROC.checkstate("Connected")) {
- as_DIA_CCR(TERMINATION_REQUEST);
+ if (Gx.checkstate("Connected") and expect_diameter) {
+ as_DIA_Gx_CCR(TERMINATION_REQUEST);
+ }
+ if (Gy.checkstate("Connected") and expect_diameter) {
+ as_DIA_Gy_CCR(TERMINATION_REQUEST);
}
alt {
- [] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := exp_teid, cause := exp_cause)) {
+ [] GTP2.receive(tr_GTP2C_DeleteSessionResp(d_teid := g_pars.teic_local, cause := exp_cause)) {
setverdict(pass);
}
[] GTP2.receive(tr_GTP2C_DeleteSessionResp(?, ?)) {
- setverdict(fail, "Unexpected DeleteSessionResp");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected DeleteSessionResp");
}
[] GTP2.receive {
- setverdict(fail, "Unexpected GTPv2 while waiting for DeleteSessionResp");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ "Unexpected GTPv2 while waiting for DeleteSessionResp");
}
}
/* destroy tunnel in daemon */
- if (isbound(g_teid)) {
+ if (isbound(g_pars.bearer.teid_local)) {
var UECUPS_DestroyTun uecups_destroy := {
local_gtp_ep := valueof(ts_UECUPS_SockAddr(f_inet_addr(mp_local_hostname_u))),
- rx_teid := oct2int(g_teid)
+ rx_teid := oct2int(g_pars.bearer.teid_local)
};
/* FIXME: what about IPv4/IPv6 differentiation? */
f_gtp2_destroy_tunnel(uecups_destroy);
@@ -392,7 +876,8 @@ private function f_delete_session(template (omit) OCT1 tx_cause := omit,
}
/* start a program on the user plane side; return its PID */
-private function f_start_prog(charstring command) runs on PGW_Session_CT return integer
+private function f_start_prog(charstring command, boolean redirect_output := true)
+runs on PGW_Session_CT return integer
{
var UECUPS_StartProgram sprog := {
command := command,
@@ -400,10 +885,23 @@ private function f_start_prog(charstring command) runs on PGW_Session_CT return
run_as_user := mp_run_prog_as_user,
tun_netns_name := g_pars.tun_netns_name
};
+ g_start_prog_count := g_start_prog_count + 1;
+
+ /* Redirect stdout/stderr to the user-specified location */
+ if (redirect_output) {
+ var charstring id := testcasename() & "-" & hex2str(g_pars.imsi) & "-" & int2str(g_start_prog_count);
+ var charstring prefix := mp_run_prog_log_path & "/" & id;
+ sprog.command := sprog.command & " 1>>" & prefix & ".prog.stdout";
+ sprog.command := sprog.command & " 2>>" & prefix & ".prog.stderr";
+ }
+
+ log("Starting a program: ", command);
var UECUPS_StartProgramRes res := f_gtp2_start_program(sprog);
if (res.result != OK) {
- setverdict(fail, "Unable to start program '", command, "'");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Unable to start program '", command, "'"));
}
+ log("Started program '", command, "' with PID ", res.pid);
return res.pid;
}
@@ -411,6 +909,7 @@ private function f_start_prog(charstring command) runs on PGW_Session_CT return
private function f_wait_term(integer pid, template (present) integer exit_code := 0,
float tout := 10.0) runs on PGW_Session_CT
{
+ var UECUPS_ProgramTermInd pti;
timer T := tout;
T.start;
@@ -418,19 +917,25 @@ private function f_wait_term(integer pid, template (present) integer exit_code :
[] GTP2.receive(UECUPS_ProgramTermInd:{pid := pid, exit_code := exit_code}) {
setverdict(pass);
}
- [] GTP2.receive(UECUPS_ProgramTermInd:?) {
- setverdict(fail, "Received unexpected ProgramTermInd");
+ [] GTP2.receive(UECUPS_ProgramTermInd:?) -> value pti {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("Received unexpected ProgramTermInd := ", pti));
}
[] T.timeout {
- setverdict(fail, "timeout waiting for user-plane program termination");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
+ log2str("timeout (", tout, " seconds) waiting for user-plane program PID ", pid, " termination"));
}
}
}
/* execute a program and wait for result */
-private function f_start_prog_wait(charstring command, template integer exit_code := 0, float tout := 10.0) runs on PGW_Session_CT
+private function f_start_prog_wait(charstring command,
+ template integer exit_code := 0,
+ float tout := 10.0,
+ boolean redirect_output := true)
+runs on PGW_Session_CT
{
- var integer pid := f_start_prog(command);
+ var integer pid := f_start_prog(command, redirect_output);
f_wait_term(pid, exit_code, tout);
}
@@ -438,6 +943,10 @@ private function f_start_prog_wait(charstring command, template integer exit_cod
private function f_ping4(charstring host, integer interval := 1, integer count := 10) runs on PGW_Session_CT
{
var charstring ping :="ping -c " & int2str(count) & " -i " & int2str(interval);
+
+ if (not isbound(g_ip4_addr)) {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "f_ping4(): g_ip4_addr is unset!");
+ }
ping := ping & " -I " & f_inet_ntoa(g_ip4_addr);
ping := ping & " " & host;
f_start_prog_wait(ping, tout := int2float(5 + interval*count));
@@ -452,21 +961,21 @@ testcase TC_tx_echo() runs on PGW_Test_CT {
f_init();
- TEID0.send(ts_GTP2C_EchoReq(0));
+ GTP2.send(ts_GTP2C_EchoReq(0));
T.start;
alt {
- [] TEID0.receive(tr_GTP2C_EchoResp) {
+ [] GTP2.receive(tr_GTP2C_EchoResp) {
setverdict(pass);
}
[] T.timeout {
- setverdict(fail, "timeout waiting for Echo Response");
+ 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 PGW_Session_CT {
- f_create_session();
+ f_s5s8_create_session();
setverdict(pass);
}
testcase TC_createSession() runs on PGW_Test_CT {
@@ -479,7 +988,7 @@ testcase TC_createSession() runs on PGW_Test_CT {
/* create a session, then execute a ping command on the user plane */
private function f_TC_createSession_ping4() runs on PGW_Session_CT {
- f_create_session();
+ f_s5s8_create_session();
f_ping4(mp_ping_hostname);
setverdict(pass);
}
@@ -510,8 +1019,8 @@ testcase TC_createSession_ping4_256() runs on PGW_Test_CT {
/* create a session, then delete it again */
private function f_TC_createSession_deleteSession() runs on PGW_Session_CT {
- f_create_session();
- f_delete_session(omit, g_teic, '10'O);
+ f_s5s8_create_session();
+ f_delete_session(omit, Request_accepted);
setverdict(pass);
}
testcase TC_createSession_deleteSession() runs on PGW_Test_CT {
@@ -524,9 +1033,8 @@ testcase TC_createSession_deleteSession() runs on PGW_Test_CT {
/* send a DeleteSessionReq for an unknown/invalid TEID */
private function f_TC_deleteSession_unknown() runs on PGW_Session_CT {
- g_teic := f_gtp2_allocate_teid();
- g_teic_remote := f_rnd_octstring(4);
- f_delete_session(omit, '00000000'O, '40'O /* Context Unknown */);
+ g_pars.teic_remote := f_rnd_octstring(4);
+ f_delete_session(omit, Context_Not_Found, false);
setverdict(pass);
}
testcase TC_deleteSession_unknown() runs on PGW_Test_CT {
@@ -537,8 +1045,104 @@ testcase TC_deleteSession_unknown() runs on PGW_Test_CT {
vc_conn.done;
}
+/* Test charging over Gy interface. */
+private function f_TC_gy_charging_cc_time() runs on PGW_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);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), 0, 0);
+
+ d := activate(as_DIA_Gy_CCR(UPDATE_REQUEST));
+ f_ping4(mp_ping_hostname);
+ /* Let the CCA reach the PGW */
+ f_sleep(0.5);
+ deactivate(d);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), (28..1000), (28..1000));
+
+ as_DIA_Gy_CCR(UPDATE_REQUEST);
+ f_validate_gy_cc_report(g_rx_gy, VALIDITY_TIME, (3..4), ?, ?);
+
+ f_delete_session(omit, Request_accepted);
+ f_validate_gy_cc_report(g_rx_gy, FINAL, (0..1), 0, 0);
+ setverdict(pass);
+}
+testcase TC_gy_charging_cc_time() runs on PGW_Test_CT {
+ var PGW_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars('001010123456789'H, "tun23"));
+ 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_charging_cc_time), 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 PGW_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 PGW 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 PGW_Test_CT {
+ var PGW_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars('001010123456789'H, "tun23"));
+ 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 PGW_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 PGW_Test_CT {
+ var PGW_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars('001010123456789'H,
+ "tun22",
+ 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 PGW_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 PGW_Test_CT {
+ var PGW_Session_CT vc_conn;
+ var SessionPars pars := valueof(t_SessionPars('001010123456789'H,
+ "tun22",
+ 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() );
@@ -547,6 +1151,10 @@ control {
execute( TC_createSession_ping4_256() );
execute( TC_createSession_deleteSession() );
execute( TC_deleteSession_unknown() );
+ execute( TC_gy_charging_cc_time() );
+ execute( TC_gy_ccr_update_rejected() );
+ execute( TC_s2b_createSession_v4_noapco() );
+ execute( TC_s2b_createSession_v4_apco() );
}
diff --git a/pgw/expected-results.xml b/pgw/expected-results.xml
new file mode 100644
index 00000000..913f669f
--- /dev/null
+++ b/pgw/expected-results.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<testsuite name='Titan' tests='9' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='PGW_Tests' name='TC_tx_echo' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_createSession' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_createSession_ping4' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_createSession_ping4_256' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_createSession_deleteSession' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_deleteSession_unknown' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_gy_charging_cc_time' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_gy_ccr_update_rejected' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_s2b_createSession_v4_noapco' time='MASKED'/>
+ <testcase classname='PGW_Tests' name='TC_s2b_createSession_v4_apco' time='MASKED'/>
+</testsuite>
diff --git a/pgw/gen_links.sh b/pgw/gen_links.sh
index a0f12811..9bdface5 100755
--- a/pgw/gen_links.sh
+++ b/pgw/gen_links.sh
@@ -6,6 +6,7 @@ BASEDIR=../deps
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
@@ -32,6 +33,14 @@ 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
@@ -50,11 +59,12 @@ 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 PAP_Types.ttcn "
-FILES+="GTP_CodecPort.ttcn GTP_CodecPort_CtrlFunct.ttcn GTP_CodecPort_CtrlFunctDef.cc GTP_Templates.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+="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 DIAMETER_Templates.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 "
gen_links $DIR $FILES
ignore_pp_results
diff --git a/pgw/regen_makefile.sh b/pgw/regen_makefile.sh
index adb58206..2f58493e 100755
--- a/pgw/regen_makefile.sh
+++ b/pgw/regen_makefile.sh
@@ -1,7 +1,31 @@
#!/bin/bash
-FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc GTPC_EncDec.cc GTPU_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc GTPv2_CodecPort_CtrlFunctDef.cc ICMPv6_EncDec.cc IP_EncDec.cc Native_FunctionDefs.cc UDP_EncDec.cc ICMP_EncDec.cc "
-FILES+="UECUPS_CodecPort_CtrlFunctDef.cc "
-FILES+="DIAMETER_EncDec.cc DIAMETER_CodecPort_CtrlFunctDef.cc "
+NAME=PGW_Tests
-../regen-makefile.sh PGW_Tests.ttcn $FILES
+FILES="
+ *.ttcn
+ 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
+ UECUPS_CodecPort_CtrlFunctDef.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/regen-makefile.sh b/regen-makefile.sh
index a2aa946f..09088e0f 100755
--- a/regen-makefile.sh
+++ b/regen-makefile.sh
@@ -24,9 +24,6 @@
#
# See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=884303 for details.
#
-# The regexes below patch the generated Makefile to work on Debian 9 and
-# unstable, so far tested with TITAN 6.1.0, 6.2.0 and 6.3.0
-#
test -x "$(which ttcn3_makefilegen 2>/dev/null)" || { echo "ERROR: ttcn3_makefilegen not in PATH"; exit 1; }
@@ -40,27 +37,23 @@ if [ -z "$USE_CCACHE" ] && which ccache 2>/dev/null; then
USE_CCACHE=1
fi
-ttcn3_makefilegen -g -p -l -U 5 -f $*
-
-TITAN_VERSION=$(ttcn3_makefilegen -v 2>&1 |grep "Product number" |cut --delimiter="/" -f 2-| sed -e "s/[A-Z ]//g")
+ttcn3_makefilegen -g -p -l -U 8 -f $*
sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
-sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan /' Makefile
+sed -i -e 's/LDFLAGS = /LDFLAGS = -L \/usr\/lib\/titan/' Makefile
+sed -i -e 's/LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lsctp/' Makefile
#sed -i -e 's/TTCN3_LIB = ttcn3-parallel/TTCN3_LIB = ttcn3/' Makefile
# The -DMAKEDEPEND_RUN is a workaround for Debian packaging issue,
# see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=879816 for details
-if [ $(($TITAN_VERSION >= 65)) = 1 ]; then
- sed -i -e 's/CPPFLAGS = -D$(PLATFORM)/CPPFLAGS = -D$(PLATFORM) -DMAKEDEPEND_RUN -DUSE_SCTP/' Makefile
-else
- sed -i -e 's/CPPFLAGS = -D$(PLATFORM) -I$(TTCN3_DIR)\/include/CPPFLAGS = -D$(PLATFORM) -DMAKEDEPEND_RUN -DUSE_SCTP -I$(TTCN3_DIR)\/include -I\/usr\/include\/titan/' Makefile
-fi
+sed -i -e 's/CPPFLAGS = -D$(PLATFORM)/CPPFLAGS = -D$(PLATFORM) -DMAKEDEPEND_RUN -DUSE_SCTP -DLKSCTP_MULTIHOMING_ENABLED/' Makefile
#remove -Wall from CXXFLAGS: we're not interested in generic warnings for autogenerated code cluttering the logs
sed -i -e 's/-Wall//' Makefile
if [ "x$CPPFLAGS_TTCN3" != "x" ]; then
- sed -i -e 's/CPPFLAGS_TTCN3 =/CPPFLAGS_TTCN3 = '"$CPPFLAGS_TTCN3"'/' Makefile
+ CPPFLAGS_TTCN3="$(echo "$CPPFLAGS_TTCN3" | tr -d '\n' | tr '\t' ' ')"
+ sed -i -e "s/CPPFLAGS_TTCN3 =/CPPFLAGS_TTCN3 = $CPPFLAGS_TTCN3/" Makefile
fi
# for TITAN 6.3.0
diff --git a/remsim/REMSIM_Tests.default b/remsim/REMSIM_Tests.default
index 7a415555..3059a8d5 100644
--- a/remsim/REMSIM_Tests.default
+++ b/remsim/REMSIM_Tests.default
@@ -1,3 +1,3 @@
[TESTPORT_PARAMETERS]
system.HTTP.http_debugging := "yes"
-system.HTTP.use_notification_ASPs := "no"
+system.HTTP.use_notification_ASPs := "yes"
diff --git a/remsim/RSPRO.asn b/remsim/RSPRO.asn
index ce290033..5e2c05b6 100644
--- a/remsim/RSPRO.asn
+++ b/remsim/RSPRO.asn
@@ -15,10 +15,6 @@
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
--- You should have received a copy of the GNU General Public License along
--- with this program; if not, write to the Free Software Foundation, Inc.,
--- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
---
----------------------------------------------------------------------
RSPRO {} DEFINITIONS
@@ -91,6 +87,7 @@ ResultCode ::= ENUMERATED {
illegalSlotId (3),
unsupportedProtocolVersion (4),
unknownSlotmap (5),
+ identityInUse (6),
-- no card is present in given slot
cardNotPresent (100),
diff --git a/remsim/RSPRO_Server.ttcn b/remsim/RSPRO_Server.ttcn
index 635629fb..bb11689d 100644
--- a/remsim/RSPRO_Server.ttcn
+++ b/remsim/RSPRO_Server.ttcn
@@ -46,6 +46,7 @@ private altstep as_rspro_srv_Tguard() runs on rspro_server_CT {
altstep as_ignore_id_ack(integer i) runs on rspro_server_CT {
[] RSPRO_SRV[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) { repeat; }
+ [] RSPRO_SRV[i].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP)) { repeat; }
}
diff --git a/remsim/RemsimBankd_Tests.ttcn b/remsim/RemsimBankd_Tests.ttcn
index 47beedd4..a2686d30 100644
--- a/remsim/RemsimBankd_Tests.ttcn
+++ b/remsim/RemsimBankd_Tests.ttcn
@@ -35,11 +35,23 @@ modulepar {
/* We implement a RSPRO server to simulate the remsim-server and a
RSPRO client to simulate a remsim-client connecting to bankd */
type component bankd_test_CT extends rspro_server_CT, rspro_client_CT, VPCD_Adapter_CT {
+ timer g_T_guard := 60.0;
+}
+
+private altstep as_Tguard() runs on bankd_test_CT {
+ [] g_T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
}
private function f_init(boolean start_client := false) runs on bankd_test_CT {
var ComponentIdentity srv_comp_id := valueof(ts_CompId(remsimServer, "ttcn-server"));
+ /* Start the guard timer */
+ g_T_guard.start;
+ activate(as_Tguard());
+
f_rspro_srv_init(0, mp_server_ip, mp_server_port, srv_comp_id);
if (start_client) {
diff --git a/remsim/RemsimClient_Tests.ttcn b/remsim/RemsimClient_Tests.ttcn
index 499fd3e8..219573cb 100644
--- a/remsim/RemsimClient_Tests.ttcn
+++ b/remsim/RemsimClient_Tests.ttcn
@@ -15,6 +15,7 @@ module RemsimClient_Tests {
import from Native_Functions all;
import from Osmocom_Types all;
import from IPA_Emulation all;
+import from Misc_Helpers all;
/* the PIPEasp port allows us to interact with osmo-remsim-client-shell via stdin/stdout */
import from PIPEasp_PortType all;
@@ -33,12 +34,24 @@ modulepar {
type component client_test_CT extends rspro_server_CT {
port PIPEasp_PT PIPE;
var ComponentIdentity g_srv_comp_id, g_bankd_comp_id;
+ timer g_T_guard := 60.0;
};
+private altstep as_Tguard() runs on client_test_CT {
+ [] g_T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+}
+
private function f_init() runs on client_test_CT {
g_srv_comp_id := valueof(ts_CompId(remsimServer, "ttcn-server"));
g_bankd_comp_id := valueof(ts_CompId(remsimBankd, "ttcn-bankd"));
+ /* Start the guard timer */
+ g_T_guard.start;
+ activate(as_Tguard());
+
f_rspro_srv_init(0, mp_server_ip, mp_server_port, g_srv_comp_id);
f_rspro_srv_init(1, mp_bankd_ip, mp_bankd_port, g_bankd_comp_id, exp_connect := false);
}
@@ -286,8 +299,8 @@ function f_xceive_apdus(ClientSlot cslot, BankSlot bslot,
integer count := 100, integer i := 0) runs on client_test_CT
{
for (var integer j := 0; j < count; j := j+1) {
- var octetstring c_apdu := f_rnd_octstring(f_rnd_int(270));
- var octetstring r_apdu := f_rnd_octstring(f_rnd_int(270));
+ var octetstring c_apdu := f_rnd_octstring_rnd_len(270);
+ var octetstring r_apdu := f_rnd_octstring_rnd_len(270);
f_client2bank(cslot, bslot, c_apdu, i:=i);
f_bank2client(bslot, cslot, r_apdu, i:=i);
}
@@ -332,8 +345,8 @@ testcase TC_pipe_apdu_wrong_cslot() runs on client_test_CT {
f_set_atr(cslot, '3B9F96801FC78031A073BE21136743200718000001A5'O, i:=1);
- var octetstring c_apdu := f_rnd_octstring(f_rnd_int(270));
- var octetstring r_apdu := f_rnd_octstring(f_rnd_int(270));
+ var octetstring c_apdu := f_rnd_octstring_rnd_len(270);
+ var octetstring r_apdu := f_rnd_octstring_rnd_len(270);
/* Send C-APDU from correct ClientId/Slot to simulated bankd */
f_client2bank(cslot, bslot, c_apdu, i:=1);
/* respond with R-APDU from correct bankId/Slot but stating wrong ClientId */
@@ -359,8 +372,8 @@ testcase TC_pipe_apdu_wrong_bslot() runs on client_test_CT {
f_set_atr(cslot, '3B9F96801FC78031A073BE21136743200718000001A5'O, i:=1);
- var octetstring c_apdu := f_rnd_octstring(f_rnd_int(270));
- var octetstring r_apdu := f_rnd_octstring(f_rnd_int(270));
+ var octetstring c_apdu := f_rnd_octstring_rnd_len(270);
+ var octetstring r_apdu := f_rnd_octstring_rnd_len(270);
/* Send C-APDU from correct ClientId/Slot to simulated bankd */
f_client2bank(cslot, bslot, c_apdu, i:=1);
/* respond with R-APDU from wrong bankId but stating correct ClientId */
diff --git a/remsim/RemsimServer_Tests.ttcn b/remsim/RemsimServer_Tests.ttcn
index 1ca5ce95..6d2b27d4 100644
--- a/remsim/RemsimServer_Tests.ttcn
+++ b/remsim/RemsimServer_Tests.ttcn
@@ -20,94 +20,14 @@ import from RSRES all;
import from RSPRO_Types all;
import from REMSIM_Tests all;
+import from Misc_Helpers all;
import from IPA_Emulation all;
import from HTTPmsg_Types all;
import from HTTPmsg_PortType all;
+import from HTTP_Adapter all;
import from JSON_Types all;
-type component http_CT {
- port HTTPmsg_PT HTTP;
- var charstring g_http_host;
- var integer g_http_port;
-};
-
-function f_http_init(charstring host, integer http_port) runs on http_CT {
- map(self:HTTP, system:HTTP);
- g_http_host := host;
- g_http_port := http_port;
-}
-
-template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
- template (value) integer http_port := 80,
- template (value) boolean use_ssl := false) := {
- hostname := hostname,
- portnumber := http_port,
- use_ssl := use_ssl
-}
-template (value) Close ts_HTTP_Close := { client_id := omit };
-
-template (value) HeaderLines ts_HTTP_Header(charstring body) := {
- { header_name := "Content-Type", header_value := "application/json" },
- { header_name := "Content-Length", header_value := int2str(lengthof(body)) }
-}
-
-template (value) HTTPMessage ts_HTTP_Req(charstring url,
- charstring method := "GET",
- charstring body := "",
- integer v_maj := 1, integer v_min := 1) := {
- request := {
- client_id := omit,
- method := method,
- uri := url,
- version_major := v_maj,
- version_minor := v_min,
- header := ts_HTTP_Header(body),
- body := body
- }
-}
-
-template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
- response := {
- client_id := ?,
- version_major := ?,
- version_minor := ?,
- statuscode := sts,
- statustext := ?,
- header := ?,
- body := ?
- }
-};
-
-template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
-
-/* run a HTTP request and return the response */
-function f_http_transact(charstring url, charstring method := "GET",
- charstring body := "", template HTTPMessage exp := tr_HTTP_Resp2xx)
-runs on http_CT return HTTPMessage {
- var HTTPMessage resp;
- timer T := 2.0;
-
- HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
- //HTTP.receive(Connect_result:?);
- HTTP.send(ts_HTTP_Req(url, method, body));
- T.start;
- alt {
- [] HTTP.receive(exp) -> value resp {
- setverdict(pass);
- }
- [] HTTP.receive(tr_HTTP_Resp) -> value resp {
- setverdict(fail, "Unexpected HTTP response ", resp);
- }
- [] T.timeout {
- setverdict(fail, "Timeout waiting for HTTP response");
- self.stop;
- }
- }
- HTTP.send(ts_HTTP_Close);
- return resp;
-}
-
/* run a HTTP GET on specified URL expecting json in RSRES format as response */
function f_rsres_get(charstring url, template integer exp_sts := 200)
runs on http_CT return JsRoot {
@@ -153,13 +73,28 @@ function f_rsres_init() runs on http_CT {
}
type component test_CT extends rspro_client_CT, http_CT {
+ timer g_T_guard := 60.0;
};
+private altstep as_Tguard() runs on test_CT {
+ [] g_T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+}
+
+private function f_init() runs on test_CT {
+ /* Start the guard timer */
+ g_T_guard.start;
+ activate(as_Tguard());
+}
-testcase TC_connect_and_nothing() runs on rspro_client_CT {
+
+testcase TC_connect_and_nothing() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
timer T := 20.0;
+ f_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
T.start;
/* expect that we're disconnected if we never send a ConnectClientReq */
@@ -178,6 +113,7 @@ testcase TC_connect_client() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
var JsRoot js;
+ f_init();
f_rsres_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
@@ -197,10 +133,74 @@ testcase TC_connect_client() runs on test_CT {
setverdict(pass);
}
+/* duplicate connection from Same Client/Slot ID */
+testcase TC_connect_client_duplicate() runs on test_CT {
+ var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
+ var JsRoot js;
+
+ f_init();
+ f_rsres_init();
+ f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
+ rspro[0].rspro_client_slot := valueof(ts_ClientSlot(13,1));
+
+ js := f_rsres_get("/api/backend/v1/clients");
+ if (not match(js.clients, JsClients:{})) {
+ setverdict(fail, "Initial state not empty");
+ mtc.stop;
+ }
+ f_rspro_connect_client(0);
+ js := f_rsres_get("/api/backend/v1/clients");
+ if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
+ setverdict(fail, "Non-matching JSON response");
+ mtc.stop;
+ }
+
+ /* connect a second time for same Client ID */
+ f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_id, 1);
+ rspro[1].rspro_client_slot := valueof(ts_ClientSlot(13,1));
+ f_rspro_connect_client(1, identityInUse);
+ f_rspro_exp_disconnect(1);
+
+ /* expect the first connection still to be active */
+ js := f_rsres_get("/api/backend/v1/clients");
+ if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
+ setverdict(fail, "Non-matching JSON response");
+ mtc.stop;
+ }
+
+ setverdict(pass);
+}
+
testcase TC_connect_bank() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
var JsRoot js;
+ f_init();
+ f_rsres_init();
+ f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
+ rspro[0].rspro_bank_id := 1;
+ rspro[0].rspro_bank_nslots := 8;
+
+ js := f_rsres_get("/api/backend/v1/banks");
+ if (not match(js.banks, JsBanks:{})) {
+ setverdict(fail, "Initial state not empty");
+ mtc.stop;
+ }
+ f_rspro_connect_client(0);
+ js := f_rsres_get("/api/backend/v1/banks");
+ if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
+ rspro[0].rspro_bank_nslots))) {
+ setverdict(fail, "Non-matching JSON response");
+ mtc.stop;
+ }
+ setverdict(pass);
+}
+
+testcase TC_connect_bank_duplicate() runs on test_CT {
+ var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
+ var JsRoot js;
+
+ f_init();
f_rsres_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_bank_id := 1;
@@ -218,9 +218,28 @@ testcase TC_connect_bank() runs on test_CT {
setverdict(fail, "Non-matching JSON response");
mtc.stop;
}
+
+ /* connect a second time for same Bank ID */
+ f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_id, 1);
+ rspro[1].rspro_bank_id := 1;
+ rspro[1].rspro_bank_nslots := 23;
+ f_rspro_connect_client(1, identityInUse);
+
+ /* expect only the first bank to survive */
+ js := f_rsres_get("/api/backend/v1/banks");
+ if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
+ rspro[0].rspro_bank_nslots))) {
+ setverdict(fail, "Non-matching JSON response");
+ mtc.stop;
+ }
+
+ /* wait for T2/rejected timer to expire in server */
+ f_sleep(2.0);
+
setverdict(pass);
}
+
function f_ensure_slotmaps(template JsSlotmaps maps)
runs on http_CT {
var JsRoot js;
@@ -251,6 +270,7 @@ runs on http_CT {
/* test adding a single slotmap */
testcase TC_slotmap_add() runs on test_CT {
+ f_init();
f_rsres_init();
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
@@ -262,6 +282,7 @@ testcase TC_slotmap_add() runs on test_CT {
/* test adding a single slotmap with out-of-range values */
testcase TC_slotmap_add_out_of_range() runs on test_CT {
+ f_init();
f_rsres_init();
var HTTPMessage http_resp;
@@ -287,6 +308,8 @@ testcase TC_slotmap_add_out_of_range() runs on test_CT {
/* test adding a slotmap and then connecting a client + bankd */
testcase TC_slotmap_add_conn_cl_b() runs on test_CT {
+ f_init();
+
/* Simulate one client */
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
@@ -330,6 +353,8 @@ testcase TC_slotmap_add_conn_cl_b() runs on test_CT {
/* test connecting a client and later adding a slotmap for it */
testcase TC_conn_cl_b_slotmap_add() runs on test_CT {
+ f_init();
+
/* Simulate one client */
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
@@ -373,6 +398,7 @@ testcase TC_conn_cl_b_slotmap_add() runs on test_CT {
/* simple delete of a 'NEW' slotmap */
testcase TC_slotmap_del_new() runs on test_CT {
+ f_init();
f_rsres_init();
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
@@ -384,6 +410,7 @@ testcase TC_slotmap_del_new() runs on test_CT {
/* simple delete of a non-existant slotmap */
testcase TC_slotmap_del_nonexistant() runs on test_CT {
+ f_init();
f_rsres_init();
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(11,12), ts_ClientSlot(13,14)));
@@ -395,6 +422,8 @@ testcase TC_slotmap_del_nonexistant() runs on test_CT {
/* simple delete of a 'UNACKNOWLEDGED' slotmap */
testcase TC_slotmap_del_unack() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
+
+ f_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_bank_id := 1;
rspro[0].rspro_bank_nslots := 8;
@@ -428,6 +457,8 @@ testcase TC_slotmap_del_unack() runs on test_CT {
/* simple delete of a 'ACTIVE' slotmap from server + bankd */
testcase TC_slotmap_del_active() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
+
+ f_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_bank_id := 1;
rspro[0].rspro_bank_nslots := 8;
@@ -467,6 +498,8 @@ testcase TC_slotmap_del_active() runs on test_CT {
/* simple delete of a 'ACTIVE' slotmap from client */
testcase TC_slotmap_del_active_client() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
+
+ f_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_bank_id := 1;
rspro[0].rspro_bank_nslots := 8;
@@ -519,6 +552,8 @@ testcase TC_slotmap_del_active_client() runs on test_CT {
/* Add a slotmap to a currently active bank */
testcase TC_slotmap_add_active_bank() runs on test_CT {
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
+
+ f_init();
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
rspro[0].rspro_bank_id := 1;
rspro[0].rspro_bank_nslots := 8;
@@ -555,7 +590,9 @@ testcase TC_slotmap_add_active_bank() runs on test_CT {
control {
execute( TC_connect_and_nothing() );
execute( TC_connect_client() );
+ execute( TC_connect_client_duplicate() );
execute( TC_connect_bank() );
+ execute( TC_connect_bank_duplicate() );
execute( TC_slotmap_add() );
execute( TC_slotmap_add_conn_cl_b() );
execute( TC_slotmap_add_out_of_range() );
diff --git a/remsim/gen_links.sh b/remsim/gen_links.sh
index 995abfb0..b25375b5 100755
--- a/remsim/gen_links.sh
+++ b/remsim/gen_links.sh
@@ -42,6 +42,7 @@ FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Osmocom_T
FILES+="IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp IPA_CodecPort.ttcn " #RSL_Types.ttcn RSL_Emulation.ttcn "
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="HTTP_Adapter.ttcn "
FILES+="VPCD_Types.ttcn VPCD_CodecPort.ttcn VPCD_CodecPort_CtrlFunct.ttcn VPCD_CodecPort_CtrlFunctDef.cc
VPCD_Adapter.ttcn "
gen_links $DIR $FILES
diff --git a/remsim/regen_makefile.sh b/remsim/regen_makefile.sh
index 3f19228f..fb04cce8 100755
--- a/remsim/regen_makefile.sh
+++ b/remsim/regen_makefile.sh
@@ -1,10 +1,33 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp *.asn IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc TELNETasp_PT.cc Native_FunctionDefs.cc RSPRO_EncDec.cc Abstract_Socket.cc HTTPmsg_PT.cc HTTPmsg_MessageLen_Function.cc JSON_EncDec.cc VPCD_CodecPort_CtrlFunctDef.cc PIPEasp_PT.cc "
+NAME=REMSIM_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSPRO -DIPA_EMULATION_CTRL"
+FILES="
+ *.asn
+ *.ttcn
+ *.ttcnpp
+ Abstract_Socket.cc
+ HTTPmsg_MessageLen_Function.cc
+ HTTPmsg_PT.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ JSON_EncDec.cc
+ Native_FunctionDefs.cc
+ PIPEasp_PT.cc
+ RSPRO_EncDec.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ VPCD_CodecPort_CtrlFunctDef.cc
+"
-../regen-makefile.sh REMSIM_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_RSPRO
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES
# required for forkpty(3) used by PIPEasp
sed -i -e '/^LINUX_LIBS/ s/$/ -lutil/' Makefile
diff --git a/sccp/SCCP_Tests_RAW.ttcn b/sccp/SCCP_Tests_RAW.ttcn
index 7d44eb42..5849dad3 100644
--- a/sccp/SCCP_Tests_RAW.ttcn
+++ b/sccp/SCCP_Tests_RAW.ttcn
@@ -69,6 +69,18 @@ function f_init_vty() runs on SCCP_Test_RAW_CT {
"sccp-timer iar " & int2str(g_demo_sccp_timer_iar)});
}
+function f_vty_cmd_connect_req(integer conn_id) runs on SCCP_Test_RAW_CT {
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "sccp-user");
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "connect-req " & int2str(conn_id));
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "end");
+}
+
+function f_vty_cmd_disconnect_req(integer conn_id) runs on SCCP_Test_RAW_CT {
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "sccp-user");
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "disconnect-req " & int2str(conn_id));
+ f_vty_transceive(SCCP_DEMO_USER_VTY, "end");
+}
+
private function f_init_raw(SCCP_Configuration cfg) runs on SCCP_Test_RAW_CT {
g_param := {
sio := {
@@ -178,11 +190,11 @@ testcase TC_cr_cc() runs on SCCP_Test_RAW_CT {
}
/* Verify sccp_demo_user inactivty timers are not armed upon dealing with
-/* connectionless data-unit messages. Since no connection exists. */
+ * connectionless data-unit messages. Since no connection exists. */
testcase TC_udt_without_cr_cc() runs on SCCP_Test_RAW_CT {
var SCCP_PAR_Address calling, called;
var SCCP_MTP3_TRANSFERind rx;
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
/* Keep recommended ratio of T(iar) >= T(ias)*2, but anyway no IT
should be received in this case. */
@@ -215,7 +227,7 @@ testcase TC_udt_without_cr_cc() runs on SCCP_Test_RAW_CT {
testcase TC_tiar_timeout() runs on SCCP_Test_RAW_CT {
var SCCP_PAR_Address calling, called;
var OCT3 remote_lref;
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
/* Set T(iar) in sccp_demo_user low enough that it will trigger before other side
has time to keep alive with a T(ias). Keep recommended ratio of
@@ -248,6 +260,7 @@ testcase TC_it_avoids_tiar() runs on SCCP_Test_RAW_CT {
var SCCP_PAR_Address calling, called;
var OCT3 remote_lref;
var boolean it_received := false;
+ var SCCP_MTP3_TRANSFERind rx;
g_demo_sccp_timer_ias := 1;
g_demo_sccp_timer_iar := 3;
@@ -273,6 +286,10 @@ testcase TC_it_avoids_tiar() runs on SCCP_Test_RAW_CT {
setverdict(fail, "Unexpected SCCP RLSD received");
self.stop;
}
+ [] MTP3.receive(tr_SCCP_MTP3_TRANSFERind(*)) -> value rx {
+ setverdict(fail, "Unexpected MTP/SCCP TRANSFERind received: ", rx);
+ self.stop;
+ }
[] MTP3.receive {
setverdict(fail, "Unexpected MTP/SCCP received");
self.stop;
@@ -310,11 +327,219 @@ testcase TC_it_avoids_tiar() runs on SCCP_Test_RAW_CT {
}
}
+private function f_tx_xudt_exp(SCCP_PAR_Address calling, SCCP_PAR_Address called, octetstring data) runs on SCCP_Test_RAW_CT {
+ var template PDU_SCCP exp_rx;
+ f_send_sccp(ts_SCCP_XUDT(calling, called, data));
+ exp_rx := (tr_SCCP_UDT(called, calling, data), tr_SCCP_XUDT(called, calling, data));
+ f_exp_sccp(exp_rx);
+}
+
+/* Test if the IUT SCCP code processes an XUDT [treat it like UDT] and answers back. */
+testcase TC_process_rx_xudt() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var octetstring data := f_rnd_octstring_rnd_len(100);
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ /* Make sure an XUDT is echoed back just like an UDT */
+ f_tx_xudt_exp(calling, called, data);
+ setverdict(pass);
+}
+
+private function f_tx_ludt_exp(SCCP_PAR_Address calling, SCCP_PAR_Address called, octetstring data) runs on SCCP_Test_RAW_CT {
+ var template PDU_SCCP exp_rx;
+ f_send_sccp(ts_SCCP_LUDT(calling, called, data));
+ exp_rx := tr_SCCP_LUDT(called, calling, data);
+ f_exp_sccp(exp_rx);
+}
+
+/* Test if the IUT SCCP code processes a LUDT [treat it like UDT] and answers back. */
+testcase TC_process_rx_ludt() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var octetstring data := f_rnd_octstring(1000);
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ /* Make sure an LUDT is echoed back just like an UDT */
+ f_tx_ludt_exp(calling, called, data);
+ setverdict(pass);
+}
+
+function f_scmg_xceive(SCCP_PAR_Address calling, SCCP_PAR_Address called,
+ template (value) PDU_SCMG_message tx,
+ template (omit) PDU_SCMG_message rx_exp,
+ boolean accept_other_called_resp := false) runs on SCCP_Test_RAW_CT
+{
+ var boolean exp_something := true;
+ var SCCP_MTP3_TRANSFERind rx;
+ timer T := 5.0;
+
+ if (istemplatekind(rx_exp, "omit")) {
+ exp_something := false;
+ }
+
+ MTP3.clear;
+ f_send_sccp(ts_SCCP_UDT(calling, called, enc_PDU_SCMG_message(valueof(tx))));
+ T.start;
+ alt {
+ [exp_something] MTP3.receive(tr_SCCP_MTP3_TRANSFERind(tr_SCCP_UDT(called, calling, decmatch rx_exp))) {
+ setverdict(pass);
+ }
+ [exp_something and accept_other_called_resp] MTP3.receive(tr_SCCP_MTP3_TRANSFERind(tr_SCCP_UDT(called, ?, decmatch rx_exp))) {
+ setverdict(pass);
+ }
+ [] MTP3.receive(tr_SCCP_MTP3_TRANSFERind(tr_SCCP_UDT(called, calling, ?))) -> value rx {
+ setverdict(fail, "Received unexpected SCCP/MTP3 TRANSFERind (specific): ", rx, " but waiting for (specific) ", rx_exp);
+ }
+ [] MTP3.receive(tr_SCCP_MTP3_TRANSFERind(*)) -> value rx {
+ setverdict(fail, "Received unexpected SCCP/MTP3 TRANSFERind (*): ", rx, " but waiting for ", rx_exp);
+ }
+ [] MTP3.receive {
+ setverdict(fail, "Received unexpected waiting for ", rx_exp);
+ }
+ [exp_something] T.timeout {
+ setverdict(fail, "Timeout waiting for ", rx_exp);
+ }
+ [not exp_something] T.timeout {
+ setverdict(pass);
+ }
+ }
+
+}
+
+/* Test is SST(SSN=1) returns SSA */
+testcase TC_scmg_sst_ssn1() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var template (value) PDU_SCMG_message tx;
+ var template (present) PDU_SCMG_message rx_exp;
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ tx := ts_SCMG_SST(1, mp_sccp_cfg[0].peer_pc);
+ rx_exp := ts_SCMG_SSA(1, mp_sccp_cfg[0].peer_pc);
+ f_scmg_xceive(calling, called, tx, rx_exp);
+}
+
+/* Test is SST(SSN=valid) returns SSA */
+testcase TC_scmg_sst_ssn_valid() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var template (value) PDU_SCMG_message tx;
+ var template (present) PDU_SCMG_message rx_exp;
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ tx := ts_SCMG_SST(mp_sccp_cfg[0].peer_ssn, mp_sccp_cfg[0].peer_pc);
+ rx_exp := ts_SCMG_SSA(mp_sccp_cfg[0].peer_ssn, mp_sccp_cfg[0].peer_pc);
+ f_scmg_xceive(calling, called, tx, rx_exp);
+}
+
+
+/* Test is SST(SSN=invalid) returns nothing */
+testcase TC_scmg_sst_ssn_invalid() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var template (value) PDU_SCMG_message tx;
+ var template (omit) PDU_SCMG_message rx_exp;
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+ calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, 1,
+ mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
+
+ tx := ts_SCMG_SST(123, mp_sccp_cfg[0].peer_pc);
+ rx_exp := omit;
+ f_scmg_xceive(calling, called, tx, rx_exp);
+}
+
+/* Test CallingParty(only SSN) solicits response (OS#5146) */
+testcase TC_callingparty_ssn_only() runs on SCCP_Test_RAW_CT {
+ var SCCP_PAR_Address calling, called;
+ var template (value) PDU_SCMG_message tx;
+ var template (present) PDU_SCMG_message rx_exp;
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ called := valueof(ts_SccpAddr_SSN(1));
+ calling := valueof(ts_SccpAddr_SSN(1));
+
+ tx := ts_SCMG_SST(1, mp_sccp_cfg[0].peer_pc);
+ rx_exp := ts_SCMG_SSA(1, mp_sccp_cfg[0].peer_pc);
+ f_scmg_xceive(calling, called, tx, rx_exp, accept_other_called_resp:=true);
+}
+
+
+/* Test user initiating a conn (eg RUA), which triggers SCCP CR. While waiting
+ * for CC, user decides it timed out (eg. RUA side timeout) which makes it move to
+ * WAIT_CONN_CONF state. In that state, wait for CC and then submit an RLSD and
+ * wait for ack. */
+testcase TC_cr_timeout_cc_too_late() runs on SCCP_Test_RAW_CT {
+ var SCCP_MTP3_TRANSFERind mtp3_rx;
+ var integer conn_id := 1234;
+ var OCT3 remote_lref;
+
+ f_init_raw(mp_sccp_cfg[0]);
+ f_sleep(1.0);
+
+ f_vty_cmd_connect_req(conn_id);
+ mtp3_rx := f_exp_sccp(tr_SCCP_CR(?, ?, ?));
+
+ /* Emulate disconnection from the user: */
+ f_vty_cmd_disconnect_req(conn_id);
+ remote_lref := mtp3_rx.data.connrequest.sourceLocRef;
+
+ /* Now send CC, user should send RLSD to us: */
+ f_send_sccp(ts_SCCP_CC(g_own_lref, remote_lref));
+ log("Waiting for RLSD");
+ /* Cause set hardcoded by osmo_sccp_demo_user VTY code, nothing to test here: */
+ var template (present) integer cause := ?;
+ f_exp_sccp(tr_SCCP_RLSD(remote_lref, g_own_lref, cause));
+ f_send_sccp(ts_SCCP_RLC(g_own_lref, remote_lref));
+
+ setverdict(pass);
+}
+
+
control {
execute( TC_cr_cc() );
execute( TC_udt_without_cr_cc() );
execute( TC_tiar_timeout() );
execute( TC_it_avoids_tiar() );
+ execute( TC_process_rx_xudt() );
+ execute( TC_process_rx_ludt() );
+
+ execute( TC_scmg_sst_ssn1() );
+ execute( TC_scmg_sst_ssn_valid() );
+ execute( TC_scmg_sst_ssn_invalid() );
+
+ execute( TC_callingparty_ssn_only() );
+ execute( TC_cr_timeout_cc_too_late() );
}
diff --git a/sccp/regen_makefile.sh b/sccp/regen_makefile.sh
index 08db33e1..7cd809d1 100755
--- a/sccp/regen_makefile.sh
+++ b/sccp/regen_makefile.sh
@@ -1,7 +1,27 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc SCTPasp_PT.cc TCCConversion.cc TCCInterface.cc UD_PT.cc IPL4asp_PT.cc IPL4asp_discovery.cc IPA_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc TCCEncoding.cc "
+NAME=SCCP_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_CTRL -DIPA_EMULATION_SCCP -DUSE_MTP3_DISTRIBUTOR"
+FILES="
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ SCCP_EncDec.cc
+ SCTPasp_PT.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+ UD_PT.cc
+"
-../regen-makefile.sh SCCP_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_SCCP
+ -DUSE_MTP3_DISTRIBUTOR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/selftest/gen_links.sh b/selftest/gen_links.sh
index fd64a485..1a3bbe1b 100755
--- a/selftest/gen_links.sh
+++ b/selftest/gen_links.sh
@@ -39,7 +39,7 @@ FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn BSSAP_CodecPort.ttcn Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn GSUP_Types.ttcn"
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn GSM_RestOctets.ttcn RSL_Types.ttcn BSSAP_CodecPort.ttcn Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn PCO_Types.ttcn GSUP_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc"
gen_links $DIR $FILES
ignore_pp_results
diff --git a/selftest/regen_makefile.sh b/selftest/regen_makefile.sh
index 9d302acc..383e2db7 100755
--- a/selftest/regen_makefile.sh
+++ b/selftest/regen_makefile.sh
@@ -1,9 +1,22 @@
#!/bin/sh
-MAIN=Selftest.ttcn
+NAME=Selftest
-FILES="*.ttcn *.ttcnpp IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc"
+FILES="
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCInterface.cc
+"
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSL -DIPA_EMULATION_CTRL -DUSE_MTP3_DISTRIBUTOR"
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_RSL
+ -DUSE_MTP3_DISTRIBUTOR
+"
-../regen-makefile.sh $MAIN $FILES
+../regen-makefile.sh -e $NAME $FILES
diff --git a/sgsn/SGSN_Tests.cfg b/sgsn/SGSN_Tests.cfg
index 51677502..4f92ac2a 100644
--- a/sgsn/SGSN_Tests.cfg
+++ b/sgsn/SGSN_Tests.cfg
@@ -14,16 +14,43 @@
[MODULE_PARAMETERS]
SGSN_Tests.mp_nsconfig := {
{
- local_ip := "127.0.0.103",
- remote_ip := "127.0.0.10"
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
},
{
- local_ip := "127.0.0.103",
- remote_ip := "127.0.0.10"
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
},
{
- local_ip := "127.0.0.103",
- remote_ip := "127.0.0.10"
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
}
}
SGSN_Tests.mp_ranap_cfg := {
@@ -38,3 +65,5 @@ SGSN_Tests.mp_ggsn_ip := "127.0.0.103"
[EXECUTE]
SGSN_Tests.control
+SGSN_Tests_Iu.control
+SGSN_Tests_NS.control
diff --git a/sgsn/SGSN_Tests.ttcn b/sgsn/SGSN_Tests.ttcn
index 0e656a3e..67e815b7 100644
--- a/sgsn/SGSN_Tests.ttcn
+++ b/sgsn/SGSN_Tests.ttcn
@@ -12,9 +12,11 @@ module SGSN_Tests {
*/
friend module SGSN_Tests_Iu;
+friend module SGSN_Tests_NS;
import from General_Types all;
import from Osmocom_Types all;
+import from GSM_Types all;
import from Native_Functions all;
import from NS_Types all;
import from NS_Emulation all;
@@ -29,8 +31,9 @@ import from MobileL3_Types all;
import from L3_Templates all;
import from L3_Common all;
-import from GSUP_Emulation all;
import from GSUP_Types all;
+import from GSUP_Templates all;
+import from GSUP_Emulation all;
import from IPA_Emulation all;
import from RAN_Adapter all;
@@ -39,11 +42,13 @@ import from RANAP_Templates all;
import from RANAP_PDU_Descriptions all;
import from RANAP_IEs all;
-import from GTP_Emulation all;
-import from GTP_Templates all;
-import from GTP_CodecPort all;
+import from GTPv1C_CodecPort all;
+import from GTPv1U_CodecPort all;
import from GTPC_Types all;
import from GTPU_Types all;
+import from GTPv1C_Templates all;
+import from GTPv1U_Templates all;
+import from GTP_Emulation all;
import from LLC_Types all;
import from LLC_Templates all;
@@ -53,8 +58,6 @@ import from SNDCP_Types all;
import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;
-import from GSM_RR_Types all;
-
import from MobileL3_MM_Types all;
@@ -62,39 +65,73 @@ modulepar {
/* IP/port on which we run our internal GSUP/HLR emulation */
charstring mp_hlr_ip := "127.0.0.1";
integer mp_hlr_port := 4222;
- charstring mp_ggsn_ip := "127.0.0.2";
+ charstring mp_ggsn_ip := "127.0.0.103";
integer mp_echo_interval := 5; /* in seconds. Only used in test enabling g_use_echo */
+ charstring mp_sgsn_gtp_ip := "127.0.0.10";
NSConfigurations mp_nsconfig := {
{
- local_udp_port := 21010,
- local_ip := "127.0.0.1",
- remote_udp_port := 23000,
- remote_ip := "127.0.0.1",
- nsvci := 97,
nsei := 96,
role_sgsn := false,
- handle_sns := false
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21010,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 97
+ }
+ }
},
{
- local_udp_port := 21011,
- local_ip := "127.0.0.1",
- remote_udp_port := 23000,
- remote_ip := "127.0.0.1",
- nsvci := 98,
nsei := 97,
role_sgsn := false,
- handle_sns := false
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21011,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 98
+ }
+ }
},
{
- local_udp_port := 21012,
- local_ip := "127.0.0.1",
- remote_udp_port := 23000,
- remote_ip := "127.0.0.1",
- nsvci := 99,
nsei := 98,
role_sgsn := false,
- handle_sns := false
+ handle_sns := false,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_udp_port := 21012,
+ local_ip := "127.0.0.1",
+ remote_udp_port := 23000,
+ remote_ip := "127.0.0.1",
+ data_weight := 1,
+ signalling_weight := 1
+ }
+ },
+ nsvci := 99
+ }
+ }
}
};
@@ -113,9 +150,11 @@ modulepar {
}
};
+const integer NUM_BVC_PER_NSE := 1;
type record GbInstance {
NS_CT vc_NS,
BSSGP_CT vc_BSSGP,
+ BSSGP_BVC_CT vc_BSSGP_BVC[NUM_BVC_PER_NSE],
BssgpConfig cfg
};
@@ -137,6 +176,13 @@ type component test_CT {
/* only to get events from IPA underneath GSUP */
port IPA_CTRL_PT GSUP_IPA_EVENT;
+ /* only needed at start to get the per-BVC references */
+ port BSSGP_CT_PROC_PT PROC;
+
+ /* used by RIM related test */
+ port BSSGP_PT RIM[NUM_GB];
+ port GTPEM_PT GTPC;
+
var GTP_Emulation_CT vc_GTP;
port TELNETasp_PT SGSNVTY;
@@ -182,6 +228,12 @@ type record BSSGP_ConnHdlrPars {
SCCP_PAR_Address sccp_addr_peer optional
};
+/* Passed in RAN-INFO message from emulated neighbor using RIM */
+const octetstring si1_default := '198fb100000000000000000000000000007900002b'O;
+const octetstring si3_default := '1b753000f110236ec9033c2747407900003c0b2b2b'O;
+const octetstring si13_default := '009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b'O;
+const octetstring si_default := si1_default & si3_default & si13_default;
+
private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
/* mcc_mnc is encoded as of 24.008 10.5.5.15 */
var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
@@ -193,22 +245,34 @@ private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdent
mncDigit3 := mcc_mnc[3],
mncDigit1 := mcc_mnc[4],
mncDigit2 := mcc_mnc[5],
- lac := int2oct(cell_id.ra_id.lai.lac, 16),
- rac := int2oct(cell_id.ra_id.rac, 8)
+ lac := int2oct(cell_id.ra_id.lai.lac, 2),
+ rac := int2oct(cell_id.ra_id.rac, 1)
}
return ret;
};
+private function f_BssgpCellId_to_GTP_CellId(in BssgpCellId cell_id) return GTP_CellId
+{
+ template (value) GTP_CellId ret := ts_GTP_CellId(cell_id.ra_id, cell_id.cell_id);
+ return valueof(ret);
+}
+
private function f_init_gb(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
- gb.vc_NS := NS_CT.create(id & "-NS" & int2str(offset));
- gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP" & int2str(offset));
+ gb.vc_NS := NS_CT.create(id & "-NS" & int2str(offset)) alive;
+ gb.vc_BSSGP := BSSGP_CT.create(id & "-BSSGP" & int2str(offset)) alive;
/* connect lower end of BSSGP emulation with NS upper port */
connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
- /* connect lower end of NS emulation to NS codec port (on top of IPL4) */
- map(gb.vc_NS:NSCP, system:NS_CODEC_PORT);
gb.vc_NS.start(NSStart(mp_nsconfig[offset]));
- gb.vc_BSSGP.start(BssgpStart(gb.cfg));
+ gb.vc_BSSGP.start(BssgpStart(gb.cfg, testcasename()));
+ /* resolve the per-BVC component references */
+ for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i+1) {
+ connect(self:PROC, gb.vc_BSSGP:PROC);
+ gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
+ disconnect(self:PROC, gb.vc_BSSGP:PROC);
+ }
+ /* connect RIM related port */
+ connect(gb.vc_BSSGP:RIM, self:RIM[offset]);
}
private function f_init_gsup(charstring id) runs on test_CT {
@@ -255,7 +319,7 @@ private function f_init_gtp(charstring id) runs on test_CT {
vc_GTP.start(GTP_Emulation.main(gtp_cfg));
}
-private function f_init_vty() runs on test_CT {
+friend function f_init_vty() runs on test_CT {
map(self:SGSNVTY, system:SGSNVTY);
f_vty_set_prompts(SGSNVTY);
f_vty_transceive(SGSNVTY, "enable");
@@ -282,45 +346,66 @@ function f_init(BcdMccMnc mcc_mnc := '262F42'H) runs on test_CT {
g_initialized := true;
g_gb[0].cfg := {
nsei := 96,
- bvci := 196,
- cell_id := {
- ra_id := {
- lai := {
- mcc_mnc := mcc_mnc, lac := 13135},
- rac := 0
- },
- cell_id := 20960
- },
sgsn_role := false,
- depth := BSSGP_DECODE_DEPTH_L3
+ bvc := {
+ {
+ bvci := 196,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := mcc_mnc,
+ lac := 13135
+ },
+ rac := 0
+ },
+ cell_id := 20960
+ },
+ depth := BSSGP_DECODE_DEPTH_L3,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
};
g_gb[1].cfg := {
nsei := 97,
- bvci := 210,
- cell_id := {
- ra_id := {
- lai := {
- mcc_mnc := mcc_mnc, lac := 13200},
- rac := 0
- },
- cell_id := 20961
- },
sgsn_role := false,
- depth := BSSGP_DECODE_DEPTH_L3
+ bvc := {
+ {
+ bvci := 210,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := mcc_mnc,
+ lac := 13200
+ },
+ rac := 0
+ },
+ cell_id := 20961
+ },
+ depth := BSSGP_DECODE_DEPTH_L3,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
};
- g_gb[2].cfg := {
+ g_gb[2].cfg := { /* [2] configured to have same RAC as [1] */
nsei := 98,
- bvci := 220,
- cell_id := {
- ra_id := {
- lai := {
- mcc_mnc := mcc_mnc, lac := 13300},
- rac := 0
- },
- cell_id := 20962
- },
sgsn_role := false,
- depth := BSSGP_DECODE_DEPTH_L3
+ bvc := {
+ {
+ bvci := 220,
+ cell_id := {
+ ra_id := {
+ lai := {
+ mcc_mnc := mcc_mnc,
+ lac := 13200
+ },
+ rac := 0
+ },
+ cell_id := 20962
+ },
+ depth := BSSGP_DECODE_DEPTH_L3,
+ create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
+ }
+ }
};
f_init_vty();
@@ -373,6 +458,7 @@ const RanOps RNC_RanOps := {
protocol := RAN_PROTOCOL_RANAP,
transport := RANAP_TRANSPORT_IuCS,
use_osmux := false,
+ bssap_reset_retries := 1,
sccp_addr_local := omit,
sccp_addr_peer := omit
};
@@ -381,13 +467,13 @@ type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
/* helper function to create, connect and start a BSSGP_ConnHdlr component */
function f_start_handler(void_fn fn, charstring id, GbInstances gb, integer imsi_suffix,
- float t_guard := 30.0)
+ float t_guard := 30.0, boolean expect_ciph := false)
runs on test_CT return BSSGP_ConnHdlr {
var BSSGP_ConnHdlr vc_conn;
var SGSN_ConnHdlrNetworkPars net_pars := {
expect_ptmsi := true,
expect_auth := true,
- expect_ciph := false
+ expect_ciph := expect_ciph
};
var BSSGP_ConnHdlrPars pars := {
imei := f_gen_imei(imsi_suffix),
@@ -398,7 +484,11 @@ runs on test_CT return BSSGP_ConnHdlr {
tlli := f_gprs_tlli_random(),
tlli_old := omit,
ra := omit,
- bssgp_cell_id := { gb[0].cfg.cell_id, gb[1].cfg.cell_id, gb[2].cfg.cell_id },
+ bssgp_cell_id := {
+ gb[0].cfg.bvc[0].cell_id,
+ gb[1].cfg.bvc[0].cell_id,
+ gb[2].cfg.bvc[0].cell_id
+ },
rnc_send_initial_ue := true,
vec := omit,
net := net_pars,
@@ -413,15 +503,21 @@ runs on test_CT return BSSGP_ConnHdlr {
}
vc_conn := BSSGP_ConnHdlr.create(id);
- connect(vc_conn:BSSGP[0], gb[0].vc_BSSGP:BSSGP_SP);
- connect(vc_conn:BSSGP_SIG[0], gb[0].vc_BSSGP:BSSGP_SP_SIG);
- connect(vc_conn:BSSGP_PROC[0], gb[0].vc_BSSGP:BSSGP_PROC);
- connect(vc_conn:BSSGP[1], gb[1].vc_BSSGP:BSSGP_SP);
- connect(vc_conn:BSSGP_SIG[1], gb[1].vc_BSSGP:BSSGP_SP_SIG);
- connect(vc_conn:BSSGP_PROC[1], gb[1].vc_BSSGP:BSSGP_PROC);
- connect(vc_conn:BSSGP[2], gb[2].vc_BSSGP:BSSGP_SP);
- connect(vc_conn:BSSGP_SIG[2], gb[2].vc_BSSGP:BSSGP_SP_SIG);
- connect(vc_conn:BSSGP_PROC[2], gb[2].vc_BSSGP:BSSGP_PROC);
+
+ connect(vc_conn:BSSGP[0], gb[0].vc_BSSGP_BVC[0]:BSSGP_SP);
+ connect(vc_conn:BSSGP_SIG[0], gb[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
+ connect(vc_conn:BSSGP_PROC[0], gb[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
+ connect(vc_conn:BSSGP_GLOBAL[0], gb[0].vc_BSSGP:GLOBAL);
+
+ connect(vc_conn:BSSGP[1], gb[1].vc_BSSGP_BVC[0]:BSSGP_SP);
+ connect(vc_conn:BSSGP_SIG[1], gb[1].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
+ connect(vc_conn:BSSGP_PROC[1], gb[1].vc_BSSGP_BVC[0]:BSSGP_PROC);
+ connect(vc_conn:BSSGP_GLOBAL[1], gb[1].vc_BSSGP:GLOBAL);
+
+ connect(vc_conn:BSSGP[2], gb[2].vc_BSSGP_BVC[0]:BSSGP_SP);
+ connect(vc_conn:BSSGP_SIG[2], gb[2].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
+ connect(vc_conn:BSSGP_PROC[2], gb[2].vc_BSSGP_BVC[0]:BSSGP_PROC);
+ connect(vc_conn:BSSGP_GLOBAL[2], gb[2].vc_BSSGP:GLOBAL);
/* FIXME: support multiple RNCs */
if (g_ranap_enable) {
@@ -455,7 +551,7 @@ runs on BSSGP_ConnHdlr {
llc := f_llc_create(false);
/* register with BSSGP core */
- f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli);
/* tell GSUP dispatcher to send this IMSI to us */
f_create_gsup_expect(hex2str(g_pars.imsi));
/* tell GTP dispatcher to send this IMSI to us */
@@ -593,6 +689,34 @@ runs on BSSGP_ConnHdlr return PDU_L3_SGSN_MS {
return l3_mt;
}
+/* (copied from msc/BSC_ConnectionHandler.ttcn) */
+private altstep as_ciph_utran() runs on BSSGP_ConnHdlr
+{
+ [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(uia_algs := ?,
+ uia_key := oct2bit(g_pars.vec.ik),
+ key_sts := ?,
+ uea_algs := ?,
+ uea_key := oct2bit(g_pars.vec.ck))) {
+ var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1*/
+ var EncryptionAlgorithm uea_chosen := 1; /*standard_UMTS_encryption_algorith_UEA1*/
+ BSSAP.send(ts_RANAP_SecurityModeCompleteEnc(uia_chosen, uea_chosen));
+ }
+ [g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(?,?,?,?,?)) {
+ setverdict(fail, "Invalid SecurityModeCommand (ciphering case)");
+ mtc.stop;
+ }
+ [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?,
+ uia_key := oct2bit(g_pars.vec.ik),
+ key_sts := ?)) {
+ var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1;*/
+ BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
+ }
+ [not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(?,?,?)) {
+ setverdict(fail, "Invalid SecurityModeCommand (non-ciphering case)");
+ mtc.stop;
+ }
+}
+
/* perform GMM authentication (if expected).
* Note, for umts_aka_challenge to work, the revisionLevelIndicatior needs to
* be 1 to mark R99 capability, in the GMM Attach Request, see f_gmm_attach(). */
@@ -636,7 +760,7 @@ function f_gmm_auth (boolean umts_aka_challenge := false, boolean force_gsm_sres
auth_ciph_req.msgs.gprs_mm.authenticationAndCipheringRequest.authenticationParameterAUTN := autn;
l3_mt := f_receive_l3(auth_ciph_req, ran_index);
var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
- var template PDU_L3_MS_SGSN auth_ciph_resp := ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres);
+ var template (value) PDU_L3_MS_SGSN auth_ciph_resp := ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres);
if (umts_aka_challenge and not force_gsm_sres) {
/* set UMTS response instead */
@@ -660,12 +784,8 @@ function f_gmm_auth (boolean umts_aka_challenge := false, boolean force_gsm_sres
/* Security Mode Command + Complete on Iu case */
if (is_iu(ran_index)) {
- BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?, uia_key := oct2bit(g_pars.vec.ik),
- key_sts := ?)) {
- var IntegrityProtectionAlgorithm uia_chosen := 0; /* 0 = standard_UMTS_integrity_algorithm_UIA1 */
- BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
- BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)))
- }
+ as_ciph_utran();
+ BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)));
}
} else {
/* wait for identity procedure */
@@ -685,12 +805,14 @@ function f_upd_ptmsi_and_tlli(OCT4 p_tmsi, integer ran_index := 0) runs on BSSGP
}
}
-function f_process_attach_accept(PDU_GMM_AttachAccept aa) runs on BSSGP_ConnHdlr {
+function f_process_attach_accept(PDU_GMM_AttachAccept aa, integer ran_index := 0) runs on BSSGP_ConnHdlr {
/* mandatory IE */
var hexstring aa_plmn := f_RAI_to_plmn_hexstr(aa.routingAreaIdentification);
+ /* we cannot use ran_index here, as it would overflow the cell_id object, since ran_idx > NUM_GB
+ * indicates an Iu RAN connection. All cells are expected to run the same MCC/MNC anyway... */
if (not (g_pars.bssgp_cell_id[0].ra_id.lai.mcc_mnc == aa_plmn)) {
setverdict(fail, "mismatching PLMN in Attach Accept: " & hex2str(aa_plmn)
- & "; expected " & hex2str(g_pars.bssgp_cell_id[0].ra_id.lai.mcc_mnc));
+ & "; expected " & hex2str(g_pars.bssgp_cell_id[ran_index].ra_id.lai.mcc_mnc));
mtc.stop;
}
g_pars.ra := aa.routingAreaIdentification;
@@ -699,7 +821,8 @@ function f_process_attach_accept(PDU_GMM_AttachAccept aa) runs on BSSGP_ConnHdlr
setverdict(fail, "unexpected P-TMSI allocation");
mtc.stop;
}
- f_upd_ptmsi_and_tlli(aa.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets);
+ f_upd_ptmsi_and_tlli(aa.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets,
+ ran_index);
}
if (ispresent(aa.msIdentity)) {
setverdict(fail, "unexpected TMSI allocation in non-combined attach");
@@ -722,7 +845,8 @@ function f_process_rau_accept(PDU_GMM_RoutingAreaUpdateAccept ra, integer ran_in
setverdict(fail, "unexpected P-TMSI allocation");
mtc.stop;
}
- f_upd_ptmsi_and_tlli(ra.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets, ran_index);
+ f_upd_ptmsi_and_tlli(ra.allocatedPTMSI.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets,
+ ran_index);
}
if (ispresent(ra.msIdentity)) {
setverdict(fail, "unexpected TMSI allocation in non-combined attach");
@@ -751,22 +875,29 @@ private function f_mi_get_lv() runs on BSSGP_ConnHdlr return MobileIdentityLV {
}
}
-private function f_gmm_gsup_lu_isd() runs on BSSGP_ConnHdlr {
- var GSUP_PDU gsup;
- /* Expect MSC to perform LU with HLR */
- GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
- gsup := valueof(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
- gsup.ies := gsup.ies & { valueof(ts_GSUP_IE_PdpInfo(char2oct("*"), '0121'O, ''O)) };
- GSUP.send(gsup);
- GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
- GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
+private altstep as_gmm_gsup_lu_isd() runs on BSSGP_ConnHdlr {
+ [] GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi)) {
+ var GSUP_PDU gsup := valueof(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
+ gsup.ies := gsup.ies & { valueof(ts_GSUP_IE_PdpInfo('00'O, char2oct("*"), ts_EuaIPv4Dyn, ''O)) };
+ GSUP.send(gsup);
+ GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
+ GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
+ }
}
-friend function f_gmm_attach(boolean umts_aka_challenge, boolean force_gsm_sres, integer ran_index := 0) runs on BSSGP_ConnHdlr {
- var RoutingAreaIdentificationV old_ra := f_random_RAI();
- var template PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
+friend function f_gmm_attach(boolean umts_aka_challenge, boolean force_gsm_sres, integer ran_index := 0,
+ template (omit) RoutingAreaIdentificationV old_ra := omit) runs on BSSGP_ConnHdlr {
+ var RoutingAreaIdentificationV old_ra_val;
+ var template (value) PDU_L3_MS_SGSN attach_req;
var PDU_L3_SGSN_MS l3_mt;
+ if (istemplatekind(old_ra, "omit")) {
+ old_ra_val := f_random_RAI();
+ } else {
+ old_ra_val := valueof(old_ra);
+ }
+
+ attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra_val, false, false, omit, omit);
/* indicate R99 capability of the MS to enable UMTS AKA in presence of
* 3G auth vectors */
attach_req.msgs.gprs_mm.attachRequest.msNetworkCapability.msNetworkCapabilityV.revisionLevelIndicatior := '1'B;
@@ -777,10 +908,10 @@ friend function f_gmm_attach(boolean umts_aka_challenge, boolean force_gsm_sres,
f_send_l3(attach_req, ran_index);
f_gmm_auth(umts_aka_challenge, force_gsm_sres, ran_index);
/* Expect SGSN to perform LU with HLR */
- f_gmm_gsup_lu_isd();
+ as_gmm_gsup_lu_isd();
l3_mt := f_receive_l3(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?), ran_index);
- f_process_attach_accept(l3_mt.msgs.gprs_mm.attachAccept);
+ f_process_attach_accept(l3_mt.msgs.gprs_mm.attachAccept, ran_index);
/* FIXME: Extract P-TMSI, if any. Only send Complete if necessary */
f_send_l3(ts_GMM_ATTACH_COMPL, ran_index);
@@ -802,13 +933,13 @@ friend function f_gmm_attach(boolean umts_aka_challenge, boolean force_gsm_sres,
friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
timer T := 5.0;
var PDU_BSSGP rx_pdu;
- BSSGP_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
+ BSSGP_GLOBAL[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
T.start;
alt {
- [] BSSGP_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
+ [] BSSGP_GLOBAL[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
}
- [] BSSGP_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
+ [] BSSGP_GLOBAL[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, ?)) -> value rx_pdu {
setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
mtc.stop;
}
@@ -822,11 +953,11 @@ friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr ret
friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
timer T := 5.0;
- BSSGP_SIG[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, susp_ref));
+ BSSGP_GLOBAL[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id, susp_ref));
T.start;
alt {
- [] BSSGP_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
- [] BSSGP_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id,
+ [] BSSGP_GLOBAL[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id));
+ [] BSSGP_GLOBAL[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, g_pars.bssgp_cell_id[ran_idx].ra_id,
?)) {
setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
mtc.stop;
@@ -888,6 +1019,78 @@ testcase TC_attach_umts_aka_gsm_sres() runs on test_CT {
f_cleanup();
}
+/* Let T3350 expire while the MS holds an active PDP context (OS#4221). Do this by
+ * Establishing a PDP context and then resending an ATTACH REQUEST,
+ * making sure that exactly five ATTACH ACCEPTS are sent */
+private function f_TC_attach_timeout_after_pdp_act(charstring id) runs on BSSGP_ConnHdlr {
+ var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
+ /* Vars needed for triggering T3350 timeouts */
+ const integer ran_index := 0;
+ /* See TS 24.008 Rel. 16 Sect. 4.7.3.1.6 c) */
+ const integer gmm_attach_repeats := 5;
+ /* See TS 24.008 Rel. 16 Table 11.4 */
+ const float T3350 := 6.0;
+ var template (value) PDU_L3_MS_SGSN attach_req;
+ timer t_receive_GMM_ATTACH_ACCEPT;
+ var RoutingAreaIdentificationV rai := f_random_RAI();
+ timer T;
+
+ /* First establish PDP context */
+ f_TC_attach(id);
+ f_pdp_ctx_act(apars);
+
+ /* Now, try another GPRS attach procedure. Note that osmo-sgsn does not require
+ * authentication for the second GMM ATTACH REQUEST, so we expect GSUP UPDATE
+ * LOCATION REQUEST and optionally a GMM IDENTITY REQUEST (IMEI). */
+ attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), rai, false, false, omit, omit);
+ f_send_l3(attach_req, ran_index);
+
+ T.start(1.0);
+ alt {
+ [] as_gmm_gsup_lu_isd();
+ [] as_mm_identity(ran_index);
+ [] as_xid(apars, ran_index);
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for GSUP UPDATE LOCATION REQUEST");
+ return;
+ }
+ }
+
+ BSSGP[ran_index].clear;
+ log("Trying to receive ", gmm_attach_repeats, " ATTACH ACCEPTs");
+ for (var integer i := 1; i <= gmm_attach_repeats; i := i+1) {
+ t_receive_GMM_ATTACH_ACCEPT.start(T3350 + 0.5);
+ alt {
+ [] BSSGP[ran_index].receive(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?)) {
+ t_receive_GMM_ATTACH_ACCEPT.stop;
+ }
+ [] t_receive_GMM_ATTACH_ACCEPT.timeout {
+ setverdict(fail, "Timeout on receiving ", i, "th ATTACH ACCEPT")
+ }
+ }
+ }
+ log("Have received ", gmm_attach_repeats, " ATTACH ACCEPT messages");
+ log("Make sure not more than ", gmm_attach_repeats, " ATTACH ACCEPT messages are sent");
+ t_receive_GMM_ATTACH_ACCEPT.start(T3350 + 0.5);
+ alt {
+ [] BSSGP[ran_index].receive(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?)) {
+ setverdict(fail, "Received ", gmm_attach_repeats + 1, "th ATTACH ACCEPT")
+ }
+ [] t_receive_GMM_ATTACH_ACCEPT.timeout { }
+ }
+
+ setverdict(pass);
+}
+
+testcase TC_attach_timeout_after_pdp_act() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_attach_timeout_after_pdp_act),
+ testcasename(), g_gb, 21, t_guard := 45.0);
+ vc_conn.done;
+ f_cleanup();
+}
+
/* MS never responds to ID REQ, expect ATTACH REJECT */
private function f_TC_attach_auth_id_timeout(charstring id) runs on BSSGP_ConnHdlr {
var RoutingAreaIdentificationV old_ra := f_random_RAI();
@@ -1028,7 +1231,7 @@ private function f_TC_attach_combined(charstring id) runs on BSSGP_ConnHdlr {
f_send_l3(ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, true, false, omit, omit));
f_gmm_auth();
/* Expect MSC to perform LU with HLR */
- f_gmm_gsup_lu_isd();
+ as_gmm_gsup_lu_isd();
BSSGP[0].receive(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?)) -> value l3_mt {
f_process_attach_accept(l3_mt.msgs.gprs_mm.attachAccept);
@@ -1076,7 +1279,7 @@ private function f_TC_attach_closed_foreign(charstring id) runs on BSSGP_ConnHdl
/* Simulate a foreign IMSI */
g_pars.imsi := '001010123456789'H;
- f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli);
g_pars.net.expect_auth := false;
@@ -1349,12 +1552,13 @@ function f_pdp_ctx_deact_mt(inout PdpActPars apars, boolean error_ind := false,
runs on BSSGP_ConnHdlr {
var Gtp1cUnitdata g_ud;
var integer seq_nr := 23;
- var GtpPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
BSSGP[ran_index].clear;
if (error_ind) {
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_c));
GTP.send(ts_GTPU_ErrorIndication(peer, 0 /* seq */, apars.ggsn_tei_u, apars.ggsn_ip_u));
} else {
+ var Gtp1cPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
GTP.send(ts_GTPC_DeletePDP(peer, seq_nr, apars.sgsn_tei_c, apars.nsapi, '1'B));
}
@@ -1449,20 +1653,20 @@ template (value) PdpActPars t_PdpActPars(charstring ggsn_ip) := {
sgsn_ip_u := omit
}
-template (value) GtpPeer ts_GtpPeerU(octetstring ip) := {
+template (value) Gtp1uPeer ts_GtpPeerU(octetstring ip) := {
connId := 1,
remName := f_inet_ntoa(ip),
remPort := GTP1U_PORT
}
-template (value) GtpPeer ts_GtpPeerC(octetstring ip) := {
+template (value) Gtp1cPeer ts_GtpPeerC(octetstring ip) := {
connId := 1,
remName := f_inet_ntoa(ip),
remPort := GTP1C_PORT
}
private function f_gtpu_send(inout PdpActPars apars, octetstring payload) runs on BSSGP_ConnHdlr {
- var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
GTP.send(ts_GTP1U_GPDU(peer, 0 /*seq*/, apars.sgsn_tei_u, payload));
}
@@ -1530,12 +1734,12 @@ runs on BSSGP_ConnHdlr {
}
/* Transceive given 'payload' as MO message from Gb -> OsmoSGSN -> GTP */
-private function f_gtpu_xceive_mo(inout PdpActPars apars, octetstring payload, integer ran_index := 0)
+private function f_gtpu_xceive_mo(inout PdpActPars apars, octetstring payload, integer ran_index := 0, uint9_t n_u := 0)
runs on BSSGP_ConnHdlr {
/* Send PDU via SNDCP/LLC/BSSGP/NS via simulated MS/PCU to the SGSN */
- var GtpPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
var PDU_SN sndcp := valueof(ts_SN_UD(apars.nsapi, payload));
- BSSGP[ran_index].send(ts_LLC_UI(enc_PDU_SN(sndcp), apars.sapi, '0'B, 0));
+ BSSGP[ran_index].send(ts_LLC_UI(enc_PDU_SN(sndcp), apars.sapi, '0'B, n_u));
/* Expect PDU via GTP from SGSN on simulated GGSN */
alt {
[] GTP.receive(tr_GTPU_GPDU(peer, apars.ggsn_tei_u, payload));
@@ -1848,7 +2052,6 @@ private function f_TC_attach_restart_ctr_create(charstring id) runs on BSSGP_Con
var Gtp1cUnitdata g_ud;
var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
var integer seq_nr := 23;
- var GtpPeer peer;
/* first perform regular attach */
f_TC_attach(id);
@@ -1888,7 +2091,7 @@ testcase TC_attach_restart_ctr_create() runs on test_CT {
private function f_TC_attach_pdp_act_deact_mt_t3395_expire(charstring id) runs on BSSGP_ConnHdlr {
var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
var integer seq_nr := 23;
- var GtpPeer peer;
+ var Gtp1cPeer peer;
var integer i;
/* first perform regular attach */
@@ -1992,7 +2195,7 @@ private function f_TC_attach_pdp_act_deact_gtp_retrans_resp(charstring id) runs
/* Now perform an MT DeleteCtxReq and emulate GGSN didn't receive response and sends a duplicated DeleteCtxReq */
BSSGP[0].clear;
- var GtpPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
+ var Gtp1cPeer peer := valueof(ts_GtpPeerC(apars.sgsn_ip_c));
g_delete_req := ts_GTPC_DeletePDP(peer, seq_nr, apars.sgsn_tei_c, apars.nsapi, '1'B);
GTP.send(g_delete_req);
alt {
@@ -2329,7 +2532,7 @@ private function f_TC_attach_closed_imsi_added(charstring id) runs on BSSGP_Conn
f_bssgp_client_unregister(g_pars.imsi);
/* Simulate a foreign IMSI */
g_pars.imsi := '001010123456700'H;
- f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli);
/* there is no auth */
g_pars.net.expect_auth := false;
@@ -2391,7 +2594,7 @@ private function f_TC_attach_check_complete_resend(charstring id) runs on BSSGP_
f_send_l3(ts_GMM_ATTACH_REQ(f_mi_get_lv(), f_random_RAI(), true, false, omit, omit));
f_gmm_auth();
/* Expect SGSN to perform LU with HLR */
- f_gmm_gsup_lu_isd();
+ as_gmm_gsup_lu_isd();
timer T := 10.0;
T.start;
@@ -2427,46 +2630,67 @@ testcase TC_attach_check_complete_resend() runs on test_CT {
f_cleanup();
}
-friend function f_routing_area_update(RoutingAreaIdentificationV ra, integer ran_index := 0) runs on BSSGP_ConnHdlr {
+friend altstep as_routing_area_update_gb(integer ran_index := 0) runs on BSSGP_ConnHdlr {
var PDU_L3_SGSN_MS l3_mt;
- var PDU_DTAP_PS_MT mt;
- var template OCT4 p_tmsi := omit;
- if (is_iu(ran_index)) {
- p_tmsi := g_pars.p_tmsi;
- }
- /* then send RAU */
- f_send_l3(ts_GMM_RAU_REQ(f_mi_get_lv(), GPRS_UPD_T_RA, g_pars.ra, false, omit, omit, p_tmsi), ran_index);
- alt {
- [is_gb(ran_index)] BSSGP[ran_index].receive(tr_GMM_RAU_ACCEPT) -> value l3_mt {
+ [] BSSGP[ran_index].receive(tr_GMM_RAU_ACCEPT) -> value l3_mt {
f_process_rau_accept(l3_mt.msgs.gprs_mm.routingAreaUpdateAccept, ran_index);
f_send_l3(ts_GMM_RAU_COMPL, ran_index);
setverdict(pass);
}
- [is_iu(ran_index)] BSSAP.receive(tr_PDU_DTAP_PS_MT(tr_GMM_RAU_ACCEPT)) -> value mt {
+ [] BSSGP[ran_index].receive(tr_GMM_RAU_REJECT) {
+ setverdict(fail, "Unexpected RAU Reject");
+ mtc.stop;
+ }
+}
+friend altstep as_routing_area_update_iu(integer ran_index := 0) runs on BSSGP_ConnHdlr {
+ var PDU_DTAP_PS_MT mt;
+
+ [] BSSAP.receive(tr_PDU_DTAP_PS_MT(tr_GMM_RAU_ACCEPT)) -> value mt {
f_process_rau_accept(mt.dtap.msgs.gprs_mm.routingAreaUpdateAccept, ran_index);
f_send_l3(ts_GMM_RAU_COMPL, ran_index);
setverdict(pass);
}
-
- [is_gb(ran_index)] BSSGP[ran_index].receive(tr_GMM_RAU_REJECT) {
- setverdict(fail, "Unexpected RAU Reject");
- mtc.stop;
- }
- [is_iu(ran_index)] BSSAP.receive(tr_PDU_DTAP_PS_MT(tr_GMM_RAU_REJECT)) {
+ [] BSSAP.receive(tr_PDU_DTAP_PS_MT(tr_GMM_RAU_REJECT)) {
setverdict(fail, "Unexpected RAU Reject");
mtc.stop;
}
+ [] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?,
+ uia_key := oct2bit(g_pars.vec.ik),
+ key_sts := ?)) {
+ var IntegrityProtectionAlgorithm uia_chosen := 0; /* 0 = standard_UMTS_integrity_algorithm_UIA1 */
+ BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
+ BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)))
+ repeat;
+ }
+}
+friend altstep as_routing_area_update(integer ran_index := 0) runs on BSSGP_ConnHdlr {
+ [is_gb(ran_index)] as_routing_area_update_gb(ran_index);
+ [is_iu(ran_index)] as_routing_area_update_iu(ran_index);
+}
- [is_iu(ran_index)] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?, uia_key := oct2bit(g_pars.vec.ik),
- key_sts := ?)) {
- var IntegrityProtectionAlgorithm uia_chosen := 0; /* 0 = standard_UMTS_integrity_algorithm_UIA1 */
- BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
- BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)))
- repeat;
- }
+friend function f_routing_area_update(RoutingAreaIdentificationV old_ra,
+ GprsUpdateType upd_type := GPRS_UPD_T_RA,
+ integer ran_index := 0,
+ float Tval := 2.0) runs on BSSGP_ConnHdlr {
+ var template (omit) OCT4 p_tmsi := omit;
+ timer T := Tval;
+
+ if (is_iu(ran_index)) {
+ p_tmsi := g_pars.p_tmsi;
+ }
+
+ f_send_l3(ts_GMM_RAU_REQ(f_mi_get_lv(), upd_type, old_ra, p_tmsi := p_tmsi), ran_index);
+
+ T.start;
+ alt {
+ [] as_routing_area_update(ran_index) { setverdict(pass); }
[is_gb(ran_index)] BSSGP[ran_index].receive { repeat; }
[is_iu(ran_index)] BSSAP.receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout completing the RAU procedure");
+ mtc.stop;
+ }
}
}
@@ -2503,14 +2727,14 @@ private function f_TC_attach_rau_a_b(charstring id) runs on BSSGP_ConnHdlr {
f_TC_attach(id);
log("attach complete sending rau");
- f_routing_area_update(g_pars.ra, 0);
+ f_routing_area_update(g_pars.ra);
log("rau complete unregistering");
f_bssgp_client_unregister(g_pars.imsi);
- f_bssgp_client_register(g_pars.imsi, g_pars.tlli, g_pars.bssgp_cell_id[1], BSSGP_PROC[1]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[1]);
log("sending second RAU via different RA");
- f_routing_area_update(f_cellid_to_RAI(g_pars.bssgp_cell_id[1]), 1);
+ f_routing_area_update(f_cellid_to_RAI(g_pars.bssgp_cell_id[1]), ran_index := 1);
f_detach_mo(c_GMM_DTT_MO_GPRS, true, true, 1);
}
@@ -2607,7 +2831,7 @@ testcase TC_attach_gmm_attach_req_while_gmm_attach() runs on test_CT {
private function f_TC_attach_usim_resync(charstring id) runs on BSSGP_ConnHdlr {
var RoutingAreaIdentificationV old_ra := f_random_RAI();
- var template PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
+ var template (value) PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
/* send Attach Request */
/* indicate R99 capability of the MS to enable UMTS AKA in presence of
@@ -2679,7 +2903,7 @@ private function f_TC_attach_usim_resync(charstring id) runs on BSSGP_ConnHdlr {
auth_ciph_req.msgs.gprs_mm.authenticationAndCipheringRequest.authenticationParameterAUTN := autn;
BSSGP[0].receive(auth_ciph_req) -> value l3_mt;
var BIT4 ac_ref := l3_mt.msgs.gprs_mm.authenticationAndCipheringRequest.acReferenceNumber.valueField;
- var template PDU_L3_MS_SGSN auth_ciph_resp := ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres);
+ var template (value) PDU_L3_MS_SGSN auth_ciph_resp := ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres);
auth_ciph_resp := ts_GMM_AUTH_RESP_2G(ac_ref, g_pars.vec.sres);
auth_ciph_resp.msgs.gprs_mm.authenticationAndCipheringResponse.authenticationParResp := {
valueField := substr(g_pars.vec.res, 0, 4)
@@ -2699,7 +2923,7 @@ private function f_TC_attach_usim_resync(charstring id) runs on BSSGP_ConnHdlr {
deactivate(di);
/* Expect SGSN to perform LU with HLR */
- f_gmm_gsup_lu_isd();
+ as_gmm_gsup_lu_isd();
BSSGP[0].receive(tr_GMM_ATTACH_ACCEPT('001'B, ?, ?)) -> value l3_mt {
f_process_attach_accept(l3_mt.msgs.gprs_mm.attachAccept);
@@ -2733,6 +2957,123 @@ testcase TC_attach_usim_resync() runs on test_CT {
f_cleanup();
}
+private function f_TC_attach_usim_crypt(OCT1 netcap_a2345, BIT3 auth_req_ciph) runs on BSSGP_ConnHdlr {
+ var RoutingAreaIdentificationV old_ra := f_random_RAI();
+
+ var template (value) PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
+ attach_req.msgs.gprs_mm.attachRequest.msNetworkCapability.msNetworkCapabilityV.spare_octets := netcap_a2345; /* GEA2345... */
+
+ /* send Attach Request */
+ /* indicate R99 capability of the MS to enable UMTS AKA in presence of
+ * 3G auth vectors */
+ attach_req.msgs.gprs_mm.attachRequest.msNetworkCapability.msNetworkCapabilityV.revisionLevelIndicatior := '1'B;
+ /* The thing is, if the solSACapability is 'omit', then the
+ * revisionLevelIndicatior is at the wrong place! */
+ attach_req.msgs.gprs_mm.attachRequest.msNetworkCapability.msNetworkCapabilityV.solSACapability := '0'B;
+ f_send_l3(attach_req);
+
+ /* do the auth */
+ var PDU_L3_MS_SGSN l3_mo;
+ var PDU_L3_SGSN_MS l3_mt;
+ var default di := activate(as_mm_identity());
+
+ var GSUP_IE auth_tuple;
+ var template AuthenticationParameterAUTNTLV autn;
+
+ g_pars.vec := f_gen_auth_vec_3g();
+ autn := {
+ elementIdentifier := '28'O,
+ lengthIndicator := lengthof(g_pars.vec.autn),
+ autnValue := g_pars.vec.autn
+ };
+ auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
+ g_pars.vec.sres,
+ g_pars.vec.kc,
+ g_pars.vec.ik,
+ g_pars.vec.ck,
+ g_pars.vec.autn,
+ g_pars.vec.res));
+ log("GSUP sends 2G and 3G auth tuples", auth_tuple);
+ GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
+ GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
+
+ var template PDU_L3_SGSN_MS auth_ciph_req := tr_GMM_AUTH_REQ(g_pars.vec.rand, auth_req_ciph);
+ auth_ciph_req.msgs.gprs_mm.authenticationAndCipheringRequest.authenticationParameterAUTN := autn;
+ BSSGP[0].receive(auth_ciph_req) -> value l3_mt;
+
+ setverdict(pass);
+ deactivate(di);
+}
+
+private function f_TC_attach_usim_a54_a54(charstring id) runs on BSSGP_ConnHdlr {
+ f_TC_attach_usim_crypt('10'O, '100'B);
+}
+
+private function f_TC_attach_usim_a54_a53(charstring id) runs on BSSGP_ConnHdlr {
+ f_TC_attach_usim_crypt('20'O, '011'B);
+}
+
+private function f_TC_attach_usim_a53_a54(charstring id) runs on BSSGP_ConnHdlr {
+ f_TC_attach_usim_crypt('30'O, '011'B);
+}
+
+private function f_TC_attach_usim_a50_a54(charstring id) runs on BSSGP_ConnHdlr {
+ f_TC_attach_usim_crypt('30'O, '000'B);
+}
+
+private function f_TC_attach_usim_a54_a50(charstring id) runs on BSSGP_ConnHdlr {
+ f_TC_attach_usim_crypt('00'O, '000'B);
+}
+
+testcase TC_attach_usim_a54_a54() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ f_vty_config(SGSNVTY, "sgsn", "encryption gea 0 3 4");
+ vc_conn := f_start_handler(refers(f_TC_attach_usim_a54_a54), testcasename(), g_gb, 40);
+ vc_conn.done;
+ f_cleanup();
+}
+
+testcase TC_attach_usim_a54_a53() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ f_vty_config(SGSNVTY, "sgsn", "encryption gea 0 3 4");
+ vc_conn := f_start_handler(refers(f_TC_attach_usim_a54_a53), testcasename(), g_gb, 40);
+ vc_conn.done;
+ f_cleanup();
+}
+
+testcase TC_attach_usim_a53_a54() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ f_vty_config(SGSNVTY, "sgsn", "encryption gea 0 3");
+ vc_conn := f_start_handler(refers(f_TC_attach_usim_a53_a54), testcasename(), g_gb, 40);
+ vc_conn.done;
+ f_cleanup();
+}
+
+testcase TC_attach_usim_a50_a54() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ f_vty_config(SGSNVTY, "sgsn", "encryption gea 0");
+ vc_conn := f_start_handler(refers(f_TC_attach_usim_a50_a54), testcasename(), g_gb, 40);
+ vc_conn.done;
+ f_cleanup();
+}
+
+testcase TC_attach_usim_a54_a50() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ f_vty_config(SGSNVTY, "sgsn", "encryption gea 0 3 4");
+ vc_conn := f_start_handler(refers(f_TC_attach_usim_a54_a50), testcasename(), g_gb, 40);
+ vc_conn.done;
+ f_cleanup();
+}
/* Send LLC NULL to see if the SGSN survives it (OS#3952) */
private function f_TC_llc_null(charstring id) runs on BSSGP_ConnHdlr {
@@ -2875,7 +3216,7 @@ private function f_TC_attach_req_id_req_ra_update(charstring id) runs on BSSGP_C
var RoutingAreaIdentificationV old_ra := f_random_RAI();
var RoutingAreaIdentificationV new_ra := f_random_RAI();
while (old_ra == new_ra) { new_ra := f_random_RAI(); };
- var template PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
+ var template (value) PDU_L3_MS_SGSN attach_req := ts_GMM_ATTACH_REQ(f_mi_get_lv(), old_ra, false, false, omit, omit);
var PDU_L3_SGSN_MS l3_mt;
f_send_l3(attach_req, 0);
@@ -3013,6 +3354,9 @@ private function f_TC_suspend_rau(charstring id) runs on BSSGP_ConnHdlr {
/* perform RAU (implicit RESUME) */
f_routing_area_update(g_pars.ra);
+ /* give SGSN some time to actually receve + process the RAU Complete we sent */
+ f_sleep(0.5);
+
/* now data should be flowing again */
f_gtpu_xceive_mt(apars, f_rnd_octstring(100));
@@ -3061,15 +3405,510 @@ testcase TC_paging_ps() runs on test_CT {
f_cleanup();
}
+/* Run a RIM single report procedure over the sgsn. Since the SGSN will only do a transparent routing of the
+ * RIM messages this basically tests if the message is correctly transfered from one GB interface to the
+ * other and vice versa. */
+testcase TC_bssgp_rim_single_report() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+
+ timer T := 2.0;
+
+ var template RIM_Routing_Address dst_addr;
+ var template RIM_Routing_Address src_addr;
+ var template (value) RAN_Information_Request_RIM_Container req_cont;
+ var template (value) RAN_Information_RIM_Container res_cont;
+ var template (value) PDU_BSSGP bssgp_rim_pdu;
+ var template PDU_BSSGP bssgp_rim_pdu_expect;
+
+ dst_addr := t_RIM_Routing_Address_cid(g_gb[1].cfg.bvc[0].cell_id);
+ src_addr := t_RIM_Routing_Address_cid(g_gb[0].cfg.bvc[0].cell_id);
+
+
+ /* Send NACC Ran information request to SGSN at GB interface #0. We epect the SGSN to forward this request
+ * based on the cell id in dst_addr to GB interface #1. */
+ req_cont := ts_RAN_Information_Request_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(1),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_RAN_Information_Request_Application_Container_NACC(g_gb[1].cfg.bvc[0].cell_id),
+ omit);
+ bssgp_rim_pdu := ts_RAN_INFORMATION_REQUEST(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ req_cont);
+ bssgp_rim_pdu_expect := tr_RAN_INFORMATION_REQUEST(tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ tr_RAN_Information_Request_RIM_Container);
+ RIM[0].send(bssgp_rim_pdu);
+ T.start;
+ alt {
+ [] RIM[1].receive(bssgp_rim_pdu_expect) {
+ setverdict(pass);
+ }
+ [] RIM[1].receive {
+ setverdict(fail, "Unexpected BSSGP RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No BSSGP RIM PDU received");
+ mtc.stop;
+ }
+ }
+
+ /* Now also emulate also the response as well and send it back on GB interface #1. Expect the result on
+ * GB interface #0 */
+ res_cont := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(2),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_ApplContainer_or_ApplErrContainer_NACC(tsu_ApplContainer_NACC(g_gb[0].cfg.bvc[0].cell_id, false, 3, si_default)),
+ omit);
+ bssgp_rim_pdu := ts_PDU_BSSGP_RAN_INFORMATION(ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ res_cont);
+ bssgp_rim_pdu_expect := tr_PDU_BSSGP_RAN_INFORMATION(tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, src_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, dst_addr),
+ ?);
+ RIM[1].send(bssgp_rim_pdu);
+ T.start;
+ alt {
+ [] RIM[0].receive(bssgp_rim_pdu_expect) {
+ setverdict(pass);
+ }
+ [] RIM[0].receive {
+ setverdict(fail, "Unexpected BSSGP RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No BSSGP RIM PDU received");
+ mtc.stop;
+ }
+ }
+
+ f_cleanup();
+}
+
+testcase TC_rim_eutran_to_geran() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ /* connect RIM related port */
+ connect(vc_GTP:CLIENT_DEFAULT, self:GTPC);
+
+ var Gtp1cPeer peer := {
+ connId := 1,
+ remName := mp_sgsn_gtp_ip,
+ remPort := GTP1C_PORT
+ }
+ var GTP_CellId gtp_ci := f_BssgpCellId_to_GTP_CellId(g_gb[1].cfg.bvc[0].cell_id);
+
+ var template (value) RIM_Routing_Address_GTPC gtpc_dst_addr, gtpc_src_addr;
+ var template (value) RAN_Information_Request_RIM_Container_GTPC gtpc_rim_req_cont;
+ var template (value) PDU_BSSGP_RAN_INFORMATION_REQUEST_GTPC gtpc_bssgp_cont;
+ var template (value) RIM_RoutingAddress gtpc_rim_ra;
+ var template (value) RIM_RoutingAddress_Discriminator gtpc_rim_ra_discr;
+ var template (value) Gtp1cUnitdata gtpc_pdu;
+
+ gtpc_dst_addr := t_GTPC_RIM_Routing_Address_cid(gtp_ci);
+ gtpc_src_addr := t_GTPC_RIM_Routing_Address_enbid(gtp_ci, tac := 3, gnbid := '12345678123456'O);
+
+ gtpc_rim_req_cont := ts_GTPC_RAN_Information_Request_RIM_Container(ts_GTPC_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_GTPC_RIM_Sequence_Number(1),
+ ts_GTPC_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_GTPC_RIM_Protocol_Version_Number(1),
+ tsu_GTPC_RAN_Information_Request_Application_Container_NACC(gtp_ci),
+ omit);
+ gtpc_bssgp_cont := ts_GTPC_RAN_Information_Request(ts_GTPC_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, gtpc_dst_addr),
+ ts_GTPC_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, gtpc_src_addr),
+ gtpc_rim_req_cont);
+
+ /* Assemble RIM Routing Address (essentially a copy of the destination cell identifier)*/
+ gtpc_rim_ra := ts_RIM_RoutingAddress(enc_RIM_Routing_Address_GTPC(valueof(gtpc_dst_addr)));
+ gtpc_rim_ra_discr := ts_RIM_RoutingAddress_Discriminator(hex2bit(RIM_ADDR_GERAN_CELL_ID));
+ gtpc_pdu := ts_GTPC_RANInfoRelay(peer, ts_RANTransparentContainer_RAN_INFO_REQ(gtpc_bssgp_cont),
+ gtpc_rim_ra, gtpc_rim_ra_discr);
+ GTPC.send(gtpc_pdu);
+
+ var template RIM_Routing_Address bssgp_dst_addr, bssgp_src_addr;
+ var template PDU_BSSGP bssgp_rim_pdu_expect;
+ bssgp_dst_addr := t_RIM_Routing_Address_cid(g_gb[1].cfg.bvc[0].cell_id);
+ bssgp_src_addr := t_RIM_Routing_Address_enbid(g_gb[1].cfg.bvc[0].cell_id, tac := 3, gnbid := '12345678123456'O);
+ bssgp_rim_pdu_expect := tr_RAN_INFORMATION_REQUEST(tr_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, bssgp_dst_addr),
+ tr_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, bssgp_src_addr),
+ tr_RAN_Information_Request_RIM_Container);
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] RIM[1].receive(bssgp_rim_pdu_expect) {
+ setverdict(pass);
+ T.stop;
+ }
+ [] RIM[1].receive {
+ setverdict(fail, "Unexpected BSSGP RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No BSSGP RIM PDU received");
+ mtc.stop;
+ }
+ }
+
+ /* Now also emulate also the response as well and send it back on GB
+ interface #1. Expect the result on * GTPC */
+ var template (value) RAN_Information_RIM_Container res_cont;
+ var template (value) PDU_BSSGP bssgp_rim_pdu;
+ res_cont := ts_RAN_Information_RIM_Container(ts_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_RIM_Sequence_Number(2),
+ ts_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_RIM_Protocol_Version_Number(1),
+ tsu_ApplContainer_or_ApplErrContainer_NACC(tsu_ApplContainer_NACC(g_gb[1].cfg.bvc[0].cell_id, false, 3, si_default)),
+ omit);
+ bssgp_rim_pdu := ts_PDU_BSSGP_RAN_INFORMATION(ts_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, bssgp_src_addr),
+ ts_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, bssgp_dst_addr),
+ res_cont);
+ RIM[1].send(bssgp_rim_pdu);
+
+ var template RAN_Information_RIM_Container_GTPC rim_cont;
+ var template PDU_BSSGP_RAN_INFORMATION_GTPC gtpc_bssgp_cont_ack;
+ var template Gtp1cUnitdata gtpc_pdu_exp;
+ rim_cont := tr_GTPC_RAN_Information_RIM_Container(ts_GTPC_RIM_Application_Identity(RIM_APP_ID_NACC),
+ ts_GTPC_RIM_Sequence_Number(2),
+ ts_GTPC_RIM_PDU_Indications(false, RIM_PDU_TYPE_SING_REP),
+ ts_GTPC_RIM_Protocol_Version_Number(1),
+ tru_GTPC_ApplContainer_or_ApplErrContainer_NACC(tru_GTPC_ApplContainer_NACC(gtp_ci, false, 3, si_default)),
+ omit);
+ gtpc_bssgp_cont_ack := tr_GTPC_RAN_Information(tr_GTPC_RIM_Routing_Information(RIM_ADDR_EUTRAN_NODEB_ID, gtpc_src_addr),
+ tr_GTPC_RIM_Routing_Information(RIM_ADDR_GERAN_CELL_ID, gtpc_dst_addr),
+ rim_cont);
+ gtpc_pdu_exp := tr_GTPC_RANInfoRelay(peer, tr_RANTransparentContainer_RAN_INFO(gtpc_bssgp_cont_ack));
+
+ T.start;
+ alt {
+ [] GTPC.receive(gtpc_pdu_exp) {
+ setverdict(pass);
+ T.stop;
+ }
+ [] GTPC.receive {
+ setverdict(fail, "Unexpected GTPC RIM PDU received");
+ }
+ [] T.timeout {
+ setverdict(fail, "No GTPC RIM PDU received");
+ mtc.stop;
+ }
+ }
+
+ f_cleanup();
+}
+
+/* Test if the SGSN routes traffic to new cell after the MS attached to it */
+private function f_TC_cell_change_different_rai_ci_attach(charstring id) runs on BSSGP_ConnHdlr {
+ var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
+
+ /* first perform regular attach */
+ f_gmm_attach(false, false, ran_index := 0);
+ /* then activate PDP context */
+ f_pdp_ctx_act(apars, ran_index := 0);
+ /* then transceive a downlink PDU */
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 0);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 0);
+
+ /* Now attach on different cell: */
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[1]);
+ g_pars.net.expect_auth := false;
+ f_gmm_attach(false, false, ran_index := 1, old_ra := f_cellid_to_RAI(g_pars.bssgp_cell_id[0]));
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 1);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 1, n_u := 1);
+}
+testcase TC_cell_change_different_rai_ci_attach() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_cell_change_different_rai_ci_attach), testcasename(), g_gb, 68);
+ vc_conn.done;
+ f_cleanup();
+}
+
+/* Test if the SGSN routes traffic to new cell after the MS attached to it */
+/* Assumption: g_gb[1] and g_gb[2] configured with same RAC */
+private function f_TC_cell_change_different_ci_attach(charstring id) runs on BSSGP_ConnHdlr {
+ var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
+
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[1]);
+
+ /* first perform regular attach */
+ f_gmm_attach(false, false, ran_index := 1);
+ /* then activate PDP context */
+ f_pdp_ctx_act(apars, ran_index := 1);
+ /* then transceive a downlink PDU */
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 1);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 1);
+
+ /* Now attach on different cell: */
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[1]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[2]);
+ g_pars.net.expect_auth := false;
+ f_gmm_attach(false, false, ran_index := 2, old_ra := f_cellid_to_RAI(g_pars.bssgp_cell_id[1]));
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 2);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 2, n_u := 1);
+}
+testcase TC_cell_change_different_ci_attach() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_cell_change_different_ci_attach), testcasename(), g_gb, 69);
+ vc_conn.done;
+ f_cleanup();
+}
+
+/* Test if the SGSN silently drops MO data message coming from new BVCI if RAC changed (eg. cell change) */
+private function f_TC_cell_change_different_rai_ci_data(charstring id) runs on BSSGP_ConnHdlr {
+ var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
+
+ /* first perform regular attach */
+ f_gmm_attach(false, false, ran_index := 0);
+ /* then activate PDP context */
+ f_pdp_ctx_act(apars, ran_index := 0);
+ /* then transceive a downlink PDU */
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 0);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 0);
+
+ /* Send some data over new bvci, it should be silently discarded since
+ * RAC changed and SGSN expects a RAU to occur in that case */
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[1]);
+ var octetstring payload := f_rnd_octstring(200);
+ var PDU_SN sndcp := valueof(ts_SN_UD(apars.nsapi, payload));
+ BSSGP[1].send(ts_LLC_UI(enc_PDU_SN(sndcp), apars.sapi, '0'B, 1));
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(apars.sgsn_ip_u));
+ timer T := 2.0;
+ T.start;
+ alt {
+ [] GTP.receive(tr_GTPU_GPDU(peer, apars.ggsn_tei_u, payload)) {
+ setverdict(fail, "Unexpected GTP message");
+ }
+ [] T.timeout { setverdict(pass); }
+ }
+
+ /* Expect SGSN to continue routing DL data to last known NSEI+BVCI */
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[1]);
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 0);
+}
+testcase TC_cell_change_different_rai_ci_data() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_cell_change_different_rai_ci_data), testcasename(), g_gb, 70);
+ vc_conn.done;
+ f_cleanup();
+}
+
+/* Test if the SGSN routes traffic to new cell after the MS switched cell without re-attaching */
+/* Assumption: g_gb[1] and g_gb[2] configured with same RAC */
+private function f_TC_cell_change_different_ci_data(charstring id) runs on BSSGP_ConnHdlr {
+ var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
+
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[0]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[1]);
+
+ /* first perform regular attach */
+ f_gmm_attach(false, false, ran_index := 1);
+ /* then activate PDP context */
+ f_pdp_ctx_act(apars, ran_index := 1);
+ /* then transceive a downlink PDU */
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 1);
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 1);
+
+ /* Now attach on different cell: */
+ f_bssgp_client_unregister(g_pars.imsi, BSSGP_PROC[1]);
+ f_bssgp_client_register(g_pars.imsi, g_pars.tlli, BSSGP_PROC[2]);
+
+ f_gtpu_xceive_mo(apars, f_rnd_octstring(200), ran_index := 2, n_u := 1);
+ f_gtpu_xceive_mt(apars, f_rnd_octstring(100), ran_index := 2);
+}
+testcase TC_cell_change_different_ci_data() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ vc_conn := f_start_handler(refers(f_TC_cell_change_different_ci_data), testcasename(), g_gb, 71);
+ vc_conn.done;
+ f_cleanup();
+}
+
+/* SGSN terminated SGSN Context Request procedure (we request, SGSN responds)
+ * 3GPP TS 23.401, Figure D.3.6-1: "Gn/Gp SGSN to MME Tracking Area Update procedure" */
+private function f_TC_sgsn_context_req_in(charstring id) runs on BSSGP_ConnHdlr {
+ var integer seq_nr := f_rnd_int(65535);
+ var Gtp1cUnitdata gtpc_ud;
+ timer T;
+
+ var Gtp1cPeer peer := {
+ connId := 1,
+ remName := mp_sgsn_gtp_ip,
+ remPort := GTP1C_PORT
+ }
+
+ /* The MS attaches to GERAN/UTRAN and enjoys the service */
+ f_gmm_attach(false, false);
+
+ /* The MS switches to an LTE cell and performs Tracking Area Update Request there.
+ * The MME requests information about the MS by sending SGSN Context Request. */
+ var template (value) GTPC_PDUs ctx_req;
+ ctx_req := ts_SGSNContextReqPDU(rai := ts_RoutingAreaIdentity('250'H, 'F99'H, '4242'O, 'DE'O),
+ teic := '12345678'O,
+ sgsn_addr_control := f_inet_addr(mp_ggsn_ip),
+ ptmsi := ts_PTMSI(g_pars.p_tmsi),
+ ptmsi_sig := ts_PTMSI_sig('010203'O));
+ GTP.send(ts_GTPC_SGSNContextReq(peer, seq_nr, ctx_req));
+
+ /* The SGSN responds with subscriber's IMSI */
+ var template (present) GTPC_PDUs ctx_rsp;
+ ctx_rsp := tr_SGSNContextRespPDU(cause := GTP_CAUSE_REQUEST_ACCEPTED,
+ imsi := g_pars.imsi);
+
+ /* SGSN Address for Control Plane */
+ var octetstring sgsn_addr := f_inet_addr(mp_sgsn_gtp_ip);
+ ctx_rsp.sgsn_ContextResponse.sgsn_addr_controlPlane := tr_GsnAddr(sgsn_addr);
+
+ /* Match MM Context */
+ if (ispresent(g_pars.vec)) {
+ /* XXX: this is only valid for GERAN */
+ var octetstring triplet := g_pars.vec.rand & g_pars.vec.sres & g_pars.vec.kc;
+ ctx_rsp.sgsn_ContextResponse.mm_Context := tr_MM_ContextGSM(kc := g_pars.vec.kc,
+ triplet := triplet);
+ /* TODO: 7.5.4 "The IMEISV shall, if available, be included in the MM Context".
+ * See also 3GPP TS 29.060, section 7.7.28 and Table 47A */
+ }
+
+ /* TODO: match PDP Context */
+
+ T.start(2.0);
+ alt {
+ [] GTP.receive(tr_GTPC_SGSNContextResp(?, ?, ctx_rsp)) -> value gtpc_ud {
+ log("Rx SGSN Context Resp from SGSN, sending Ack");
+ GTP.send(ts_GTPC_SGSNContextAck(gtpc_ud.peer, '12345678'O, seq_nr));
+ setverdict(pass);
+ }
+ [] GTP.receive(tr_GTPC_SGSNContextResp) -> value gtpc_ud {
+ GTP.send(ts_GTPC_SGSNContextAck(gtpc_ud.peer, '12345678'O, seq_nr,
+ ts_SGSNContextAckPDU(GTP_CAUSE_INVALID_MSG_FORMAT)));
+ setverdict(fail, "Rx unexpected SGSN Context Resp");
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for SGSN Context Resp");
+ }
+ }
+
+ /* HLR/HSS tells SGSN to forget this MS/UE */
+ GSUP.send(ts_GSUP_CL_REQ(g_pars.imsi, OSMO_GSUP_CANCEL_TYPE_UPDATE));
+ GSUP.receive(tr_GSUP_CL_RES(g_pars.imsi));
+}
+testcase TC_sgsn_context_req_in() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_TC_sgsn_context_req_in), testcasename(), g_gb, 72);
+ vc_conn.done;
+ f_cleanup();
+}
+
+/* SGSN originated SGSN Context Request procedure (SGSN requests, we respond)
+ * 3GPP TS 23.401, Figure D.3.5-1 "Routing Area Update procedure" */
+private function f_TC_sgsn_context_req_out(charstring id) runs on BSSGP_ConnHdlr {
+ var integer seq_nr := f_rnd_int(65535);
+ var Gtp1cUnitdata gtpc_ud;
+ timer T;
+
+ /* The MS goes to GERAN/UTRAN from an LTE cell */
+ f_send_l3(ts_GMM_RAU_REQ(mi_lv := valueof(ts_MI_TMSI_LV('DE42DE42'O)),
+ upd_type := GPRS_UPD_T_RA,
+ old_ra := f_random_RAI()), 0);
+
+
+ /* The SGSN has no idea about the MS and inquires the MME about it */
+ T.start(2.0);
+ alt {
+ [] GTP.receive(tr_GTPC_SGSNContextReq(?, ?)) -> value gtpc_ud {
+ log("Rx SGSN Context Req from SGSN");
+ setverdict(pass);
+ T.stop;
+ }
+ [] GTP.receive(tr_GTPC_SGSNContextResp) {
+ setverdict(fail, "Rx unexpected SGSN Context Req");
+ mtc.stop;
+ }
+ [] BSSGP[0].receive(tr_LLC_XID_MT_CMD(?, ?)) {
+ /* Ignore XID Reset */
+ repeat;
+ }
+ [] BSSGP[0].receive(tr_GMM_RAU_REJECT) {
+ /* osmo-sgsn -latest would send RAU Reject (Implicitly detached) */
+ setverdict(fail, "Rx unexpected RAU Reject");
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for SGSN Context Req");
+ mtc.stop;
+ }
+ }
+
+ /* The MME responds */
+ var OCT8 kc := f_rnd_octstring(8);
+
+ var template (value) PDP_Context_GTPC pdp_ctx;
+ pdp_ctx := ts_PDP_Context_GTPC(pdp_addr := f_inet_addr("10.10.10.10"),
+ ggsn_gsn_addr := f_inet_addr(mp_ggsn_ip),
+ apn := '08696E7465726E6574'O);
+ var template (value) GTPC_PDUs ctx_rsp;
+ ctx_rsp := ts_SGSNContextRespPDU(cause := GTP_CAUSE_REQUEST_ACCEPTED,
+ imsi := g_pars.imsi,
+ teic := '12345678'O,
+ mm_context := ts_MM_ContextGSM(kc),
+ pdp_ctx_list := { pdp_ctx });
+ GTP.send(ts_GTPC_SGSNContextResp(gtpc_ud.peer, '12345678'O, seq_nr, ctx_rsp));
+
+ /* TODO: Security Functions (auth/ciphering?) */
+
+ /* The SGSN ACKs */
+ T.start(2.0);
+ alt {
+ [] GTP.receive(tr_GTPC_SGSNContextAck) -> value gtpc_ud {
+ log("Rx SGSN Context ACK from SGSN");
+ setverdict(pass);
+ T.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for SGSN Contect ACK");
+ mtc.stop;
+ }
+ }
+ /* TODO: Update PDP Context Req/Resp */
+ /* TODO: 7..10 Update Location, ISD */
+ /* RAU procedure completion */
+ T.start(2.0);
+ alt {
+ [] as_routing_area_update_gb(0) {
+ log("RAU procedure completed");
+ setverdict(pass);
+ T.stop;
+ }
+ [] BSSGP[0].receive { repeat; }
+ [] T.timeout {
+ setverdict(fail, "Timeout completing the RAU procedure");
+ mtc.stop;
+ }
+ }
+}
+testcase TC_sgsn_context_req_out() runs on test_CT {
+ var BSSGP_ConnHdlr vc_conn;
+ f_init();
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_TC_sgsn_context_req_out), testcasename(), g_gb, 73);
+ vc_conn.done;
+ f_cleanup();
+}
control {
execute( TC_attach() );
execute( TC_attach_mnc3() );
execute( TC_attach_umts_aka_umts_res() );
execute( TC_attach_umts_aka_gsm_sres() );
+ execute( TC_attach_timeout_after_pdp_act() );
execute( TC_attach_auth_id_timeout() );
execute( TC_attach_auth_sai_timeout() );
execute( TC_attach_auth_sai_reject() );
@@ -3093,6 +3932,11 @@ control {
execute( TC_attach_rau_a_a() );
execute( TC_attach_rau_a_b() );
execute( TC_attach_usim_resync() );
+ execute( TC_attach_usim_a54_a54() );
+ execute( TC_attach_usim_a54_a53() );
+ execute( TC_attach_usim_a53_a54() );
+ execute( TC_attach_usim_a50_a54() );
+ execute( TC_attach_usim_a54_a50() );
execute( TC_detach_unknown_nopoweroff() );
execute( TC_detach_unknown_poweroff() );
execute( TC_detach_nopoweroff() );
@@ -3127,6 +3971,17 @@ control {
execute( TC_suspend_rau() );
execute( TC_paging_ps() );
+ execute( TC_bssgp_rim_single_report() );
+ execute( TC_rim_eutran_to_geran() );
+
+ execute( TC_cell_change_different_rai_ci_attach() );
+ execute( TC_cell_change_different_rai_ci_data() );
+ execute( TC_cell_change_different_ci_attach() );
+ execute( TC_cell_change_different_ci_data() );
+
+ execute( TC_sgsn_context_req_in() );
+ execute( TC_sgsn_context_req_out() );
+
/* At the end, may crash osmo-sgsn, see OS#3957, OS#4245 */
execute( TC_attach_req_id_req_ra_update() );
}
diff --git a/sgsn/SGSN_Tests_Iu.ttcn b/sgsn/SGSN_Tests_Iu.ttcn
index 2b63b4ed..236a6a7f 100644
--- a/sgsn/SGSN_Tests_Iu.ttcn
+++ b/sgsn/SGSN_Tests_Iu.ttcn
@@ -1,6 +1,7 @@
module SGSN_Tests_Iu {
import from Osmocom_Types all;
+import from Osmocom_VTY_Functions all;
import from SGSN_Tests all;
@@ -36,6 +37,29 @@ testcase TC_iu_attach() runs on test_CT {
f_cleanup();
}
+testcase TC_iu_attach_encr() runs on test_CT {
+ /* MS -> SGSN: Attach Request IMSI
+ * MS <- SGSN: Identity Request IMEI
+ * MS -> SGSN: Identity Response IMEI
+ * MS <- SGSN: Auth Request
+ * MS -> SGSN: Auth Response
+ * MS <- SGSN: Security Mode Command
+ * MS -> SGSN: Security Mode Complete
+ * hNodeB <- SGSN: Common Id
+ * MS <- SGSN: Attach Accept
+ * MS -> SGSN: Attach Complete
+ */
+ var BSSGP_ConnHdlr vc_conn;
+ g_ranap_enable := true;
+ f_init();
+ f_vty_config(SGSNVTY, "sgsn", "encryption uea 1 2");
+ f_sleep(1.0);
+ vc_conn := f_start_handler(refers(f_TC_iu_attach), testcasename(), g_gb, 1001, expect_ciph := true);
+ vc_conn.done;
+ f_vty_config(SGSNVTY, "sgsn", "encryption uea 0");
+ f_cleanup();
+}
+
private function f_TC_iu_attach_geran_rau(charstring id) runs on BSSGP_ConnHdlr {
var PdpActPars apars := valueof(t_PdpActPars(mp_ggsn_ip));
@@ -85,6 +109,7 @@ testcase TC_geran_attach_iu_rau() runs on test_CT {
control {
execute( TC_iu_attach() );
+ execute( TC_iu_attach_encr() );
execute( TC_iu_attach_geran_rau() );
execute( TC_geran_attach_iu_rau() );
}
diff --git a/sgsn/SGSN_Tests_NS.ttcn b/sgsn/SGSN_Tests_NS.ttcn
new file mode 100644
index 00000000..e5d012f2
--- /dev/null
+++ b/sgsn/SGSN_Tests_NS.ttcn
@@ -0,0 +1,120 @@
+module SGSN_Tests_NS {
+
+/* Osmocom SGSN test suite in TTCN-3
+ * (C) 2020 sysmocom - s.f.m.c. GmbH
+ * 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
+ */
+
+import from Osmocom_Types all;
+import from Osmocom_Gb_Types all;
+import from Osmocom_VTY_Functions all;
+import from NS_Types all;
+import from RAW_NS all;
+import from SGSN_Tests all;
+
+type component RAW_Test_CT extends RAW_NS_CT, test_CT {
+}
+
+testcase TC_NS_connect_reset() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+
+ /* Send a NS-ALIVE */
+ f_outgoing_ns_reset();
+
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+testcase TC_NS_connect_alive() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+
+ /* Send a NS-ALIVE */
+ NSCP[0].send(t_NS_ALIVE);
+ alt {
+ [] NSCP[0].receive(t_NS_ALIVE_ACK);
+ [] NSCP[0].receive(tr_NS_STATUS(*)) { setverdict(fail); }
+ [] NSCP[0].receive { repeat; }
+ }
+
+ f_sleep(1.0);
+ f_clean_ns_codec();
+}
+
+/* perform outgoing SNS-SIZE procedure */
+testcase TC_SNS_size() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+ g_handle_rx_alive := true;
+
+ f_outgoing_sns_size();
+ setverdict(pass);
+}
+
+/* outgoing SNS-SIZE procedure with more BSS side IPs than SGSN can handle */
+testcase TC_SNS_size_too_big() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+ g_handle_rx_alive := true;
+
+ f_outgoing_sns_size(cause := NS_CAUSE_INVALID_NR_OF_NSVCS, num_ip := 100);
+ setverdict(pass);
+}
+
+/* perform outgoing SNS-CONFIG procedure (for BSS) */
+testcase TC_SNS_config_bss() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+ g_handle_rx_alive := true;
+
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ setverdict(pass);
+}
+
+/* perform incoming SNS-CONFIG procedure (for SGSN) */
+testcase TC_SNS_config_sgsn() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 10.0);
+ g_handle_rx_alive := true;
+
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ setverdict(pass);
+}
+
+/* perform full SNS handshake and then outbound NS-ALIVE */
+testcase TC_SNS_and_alive() runs on RAW_Test_CT {
+ f_init_vty();
+ f_init_ns_codec(mp_nsconfig[0], guard_secs := 120.0);
+ g_handle_rx_alive := true;
+
+ f_outgoing_sns_size();
+ f_outgoing_sns_config();
+ f_incoming_sns_config();
+ f_outgoing_ns_alive();
+ setverdict(pass);
+}
+
+control {
+
+ if (mp_nsconfig[0].handle_sns) {
+ execute( TC_SNS_size() );
+ execute( TC_SNS_size_too_big() );
+ execute( TC_SNS_config_bss() );
+ execute( TC_SNS_config_sgsn() );
+ execute( TC_SNS_and_alive() );
+ } else {
+ execute( TC_NS_connect_alive() );
+ execute( TC_NS_connect_reset() );
+ }
+}
+
+}
diff --git a/sgsn/SGSN_Tests_SNS.cfg b/sgsn/SGSN_Tests_SNS.cfg
new file mode 100644
index 00000000..d4dcea09
--- /dev/null
+++ b/sgsn/SGSN_Tests_SNS.cfg
@@ -0,0 +1,72 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./SGSN_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+*.SGSNVTY.CTRL_HOSTNAME := "127.0.0.10"
+
+[MODULE_PARAMETERS]
+SGSN_Tests.mp_nsconfig := {
+ {
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
+ },
+ {
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
+ },
+ {
+ handle_sns := true,
+ nsvc := {
+ {
+ provider := {
+ ip := {
+ address_family := AF_INET,
+ local_ip := "127.0.0.103",
+ remote_ip := "127.0.0.10"
+ }
+ }
+ }
+ }
+ }
+}
+SGSN_Tests.mp_ranap_cfg := {
+ {
+ sctp_addr := { 23908, "127.0.0.103", 2905, "127.0.0.200" }
+ }
+}
+SGSN_Tests.mp_hlr_ip := "127.0.0.103"
+SGSN_Tests.mp_ggsn_ip := "127.0.0.103"
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+SGSN_Tests.control
+SGSN_Tests_Iu.control
+SGSN_Tests_NS.control
diff --git a/sgsn/expected-results.xml b/sgsn/expected-results.xml
index 39d5529d..bef13dc9 100644
--- a/sgsn/expected-results.xml
+++ b/sgsn/expected-results.xml
@@ -1,9 +1,10 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='57' failures='3' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='74' failures='4' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='SGSN_Tests' name='TC_attach' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_mnc3' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_umts_aka_umts_res' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_umts_aka_gsm_sres' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_timeout_after_pdp_act' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_auth_id_timeout' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_auth_sai_timeout' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_auth_sai_reject' time='MASKED'/>
@@ -37,6 +38,11 @@
<testcase classname='SGSN_Tests' name='TC_attach_rau_a_a' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_rau_a_b' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_usim_resync' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_usim_a54_a54' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_usim_a54_a53' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_usim_a53_a54' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_usim_a50_a54' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_attach_usim_a54_a50' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_detach_unknown_nopoweroff' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_detach_unknown_poweroff' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_detach_nopoweroff' time='MASKED'/>
@@ -68,8 +74,34 @@
<testcase classname='SGSN_Tests' name='TC_llc_null' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_llc_sabm_dm_llgmm' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_llc_sabm_dm_ll5' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_suspend_nopaging' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_suspend_resume' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_suspend_rau' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_paging_ps' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_bssgp_rim_single_report' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_rim_eutran_to_geran' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_cell_change_different_rai_ci_attach' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_cell_change_different_rai_ci_data' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_cell_change_different_ci_attach' time='MASKED'/>
+ <testcase classname='SGSN_Tests' name='TC_cell_change_different_ci_data' time='MASKED'/>
<testcase classname='SGSN_Tests' name='TC_attach_req_id_req_ra_update' time='MASKED'/>
+ <!-- SGSN_Tests_Iu testcases start here -->
<testcase classname='SGSN_Tests_Iu' name='TC_iu_attach' time='MASKED'/>
- <testcase classname='SGSN_Tests_Iu' name='TC_iu_attach_geran_rau' time='MASKED'/>
+ <testcase classname='SGSN_Tests_Iu' name='TC_iu_attach_encr' time='MASKED'/>
+ <testcase classname='SGSN_Tests_Iu' name='TC_iu_attach_geran_rau' time='MASKED'>
+ <failure type='fail-verdict'>"BSSGP_Emulation.ttcnpp:830 : Couldn't find Component for TLLI 'E918E6AA'O"
+ SGSN_Tests_Iu.ttcn:MASKED SGSN_Tests_Iu control part
+ SGSN_Tests_Iu.ttcn:MASKED TC_iu_attach_geran_rau testcase
+ </failure>
+ </testcase>
<testcase classname='SGSN_Tests_Iu' name='TC_geran_attach_iu_rau' time='MASKED'/>
+ <!-- SGSN_Tests_NS (handle_sns == true) testcases start here -->
+ <testcase classname='SGSN_Tests_NS' name='TC_SNS_size' time='MASKED'/>
+ <testcase classname='SGSN_Tests_NS' name='TC_SNS_size_too_big' time='MASKED'/>
+ <testcase classname='SGSN_Tests_NS' name='TC_SNS_config_bss' time='MASKED'/>
+ <testcase classname='SGSN_Tests_NS' name='TC_SNS_config_sgsn' time='MASKED'/>
+ <testcase classname='SGSN_Tests_NS' name='TC_SNS_and_alive' time='MASKED'/>
+ <!-- SGSN_Tests_NS (handle_sns == false) testcases start here -->
+ <testcase classname='SGSN_Tests_NS' name='TC_NS_connect_alive' time='MASKED'/>
+ <testcase classname='SGSN_Tests_NS' name='TC_NS_connect_reset' time='MASKED'/>
</testsuite>
diff --git a/sgsn/gen_links.sh b/sgsn/gen_links.sh
index bd3a7eaf..8df1a875 100755
--- a/sgsn/gen_links.sh
+++ b/sgsn/gen_links.sh
@@ -9,7 +9,7 @@ BASEDIR=../deps
#gen_links $DIR $FILES
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
-FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h"
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
@@ -83,17 +83,19 @@ FILES+="RANAP_Types.ttcn RANAP_Templates.ttcn RANAP_CodecPort.ttcn RANAP_EncDec.
gen_links $DIR $FILES
DIR=../library
-FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn GSM_RR_Types.ttcn Osmocom_Types.ttcn RLCMAC_Templates.ttcn RLCMAC_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn RLCMAC_EncDec.cc "
-FILES+="NS_Emulation.ttcn NS_CodecPort.ttcn NS_CodecPort_CtrlFunct.ttcn NS_CodecPort_CtrlFunctDef.cc "
-FILES+="BSSGP_Emulation.ttcn Osmocom_Gb_Types.ttcn "
+FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn "
+FILES+="RAW_NS.ttcnpp NS_Provider_IPL4.ttcn NS_Emulation.ttcnpp "
+FILES+="BSSGP_Emulation.ttcnpp Osmocom_Gb_Types.ttcn "
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
FILES+="Osmocom_VTY_Functions.ttcn "
FILES+="LLC_Templates.ttcn L3_Templates.ttcn L3_Common.ttcn "
FILES+="RAN_Emulation.ttcnpp RAN_Adapter.ttcnpp SCCP_Templates.ttcn "
# IPA_Emulation + dependencies
-FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc Native_Functions.ttcn Native_FunctionDefs.cc GSUP_Types.ttcn GSUP_Emulation.ttcn "
-FILES+="GTP_CodecPort.ttcn GTP_CodecPort_CtrlFunct.ttcn GTP_CodecPort_CtrlFunctDef.cc GTP_Emulation.ttcn
-GTP_Templates.ttcn IPCP_Types.ttcn "
+FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="PCO_Types.ttcn GSUP_Types.ttcn GSUP_Templates.ttcn GSUP_Emulation.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_Templates.ttcn "
+FILES+="GTP_Emulation.ttcn IPCP_Types.ttcn RAW_NS.ttcnpp "
gen_links $DIR $FILES
ignore_pp_results
diff --git a/sgsn/osmo-sgsn.cfg b/sgsn/osmo-sgsn.cfg
index 7ac50bcc..4a5f2361 100644
--- a/sgsn/osmo-sgsn.cfg
+++ b/sgsn/osmo-sgsn.cfg
@@ -2,27 +2,49 @@
! OsmoSGSN (1.2.0.46-e77e-dirty) configuration saved from vty
!!
!
+log gsmtap 127.0.0.1
+ logging level set-all debug
+ logging filter all 1
+!
log stderr
logging filter all 1
- logging color 1
- logging print category 1
- logging timestamp 1
logging print extended-timestamp 1
- logging print file 1
- logging level set-all notice
+ logging print file basename last
+ logging print category-hex 0
+ logging print category 1
+ logging print level 1
+ logging color 1
logging level mm debug
+ logging level pag notice
+ logging level meas notice
+ logging level ref notice
logging level gprs debug
- logging level ns info
- logging level bssgp info
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp info
logging level llc debug
logging level sndcp debug
+ logging level slhc notice
logging level ranap info
logging level sua info
logging level v42bis info
logging level lglobal info
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
logging level lgtp debug
+ logging level lstats notice
logging level lgsup debug
+ logging level loap notice
+ logging level lss7 notice
logging level lsccp info
+ logging level lsua notice
+ logging level lm3ua notice
+ logging level lmgcp notice
!
stats interval 5
!
@@ -36,6 +58,8 @@ cs7 instance 0
point-code 0.23.4
asp asp-clnt-OsmoSGSN-A 2905 0 m3ua
remote-ip 127.0.0.200
+ role asp
+ sctp-role client
as as-clnt-OsmoSGSN-A m3ua
asp asp-clnt-OsmoSGSN-A
routing-key 3 0.23.4
@@ -47,9 +71,11 @@ ns
timer tns-test 30
timer tns-alive 3
timer tns-alive-retries 10
- encapsulation udp local-ip 127.0.0.10
- encapsulation udp local-port 23000
- encapsulation framerelay-gre enabled 0
+ bind udp local10
+ listen 127.0.0.10 23000
+ accept-ipaccess
+ bind udp local10_1
+ listen 127.0.0.10 23001
bssgp
sgsn
gtp local-ip 127.0.0.10
@@ -77,3 +103,6 @@ sgsn
timer t3397 8
no compression rfc1144
no compression v42bis
+ mme test-mme0
+ gtp remote-ip 127.0.0.103
+ gtp ran-info-relay 262 42 3
diff --git a/sgsn/osmo-sgsn.sns.cfg b/sgsn/osmo-sgsn.sns.cfg
new file mode 100644
index 00000000..327535e3
--- /dev/null
+++ b/sgsn/osmo-sgsn.sns.cfg
@@ -0,0 +1,107 @@
+!
+! OsmoSGSN (1.2.0.46-e77e-dirty) configuration saved from vty
+!!
+!
+log gsmtap 127.0.0.1
+ logging level set-all debug
+ logging filter all 1
+!
+log stderr
+ logging filter all 1
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging print category-hex 0
+ logging print category 1
+ logging print level 1
+ logging color 1
+ logging level mm debug
+ logging level pag notice
+ logging level meas notice
+ logging level ref notice
+ logging level gprs debug
+ logging level lns debug
+ logging level lnssignal debug
+ logging level lbssgp info
+ logging level llc debug
+ logging level sndcp debug
+ logging level slhc notice
+ logging level ranap info
+ logging level sua info
+ logging level v42bis info
+ logging level lglobal info
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp debug
+ logging level lstats notice
+ logging level lgsup debug
+ logging level loap notice
+ logging level lss7 notice
+ logging level lsccp info
+ logging level lsua notice
+ logging level lm3ua notice
+ logging level lmgcp notice
+!
+stats interval 5
+!
+line vty
+ no login
+ bind 127.0.0.10
+ctrl
+ bind 127.0.0.10
+!
+cs7 instance 0
+ point-code 0.23.4
+ asp asp-clnt-OsmoSGSN-A 2905 0 m3ua
+ remote-ip 127.0.0.200
+ role asp
+ sctp-role client
+ as as-clnt-OsmoSGSN-A m3ua
+ asp asp-clnt-OsmoSGSN-A
+ routing-key 3 0.23.4
+ns
+ timer tns-block 3
+ timer tns-block-retries 3
+ timer tns-reset 3
+ timer tns-reset-retries 3
+ timer tns-test 30
+ timer tns-alive 3
+ timer tns-alive-retries 10
+ bind udp local10
+ listen 127.0.0.10 23000
+ accept-dynamic-ip-sns
+ bind udp local10_1
+ listen 127.0.0.10 23001
+ ip-sns-default bind local10
+ !ip-sns-default bind local10_1
+bssgp
+sgsn
+ gtp local-ip 127.0.0.10
+ ggsn 0 remote-ip 127.0.0.103
+ ggsn 0 gtp-version 1
+ gsup remote-ip 127.0.0.103
+ gsup remote-port 4222
+ auth-policy remote
+ gsup oap-id 0
+ ! apn * ggsn 0
+ no cdr filename
+ no cdr trap
+ cdr interval 600
+ timer t3312 600
+ timer t3322 6
+ timer t3350 6
+ timer t3360 6
+ timer t3370 6
+ timer t3313 30
+ timer t3314 44
+ timer t3316 44
+ timer t3385 8
+ timer t3386 8
+ timer t3395 8
+ timer t3397 8
+ no compression rfc1144
+ no compression v42bis
diff --git a/sgsn/osmo-stp.cfg b/sgsn/osmo-stp.cfg
index b42f967a..23c4e8f6 100644
--- a/sgsn/osmo-stp.cfg
+++ b/sgsn/osmo-stp.cfg
@@ -4,16 +4,33 @@
!
log gsmtap 127.0.0.1
logging level set-all debug
+ logging filter all 1
!
log stderr
- logging color 1
logging filter all 1
- logging print level 1
- logging print category 1
- logging print category-hex 0
- logging print file basename last
logging print extended-timestamp 1
- logging level set-all debug
+ logging print file basename last
+ logging print category-hex 0
+ logging print category 1
+ logging print level 1
+ logging color 1
+ logging level lglobal notice
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp notice
+ logging level lstats notice
+ logging level lgsup notice
+ logging level loap notice
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp notice
!
line vty
no login
@@ -23,6 +40,8 @@ cs7 instance 0
asp virt-rnc0-0 23908 2905 m3ua
local-ip 127.0.0.200
remote-ip 127.0.0.103
+ role sg
+ sctp-role server
as virt-rnc0 m3ua
asp virt-rnc0-0
routing-key 2 0.24.3
diff --git a/sgsn/regen_makefile.sh b/sgsn/regen_makefile.sh
index a239a3b4..5c9c5ea8 100755
--- a/sgsn/regen_makefile.sh
+++ b/sgsn/regen_makefile.sh
@@ -1,9 +1,37 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp *.asn BSSGP_EncDec.cc LLC_EncDec.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc NS_CodecPort_CtrlFunctDef.cc RLCMAC_EncDec.cc Native_FunctionDefs.cc TELNETasp_PT.cc IPA_CodecPort_CtrlFunctDef.cc GTPU_EncDec.cc GTPC_EncDec.cc GTP_CodecPort_CtrlFunctDef.cc SCCP_EncDec.cc SCTPasp_PT.cc RANAP_EncDec.cc "
+NAME=SGSN_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_GSUP -DIPA_EMULATION_CTRL -DUSE_MTP3_DISTRIBUTOR -DRAN_EMULATION_RANAP"
+FILES="
+ *.asn
+ *.ttcn
+ *.ttcnpp
+ BSSGP_EncDec.cc
+ GTPC_EncDec.cc
+ GTPU_EncDec.cc
+ GTPv1C_CodecPort_CtrlFunctDef.cc
+ GTPv1U_CodecPort_CtrlFunctDef.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ LLC_EncDec.cc
+ Native_FunctionDefs.cc
+ RANAP_EncDec.cc
+ SCCP_EncDec.cc
+ SCTPasp_PT.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
-../regen-makefile.sh SGSN_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DBSSGP_EM_L3
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_GSUP
+ -DRAN_EMULATION_RANAP
+ -DUSE_MTP3_DISTRIBUTOR
+"
-sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lfftranscode/' Makefile
+../regen-makefile.sh -e $NAME $FILES
+
+sed -i -e 's/^LINUX_LIBS = -lxml2 -lsctp/LINUX_LIBS = -lxml2 -lsctp -lfftranscode/' Makefile
diff --git a/simtrace/gen_links.sh b/simtrace/gen_links.sh
index 72787b90..3bce04d8 100755
--- a/simtrace/gen_links.sh
+++ b/simtrace/gen_links.sh
@@ -4,9 +4,9 @@ BASEDIR=../deps
. ../gen_links.sh.inc
-#DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
-#FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
-#gen_links $DIR $FILES
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCConversion_Functions.ttcn TCCConversion.cc"
+gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.USB/src
FILES="USB_PT.cc USB_PT.hh USB_PortType.ttcn USB_PortTypes.ttcn USB_Templates.ttcn USB_Types.ttcn USB_Component.ttcn "
@@ -15,6 +15,7 @@ gen_links $DIR $FILES
DIR=../library
FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn "
FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
+FILES+="SIMTRACE_Types.ttcn SIMTRACE_Templates.ttcn SIMTRACE_Emulation.ttcn "
gen_links $DIR $FILES
ignore_pp_results
diff --git a/simtrace/regen_makefile.sh b/simtrace/regen_makefile.sh
index 3f2d4727..04c8397e 100755
--- a/simtrace/regen_makefile.sh
+++ b/simtrace/regen_makefile.sh
@@ -1,8 +1,18 @@
#!/bin/sh
-FILES="*.ttcn USB_PT.cc Native_FunctionDefs.cc "
+NAME=SIMTRACE_Tests
-../regen-makefile.sh SIMTRACE_Tests.ttcn $FILES
+FILES="
+ *.ttcn
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ USB_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
#sed -i -e 's/^LINUX_LIBS = -lxml2/LINUX_LIBS = -lxml2 -lusb/' Makefile
sed -i -e '/^LINUX_LIBS/ s/$/ `pkg-config --libs libusb-1.0`/' Makefile
diff --git a/sip/SIP_Tests.default b/sip/SIP_Tests.default
index faf87c8d..4434a1a5 100644
--- a/sip/SIP_Tests.default
+++ b/sip/SIP_Tests.default
@@ -25,7 +25,6 @@ mtc.FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
[MODULE_PARAMETERS]
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoSIPcon";
-MNCC_Emulation.mp_mncc_version := 6;
[MAIN_CONTROLLER]
diff --git a/sip/SIP_Tests.ttcn b/sip/SIP_Tests.ttcn
index 9de27233..95f09e85 100644
--- a/sip/SIP_Tests.ttcn
+++ b/sip/SIP_Tests.ttcn
@@ -12,6 +12,8 @@ module SIP_Tests {
import from General_Types all;
import from Osmocom_Types all;
+import from Native_Functions all;
+import from Misc_Helpers all;
import from Osmocom_CTRL_Functions all;
import from Osmocom_CTRL_Types all;
@@ -24,6 +26,7 @@ import from MNCC_Emulation all;
import from MNCC_Types all;
import from SDP_Types all;
+import from SDP_Templates all;
import from SIP_Emulation all;
import from SIPmsg_Types all;
@@ -59,8 +62,17 @@ type record CallPars {
charstring called,
uint32_t mncc_call_id optional,
+ CallParsComputed comp optional,
- CallParsComputed comp optional
+ charstring sip_rtp_addr,
+ uint16_t sip_rtp_port,
+ charstring cn_rtp_addr,
+ uint16_t cn_rtp_port,
+
+ /* Send SDP to MNCC, and expect to receive SDP from MNCC. mncc_with_sdp := false tests legacy compatibility to
+ * the time when we did not include SDP in MNCC messages. mncc_with_sdp := true expects SDP to pass through the
+ * SUT osmo-sip-connector unchanged. */
+ boolean mncc_with_sdp
}
type record CallParsComputed {
@@ -71,29 +83,38 @@ type record CallParsComputed {
integer sip_seq_nr
}
-private template (value) CallPars t_CallPars(boolean is_mo) := {
+private template (value) CallPars t_CallPars(boolean is_mo, boolean mncc_with_sdp := true) := {
is_mo := is_mo,
calling := "12345",
called := "98766",
+
mncc_call_id := omit,
- comp := omit
+ comp := omit,
+ sip_rtp_addr := "1.2.3.4",
+ sip_rtp_port := 1234,
+ cn_rtp_addr := "5.6.7.8",
+ cn_rtp_port := 5678,
+ mncc_with_sdp := mncc_with_sdp
}
private function f_CallPars_compute(inout CallPars cp) {
if (cp.is_mo) {
- cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.called, mp_local_host, 5060));
- cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.calling, mp_osmosip_host, 5060));
- cp.mncc_call_id := f_rnd_int(429496725);
+ cp.comp.sip_url_ext := valueof(ts_SipAddr(ts_HostPort(mp_local_host, 5060),
+ ts_UserInfo(cp.called)));
+ cp.comp.sip_url_gsm := valueof(ts_SipAddr(ts_HostPort(mp_osmosip_host, 5060),
+ ts_UserInfo(cp.calling)));
+ cp.mncc_call_id := f_sip_rand_seq_nr();
} else {
- cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.calling, mp_local_host, 5060));
- cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.called, mp_osmosip_host, 5060));
+ cp.comp.sip_url_ext := valueof(ts_SipAddr(ts_HostPort(mp_local_host, 5060),
+ ts_UserInfo(cp.calling)));
+ cp.comp.sip_url_gsm := valueof(ts_SipAddr(ts_HostPort(mp_osmosip_host, 5060),
+ ts_UserInfo(cp.called)));
cp.comp.sip_call_id := hex2str(f_rnd_hexstring(15));
}
- cp.comp.sip_seq_nr := f_rnd_int(4294967295);
+ cp.comp.sip_seq_nr := f_sip_rand_seq_nr();
cp.comp.sip_body := "";
}
-
function f_init_mncc(charstring id) runs on test_CT {
id := id & "-MNCC";
var MnccOps ops := {
@@ -101,13 +122,13 @@ function f_init_mncc(charstring id) runs on test_CT {
unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
};
- vc_MNCC := MNCC_Emulation_CT.create(id);
+ vc_MNCC := MNCC_Emulation_CT.create(id) alive;
map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_mncc, true));
}
function f_init() runs on test_CT {
- //f_ipa_ctrl_start(mp_osmosip_host, mp_osmosip_port_ctrl);
+ //f_ipa_ctrl_start_client(mp_osmosip_host, mp_osmosip_port_ctrl);
f_init_mncc("SIP_Test");
log("end of f_init_mncc");
f_init_sip(vc_SIP, "SIP_Test");
@@ -126,7 +147,7 @@ runs on test_CT return ConnHdlr {
var ConnHdlr vc_conn;
var charstring id := testcasename();
- vc_conn := ConnHdlr.create(id);
+ vc_conn := ConnHdlr.create(id) alive;
connect(vc_conn:SIP, vc_SIP:CLIENT);
connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
@@ -161,55 +182,190 @@ template (value) ConnHdlrPars t_Pars := {
g_cp := omit
}
+altstep as_SIP_expect_resp(template PDU_SIP_Response sip_expect) runs on ConnHdlr
+{
+ [] SIP.receive(sip_expect);
+ [] SIP.receive {
+ log("FAIL: expected SIP message ", sip_expect);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
+ }
+}
+
+function f_SIP_expect_req(template PDU_SIP_Request sip_expect) runs on ConnHdlr return PDU_SIP_Request
+{
+ var PDU_SIP_Request rx;
+ alt {
+ [] SIP.receive(sip_expect) -> value rx;
+ [] SIP.receive {
+ log("FAIL: expected SIP message ", sip_expect);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
+ }
+ }
+ return rx;
+}
+
+/* Update 'last_sdp', and match with expectation of what the current SDP should be.
+ * Useful to ensure that MNCC or SIP send and possibly resend only the expected SDP.
+ * last_sdp keeps the last non-empty rx_sdp, across multiple check_sdp() invocations.
+ * rx_sdp is the SDP charstring just received. If it is nonempty, update last_sdp to rx_sdp.
+ * After updating last_sdp as appropriate, match last_sdp with expect_sdp. */
+private function check_sdp(inout charstring last_sdp,
+ charstring rx_sdp,
+ template charstring expect_sdp)
+{
+ /* If there is new SDP, store it. */
+ if (lengthof(rx_sdp) > 0) {
+ if (last_sdp != rx_sdp) {
+ log("SDP update from ", last_sdp, " to ", rx_sdp);
+ }
+
+ /* If MNCC sent SDP data, remember it as the last valid SDP */
+ last_sdp := rx_sdp;
+ }
+ /* Validate expectations of the SDP data */
+ if (not match(last_sdp, expect_sdp)) {
+ log("FAIL: expected SDP ", expect_sdp, " but got ", last_sdp);
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "unexpected SDP");
+ }
+}
+
/* Establish a mobile terminated call described in 'cp' */
function f_establish_mt(inout CallPars cp) runs on ConnHdlr {
var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
- var PDU_SIP_Request sip_req;
var MNCC_PDU mncc;
+ /* The last SDP that the MSC received via MNCC from osmo-sip-connector */
+ var charstring sdp_to_msc := "";
+ /* At first, allow any empty and nonempty SDP. As the test progresses, this may expect specific SDP instead. */
+ var template charstring expect_sdp_to_msc := *;
+
+ /* If cp.mncc_with_sdp == true, expect SDP forwarding like this:
+ *
+ * SDP1: SIP agent's RTP and codec info
+ * SDP2: osmo-msc's RTP and codec info
+ *
+ * MNCC osmo-sip-connector SIP
+ * |<--SDP1----- SIP Invite
+ * |-----------> SIP (Invite) Trying
+ * <--SDP1-------| MNCC SETUP req
+ * ------------->| MNCC CALL CONF ind
+ * <-------------| MNCC RTP CREATE (SDP optional, still unchanged from SDP1)
+ * -------SDP2-->| MNCC RTP CREATE
+ * ------------->| MNCC ALERT ind
+ * |--------------> SIP (Invite) Ringing
+ * (MT picks up) |
+ * ------------->| MNCC SETUP CNF
+ * <-------------| MNCC RTP CONNECT (SDP optional, still unchanged from SDP1)
+ * |--------SDP2--> SIP (Invite) OK
+ * |<-------------- SIP ACK
+ * <-------------| MNCC SETUP COMPL (SDP optional, still unchanged from SDP1)
+ */
+
/* Ask MNCC_Emulation to "expect" a call to the given called number */
f_create_mncc_expect(cp.called);
/* OSC <- SIP: A party sends SIP invite for a MT-call into OSC */
SIP.send(ts_SIP_INVITE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
- cp.comp.sip_seq_nr, cp.comp.sip_body));
+ ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
+ ts_Contact_SipAddr(cp.comp.sip_url_ext),
+ cp.comp.sip_seq_nr, cp.comp.sip_body));
+ if (cp.mncc_with_sdp) {
+ /* We just sent SDP via SIP, now expect the same SDP in MNCC to the MSC */
+ expect_sdp_to_msc := cp.comp.sip_body;
+ }
+
+ /* OSC -> SIP */
+ as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+ *,
+ "INVITE", 100, ?, "Trying", *));
+
+ alt {
/* MSC <- OSC: OSC generates MNCC_SETUP_REQ from INVITE */
- MNCC.receive(tr_MNCC_SETUP_req) -> value mncc {
- cp.mncc_call_id := mncc.u.signal.callref;
+ [] MNCC.receive(tr_MNCC_SETUP_req) -> value mncc {
+ cp.mncc_call_id := mncc.u.signal.callref;
+ /* Expect the SDP sent via SIP to arrive in MNCC */
+ check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
}
- /* OSC -> SIP */
- SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
- "INVITE", 100, ?, "Trying", *));
+ [] SIP.receive {
+ setverdict(fail, "Received unexpected SIP response");
+ SIP.send(ts_SIP_ACK(cp.comp.sip_call_id,
+ cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+ ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
+ cp.comp.sip_seq_nr, omit));
+ mtc.stop;
+ }
+ }
/* MSC -> OSC: After MS sends CALL CONF in response to SETUP */
MNCC.send(ts_MNCC_CALL_CONF_ind(cp.mncc_call_id));
/* MSC <- OSC: OSC asks MSC to create RTP socket */
- MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id));
- MNCC.send(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
+ MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
+ }
+
+ /* MSC -> OSC: SDP that the MSC will send via MNCC */
+ var charstring cn_sdp := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.cn_rtp_addr) & " " & cp.cn_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.cn_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ /* OSC -> SIP: what SDP to expect in SIP from osmo-sip-connector */
+ var template charstring expect_sdp_to_sip := pattern "*" & cp.cn_rtp_addr & "*";
+
+ mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
+ mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
+ mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
+ mncc.u.rtp.rtp_port := cp.cn_rtp_port;
+ if (cp.mncc_with_sdp) {
+ /* MSC -> OSC: tell OSC our RTP info in SDP form */
+ mncc.u.rtp.sdp := cn_sdp;
+ /* OSC -> SIP: and expect it unchanged on SIP later, but allow osmo-sip-connector to append an
+ * "a=sendrecv;" */
+ expect_sdp_to_sip := pattern cn_sdp & "*";
+ }
+ MNCC.send(mncc);
/* MSC -> OSC: After MS is ringing and sent CC ALERTING */
MNCC.send(ts_MNCC_ALERT_ind(cp.mncc_call_id));
+
+ /* Now expect SIP response "Ringing" back to MO, containing the same SDP information as in the MNCC RTP CREATE
+ * sent to OSC above */
SIP.clear;
- SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
- "INVITE", 180, ?, "Ringing", *));
+
+ /* 180 Ringing should not contain any SDP. */
+ as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+ *,
+ "INVITE", 180, ?, "Ringing", omit));
/* MSC -> OSC: After MT user has picked up and sent CC CONNECT */
MNCC.send(ts_MNCC_SETUP_CNF(cp.mncc_call_id));
SIP.clear;
- interleave {
/* MSC <- OSC: OSC asks MSC to connect its RTP stream to remote end */
- [] MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id)) {}
- /* OSC -> SIP: OSC confirms call establishment to SIP side */
- [] SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, ?,
- "INVITE", 200, ?, "OK", ?)) {}
+ MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id, f_addrstr2addr(cp.sip_rtp_addr), cp.sip_rtp_port))
+ -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
}
+
+ /* OSC -> SIP: OSC confirms call establishment to SIP side */
+ as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+ contact := ?,
+ method := "INVITE", status_code := 200,
+ seq_nr := ?, reason := "OK",
+ body := expect_sdp_to_sip));
+
/* OSC <- SIP: SIP world acknowledges "200 OK" */
- SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+ SIP.send(ts_SIP_ACK(cp.comp.sip_call_id,
+ cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+ ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
cp.comp.sip_seq_nr, omit));
/* MSC <- OSC: OSC sends SETUP COMPL to MNCC (which triggers CC CONNECT ACK */
- MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id));
+ MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
+ }
}
/* Establish a mobile originated call described in 'cp' */
@@ -220,48 +376,119 @@ function f_establish_mo(inout CallPars cp) runs on ConnHdlr {
var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
var PDU_SIP_Request sip_req;
var integer seq_nr;
+ var MNCC_PDU mncc;
+
+ /* The last SDP that the MSC received via MNCC from osmo-sip-connector */
+ var charstring sdp_to_msc := "";
+ /* At first, allow any empty and nonempty SDP. As the test progresses, this may expect specific SDP instead. */
+ var template charstring expect_sdp_to_msc := *;
+
+ /* If cp.mncc_with_sdp == true, expect SDP forwarding like this:
+ *
+ * SDP1: osmo-msc's RTP and codec info
+ * SDP2: SIP agent's RTP and codec info
+ *
+ * MNCC osmo-sip-connector SIP
+ * -------SDP1-->| MNCC SETUP ind
+ * <-------------| MNCC RTP CREATE (?)
+ * |-----SDP1--> SIP Invite
+ * |<----------- SIP (Invite) Trying
+ * <-------------| MNCC CALL PROC req
+ * |<----------- SIP (Invite) Ringing
+ * <-------------| MNCC ALERT req
+ * | (MT picks up)
+ * |<--SDP2----- SIP (Invite) OK
+ * <--SDP2-------| MNCC RTP CONNECT (SDP optional, still unchanged from SDP2)
+ * <-------------| MNCC SETUP rsp (SDP optional, still unchanged from SDP2)
+ * ------------->| MNCC SETUP COMPL ind (SDP optional, still unchanged from SDP1)
+ * |------------> SIP ACK
+ */
+
+ var charstring cn_sdp := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.cn_rtp_addr) & " " & cp.cn_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.cn_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec);
/* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */
- MNCC.send(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
+ mncc := valueof(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
+ if (cp.mncc_with_sdp) {
+ mncc.u.signal.sdp := cn_sdp;
+ }
+ MNCC.send(mncc);
+
/* MSC <- OSC: Create GSM side RTP socket */
MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
- var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
+ mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
mncc.u.rtp.payload_msg_type := oct2int('0300'O);
- MNCC.send(mncc); /* FIXME: port/ip */
+ /* FIXME: makes no sense to send cp.cn_rtp_addr back to the cn. */
+ mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
+ mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
+ mncc.u.rtp.rtp_port := cp.cn_rtp_port;
+ MNCC.send(mncc);
}
+
/* OSC -> SIP: Send INVITE with GSM side IP/Port in SDP */
- SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) -> value sip_req {
- cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
- cp.comp.sip_call_id := sip_req.msgHeader.callId.callid;
- seq_nr := sip_req.msgHeader.cSeq.seqNumber;
- }
+ var template charstring expect_sdp_to_sip := ?;
+ if (cp.mncc_with_sdp) {
+ /* Expect the same SDP as sent to osmo-sip-connector in MNCC, and allow osmo-sip-connector to append an
+ * "a=sendrecv;" */
+ expect_sdp_to_sip := pattern cn_sdp & "*";
+ }
+ sip_req := f_SIP_expect_req(tr_SIP_INVITE(sip_addr_ext.addr.nameAddr.addrSpec, ?,
+ sip_addr_gsm, sip_addr_ext,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+ ?, expect_sdp_to_sip));
+ cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
+ cp.comp.sip_call_id := sip_req.msgHeader.callId.callid;
+ seq_nr := sip_req.msgHeader.cSeq.seqNumber;
+
/* OSC <- SIP: Notify call is proceeding */
SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
"INVITE", 100, seq_nr, "Trying", sip_req.msgHeader.via));
/* MSC <- OSC: "100 Trying" translated to MNCC_CALL_PROC_REQ */
- MNCC.receive(tr_MNCC_CALL_PROC_req(cp.mncc_call_id));
+ MNCC.receive(tr_MNCC_CALL_PROC_req(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.signal.sdp, "");
+ }
- /* OSC <- SIP: SIP-terminated user is ringing now */
+ /* OSC <- SIP: SIP-terminated user is ringing now. 180 Ringing should not contain any SDP. */
SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
- "INVITE", 180, seq_nr, "Ringing", sip_req.msgHeader.via));
+ "INVITE", 180, seq_nr, "Ringing", sip_req.msgHeader.via, omit));
/* MSC <- OSC: "180 Ringing" translated to MNCC_ALERT_REQ */
- MNCC.receive(tr_MNCC_ALERT_req(cp.mncc_call_id)) {}
+ MNCC.receive(tr_MNCC_ALERT_req(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
+ }
/* OSC <- SIP: SIP-terminated user has accepted the call */
SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
"INVITE", 200, seq_nr, "OK", sip_req.msgHeader.via,
cp.comp.sip_body));
- MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id));
+
+ if (cp.mncc_with_sdp) {
+ /* If we expect SDP forwarding, from now on expect MNCC to reflect the SDP that we just sent on SIP. */
+ expect_sdp_to_msc := cp.comp.sip_body;
+ }
+ /* If we don't expect SDP forwarding, just keep expect_sdp_to_msc := *. */
+
+ MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
+ }
/* MSC <- OSC: "200 OK" translated to MNCC_SETUP_RSP */
- MNCC.receive(tr_MNCC_SETUP_rsp(cp.mncc_call_id));
+ MNCC.receive(tr_MNCC_SETUP_rsp(cp.mncc_call_id)) -> value mncc {
+ check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
+ }
/* MSC -> OSC: CC CONNECT ACK was received from MS */
MNCC.send(ts_MNCC_SETUP_COMPL_ind(cp.mncc_call_id));
/* OSC -> SIP: Acknowledge the call */
- SIP.receive(tr_SIP_ACK(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, omit));
+ SIP.receive(tr_SIP_ACK(sip_addr_ext.addr.nameAddr.addrSpec,
+ cp.comp.sip_call_id,
+ sip_addr_gsm,
+ sip_addr_ext,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+ ?, omit));
}
/* Release call from the mobile side */
@@ -272,10 +499,14 @@ function f_release_mobile(inout CallPars cp) runs on ConnHdlr {
SIP.clear;
/* MSC -> OSC: Simulate a CC DISCONNET from the MT user */
MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
+
/* OSC -> SIP: Expect BYE from OSC to SIP side */
- SIP.receive(tr_SIP_BYE(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, *)) -> value sip_req {
- cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
- }
+ sip_req := f_SIP_expect_req(tr_SIP_BYE(sip_addr_ext.addr.nameAddr.addrSpec,
+ cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+ ?, *));
+ cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
+
/* OSC <- SIP: Acknowledge the BYE */
SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
"BYE", 200, sip_req.msgHeader.cSeq.seqNumber, "OK",
@@ -292,21 +523,27 @@ function f_release_sip(inout CallPars cp) runs on ConnHdlr {
var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
/* OSC <- SIP: SIP-side sends a BYE to OSC */
SIP.send(ts_SIP_BYE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
+ ts_Via_from(cp.comp.sip_url_ext.addr.nameAddr.addrSpec.hostPort),
cp.comp.sip_seq_nr, omit));
/* MSC <- OSC: Expect OSC to cause MNCC Disconnect Request */
MNCC.receive(tr_MNCC_DISC_req(cp.mncc_call_id));
/* MSC -> OSC: Indicate GSM side release */
MNCC.send(ts_MNCC_REL_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
/* OSC -> SIP: Confirmation to SIP side */
- SIP.receive(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
- "BYE", 200, cp.comp.sip_seq_nr, "OK", omit));
+ as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_ext.addr.nameAddr.addrSpec.hostPort)),
+ *,
+ "BYE", 200, cp.comp.sip_seq_nr, "OK", omit));
}
/* Successful MT Call, which is subsequently released by GSM side */
private function f_TC_mt_success_rel_gsm(charstring id) runs on ConnHdlr {
- var CallPars cp := valueof(t_CallPars(false));
+ var CallPars cp := g_pars.g_cp;
f_CallPars_compute(cp);
- cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_sleep(3.0)
f_establish_mt(cp);
@@ -320,15 +557,30 @@ testcase TC_mt_success_rel_gsm() runs on test_CT {
var ConnHdlr vc_conn;
f_init();
pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(false, false));
+ vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
+ vc_conn.done;
+}
+testcase TC_mt_success_rel_gsm_ipv6() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+ pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(false, false));
+ pars.g_cp.sip_rtp_addr := "::1";
+ pars.g_cp.cn_rtp_addr := "::2";
vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
vc_conn.done;
}
/* Successful MT Call, which is subsequently released by SIP side */
private function f_TC_mt_success_rel_sip(charstring id) runs on ConnHdlr {
- var CallPars cp := valueof(t_CallPars(false));
+ var CallPars cp := g_pars.g_cp;
f_CallPars_compute(cp);
- cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_sleep(3.0)
f_establish_mt(cp);
@@ -342,6 +594,7 @@ testcase TC_mt_success_rel_sip() runs on test_CT {
var ConnHdlr vc_conn;
f_init();
pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(false, false));
vc_conn := f_start_handler(refers(f_TC_mt_success_rel_sip), pars);
vc_conn.done;
}
@@ -349,9 +602,12 @@ testcase TC_mt_success_rel_sip() runs on test_CT {
/* Successful MO Call, which is subsequently released by GSM side */
private function f_TC_mo_success_rel_gsm(charstring id) runs on ConnHdlr {
- var CallPars cp := valueof(t_CallPars(true));
+ var CallPars cp := g_pars.g_cp;
f_CallPars_compute(cp);
- cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_sleep(3.0)
f_establish_mo(cp);
@@ -365,15 +621,30 @@ testcase TC_mo_success_rel_gsm() runs on test_CT {
var ConnHdlr vc_conn;
f_init();
pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(true, false));
+ vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
+ vc_conn.done;
+}
+testcase TC_mo_success_rel_gsm_ipv6() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+ pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(true, false));
+ pars.g_cp.sip_rtp_addr := "::1";
+ pars.g_cp.cn_rtp_addr := "::2";
vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
vc_conn.done;
}
/* Successful MO Call, which is subsequently released by SIP side */
private function f_TC_mo_success_rel_sip(charstring id) runs on ConnHdlr {
- var CallPars cp := valueof(t_CallPars(true));
+ var CallPars cp := g_pars.g_cp;
f_CallPars_compute(cp);
- cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_sleep(3.0)
f_establish_mo(cp);
@@ -387,15 +658,19 @@ testcase TC_mo_success_rel_sip() runs on test_CT {
var ConnHdlr vc_conn;
f_init();
pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := false));
vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars);
vc_conn.done;
}
/* SETUP followed by DISC results in lingering B-leg (OS#3518)*/
private function f_TC_mo_setup_disc_late_rtp(charstring id) runs on ConnHdlr {
- var CallPars cp := valueof(t_CallPars(true));
+ var CallPars cp := g_pars.g_cp;
f_CallPars_compute(cp);
- cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 0.0.0.0\r\ns=GSM Call\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\nm=audio 0 RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
+ cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
+ f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
+ "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
+ " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
f_sleep(3.0);
var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN));
@@ -415,14 +690,20 @@ private function f_TC_mo_setup_disc_late_rtp(charstring id) runs on ConnHdlr {
MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
mncc.u.rtp.payload_msg_type := oct2int('0300'O);
- MNCC.send(mncc); /* FIXME: port/ip */
+ mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
+ mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
+ mncc.u.rtp.rtp_port := cp.cn_rtp_port;
+ MNCC.send(mncc);
}
/* OSC -> SIP: We should never receive INVITE */
timer T := 10.0;
T.start;
alt {
- [] SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) {
+ [] SIP.receive(tr_SIP_INVITE(sip_addr_ext.addr.nameAddr.addrSpec, ?,
+ sip_addr_gsm, sip_addr_ext,
+ tr_Via_from(f_tr_HostPort_opt_defport(sip_addr_gsm.addr.nameAddr.addrSpec.hostPort)),
+ ?, ?)) {
setverdict(fail, "Received unexpected INVITE");
}
[] T.timeout {
@@ -435,16 +716,41 @@ testcase TC_mo_setup_disc_late_rtp() runs on test_CT {
var ConnHdlr vc_conn;
f_init();
pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := false));
vc_conn := f_start_handler(refers(f_TC_mo_setup_disc_late_rtp), pars);
vc_conn.done;
}
+testcase TC_mt_with_sdp() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+ pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(is_mo := false, mncc_with_sdp := true));
+ vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
+ vc_conn.done;
+}
+
+testcase TC_mo_with_sdp() runs on test_CT {
+ var ConnHdlrPars pars;
+ var ConnHdlr vc_conn;
+ f_init();
+ pars := valueof(t_Pars);
+ pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := true));
+ vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars);
+ vc_conn.done;
+}
+
control {
execute( TC_mt_success_rel_gsm() );
+ execute( TC_mt_success_rel_gsm_ipv6() );
execute( TC_mt_success_rel_sip() );
execute( TC_mo_success_rel_gsm() );
+ execute( TC_mo_success_rel_gsm_ipv6() );
execute( TC_mo_success_rel_sip() );
execute( TC_mo_setup_disc_late_rtp() );
+ execute( TC_mt_with_sdp() );
+ execute( TC_mo_with_sdp() );
}
diff --git a/sip/expected-results.xml b/sip/expected-results.xml
index 2ac1ec52..1d2b6706 100644
--- a/sip/expected-results.xml
+++ b/sip/expected-results.xml
@@ -1,8 +1,12 @@
<?xml version="1.0"?>
-<testsuite name='Titan' tests='5' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+<testsuite name='Titan' tests='9' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
<testcase classname='SIP_Tests' name='TC_mt_success_rel_gsm' time='MASKED'/>
+ <testcase classname='SIP_Tests' name='TC_mt_success_rel_gsm_ipv6' time='MASKED'/>
<testcase classname='SIP_Tests' name='TC_mt_success_rel_sip' time='MASKED'/>
<testcase classname='SIP_Tests' name='TC_mo_success_rel_gsm' time='MASKED'/>
+ <testcase classname='SIP_Tests' name='TC_mo_success_rel_gsm_ipv6' time='MASKED'/>
<testcase classname='SIP_Tests' name='TC_mo_success_rel_sip' time='MASKED'/>
<testcase classname='SIP_Tests' name='TC_mo_setup_disc_late_rtp' time='MASKED'/>
+ <testcase classname='SIP_Tests' name='TC_mt_with_sdp' time='MASKED'/>
+ <testcase classname='SIP_Tests' name='TC_mo_with_sdp' time='MASKED'/>
</testsuite>
diff --git a/sip/gen_links.sh b/sip/gen_links.sh
index cf097316..4c8456c4 100755
--- a/sip/gen_links.sh
+++ b/sip/gen_links.sh
@@ -9,7 +9,9 @@ FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
gen_links $DIR $FILES
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
-FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h "
+FILES+="TCCOpenSecurity_Functions.ttcn TCCOpenSecurity.cc TCCOpenSecurity_Functions.hh "
+FILES+="TCCDateTime.cc TCCDateTime_Functions.ttcn"
gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
@@ -43,6 +45,7 @@ FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn MN
FILES+="IPA_Types.ttcn IPA_Emulation.ttcnpp IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc "
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
FILES+="RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunctDef.cc "
+FILES+="SDP_Templates.ttcn "
FILES+="SIP_Emulation.ttcn SIP_Templates.ttcn "
gen_links $DIR $FILES
diff --git a/sip/regen_makefile.sh b/sip/regen_makefile.sh
index 722620bf..b737316c 100755
--- a/sip/regen_makefile.sh
+++ b/sip/regen_makefile.sh
@@ -1,8 +1,31 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc IPL4asp_PT.cc
-IPL4asp_discovery.cc SDP_EncDec.cc RTP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc RTP_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc SIPmsg_PT.cc *.c "
+NAME=SIP_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_CTRL -DRAN_EMULATION_CTRL"
+FILES="
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ MNCC_EncDec.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SDP_EncDec.cc
+ SIPmsg_PT.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TCCOpenSecurity.cc
+ TCCDateTime.cc
+ TELNETasp_PT.cc
+ UD_PT.cc
+"
-../regen-makefile.sh SIP_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DRAN_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/smlc/BSC_ConnectionHandler.ttcn b/smlc/BSC_ConnectionHandler.ttcn
new file mode 100644
index 00000000..bd787c7b
--- /dev/null
+++ b/smlc/BSC_ConnectionHandler.ttcn
@@ -0,0 +1,95 @@
+module BSC_ConnectionHandler {
+
+/* BSC Connection Handler of SMLC Tests in TTCN-3
+ * (C) 2020 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
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from SCCPasp_Types all;
+import from BSSAP_Types all;
+import from BSSAP_CodecPort all;
+import from RAN_Emulation all;
+import from BSSMAP_Templates all;
+import from BSSAP_LE_Emulation all;
+import from BSSAP_LE_Types all;
+import from BSSMAP_LE_Templates all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+
+/* this component represents a single subscriber connection at the SMLC. */
+type component BSC_ConnHdlr extends BSSAP_LE_ConnHdlr {
+ /* SCCP Connecction Identifier for the underlying SCCP connection */
+ var integer g_sccp_conn_id;
+
+ port TELNETasp_PT SMLCVTY;
+
+ var TestHdlrParams g_pars;
+
+ var charstring host_bsc := "127.0.0.4";
+
+ var boolean g_vty_initialized := false;
+}
+
+function f_BscConnHdlr_init_vty() runs on BSC_ConnHdlr {
+ if (not g_vty_initialized) {
+ map(self:SMLCVTY, system:SMLCVTY);
+ f_vty_set_prompts(SMLCVTY);
+ f_vty_transceive(SMLCVTY, "enable");
+ g_vty_initialized := true;
+ }
+}
+
+/* initialize all parameters */
+function f_BscConnHdlr_init() runs on BSC_ConnHdlr {
+ f_BscConnHdlr_init_vty();
+}
+
+/* Callback function from general BSSAP_LE_Emulation whenever a connectionless
+ * BSSAP_LE message arrives. Can return a PDU_BSSAP_LE that should be sent in return */
+private function BSSAP_LE_UnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
+ var template PDU_BSSAP_LE resp := omit;
+
+ /* answer all RESET with a RESET ACK */
+ if (match(bssap, tr_BSSMAP_LE_Reset)) {
+ resp := ts_BSSMAP_LE_ResetAck;
+ }
+
+ return resp;
+}
+
+const BssapLeOps BSC_BssapLeOps := {
+ create_cb := refers(BSSAP_LE_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(BSSAP_LE_UnitdataCallback),
+ decode_dtap := false,
+ role_ms := false,
+ sccp_addr_local := omit,
+ sccp_addr_peer := omit
+}
+type record TestHdlrParams {
+ hexstring imsi,
+ integer bssap_le_idx,
+ SCCP_PAR_Address sccp_addr_bsc optional,
+ SCCP_PAR_Address sccp_addr_smlc optional
+};
+
+/* Note: Do not use valueof() to get a value of this template, use
+ * f_gen_test_hdlr_pars() instead in order to get a configuration that is
+ * matched to the current test situation (aoip vs. sccplite) */
+template (value) TestHdlrParams t_def_TestHdlrPars := {
+ imsi := '001019876543210'H,
+ bssap_le_idx := 0,
+ sccp_addr_bsc := omit,
+ sccp_addr_smlc := omit
+}
+
+}
diff --git a/smlc/SMLC_Tests.cfg b/smlc/SMLC_Tests.cfg
new file mode 100644
index 00000000..cc9fd6e4
--- /dev/null
+++ b/smlc/SMLC_Tests.cfg
@@ -0,0 +1,18 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./SMLC_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+SMLC_Tests.control
diff --git a/smlc/SMLC_Tests.default b/smlc/SMLC_Tests.default
new file mode 100644
index 00000000..485d2151
--- /dev/null
+++ b/smlc/SMLC_Tests.default
@@ -0,0 +1,19 @@
+[LOGGING]
+"VirtBSC-SCCP".FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.SMLCVTY.CTRL_MODE := "client"
+*.SMLCVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.SMLCVTY.CTRL_PORTNUM := "4271"
+*.SMLCVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.SMLCVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.SMLCVTY.CTRL_READMODE := "buffered"
+*.SMLCVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.SMLCVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.SMLCVTY.PROMPT1 := "OsmoSMLC> "
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoSMLC";
+
+[EXECUTE]
diff --git a/smlc/SMLC_Tests.ttcn b/smlc/SMLC_Tests.ttcn
new file mode 100644
index 00000000..2a506661
--- /dev/null
+++ b/smlc/SMLC_Tests.ttcn
@@ -0,0 +1,491 @@
+module SMLC_Tests {
+
+/* Integration Tests for OsmoSMLC
+ * (C) 2020 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
+ *
+ * This test suite tests OsmoSMLC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for lower-
+ * level testing.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSAP_LE_Emulation all;
+import from BSSMAP_LE_Templates all;
+import from BSSLAP_Types all;
+
+import from BSSAP_Types all;
+import from BSSMAP_Templates all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from SCCP_Templates all;
+
+import from SCCPasp_Types all;
+
+import from BSC_ConnectionHandler all;
+
+const integer NUM_BSC := 1;
+
+/* Default list of counters for 'smlc' */
+const CounterNameVals counternames_bsc := {
+ { "foo:bar", 0 }
+};
+
+type component test_CT extends CTRL_Adapter_CT {
+ var BSSAP_LE_Adapter g_bssap_le[NUM_BSC];
+ port BSSAP_LE_CODEC_PT BSSAP_LE;
+
+ port TELNETasp_PT SMLCVTY;
+
+ /* are we initialized yet */
+ var boolean g_initialized := false;
+
+ /*Configure T(tias) over VTY, seconds */
+ var integer g_smlc_sccp_timer_ias := 7 * 60;
+ /*Configure T(tiar) over VTY, seconds */
+ var integer g_smlc_sccp_timer_iar := 15 * 60;
+
+ /* global test case guard timer (actual timeout value is set in f_init()) */
+ timer T_guard := 30.0;
+
+ var CounterNameValsList g_ctr_smlc;
+ var CounterNameValsList g_ctr_bsc;
+
+}
+
+type record of BSSAP_LE_Configuration BSSAP_LE_Configurations;
+
+modulepar {
+ /* IP address at which the SMLC can be reached */
+ charstring mp_smlc_ip := "127.0.0.1";
+ /* port number to which to establish the IPA CTRL connection */
+ integer mp_smlc_ctrl_port := 4272;
+ /* IP address at which the test binds */
+ charstring mp_test_ip := "127.0.0.1";
+
+ BSSAP_LE_Configurations mp_bssap_le_cfg := {
+ {
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 187, /* 0.23.3 first BSC emulation */
+ own_ssn := 250, /* BSC side SSN */
+ peer_pc := 190, /* 0.23.6 osmo-smlc */
+ peer_ssn := 252, /* SMLC side SSN */
+ sio := '83'O,
+ rctx := 1
+ }
+ };
+}
+
+private function f_gen_test_hdlr_pars(integer bssap_le_idx := 0) return TestHdlrParams {
+
+ var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ return pars;
+}
+
+/* Convenience functions for rate counters using g_ctr_bsc. */
+
+private function f_ctrs_smlc_init(integer bscs_count := NUM_BSC, CounterNameVals counternames := counternames_bsc) runs on test_CT {
+ g_ctr_bsc := f_counter_name_vals_get_n(IPA_CTRL, "bsc", bscs_count, counternames);
+ log("initial msc rate counters: ", g_ctr_bsc);
+}
+
+private function f_ctrs_smlc_add(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_counter_name_vals_list_add(g_ctr_bsc, msc_nr, countername, val);
+}
+
+/* f_ctrs_smlc_init();
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_do_other(on_msc := 1);
+ * f_ctrs_smlc_add(0, "thing", 2);
+ * f_ctrs_smlc_add(1, "other");
+ * f_ctrs_smlc_verify();
+ */
+private function f_ctrs_smlc_verify() runs on test_CT {
+ log("verifying msc rate counters: ", g_ctr_bsc);
+ f_counter_name_vals_expect_n(IPA_CTRL, "bsc", g_ctr_bsc);
+}
+
+/* convenience: f_ctrs_smlc_add() and f_ctrs_smlc_verify() in one call.
+ * f_ctrs_smlc_init();
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_do_thing(on_msc := 0);
+ * f_ctrs_smlc_expect(0, "thing", 3);
+ */
+private function f_ctrs_smlc_expect(integer msc_nr, charstring countername, integer val := 1) runs on test_CT {
+ f_ctrs_smlc_add(msc_nr, countername, val);
+ f_ctrs_smlc_verify();
+}
+
+private function f_shutdown_helper() runs on test_CT {
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+/* global altstep for global guard timer */
+altstep as_Tguard() runs on test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+/* global initialization function
+ * \param nr_bts Number of BTSs we should start/bring up
+ * \param handler_mode Start an RSL_Emulation_CT component (true) or not (false).
+ * \param nr_msc Number of virtual MSCs to bring up to connect to osmo-bsc.
+ */
+function f_init(integer nr_bsc := NUM_BSC, float guard_timeout := 30.0) runs on test_CT {
+ var integer bssap_le_idx;
+
+ if (g_initialized) {
+ return;
+ }
+ g_initialized := true;
+
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
+ f_init_vty("VirtBSC");
+
+ for (bssap_le_idx := 0; bssap_le_idx < nr_bsc; bssap_le_idx := bssap_le_idx+1) {
+ f_bssap_le_adapter_init(g_bssap_le[bssap_le_idx], mp_bssap_le_cfg[bssap_le_idx], "VirtBSC", BSC_BssapLeOps);
+ f_bssap_le_adapter_start(g_bssap_le[bssap_le_idx]);
+ }
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+ if (SMLCVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:SMLCVTY, system:SMLCVTY);
+ f_vty_set_prompts(SMLCVTY);
+ f_vty_transceive(SMLCVTY, "enable");
+ f_cs7_inst_0_cfg(SMLCVTY, {"sccp-timer ias " & int2str(g_smlc_sccp_timer_ias),
+ "sccp-timer iar " & int2str(g_smlc_sccp_timer_iar)});
+}
+
+type function void_fn(charstring id) runs on BSC_ConnHdlr;
+
+private function f_connect_handler(inout BSC_ConnHdlr vc_conn, integer bssap_le_idx := 0) runs on test_CT {
+ connect(vc_conn:BSSAP_LE, g_bssap_le[bssap_le_idx].vc_BSSAP_LE:CLIENT);
+ connect(vc_conn:BSSAP_LE_PROC, g_bssap_le[bssap_le_idx].vc_BSSAP_LE:PROC);
+}
+
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars := omit)
+runs on test_CT return BSC_ConnHdlr {
+ var charstring id := testcasename();
+ var BSC_ConnHdlr vc_conn;
+ var integer bssap_le_idx := 0;
+ if (isvalue(pars)) {
+ bssap_le_idx := valueof(pars).bssap_le_idx;
+ }
+ vc_conn := BSC_ConnHdlr.create(id);
+ f_connect_handler(vc_conn, bssap_le_idx);
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(SMLCVTY, testcasename() & "() start");
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+private function f_handler_init(void_fn fn, charstring id, template (omit) TestHdlrParams pars := omit)
+runs on BSC_ConnHdlr {
+ if (isvalue(pars)) {
+ g_pars := valueof(pars);
+ }
+ fn.apply(id);
+}
+
+type record of charstring Commands;
+
+private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
+{
+ f_vty_enter_cfg_cs7_inst(pt, 0);
+ for (var integer i := 0; i < sizeof(cmds); i := i+1) {
+ f_vty_transceive(pt, cmds[i]);
+ }
+ f_vty_transceive(pt, "end");
+}
+
+template (value) PDU_BSSAP_LE ts_BSSMAP_LE_BSSLAP(template (value) BSSLAP_PDU bsslap)
+ := ts_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
+
+template PDU_BSSAP_LE tr_BSSMAP_LE_BSSLAP(template BSSLAP_PDU bsslap)
+ := tr_BSSMAP_LE_ConnInfo(BSSMAP_LE_PROT_BSSLAP, data := enc_BSSLAP_PDU(valueof(bsslap)));
+
+/* BSC sends Perform Location Request that already contains a TA Layer 3 BSSLAP APDU */
+private function f_tc_smlc_location_request_with_ta_l3(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi,
+ enc_BSSLAP_PDU(valueof(ts_BSSLAP_TA_Layer3(23)))))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .010 0001 0000 1001 1100 1001 = Degrees of latitude: 2165193 (23.23000 degrees)
+ * 0001 1110 0010 1010 0101 0011 = Degrees of longitude: 1976915 (42.42000 degrees)
+ * .100 1010 = Uncertainty code: 74 (11552.7 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=23.23000&mlon=42.42000&zoom=12]
+ */
+ var octetstring geo := '102109C91E2A534A'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_with_ta_l3() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init();
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_with_ta_l3), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request without BSSLAP APDU, SMLC needs to request TA */
+private function f_tc_smlc_location_request_without_ta_l3(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC figures out the TA and sends it back to the SMLC */
+
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_TA_Resp(cell_id, 23)));
+
+ /* SMLC got the TA from the BSC, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .010 0001 0000 1001 1100 1001 = Degrees of latitude: 2165193 (23.23000 degrees)
+ * 0001 1110 0010 1010 0101 0011 = Degrees of longitude: 1976915 (42.42000 degrees)
+ * .100 1010 = Uncertainty code: 74 (11552.7 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=23.23000&mlon=42.42000&zoom=12]
+ */
+ var octetstring geo := '102109C91E2A534A'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_without_ta_l3() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_without_ta_l3), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, halfway the BSC indicates handover via BSSLAP Reset */
+private function f_tc_smlc_location_request_bsslap_reset(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 1;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(1, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC reports a Handover via a BSSLAP Reset */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_Reset(17, 42,
+ valueof(ts_BSSLAP_IE_ChanDesc),
+ BSSLAP_CAUSE_INTRA_BSS_HO)));
+
+ /* SMLC got the TA from the BSC via BSSLAP Reset, now responds with geo information data. */
+ /* TODO: implement GAD coding in ttcn */
+ /* Expecting geo:
+ * 0001 .... = Location estimate: Ellipsoid point with uncertainty Circle (1)
+ * 0... .... = Sign of latitude: North (0)
+ * .000 1011 0011 1000 1011 0100 = Degrees of latitude: 735412 (7.89012 degrees)
+ * 0000 0110 0101 0100 0110 1011 = Degrees of longitude: 414827 (8.90122 degrees)
+ * .101 0001 = Uncertainty code: 81 (22522.4 m)
+ * [Location OSM URI: https://www.openstreetmap.org/?mlat=7.89012&mlon=8.90122&zoom=12]
+ */
+ var octetstring geo := '100B38B406546B51'O;
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(geo, omit));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_bsslap_reset() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_bsslap_reset), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, halfway the BSC aborts the request because of inter-BSC HO */
+private function f_tc_smlc_location_request_abort(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC aborts */
+ BSSAP_LE.send(ts_BSSMAP_LE_PerfLocAbort(BSSMAP_LE_LCS_CAUSE_INTER_BSC_HO));
+
+ var PDU_BSSAP_LE bssap_le;
+ timer nothing := 7.0;
+ nothing.start;
+ alt {
+ [] BSSAP_LE.receive(tr_BSSAP_LE_BSSMAP) -> value(bssap_le) {
+ log("unexpected bssap_le: ", bssap_le);
+ setverdict(fail, "No more messages expected from SMLC");
+ mtc.stop;
+ }
+ [] nothing.timeout {
+ setverdict(pass);
+ break;
+ }
+ }
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_abort() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_abort), pars);
+ vc_conn.done;
+}
+
+/* BSC sends Perform Location Request, SMLC asks for TA, halfway the BSC aborts the TA request */
+private function f_tc_smlc_location_request_bsslap_abort(charstring id) runs on BSC_ConnHdlr {
+ f_sleep(1.0);
+
+ f_BscConnHdlr_init();
+ f_bssap_le_register_imsi(g_pars.imsi, omit);
+
+ var uint16_t cell_id := 42;
+ var BSSMAP_IE_CellIdentifier cell_ident := valueof(ts_CellID_LAC_CI(23, cell_id));
+
+ BSSAP_LE.send(ts_BSSAP_LE_Conn_Req(g_pars.sccp_addr_smlc, g_pars.sccp_addr_bsc,
+ valueof(ts_BSSMAP_LE_PerfLocReq(BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC_LOC, cell_ident, g_pars.imsi))));
+ BSSAP_LE.receive(BSSAP_LE_Conn_Prim:CONN_PRIM_CONF_IND);
+
+ /* SMLC wants to ask the TA from the SMLC explicitly in a BSSLAP TA Request message */
+ BSSAP_LE.receive(tr_BSSMAP_LE_BSSLAP(tr_BSSLAP_TA_Req));
+
+ /* BSC aborts the TA Request */
+ BSSAP_LE.send(ts_BSSMAP_LE_BSSLAP(ts_BSSLAP_Abort(BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED)));
+
+ /* Expect response without location, just an LCS Cause indicating abort */
+ BSSAP_LE.receive(tr_BSSMAP_LE_PerfLocResp(omit, BSSMAP_LE_LCS_CAUSE_REQUEST_ABORTED));
+
+ f_sleep(2.0);
+ setverdict(pass);
+}
+testcase TC_smlc_location_request_bsslap_abort() runs on test_CT {
+ var BSC_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ f_init(1);
+ f_sleep(1.0);
+
+ pars.sccp_addr_bsc := g_bssap_le[0].sccp_addr_own;
+ pars.sccp_addr_smlc := g_bssap_le[0].sccp_addr_peer;
+
+ vc_conn := f_start_handler(refers(f_tc_smlc_location_request_bsslap_abort), pars);
+ vc_conn.done;
+}
+
+control {
+ execute( TC_smlc_location_request_with_ta_l3() );
+ execute( TC_smlc_location_request_without_ta_l3() );
+ execute( TC_smlc_location_request_bsslap_reset() );
+ execute( TC_smlc_location_request_bsslap_abort() );
+ execute( TC_smlc_location_request_abort() );
+}
+
+}
diff --git a/smlc/expected-results.xml b/smlc/expected-results.xml
new file mode 100644
index 00000000..7834ebdf
--- /dev/null
+++ b/smlc/expected-results.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<testsuite name='SMLC_Tests' tests='5' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_with_ta_l3' time='MASKED'/>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_without_ta_l3' time='MASKED'/>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_bsslap_reset' time='MASKED'/>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_bsslap_abort' time='MASKED'/>
+ <testcase classname='SMLC_Tests' name='TC_smlc_location_request_abort' time='MASKED'/>
+</testsuite>
diff --git a/smlc/gen_links.sh b/smlc/gen_links.sh
new file mode 100755
index 00000000..cf715f62
--- /dev/null
+++ b/smlc/gen_links.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+#FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn"
+#gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h SDP_EncDec.cc"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+# Required by MGCP and IPA
+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
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.ProtocolModules.M3UA/src
+FILES="M3UA_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by M3UA_Emulation
+DIR=$BASEDIR/titan.TestPorts.SCTPasp/src
+FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.ProtocolEmulations.M3UA/src
+FILES="M3UA_Emulation.ttcn"
+gen_links $DIR $FILES
+
+# required by SCCP Emulation
+DIR=$BASEDIR/titan.TestPorts.MTP3asp/src
+FILES="MTP3asp_PortType.ttcn MTP3asp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolEmulations.SCCP/src
+FILES="SCCP_Emulation.ttcn SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.BSSMAP/src
+FILES="BSSAP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
+FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.SDP/src
+FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
+SDP_parser.y lex.SDP_parse_.c"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.RTP/src
+FILES="RTP_EncDec.cc RTP_Types.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn BSSAP_LE_Types.ttcn RAN_Emulation.ttcnpp RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn SDP_Templates.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn RAN_Adapter.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn IPA_Testing.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn "
+FILES+="BSSAP_LE_CodecPort.ttcn BSSAP_LE_Emulation.ttcn BSSAP_LE_Adapter.ttcn BSSLAP_Types.ttcn BSSMAP_LE_Templates.ttcn "
+
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/smlc/osmo-smlc.cfg b/smlc/osmo-smlc.cfg
new file mode 100644
index 00000000..7da21632
--- /dev/null
+++ b/smlc/osmo-smlc.cfg
@@ -0,0 +1,29 @@
+log gsmtap 172.18.23.203
+ logging level set-all debug
+ logging filter all 1
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print level 1
+ logging print category 1
+ logging print category-hex 0
+ logging print extended-timestamp 1
+ logging print file basename last
+ logging level set-all debug
+
+line vty
+ no login
+ bind 0.0.0.0
+
+cs7 instance 0
+ asp asp-clnt-msc-0 2905 2905 m3ua
+ local-ip 172.18.23.20
+ local-ip fd02:db8:23::20
+ remote-ip 172.18.23.200
+ remote-ip fd02:db8:23::200
+ role asp
+ sctp-role client
+cells
+ lac-ci 23 42 lat 23.23 lon 42.42
+ cgi 001 02 3 4 lat 5.678 lon 6.789
+ cgi 001 02 1 17 lat 7.890123 lon 8.90123
diff --git a/smlc/osmo-stp.cfg b/smlc/osmo-stp.cfg
new file mode 100644
index 00000000..e2568e23
--- /dev/null
+++ b/smlc/osmo-stp.cfg
@@ -0,0 +1,46 @@
+!
+! OsmoSTP (0.8.1) configuration saved from vty
+!!
+!
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 1
+ logging print extended-timestamp 1
+ logging level lglobal notice
+ logging level llapd notice
+ logging level linp notice
+ logging level lmux notice
+ logging level lmi notice
+ logging level lmib notice
+ logging level lsms notice
+ logging level lctrl notice
+ logging level lgtp notice
+ logging level lstats notice
+ logging level lgsup notice
+ logging level loap notice
+ logging level lss7 debug
+ logging level lsccp debug
+ logging level lsua debug
+ logging level lm3ua debug
+ logging level lmgcp notice
+!
+line vty
+ no login
+!
+cs7 instance 0
+ xua rkm routing-key-allocation dynamic-permitted
+ asp virt-bsc0-0 23905 2905 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ sctp-role server
+ as virt-bsc0 m3ua
+ asp virt-bsc0-0
+ routing-key 1 0.23.3
+
+ route-table system
+ update route 0.23.3 7.255.7 linkset virt-bsc0
+ listen m3ua 2905
+ accept-asp-connections dynamic-permitted
diff --git a/smlc/regen_makefile.sh b/smlc/regen_makefile.sh
new file mode 100755
index 00000000..180486c0
--- /dev/null
+++ b/smlc/regen_makefile.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+NAME=SMLC_Tests
+
+FILES="
+ *.c
+ *.ttcn
+ *.ttcnpp
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IuUP_EncDec.cc
+ MGCP_CodecPort_CtrlFunctDef.cc
+ Native_FunctionDefs.cc
+ RTP_CodecPort_CtrlFunctDef.cc
+ RTP_EncDec.cc
+ SCTPasp_PT.cc
+ SDP_EncDec.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_RSL
+ -DIPA_EMULATION_MGCP
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_SCCP
+ -DRAN_EMULATION_BSSAP
+ -DRAN_EMULATION_MGCP
+ -DRAN_EMULATION_CTRL
+ -DUSE_MTP3_DISTRIBUTOR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/start-testsuite.sh b/start-testsuite.sh
index b9324bbf..4b88501a 100755
--- a/start-testsuite.sh
+++ b/start-testsuite.sh
@@ -45,9 +45,13 @@ fi
#TITAN_LIBRARY_PATH="$TTCN3_DIR/lib"
#TTCN3_BIN_DIR="$TTCN3_DIR/bin"
+# Limit max num of open file descriptors to workaround titan.core bug:
+# https://gitlab.eclipse.org/eclipse/titan/titan.core/-/issues/690
+ulimit -n 100000
+
# below is for the debian packages
TTCN3_BIN_DIR="${TTCN3_BIN_DIR:-/usr/bin}"
-TITAN_LIBRARY_PATH="/usr/lib/titan:/usr/ttcn3/lib"
+TITAN_LIBRARY_PATH="${TITAN_LIBRARY_PATH:-/usr/lib/titan:/usr/ttcn3/lib}"
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$SUITE_DIR:$TITAN_LIBRARY_PATH" "$TTCN3_BIN_DIR/ttcn3_start" $SUITE $CFG $TEST
expected="$SUITE_DIR/expected-results.xml"
diff --git a/stp/STP_Tests.cfg b/stp/STP_Tests.cfg
index 3ba2d13c..945ef8fc 100644
--- a/stp/STP_Tests.cfg
+++ b/stp/STP_Tests.cfg
@@ -15,4 +15,6 @@
[MAIN_CONTROLLER]
[EXECUTE]
+STP_Tests_M3UA.control
+STP_Tests_IPA.control
STP_Tests.control
diff --git a/stp/STP_Tests.ttcn b/stp/STP_Tests.ttcn
index 990518c3..e2e5336a 100644
--- a/stp/STP_Tests.ttcn
+++ b/stp/STP_Tests.ttcn
@@ -73,7 +73,7 @@ testcase TC_m3ua_to_ipa() runs on IPA_M3UA_CT {
f_M3UA_asp_up_act(0, omit, omit); // TODO: rctx
/* send a well-formed, encoded SCCP message via M3UA */
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
var SCCP_PAR_Address called := valueof(ts_SccpAddr_GT('1234'H));
var SCCP_PAR_Address calling := valueof(ts_SccpAddr_GT('5678'H));
var PDU_SCCP sccp := valueof(ts_SCCP_UDT(called, calling, data));
@@ -105,7 +105,7 @@ testcase TC_ipa_to_m3ua() runs on IPA_M3UA_CT {
f_M3UA_asp_up_act(0, omit, omit); // TODO: rctx
/* send a well-formed, encoded SCCP message via IPA */
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
var SCCP_PAR_Address called := valueof(ts_SccpAddr_GT('1234'H));
var SCCP_PAR_Address calling := valueof(ts_SccpAddr_GT('5678'H));
var PDU_SCCP sccp := valueof(ts_SCCP_UDT(called, calling, data));
@@ -114,12 +114,47 @@ testcase TC_ipa_to_m3ua() runs on IPA_M3UA_CT {
/* expect to receive it via M3UA */
var template (present) M3UA_Protocol_Data rx_pd;
- rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, '00'O, sccp_enc);
+ rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, ?, sccp_enc);
f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));
f_clear_m3ua();
}
+/* test routing an SCCP message from IPA ASP to M3UA ASP using national network indicator */
+testcase TC_ipa_to_m3ua_ni() runs on IPA_M3UA_CT {
+ var OCT4 pc_sender := int2oct(5, 4);
+ var OCT4 rctx_receiver := int2oct(1023, 4);
+ var OCT4 pc_receiver := int2oct(23, 4);
+
+ f_init_common();
+ f_vty_config2(VTY, {"cs7 instance 0", "as ipa-as-dynamic-asp ipa"},
+ "point-code override patch-sccp disabled");
+
+ f_init_m3ua();
+ f_init_ipa();
+
+ f_connect_ipa(3);
+ f_M3UA_asp_up_act(0, omit, omit); // TODO: rctx
+
+ /* send a well-formed, encoded SCCP message via IPA */
+ var octetstring data := f_rnd_octstring_rnd_len(100);
+ var SCCP_PAR_Address called := valueof(ts_SccpAddr_GT('1234'H));
+ var SCCP_PAR_Address calling := valueof(ts_SccpAddr_GT('5678'H));
+ var PDU_SCCP sccp := valueof(ts_SCCP_UDT(called, calling, data));
+ var octetstring sccp_enc := enc_PDU_SCCP(sccp);
+ f_vty_config2(VTY, {"cs7 instance 0"}, "network-indicator national");
+ f_IPA_send(3, sccp_enc);
+
+ /* expect to receive it via M3UA */
+ var template (present) M3UA_Protocol_Data rx_pd;
+ rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, c_M3UA_NI_NATIONAL,
+ '00'O, ?, sccp_enc);
+ f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));
+ f_vty_config2(VTY, {"cs7 instance 0"}, "network-indicator international");
+ f_clear_m3ua();
+}
+
+
/* test routing an SCCP message from IPA ASP to M3UA ASP while patching PC into SCCP addresses */
testcase TC_ipa_to_m3ua_patch_sccp() runs on IPA_M3UA_CT {
var OCT4 pc_sender := int2oct(5, 4);
@@ -137,7 +172,7 @@ testcase TC_ipa_to_m3ua_patch_sccp() runs on IPA_M3UA_CT {
f_M3UA_asp_up_act(0, omit, omit); // TODO: rctx
/* send a well-formed, encoded SCCP message via IPA */
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
var SCCP_PAR_Address called := valueof(ts_SccpAddr_GT('1234'H));
var SCCP_PAR_Address calling := valueof(ts_SccpAddr_GT('5678'H));
var PDU_SCCP sccp := valueof(ts_SCCP_UDT(called, calling, data));
@@ -150,7 +185,7 @@ testcase TC_ipa_to_m3ua_patch_sccp() runs on IPA_M3UA_CT {
/* expect to receive it via M3UA */
var template (present) M3UA_Protocol_Data rx_pd;
- rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, '00'O,
+ rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, c_M3UA_SI_SCCP, '00'O, '00'O, ?,
enc_PDU_SCCP(sccp_exp));
f_M3UA_exp(0, tr_M3UA_DATA(rctx_receiver, rx_pd));
@@ -163,6 +198,7 @@ control {
/* M3UA <-> IPA Tests */
execute( TC_m3ua_to_ipa() );
execute( TC_ipa_to_m3ua() );
+ execute( TC_ipa_to_m3ua_ni() );
execute( TC_ipa_to_m3ua_patch_sccp() );
}
diff --git a/stp/STP_Tests_Common.ttcn b/stp/STP_Tests_Common.ttcn
index aee5a886..a540b102 100644
--- a/stp/STP_Tests_Common.ttcn
+++ b/stp/STP_Tests_Common.ttcn
@@ -19,19 +19,6 @@ import from Osmocom_VTY_Functions all;
import from IPL4asp_Types all;
-modulepar {
- charstring mp_stp_ip := "127.0.0.1";
- charstring mp_local_ip := "127.0.0.1";
-}
-
-friend template (value) SctpTuple ts_SCTP(template (omit) integer ppid := 3,
- template (omit) integer stream := 0) := {
- sinfo_stream := stream,
- sinfo_ppid := ppid,
- remSocks := omit,
- assocId := omit
-}
-
type component Test_CT {
port TELNETasp_PT VTY;
timer g_Tguard := 30.0;
diff --git a/stp/STP_Tests_IPA.ttcn b/stp/STP_Tests_IPA.ttcn
index 48652b8c..10367ad0 100644
--- a/stp/STP_Tests_IPA.ttcn
+++ b/stp/STP_Tests_IPA.ttcn
@@ -38,6 +38,8 @@ private const integer NR_IPA := 7;
type record of charstring AspNameArray;
modulepar {
+ charstring mp_stp_ipa_ip := "127.0.0.1";
+ charstring mp_local_ipa_ip := "127.0.0.1";
integer mp_stp_ipa_port := 5000;
integer mp_local_ipa_port := 20000;
AspNameArray mp_ipa_as_names := {"ipa-as-loadshare-sender",
@@ -54,6 +56,7 @@ type component IPA_CT extends Test_CT {
/* for IPA we use the IPA_Emulation and not directly IPA_CodecPort to avoid
* having to re-invent IPA CCM handling here */
port MTP3asp_PT IPA[NR_IPA];
+ port IPA_SP_PT IPA_CTRL[NR_IPA];
var IPA_Emulation_CT vc_IPA[NR_IPA];
var IPA_CCM_Parameters g_ccm_pars[NR_IPA];
}
@@ -101,20 +104,27 @@ friend function f_init_ipa() runs on IPA_CT {
vc_IPA[i] := IPA_Emulation_CT.create("IPA" & int2str(i));
map(vc_IPA[i]:IPA_PORT, system:IPA_CODEC_PT);
connect(self:IPA[i], vc_IPA[i]:MTP3_SP_PORT);
+ connect(self:IPA_CTRL[i], vc_IPA[i]:IPA_SP_PORT);
g_ccm_pars[i] := c_IPA_default_ccm_pars;
g_ccm_pars[i].name := mp_ipa_as_names[i];
}
}
-friend function f_connect_ipa(integer idx, boolean use_unknown_asp_port := false) runs on IPA_CT {
+friend function f_connect_ipa(integer idx, boolean use_unknown_asp_port := false, boolean exp_act := true) runs on IPA_CT {
var integer port_offset := 0;
if (use_unknown_asp_port) {
/* Add 100 to the port since we know that port is not configured in any
ASP only up to NR_IPA are configured. */
port_offset := 100;
}
- vc_IPA[idx].start(IPA_Emulation.main_client(mp_stp_ip, mp_stp_ipa_port, mp_local_ip,
+ vc_IPA[idx].start(IPA_Emulation.main_client(mp_stp_ipa_ip, mp_stp_ipa_port, mp_local_ipa_ip,
mp_local_ipa_port + idx + port_offset, g_ccm_pars[idx]));
+ IPA_CTRL[idx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP));
+ alt {
+ [exp_act] IPA_CTRL[idx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK));
+ [not exp_act] IPA_CTRL[idx].receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN));
+ [] IPA_CTRL[idx].receive(tr_ASP_IPA_EV(?)) { repeat; }
+ }
}
@@ -124,16 +134,12 @@ testcase TC_unknown_client_nodynamic() runs on IPA_CT {
f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
"accept-asp-connections pre-configured");
f_init_ipa();
- f_connect_ipa(0, true);
- f_sleep(1.0);
- if (IPA[0].checkstate("Connected")) {
- setverdict(fail, "Expected IPA port to be disconnected");
- } else {
- setverdict(pass);
- }
+ f_connect_ipa(0, true, false);
+
/* switch back to default */
f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
"accept-asp-connections dynamic-permitted");
+ setverdict(pass);
}
/* "accept-asp-connections pre-configured" and client from known source */
@@ -143,15 +149,11 @@ testcase TC_known_client_nodynamic() runs on IPA_CT {
"accept-asp-connections pre-configured");
f_init_ipa();
f_connect_ipa(0, false);
- f_sleep(1.0);
- if (not IPA[0].checkstate("Connected")) {
- setverdict(fail, "Expected IPA port to be connected");
- } else {
- setverdict(pass);
- }
+
/* switch back to default */
f_vty_config2(VTY, {"cs7 instance 0", "listen ipa 5000"},
"accept-asp-connections dynamic-permitted");
+ setverdict(pass);
}
@@ -160,12 +162,7 @@ testcase TC_unknown_client_dynamic() runs on IPA_CT {
f_init_common();
f_init_ipa();
f_connect_ipa(0, true);
- f_sleep(1.0);
- if (not IPA[0].checkstate("Connected")) {
- setverdict(fail, "Expected IPA port to be connected");
- } else {
- setverdict(pass);
- }
+ setverdict(pass);
}
private function f_tc_tmt_override(boolean unknwon_dynamic_asp)
@@ -176,17 +173,16 @@ runs on IPA_CT {
f_connect_ipa(4, unknwon_dynamic_asp);
/* activate the first 'receiver' side ASP */
f_connect_ipa(5, unknwon_dynamic_asp);
- f_sleep(1.0);
/* verify traffic is routed from sender to [sole] receiver */
f_test_traffic(4, 5);
/* activate the second 'receiver' side ASP */
f_connect_ipa(6, unknwon_dynamic_asp);
- f_sleep(1.0);
/* verify traffic is routed from sender to new receiver */
f_test_traffic(4, 6);
+ setverdict(pass);
}
/* test "traffic-mode override" behavior */
@@ -216,7 +212,6 @@ runs on IPA_CT {
f_connect_ipa(0, unknwon_dynamic_asp);
/* activate the first 'receiver' side ASP */
f_connect_ipa(1, unknwon_dynamic_asp);
- f_sleep(1.0);
/* verify traffic is routed from sender to [sole] receiver */
for (i := 0; i < 10; i := i+1) {
@@ -225,7 +220,6 @@ runs on IPA_CT {
/* activate the second 'receiver' side ASP */
f_connect_ipa(2, unknwon_dynamic_asp);
- f_sleep(1.0);
/* verify traffic is routed from sender to new receiver */
const integer iter_per_asp := 5;
@@ -234,8 +228,8 @@ runs on IPA_CT {
var octetstring data := f_rnd_octstring(f_rnd_ipa_len());
f_IPA_send(0, data);
alt {
- [] as_count_rx(1, data, num_rx[1])
- [] as_count_rx(2, data, num_rx[2])
+ [] as_count_rx(1, data, num_rx[1]);
+ [] as_count_rx(2, data, num_rx[2]);
}
}
/* FIXME: check for extraneous messages? */
diff --git a/stp/STP_Tests_M3UA.ttcn b/stp/STP_Tests_M3UA.ttcn
index f6fa6252..24b3ae1e 100644
--- a/stp/STP_Tests_M3UA.ttcn
+++ b/stp/STP_Tests_M3UA.ttcn
@@ -2,6 +2,7 @@ module STP_Tests_M3UA {
/* Osmocom STP test suite in in TTCN-3
* (C) 2019 Harald Welte <laforge@gnumonks.org>
+ * (C) 2024 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
@@ -15,6 +16,7 @@ friend module STP_Tests;
import from General_Types all;
import from Osmocom_Types all;
import from IPL4asp_Types all;
+import from Misc_Helpers all;
import from Osmocom_VTY_Functions all;
@@ -34,20 +36,116 @@ import from SCCP_Emulation all;
import from STP_Tests_Common all;
+private const integer NR_M3UA := 4; /* number of M3UA clients in ATS */
+private const integer NR_M3UA_SRV := 4; /* number of M3UA servres in ATS */
+
modulepar {
- integer mp_stp_m3ua_port := 2905;
- integer mp_stp_m3ua_clnt_port := 2906;
- integer mp_local_m3ua_port := 9999;
+ /* STP-side IP addresses */
+ HostList mp_stp_m3ua_ip := { "127.0.0.1", "::1" };
+ /* local IP addresses */
+ HostList mp_local_m3ua_ip := { "127.0.0.1", "::1" };
+ M3uaConfigs mp_m3ua_configs := {
+ /* as-sender: One ASP within AS */
+ {
+ use_tcp := false,
+ remote_port := 2905,
+ local_port := 9999,
+ point_code := 23,
+ routing_ctx := 1023
+ },
+ /* as-receiver: Two ASP within AS */
+ {
+ use_tcp := false,
+ remote_port := 2905,
+ local_port := 10000,
+ point_code := 42,
+ routing_ctx := 1042
+ }, {
+ use_tcp := false,
+ remote_port := 2905,
+ local_port := 10001,
+ point_code := 42,
+ routing_ctx := 1042
+ },
+ /* as-sender-tcp: One ASP within AS */
+ {
+ use_tcp := true,
+ remote_port := 2905,
+ local_port := 9999,
+ point_code := 123,
+ routing_ctx := 1123
+ },
+ /* as-client: One ASP within AS */
+ {
+ use_tcp := false,
+ remote_port := 2906,
+ local_port := 10002,
+ point_code := 55,
+ routing_ctx := 1055
+ },
+ /* as-client60-norctx */
+ {
+ use_tcp := false,
+ remote_port := 2907,
+ local_port := 11060,
+ point_code := 60,
+ routing_ctx := -
+ },
+ /* as-client61-norctx */
+ {
+ use_tcp := false,
+ remote_port := 2907,
+ local_port := 11061,
+ point_code := 61,
+ routing_ctx := -
+ },
+ /* as-client-tcp: One ASP within AS */
+ {
+ use_tcp := true,
+ remote_port := 2906,
+ local_port := 10002,
+ point_code := 155,
+ routing_ctx := 1155
+ }
+ };
integer mp_recovery_timeout_msec := 2000;
+ charstring mp_sccp_service_type := "mtp3_itu";
}
-private const integer NR_M3UA := 3; /* number of M3UA clients in ATS */
-private const integer NR_M3UA_SRV := 1; /* number of M3UA servres in ATS */
+type record M3uaConfig {
+ /* use TCP (true) or SCTP (false) */
+ boolean use_tcp,
+ /* STP-side SCTP (or TCP) port for M3UA */
+ integer remote_port,
+ /* local M3UA base port on TTCN3 side */
+ integer local_port,
+ /* point code routed via this M3U */
+ integer point_code,
+ /* associated routing context */
+ integer routing_ctx
+};
+type record length (NR_M3UA+NR_M3UA_SRV) of M3uaConfig M3uaConfigs;
private function M3UA_SRV(integer idx) return integer {
return NR_M3UA+idx;
}
+private function f_m3ua_cli_config(integer idx) return M3uaConfig {
+ if (idx < 0 or idx >= NR_M3UA) {
+ setverdict(fail, "f_m3ua_cli_config(): unexpected idx");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ return mp_m3ua_configs[idx];
+}
+
+private function f_m3ua_srv_config(integer idx) return M3uaConfig {
+ if (idx < 0 or idx >= NR_M3UA_SRV) {
+ setverdict(fail, "f_m3ua_srv_config(): unexpected idx");
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__);
+ }
+ return mp_m3ua_configs[M3UA_SRV(idx)];
+}
+
type component RAW_M3UA_CT extends Test_CT {
port M3UA_CODEC_PT M3UA[NR_M3UA+NR_M3UA_SRV];
var integer g_m3ua_conn_id[NR_M3UA+NR_M3UA_SRV];
@@ -63,7 +161,7 @@ private template PortEvent tr_SctpPeerAddrChange := {
sctpPeerAddrChange := ?
}
}
-private template PortEvent tr_SctpConnOpened := {
+private template PortEvent tr_ConnOpened := {
connOpened := ?
}
@@ -73,13 +171,27 @@ private altstep as_m3ua_sctp() runs on RAW_M3UA_CT {
[] any from M3UA.receive(tr_SctpPeerAddrChange) { repeat; }
}
-friend function f_M3UA_send(integer idx, template (present) PDU_M3UA msg, template integer stream := 0)
+private altstep as_m3ua_ssnm_ignore() runs on RAW_M3UA_CT {
+ var M3UA_RecvFrom rx;
+ [] any from M3UA.receive(t_M3UA_RecvFrom(tr_M3UA_SSNM)) -> value rx {
+ log("Ignoring M3UA SSNM", rx);
+ repeat;
+ }
+}
+
+friend function f_M3UA_send(integer idx, template (present) PDU_M3UA msg, integer stream := 0)
runs on RAW_M3UA_CT {
- M3UA[idx].send(t_M3UA_Send(g_m3ua_conn_id[idx], msg, stream));
+ if (mp_m3ua_configs[idx].use_tcp) {
+ M3UA[idx].send(t_M3UA_Send(g_m3ua_conn_id[idx], msg, omit));
+ } else {
+ M3UA[idx].send(t_M3UA_Send(g_m3ua_conn_id[idx], msg, stream));
+ }
}
friend function f_M3UA_exp(integer idx, template (present) PDU_M3UA msg) runs on RAW_M3UA_CT {
var M3UA_RecvFrom rx;
+ timer T := 5.0;
+ T.start;
alt {
[] M3UA[idx].receive(t_M3UA_RecvFrom(msg)) {
setverdict(pass);
@@ -89,47 +201,188 @@ friend function f_M3UA_exp(integer idx, template (present) PDU_M3UA msg) runs on
"while waiting for ", msg);
mtc.stop;
}
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for M3UA[", idx, "] ", msg);
+ mtc.stop;
+ }
+ }
+}
+
+/* flush any number of queued messages matching 'msg' */
+friend function f_M3UA_flush(integer idx, template (present) PDU_M3UA msg) runs on RAW_M3UA_CT {
+ var M3UA_RecvFrom rx;
+ timer T := 0.01;
+ T.start;
+ alt {
+ /* this should normally be possible with something like M3UA[idx].check(receive(...)) but somehow
+ * TITAN complains about the 'check' token, so it looks that feature of TTCN3 is not supported? */
+ [] M3UA[idx].receive(t_M3UA_RecvFrom(msg)) {
+ repeat;
+ }
+ [] T.timeout {
+ }
+ }
+}
+
+private template (value) Socket ts_Socket(HostName hostName, PortNumber portNumber) := {
+ hostName := hostName,
+ portNumber := portNumber
+};
+
+private template (value) SctpTuple ts_SCTP(template (omit) integer ppid := 3,
+ template (omit) integer stream := 0,
+ template (omit) SocketList remSocks := omit) := {
+ sinfo_stream := stream,
+ sinfo_ppid := ppid,
+ remSocks := remSocks,
+ assocId := omit
+};
+
+friend function f_M3UA_connect_sctp(integer i) runs on RAW_M3UA_CT {
+ var Result res;
+ var Option opt_add_local_addrs;
+ var OptionList opt_list := {};
+ var template SocketList opt_add_remote_addrs;
+ var M3uaConfig m3cfg := mp_m3ua_configs[i];
+
+ if (lengthof(mp_local_m3ua_ip) == 0 or lengthof(mp_stp_m3ua_ip) == 0) {
+ setverdict(fail, "Empty local or remote address trying to connect SCTP socket: ",
+ mp_local_m3ua_ip, " / ", mp_stp_m3ua_ip);
+ mtc.stop;
+ }
+
+ if (lengthof(mp_local_m3ua_ip) > 1) {
+ opt_add_local_addrs.sctpAdditionalLocalAddresses := substr(mp_local_m3ua_ip, 1,
+ lengthof(mp_local_m3ua_ip) - 1); //{mp_local_m3ua_ip};
+ opt_list := {opt_add_local_addrs};
+ }
+
+ if (lengthof(mp_stp_m3ua_ip) > 1) {
+ for (var integer j := 1; j < lengthof(mp_stp_m3ua_ip); j := j + 1) {
+ var Socket sk := valueof(ts_Socket(mp_stp_m3ua_ip[j], m3cfg.remote_port));
+ opt_add_remote_addrs[j - 1] := sk;
+ }
+ } else {
+ opt_add_remote_addrs := omit;
}
+
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_connect(M3UA[i], mp_stp_m3ua_ip[0], m3cfg.remote_port,
+ mp_local_m3ua_ip[0], m3cfg.local_port, 0,
+ {sctp:=valueof(ts_SCTP(3, 0, opt_add_remote_addrs))},
+ opt_list);
+ if (not ispresent(res.connId)) {
+ setverdict(fail, "Could not connect M3UA socket, check your configuration");
+ mtc.stop;
+ }
+ g_m3ua_conn_id[i] := res.connId;
}
-friend function f_M3UA_connect(integer i) runs on RAW_M3UA_CT {
+friend function f_M3UA_connect_tcp(integer i) runs on RAW_M3UA_CT {
+ var M3uaConfig m3cfg := mp_m3ua_configs[i];
var Result res;
- res := M3UA_CodecPort_CtrlFunct.f_IPL4_connect(M3UA[i], mp_stp_ip, mp_stp_m3ua_port,
- mp_local_ip, mp_local_m3ua_port+i, -1,
- {sctp:=valueof(ts_SCTP)});
+
+ /* XXX: M3UA-over-TCP is not supported by osmo-stp <= 1.8.1 */
+ if (not Misc_Helpers.f_osmo_repo_is("nightly")) {
+ log("Not connect()ing m3cfg := ", m3cfg, " (not supported by IUT)");
+ g_m3ua_conn_id[i] := -1;
+ return;
+ }
+
+ if (lengthof(mp_local_m3ua_ip) == 0 or lengthof(mp_stp_m3ua_ip) == 0) {
+ setverdict(fail, "Empty local or remote address trying to connect TCP socket: ",
+ mp_local_m3ua_ip, " / ", mp_stp_m3ua_ip);
+ mtc.stop;
+ }
+
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_connect(M3UA[i], mp_stp_m3ua_ip[0], m3cfg.remote_port,
+ mp_local_m3ua_ip[0], m3cfg.local_port, 0,
+ {tcp:={}});
if (not ispresent(res.connId)) {
setverdict(fail, "Could not connect M3UA socket, check your configuration");
- mtc.stop;
+ mtc.stop;
}
g_m3ua_conn_id[i] := res.connId;
+ M3UA_CodecPort.f_set_tcp_segmentation(M3UA[i], res.connId);
}
friend function f_M3UA_close(integer i) runs on RAW_M3UA_CT {
var Result res;
- res := M3UA_CodecPort_CtrlFunct.f_IPL4_close(M3UA[i], g_m3ua_conn_id[i], {sctp:=valueof(ts_SCTP)});
- g_m3ua_conn_id[i] := 0;
+ if (g_m3ua_conn_id[i] < 0) {
+ log("Not close()ing m3cfg := ", mp_m3ua_configs[i], " (not connected)");
+ /* not connected */
+ return;
+ }
+ if (mp_m3ua_configs[i].use_tcp) {
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_close(M3UA[i], g_m3ua_conn_id[i], {tcp:={}});
+ } else {
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_close(M3UA[i], g_m3ua_conn_id[i], {sctp:=valueof(ts_SCTP)});
+ }
+ g_m3ua_conn_id[i] := -1;
}
friend function f_M3UA_listen(integer i) runs on RAW_M3UA_CT {
var Result res;
- res := M3UA_CodecPort_CtrlFunct.f_IPL4_listen(M3UA[i], mp_local_ip, mp_local_m3ua_port+i,
- {sctp:=valueof(ts_SCTP)});
+ var Option opt_add_local_addrs;
+ var OptionList opt_list := {};
+ var M3uaConfig m3cfg := mp_m3ua_configs[i];
+
+ /* XXX: M3UA-over-TCP is not supported by osmo-stp <= 1.8.1 */
+ if (not Misc_Helpers.f_osmo_repo_is("nightly") and m3cfg.use_tcp) {
+ log("Not listen()ing m3cfg := ", m3cfg, " (not supported by IUT)");
+ return;
+ }
+
+ if (lengthof(mp_local_m3ua_ip) == 0 ) {
+ setverdict(fail, "Empty local address trying to bind SCTP socket: ",
+ mp_local_m3ua_ip);
+ mtc.stop;
+ }
+
+ if (lengthof(mp_local_m3ua_ip) > 1) {
+ opt_add_local_addrs.sctpAdditionalLocalAddresses := substr(mp_local_m3ua_ip, 1,
+ lengthof(mp_local_m3ua_ip) - 1); //{mp_local_m3ua_ip};
+ opt_list := {opt_add_local_addrs};
+ }
+
+ if (m3cfg.use_tcp) {
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_listen(M3UA[i], mp_local_m3ua_ip[0], m3cfg.local_port,
+ {tcp:={}});
+ } else {
+ res := M3UA_CodecPort_CtrlFunct.f_IPL4_listen(M3UA[i], mp_local_m3ua_ip[0], m3cfg.local_port,
+ {sctp:=valueof(ts_SCTP)}, opt_list);
+ }
if (not ispresent(res.connId)) {
setverdict(fail, "Could not bind M3UA socket, check your configuration");
- mtc.stop;
+ mtc.stop;
+ }
+ if (m3cfg.use_tcp) {
+ M3UA_CodecPort.f_set_tcp_segmentation(M3UA[i], res.connId);
}
}
-friend function f_init_m3ua() runs on RAW_M3UA_CT {
+friend function f_init_m3ua(boolean ignore_ssnm := true) runs on RAW_M3UA_CT {
var integer i;
f_init_common();
activate(as_m3ua_sctp());
+ if (ignore_ssnm) {
+ activate(as_m3ua_ssnm_ignore());
+ }
for (i := 0; i < NR_M3UA; i:=i+1) {
+ /* XXX: M3UA-over-TCP is not supported by osmo-stp <= 1.8.1 */
+ if (not Misc_Helpers.f_osmo_repo_is("nightly") and mp_m3ua_configs[i].use_tcp) {
+ log("Not connect()ing m3cfg := ", mp_m3ua_configs[i], " (not supported by IUT)");
+ g_m3ua_conn_id[i] := -1;
+ continue;
+ }
map(self:M3UA[i], system:M3UA_CODEC_PT);
- f_M3UA_connect(i);
+ if (mp_m3ua_configs[i].use_tcp) {
+ f_M3UA_connect_tcp(i);
+ } else {
+ f_M3UA_connect_sctp(i);
+ }
}
}
@@ -148,15 +401,21 @@ friend function f_clear_m3ua() runs on RAW_M3UA_CT {
friend function f_init_m3ua_srv() runs on RAW_M3UA_CT {
var integer i;
- var PortEvent sctp_evt;
+ var PortEvent port_evt;
for (i := NR_M3UA; i < NR_M3UA+NR_M3UA_SRV; i:=i+1) {
+ /* XXX: M3UA-over-TCP is not supported by osmo-stp <= 1.8.1 */
+ if (not Misc_Helpers.f_osmo_repo_is("nightly") and mp_m3ua_configs[i].use_tcp) {
+ log("Not listen()ing m3cfg := ", mp_m3ua_configs[i], " (not supported by IUT)");
+ g_m3ua_conn_id[i] := -1;
+ continue;
+ }
map(self:M3UA[i], system:M3UA_CODEC_PT);
/* bind+ listen */
f_M3UA_listen(i);
/* wait for accept() */
- M3UA[i].receive(tr_SctpConnOpened) -> value sctp_evt {
- g_m3ua_conn_id[i] := sctp_evt.connOpened.connId;
+ M3UA[i].receive(tr_ConnOpened) -> value port_evt {
+ g_m3ua_conn_id[i] := port_evt.connOpened.connId;
}
}
}
@@ -190,6 +449,12 @@ friend function f_M3UA_asp_act(integer idx, template (omit) M3UA_Traffic_Mode_Ty
f_M3UA_exp(idx, tr_M3UA_ASPAC_ACK(tmt, rctx));
}
+/* perform an outbound ASP-INACTIVATE procedure */
+friend function f_M3UA_asp_inact(integer idx, template (omit) OCT4 rctx := omit) runs on RAW_M3UA_CT {
+ f_M3UA_send(idx, ts_M3UA_ASPIA(rctx));
+ f_M3UA_exp(idx, tr_M3UA_ASPIA_ACK(rctx));
+}
+
/* perform outbound ASP-UP and ASP-ACT, optionally expect interemittent NOTIFY */
friend function f_M3UA_asp_up_act(integer idx, template (omit) M3UA_Traffic_Mode_Type tmt := omit,
template (omit) OCT4 rctx := omit,
@@ -263,10 +528,10 @@ testcase TC_asp_act_broadcast() runs on RAW_M3UA_CT {
/* test whether the STP accepts M3UA DATA without Routing Context IE */
testcase TC_act_rctx_data_no_rctx() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1023, 4);
- var OCT4 pc_sender := int2oct(23, 4);
- var OCT4 rctx_receiver := int2oct(1042, 4);
- var OCT4 pc_receiver := int2oct(42, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(1).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(1).point_code, 4);
f_init_m3ua();
/* bring up the sender specifying a routing context */
@@ -285,7 +550,7 @@ private function f_test_traffic(integer idx_tx, template (omit) OCT4 rctx_sender
integer idx_rx, template (omit) OCT4 rctx_receiver, OCT4 pc_rx,
OCT1 si := '23'O, OCT1 ni := '00'O, OCT1 mp := '00'O, OCT1 sls := '00'O)
runs on RAW_M3UA_CT {
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
f_M3UA_send(idx_tx, ts_M3UA_DATA(rctx_sender,
ts_M3UA_protocol_data(pc_tx, pc_rx, si, ni, mp, sls, data)), 1);
f_M3UA_exp(idx_rx, tr_M3UA_DATA(rctx_receiver,
@@ -295,10 +560,10 @@ runs on RAW_M3UA_CT {
/* test "traffic-mode override" behavior */
testcase TC_tmt_override() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1023, 4);
- var OCT4 pc_sender := int2oct(23, 4);
- var OCT4 rctx_receiver := int2oct(1042, 4);
- var OCT4 pc_receiver := int2oct(42, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(1).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(1).point_code, 4);
f_init_m3ua();
@@ -332,10 +597,10 @@ runs on RAW_M3UA_CT {
/* test "traffic-mode load-share" behavior */
testcase TC_tmt_loadshare() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1023, 4);
- var OCT4 pc_sender := int2oct(23, 4);
- var OCT4 rctx_receiver := int2oct(1042, 4);
- var OCT4 pc_receiver := int2oct(42, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(1).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(1).point_code, 4);
var integer i;
f_init_m3ua();
@@ -358,17 +623,17 @@ testcase TC_tmt_loadshare() runs on RAW_M3UA_CT {
/* verify traffic is routed from sender to new receiver */
const integer iter_per_asp := 5;
- var integer num_rx[NR_M3UA] := { 0, 0, 0 };
+ var integer num_rx[NR_M3UA] := { 0, 0, 0, 0 };
for (i := 0; i < 2*iter_per_asp; i := i+1) {
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
var template (value) M3UA_Protocol_Data tx_pd;
var template (present) M3UA_Protocol_Data rx_pd;
tx_pd := ts_M3UA_protocol_data(pc_sender, pc_receiver, '23'O, '00'O, '00'O, '00'O, data);
rx_pd := tr_M3UA_protocol_data(pc_sender, pc_receiver, '23'O, '00'O, '00'O, '00'O, data);
f_M3UA_send(0, ts_M3UA_DATA(rctx_sender, tx_pd), 1);
alt {
- [] as_count_rx(1, tr_M3UA_DATA(rctx_receiver, rx_pd), num_rx[1])
- [] as_count_rx(2, tr_M3UA_DATA(rctx_receiver, rx_pd), num_rx[2])
+ [] as_count_rx(1, tr_M3UA_DATA(rctx_receiver, rx_pd), num_rx[1]);
+ [] as_count_rx(2, tr_M3UA_DATA(rctx_receiver, rx_pd), num_rx[2]);
}
}
/* FIXME: check for extraneous messages? */
@@ -385,10 +650,10 @@ testcase TC_tmt_loadshare() runs on RAW_M3UA_CT {
/* test "traffic-mode broadcast" behavior */
testcase TC_tmt_broadcast() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1023, 4);
- var OCT4 pc_sender := int2oct(23, 4);
- var OCT4 rctx_receiver := int2oct(1042, 4);
- var OCT4 pc_receiver := int2oct(42, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(1).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(1).point_code, 4);
var integer i;
f_init_m3ua();
@@ -411,7 +676,7 @@ testcase TC_tmt_broadcast() runs on RAW_M3UA_CT {
/* verify traffic is routed from sender to new receiver */
for (i := 0; i < 10; i := i+1) {
- var octetstring data := f_rnd_octstring(f_rnd_int(100));
+ var octetstring data := f_rnd_octstring_rnd_len(100);
var template (value) M3UA_Protocol_Data tx_pd;
var template (present) M3UA_Protocol_Data rx_pd;
tx_pd := ts_M3UA_protocol_data(pc_sender, pc_receiver, '23'O, '00'O, '00'O, '00'O, data);
@@ -447,8 +712,8 @@ testcase TC_rkm_reg_static_notpermitted() runs on RAW_M3UA_CT {
/* Send RKM registration; expect OK as RCTX does match config */
testcase TC_rkm_reg_static_permitted() runs on RAW_M3UA_CT {
- var OCT3 dpc := int2oct(23, 3); // must match config
- var OCT4 rctx := int2oct(1023, 4); // must match config
+ var OCT3 dpc := int2oct(f_m3ua_cli_config(0).point_code, 3); // must match config
+ var OCT4 rctx := int2oct(f_m3ua_cli_config(0).routing_ctx, 4); // must match config
f_init_m3ua();
@@ -477,7 +742,8 @@ testcase TC_rkm_reg_dynamic_permitted() runs on RAW_M3UA_CT {
/* try to de-register a routing key that was never registered -> error */
testcase TC_rkm_unreg_never_registered() runs on RAW_M3UA_CT {
f_init_m3ua();
- f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(int2oct(1023,4))));
+ var octetstring rctx := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(rctx)));
f_M3UA_exp(0, tr_M3UA_DEREG_RSP({tr_M3UA_dereg_res(?,c_m3UA_DEREGSTS_ERR_NOT_REG)}));
f_clear_m3ua();
}
@@ -490,19 +756,33 @@ testcase TC_rkm_unreg_invalid() runs on RAW_M3UA_CT {
f_clear_m3ua();
}
-/* try to de-register a routing key that was registered -> OK*/
+/* try to de-register a routing key that was registered -> OK */
testcase TC_rkm_unreg_registered() runs on RAW_M3UA_CT {
+ var OCT3 dpc := int2oct(123, 3);
+ var OCT4 rctx := int2oct(1234, 4);
+
+ f_init_common();
+ f_vty_config2(VTY, {"cs7 instance 0"}, "xua rkm routing-key-allocation dynamic-permitted");
f_init_m3ua();
- f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(int2oct(1023,4))));
+
+ /* first register the routing key */
+ f_M3UA_rkm_register(id:='30000099'O, dpc:=dpc, rctx:=rctx);
+
+ /* then try to de-register */
+ f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(rctx)));
f_M3UA_exp(0, tr_M3UA_DEREG_RSP({tr_M3UA_dereg_res(?,c_m3UA_DEREGSTS_SUCCESS)}));
+
+ f_vty_config2(VTY, {"cs7 instance 0"}, "xua rkm routing-key-allocation static-only");
f_clear_m3ua();
}
/* try to de-register a routing key for an active ASP -> ERROR */
testcase TC_rkm_unreg_active() runs on RAW_M3UA_CT {
- var OCT3 dpc := int2oct(23, 3); // must match config
- var OCT4 rctx := int2oct(1023, 4); // must match config
+ var OCT3 dpc := int2oct(123, 3);
+ var OCT4 rctx := int2oct(1234, 4);
+ f_init_common();
+ f_vty_config2(VTY, {"cs7 instance 0"}, "xua rkm routing-key-allocation dynamic-permitted");
f_init_m3ua();
/* first register the routing key */
@@ -510,12 +790,22 @@ testcase TC_rkm_unreg_active() runs on RAW_M3UA_CT {
/* then activate the ASP */
f_M3UA_asp_up_act(0);
+ f_M3UA_exp(0, tr_M3UA_DAVA({*}, rctx));
+ f_M3UA_exp(0, tr_M3UA_NOTIFY(c_M3UA_ST_T_STATE_CHG, c_M3UA_ST_I_AS_ACTIVE, *));
+ f_M3UA_exp(0, tr_M3UA_DAVA({*}, *));
- /* then try to de-regsiter */
+ /* then try to de-register -> ERR_ASP_ACTIVE */
f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(rctx)));
f_M3UA_exp(0, tr_M3UA_DEREG_RSP({tr_M3UA_dereg_res(?,c_m3UA_DEREGSTS_ERR_ASP_ACTIVE)}));
- /* FIXME: we now may have changed the state on the STP side! */
+ /* deactivate ASP and properly de-register to clean up */
+ f_M3UA_asp_inact(0);
+ f_M3UA_send(0, ts_M3UA_DEREG_REQ(ts_M3UA_routing_ctx(rctx)));
+ f_M3UA_exp(0, tr_M3UA_NOTIFY(c_M3UA_ST_T_STATE_CHG, c_M3UA_ST_I_AS_PENDING, *));
+ f_M3UA_exp(0, tr_M3UA_NOTIFY(c_M3UA_ST_T_STATE_CHG, c_M3UA_ST_I_AS_PENDING, *));
+ f_M3UA_exp(0, tr_M3UA_DEREG_RSP({tr_M3UA_dereg_res(?,c_m3UA_DEREGSTS_SUCCESS)}));
+
+ f_vty_config2(VTY, {"cs7 instance 0"}, "xua rkm routing-key-allocation static-only");
f_clear_m3ua();
}
@@ -526,6 +816,9 @@ testcase TC_rkm_unreg_active() runs on RAW_M3UA_CT {
/* expect/perform an inbound ASP-UP procedure */
friend function f_M3UA_CLNT_asp_up(integer idx, template OCT4 aspid := omit) runs on RAW_M3UA_CT {
f_M3UA_exp(idx, tr_M3UA_ASPUP(aspid));
+ /* there might have been multiple re-transmissions that have queued up in the ATS between
+ * the SCTP connection establishment and this function execution, so let's flush those copies. */
+ f_M3UA_flush(idx, tr_M3UA_ASPUP(aspid));
f_M3UA_send(idx, ts_M3UA_ASPUP_ACK);
}
@@ -568,7 +861,8 @@ testcase TC_clnt_asp_act() runs on RAW_M3UA_CT {
f_init_m3ua();
f_init_m3ua_srv();
- f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := int2oct(1055, 4));
+ var OCT4 rctx := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctx);
f_clear_m3ua();
}
@@ -580,7 +874,8 @@ testcase TC_clnt_asp_act_tmt_loadshare() runs on RAW_M3UA_CT {
f_init_m3ua();
f_init_m3ua_srv();
- f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), tmt := c_M3UA_TMT_loadshare, rctx := int2oct(1055, 4));
+ var OCT4 rctx := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), tmt := c_M3UA_TMT_loadshare, rctx := rctx);
f_clear_m3ua();
}
@@ -588,16 +883,16 @@ testcase TC_clnt_asp_act_tmt_loadshare() runs on RAW_M3UA_CT {
/* Test traffic being routed through "server" side STP (M3UA SG), coming back in "client"
* side STP (M3UA ASP) */
testcase TC_clnt_sg_to_asp() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1023, 4);
- var OCT4 pc_sender := int2oct(23, 4);
- var OCT4 rctx_receiver := int2oct(1055, 4);
- var OCT4 pc_receiver := int2oct(55, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_srv_config(0).point_code, 4);
f_init_m3ua();
f_M3UA_asp_up_act(0);
f_init_m3ua_srv();
- f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := int2oct(1055, 4));
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctx_receiver);
f_sleep(1.0);
@@ -610,16 +905,16 @@ testcase TC_clnt_sg_to_asp() runs on RAW_M3UA_CT {
/* Test traffic being routed through "client" side STP (M3UA ASP), coming back in "server"
* side STP (M3UA SG) */
testcase TC_clnt_asp_to_sg() runs on RAW_M3UA_CT {
- var OCT4 rctx_sender := int2oct(1055, 4);
- var OCT4 pc_sender := int2oct(55, 4);
- var OCT4 rctx_receiver := int2oct(1023, 4);
- var OCT4 pc_receiver := int2oct(23, 4);
+ var OCT4 rctx_sender := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_srv_config(0).point_code, 4);
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(0).point_code, 4);
f_init_m3ua();
f_M3UA_asp_up_act(0);
f_init_m3ua_srv();
- f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := int2oct(1055, 4));
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctx_sender);
f_sleep(1.0);
@@ -628,6 +923,372 @@ testcase TC_clnt_asp_to_sg() runs on RAW_M3UA_CT {
f_clear_m3ua();
}
+/* Test traffic being routed through "server" side STP (M3UA SG), coming back in "client"
+ * side STP (M3UA ASP) which has no routing context set */
+testcase TC_clnt_sg_to_asp_norctx() runs on RAW_M3UA_CT {
+ var OCT4 rctx_sender := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_srv_config(1).point_code, 4);
+ var OCT4 pc_receiver2 := int2oct(f_m3ua_srv_config(2).point_code, 4);
+
+ /* activate the sender side (ATS is client to STP in SG role) */
+ f_init_m3ua();
+ f_M3UA_asp_up_act(0);
+
+ /* activate the receiver side (ATS is server to STP in ASP role) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(1), rctx := omit);
+ /* activate another instance of STP in ASP role with no routing context */
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(2), rctx := omit);
+
+ f_sleep(1.0);
+
+ /* verify traffic is routed from sender to [sole] receiver for each PC */
+ f_test_traffic(0, rctx_sender, pc_sender, M3UA_SRV(1), omit, pc_receiver);
+ f_test_traffic(0, rctx_sender, pc_sender, M3UA_SRV(2), omit, pc_receiver2);
+
+ f_clear_m3ua();
+}
+
+/* Test traffic being routed through "server" side STP (M3UA SG), coming back in "client"
+ * side STP (M3UA ASP) which has no routing context set */
+testcase TC_clnt_asp_to_sg_norctx() runs on RAW_M3UA_CT {
+ var OCT4 rctx_receiver := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 pc_receiver := int2oct(f_m3ua_cli_config(0).point_code, 4);
+ var OCT4 pc_sender := int2oct(f_m3ua_srv_config(1).point_code, 4);
+ var OCT4 pc_sender2 := int2oct(f_m3ua_srv_config(2).point_code, 4);
+
+ /* activate the sender side (ATS is client to STP in SG role) */
+ f_init_m3ua();
+ f_M3UA_asp_up_act(0);
+
+ /* activate the receiver side (ATS is server to STP in ASP role) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(1), rctx := omit);
+ /* activate another instance of STP in ASP role with no routing context */
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(2), rctx := omit);
+
+ f_sleep(1.0);
+
+ /* verify traffic is routed from sender to [sole] receiver for each PC */
+ f_test_traffic(M3UA_SRV(1), omit, pc_sender, 0, rctx_receiver, pc_receiver);
+ f_test_traffic(M3UA_SRV(2), omit, pc_sender2, 0, rctx_receiver, pc_receiver);
+
+ f_clear_m3ua();
+}
+
+/* Test if ASPAC / ASPIA of one ASP generates DAVA / DUNA on other ASP */
+testcase TC_ssnm_aspac_dava_aspia_duna() runs on RAW_M3UA_CT {
+ var OCT4 rctx0 := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var integer pc0 := f_m3ua_cli_config(1).point_code;
+
+ f_init_m3ua(ignore_ssnm := false);
+ /* activate the first ASP */
+ f_M3UA_asp_up_act(0);
+
+ /* activate the second ASP */
+ f_M3UA_asp_up_act(1, c_M3UA_TMT_override, omit);
+ /* expect DAVA for PC of second ASP on first ASP */
+ f_M3UA_exp(0, tr_M3UA_DAVA({ts_M3UA_PC(pc0, 0)}, rctx0));
+ /* TODO: expect no DAVA on second ASP */
+
+ /* deactivate the second ASP */
+ f_M3UA_asp_inact(1);
+ /* expect DUNA for PC of second ASP on first ASP */
+ f_M3UA_exp(0, tr_M3UA_DUNA({ts_M3UA_PC(pc0, 0)}, rctx0));
+ /* TODO: expect no DUNA on second ASP */
+
+ f_clear_m3ua();
+}
+
+/* Test if DAVA/DUNA sent from SG to ASP-role STP gets forwarded to other ASP */
+testcase TC_ssnm_distribution_dava_duna() runs on RAW_M3UA_CT {
+ var OCT4 rctx0 := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 rctxS0 := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ /* some random point code whose availability we advertise */
+ var template (value) M3UA_Point_Code adv_pc := ts_M3UA_PC(1234, 0);
+
+ f_init_m3ua(ignore_ssnm := false);
+
+ /* activate the first ASP */
+ f_M3UA_asp_up_act(0);
+
+ /* activate SG-role ASP (ASP on STP) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctxS0);
+
+ /* transmit a DAVA to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAVA({adv_pc}, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_DAVA({adv_pc}, rctx0));
+
+ /* transmit a DUNA to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DUNA({adv_pc}, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_DUNA({adv_pc}, rctx0));
+}
+
+/* Test if DAVA/DUNA sent from SG to ASP-role STP gets forwarded to other ASP */
+testcase TC_ssnm_distribution_dava_duna_multipc() runs on RAW_M3UA_CT {
+ var OCT4 rctx0 := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 rctxS0 := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ /* some random point code whose availability we advertise */
+ var template (value) M3UA_Point_Codes adv_pcs := { ts_M3UA_PC(1234, 0), ts_M3UA_PC(5678, 0) };
+
+ f_init_m3ua(ignore_ssnm := false);
+
+ /* activate the first ASP */
+ f_M3UA_asp_up_act(0);
+
+ /* activate SG-role ASP (ASP on STP) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctxS0);
+
+ /* transmit a DAVA to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAVA(adv_pcs, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_DAVA(adv_pcs, rctx0));
+
+ /* transmit a DUNA to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DUNA(adv_pcs, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_DUNA(adv_pcs, rctx0));
+}
+
+/* Test if DUPU sent from SG to ASP-role STP gets forwarded to other ASP */
+testcase TC_ssnm_distribution_dupu() runs on RAW_M3UA_CT {
+ var OCT4 rctx0 := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 rctxS0 := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ /* some random point code whose availability we advertise */
+ var template (value) M3UA_Point_Code adv_pc := ts_M3UA_PC(1234, 0);
+
+ f_init_m3ua(ignore_ssnm := false);
+
+ /* activate the first ASP */
+ f_M3UA_asp_up_act(0);
+
+ /* activate SG-role ASP (ASP on STP) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctxS0);
+
+ /* transmit a DUPU to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DUPU({adv_pc}, '0102'O, 'ABCD'O, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_DUPU({adv_pc}, '0102'O, 'ABCD'O, rctx0));
+}
+
+/* Test if SCON sent from SG to ASP-role STP gets forwarded to other ASP */
+testcase TC_ssnm_distribution_scon() runs on RAW_M3UA_CT {
+ var OCT4 rctx0 := int2oct(f_m3ua_cli_config(0).routing_ctx, 4);
+ var OCT4 rctxS0 := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ /* some random point code whose availability we advertise */
+ var template (value) M3UA_Point_Code adv_pc := ts_M3UA_PC(1234, 0);
+
+ f_init_m3ua(ignore_ssnm := false);
+
+ /* activate the first ASP */
+ f_M3UA_asp_up_act(0);
+
+ /* activate SG-role ASP (ASP on STP) */
+ f_init_m3ua_srv();
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctxS0);
+
+ /* transmit a SCON to the remote ASP */
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_SCON({adv_pc}, rctxS0));
+ /* expect that to show up on other ASP */
+ f_M3UA_exp(0, tr_M3UA_SCON({adv_pc}, rctx0));
+}
+
+private function f_asp_cfg_str(charstring asp_name, in M3uaConfig cfg)
+return charstring {
+ var charstring str;
+
+ str := "asp " & asp_name;
+ str := str & " " & int2str(cfg.local_port);
+ str := str & " " & int2str(cfg.remote_port);
+ str := str & " m3ua";
+
+ if (cfg.use_tcp) {
+ str := str & " tcp";
+ }
+
+ return str;
+}
+
+private function f_quirk(charstring quirk) runs on RAW_M3UA_CT {
+ var charstring asp_cfg_str := f_asp_cfg_str("asp-client0", f_m3ua_srv_config(0));
+ f_vty_config2(VTY, {"cs7 instance 0", asp_cfg_str}, "quirk " & quirk);
+}
+
+private function f_no_quirk(charstring quirk) runs on RAW_M3UA_CT {
+ var charstring asp_cfg_str := f_asp_cfg_str("asp-client0", f_m3ua_srv_config(0));
+ f_vty_config2(VTY, {"cs7 instance 0", asp_cfg_str}, "no quirk " & quirk);
+}
+
+/* quirk 'no_notify': Expect inbound connection from ASP/SCTP-client, followed by ASP-UP + ASP-ACT */
+testcase TC_clnt_quirk_no_notify_asp_act() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_quirk("no_notify");
+ f_init_m3ua_srv();
+
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := int2oct(f_m3ua_srv_config(0).routing_ctx, 4),
+ ntfy_after_up := omit, ntfy_after_act := omit);
+ f_no_quirk("no_notify");
+ f_clear_m3ua();
+}
+
+/* ensure that DAUD is not supported in ASP role, as required by RFC */
+testcase TC_clnt_no_daud_in_asp() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_no_quirk("daud_in_asp");
+ f_init_m3ua_srv();
+
+ var OCT4 rctx := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ var integer pc := f_m3ua_srv_config(0).point_code;
+
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctx);
+
+ var template (value) M3UA_Point_Codes aff_pcs := { ts_M3UA_PC(pc) };
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAUD(aff_pcs));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_ERR('00000004'O, omit));
+ setverdict(pass);
+
+ f_clear_m3ua();
+}
+
+/* quirk 'daud_in_asp': allowing inbound DAUD from SG in ASP role */
+testcase TC_clnt_quirk_daud_in_asp() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_quirk("daud_in_asp");
+ f_init_m3ua_srv();
+
+ var OCT4 rctx := int2oct(f_m3ua_srv_config(0).routing_ctx, 4);
+ var integer pc := f_m3ua_srv_config(0).point_code;
+
+ f_M3UA_CLNT_asp_up_act(M3UA_SRV(0), rctx := rctx);
+
+ var template (value) M3UA_Point_Codes aff_pcs := { ts_M3UA_PC(pc) };
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAUD(aff_pcs));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_DAVA(aff_pcs));
+ setverdict(pass);
+
+ f_no_quirk("daud_in_asp");
+ f_clear_m3ua();
+}
+
+/* Expect a normal ASP to reject any [S]SNM messages in ASP-INACTIVE state */
+testcase TC_clnt_no_snm_inactive() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_quirk("no_notify");
+ f_quirk("daud_in_asp");
+ f_no_quirk("snm_inactive");
+ f_init_m3ua_srv();
+
+ /* bring ASP only UP (into INACTIVE state), but not ACTIVE! */
+ f_M3UA_CLNT_asp_up(M3UA_SRV(0));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_ASPAC(*, *));
+
+ var template (value) M3UA_Point_Codes aff_pcs := { ts_M3UA_PC(f_m3ua_srv_config(0).point_code) };
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAUD(aff_pcs));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_ERR('00000006'O, omit));
+ setverdict(pass);
+
+ f_no_quirk("no_notify");
+ f_no_quirk("daud_in_asp");
+ f_clear_m3ua();
+}
+
+/* quirk 'snm_inactive': Process [S]SNM in ASP-INACTIVE state */
+testcase TC_clnt_quirk_snm_inactive() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_quirk("no_notify");
+ f_quirk("daud_in_asp");
+ f_quirk("snm_inactive");
+ f_init_m3ua_srv();
+
+ /* bring ASP only UP (into INACTIVE state), but not ACTIVE! */
+ f_M3UA_CLNT_asp_up(M3UA_SRV(0));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_ASPAC(*, *));
+
+ var template (value) M3UA_Point_Codes aff_pcs := { ts_M3UA_PC(f_m3ua_srv_config(0).point_code) };
+ f_M3UA_send(M3UA_SRV(0), ts_M3UA_DAUD(aff_pcs));
+ f_M3UA_exp(M3UA_SRV(0), tr_M3UA_DAVA(aff_pcs));
+ setverdict(pass);
+
+ f_no_quirk("no_notify");
+ f_no_quirk("daud_in_asp");
+ f_no_quirk("snm_inactive");
+ f_clear_m3ua();
+}
+
+private function f_TC_m3ua_tcp(integer idx_a, integer idx_b) runs on RAW_M3UA_CT {
+ var M3uaConfig cfg_a := mp_m3ua_configs[idx_a];
+ var M3uaConfig cfg_b := mp_m3ua_configs[idx_b];
+ var OCT4 rctx_a := int2oct(cfg_a.routing_ctx, 4);
+ var OCT4 rctx_b := int2oct(cfg_b.routing_ctx, 4);
+ var OCT4 pc_a := int2oct(cfg_a.point_code, 4);
+ var OCT4 pc_b := int2oct(cfg_b.point_code, 4);
+
+ /* establish connection with ASP 'A' */
+ if (idx_a < NR_M3UA) {
+ f_M3UA_asp_up_act(idx_a, rctx := rctx_a);
+ } else {
+ f_M3UA_CLNT_asp_up_act(idx_a, rctx := rctx_a);
+ }
+
+ /* establish connection with ASP 'B' */
+ if (idx_b < NR_M3UA) {
+ f_M3UA_asp_up_act(idx_b, rctx := rctx_b);
+ } else {
+ f_M3UA_CLNT_asp_up_act(idx_b, rctx := rctx_b);
+ }
+
+ /* In the case when ASP[idx_b] is configured as the client (i.e. osmo-stp connects to
+ * the testsuite; idx_b >= NR_M3UA), in f_M3UA_CLNT_asp_up_act() we're expecting to
+ * receive ASPACT and then sending ASPACT_ACK to it. Right after that, we're sending
+ * some random data via ASP[idx_a], which we then expect to receive via ASP[idx_b].
+ *
+ * There is a chance that the random data sent via ASP[idx_a] would reach osmo-stp
+ * earlier than the ASPUP_ACK we sent for ASP[idx_b]. This is happening most of the
+ * times when running TC_m3ua_tcp_cli_srv. Using f_sleep() helps to avoid this. */
+ f_sleep(1.0);
+
+ /* M3UA/A -> M3UA/B */
+ f_test_traffic(idx_a, rctx_a, pc_a,
+ idx_b, rctx_b, pc_b);
+ /* M3UA/B -> M3UA/A */
+ f_test_traffic(idx_b, rctx_b, pc_b,
+ idx_a, rctx_a, pc_a);
+
+ f_clear_m3ua();
+}
+
+/* test routing between M3UA/SCTP (client) and M3UA/TCP (client) */
+testcase TC_m3ua_tcp_cli() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_TC_m3ua_tcp(0, 3); /* 'asp-sender' <-> 'asp-sender-tcp' */
+}
+
+/* test routing between M3UA/SCTP (client) and M3UA/TCP (server) */
+testcase TC_m3ua_tcp_cli_srv() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_init_m3ua_srv();
+ f_TC_m3ua_tcp(0, M3UA_SRV(3)); /* 'asp-sender' <-> 'asp-client-tcp' */
+}
+
+/* test routing between M3UA/SCTP (server) and M3UA/TCP (server) */
+testcase TC_m3ua_tcp_srv() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_init_m3ua_srv();
+ f_TC_m3ua_tcp(M3UA_SRV(0), M3UA_SRV(3)); /* 'asp-client' <-> 'asp-client-tcp' */
+}
+
+/* test routing between M3UA/SCTP (server) and M3UA/TCP (client) */
+testcase TC_m3ua_tcp_srv_cli() runs on RAW_M3UA_CT {
+ f_init_m3ua();
+ f_init_m3ua_srv();
+ f_TC_m3ua_tcp(M3UA_SRV(0), 3); /* 'asp-client' <-> 'asp-sender-tcp' */
+}
control {
@@ -644,11 +1305,17 @@ control {
execute( TC_tmt_broadcast() );
execute( TC_act_rctx_data_no_rctx() );
+ execute( TC_m3ua_tcp_cli() );
+ execute( TC_m3ua_tcp_cli_srv() );
+ execute( TC_m3ua_tcp_srv() );
+ execute( TC_m3ua_tcp_srv_cli() );
+
/* M3UA RKM tests */
execute( TC_rkm_reg_static_notpermitted() );
execute( TC_rkm_reg_static_permitted() );
execute( TC_rkm_reg_dynamic_permitted() );
execute( TC_rkm_unreg_never_registered() );
+
execute( TC_rkm_unreg_invalid() );
execute( TC_rkm_unreg_registered() );
execute( TC_rkm_unreg_active() );
@@ -662,6 +1329,23 @@ control {
execute( TC_clnt_sg_to_asp() );
execute( TC_clnt_asp_to_sg() );
+ execute( TC_clnt_sg_to_asp_norctx() );
+ execute( TC_clnt_asp_to_sg_norctx() );
+
+ execute( TC_clnt_quirk_no_notify_asp_act() );
+ execute( TC_clnt_no_daud_in_asp() );
+ execute( TC_clnt_quirk_daud_in_asp() );
+ execute( TC_clnt_no_snm_inactive() );
+ execute( TC_clnt_quirk_snm_inactive() );
+
+
+ /* M3UA SSNM tests */
+ execute( TC_ssnm_aspac_dava_aspia_duna() );
+ execute( TC_ssnm_distribution_dava_duna() );
+ execute( TC_ssnm_distribution_dava_duna_multipc() );
+ execute( TC_ssnm_distribution_dupu() );
+ execute( TC_ssnm_distribution_scon() );
+
/* put this one last as it changes the stp side config */
execute( TC_clnt_asp_act_tmt_loadshare() );
}
diff --git a/stp/expected-results.xml b/stp/expected-results.xml
new file mode 100644
index 00000000..fdb4e44d
--- /dev/null
+++ b/stp/expected-results.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0"?>
+<testsuite name='STP_Tests' tests='50' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='STP_Tests_M3UA' name='TC_connect_asp_up' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_beat' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_beat_payload' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_asp_act' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_asp_act_override' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_asp_act_loadshare' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_asp_act_broadcast' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_tmt_override' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_tmt_loadshare' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_tmt_broadcast' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_act_rctx_data_no_rctx' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_m3ua_tcp_cli' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_m3ua_tcp_cli_srv' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_m3ua_tcp_srv' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_m3ua_tcp_srv_cli' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_reg_static_notpermitted' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_reg_static_permitted' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_reg_dynamic_permitted' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_unreg_never_registered' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_unreg_invalid' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_unreg_registered' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_rkm_unreg_active' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_connect_asp_up' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_asp_act' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_sg_to_asp' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_asp_to_sg' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_sg_to_asp_norctx' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_asp_to_sg_norctx' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_quirk_no_notify_asp_act' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_no_daud_in_asp' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_quirk_daud_in_asp' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_no_snm_inactive' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_quirk_snm_inactive' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_ssnm_aspac_dava_aspia_duna' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_ssnm_distribution_dava_duna' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_ssnm_distribution_dava_duna_multipc' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_ssnm_distribution_dupu' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_ssnm_distribution_scon' time='MASKED'/>
+ <testcase classname='STP_Tests_M3UA' name='TC_clnt_asp_act_tmt_loadshare' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_unknown_client_nodynamic' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_known_client_nodynamic' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_unknown_client_dynamic' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_tmt_override' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_unknown_client_dynamic_tmt_override' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_tmt_loadshare' time='MASKED'/>
+ <testcase classname='STP_Tests_IPA' name='TC_unknown_client_dynamic_tmt_loadshare' time='MASKED'/>
+ <testcase classname='STP_Tests' name='TC_m3ua_to_ipa' time='MASKED'/>
+ <testcase classname='STP_Tests' name='TC_ipa_to_m3ua' time='MASKED'/>
+ <testcase classname='STP_Tests' name='TC_ipa_to_m3ua_ni' time='MASKED'/>
+ <testcase classname='STP_Tests' name='TC_ipa_to_m3ua_patch_sccp' time='MASKED'/>
+</testsuite>
diff --git a/stp/osmo-stp-tcp.confmerge b/stp/osmo-stp-tcp.confmerge
new file mode 100644
index 00000000..b40867a1
--- /dev/null
+++ b/stp/osmo-stp-tcp.confmerge
@@ -0,0 +1,22 @@
+cs7 instance 0
+ asp asp-sender-tcp 9999 2905 m3ua tcp
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role sg
+ transport-role server
+ asp asp-client0-tcp 10002 2906 m3ua tcp
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role asp
+ transport-role client
+ as as-sender-tcp m3ua
+ asp asp-sender-tcp
+ routing-key 1123 123
+ as as-client-tcp m3ua
+ routing-key 1155 155
+ asp asp-client0-tcp
+ route-table system
+ update route 123 16777215 linkset as-sender-tcp
+ update route 155 16777215 linkset as-client-tcp
+ listen m3ua 2905 tcp
+ accept-asp-connections dynamic-permitted
diff --git a/stp/osmo-stp.cfg b/stp/osmo-stp.cfg
index 50c80d37..13b1b719 100644
--- a/stp/osmo-stp.cfg
+++ b/stp/osmo-stp.cfg
@@ -4,11 +4,12 @@
!
log stderr
logging filter all 1
- logging color 1
- logging print category-hex 1
+ logging print file basename last
+ logging print category-hex 0
logging print category 1
+ logging print level 1
logging timestamp 0
- logging print file 1
+ logging color 1
logging level lglobal notice
logging level llapd notice
logging level linp notice
@@ -42,17 +43,33 @@ cs7 instance 0
asp asp-sender 9999 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
asp asp-receiver0 10000 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
asp asp-receiver1 10001 2905 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
asp asp-client0 10002 2906 m3ua
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role asp
+ sctp-role client
+ asp asp-client60-norctx0 11060 2907 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
+ role asp
sctp-role client
+ asp asp-client61-norctx0 11061 2907 m3ua
+ local-ip 127.0.0.1
+ remote-ip 127.0.0.1
role asp
+ sctp-role client
as as-sender m3ua
asp asp-sender
routing-key 1023 23
@@ -63,12 +80,20 @@ cs7 instance 0
as as-client m3ua
routing-key 1055 55
asp asp-client0
+ as as-client60-norctx m3ua
+ routing-key 0 60
+ asp asp-client60-norctx0
+ as as-client61-norctx m3ua
+ routing-key 0 61
+ asp asp-client61-norctx0
!
! IPA AS/ASP:
!
asp ipa-asp-loadshare-sender 20000 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as ipa-as-loadshare-sender ipa
routing-key 0 6
point-code override dpc 31
@@ -76,9 +101,13 @@ cs7 instance 0
asp ipa-asp-loadshare-receiver0 20001 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
asp ipa-asp-loadshare-receiver1 20002 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as ipa-as-loadshare-receiver ipa
traffic-mode loadshare
routing-key 0 7
@@ -89,6 +118,8 @@ cs7 instance 0
asp ipa-asp-override-sender 20004 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
as ipa-as-override-sender ipa
routing-key 0 6
point-code override dpc 33
@@ -96,6 +127,8 @@ cs7 instance 0
asp ipa-asp-override-receiver0 20005 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
+ role sg
+ sctp-role server
asp ipa-asp-override-receiver1 20006 5000 ipa
local-ip 127.0.0.1
remote-ip 127.0.0.1
@@ -116,6 +149,8 @@ cs7 instance 0
update route 23 16777215 linkset as-sender
update route 42 16777215 linkset as-receiver
update route 55 16777215 linkset as-client
+ update route 60 16777215 linkset as-client60-norctx
+ update route 61 16777215 linkset as-client61-norctx
update route 31 16777215 linkset ipa-as-loadshare-receiver
update route 33 16777215 linkset ipa-as-override-receiver
update route 5 16777215 linkset ipa-as-dynamic-asp
diff --git a/stp/regen_makefile.sh b/stp/regen_makefile.sh
index be96829d..032be0d0 100755
--- a/stp/regen_makefile.sh
+++ b/stp/regen_makefile.sh
@@ -1,7 +1,27 @@
#!/bin/sh
-FILES="*.ttcn *.ttcnpp SCCP_EncDec.cc SCTPasp_PT.cc TCCConversion.cc TCCInterface.cc IPL4asp_PT.cc IPL4asp_discovery.cc IPA_CodecPort_CtrlFunctDef.cc TELNETasp_PT.cc Native_FunctionDefs.cc TCCEncoding.cc M3UA_CodecPort_CtrlFunctDef.cc "
+NAME=STP_Tests
-export CPPFLAGS_TTCN3="-DIPA_EMULATION_CTRL -DIPA_EMULATION_SCCP -DUSE_MTP3_DISTRIBUTOR"
+FILES="
+ *.ttcn
+ *.ttcnpp
+ SCCP_EncDec.cc
+ SCTPasp_PT.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ TELNETasp_PT.cc
+ Native_FunctionDefs.cc
+ TCCEncoding.cc
+ M3UA_CodecPort_CtrlFunctDef.cc
+"
-../regen-makefile.sh STP_Tests.ttcn $FILES
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+ -DIPA_EMULATION_SCCP
+ -DUSE_MTP3_DISTRIBUTOR
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/sysinfo/gen_links.sh b/sysinfo/gen_links.sh
index 0648e7b8..c8a3ee36 100755
--- a/sysinfo/gen_links.sh
+++ b/sysinfo/gen_links.sh
@@ -9,7 +9,7 @@ FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc
gen_links $DIR $FILES
DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
-FILES="MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn"
+FILES="MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn"
gen_links $DIR $FILES
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
@@ -25,7 +25,7 @@ FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
gen_links $DIR $FILES
DIR=../library
-FILES="GSMTAP_PortType.ttcn GSMTAP_Types.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn GSM_RR_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_Types.ttcn IPL4_GSMTAP_CtrlFunct.ttcn IPL4_GSMTAP_CtrlFunctDef.cc Osmocom_Types.ttcn Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn"
+FILES="GSMTAP_PortType.ttcn GSMTAP_Types.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn GSM_RR_Types.ttcn RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_Types.ttcn IPL4_GSMTAP_CtrlFunct.ttcn IPL4_GSMTAP_CtrlFunctDef.cc Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn"
gen_links $DIR $FILES
ignore_pp_results
diff --git a/sysinfo/regen_makefile.sh b/sysinfo/regen_makefile.sh
index 9dd3b7f2..1ed5835c 100755
--- a/sysinfo/regen_makefile.sh
+++ b/sysinfo/regen_makefile.sh
@@ -1,5 +1,19 @@
#!/bin/sh
-FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc IPL4_GSMTAP_CtrlFunctDef.cc TELNETasp_PT.cc"
+NAME=Test
-../regen-makefile.sh Test.ttcn $FILES
+FILES="
+ *.ttcn
+ IPL4_GSMTAP_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ TCCConversion.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+"
+
+../regen-makefile.sh -e $NAME $FILES
diff --git a/ttcn3-dumpcap-start.sh b/ttcn3-dumpcap-start.sh
new file mode 100755
index 00000000..a1e64fcc
--- /dev/null
+++ b/ttcn3-dumpcap-start.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+#
+# contrary to ttcn3-tcpdump-start.sh, this version is dumpcap-only and
+# needed when we want to capture from interfaces of different link
+# types. It will also store the results as pcap-ng, not plain old pcap.
+
+PIDFILE_PCAP=/tmp/pcap.pid
+DUMPCAP=/usr/bin/dumpcap
+
+PIDFILE_NETCAT=/tmp/netcat.pid
+NETCAT=/bin/nc
+GSMTAP_PORT=4729
+
+TESTCASE=$1
+
+kill_rm_pidfile() {
+ if [ -e $1 ]; then
+ kill "$(cat "$1")"
+ rm $1
+ fi
+}
+
+echo "------ $TESTCASE ------"
+date
+
+if [ "z$TTCN3_PCAP_PATH" = "z" ]; then
+ TTCN3_PCAP_PATH=/tmp
+fi
+
+kill_rm_pidfile $PIDFILE_NETCAT
+kill_rm_pidfile $PIDFILE_PCAP
+
+if [ ! -x "$DUMPCAP" ]; then
+ echo "Missing required dumpcap binary at ${DUMPCAP}"
+ exit 31
+fi
+
+if [ "$(id -u)" = "0" ]; then
+ CMD="$DUMPCAP -q"
+else
+ CAP_ERR="1"
+ if [ -x /sbin/setcap ]; then
+ # N. B: this check requires libcap2-bin package
+ /sbin/setcap -q -v 'cap_net_admin,cap_net_raw=pie' $DUMPCAP
+ CAP_ERR="$?"
+ fi
+ if [ -u $DUMPCAP -o "$CAP_ERR" = "0" ]; then
+ CMD="$DUMPCAP -q"
+ else
+ echo "NOTE: unable to use dumpcap due to missing capabilities or suid bit"
+ exit 32
+ fi
+fi
+
+# Create a dummy sink for GSMTAP packets
+$NETCAT -l -u -k -p $GSMTAP_PORT >/dev/null 2>$TESTCASE.netcat.stderr &
+PID=$!
+echo $PID > $PIDFILE_NETCAT
+
+# generate the list of interface arguments. For capturing from
+# interfaces of different link-layer types, we cannot use "-i all"
+# but must use dumpcap with each individual interface name. We also
+# must write pcapng files, as only those can record the interface of
+# each packet
+ADDL_ARGS="-i lo"
+for f in /sys/class/net/*; do
+ DEV=`basename $f`
+ if [[ "$DEV" == "hdlcnet"* ]]; then
+ # skip these as we only want the hdlcX devices, avoid capturing twice on both sides
+ continue
+ elif [[ "$DEV" == "hdlc"* ]]; then
+ # these are the user-side of the FR links, which is
+ # what we interface with from our test suite, emulating
+ # a BSS.
+ ADDL_ARGS="${ADDL_ARGS} -i ${DEV}"
+ elif [[ "$DEV" == "eth"* ]]; then
+ # we blindly assume that "normal" docker network devices
+ # are called ethXXX
+ ADDL_ARGS="${ADDL_ARGS} -i ${DEV}"
+ fi
+done
+
+$CMD -s 1520 -n ${ADDL_ARGS} -w "$TTCN3_PCAP_PATH/$TESTCASE.pcapng" >$TTCN3_PCAP_PATH/$TESTCASE.pcapng.stdout 2>&1 &
+PID=$!
+echo $PID > $PIDFILE_PCAP
+
+# Wait until packet dumper creates the pcap file and starts recording.
+# We generate some traffic until we see packet dumper catches it.
+# Timeout is 10 seconds.
+ping 127.0.0.1 >/dev/null 2>&1 &
+PID=$!
+i=0
+while [ ! -f "$TTCN3_PCAP_PATH/$TESTCASE.pcapng" ] ||
+ [ "$(stat -c '%s' "$TTCN3_PCAP_PATH/$TESTCASE.pcapng")" -eq 32 ]
+do
+ echo "Waiting for packet dumper to start... $i"
+ sleep 1
+ i=$((i+1))
+ if [ $i -eq 10 ]; then
+ break
+ fi
+done
+kill $PID
diff --git a/ttcn3-dumpcap-stop.sh b/ttcn3-dumpcap-stop.sh
new file mode 100755
index 00000000..188b8da4
--- /dev/null
+++ b/ttcn3-dumpcap-stop.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+PIDFILE_PCAP=/tmp/pcap.pid
+PIDFILE_NETCAT=/tmp/netcat.pid
+TESTCASE=$1
+VERDICT="$2"
+
+kill_rm_pidfile() {
+if [ -e $1 ]; then
+ PSNAME="$(ps -q "$(cat "$1")" -o comm=)"
+ if [ "$PSNAME" != "sudo" ]; then
+ kill "$(cat "$1")"
+ else
+ # NOTE: This requires you to be root or something like
+ # "laforge ALL=NOPASSWD: /usr/sbin/tcpdump, /bin/kill" in your sudoers file
+ sudo kill "$(cat "$1")"
+ fi
+ rm $1
+fi
+}
+
+date
+
+if [ x"$VERDICT" = x"pass" ]; then
+ printf "\033[1;32m====== $TESTCASE $VERDICT ======\033[0m\n\n"
+else
+ printf "\033[1;31m------ $TESTCASE $VERDICT ------\033[0m\n\n"
+fi
+
+if [ "z$TTCN3_PCAP_PATH" = "z" ]; then
+ TTCN3_PCAP_PATH=/tmp
+fi
+
+# Wait for up to 2 seconds if we keep receiving traffinc from packet dumper,
+# otherwise we might lose last packets from test.
+i=0
+prev_count=-1
+count=$(stat --format="%s" "$TTCN3_PCAP_PATH/$TESTCASE.pcapng")
+while [ $count -gt $prev_count ] && [ $i -lt 2 ]
+do
+ echo "Waiting for packet dumper to finish... $i (prev_count=$prev_count, count=$count)"
+ sleep 1
+ prev_count=$count
+ count=$(stat --format="%s" "$TTCN3_PCAP_PATH/$TESTCASE.pcapng")
+ i=$((i+1))
+done
+
+kill_rm_pidfile "$PIDFILE_PCAP"
+kill_rm_pidfile "$PIDFILE_NETCAT"
+
+gzip -f "$TTCN3_PCAP_PATH/$TESTCASE.pcapng"
diff --git a/ttcn3-tcpdump-start.sh b/ttcn3-tcpdump-start.sh
index 3ad14c0a..36aa3204 100755
--- a/ttcn3-tcpdump-start.sh
+++ b/ttcn3-tcpdump-start.sh
@@ -1,18 +1,30 @@
#!/bin/sh
PIDFILE_PCAP=/tmp/pcap.pid
-TCPDUMP=/usr/sbin/tcpdump
-DUMPCAP=/usr/bin/dumpcap
+TCPDUMP=$(command -v tcpdump)
+DUMPCAP=$(command -v dumpcap)
PIDFILE_NETCAT=/tmp/netcat.pid
-NETCAT=/bin/nc
+NETCAT=$(command -v nc)
GSMTAP_PORT=4729
TESTCASE=$1
+
+SUDOSTR=""
+if ! [ "$(id -u)" = "0" ]; then
+ SUDOSTR="sudo -n"
+ # Otherwise, if sudo /usr/bin/kill, sudo /usr/bin/tcpdump cannot be run without a password prompt,
+ # and this script will hang indefinitely
+fi
+
kill_rm_pidfile() {
- if [ -e $1 ]; then
- kill "$(cat "$1")"
+ # NOTE: This requires you to be root or something like
+ # "laforge ALL=NOPASSWD: /usr/sbin/tcpdump, /bin/kill" in your sudoers file
+ if [ -e "$1" ]; then
+ if [ -s "$1" ]; then
+ $SUDOSTR kill "$(cat "$1")" 2>&1 | grep -v "No such process"
+ fi
rm $1
fi
}
@@ -27,21 +39,28 @@ fi
kill_rm_pidfile $PIDFILE_NETCAT
kill_rm_pidfile $PIDFILE_PCAP
-if [ "$(id -u)" = "0" ]; then
- CMD="$TCPDUMP -U"
-else
-# NOTE: This requires you to be root or something like
-# "laforge ALL=NOPASSWD: /usr/sbin/tcpdump, /bin/kill" in your sudoers file
- CMD="sudo $TCPDUMP -U"
-fi
+CMD="$SUDOSTR $TCPDUMP -U"
-if [ -x $DUMPCAP ]; then
+if [ -x "$DUMPCAP" ]; then
CAP_ERR="1"
if [ -x /sbin/setcap ]; then
# N. B: this check requires libcap2-bin package
- setcap -q -v 'cap_net_admin,cap_net_raw=pie' $DUMPCAP
+ /sbin/setcap -q -v 'cap_net_admin,cap_net_raw=pie' $DUMPCAP
+ CAP_ERR="$?"
+ fi
+
+ # did we implicitly inherit all those caps because we're root in a netns?
+ if [ -u $DUMPCAP -o "$CAP_ERR" = "1" ]; then
+ getpcaps 0 2>&1 | grep -e cap_net_admin | grep -q -e cap_net_raw
CAP_ERR="$?"
fi
+
+ # did we implicitly inherit all those caps because we're root in a netns?
+ if [ -u $DUMPCAP -o "$CAP_ERR" = "1" ]; then
+ getpcaps 0 2>&1 | grep -q -e " =ep" # all perms
+ CAP_ERR="$?"
+ fi
+
if [ -u $DUMPCAP -o "$CAP_ERR" = "0" ]; then
CMD="$DUMPCAP -q"
else
@@ -54,9 +73,28 @@ $NETCAT -l -u -k -p $GSMTAP_PORT >/dev/null 2>$TESTCASE.netcat.stderr &
PID=$!
echo $PID > $PIDFILE_NETCAT
-$CMD -s 1500 -n -i any -w "$TTCN3_PCAP_PATH/$TESTCASE.pcap" >$TTCN3_PCAP_PATH/$TESTCASE.pcap.stdout 2>&1 &
+CMD_OUTFILE=$TTCN3_PCAP_PATH/$TESTCASE.pcap.stdout
+CMD_OUTFILE_ERR=$TTCN3_PCAP_PATH/$TESTCASE.pcap.stderr
+FIFO=/tmp/cmderr
+if ! [ -e $FIFO ]; then
+ mkfifo $FIFO
+else
+ echo "Warning: Named pipe already exists: $FIFO"
+fi
+
+# Log stderr to CMD_OUTFILE and a dedicated error log file
+tee $CMD_OUTFILE < $FIFO > $CMD_OUTFILE_ERR &
+CMD_STR="$CMD -s 1520 -n -i any -w \"$TTCN3_PCAP_PATH/$TESTCASE.pcap\" >$CMD_OUTFILE 2>$FIFO &"
+eval $CMD_STR
+# $CMD -s 1520 -n -i any -w \"$TTCN3_PCAP_PATH/$TESTCASE.pcap\" >$CMD_OUTFILE &
PID=$!
echo $PID > $PIDFILE_PCAP
+if [ -f $CMD_OUTFILE_ERR ] && [ $(wc -l $CMD_OUTFILE_ERR | awk '{print $1}') -ne 0 ]; then
+ echo "Warnings or error messages from command:" >&2
+ echo " $CMD_STR" >&2
+ echo "Message:" >&2
+ echo "$(cat $CMD_OUTFILE_ERR)" | sed 's/^/\t/' >&2
+fi
# Wait until packet dumper creates the pcap file and starts recording.
# We generate some traffic until we see packet dumper catches it.
diff --git a/ttcn3-tcpdump-stop.sh b/ttcn3-tcpdump-stop.sh
index b2a3a3e3..82d3a4fb 100755
--- a/ttcn3-tcpdump-stop.sh
+++ b/ttcn3-tcpdump-stop.sh
@@ -2,36 +2,58 @@
PIDFILE_PCAP=/tmp/pcap.pid
PIDFILE_NETCAT=/tmp/netcat.pid
+FIFO=/tmp/cmderr
TESTCASE=$1
VERDICT="$2"
+SUDOSTR=""
+if ! [ "$(id -u)" = "0" ]; then
+ SUDOSTR="sudo -n"
+ # Otherwise, if sudo /usr/bin/kill, sudo /usr/bin/tcpdump cannot be run without a password prompt,
+ # and this script will hang indefinitely
+fi
+
kill_rm_pidfile() {
-if [ -e $1 ]; then
- PSNAME="$(ps -q "$(cat "$1")" -o comm=)"
- if [ "$PSNAME" != "sudo" ]; then
- kill "$(cat "$1")"
- else
# NOTE: This requires you to be root or something like
# "laforge ALL=NOPASSWD: /usr/sbin/tcpdump, /bin/kill" in your sudoers file
- sudo kill "$(cat "$1")"
+ if [ -e "$1" ]; then
+ if [ -s "$1" ]; then
+ $SUDOSTR kill "$(cat "$1")" 2>&1 | grep -v "No such process"
+ fi
+ rm $1
fi
- rm $1
-fi
}
date
if [ x"$VERDICT" = x"pass" ]; then
- echo -e "\033[1;32m====== $TESTCASE $VERDICT ======\033[0m"
+ printf "\033[1;32m====== $TESTCASE $VERDICT ======\033[0m\n\n"
else
- echo -e "\033[1;31m------ $TESTCASE $VERDICT ------\033[0m"
+ printf "\033[1;31m------ $TESTCASE $VERDICT ------\033[0m\n\n"
fi
-echo
if [ "z$TTCN3_PCAP_PATH" = "z" ]; then
TTCN3_PCAP_PATH=/tmp
fi
+# Order the SUT to print a talloc report
+if [ "z$OSMO_SUT_HOST" != "z" ] && [ "z$OSMO_SUT_PORT" != "z" ]; then
+ if [ -x "$(command -v osmo_interact_vty.py)" ]; then
+ echo "Saving talloc report from $OSMO_SUT_HOST:$OSMO_SUT_PORT to $TESTCASE.talloc"
+ if ! timeout 5 osmo_interact_vty.py \
+ -H $OSMO_SUT_HOST -p $OSMO_SUT_PORT \
+ -c "en; show talloc-context application full" \
+ > "$TTCN3_PCAP_PATH/$TESTCASE.talloc"; then
+ echo
+ echo "ERROR: failed to get talloc report via vty"
+ echo
+ fi
+ else
+ echo "Missing osmo_interact_vty.py from osmo-python-tests!"
+ echo " -> Unable to obtain talloc report from the SUT"
+ fi
+fi
+
# Wait for up to 2 seconds if we keep receiving traffinc from packet dumper,
# otherwise we might lose last packets from test.
i=0
@@ -48,5 +70,6 @@ done
kill_rm_pidfile "$PIDFILE_PCAP"
kill_rm_pidfile "$PIDFILE_NETCAT"
+rm $FIFO
gzip -f "$TTCN3_PCAP_PATH/$TESTCASE.pcap"
diff --git a/upf/CPF_ConnectionHandler.ttcn b/upf/CPF_ConnectionHandler.ttcn
new file mode 100644
index 00000000..b5945d3f
--- /dev/null
+++ b/upf/CPF_ConnectionHandler.ttcn
@@ -0,0 +1,118 @@
+module CPF_ConnectionHandler {
+
+/* CPF Connection Handler of UPF_Tests in TTCN-3
+ * (C) 2022 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
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+
+import from StatsD_Checker all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+
+import from PFCP_Types all;
+import from PFCP_Emulation all;
+
+/* The system under test is a UPF (User Plane Function). This component represents a Control Plane Function, with a
+ * single association via PFCP to the UPF (User Plane Function). */
+type component CPF_ConnHdlr extends StatsD_ConnHdlr {
+ port PFCPEM_PT PFCP;
+ port TELNETasp_PT UPFVTY;
+
+ var PFCP_Emulation_CT vc_PFCP;
+
+ var TestHdlrParams g_pars;
+
+ var boolean g_vty_initialized := false;
+ var integer g_recovery_timestamp;
+ var integer g_next_seid_state;
+ var integer g_next_local_teid_state;
+ var integer g_next_remote_teid_state;
+ var integer g_next_ue_addr_state;
+}
+
+function f_next_seid() runs on CPF_ConnHdlr return OCT8 {
+ g_next_seid_state := g_next_seid_state + 1;
+ return int2oct(g_next_seid_state, 8);
+}
+
+function f_next_remote_teid() runs on CPF_ConnHdlr return OCT4 {
+ g_next_remote_teid_state := g_next_remote_teid_state + 1;
+ return int2oct(g_next_remote_teid_state, 4);
+}
+
+function f_next_ue_addr() runs on CPF_ConnHdlr return charstring {
+ g_next_ue_addr_state := g_next_ue_addr_state + 1;
+ if (g_next_ue_addr_state > 254) {
+ g_next_ue_addr_state := 16;
+ }
+ return "192.168.44." & int2str(g_next_ue_addr_state);
+}
+
+function f_CPF_ConnHdlr_init_vty() runs on CPF_ConnHdlr {
+ if (not g_vty_initialized) {
+ map(self:UPFVTY, system:UPFVTY);
+ f_vty_set_prompts(UPFVTY);
+ f_vty_transceive(UPFVTY, "enable");
+ g_vty_initialized := true;
+ }
+}
+
+private function f_CPF_ConnHdlr_init_pfcp(charstring id) runs on CPF_ConnHdlr {
+ id := id & "-PFCP";
+
+ g_recovery_timestamp := f_rnd_int(4294967295);
+ g_next_seid_state := (1 + f_rnd_int(65534)) * 65536;
+ g_next_local_teid_state := (1 + f_rnd_int(65534)) * 65536;
+ g_next_remote_teid_state := (1 + f_rnd_int(65534)) * 65536;
+ g_next_ue_addr_state := (1 + f_rnd_int(15)) * 16;
+
+ var PFCP_Emulation_Cfg pfcp_cfg := {
+ pfcp_bind_ip := g_pars.local_addr,
+ pfcp_bind_port := g_pars.local_port,
+ pfcp_remote_ip := g_pars.remote_upf_addr,
+ pfcp_remote_port := g_pars.remote_upf_port,
+ role := CPF
+ };
+
+ vc_PFCP := PFCP_Emulation_CT.create(id) alive;
+ connect(self:PFCP, vc_PFCP:CLIENT);
+ vc_PFCP.start(PFCP_Emulation.main(pfcp_cfg));
+}
+
+/* initialize all parameters */
+function f_CPF_ConnHdlr_init(charstring id, TestHdlrParams pars) runs on CPF_ConnHdlr {
+ g_pars := valueof(pars);
+ f_CPF_ConnHdlr_init_pfcp(id);
+ f_CPF_ConnHdlr_init_vty();
+}
+
+type record TestHdlrParams {
+ charstring remote_upf_addr,
+ integer remote_upf_port,
+ charstring local_addr,
+ integer local_port,
+ Node_ID local_node_id
+};
+
+/* Note: Do not use valueof() to get a value of this template, use
+ * f_gen_test_hdlr_pars() instead in order to get a configuration. */
+template (value) TestHdlrParams t_def_TestHdlrPars := {
+ remote_upf_addr := "127.0.0.1",
+ remote_upf_port := 8805,
+ local_addr := "127.0.0.2",
+ local_port := 8805
+}
+
+}
diff --git a/upf/README.md b/upf/README.md
new file mode 100644
index 00000000..09d8199b
--- /dev/null
+++ b/upf/README.md
@@ -0,0 +1,21 @@
+# UPF_Tests.ttcn
+
+* external interfaces
+ * PFCP
+ * VTY
+ * CTRL
+ * StatsD
+
+{% dot upf_tests.svg
+digraph G {
+ graph [label="UPF_Tests", labelloc=t, fontsize=30];
+ rankdir=LR;
+ UPF [label="IUT\nosmo-upf",shape="box"];
+ ATS [label="ATS\nUPF_Tests.ttcn"];
+
+ UPF <- ATS [label="PFCP"];
+ UPF <- ATS [label="CTRL"];
+ UPF <- ATS [label="VTY"];
+ UPF -> ATS [label="StatsD"];
+}
+%}
diff --git a/upf/README.txt b/upf/README.txt
new file mode 100644
index 00000000..9f1eced2
--- /dev/null
+++ b/upf/README.txt
@@ -0,0 +1,4 @@
+Integration Tests for OsmoUPF
+-----------------------------
+
+This test suite tests OsmoUPF, emulating a Control Plane Function.
diff --git a/upf/UPF_Tests.cfg b/upf/UPF_Tests.cfg
new file mode 100644
index 00000000..06ef1d04
--- /dev/null
+++ b/upf/UPF_Tests.cfg
@@ -0,0 +1,19 @@
+[ORDERED_INCLUDE]
+# Common configuration, shared between test suites
+"../Common.cfg"
+# testsuite specific configuration, not expected to change
+"./UPF_Tests.default"
+
+# Local configuration below
+
+[LOGGING]
+
+[TESTPORT_PARAMETERS]
+
+[MODULE_PARAMETERS]
+UPF_Tests.mp_verify_gtp_actions := false;
+
+[MAIN_CONTROLLER]
+
+[EXECUTE]
+UPF_Tests.control
diff --git a/upf/UPF_Tests.default b/upf/UPF_Tests.default
new file mode 100644
index 00000000..2175e9f2
--- /dev/null
+++ b/upf/UPF_Tests.default
@@ -0,0 +1,28 @@
+[LOGGING]
+mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC;
+
+[TESTPORT_PARAMETERS]
+*.UPFVTY.CTRL_MODE := "client"
+*.UPFVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.UPFVTY.CTRL_PORTNUM := "4275"
+*.UPFVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.UPFVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.UPFVTY.CTRL_READMODE := "buffered"
+*.UPFVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.UPFVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.UPFVTY.PROMPT1 := "OsmoUPF> "
+*.STATSVTY.CTRL_MODE := "client"
+*.STATSVTY.CTRL_HOSTNAME := "127.0.0.1"
+*.STATSVTY.CTRL_PORTNUM := "4276"
+*.STATSVTY.CTRL_LOGIN_SKIPPED := "yes"
+*.STATSVTY.CTRL_DETECT_SERVER_DISCONNECTED := "yes"
+*.STATSVTY.CTRL_READMODE := "buffered"
+*.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes"
+*.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes"
+*.STATSVTY.PROMPT1 := "OsmoUPF> "
+*.LLSK.socket_type := "SEQPACKET"
+
+[MODULE_PARAMETERS]
+Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoUPF";
+
+[EXECUTE]
diff --git a/upf/UPF_Tests.ttcn b/upf/UPF_Tests.ttcn
new file mode 100644
index 00000000..cb8c4896
--- /dev/null
+++ b/upf/UPF_Tests.ttcn
@@ -0,0 +1,1176 @@
+module UPF_Tests {
+
+/* Integration Tests for OsmoUPF
+ * (C) 2022 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
+ *
+ * This test suite acts as a PFCP Control Plane Function to test OsmoUPF.
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+import from TCCConversion_Functions all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from CPF_ConnectionHandler all;
+
+import from PFCP_Types all;
+import from PFCP_Emulation all;
+import from PFCP_Templates all;
+
+modulepar {
+ /* IP address at which the UPF can be reached */
+ charstring mp_pfcp_ip_upf := "127.0.0.1";
+ charstring mp_pfcp_ip_local := "127.0.0.2";
+
+ charstring mp_netinst_access_ip_1 := "127.0.1.1";
+ charstring mp_netinst_access_ip_2 := "127.0.1.2";
+ charstring mp_netinst_core_ip_1 := "127.0.2.1";
+ charstring mp_netinst_core_ip_2 := "127.0.2.2";
+
+ /* When testing with gtp mockup, actions will not show. */
+ boolean mp_verify_gtp_actions := false;
+}
+
+type component test_CT extends CTRL_Adapter_CT {
+ port PFCPEM_PT PFCP;
+
+ port TELNETasp_PT UPFVTY;
+
+ /* global test case guard timer (actual timeout value is set in f_init()) */
+ timer T_guard := 15.0;
+}
+
+/* global altstep for global guard timer; */
+altstep as_Tguard() runs on test_CT {
+ [] T_guard.timeout {
+ setverdict(fail, "Timeout of T_guard");
+ mtc.stop;
+ }
+}
+
+private function f_get_name_val(out charstring val, charstring str, charstring name, charstring sep := ":", charstring delim := " ") return boolean {
+ var charstring labl := name & sep;
+ var integer namepos := f_strstr(str, labl);
+ if (namepos < 0) {
+ return false;
+ }
+ var integer valpos := namepos + lengthof(labl);
+ var integer valend := f_strstr(str, delim, valpos);
+ if (valend < 0) {
+ valend := lengthof(str);
+ }
+ val := substr(str, valpos, valend - valpos);
+ return true;
+}
+
+private function f_get_name_val_oct8(out OCT8 val, charstring str, charstring name) return boolean {
+ var charstring token;
+ if (not f_get_name_val(token, str, name, ":0x")) {
+ return false;
+ }
+ if (lengthof(token) > 16) {
+ log("token too long: ", name, " in ", str);
+ return false;
+ }
+ var charstring padded := substr("0000000000000000", 0, 16 - lengthof(token)) & token;
+ val := str2oct(padded);
+ return true;
+}
+
+private function f_get_name_val_oct4(out OCT4 val, charstring str, charstring name) return boolean {
+ var charstring token;
+ if (not f_get_name_val(token, str, name, ":0x")) {
+ return false;
+ }
+ if (lengthof(token) > 8) {
+ log("token too long: ", name, " in ", str);
+ return false;
+ }
+ var charstring padded := substr("00000000", 0, 8 - lengthof(token)) & token;
+ val := str2oct(padded);
+ return true;
+}
+
+private function f_get_name_val_int(out integer val, charstring str, charstring name) return boolean {
+ var charstring token;
+ if (not f_get_name_val(token, str, name)) {
+ return false;
+ }
+ val := str2int(token);
+ return true;
+}
+
+private function f_get_name_val_2int(out integer val1, out integer val2, charstring str, charstring name, charstring delim := ",") return boolean {
+ var charstring token;
+ if (not f_get_name_val(token, str, name)) {
+ return false;
+ }
+ var Misc_Helpers.ro_charstring nrl := f_str_split(token, delim);
+ if (lengthof(nrl) != 2) {
+ return false;
+ }
+ val1 := str2int(nrl[0]);
+ val2 := str2int(nrl[1]);
+ return true;
+}
+
+/* A PFCP session as seen by the system under test, osmo-upf. up_seid is what osmo-upf sees as its local SEID
+ * ("SEID-l"). cp_seid is this tester's side's SEID, which osmo-upf sees as the remote SEID. */
+type record PFCP_session {
+ OCT8 up_seid,
+ OCT8 cp_seid,
+ GTP_Action gtp
+}
+
+/* _r and _l means 'remote' and 'local', from the perspective of the osmo-upf process. */
+type record GTP_Action_tunend {
+ /* the PDR Id detecting packets from this side */
+ integer pdr_id,
+ /* IP packets arriving from this side are arriving on ip_l */
+ charstring ip_l,
+
+ /* the FAR Id forwarding packets to this side */
+ integer far_id
+}
+
+/* _r and _l means 'remote' and 'local', from the perspective of the osmo-upf process. */
+type record GTP_Action_tun {
+ /* the PDR Id detecting packets from this side */
+ integer pdr_id,
+ /* GTP arriving from this side is arriving on gtp_ip_l with teid_l */
+ charstring gtp_ip_l,
+ OCT4 teid_l,
+
+ /* the FAR Id forwarding packets to this side */
+ integer far_id,
+ /* GTP going out to this side should be sent to gtp_ip_r with teid_r */
+ charstring gtp_ip_r,
+ OCT4 teid_r
+}
+
+type union GTP_Action_core {
+ /* For kind = "tunend", the local IP that the UE has on 'the internet' */
+ GTP_Action_tunend tunend,
+ /* For kind = "tunmap", the second GTP tunnel */
+ GTP_Action_tun tunmap
+}
+
+/* State of what GTP functionality osmo-upf should put in place, after a PFCP request was ACKed by it.
+ * _r and _l means 'remote' and 'local', from the perspective of the osmo-upf process.
+ *
+ * tunend:
+ * Access UPF Core
+ * GTP-r:127.0.0.2,0x1 <-FAR-1-- | 192.168.0.1 <-PDR-1--
+ * --PDR-2-> GTP-l:127.0.0.1,0x2 | --FAR-2-> (IP destination is in each GTP payload)
+ *
+ * tunmap:
+ * Access UPF Core
+ * GTP-r:127.0.0.2,0x1 <-FAR-1-- | 127.0.0.1,0x1 <-PDR-1--
+ * --PDR-2-> GTP-l:127.0.0.1,0x2 | --FAR-2-> GTP-r:127.0.0.3,0x2
+ */
+type record GTP_Action {
+ /* kind = ("tunend"|"tunmap") */
+ charstring kind,
+ /* The access side GTP tunnel. (The 'Access' side is always GTP.) */
+ GTP_Action_tun access,
+ /* The core side GTP tunnel (tunmap) or local IP (tunend) */
+ GTP_Action_core core,
+ /* Reference to the PFCP Session that created this GTP action: PFCP session's F-SEID as seen from osmo-upf */
+ charstring pfcp_peer,
+ OCT8 seid_l
+};
+
+type record of GTP_Action GTP_Action_List;
+
+private function f_parse_gtp_action(out GTP_Action ret, charstring str) return boolean {
+ /* Parse a string like
+ * "GTP:tunend GTP-access-r:127.0.0.2 TEID-access-r:0x94f0001 TEID-access-l:0x1 IP-core-l:192.168.44.241 PFCP-peer:127.0.0.2 SEID-l:0x1 PDR:1,2"
+ */
+ var GTP_Action a;
+ if (not f_get_name_val(a.kind, str, "GTP")) {
+ return false;
+ }
+ if (not f_get_name_val(a.access.gtp_ip_r, str, "GTP-access-r")) {
+ return false;
+ }
+ if (not f_get_name_val_oct4(a.access.teid_r, str, "TEID-access-r")) {
+ return false;
+ }
+ if (not f_get_name_val(a.access.gtp_ip_l, str, "GTP-access-l")) {
+ return false;
+ }
+ if (not f_get_name_val_oct4(a.access.teid_l, str, "TEID-access-l")) {
+ return false;
+ }
+ if (not f_get_name_val_int(a.access.pdr_id, str, "PDR-access")) {
+ return false;
+ }
+ if (not f_get_name_val(a.pfcp_peer, str, "PFCP-peer")) {
+ return false;
+ }
+ if (not f_get_name_val_oct8(a.seid_l, str, "SEID-l")) {
+ return false;
+ }
+ if (a.kind == "tunend") {
+ if (not f_get_name_val_int(a.core.tunend.pdr_id, str, "PDR-core")) {
+ return false;
+ }
+ if (not f_get_name_val(a.core.tunend.ip_l, str, "IP-core-l")) {
+ return false;
+ }
+ /* in these tests, the PDR Id and its FAR Id are always the same: PDR for incoming on Access matches its
+ * FAR that forwards to Core. */
+ a.core.tunend.far_id := a.access.pdr_id;
+ a.access.far_id := a.core.tunend.pdr_id;
+ } else if (a.kind == "tunmap") {
+ if (not f_get_name_val(a.core.tunmap.gtp_ip_r, str, "GTP-core-r")) {
+ return false;
+ }
+ if (not f_get_name_val_oct4(a.core.tunmap.teid_r, str, "TEID-core-r")) {
+ return false;
+ }
+ if (not f_get_name_val(a.core.tunmap.gtp_ip_l, str, "GTP-core-l")) {
+ return false;
+ }
+ if (not f_get_name_val_oct4(a.core.tunmap.teid_l, str, "TEID-core-l")) {
+ return false;
+ }
+ if (not f_get_name_val_int(a.core.tunmap.pdr_id, str, "PDR-core")) {
+ return false;
+ }
+ /* in these tests, the PDR Id and its FAR Id are always the same: PDR for incoming on Access matches its
+ * FAR that forwards to Core. */
+ a.core.tunmap.far_id := a.access.pdr_id;
+ a.access.far_id := a.core.tunmap.pdr_id;
+ }
+
+ ret := a;
+ return true;
+}
+
+private function f_vty_get_gtp_actions(TELNETasp_PT vty_pt) return GTP_Action_List {
+ var charstring gtp_str := f_vty_transceive_ret(vty_pt, "show gtp");
+ var Misc_Helpers.ro_charstring lines := f_str_split(gtp_str, "\n");
+ var GTP_Action_List gtps := {};
+ for (var integer i := 0; i < lengthof(lines); i := i + 1) {
+ var charstring line := lines[i];
+ var GTP_Action a;
+ if (not f_parse_gtp_action(a, line)) {
+ continue;
+ }
+ gtps := gtps & { a };
+ }
+ log("GTP-actions: ", gtps);
+ return gtps;
+}
+
+private function f_find_gtp_action(GTP_Action_List actions, template GTP_Action find) return boolean {
+ for (var integer i := 0; i < lengthof(actions); i := i + 1) {
+ if (match(actions[i], find)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+private function f_expect_gtp_action(GTP_Action_List actions, template GTP_Action expect) {
+ if (f_find_gtp_action(actions, expect)) {
+ log("VTY confirms: GTP action active: ", expect);
+ setverdict(pass);
+ return;
+ }
+ log("Expected to find ", expect, " in ", actions);
+ setverdict(fail, "on VTY, a GTP action failed to show as active");
+ mtc.stop;
+}
+
+private function f_expect_no_gtp_action(GTP_Action_List actions, template GTP_Action expect) {
+ if (f_find_gtp_action(actions, expect)) {
+ log("Expected to *not* find ", expect, " in ", actions);
+ setverdict(fail, "a GTP action failed to show as inactive");
+ mtc.stop;
+ }
+ log("VTY confirms: GTP action inactive: ", expect);
+ setverdict(pass);
+ return;
+}
+
+private function f_vty_expect_gtp_action(TELNETasp_PT vty_pt, template GTP_Action expect) {
+ if (not mp_verify_gtp_actions) {
+ /* In GTP mockup mode, GTP actions don't show on VTY. Cannot verify. */
+ setverdict(pass);
+ return;
+ }
+ var GTP_Action_List actions := f_vty_get_gtp_actions(vty_pt);
+ f_expect_gtp_action(actions, expect);
+}
+
+private function f_vty_expect_no_gtp_actions(TELNETasp_PT vty_pt) {
+ var GTP_Action_List actions := f_vty_get_gtp_actions(vty_pt);
+ if (lengthof(actions) > 0) {
+ setverdict(fail, "VTY says that there are still active GTP actions");
+ mtc.stop;
+ }
+ setverdict(pass);
+}
+
+type record PFCP_Session_Status {
+ charstring peer,
+ OCT8 seid_r,
+ OCT8 seid_l,
+ charstring state,
+ integer pdr_active_count,
+ integer pdr_count,
+ integer far_active_count,
+ integer far_count,
+ integer gtp_active_count
+};
+
+template PFCP_Session_Status PFCP_session_active := {
+ peer := ?,
+ seid_r := ?,
+ seid_l := ?,
+ state := "ESTABLISHED",
+ pdr_active_count := (1..99999),
+ pdr_count := (1..99999),
+ far_active_count := (1..99999),
+ far_count := (1..99999),
+ gtp_active_count := (1..99999)
+};
+
+template PFCP_Session_Status PFCP_session_inactive := {
+ peer := ?,
+ seid_r := ?,
+ seid_l := ?,
+ state := "ESTABLISHED",
+ pdr_active_count := 0,
+ pdr_count := (1..99999),
+ far_active_count := 0,
+ far_count := (1..99999),
+ gtp_active_count := 0
+};
+
+type record of PFCP_Session_Status PFCP_Session_Status_List;
+
+private function f_parse_session_status(out PFCP_Session_Status ret, charstring str) return boolean {
+ var PFCP_Session_Status st;
+ if (not f_get_name_val(st.peer, str, "peer")) {
+ return false;
+ }
+ if (not f_get_name_val_oct8(st.seid_l, str, "SEID-l")) {
+ return false;
+ }
+ f_get_name_val_oct8(st.seid_r, str, "SEID-r");
+ f_get_name_val(st.state, str, "state");
+
+ /* parse 'PDR-active:1/2' */
+ if (not f_get_name_val_2int(st.pdr_active_count, st.pdr_count, str, "PDR-active", "/")) {
+ return false;
+ }
+ /* parse 'FAR-active:1/2' */
+ if (not f_get_name_val_2int(st.far_active_count, st.far_count, str, "FAR-active", "/")) {
+ return false;
+ }
+
+ f_get_name_val_int(st.gtp_active_count, str, "GTP-active");
+ ret := st;
+ return true;
+}
+
+private function f_vty_get_sessions(TELNETasp_PT vty_pt) return PFCP_Session_Status_List {
+ var charstring sessions_str := f_vty_transceive_ret(vty_pt, "show session");
+ var Misc_Helpers.ro_charstring lines := f_str_split(sessions_str, "\n");
+ var PFCP_Session_Status_List sessions := {};
+ for (var integer i := 0; i < lengthof(lines); i := i + 1) {
+ var charstring line := lines[i];
+ var PFCP_Session_Status st;
+ if (not f_parse_session_status(st, line)) {
+ continue;
+ }
+ sessions := sessions & { st };
+ }
+ log("Sessions: ", sessions);
+ return sessions;
+}
+
+private function f_vty_get_session_status(TELNETasp_PT vty_pt, PFCP_session s, out PFCP_Session_Status ret) return boolean {
+ var PFCP_Session_Status_List sessions := f_vty_get_sessions(vty_pt);
+ return f_get_session_status(sessions, s, ret);
+}
+
+private function f_get_session_status(PFCP_Session_Status_List sessions, PFCP_session s, out PFCP_Session_Status ret)
+return boolean {
+ var PFCP_Session_Status_List matches := {};
+ for (var integer i := 0; i < lengthof(sessions); i := i + 1) {
+ var PFCP_Session_Status st := sessions[i];
+ if (st.seid_l != s.up_seid) {
+ continue;
+ }
+ if (st.seid_r != s.cp_seid) {
+ continue;
+ }
+ matches := matches & { st };
+ }
+ if (lengthof(matches) < 1) {
+ log("no session with SEID-l = ", s.up_seid);
+ return false;
+ }
+ if (lengthof(matches) > 1) {
+ log("multiple sessions have ", s, ": ", matches);
+ return false;
+ }
+ ret := matches[0];
+ return true;
+}
+
+private function f_vty_expect_session_status(TELNETasp_PT vty_pt, PFCP_session s, template PFCP_Session_Status expect_st) {
+ var PFCP_Session_Status st;
+ if (not f_vty_get_session_status(vty_pt, s, st)) {
+ log("Session ", s, " not found in VTY session list");
+ setverdict(fail, "Session not found in VTY list");
+ mtc.stop;
+ }
+ log("Session ", s, " status: ", st);
+ if (not match(st, expect_st)) {
+ log("ERROR: Session ", st, " does not match ", expect_st);
+ setverdict(fail, "VTY shows unexpected state of PFCP session");
+ mtc.stop;
+ }
+
+ setverdict(pass);
+}
+
+private function f_vty_expect_session_active(TELNETasp_PT vty_pt, PFCP_session s)
+{
+ f_vty_expect_session_status(vty_pt, s, PFCP_session_active);
+ f_vty_expect_gtp_action(vty_pt, s.gtp);
+ setverdict(pass);
+}
+
+private function f_vty_expect_no_active_sessions(TELNETasp_PT vty_pt) {
+ var PFCP_Session_Status_List stl := f_vty_get_sessions(vty_pt);
+ var integer active := 0;
+ for (var integer i := 0; i < lengthof(stl); i := i + 1) {
+ if (match(stl[i], PFCP_session_active)) {
+ log("Active session: ", stl[i]);
+ active := active + 1;
+ }
+ }
+ if (active > 0) {
+ setverdict(fail, "There are still active sessions");
+ mtc.stop;
+ }
+ setverdict(pass);
+}
+
+private function f_vty_netinst_cfg(TELNETasp_PT vty_pt, Misc_Helpers.ro_charstring netinst_cmds)
+{
+ f_vty_enter_config(vty_pt);
+ f_vty_transceive(vty_pt, "netinst");
+ for (var integer i := 0; i < lengthof(netinst_cmds); i := i + 1) {
+ f_vty_transceive(vty_pt, netinst_cmds[i]);
+ }
+ f_vty_transceive_ret(vty_pt, "end");
+}
+
+function f_init_vty(charstring id := "foo") runs on test_CT {
+ if (UPFVTY.checkstate("Mapped")) {
+ /* skip initialization if already executed once */
+ return;
+ }
+ map(self:UPFVTY, system:UPFVTY);
+ f_vty_set_prompts(UPFVTY);
+ f_vty_transceive(UPFVTY, "enable");
+}
+
+/* global initialization function */
+function f_init(float guard_timeout := 30.0) runs on test_CT {
+ var integer bssap_idx;
+
+ T_guard.start(guard_timeout);
+ activate(as_Tguard());
+
+ f_init_vty("VirtCPF");
+
+ /* Clear out and set up default network instance config */
+ f_vty_netinst_cfg(UPFVTY,
+ { "clear",
+ "add access " & mp_netinst_access_ip_1,
+ "add access2 " & mp_netinst_access_ip_2,
+ "add core " & mp_netinst_core_ip_1,
+ "add core2 " & mp_netinst_core_ip_2
+ });
+}
+
+friend function f_shutdown_helper() runs on test_CT {
+ all component.stop;
+ setverdict(pass);
+ mtc.stop;
+}
+
+private function f_gen_test_hdlr_pars() runs on test_CT return TestHdlrParams {
+ var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+ pars.remote_upf_addr := mp_pfcp_ip_upf;
+ pars.local_addr := mp_pfcp_ip_local;
+ pars.local_node_id := valueof(ts_PFCP_Node_ID_ipv4(f_inet_addr(mp_pfcp_ip_local)));
+ return pars;
+}
+
+type function void_fn(charstring id) runs on CPF_ConnHdlr;
+
+function f_start_handler_create(TestHdlrParams pars)
+runs on test_CT return CPF_ConnHdlr {
+ var charstring id := testcasename();
+ var CPF_ConnHdlr vc_conn;
+ vc_conn := CPF_ConnHdlr.create(id);
+ return vc_conn;
+}
+
+function f_start_handler_run(CPF_ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars)
+runs on test_CT return CPF_ConnHdlr {
+ var charstring id := testcasename();
+ /* Emit a marker to appear in the SUT's own logging output */
+ f_logp(UPFVTY, id & "() start");
+ vc_conn.start(f_handler_init(fn, id, pars));
+ return vc_conn;
+}
+
+function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars_tmpl := omit)
+runs on test_CT return CPF_ConnHdlr {
+ var TestHdlrParams pars;
+ if (isvalue(pars_tmpl)) {
+ pars := valueof(pars_tmpl);
+ } else {
+ pars := valueof(f_gen_test_hdlr_pars());
+ }
+ return f_start_handler_run(f_start_handler_create(pars), fn, pars);
+}
+
+/* first function inside ConnHdlr component; sets g_pars + starts function */
+private function f_handler_init(void_fn fn, charstring id, TestHdlrParams pars)
+runs on CPF_ConnHdlr {
+ f_CPF_ConnHdlr_init(id, pars);
+ fn.apply(id);
+}
+
+/* Run a PFCP Association procedure */
+private function f_assoc_setup() runs on CPF_ConnHdlr {
+ PFCP.send(ts_PFCP_Assoc_Setup_Req(g_pars.local_node_id, g_recovery_timestamp));
+ PFCP.receive(tr_PFCP_Assoc_Setup_Resp(cause := tr_PFCP_Cause(REQUEST_ACCEPTED)));
+}
+
+/* Release a PFCP Association */
+private function f_assoc_release() runs on CPF_ConnHdlr {
+ PFCP.send(ts_PFCP_Assoc_Release_Req(g_pars.local_node_id));
+ PFCP.receive(tr_PFCP_Assoc_Release_Resp(cause := tr_PFCP_Cause(REQUEST_ACCEPTED)));
+}
+
+/* Collection of what a test intends to send to osmo-upf */
+type record PFCP_Ruleset {
+ Create_PDR_list pdr,
+ Create_FAR_list far
+};
+
+/* Add to r a rule set that does GTP decapsulation (half of encapsulation/decapsulation):
+ * Receive GTP on src_iface = ACCESS by a local F-TEID to be chosen by osmo-upf.
+ * Dispatch GTP payload as plain IP on dest_iface = CORE. */
+private function f_ruleset_add_GTP_decaps(inout PFCP_Ruleset r,
+ integer pdr_id,
+ charstring src_netinst,
+ integer far_id) {
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ ACCESS,
+ local_F_TEID := ts_PFCP_F_TEID_choose_v4(),
+ network_instance := ts_PFCP_Network_Instance(src_netinst)),
+ ts_PFCP_Outer_Header_Removal(GTP_U_UDP_IPV4),
+ far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Forwarding_Parameters(CORE))
+ )
+ )
+ };
+}
+
+/* Add to r a rule set that does GTP encapsulation (half of encapsulation/decapsulation) */
+private function f_ruleset_add_GTP_encaps(inout PFCP_Ruleset r,
+ integer pdr_id,
+ charstring ue_addr_v4 := "192.168.23.42",
+ integer far_id,
+ OCT4 remote_teid,
+ OCT4 gtp_dest_addr_v4) {
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ CORE,
+ ue_addr_v4 := ts_PFCP_UE_IP_Address_v4(f_inet_addr(ue_addr_v4), is_destination := true)
+ ),
+ far_id := far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Forwarding_Parameters(
+ ACCESS,
+ ts_PFCP_Outer_Header_Creation_GTP_ipv4(
+ remote_teid,
+ gtp_dest_addr_v4)
+ ))
+ )
+ )
+ };
+}
+
+/* Add to r a rule set that forwards GTP from one tunnel to another, i.e. one direction of a tunmap */
+private function f_ruleset_add_GTP_forw(inout PFCP_Ruleset r,
+ integer pdr_id,
+ e_PFCP_Src_Iface src_iface,
+ charstring src_netinst,
+ integer far_id,
+ e_PFCP_Dest_Iface dest_iface,
+ F_TEID dest_remote_f_teid) {
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ src_iface,
+ local_F_TEID := ts_PFCP_F_TEID_choose_v4(),
+ network_instance := ts_PFCP_Network_Instance(src_netinst)),
+ ts_PFCP_Outer_Header_Removal(GTP_U_UDP_IPV4),
+ far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Forwarding_Parameters(dest_iface,
+ ts_PFCP_Outer_Header_Creation_GTP_ipv4(dest_remote_f_teid.teid,
+ dest_remote_f_teid.ipv4_address)))
+ )
+ )
+ };
+}
+
+/* Add to r a DROP rule from src_iface to dest_iface */
+private function f_ruleset_add_GTP_drop(inout PFCP_Ruleset r,
+ integer pdr_id,
+ e_PFCP_Src_Iface src_iface,
+ charstring src_netinst,
+ integer far_id,
+ e_PFCP_Dest_Iface dest_iface) {
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ src_iface,
+ local_F_TEID := ts_PFCP_F_TEID_choose_v4(),
+ network_instance := ts_PFCP_Network_Instance(src_netinst)),
+ ts_PFCP_Outer_Header_Removal(GTP_U_UDP_IPV4),
+ far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_DROP,
+ fp := omit
+ )
+ )
+ };
+}
+
+private function f_tunmap_upd_far_to_core(GTP_Action gtp) return Update_FAR
+{
+ return valueof(
+ ts_PFCP_Update_FAR(
+ gtp.core.tunmap.far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Update_Forwarding_Parameters(
+ CORE,
+ ts_PFCP_Outer_Header_Creation_GTP_ipv4(gtp.core.tunmap.teid_r,
+ f_inet_addr(gtp.core.tunmap.gtp_ip_r))
+ )
+ )
+ )
+ );
+}
+
+/* Return two PDR+FAR rulesets that involve a src=CP-Function. Such rulesets are emitted by certain third party CPF, and
+ * osmo-upf should ACK the creation but ignore the rules (no-op). This function models rulesets seen in the field, so we
+ * can confirm that osmo-upf ACKs and ignores. */
+private function f_ruleset_noop() return PFCP_Ruleset
+{
+ var PFCP_Ruleset r := { {}, {} };
+ var integer pdr_id := lengthof(r.pdr) + 1;
+ var integer far_id := lengthof(r.far) + 1;
+
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ CP_FUNCTION,
+ local_F_TEID := ts_PFCP_F_TEID_choose_v4('17'O)),
+ ts_PFCP_Outer_Header_Removal(GTP_U_UDP_IPV4),
+ far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Forwarding_Parameters(ACCESS))
+ )
+ )
+ };
+
+ /* And another one (sic) */
+ pdr_id := lengthof(r.pdr) + 1;
+ far_id := lengthof(r.far) + 1;
+
+ r.pdr := r.pdr & {
+ valueof(
+ ts_PFCP_Create_PDR(
+ pdr_id,
+ ts_PFCP_PDI(
+ CP_FUNCTION,
+ local_F_TEID := ts_PFCP_F_TEID_choose_v4('2a'O)),
+ far_id := far_id
+ )
+ )
+ };
+ r.far := r.far & {
+ valueof(
+ ts_PFCP_Create_FAR(
+ far_id,
+ ts_PFCP_Apply_Action_FORW(),
+ valueof(ts_PFCP_Forwarding_Parameters(ACCESS))
+ )
+ )
+ };
+ return r;
+}
+
+/* Return a rule set that does GTP encapsulation and decapsulation, in both directions. */
+private function f_ruleset_tunend(GTP_Action gtp, charstring netinst_access := "access") return PFCP_Ruleset
+{
+ var PFCP_Ruleset rules := { {}, {} };
+ f_ruleset_add_GTP_decaps(rules,
+ pdr_id := gtp.access.pdr_id,
+ src_netinst := netinst_access,
+ far_id := gtp.core.tunend.far_id);
+ f_ruleset_add_GTP_encaps(rules,
+ gtp.core.tunend.pdr_id,
+ gtp.core.tunend.ip_l,
+ gtp.access.far_id,
+ gtp.access.teid_r,
+ f_inet_addr(gtp.access.gtp_ip_r));
+ return rules;
+}
+
+/* Return a rule set that does GTP tunnel forwarding in both directions.
+ * If core_gtp_known == true, place full FORW rules in both directions.
+ * If core_gtp_known == false, keep the Core side as DROP: this allows testing the usual/realistic case, where upon
+ * Session Establishment, the core side PGW has not yet provided the destination GTP F-TEID, which will follow later in
+ * a Session Modification. (This test suite has already configured which GTP F-TEID will be used on the core side, but
+ * we're omitting it from Session Establishment, until it is time to use it in f_session_mod()). */
+private function f_ruleset_tunmap(GTP_Action gtp, boolean core_gtp_known := true,
+ charstring netinst_access := "access",
+ charstring netinst_core := "core") return PFCP_Ruleset
+{
+ var PFCP_Ruleset rules := { {}, {} };
+ /* Access to Core */
+ if (core_gtp_known) {
+ f_ruleset_add_GTP_forw(rules,
+ pdr_id := gtp.access.pdr_id,
+ src_iface := ACCESS,
+ src_netinst := netinst_access,
+ far_id := gtp.core.tunmap.far_id,
+ dest_iface := CORE,
+ dest_remote_f_teid := valueof(ts_PFCP_F_TEID_ipv4(gtp.core.tunmap.teid_r,
+ f_inet_addr(gtp.core.tunmap.gtp_ip_r))));
+ } else {
+ /* The Core remote GTP will follow in a Session Modification, for now set Core->Access to DROP */
+ f_ruleset_add_GTP_drop(rules,
+ pdr_id := gtp.access.pdr_id,
+ src_iface := ACCESS,
+ src_netinst := netinst_access,
+ far_id := gtp.core.tunmap.far_id,
+ dest_iface := CORE);
+ }
+ /* Core to Access */
+ f_ruleset_add_GTP_forw(rules,
+ pdr_id := gtp.core.tunmap.pdr_id,
+ src_iface := CORE,
+ src_netinst := netinst_core,
+ far_id := gtp.access.far_id,
+ dest_iface := ACCESS,
+ dest_remote_f_teid := valueof(ts_PFCP_F_TEID_ipv4(gtp.access.teid_r,
+ f_inet_addr(gtp.access.gtp_ip_r))));
+ return rules;
+}
+
+/* From a PFCP Session Establishment Response, retrieve the F_TEID returned in the Created PDR IE for the given PDR Id
+ */
+private function f_get_created_local_f_teid(PDU_PFCP sess_est_resp, integer pdr_id) return F_TEID
+{
+ for (var integer i := 0;
+ i < lengthof(sess_est_resp.message_body.pfcp_session_establishment_response.created_PDR_list);
+ i := i + 1) {
+ var Created_PDR cpdr := sess_est_resp.message_body.pfcp_session_establishment_response.created_PDR_list[i];
+ if (oct2int(cpdr.grouped_ie.pdr_id.rule_id) != pdr_id) {
+ continue;
+ }
+ log("osmo-upf has chosen local F-TEID: PDR-" & int2str(pdr_id) & " = ", cpdr.grouped_ie.local_F_TEID);
+ return cpdr.grouped_ie.local_F_TEID;
+ }
+ setverdict(fail, "PDR Id " & int2str(pdr_id) & " not found in PFCP message");
+ mtc.stop;
+}
+
+/* Run a PFCP Session Establishment procedure */
+private function f_session_est(inout PFCP_session s, PFCP_Ruleset rules) runs on CPF_ConnHdlr
+{
+ log("f_session_est: rules = ", rules);
+ PFCP.send(ts_PFCP_Session_Est_Req(ts_PFCP_Node_ID_ipv4(f_inet_addr(g_pars.local_addr)),
+ ts_PFCP_F_SEID_ipv4(f_inet_addr(g_pars.local_addr), s.cp_seid),
+ rules.pdr, rules.far));
+
+ var PDU_PFCP pfcp;
+ PFCP.receive(tr_PFCP_Session_Est_Resp(s.cp_seid)) -> value pfcp;
+ s.up_seid := pfcp.message_body.pfcp_session_establishment_response.UP_F_SEID.seid;
+ s.gtp.seid_l := s.up_seid;
+
+ var F_TEID access_local_f_teid := f_get_created_local_f_teid(pfcp, s.gtp.access.pdr_id);
+ s.gtp.access.gtp_ip_l := f_inet_ntoa(access_local_f_teid.ipv4_address);
+ s.gtp.access.teid_l := access_local_f_teid.teid;
+
+ if (ischosen(s.gtp.core.tunmap)) {
+ var F_TEID core_local_f_teid := f_get_created_local_f_teid(pfcp, s.gtp.core.tunmap.pdr_id);
+ s.gtp.core.tunmap.gtp_ip_l := f_inet_ntoa(core_local_f_teid.ipv4_address);
+ s.gtp.core.tunmap.teid_l := core_local_f_teid.teid;
+ }
+ log("established PFCP session: ", s);
+}
+
+/* Run a PFCP Session Modification procedure */
+private function f_session_mod(inout PFCP_session s) runs on CPF_ConnHdlr
+{
+ PFCP.send(ts_PFCP_Session_Mod_Req(s.up_seid, f_tunmap_upd_far_to_core(s.gtp)));
+ PFCP.receive(tr_PFCP_Session_Mod_Resp(s.cp_seid));
+ log("modified PFCP session: ", s);
+}
+
+private function f_create_PFCP_session_tunend() runs on CPF_ConnHdlr return PFCP_session
+{
+ var PFCP_session s := {
+ up_seid := -,
+ cp_seid := f_next_seid(),
+ gtp := {
+ kind := "tunend",
+ access := {
+ pdr_id := 1,
+ /* gtp_ip_l and teid_l will be returned by Session Establishment Response, Created PDR */
+ gtp_ip_l := "",
+ teid_l := '00000000'O,
+ far_id := 2,
+ gtp_ip_r := "127.0.0.2",
+ teid_r := f_next_remote_teid()
+ },
+ core := {
+ tunend := {
+ pdr_id := 2,
+ ip_l := f_next_ue_addr(),
+ far_id := 1
+ }
+ },
+ pfcp_peer := g_pars.local_addr,
+ seid_l := '0000000000000000'O
+ /* seid_l will be returned by Session Establishment Response */
+ }
+ };
+ return s;
+}
+
+private function f_create_PFCP_session_tunmap() runs on CPF_ConnHdlr return PFCP_session
+{
+ var PFCP_session s := {
+ up_seid := -,
+ cp_seid := f_next_seid(),
+ gtp := {
+ kind := "tunmap",
+ access := {
+ pdr_id := 1,
+ /* gtp_ip_l and teid_l will be returned by Session Establishment Response, Created PDR */
+ gtp_ip_l := "",
+ teid_l := '00000000'O,
+ far_id := 2,
+ gtp_ip_r := "127.0.0.2",
+ teid_r := f_next_remote_teid()
+ },
+ core := {
+ tunmap := {
+ pdr_id := 2,
+ /* gtp_ip_l and teid_l will be returned by Session Establishment Response, Created PDR */
+ gtp_ip_l := "",
+ teid_l := '00000000'O,
+ far_id := 1,
+ gtp_ip_r := "127.0.0.3",
+ teid_r := f_next_remote_teid()
+ }
+ },
+ pfcp_peer := g_pars.local_addr,
+ seid_l := '0000000000000000'O
+ /* seid_l will be returned by Session Establishment Response */
+ }
+ };
+ return s;
+}
+
+/* Do a PFCP Session Establishment with default values (see f_create_PFCP_session_tunend()) */
+private function f_session_est_tunend() runs on CPF_ConnHdlr return PFCP_session
+{
+ var PFCP_session s := f_create_PFCP_session_tunend();
+ f_session_est(s, f_ruleset_tunend(s.gtp));
+ return s;
+}
+
+private function f_session_del(PFCP_session s) runs on CPF_ConnHdlr {
+ PFCP.send(ts_PFCP_Session_Del_Req(s.up_seid));
+ PFCP.receive(tr_PFCP_Session_Del_Resp(s.cp_seid));
+}
+
+private function f_tc_assoc(charstring id) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ f_assoc_release();
+ setverdict(pass);
+}
+
+/* Verify that the CPF can send a Node-ID of the IPv4 type */
+testcase TC_assoc_node_id_v4() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 5.0);
+ vc_conn := f_start_handler(refers(f_tc_assoc));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify that the CPF can send a Node-ID of the FQDN type */
+testcase TC_assoc_node_id_fqdn() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+ var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+ pars.local_node_id := valueof(ts_PFCP_Node_ID_fqdn("\7example\3com"));
+
+ f_init(guard_timeout := 5.0);
+ vc_conn := f_start_handler(refers(f_tc_assoc), pars);
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify PFCP Session Establishment and Deletion */
+private function f_tc_session_est_tunend(charstring id) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ var PFCP_session s := f_session_est_tunend();
+ f_sleep(1.0);
+ f_vty_expect_session_active(UPFVTY, s);
+ f_session_del(s);
+ f_vty_expect_no_active_sessions(UPFVTY);
+ f_vty_expect_no_gtp_actions(UPFVTY);
+ f_assoc_release();
+ setverdict(pass);
+}
+testcase TC_session_est_tunend() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+ vc_conn := f_start_handler(refers(f_tc_session_est_tunend));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify that releasing a PFCP Association also releases all its sessions and GTP actions. */
+private function f_tc_session_term_by_assoc_rel(charstring id) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ var PFCP_session s := f_session_est_tunend();
+ f_sleep(1.0);
+ f_vty_expect_session_active(UPFVTY, s);
+ f_assoc_release();
+ f_vty_expect_no_active_sessions(UPFVTY);
+ f_vty_expect_no_gtp_actions(UPFVTY);
+ setverdict(pass);
+}
+testcase TC_session_term_by_assoc_rel() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+ vc_conn := f_start_handler(refers(f_tc_session_term_by_assoc_rel));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify that PFCP Sessions with a src-interface other than ACCESS or CORE are ACKed by osmo-upf but have no effect. */
+private function f_tc_session_est_noop(charstring id) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ var PFCP_session s := f_create_PFCP_session_tunend();
+ f_session_est(s, f_ruleset_noop());
+
+ f_sleep(1.0);
+ f_vty_expect_session_status(UPFVTY, s, PFCP_session_inactive);
+
+ f_session_del(s);
+ f_vty_expect_no_active_sessions(UPFVTY);
+ f_vty_expect_no_gtp_actions(UPFVTY);
+ f_assoc_release();
+ setverdict(pass);
+}
+testcase TC_session_est_noop() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+ vc_conn := f_start_handler(refers(f_tc_session_est_noop));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Verify that the Network Instance IE in Create PDR chooses the right local address for a tunmap session */
+private function f_tc_session_est_tunmap(charstring id) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ var PFCP_session s := f_create_PFCP_session_tunmap();
+ f_session_est(s, f_ruleset_tunmap(s.gtp));
+ f_sleep(1.0);
+ f_vty_expect_session_active(UPFVTY, s);
+ f_session_del(s);
+ f_vty_expect_no_active_sessions(UPFVTY);
+ f_vty_expect_no_gtp_actions(UPFVTY);
+ f_assoc_release();
+ setverdict(pass);
+}
+testcase TC_session_est_tunmap() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+
+ vc_conn := f_start_handler(refers(f_tc_session_est_tunmap));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+/* Set up a tunmap session with a partial Session Establishment, followed by a Session Modification to complete it. */
+private function f_session_est_mod_tunmap(charstring netinst_access, charstring expect_gtp_ip_access,
+ charstring netinst_core, charstring expect_gtp_ip_core) runs on CPF_ConnHdlr {
+ f_assoc_setup();
+ var PFCP_session s := f_create_PFCP_session_tunmap();
+ f_session_est(s, f_ruleset_tunmap(s.gtp, core_gtp_known := false,
+ netinst_access := netinst_access, netinst_core := netinst_core));
+ /* The locally chosen GTP IP addresses where osmo-upf receives GTP traffic were chosen by netinst_access /
+ * netinst_core and are returned in s.gtp.access.gtp_ip_l / s.gtp.core.tunmap.gtp_ip_l. Verify that the netinst
+ * names have returned their matching IP addresses. */
+ if (s.gtp.access.gtp_ip_l != expect_gtp_ip_access) {
+ setverdict(fail, "Network Instance '" & netinst_access & "' should have yielded GTP IP " &
+ expect_gtp_ip_access & " but osmo-upf chose " & s.gtp.access.gtp_ip_l);
+ mtc.stop;
+ }
+ if (s.gtp.core.tunmap.gtp_ip_l != expect_gtp_ip_core) {
+ setverdict(fail, "Network Instance '" & netinst_core & "' should have yielded GTP IP " &
+ expect_gtp_ip_core & " but osmo-upf chose " & s.gtp.core.tunmap.gtp_ip_l);
+ mtc.stop;
+ }
+
+ f_sleep(1.0);
+ f_vty_expect_session_status(UPFVTY, s, PFCP_session_inactive);
+
+ f_session_mod(s);
+ f_sleep(1.0);
+ f_vty_expect_session_active(UPFVTY, s);
+ f_session_del(s);
+ f_vty_expect_no_active_sessions(UPFVTY);
+ f_vty_expect_no_gtp_actions(UPFVTY);
+ f_assoc_release();
+ setverdict(pass);
+}
+/* Run f_session_est_mod_tunmap() with the first Network Instances */
+private function f_tc_session_est_mod_tunmap(charstring id) runs on CPF_ConnHdlr {
+ f_session_est_mod_tunmap("access", mp_netinst_access_ip_1, "core", mp_netinst_core_ip_1);
+}
+/* Run f_session_est_mod_tunmap() with the second Network Instances */
+private function f_tc_session_est_mod_tunmap2(charstring id) runs on CPF_ConnHdlr {
+ f_session_est_mod_tunmap("access2", mp_netinst_access_ip_2, "core2", mp_netinst_core_ip_2);
+}
+testcase TC_session_est_mod_tunmap() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+
+ vc_conn := f_start_handler(refers(f_tc_session_est_mod_tunmap));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+testcase TC_session_est_mod_tunmap2() runs on test_CT {
+ var CPF_ConnHdlr vc_conn;
+
+ f_init(guard_timeout := 15.0);
+
+ vc_conn := f_start_handler(refers(f_tc_session_est_mod_tunmap2));
+ vc_conn.done;
+ f_shutdown_helper();
+}
+
+control {
+ execute( TC_assoc_node_id_v4() );
+ execute( TC_assoc_node_id_fqdn() );
+ execute( TC_session_est_tunend() );
+ execute( TC_session_term_by_assoc_rel() );
+ execute( TC_session_est_noop() );
+ execute( TC_session_est_tunmap() );
+ execute( TC_session_est_mod_tunmap() );
+ execute( TC_session_est_mod_tunmap2() );
+}
+
+}
diff --git a/upf/expected-results.xml b/upf/expected-results.xml
new file mode 100644
index 00000000..78f0103f
--- /dev/null
+++ b/upf/expected-results.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<testsuite name='UPF_Tests' tests='8' failures='0' errors='0' skipped='0' inconc='0' time='MASKED'>
+ <testcase classname='UPF_Tests' name='TC_assoc_node_id_v4' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_assoc_node_id_fqdn' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_est_tunend' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_term_by_assoc_rel' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_est_noop' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_est_tunmap' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_est_mod_tunmap' time='MASKED'/>
+ <testcase classname='UPF_Tests' name='TC_session_est_mod_tunmap2' time='MASKED'/>
+</testsuite>
diff --git a/upf/gen_links.sh b/upf/gen_links.sh
new file mode 100755
index 00000000..38651103
--- /dev/null
+++ b/upf/gen_links.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+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 " # GSM 7-bit coding
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+# Required by PFCP/UDP
+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.PFCP_v15.1.0/src
+FILES="PFCP_Types.ttcn"
+gen_links $DIR $FILES
+
+gen_links $DIR $FILES
+DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
+FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="PFCP_CodecPort.ttcn PFCP_CodecPort_CtrlFunct.ttcn PFCP_CodecPort_CtrlFunctDef.cc PFCP_Emulation.ttcn PFCP_Templates.ttcn"
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/upf/osmo-upf.cfg b/upf/osmo-upf.cfg
new file mode 100644
index 00000000..c354d8d5
--- /dev/null
+++ b/upf/osmo-upf.cfg
@@ -0,0 +1,18 @@
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category-hex 0
+ logging print category 1
+ logging print thread-id 0
+ logging print extended-timestamp 1
+ logging print level 1
+ logging print file basename last
+ logging level set-all debug
+pfcp
+ local-addr 127.0.0.1
+gtp
+ mockup
+nft
+ mockup
+#netinst
+# the netinst cfg is cleared and setup dynamically in UPF_Tests.ttcn
diff --git a/upf/regen_makefile.sh b/upf/regen_makefile.sh
new file mode 100755
index 00000000..953e10f2
--- /dev/null
+++ b/upf/regen_makefile.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+NAME=UPF_Tests
+
+FILES="
+ *.ttcn
+ *.ttcnpp
+ *.cc
+ IPA_CodecPort_CtrlFunctDef.cc
+ IPL4asp_PT.cc
+ IPL4asp_discovery.cc
+ Native_FunctionDefs.cc
+ StatsD_CodecPort_CtrlFunctdef.cc
+ TCCConversion.cc
+ TCCEncoding.cc
+ TCCInterface.cc
+ TELNETasp_PT.cc
+"
+
+export CPPFLAGS_TTCN3="
+ -DIPA_EMULATION_CTRL
+"
+
+../regen-makefile.sh -e $NAME $FILES