diff options
165 files changed, 17397 insertions, 2685 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..7592debf9 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: osmocom diff --git a/.gitignore b/.gitignore index eaff7cd47..412e5f164 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,11 @@ debian/*.log +debian/autoreconf.* +debian/*.substvars +debian/tmp +debian/files +debian/.debhelper +debian/osmo-msc*/ + *.o *.lo *.a @@ -73,5 +80,6 @@ doc/manuals/generated/ doc/manuals/osmomsc-usermanual.xml doc/manuals/common doc/manuals/build +doc/manuals/vty/msc_vty_reference.xml contrib/osmo-msc.spec diff --git a/Makefile.am b/Makefile.am index 759f3969a..13a7313f4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,6 +19,7 @@ SUBDIRS = \ BUILT_SOURCES = $(top_srcdir)/.version EXTRA_DIST = \ .version \ + README.md \ contrib/osmo-msc.spec.in \ debian \ git-version-gen \ diff --git a/README b/README deleted file mode 100644 index 0f1b3cf24..000000000 --- a/README +++ /dev/null @@ -1,35 +0,0 @@ -About OsmoMSC -============= - -OsmoMSC is an implementation of the 3GPP MSC (Mobile Switching Centre) -network element. It implements the following core functionality within -the 2G (GSM) and 3G (UMTS) networks: - -* mobility management -* call control (either via built-in MNCC handler or external osmo-sip-connector) -* USSD (exposed via GSUP) -* SMS (either via built-in SMSC or external via GSUP) - -Historically, OsmoMSC originated from the OpenBSC project, which started -as a minimalistic all-in-one implementation of the GSM Network. In 2017, -OpenBSC had reached maturity and diversity (including M3UA SIGTRAN and -3G support in the form of IuCS and IuPS interfaces) that naturally lead -to a separation of the all-in-one approach to fully independent separate -programs as in typical GSM networks. - -OsmoMSC was one of the parts split off from the old openbsc.git. Before, -it was the libmsc part of the old OsmoNITB. Since a true A interface and -IuCS for 3G support is available, OsmoMSC exists only as a separate -standalone entity. - -OsmoMSC exposes -- GSUP towards OsmoHLR (or a MAP proxy); -- A over IP towards a BSC (e.g. OsmoBSC); -- IuCS towards an RNC or HNB-GW (e.g. OsmoHNBGW) for 3G voice; -- MNCC (Mobile Network Call Control derived from GSM TS 04.07); -- SMPP 3.4 (Short Message Peer-to-Peer); -- The Osmocom typical telnet VTY and CTRL interfaces. - -Find OsmoMSC issue tracker and wiki online at -https://osmocom.org/projects/osmomsc -https://osmocom.org/projects/osmomsc/wiki diff --git a/README.md b/README.md new file mode 100644 index 000000000..df1cb5fc0 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +osmo-msc - Osmocom MSC Implementation +===================================== + +This repository contains a C-language implementation of a GSM **Mobile Switching +Centre (MSC)** for 2G (GSM) and 3G (UMTS). It is part of the +[Osmocom](https://osmocom.org/) Open Source Mobile Communications +project. + +OsmoMSC exposes + + * *A over IP* towards BSCs (e.g. [osmo-bsc](https://osmocom.org/projects/osmobsc/wiki): 3GPP AoIP or SCCPlite + * *IuCS over IP* towards RNCs / HNBGW (e.g. [osmo-hnbgw](https://osmocom.org/projects/osmohnbgw/wiki)) + * *MGCP* towards a co-located [osmo-mgw](https://osmocom.org/projects/osmo-mgw/wiki) for the RTP streams + * *[GSUP](https://osmocom.org/projects/cellular-infrastructure/wiki/GSUP)* (instead of 3GPP MAP) towards [osmo-hlr](https://osmocom.org/projects/osmo-hlr/wiki) + * *SMPP* towards any external SMS sending/receiving applications + * *[MNCC](https://osmocom.org/projects/osmomsc/wiki/MNCC)* as external call-control interface towards e.g. + [osmo-sip-connectr](https://osmocom.org/projects/osmo-sip-conector/wiki) + * The Osmocom typical telnet *VTY* and *CTRL* interfaces. + * The Osmocom typical *statsd* exporter. + +OsmoMSC implements + + * mobility management + * call control (either via built-in MNCC handler or external osmo-sip-connector) + * voice group call ([VGCS](https://osmocom.org/projects/cellular-infrastructure/wiki/Voice_Group_Call)) and + voice broadcast calls ([VBS](https://osmocom.org/projects/cellular-infrastructure/wiki/Voice_Broadcast_Call)) as used in GSM-R + * USSD (exposed via GSUP) + * SMS (either via built-in SMSC or external via GSUP) + +Homepage +-------- + +You can find the OsmoMSC home page and wiki online at +<https://osmocom.org/projects/osmomsc/wiki>. + + +GIT Repository +-------------- + +You can clone from the official osmo-msc.git repository using + + git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-msc + +There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-msc> + + +Documentation +------------- + +User Manuals and VTY reference manuals are [optionally] built in PDF form +as part of the build process. + +Pre-rendered PDF version of the current "master" can be found at +[User Manual](https://ftp.osmocom.org/docs/latest/osmomsc-usermanual.pdf) +as well as the [VTY Reference Manual](https://ftp.osmocom.org/docs/latest/osmomsc-vty-reference.pdf) + + +Forum +----- + +We welcome any osmo-msc related discussions in the +[Cellular Network Infrastructure -> 2G/3G CN](https://discourse.osmocom.org/c/cni/2g-3g-cn) +section of the osmocom discourse (web based Forum). + + +Mailing List +------------ + +Discussions related to osmo-msc are happening on the +openbsc@lists.osmocom.org mailing list, please see +<https://lists.osmocom.org/mailman/listinfo/openbsc> for subscription +options and the list archive. + +Please observe the [Osmocom Mailing List +Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules) +when posting. + +Issue Tracker +------------- + +We use the [issue tracker of the osmo-msc project on osmocom.org](https://osmocom.org/projects/osmomsc/issues) for +tracking the state of bug reports and feature requests. Feel free to submit any issues you may find, or help +us out by resolving existing issues. + + +Contributing +------------ + +Our coding standards are described at +<https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards> + +We us a gerrit based patch submission/review process for managing +contributions. Please see +<https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for +more details + +The current patch queue for osmo-msc can be seen at +<https://gerrit.osmocom.org/#/q/project:osmo-msc+status:open> + + +History +------- + +OsmoMSC originated from the [OsmoNITB](https://osmocom.org/projects/osmonitb/wiki/OsmoNITB) +project, which started as a minimalistic all-in-one implementation of the GSM Network. In 2017, OsmoNITB had +reached maturity and diversity (including M3UA SIGTRAN and 3G support in the form of IuCS and IuPS interfaces) +that naturally lead to a separation of the all-in-one approach to fully independent separate programs as in +typical GSM networks. + +OsmoMSC was one of the parts split off from the old openbsc.git. diff --git a/README.vty-tests b/README.vty-tests index 0669ea8e8..dc34916ee 100644 --- a/README.vty-tests +++ b/README.vty-tests @@ -1,6 +1,6 @@ To run the configuration parsing and output (VTY) test suite, first install - git://git.osmocom.org/python/osmo-python-tests + https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests and pass the following configure options here: diff --git a/TODO-RELEASE b/TODO-RELEASE index d0852fc9b..8b07972f3 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libosmogsm >1.9.0 ABI breakage in struct osmo_gsup_pdp_info, use new fields pdp_type_* and pdp_address.
\ No newline at end of file diff --git a/configure.ac b/configure.ac index 3395ecc0d..89d37c2e6 100644 --- a/configure.ac +++ b/configure.ac @@ -36,16 +36,19 @@ if test "x$PKG_CONFIG_INSTALLED" = "xno"; then fi PKG_PROG_PKG_CONFIG([0.20]) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.6.0) -PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.6.0) -PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.6.0) -PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.6.0) -PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.2.0) -PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.1.0) -PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.5.0) -PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 1.5.0) -PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.9.0) -PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.4.0) +PKG_CHECK_MODULES(LIBSQLITE3, sqlite3) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.9.0) +PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.5.0) +PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.4.0) +PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran >= 1.8.0) +PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 1.8.0) +PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.12.0) +PKG_CHECK_MODULES(LIBOSMOGSUPCLIENT, libosmo-gsup-client >= 1.7.0) + +AC_CHECK_FUNC([timegm], [AC_DEFINE(HAVE_TIMEGM, 1, Define if libc implements timegm)]) old_LIBS=$LIBS AC_SEARCH_LIBS([sctp_send], [sctp], [ @@ -103,16 +106,12 @@ AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS a [osmo_ac_iu="$enableval"],[osmo_ac_iu="no"]) if test "x$osmo_ac_iu" = "xyes" ; then PKG_CHECK_MODULES(LIBASN1C, libasn1c >= 0.9.30) - PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 0.8.0) + PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.5.0) AC_DEFINE(BUILD_IU, 1, [Define if we want to build IuPS and IuCS interfaces support]) fi AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes") AC_SUBST(osmo_ac_iu) -dnl checks for header files -AC_HEADER_STDC -AC_CHECK_HEADERS(dbi/dbd.h,,AC_MSG_ERROR(DBI library is not installed)) - # Coverage build taken from WebKit's configure.in AC_MSG_CHECKING([whether to enable code coverage support]) AC_ARG_ENABLE(coverage, @@ -160,7 +159,7 @@ if test "x$enable_ext_tests" = "xyes" ; then AM_PATH_PYTHON AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes) if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then - AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.]) + AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.]) fi fi AC_MSG_CHECKING([whether to enable VTY/CTRL tests]) @@ -235,9 +234,11 @@ AC_OUTPUT( include/Makefile include/osmocom/Makefile include/osmocom/msc/Makefile + include/osmocom/smpp/Makefile src/Makefile src/libmsc/Makefile src/libvlr/Makefile + src/libsmpputil/Makefile src/osmo-msc/Makefile src/utils/Makefile tests/Makefile @@ -248,6 +249,7 @@ AC_OUTPUT( tests/msc_vlr/Makefile tests/sdp_msg/Makefile tests/mncc/Makefile + tests/csd/Makefile doc/Makefile doc/examples/Makefile doc/manuals/Makefile diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh index fb858d763..c5161eff6 100755 --- a/contrib/jenkins.sh +++ b/contrib/jenkins.sh @@ -5,6 +5,7 @@ # * IU: configure 3G support (values: "--enable-iu", "--disable-iu") # * WITH_MANUALS: build manual PDFs if set to "1" # * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1") +# * IS_MASTER_BUILD: set to 1 when running from master-builds (not gerrit-verifications) # if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then @@ -12,6 +13,14 @@ if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then exit 2 fi +exit_tar_workspace() { + if [ "$IS_MASTER_BUILD" = "1" ]; then + tar -cJf "/tmp/workspace.tar.xz" "$base" + mv /tmp/workspace.tar.xz "$base" + fi + + cat-testlogs.sh +} set -ex @@ -35,17 +44,14 @@ export PATH="$inst/bin:$PATH" osmo-build-dep.sh libosmo-abis osmo-build-dep.sh libosmo-netif osmo-build-dep.sh libosmo-sccp -PARALLEL_MAKE="" osmo-build-dep.sh libsmpp34 +osmo-build-dep.sh libsmpp34 osmo-build-dep.sh osmo-mgw osmo-build-dep.sh osmo-hlr -enable_werror="" if [ "x$IU" = "x--enable-iu" ]; then osmo-build-dep.sh libasn1c #osmo-build-dep.sh asn1c aper-prefix # only needed for make regen in osmo-iuh osmo-build-dep.sh osmo-iuh -else - enable_werror="--enable-werror" fi # Additional configure options and depends @@ -64,14 +70,14 @@ set -x cd "$base" autoreconf --install --force -./configure --enable-sanitize $enable_werror --enable-smpp $IU --enable-external-tests $CONFIG +./configure --enable-sanitize --enable-werror --enable-smpp $IU --enable-external-tests $CONFIG $MAKE $PARALLEL_MAKE LD_LIBRARY_PATH="$inst/lib" $MAKE check \ - || cat-testlogs.sh + || exit_tar_workspace LD_LIBRARY_PATH="$inst/lib" \ - DISTCHECK_CONFIGURE_FLAGS="$enable_werror --enable-smpp $IU --enable-external-tests $CONFIG" \ + DISTCHECK_CONFIGURE_FLAGS="--enable-werror --enable-smpp $IU --enable-external-tests $CONFIG" \ $MAKE $PARALLEL_MAKE distcheck \ - || cat-testlogs.sh + || exit_tar_workspace if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then make -C "$base/doc/manuals" publish diff --git a/contrib/osmo-msc.spec.in b/contrib/osmo-msc.spec.in index 17c07b91b..de9314926 100644 --- a/contrib/osmo-msc.spec.in +++ b/contrib/osmo-msc.spec.in @@ -27,24 +27,23 @@ URL: https://osmocom.org/projects/osmomsc Source: %{name}-%{version}.tar.xz BuildRequires: autoconf BuildRequires: automake -BuildRequires: libdbi-drivers-dbd-sqlite3 BuildRequires: libtool %if 0%{?suse_version} BuildRequires: systemd-rpm-macros %endif BuildRequires: pkgconfig >= 0.20 -BuildRequires: pkgconfig(dbi) +BuildRequires: pkgconfig(sqlite3) BuildRequires: pkgconfig(libcrypto) >= 0.9.5 -BuildRequires: pkgconfig(libosmo-gsup-client) >= 1.4.0 -BuildRequires: pkgconfig(libosmo-mgcp-client) >= 1.9.0 -BuildRequires: pkgconfig(libosmo-netif) >= 1.1.0 -BuildRequires: pkgconfig(libosmo-sccp) >= 1.5.0 -BuildRequires: pkgconfig(libosmo-sigtran) >= 1.5.0 -BuildRequires: pkgconfig(libosmoabis) >= 1.2.0 -BuildRequires: pkgconfig(libosmocore) >= 1.6.0 -BuildRequires: pkgconfig(libosmoctrl) >= 1.6.0 -BuildRequires: pkgconfig(libosmogsm) >= 1.6.0 -BuildRequires: pkgconfig(libosmovty) >= 1.6.0 +BuildRequires: pkgconfig(libosmo-gsup-client) >= 1.7.0 +BuildRequires: pkgconfig(libosmo-mgcp-client) >= 1.12.0 +BuildRequires: pkgconfig(libosmo-netif) >= 1.4.0 +BuildRequires: pkgconfig(libosmo-sccp) >= 1.8.0 +BuildRequires: pkgconfig(libosmo-sigtran) >= 1.8.0 +BuildRequires: pkgconfig(libosmoabis) >= 1.5.0 +BuildRequires: pkgconfig(libosmocore) >= 1.9.0 +BuildRequires: pkgconfig(libosmoctrl) >= 1.9.0 +BuildRequires: pkgconfig(libosmogsm) >= 1.9.0 +BuildRequires: pkgconfig(libosmovty) >= 1.9.0 BuildRequires: pkgconfig(libsmpp34) >= 1.14.0 #### BuildRequires: lksctp-tools-devel @@ -52,12 +51,7 @@ BuildRequires: lksctp-tools-devel %{?systemd_requires} %if %{with_iu} BuildRequires: pkgconfig(libasn1c) >= 0.9.30 -BuildRequires: pkgconfig(libosmo-ranap) >= 0.8.0 -%endif -%if 0%{?suse_version} -Requires: libdbi-drivers-dbd-sqlite3 -%else -Requires: libdbi-dbd-sqlite +BuildRequires: pkgconfig(libosmo-ranap) >= 1.5.0 %endif %description @@ -110,7 +104,7 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +) %files %license COPYING -%doc AUTHORS README +%doc AUTHORS README.md %dir %{_docdir}/%{name}/examples %dir %{_docdir}/%{name}/examples/osmo-msc %{_docdir}/%{name}/examples/osmo-msc/osmo-msc.cfg diff --git a/contrib/systemd/osmo-msc.service b/contrib/systemd/osmo-msc.service index 343639cf3..f21aec7b5 100644 --- a/contrib/systemd/osmo-msc.service +++ b/contrib/systemd/osmo-msc.service @@ -4,10 +4,14 @@ Wants=osmo-hlr.service Wants=osmo-mgw.service After=osmo-hlr.service After=osmo-hnbgw.service +After=network-online.target +Wants=network-online.target [Service] Type=simple Restart=always +StateDirectory=osmocom +WorkingDirectory=%S/osmocom ExecStart=/usr/bin/osmo-msc -c /etc/osmocom/osmo-msc.cfg RestartSec=2 diff --git a/debian/changelog b/debian/changelog index 54fbd032d..debce4e80 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,296 @@ +osmo-msc (1.11.1) unstable; urgency=medium + + [ Neels Hofmeyr ] + * fix codecs in internal call bridge + * make two functions static + + [ Mychaela N. Falconia ] + * CC: don't start guard timer on mid-call MNCC messages + * gsup_client_mux: set destination_name in error reply function + * SMS over GSUP: correctly route GSUP responses to MT SMS + * SMS over GSUP: set source_name in GSUP reply messages + + [ Andreas Eversberg ] + * ASCI: Remove duplicated CLEAR COMMAND from VGCS/VBS channel handling + + -- Oliver Smith <osmith@sysmocom.de> Thu, 28 Sep 2023 13:53:07 +0200 + +osmo-msc (1.11.0) unstable; urgency=medium + + [ arehbein ] + * Transition to use of 'telnet_init_default' + + [ Neels Hofmeyr ] + * sdp_msg.c: fix missing rate in sdp_audio_codecs_add() + * comment: clarify L3 Info processing + * IuCS: remove IuUP LOOPBACK hack + * make: doc/sequence_charts: use wildcards for EXTRA_DIST and CLEANFILES + * tweak MNCC logging, add RTP info + * msc_log_to_ladder.py: various tweaks + * charts: Rename voice_call_full.msc to voice_call_external_mncc.msc + * update doc/sequence_charts/voice_call_external_mncc.msc + * add voice_call_internal_mncc.msc + * add codec_mapping.h,c + * MNCC: use codec_mapping, drop mgcp_codec_to_mncc_payload_msg_type() + * [codecs filter] add codec_filter.h,c + * [codecs filter] add trans.cc.codecs + * [codecs filter] store BSS codec list from Compl L3 + * [codecs filter] MO call: apply BSS codec list + * [codecs filter] MT call: apply BSS codec list + * [codecs filter] MT call: apply remote call leg codecs + * [codecs filter] MT call: store MS Bearer Cap from CC Call Conf + * msc_vlr_test_call: include RAN RTP addr in ass compl + * [codecs filter] apply BSS codecs from Assignment Complete + * add ran_infra.force_mgw_codecs_to_ran + * rtp_stream: allow multiple codecs / use codec filter from Assignment + * in ran_msg, return gsm0808_speech_codec (intra-MSC) + * in ran_msg, return gsm0808_speech_codec (inter-MSC) + * [codecs filter] use filter result in MT DTAP CC Setup + * [codecs filter] use filter result in Assignment + * [codecs filter] send + receive SDP via MNCC + * msc_vlr_tests: confirm crcx by RAN/CN side separately + * [codecs filter] use codecs filter on crcx ok + * do CN CRCX first + * mncc_recvmsg(): log caller file,line + * [codecs filter] msc_vlr_test_call: test codecs resolution + * codecs: compose HO Req Ch Type from cc.codecs + * HO Req: include IE Codec List (MSC Preferred) + * fix msc_vlr_test_call SDP mncc_rtp + * coverity: sdp_msg_test.c: check rc of sdp_msg_from_sdp_str() + * 3G: decapsulate IuUP to AMR at the MGW; allow 3G<-AMR->2G + * TODO-RELEASE: add note on osmo-sip-connector and SDP + + [ Vadim Yanitskiy ] + * src/Makefile.am: remove unneeded AM_LDFLAGS with LIBS + * tests: use -no-install libtool flag to avoid ./lt-* scripts + * tests: $(BUILT_SOURCES) is not defined, depend on osmo-msc + * copyright: fix typo: sysmocom s/s.m.f.c./s.f.m.c./ GmbH + * fixup: contrib/jenkins: create workspace.tar.xz on error + * tests/{ctrl,vty}_test_runner.py: raise an exception if proc's rc != 0 + * msc_vty: support spaces in short/long network name + * ran_a_mgcp_codec_from_sc(): cosmetic: remove unneeded breaks + * ran_a_mgcp_codec_from_sc(): map GSM0808_SCT_CSD to CODEC_CLEARMODE + * ran_a_channel_type_to_speech_codec_list(): set PI/PT for CSD + * codec_mapping: codec_map[]: add missing speech codec for CLEARMODE + * csd_bs_list_to_bearer_cap(): properly initialize bcap fields + * csd_bs_list_to_bearer_cap(): add default branch for safety + + [ Pau Espin Pedrol ] + * mncc_sock: Call osmo_fd_unregister() before closing and changing bfd->fd + * rtp_stream: Update id after modifying fields upon Tx of MGCP msg + * rtp_stream: Fix remote_osmux_cid_sent_to_mgw never set to true + * UserManual: Include sigtran*.adoc from osmo-gsm-manuals.git + * Write explicit role & sctp-role fields in ASP configurations + * Use new mgcp_client_conf_alloc() API to alloc mgcp_client_conf + * Tx Loc UPD ACC: Use PLMN provided by subscr + * trans_lcls_compose(): Set PLMN fron cell currently in use + + [ Oliver Smith ] + * msc_mgw_setup: use mgcp_client_pool_empty() + * msc_main: close SMS db on startup error + * debian: set compat level to 10 + * contrib/jenkins: create workspace.tar.xz on error + * systemd: depend on networking-online.target + * codec_mapping: add clearmode + * ran_a_channel_type_to_speech_codec_list: add CSD + * codec_filter_set_ms_from_bc: prepare for CSD + * Cosmetic: gsm48_cc_tx_setup: tweak comment + * Cosmetic: gsm48_cc_tx_setup: remove TODO comment + * codec_filter_init: prepare for CSD + * codec_filter_set_ran: prepare for CSD + * codec_filter_set_bss: prepare for CSD + * codec_filter_run: prepare for CSD + * transaction: move cc.codecs.remote -> cc.remote + * transaction: move cc.codecs.result -> cc.local + * msc: add trans_cc_set_remote_from_bc + * gsm48_cc_tx_setup: set trans->bearer_cap.transfer early + * Add initial CSD support with external MNCC + * smpp_handle_bind_tx: initialize tlv + * sdp_msg_test: fix dereference after null check + * smpp_msc: submit_to_sms: check ud_len > sms_msg_len + * msc_ho_send_handover_request: fix check_after_deref + * csd_bs_list_to_gsm0808_channel_type: fix rc check + * gsm48_cc_tx_alerting: check rc of sdp_msg_from_sdp_str + * mncc_test: fix talloc_named_const + * gsm48_cc_tx_setup: use MNCC bcaps for CSD + * test: add csd_test + * csd_bs_list_remove: fix removal logic + * mncc_builtin: permit data bearer types + * csd_bs_to_gsm0808: add T 300 / proper ch_rate_type + * Cosmetic: fix typo + * csd_bs_list_to_gsm0808_ct: assert -> ret -EINVAL + * msc_ho_send_handover_request: support CSD + * msc_a_up_call_assignment_complete: check CSD codec + * gsm48_cc_tx_call_proc_…: verify bcap.transfer + + [ Andreas Eversberg ] + * ASCI: Add log categories for GCC/BCC (call control) + * ASCI: Add log category for VGCS/VBS call and channel FSM + * ASCI: Use a unique call-id for RTP streams + * ASCI: rtp_stream_commit(): Also update MGW on conn mode change + * ASCI: Allow usage of rtp_stream with other FSM + * ASCI: Add transaction type to trans_find_by_callref() + * ASCI: Add two new transaction types for VGCS and VBS + * ASCI: Allow transaction without subscriber associated + * ASCI: Add simple implementation of Group Call Register + * ASCI: Add functions to transcode VGCS/VBS messages on A-interface + * ASCI: Add callref to assignment command + * ASCI: Add call control for VGCS/VBS + * ASCI: Add decoder for VGCS/VBS messages to msc_a.c + * ASCI: Add function to receive VGCS/VBS messages from BSS + * ASCI: Add option to switch on or off ASCI support + * ASCI: Check return code of osmo_mobile_identity_decode() + * ASCI: Remove check for trans->msc_a to be set in _assign_complete() + * ASCI: Add VTY to configure GCR (Group Call Register) + * ASCI: Add reception of UPLINK RELEASE on dedicated channel + * ASCI: Clear VGCS call and channel on BSSMAP reset message + * ASCI: Receive messages from MSC-A role related to VGCS/VBS + * ASCI: Null pointer bug fix in trans_create_bcc_gcc + * ASCI: Fix wrong check for Null pointer in vgcs_cell_fsm_null() + * ASCI: Check if codec mapping exists for given codec + * ASCI: Fix Null pointer dereference bug in gsm44068_bcc_gcc_trans_free() + * ASCI: Point to correct state machine when calling ran_encode_and_send() + * ASCI: Add debugging and error logging to VGCS/VBS call control + * ASCI: Add missing transaction ID to SET PARAMETER message + + [ Keith Whyte ] + * SMPP: Fix Memory leaks + + -- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 12 Sep 2023 16:46:11 +0200 + +osmo-msc (1.10.0) unstable; urgency=medium + + [ Keith Whyte ] + * Don't let this osmo-msc operate on a libdbi database + * Turn off secure_delete in sqlite + * Update MNCC field validation mask. + * Change CC_CAUSE returned on unanswered MT Call + * LCLS: Fix Global Call Reference generation + + [ Neels Hofmeyr ] + * fix typo in msgb name for CC SETUP + * missing whitespace in gsm_04_08_cc.c + * err log: fix reverse statement in msc_a call handling + * cosmetic: log actual MNCC msg in tch_rtp_connect() + * sdp_msg: s/_name_/_to_str_/g + * in sdp logging: add payload type number like 'AMR#111' + * sdp_msg: add sdp_audio_codecs_cmp(), add compare flags + * sdp_msg: s/sdp_audio_codec_/sdp_audio_codecs_ + * msc_a,vlr: rename ciphering_required to is_ciphering_to_be_attempted + * msc_a,vlr: add is_ciphering_required (accurately named) + * vlr_lu_fsm: clarify naming of static functions + * vlr: auth_fsm: clarify success/failure result + * vlr: auth_fsm: rename AUTH_RES to AUTH_SUCCESS + * vlr_auth_fsm: add result no_auth_info_event + * vlr: implement fallback to no-auth + * sdp_msg: when NULL, do not crash but return empty SDP str + * log CC timeouts + * add sdp_audio_codec_is_set + * add some comments to sdp_msg.c,h + * sdp_msg.c: parse send/recv mode + * fix sdp_msg_to_sdp_str(), never add fmtp for unset codec + * rtp_stream_commit: check missing MGW ep only when ready for RTP + * rtp_stream: set_remote_addr: do nothing when unchanged + + [ Max ] + * SMPP: clarify (re)start logic + * Ignore .deb build byproducts + * ESME: use osmo_sock_get_name() for logging + * tests: use common stubs for SMS queue test + * Introduce libsmpputil + * Add ESME-specific logging + * Set working directory in systemd service file + * Make esme struct shared + * Use libsmpputil functions in smpp_mirror tool + * cosmetic: use proper name for SMPP handlers + * SMPP: remove duplicate g_smsc definition + * smpp_mirror: fix compiler warning + * SMPP: use default port from libsmpp34 + * SMPP: fix possible NULL pointer dereference + * SMPP: make smpp_smsc_stop() static + * ctrl: take both address and port from vty config + * SMPP: use proper type for boolean variables + + [ Vadim Yanitskiy ] + * contrib/jenkins.sh: do not override parallel make for libsmpp34 + * mncc: move MNCC_F_ALL from mncc.c to mncc.h + * mncc: cosmetic: fix coding style in mncc_prim_check_sign() + * libmsc: check return value of gsm0808_create_ass2() + * msc_main: fix wrong comment: HLR is a separate project + * fix msc_vty_go_parent(): add missing case for MGW_NODE + + [ Pau Espin Pedrol ] + * tests/test_nodes.vty: Avoid listing commands provided by lib + * Introduce support for libosmo-mgcp-client MGW pooling + * vty: Make use of new mgcp_client_pool_config_write() API + * Use new mgcp-client VTY commands under mgw node + * call_leg: Fix EV_MGW_ENDPOINT_GONE not processed in RELEASE state + * doc: Include mgwpool.adoc from osmo-gsm-manuals + + [ Oliver Smith ] + * contrib/jenkins.sh: use enable-werror with IU too + + -- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 07 Feb 2023 17:28:16 +0100 + +osmo-msc (1.9.0) unstable; urgency=medium + + [ Alexander Couzens ] + * utran: use new UTRAN encryption enum + * libmsc/gsm_04_08: refactor require ciphering into an own function + * ran_msg_iu: do not pass UEA0 to ranap_new_msg_sec_mod_cmd2() + + [ Vadim Yanitskiy ] + * VTY: clarify deprecation message for cfg_net_per_loc_upd_cmd + * libmsc: fix memory leak (struct gsm_sms) in gsm340_rx_tpdu() + * libmsc: fix another memleak (struct gsm_sms) in gsm340_rx_tpdu() + * libvlr: vlr_set_ciph_mode(): avoid redundant check + * libvlr: fix is_ciph_required(): always send SecModeCmd for UTRAN + * libmsc: ran_iu_make_security_mode_command(): improve readability + * libmsc: ran_iu_make_security_mode_command(): clarify UIA mask + * libmsc: fix memory leak (struct msgb) in msc_i_ran_enc() + * tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS' + + [ Oliver Smith ] + * treewide: remove FSF address + * tests/msc_vlr/Makefile.am: drop -ldbi + + [ Pau Espin Pedrol ] + * Announce IuFP audio codec for UTRAN conns in CRCX towards MGW + * Avoid setting audio codec if not available during assignment_complete (MDCX) + * ran_msg_iu.c: Set proper codec in Assignment Complete + * Drop unneeded ax_check_compile_flag.m4 + * call_leg: local_bridge: Avoid null pointer access if CN-side not ready + + [ Neels Hofmeyr ] + * fix crash on CM Serv Rej: fix use count mismatch + + [ Harald Welte ] + * call rate_ctr_init() to make rate counters work properly + * switch sqlite3 to single-threaded mode + * sms_queue: Annotate each function with some comment + * vlr: Split vlr_subscr_rx_imsi_detach() + * vlr: Add rate counters and stat items + * sms_queue: Introduce rate_ctr / stat_item + * smpp: Fix use-after-free bug when ESME disconnects but has write pending + * smpp: don't enqueue write messages if ESME is disconnected + * sms_queue: refactor sms_pending add/remove code + * sms_queue: merge sms_pending_add into sms_pending_from + * tests: Remove sms.db{-wal,-shm} files, not just sms.db + * switch from libdbi to lbsqlite3 + * db: Switch from 'synchronous = FULL' to 'synchronous = NORMAL' + * sms: Encapsulate SMS queue related config parameters + * sms: Give smsc its own VTY config node + * sms_queue: Use local variable rather than 9x pointer de-ref in function + * sms_queue: Make deletion of messages from DB VTY-configurable + * smpp: Parse and use SMPP-provided validity period + * sms: Make default SMS validity period configurable via VTY + * sms: Introduce VTY-configurable minimum SMS validity period + * update git URLs (git -> https; gitea) + * Convert + Expand README file + * fix RPM build failures due to README -> README.md rename + + -- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 29 Jun 2022 11:32:11 +0200 + osmo-msc (1.8.0) unstable; urgency=medium [ Pau Espin Pedrol ] diff --git a/debian/compat b/debian/compat index ec635144f..f599e28b8 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +10 diff --git a/debian/control b/debian/control index 0b2ac6b2c..64bb73c90 100644 --- a/debian/control +++ b/debian/control @@ -2,37 +2,36 @@ Source: osmo-msc Section: net Priority: extra Maintainer: Osmocom team <openbsc@lists.osmocom.org> -Build-Depends: debhelper (>=9), +Build-Depends: debhelper (>= 10), dh-autoreconf, autotools-dev, autoconf, automake, libtool, pkg-config, - libdbi-dev, - libdbd-sqlite3, + libsqlite3-dev, libsctp-dev, libtalloc-dev, libsmpp34-dev (>= 1.14.0), libasn1c-dev (>= 0.9.30), - libosmocore-dev (>= 1.6.0), - libosmo-sccp-dev (>= 1.5.0), - libosmo-sigtran-dev (>= 1.5.0), - libosmo-abis-dev (>= 1.2.0), - libosmo-mgcp-client-dev (>= 1.9.0), - libosmo-gsup-client-dev (>= 1.4.0), - libosmo-netif-dev (>= 1.1.0), - libosmo-ranap-dev (>= 0.8.0), - osmo-gsm-manuals-dev (>= 1.2.0) + libosmocore-dev (>= 1.9.0), + libosmo-sccp-dev (>= 1.8.0), + libosmo-sigtran-dev (>= 1.8.0), + libosmo-abis-dev (>= 1.5.0), + libosmo-mgcp-client-dev (>= 1.12.0), + libosmo-gsup-client-dev (>= 1.7.0), + libosmo-netif-dev (>= 1.4.0), + libosmo-ranap-dev (>= 1.5.0), + osmo-gsm-manuals-dev (>= 1.5.0) Standards-Version: 3.9.8 -Vcs-Git: git://git.osmocom.org/osmo-msc.git -Vcs-Browser: https://git.osmocom.org/osmo-msc/ +Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-msc +Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-msc Homepage: https://osmocom.org/projects/osmomsc Package: osmo-msc Architecture: any Multi-Arch: foreign -Depends: ${misc:Depends}, ${shlibs:Depends}, libdbd-sqlite3 +Depends: ${misc:Depends}, ${shlibs:Depends} Recommends: osmo-mgw Description: OsmoMSC: Osmocom's Mobile Switching Center for 2G and 3G circuit-switched mobile networks The Mobile Switching Center (MSC) is the heart of 2G/3G diff --git a/debian/copyright b/debian/copyright index e3cd9b3cb..ac8ed52d2 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,6 +1,6 @@ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: osmo-msc -Source: git://git.osmocom.org/osmo-msc +Source: https://gitea.osmocom.org/cellular-infrastructure/osmo-msc Files: * Copyright: 2008 Daniel Willmann <daniel@totalueberwachung.de> diff --git a/doc/examples/osmo-msc/osmo-msc.cfg b/doc/examples/osmo-msc/osmo-msc.cfg index 83b2c6fec..7c5fe2d55 100644 --- a/doc/examples/osmo-msc/osmo-msc.cfg +++ b/doc/examples/osmo-msc/osmo-msc.cfg @@ -1,21 +1,30 @@ ! ! OsmoMSC configuration saved from vty ! +log stderr + logging color 1 + logging print category-hex 0 + logging print category 1 + logging timestamp 0 + logging print file basename last + logging print level 1 + line vty no login ! network - network country code 1 - mobile network code 1 + network country code 001 + mobile network code 01 short name OsmoMSC long name OsmoMSC encryption a5 0 rrlp mode none mm info 1 + mgw 0 + remote-ip 127.0.0.1 + remote-port 2427 + local-port 2728 msc - mgw remote-ip 127.0.0.1 - mgw remote-port 2427 - mgw local-port 2728 assign-tmsi auth-tuple-max-reuse-count 3 auth-tuple-reuse-on-error 1 diff --git a/doc/examples/osmo-msc/osmo-msc_custom-sccp.cfg b/doc/examples/osmo-msc/osmo-msc_custom-sccp.cfg index d949ef9a0..503359899 100644 --- a/doc/examples/osmo-msc/osmo-msc_custom-sccp.cfg +++ b/doc/examples/osmo-msc/osmo-msc_custom-sccp.cfg @@ -1,6 +1,14 @@ ! ! OsmoMSC configuration saved from vty ! +log stderr + logging color 1 + logging print category-hex 0 + logging print category 1 + logging timestamp 0 + logging print file basename last + logging print level 1 + line vty no login ! @@ -12,16 +20,19 @@ network encryption a5 0 rrlp mode none mm info 1 + mgw 0 + remote-ip 127.0.0.1 + remote-port 2427 + local-port 2728 cs7 instance 0 point-code 0.23.1 asp asp-clnt-OsmoMSC-A-Iu 2905 0 m3ua ! where to reach the STP: remote-ip 127.0.0.5 -! local-ip 10.23.24.1 + !local-ip 10.23.24.1 + role asp + sctp-role client msc cs7-instance-a 0 cs7-instance-iu 0 - mgw remote-ip 127.0.0.1 - mgw remote-port 2427 - mgw local-port 2728 assign-tmsi diff --git a/doc/examples/osmo-msc/osmo-msc_multi-cs7.cfg b/doc/examples/osmo-msc/osmo-msc_multi-cs7.cfg index cb1157db3..22f8734de 100644 --- a/doc/examples/osmo-msc/osmo-msc_multi-cs7.cfg +++ b/doc/examples/osmo-msc/osmo-msc_multi-cs7.cfg @@ -1,6 +1,14 @@ ! ! OsmoMSC configuration saved from vty ! +log stderr + logging color 1 + logging print category-hex 0 + logging print category 1 + logging timestamp 0 + logging print file basename last + logging print level 1 + line vty no login ! @@ -12,18 +20,23 @@ network encryption a5 0 rrlp mode none mm info 1 + mgw 0 + remote-ip 127.0.0.1 + remote-port 2427 + local-port 2728 cs7 instance 0 point-code 0.23.1 asp asp-clnt-OsmoMSC-A 2905 0 m3ua remote-ip 127.0.0.5 + role asp + sctp-role client cs7 instance 1 point-code 0.23.2 asp asp-clnt-OsmoMSC-Iu 2905 0 m3ua remote-ip 127.0.0.6 + role asp + sctp-role client msc cs7-instance-a 0 cs7-instance-iu 1 - mgw remote-ip 127.0.0.1 - mgw remote-port 2427 - mgw local-port 2728 assign-tmsi diff --git a/doc/manuals/chapters/running.adoc b/doc/manuals/chapters/running.adoc index 86653954e..3041145dc 100644 --- a/doc/manuals/chapters/running.adoc +++ b/doc/manuals/chapters/running.adoc @@ -74,15 +74,8 @@ msc More on MNCC in <<mncc-external>>. -The SGs interface by default listens on 0.0.0.0:29118. Configure a different IP and/or port for each osmo-msc instance. -You may also want to configure different VLR names: - ----- -sgs - local-ip 127.0.0.1 - local-port 29118 - vlr-name vlr.example.net ----- +The SGs interface by default listens on 0.0.0.0:29118 (SCTP). Each instance of OsmoMSC must use a different IP address +and/or port. For details about the configuration of the SGs interface, see section <<sgs>>. For the following links, OsmoMSC acts as a client and does not listen/bind to a specific interface, and will hence not encounter conflicts for multiple instances @@ -107,6 +100,7 @@ cs7 instance 0 point-code 0.23.1 asp asp-clnt-OsmoMSC-A-Iu 2905 0 m3ua remote-ip 127.0.0.1 + role asp sctp-role client ---- @@ -118,9 +112,13 @@ Note that _A_ and _IuCS_ may use different SCCP instances, if so desired: cs7 instance 0 asp my-OsmoMSC-A 2905 0 m3ua remote-ip 10.23.42.1 + role asp + sctp-role client cs7 instance 1 asp my-OsmoMSC-Iu 2905 0 m3ua remote-ip 10.23.42.2 + role asp + sctp-role client msc cs7-instance-a 0 cs7-instance-iu 1 @@ -149,11 +147,26 @@ default port for MGCP (2427) on local host (127.0.0.1). Here is an example configuration for a remote MGW: ---- -msc - mgw remote-ip 10.9.8.7 - mgw remote-port 2427 - mgw reset-endpoint rtpbridge/* <1> +network + mgw 0 + remote-ip 10.9.8.7 + remote-port 2427 + reset-endpoint rtpbridge/* <1> ---- <1> The 'reset-endpoint' setting instructs the OsmoMGW to send a wildcarded DLCX to the media gateway. This helps to clear lingering calls from the media gateway when the OsmoMSC is restarted. + +OsmoMSC is also able to handle a pool of media gateways for load +distribution. See also <<mgw_pooling>>. + +[NOTE] +==== +Previous versions of OsmoMSC (1.9.0 and below) didn't have the 'mgw' VTY node and +hence didn't support the MGW pooling feature. Therefore, historically the MGW +related commands where placed under the `msc` VTY node. The MGW related commands +under the `msc` VTY are still parsed and used but its use is deprecated and +hence discouraged in favour of the new `mgw` node. Writing the config to a file +from within OsmoMSC will automatically convert the config to use the new `mgw` +node. +==== diff --git a/doc/manuals/chapters/sgs.adoc b/doc/manuals/chapters/sgs.adoc new file mode 100644 index 000000000..1f0240bed --- /dev/null +++ b/doc/manuals/chapters/sgs.adoc @@ -0,0 +1,55 @@ +[[sgs]] +== SGs interface + +OsmoMSC offers an SGs interface using the SGsAP protocol. The SGs interface is an +optional interface between a 2G (GERAN) / 3G (UTRAN) MSC and an 4G (EUTRAN) MME. +Its purpose is to facilitate both CSFB (Circuit-Switched Fall Back) and SMSoS +(SMS over SGs). It is used for Mobility management (MM) and paging procedures +between the EPS (Evolved Packet Services) and CS (Circuit Switched) domain. + +=== VTY configuration + +The SGs interface implementation in OsmoMSC is automatically active and requires +only minimal configuration. When no specific configuration is provided OsmoMSC +will listen on 0.0.0.0:29118 (SCTP) for incoming connections. + +This is sufficient in the most configurations, but in larger installations, +where services are either tied to specific interfaces and/or more instances of +OsmoMSC run in parallel, a custom configuration is necessary. + +The user has the option to configure the IP address (`local-ip`) and the SCTP +port (`local-port`) and also the `vlr-name` that OsmoMSC uses to identify itself +towards the MME. It should be noted that the `vlr-name` is usually the DNS name +for the IP address of the VLR/MSC, so IP address used and the `vlr-name` should +match the DNS server entry. + +---- +sgs + local-ip 127.0.0.1 + local-port 29118 + vlr-name vlr.example.net +---- + +In order to fine tune the behavior of the SGs interface the user also has +control over the relevant timers (`ts5`, `ts6-2`, `ts7`, `ts11`, `ts14`, `ts15`) +and counters (`ns7`, `ns11`). Each timer and counter has to be configured +separately. In the following example we change the value of ts and ns11. + +---- +sgs + timer ts7 23 + counter ns11 100 +---- + + +[NOTE] +==== +In case multiple instances of OsmoMSC run in parallel, it is advised to use a +different `vlr-name` for each instance. In any case it must be ensured that the +SGs interface of each instance is bound to a different IP address and/or port. +==== + +=== Connection monitoring + +The user can use the VTY command `show sgs-connections` to list the MMEs that +are currently connected to OsmoMSC. diff --git a/doc/manuals/osmomsc-usermanual.adoc b/doc/manuals/osmomsc-usermanual.adoc index 7ba45d40f..45be140f5 100644 --- a/doc/manuals/osmomsc-usermanual.adoc +++ b/doc/manuals/osmomsc-usermanual.adoc @@ -22,6 +22,10 @@ include::./common/chapters/vty.adoc[] include::./common/chapters/logging.adoc[] +include::./common/chapters/sigtran-osmocom.adoc[] + +include::./common/chapters/cs7-config.adoc[] + include::./common/chapters/cs7-config.adoc[] include::{srcdir}/chapters/net.adoc[] @@ -32,6 +36,10 @@ include::./common/chapters/mncc.adoc[] include::{srcdir}/chapters/osmux_msc.adoc[] +include::./common/chapters/mgwpool.adoc[] + +include::{srcdir}/chapters/sgs.adoc[] + include::./common/chapters/control_if.adoc[] include::./common/chapters/gsup.adoc[] diff --git a/doc/sequence_charts/Makefile.am b/doc/sequence_charts/Makefile.am index 5efe8558b..7a5277643 100644 --- a/doc/sequence_charts/Makefile.am +++ b/doc/sequence_charts/Makefile.am @@ -4,24 +4,19 @@ all: charts: msc dot EXTRA_DIST = \ - inter_bsc_ho.msc \ - inter_msc_ho.msc \ - mncc_call_fsm.msc \ - call_reestablishment.msc \ + $(srcdir)/*.msc \ $(NULL) CLEANFILES = \ - inter_bsc_ho.png \ - inter_msc_ho.png \ - mncc_call_fsm.png \ - voice_call_full.png \ + $(builddir)/*.png \ $(NULL) msc: \ $(builddir)/mncc_call_fsm.png \ $(builddir)/inter_bsc_ho.png \ $(builddir)/inter_msc_ho.png \ - $(builddir)/voice_call_full.png \ + $(builddir)/voice_call_external_mncc.png \ + $(builddir)/voice_call_internal_mncc.png \ $(builddir)/call_reestablishment.png \ $(NULL) diff --git a/doc/sequence_charts/msc_log_to_ladder.py b/doc/sequence_charts/msc_log_to_ladder.py index 30b6594db..9bfb9c9c2 100755 --- a/doc/sequence_charts/msc_log_to_ladder.py +++ b/doc/sequence_charts/msc_log_to_ladder.py @@ -53,7 +53,7 @@ UE = 'ms' #'ue' MS_UE_UNKNOWN = 'ms' #None MSC = 'msc' MGW = 'mgw' -SIP = 'sip' +MNCC = 'mncc' MO = 'mo' MT = 'mt' @@ -69,7 +69,7 @@ class OutputBase: self.start_with_re = re.compile(start_with_re) def head(self): - self.writeln('# Generated by msc_log_to_ladder.py') + self.writeln('# Generated by osmo-msc.git/doc/sequence_charts/msc_log_to_ladder.py') def tail(self): pass @@ -129,7 +129,7 @@ class OutputLadder(OutputBase): mo_mt = arrow.mo_mt or MO def prepend_mo_mt(name): - if name in ('.', SIP): + if name in ('.', MNCC): return name return '%s%s' % (mo_mt, name) @@ -222,7 +222,7 @@ class OutputMscgen(OutputBase): mo_mt = arrow.mo_mt or MO def prepend_mo_mt(name): - if name in ('.', SIP): + if name in ('.', MNCC): return name return '%s%s' % (mo_mt, name) @@ -371,6 +371,7 @@ class Parse: self.output = output self.linenr = 0 self.rules = [] + self.rules_hit = {} self.seen_udtrace_mncc = False self.callrefs_mo_mt = {} @@ -390,6 +391,7 @@ class Parse: re_str = docstr.splitlines()[0] self.rules.append(Rule(name=member, re_str=re_str, handler=func)) + self.rules_hit[member] = 0 @@ -403,7 +405,7 @@ class Parse: #('moue', 'UE,hNodeB (MO)'), ('momgw', 'MGW for MSC (MO)'), ('momsc', 'MSC (MO)'), - ('sip', 'MNCC to PBX via\nosmo-sip-connector'), + ('mncc', 'MNCC'), ('mtmsc', 'MSC (MT)'), ('mtmgw', 'MGW for MSC (MT)'), ('mtms', 'BSS,MS (MT)\\nhNodeB,UE (MT)'), @@ -448,6 +450,7 @@ class Parse: for rule in self.rules: if rule.match(line): + self.rules_hit[rule.name] = self.rules_hit.get(rule.name, 0) + 1 break RE_DTAP_NAME = re.compile('.*GSM48_MT_([^_]+)_(.+)') @@ -473,7 +476,8 @@ class Parse: dtap = '%s %s' % m.groups() if 'IMSI_DETACH_IND' in dtap: - # detecting IMSI Detach separately + # detecting IMSI Detach separately, because this log line does not contain the IMSI. + # By using the rule_imsi_detach(), we can accurately put it on the MO/MT side. return True if l3type == 'NONE' and not tx and dtap.endswith('PAG_RESP'): @@ -497,6 +501,7 @@ class Parse: imsi = m.group(1) e = MO_MT_UNKNOWN self.diagram.add_line(Arrow(e, MS_UE_UNKNOWN, '>', MSC, 'IMSI Detach', imsi=imsi)) + return True def rule_mgcp_tx(self, m): r'.*mgw-endp\([^)]*:([^:]+):([^:]+)\).* (rtpbridge[^ ]+) .* RTP_TO_(RAN|CN)( CI=([^:]+)|): ([^ :]+).*: Sending' @@ -512,19 +517,20 @@ class Parse: return True def rule_mgcp_rx(self, m): - r'.*mgw-endp\([^)]*:([^:]+):([^:]+)\).* (rtpbridge[^ ]+) .* RTP_TO_(RAN|CN)( CI=([^:]+)|).*: received successful response to ([^:]+): (.*)' - ran, l3type, endp, rtp_to, cond_ci, ci, verb, details = m.groups() + r'.*mgw-endp\(([^)]+):([^:)]+):([^:)]+)\).* (rtpbridge[^ ]+) .* RTP_TO_(RAN|CN)( CI=([^:]+)|).*: received successful response to ([^:]+): RTP=[^:]+:([0-9.:]+)' + subscr, ran_conn, l3type, endp, rtp_to, cond_ci, ci, verb, rtp = m.groups() e = mo_mt_from_l3type(l3type) endp = self.mask_value('EP', endp) ci = self.mask_value('CI', ci) ci_str = '' if ci: ci_str = ' %s' % ci - self.diagram.add_line(Arrow(e, MGW, '>', MSC, 'for %s: %s OK\\n%s%s' % (rtp_to, verb, endp, ci_str))) + rtp = self.mask_value('IP:port', rtp) + self.diagram.add_line(Arrow(e, MGW, '>', MSC, 'for %s: %s OK\\n%s%s %s' % (rtp_to, verb, endp, ci_str, rtp))) return True def rule_ran_tx(self, m): - r'.*msc_a\(([^)]*):([^:]+):([^:]+)\).* RAN encode: ([^: ]+): (.+)$' + r'.*msc_a\(([^)]+):([^:)]+):([^:)]+)\).* RAN encode: ([^: ]+): (.+)$' subscr, ran_conn, l3type, ran_type, msg_type = m.groups() @@ -538,8 +544,6 @@ class Parse: # skip 'RAB Assignment: rab_id=1, rtp=192.168.178.66:50008, use_x213_nsap=1' return True - if l3type == 'NONE': - return True e = mo_mt_from_l3type(l3type) @@ -555,7 +559,7 @@ class Parse: return True def rule_ran_rx(self, m): - r'.*msc_a\(([^)]*):([^:]+):([^:]+)\).* RAN decode: ([^: ]+) (.+)$' + r'.*msc_a\(([^)]+):([^:)]+):([^:)]+)\).* RAN decode: ([^: ]+) (.+)$' subscr, ran_conn, l3type, ran_type, msg_type = m.groups() @@ -563,8 +567,6 @@ class Parse: # will get DTAP details from rule_dtap() instead, not from BSSMAP logging return True - if l3type == 'NONE': - return True e = mo_mt_from_l3type(l3type) @@ -589,7 +591,7 @@ class Parse: self.diagram.add_line(Arrow(e, MSC, '<>', '.', 'CC state:\\n%s' % to_state)) return True - def rule_log_mncc(self, m): + def rule_log_mncc_no_rtp(self, m): r'.*trans\(CC[^) ]* [^ )]+:([^:)]+) callref-([^ ]+) [^)]+\) (tx|rx) (MNCC_[^ ]*)$' l3type, callref_hex, tx_rx, mncc_msg = m.groups() @@ -605,12 +607,34 @@ class Parse: except: e = MT - self.diagram.add_line(Arrow(e, MSC, '>' if tx else '<', 'sip', mncc_msg)) + self.diagram.add_line(Arrow(e, MSC, '>' if tx else '<', 'mncc', mncc_msg)) + return True + + def rule_log_mncc_with_rtp(self, m): + r'.*trans\(CC[^) ]* [^ )]+:([^:)]+) callref-([^ ]+) [^)]+\) (tx|rx) (MNCC_[^ ]*) \(RTP=([^){]+)(|{.*})\)$' + l3type, callref_hex, tx_rx, mncc_msg, rtp, codec = m.groups() + + if self.seen_udtrace_mncc: + # If no udtrace is present, take the MNCC logging. + # But if there is udtrace logging available, we should not duplicate those MNCC lines. + return True + + tx = (tx_rx == 'tx') + + try: + e = self.callrefs_mo_mt.get(callref_hex, MT) + except: + e = MT + + rtp = self.mask_value('IP:port', rtp) + self.diagram.add_line(Arrow(e, MSC, '>' if tx else '<', 'mncc', f'{mncc_msg}\\n{rtp}')) return True RE_MNCC_RTP = re.compile(' ip := ([^, ]+), rtp_port := ([0-9]+),') RE_MNCC_CALLREF = re.compile(' callref := ([^ ,]+), ') + # detecting MNCC with udtrace has the advantage that we also get an indication whether RTP information is + # present def rule_udtrace_mncc(self, m): r'.*(write|recv).* (Tx|Rx): \{ msg_type := ([^ ]+) .* u := \{ (.*) \} \}$' write_recv, tx_rx, msg_type, u = m.groups() @@ -650,7 +674,7 @@ class Parse: descr = '%s\\n%s' % (descr, rtp_info) break - self.diagram.add_line(Arrow(e, MSC, '>' if tx else '<', 'sip', descr)) + self.diagram.add_line(Arrow(e, MSC, '>' if tx else '<', 'mncc', descr)) return True def rule_cc_timer(self, m): @@ -680,6 +704,9 @@ def translate(inf, outf, cmdline): break; parse.add_line(line) parse.end() + if cmdline.verbose: + for name, count in parse.rules_hit.items(): + print(f" {name}: {count}") def open_output(inf, cmdline): if cmdline.output_file == '-': @@ -716,6 +743,8 @@ if __name__ == '__main__': ' present. This makes the output reproducible across various logs.') parser.add_argument('-s', '--start-with', dest='start_with_re', default=None, help='Skip until the first message with this label (regex), e.g. -s "CC SETUP"') + parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', + help='show some debug info, like which regex rules were hit and which were not.') cmdline = parser.parse_args() diff --git a/doc/sequence_charts/voice_call_full.msc b/doc/sequence_charts/voice_call_external_mncc.msc index 75fcef2ef..94cedee67 100644 --- a/doc/sequence_charts/voice_call_full.msc +++ b/doc/sequence_charts/voice_call_external_mncc.msc @@ -1,65 +1,68 @@ -# Generated by msc_log_to_ladder.py +# Generated by osmo-msc.git/doc/sequence_charts/msc_log_to_ladder.py msc { hscale="3"; -moms[label="MS,BSS (MO)\nUE,hNodeB (MO)"],momgw[label="MGW for MSC (MO)"],momsc[label="MSC (MO)"],sip[label="MNCC to PBX via\nosmo-sip-connector"],mtmsc[label="MSC (MT)"],mtmgw[label="MGW for MSC (MT)"],mtms[label="BSS,MS (MT)\nhNodeB,UE (MT)"]; +moms[label="MS,BSS (MO)\nUE,hNodeB (MO)"],momgw[label="MGW for MSC (MO)"],momsc[label="MSC (MO)"],mncc[label="MNCC"],mtmsc[label="MSC (MT)"],mtmgw[label="MGW for MSC (MT)"],mtms[label="BSS,MS (MT)\nhNodeB,UE (MT)"]; +moms =>> momsc [label="(BSSMAP) Complete Layer 3 Information"]; moms =>> momsc [label="MM CM_SERV_REQ"]; moms <<= momsc [label="MM AUTH_REQ"]; moms =>> momsc [label="MM AUTH_RESP"]; moms <<= momsc [label="(BSSMAP) CIPHER_MODE_COMMAND"]; moms =>> momsc [label="(BSSMAP) Ciphering Mode Complete"]; +moms <<= momsc [label="(BSSMAP) COMMON_ID"]; moms =>> momsc [label="RR CIPH_M_COMPL"]; moms =>> momsc [label="CC SETUP"]; momsc note momsc [label="CC starts guard timer (180s)"]; momsc abox momsc [label="CC state:\nINITIATED"]; -momsc =>> sip [label="MNCC_SETUP_IND"]; -momsc <<= sip [label="MNCC_RTP_CREATE"]; -momgw <<= momsc [label="for RAN: CRCX\nrtpbridge/*@msc"]; -momgw =>> momsc [label="for RAN: CRCX OK\nEP-1 CI-1"]; +momgw <<= momsc [label="for CN: CRCX\nrtpbridge/*@msc"]; +momgw =>> momsc [label="for CN: CRCX OK\nEP-1 CI-1 IP:port-1"]; +momsc =>> mncc [label="MNCC_SETUP_IND\nIP:port-1"]; +momgw <<= momsc [label="for RAN: CRCX\nEP-1"]; +momsc <<= mncc [label="MNCC_RTP_CREATE"]; +momgw =>> momsc [label="for RAN: CRCX OK\nEP-1 CI-2 IP:port-2"]; moms <<= momsc [label="(BSSMAP) ASSIGNMENT_COMMAND"]; moms =>> momsc [label="(BSSMAP) Assignment Complete"]; -momgw <<= momsc [label="for RAN: MDCX\nEP-1 CI-1"]; -momgw =>> momsc [label="for RAN: MDCX OK\nEP-1 CI-1"]; -momgw <<= momsc [label="for CN: CRCX\nEP-1"]; -momgw =>> momsc [label="for CN: CRCX OK\nEP-1 CI-2"]; -momsc =>> sip [label="MNCC_RTP_CREATE\nIP:port-1"]; -momsc <<= sip [label="MNCC_CALL_PROC_REQ"]; +momgw <<= momsc [label="for RAN: MDCX\nEP-1 CI-2"]; +momsc =>> mncc [label="MNCC_RTP_CREATE\nIP:port-1"]; +momsc <<= mncc [label="MNCC_CALL_PROC_REQ"]; momsc note momsc [label="CC stops guard timer"]; momsc note momsc [label="CC starts guard timer (180s)"]; momsc abox momsc [label="CC state:\nMO_CALL_PROC"]; moms <<= momsc [label="CC CALL_PROC"]; -mtmsc <<= sip [label="MNCC_SETUP_REQ"]; +mtmsc <<= mncc [label="MNCC_SETUP_REQ\nIP:port-1"]; mtms <<= mtmsc [label="Paging"]; +momgw =>> momsc [label="for RAN: MDCX OK\nEP-1 CI-2 IP:port-2"]; +mtms =>> mtmsc [label="(BSSMAP) Complete Layer 3 Information"]; mtms =>> mtmsc [label="RR PAG_RESP"]; mtms <<= mtmsc [label="MM AUTH_REQ"]; -mtms =>> mtmsc [label="MM NULL"]; mtms =>> mtmsc [label="MM AUTH_RESP"]; -mtms <<= mtmsc [label="(RANAP) SecurityModeCommand"]; -mtms =>> mtmsc [label="(RANAP) SecurityModeControl successfulOutcome"]; -mtms <<= mtmsc [label="(RANAP) CommonId"]; +mtms <<= mtmsc [label="(BSSMAP) CIPHER_MODE_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Ciphering Mode Complete"]; +mtms <<= mtmsc [label="(BSSMAP) COMMON_ID"]; mtmsc note mtmsc [label="CC starts timer T303 (30s)"]; mtmsc abox mtmsc [label="CC state:\nCALL_PRESENT"]; mtms <<= mtmsc [label="CC SETUP"]; +mtms =>> mtmsc [label="RR CIPH_M_COMPL"]; mtms =>> mtmsc [label="CC CALL_CONF"]; mtmsc note mtmsc [label="CC stops timer T303"]; mtmsc note mtmsc [label="CC starts timer T310 (30s)"]; +mtmgw <<= mtmsc [label="for CN: CRCX\nrtpbridge/*@msc"]; mtmsc abox mtmsc [label="CC state:\nMO_TERM_CALL_CONF"]; -mtmgw <<= mtmsc [label="for RAN: CRCX\nrtpbridge/*@msc"]; -mtmsc =>> sip [label="MNCC_CALL_CONF_IND"]; -mtmsc <<= sip [label="MNCC_RTP_CREATE"]; -mtmgw =>> mtmsc [label="for RAN: CRCX OK\nEP-2 CI-3"]; -mtms <<= mtmsc [label="(RANAP) RAB AssignmentRequest"]; -mtms =>> mtmsc [label="(RANAP) RAB Assignment Response"]; -mtmgw <<= mtmsc [label="for RAN: MDCX\nEP-2 CI-3"]; -mtmgw =>> mtmsc [label="for RAN: MDCX OK\nEP-2 CI-3"]; -mtmgw <<= mtmsc [label="for CN: CRCX\nEP-2"]; -mtmgw =>> mtmsc [label="for CN: CRCX OK\nEP-2 CI-4"]; -mtmsc =>> sip [label="MNCC_RTP_CREATE\nIP:port-2"]; +mtmsc =>> mncc [label="MNCC_CALL_CONF_IND"]; +mtmsc <<= mncc [label="MNCC_RTP_CREATE"]; +mtmgw =>> mtmsc [label="for CN: CRCX OK\nEP-2 CI-3 IP:port-3"]; +mtmgw <<= mtmsc [label="for RAN: CRCX\nEP-2"]; +mtmgw =>> mtmsc [label="for RAN: CRCX OK\nEP-2 CI-4 IP:port-4"]; +mtms <<= mtmsc [label="(BSSMAP) ASSIGNMENT_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Assignment Complete"]; +mtmgw <<= mtmsc [label="for RAN: MDCX\nEP-2 CI-4"]; +mtmsc =>> mncc [label="MNCC_RTP_CREATE\nIP:port-3"]; +mtmgw =>> mtmsc [label="for RAN: MDCX OK\nEP-2 CI-4 IP:port-4"]; mtms =>> mtmsc [label="CC ALERTING"]; mtmsc note mtmsc [label="CC stops timer T310"]; mtmsc note mtmsc [label="CC starts timer T301 (180s)"]; mtmsc abox mtmsc [label="CC state:\nCALL_RECEIVED"]; -mtmsc =>> sip [label="MNCC_ALERT_IND"]; -momsc <<= sip [label="MNCC_ALERT_REQ"]; +mtmsc =>> mncc [label="MNCC_ALERT_IND\nIP:port-3"]; +momsc <<= mncc [label="MNCC_ALERT_REQ"]; momsc note momsc [label="CC stops guard timer"]; momsc note momsc [label="CC starts guard timer (180s)"]; momsc abox momsc [label="CC state:\nCALL_DELIVERED"]; @@ -67,57 +70,55 @@ moms <<= momsc [label="CC ALERTING"]; mtms =>> mtmsc [label="CC CONNECT"]; mtmsc note mtmsc [label="CC stops timer T301"]; mtmsc abox mtmsc [label="CC state:\nCONNECT_REQUEST"]; -mtmsc =>> sip [label="MNCC_SETUP_CNF"]; -mtmsc <<= sip [label="MNCC_RTP_CONNECT\nIP:port-1"]; -mtmgw <<= mtmsc [label="for CN: MDCX\nEP-2 CI-4"]; -mtmsc <<= sip [label="MNCC_SETUP_COMPL_REQ"]; +mtmsc =>> mncc [label="MNCC_SETUP_CNF\nIP:port-3"]; +mtmsc <<= mncc [label="MNCC_RTP_CONNECT\nIP:port-1"]; +mtmgw <<= mtmsc [label="for CN: MDCX\nEP-2 CI-3"]; +mtmsc <<= mncc [label="MNCC_SETUP_COMPL_REQ"]; mtmsc note mtmsc [label="CC starts guard timer (180s)"]; mtmsc abox mtmsc [label="CC state:\nACTIVE"]; mtmsc note mtmsc [label="CC stops guard timer"]; mtms <<= mtmsc [label="CC CONNECT_ACK"]; -mtmgw =>> mtmsc [label="for CN: MDCX OK\nEP-2 CI-4"]; -momsc <<= sip [label="MNCC_RTP_CONNECT\nIP:port-2"]; -momgw <<= momsc [label="for CN: MDCX\nEP-1 CI-2"]; -momsc <<= sip [label="MNCC_SETUP_RSP"]; +momsc <<= mncc [label="MNCC_RTP_CONNECT\nIP:port-3"]; +momgw <<= momsc [label="for CN: MDCX\nEP-1 CI-1"]; +momsc <<= mncc [label="MNCC_SETUP_RSP"]; momsc note momsc [label="CC stops guard timer"]; momsc note momsc [label="CC starts guard timer (180s)"]; momsc note momsc [label="CC starts timer T313 (30s)"]; momsc abox momsc [label="CC state:\nCONNECT_IND"]; moms <<= momsc [label="CC CONNECT"]; -momgw =>> momsc [label="for CN: MDCX OK\nEP-1 CI-2"]; +mtmgw =>> mtmsc [label="for CN: MDCX OK\nEP-2 CI-3 IP:port-3"]; +momgw =>> momsc [label="for CN: MDCX OK\nEP-1 CI-1 IP:port-1"]; moms =>> momsc [label="CC CONNECT_ACK"]; momsc note momsc [label="CC stops timer T313"]; momsc abox momsc [label="CC state:\nACTIVE"]; momsc note momsc [label="CC stops guard timer"]; -momsc =>> sip [label="MNCC_SETUP_COMPL_IND"]; +momsc =>> mncc [label="MNCC_SETUP_COMPL_IND"]; moms =>> momsc [label="CC DISCONNECT"]; momsc abox momsc [label="CC state:\nDISCONNECT_IND"]; -momsc =>> sip [label="MNCC_DISC_IND"]; -momsc <<= sip [label="MNCC_REL_REQ"]; +momsc =>> mncc [label="MNCC_DISC_IND"]; +momsc <<= mncc [label="MNCC_REL_REQ"]; momsc note momsc [label="CC starts guard timer (180s)"]; momsc note momsc [label="CC starts timer T308 (10s)"]; momsc abox momsc [label="CC state:\nRELEASE_REQ"]; moms <<= momsc [label="CC RELEASE"]; -mtmsc <<= sip [label="MNCC_DISC_REQ"]; +mtmsc <<= mncc [label="MNCC_DISC_REQ"]; mtmsc note mtmsc [label="CC starts guard timer (180s)"]; mtmsc note mtmsc [label="CC starts timer T306 (30s)"]; mtmsc abox mtmsc [label="CC state:\nDISCONNECT_IND"]; mtms <<= mtmsc [label="CC DISCONNECT"]; +mtms =>> mtmsc [label="CC RELEASE"]; +mtmsc note mtmsc [label="CC stops timer T306"]; +mtms <<= mtmsc [label="CC RELEASE_COMPL"]; +mtmsc =>> mncc [label="MNCC_REL_IND"]; +mtmsc abox mtmsc [label="CC state:\nNULL"]; +mtmsc note mtmsc [label="CC stops guard timer"]; +mtms <<= mtmsc [label="(BSSMAP) CLEAR_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Clear Complete"]; moms =>> momsc [label="CC RELEASE_COMPL"]; momsc note momsc [label="CC stops timer T308"]; +momsc =>> mncc [label="MNCC_REL_CNF"]; momsc abox momsc [label="CC state:\nNULL"]; momsc note momsc [label="CC stops guard timer"]; moms <<= momsc [label="(BSSMAP) CLEAR_COMMAND"]; -momsc =>> sip [label="MNCC_REL_CNF"]; moms =>> momsc [label="(BSSMAP) Clear Complete"]; -mtms =>> mtmsc [label="CC RELEASE"]; -mtmsc note mtmsc [label="CC stops timer T306"]; -mtms <<= mtmsc [label="CC RELEASE_COMPL"]; -mtmsc abox mtmsc [label="CC state:\nNULL"]; -mtmsc note mtmsc [label="CC stops guard timer"]; -mtms <<= mtmsc [label="(RANAP) Iu Release"]; -mtmsc =>> sip [label="MNCC_REL_IND"]; -mtms =>> mtmsc [label="(RANAP) Iu Release successfulOutcome"]; -moms =>> momsc [label="IMSI Detach"]; -mtms =>> mtmsc [label="IMSI Detach"]; } diff --git a/doc/sequence_charts/voice_call_internal_mncc.msc b/doc/sequence_charts/voice_call_internal_mncc.msc new file mode 100644 index 000000000..898c1ff9a --- /dev/null +++ b/doc/sequence_charts/voice_call_internal_mncc.msc @@ -0,0 +1,129 @@ +# Generated by osmo-msc.git/doc/sequence_charts/msc_log_to_ladder.py +msc { +hscale="3"; +moms[label="MS,BSS (MO)\nUE,hNodeB (MO)"],momgw[label="MGW for MSC (MO)"],momsc[label="MSC (MO)"],mncc[label="MNCC"],mtmsc[label="MSC (MT)"],mtmgw[label="MGW for MSC (MT)"],mtms[label="BSS,MS (MT)\nhNodeB,UE (MT)"]; +moms =>> momsc [label="(BSSMAP) Complete Layer 3 Information"]; +moms =>> momsc [label="MM CM_SERV_REQ"]; +moms <<= momsc [label="MM AUTH_REQ"]; +moms =>> momsc [label="MM AUTH_RESP"]; +moms <<= momsc [label="(BSSMAP) CIPHER_MODE_COMMAND"]; +moms =>> momsc [label="(BSSMAP) Ciphering Mode Complete"]; +moms <<= momsc [label="(BSSMAP) COMMON_ID"]; +moms =>> momsc [label="RR CIPH_M_COMPL"]; +moms =>> momsc [label="CC SETUP"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +momsc abox momsc [label="CC state:\nINITIATED"]; +momgw <<= momsc [label="for CN: CRCX\nrtpbridge/*@msc"]; +momgw =>> momsc [label="for CN: CRCX OK\nEP-1 CI-1 IP:port-1"]; +momsc =>> mncc [label="MNCC_SETUP_IND\nIP:port-1"]; +momsc <<= mncc [label="MNCC_CALL_PROC_REQ"]; +momsc note momsc [label="CC stops guard timer"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +momsc abox momsc [label="CC state:\nMO_CALL_PROC"]; +moms <<= momsc [label="CC CALL_PROC"]; +momsc <<= mncc [label="MNCC_LCHAN_MODIFY"]; +momsc note momsc [label="CC stops guard timer"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +mtmsc <<= mncc [label="MNCC_SETUP_REQ\nIP:port-1"]; +mtms <<= mtmsc [label="Paging"]; +momgw <<= momsc [label="for RAN: CRCX\nEP-1"]; +momgw =>> momsc [label="for RAN: CRCX OK\nEP-1 CI-2 IP:port-2"]; +moms <<= momsc [label="(BSSMAP) ASSIGNMENT_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Complete Layer 3 Information"]; +mtms =>> mtmsc [label="RR PAG_RESP"]; +mtms <<= mtmsc [label="MM AUTH_REQ"]; +moms =>> momsc [label="(BSSMAP) Assignment Complete"]; +momgw <<= momsc [label="for RAN: MDCX\nEP-1 CI-2"]; +momsc =>> mncc [label="MNCC_RTP_CREATE\nIP:port-1"]; +momgw =>> momsc [label="for RAN: MDCX OK\nEP-1 CI-2 IP:port-2"]; +mtms =>> mtmsc [label="MM AUTH_RESP"]; +mtms <<= mtmsc [label="(BSSMAP) CIPHER_MODE_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Ciphering Mode Complete"]; +mtms <<= mtmsc [label="(BSSMAP) COMMON_ID"]; +mtmsc note mtmsc [label="CC starts timer T303 (30s)"]; +mtmsc abox mtmsc [label="CC state:\nCALL_PRESENT"]; +mtms <<= mtmsc [label="CC SETUP"]; +mtms =>> mtmsc [label="RR CIPH_M_COMPL"]; +mtms =>> mtmsc [label="CC CALL_CONF"]; +mtmsc note mtmsc [label="CC stops timer T303"]; +mtmsc note mtmsc [label="CC starts timer T310 (30s)"]; +mtmgw <<= mtmsc [label="for CN: CRCX\nrtpbridge/*@msc"]; +mtmsc abox mtmsc [label="CC state:\nMO_TERM_CALL_CONF"]; +mtmsc =>> mncc [label="MNCC_CALL_CONF_IND"]; +mtmsc <<= mncc [label="MNCC_LCHAN_MODIFY"]; +mtmsc note mtmsc [label="CC starts guard timer (180s)"]; +mtmgw =>> mtmsc [label="for CN: CRCX OK\nEP-2 CI-3 IP:port-3"]; +mtmgw <<= mtmsc [label="for RAN: CRCX\nEP-2"]; +mtmgw =>> mtmsc [label="for RAN: CRCX OK\nEP-2 CI-4 IP:port-4"]; +mtms <<= mtmsc [label="(BSSMAP) ASSIGNMENT_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Assignment Complete"]; +mtmgw <<= mtmsc [label="for RAN: MDCX\nEP-2 CI-4"]; +mtmsc =>> mncc [label="MNCC_RTP_CREATE\nIP:port-3"]; +mtmgw =>> mtmsc [label="for RAN: MDCX OK\nEP-2 CI-4 IP:port-4"]; +mtms =>> mtmsc [label="CC ALERTING"]; +mtmsc note mtmsc [label="CC stops timer T310"]; +mtmsc note mtmsc [label="CC starts timer T301 (180s)"]; +mtmsc abox mtmsc [label="CC state:\nCALL_RECEIVED"]; +mtmsc =>> mncc [label="MNCC_ALERT_IND\nIP:port-3"]; +momsc <<= mncc [label="MNCC_ALERT_REQ\nIP:port-3"]; +momsc note momsc [label="CC stops guard timer"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +momsc abox momsc [label="CC state:\nCALL_DELIVERED"]; +momgw <<= momsc [label="for CN: MDCX\nEP-1 CI-1"]; +moms <<= momsc [label="CC ALERTING"]; +momgw =>> momsc [label="for CN: MDCX OK\nEP-1 CI-1 IP:port-1"]; +mtms =>> mtmsc [label="CC CONNECT"]; +mtmsc note mtmsc [label="CC stops timer T301"]; +mtmsc abox mtmsc [label="CC state:\nCONNECT_REQUEST"]; +mtmsc =>> mncc [label="MNCC_SETUP_CNF\nIP:port-3"]; +mtmsc <<= mncc [label="MNCC_SETUP_COMPL_REQ"]; +mtmsc note mtmsc [label="CC stops guard timer"]; +mtmsc note mtmsc [label="CC starts guard timer (180s)"]; +mtmsc abox mtmsc [label="CC state:\nACTIVE"]; +mtmsc note mtmsc [label="CC stops guard timer"]; +mtms <<= mtmsc [label="CC CONNECT_ACK"]; +momsc <<= mncc [label="MNCC_SETUP_RSP\nIP:port-3"]; +momsc note momsc [label="CC stops guard timer"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +momsc note momsc [label="CC starts timer T313 (30s)"]; +momsc abox momsc [label="CC state:\nCONNECT_IND"]; +moms <<= momsc [label="CC CONNECT"]; +mtmgw <<= mtmsc [label="for CN: MDCX\nEP-2 CI-3"]; +mtmgw =>> mtmsc [label="for CN: MDCX OK\nEP-2 CI-3 IP:port-3"]; +moms =>> momsc [label="CC CONNECT_ACK"]; +momsc note momsc [label="CC stops timer T313"]; +momsc abox momsc [label="CC state:\nACTIVE"]; +momsc note momsc [label="CC stops guard timer"]; +momsc =>> mncc [label="MNCC_SETUP_COMPL_IND"]; +moms =>> momsc [label="CC DISCONNECT"]; +momsc abox momsc [label="CC state:\nDISCONNECT_IND"]; +momsc =>> mncc [label="MNCC_DISC_IND"]; +momsc <<= mncc [label="MNCC_REL_REQ"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +momsc note momsc [label="CC starts timer T308 (10s)"]; +momsc abox momsc [label="CC state:\nRELEASE_REQ"]; +moms <<= momsc [label="CC RELEASE"]; +mtmsc <<= mncc [label="MNCC_DISC_REQ"]; +mtmsc note mtmsc [label="CC starts guard timer (180s)"]; +mtmsc note mtmsc [label="CC starts timer T306 (30s)"]; +mtmsc abox mtmsc [label="CC state:\nDISCONNECT_IND"]; +mtms <<= mtmsc [label="CC DISCONNECT"]; +mtms =>> mtmsc [label="CC RELEASE"]; +mtmsc note mtmsc [label="CC stops timer T306"]; +mtms <<= mtmsc [label="CC RELEASE_COMPL"]; +mtmsc =>> mncc [label="MNCC_REL_IND"]; +momsc <<= mncc [label="MNCC_REL_REQ"]; +momsc note momsc [label="CC stops guard timer"]; +momsc note momsc [label="CC starts guard timer (180s)"]; +mtmsc abox mtmsc [label="CC state:\nNULL"]; +mtmsc note mtmsc [label="CC stops guard timer"]; +mtms <<= mtmsc [label="(BSSMAP) CLEAR_COMMAND"]; +mtms =>> mtmsc [label="(BSSMAP) Clear Complete"]; +moms =>> momsc [label="CC RELEASE_COMPL"]; +momsc note momsc [label="CC stops timer T308"]; +momsc =>> mncc [label="MNCC_REL_CNF"]; +momsc abox momsc [label="CC state:\nNULL"]; +momsc note momsc [label="CC stops guard timer"]; +moms <<= momsc [label="(BSSMAP) CLEAR_COMMAND"]; +moms =>> momsc [label="(BSSMAP) Clear Complete"]; +} diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am index 4d8063711..b07a00459 100644 --- a/include/osmocom/Makefile.am +++ b/include/osmocom/Makefile.am @@ -1,3 +1,4 @@ SUBDIRS = \ msc \ + smpp \ $(NULL) diff --git a/include/osmocom/msc/Makefile.am b/include/osmocom/msc/Makefile.am index faf1048dc..a940056fc 100644 --- a/include/osmocom/msc/Makefile.am +++ b/include/osmocom/msc/Makefile.am @@ -1,6 +1,10 @@ noinst_HEADERS = \ call_leg.h \ cell_id_list.h \ + codec_filter.h \ + codec_mapping.h \ + csd_bs.h \ + csd_filter.h \ db.h \ debug.h \ e_link.h \ @@ -21,6 +25,7 @@ noinst_HEADERS = \ msc_a_remote.h \ msc_common.h \ msc_ho.h \ + msc_vgcs.h \ msc_i.h \ msc_i_remote.h \ msc_roles.h \ @@ -45,10 +50,12 @@ noinst_HEADERS = \ sgs_vty.h \ signal.h \ silent_call.h \ - smpp.h \ sms_queue.h \ transaction.h \ + transaction_cc.h \ vlr.h \ vlr_sgs.h \ vty.h \ + asci_gcr.h \ + asci_vty.h \ $(NULL) diff --git a/include/osmocom/msc/asci_gcr.h b/include/osmocom/msc/asci_gcr.h new file mode 100644 index 000000000..f2160c1e0 --- /dev/null +++ b/include/osmocom/msc/asci_gcr.h @@ -0,0 +1,55 @@ +/* Group Call Register (GCR) */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ +#pragma once + +/* Group Call Register */ +struct gcr { + struct llist_head list; + enum trans_type trans_type; + char group_id[9]; + uint16_t timeout; + bool mute_talker; + struct llist_head bss_list; +}; + +struct gcr_bss { + struct llist_head list; + int pc; + struct llist_head cell_list; +}; + +struct gcr_cell { + struct llist_head list; + uint16_t cell_id; +}; + +struct gcr_cell *gcr_add_cell(struct gcr_bss *bss, uint16_t cell_id); +struct gcr_cell *gcr_find_cell(struct gcr_bss *bss, uint16_t cell_id); +void gcr_rm_cell(struct gcr_bss *bss, uint16_t cell_id); +struct gcr_bss *gcr_add_bss(struct gcr *gcr, int pc); +struct gcr_bss *gcr_find_bss(struct gcr *gcr, int pc); +void gcr_rm_bss(struct gcr *gcr, int pc); +struct gcr *gcr_create(struct gsm_network *gsmnet, enum trans_type trans_type, const char *group_id); +void gcr_destroy(struct gcr *gcr); +struct gcr *gcr_by_group_id(struct gsm_network *gsmnet, enum trans_type trans_type, const char *group_id); +struct gcr *gcr_by_callref(struct gsm_network *gsmnet, enum trans_type trans_type, uint32_t callref); diff --git a/include/osmocom/msc/asci_vty.h b/include/osmocom/msc/asci_vty.h new file mode 100644 index 000000000..5fe11f6f5 --- /dev/null +++ b/include/osmocom/msc/asci_vty.h @@ -0,0 +1,25 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ + +#pragma once + +void asci_vty_init(struct gsm_network *msc_network); diff --git a/include/osmocom/msc/call_leg.h b/include/osmocom/msc/call_leg.h index a225b6683..c7d3b9739 100644 --- a/include/osmocom/msc/call_leg.h +++ b/include/osmocom/msc/call_leg.h @@ -12,6 +12,7 @@ struct gsm_network; struct gsm_trans; struct rtp_stream; enum rtp_direction; +struct sdp_audio_codecs; extern struct osmo_tdef g_mgw_tdefs[]; @@ -74,7 +75,8 @@ int call_leg_local_bridge(struct call_leg *cl1, uint32_t call_id1, struct gsm_tr int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans); int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans, - const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known); + const struct sdp_audio_codecs *codecs_if_known, + const struct osmo_sockaddr_str *remote_addr_if_known); struct osmo_sockaddr_str *call_leg_local_ip(struct call_leg *cl, enum rtp_direction dir); void call_leg_rtp_stream_gone(struct call_leg *cl, struct rtp_stream *rtps); diff --git a/include/osmocom/msc/cell_id_list.h b/include/osmocom/msc/cell_id_list.h index 83d05f5da..4c0c6eac4 100644 --- a/include/osmocom/msc/cell_id_list.h +++ b/include/osmocom/msc/cell_id_list.h @@ -1,6 +1,6 @@ /* Manage a list of struct gsm0808_cell_id */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr @@ -16,10 +16,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. */ #pragma once diff --git a/include/osmocom/msc/codec_filter.h b/include/osmocom/msc/codec_filter.h new file mode 100644 index 000000000..da4a67e04 --- /dev/null +++ b/include/osmocom/msc/codec_filter.h @@ -0,0 +1,57 @@ +/* Filter/overlay codec selections for a voice call, across MS, RAN and CN limitations */ +/* + * (C) 2019-2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + */ +#pragma once + +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/mncc.h> +#include <osmocom/mgcp_client/mgcp_client.h> + +#include <osmocom/msc/sdp_msg.h> + +struct gsm0808_speech_codec_list; + +/* Combine various codec selections to obtain a resulting set of codecs allowed by all of them. + * Members reflect the different entities/stages that select codecs in a voice call. + * Call codec_filter_run() and obtain the resulting set of codecs in codec_filter.result. */ +struct codec_filter { + /* The fixed set of codecs available on the RAN type, per definition. */ + struct sdp_audio_codecs ran; + /* The codecs advertised by the MS Bearer Capabilities */ + struct sdp_audio_codecs ms; + /* If known, the set of codecs the current RAN cell allows / has available. + * This may not be available if the BSC does not issue this information early enough. + * Should be ignored if empty. */ + struct sdp_audio_codecs bss; + + /* After a channel was assigned, this reflects the chosen codec. */ + struct sdp_audio_codec assignment; +}; + +void codec_filter_set_ran(struct codec_filter *codec_filter, enum osmo_rat_type ran_type); +void codec_filter_set_bss(struct codec_filter *codec_filter, + const struct gsm0808_speech_codec_list *codec_list_bss_supported); +int codec_filter_run(struct codec_filter *codec_filter, struct sdp_msg *result, const struct sdp_msg *remote); + +int codec_filter_to_str_buf(char *buf, size_t buflen, const struct codec_filter *codec_filter, + const struct sdp_msg *result, const struct sdp_msg *remote); +char *codec_filter_to_str_c(void *ctx, const struct codec_filter *codec_filter, const struct sdp_msg *result, + const struct sdp_msg *remote); +const char *codec_filter_to_str(const struct codec_filter *codec_filter, const struct sdp_msg *result, + const struct sdp_msg *remote); diff --git a/include/osmocom/msc/codec_mapping.h b/include/osmocom/msc/codec_mapping.h new file mode 100644 index 000000000..3b502a913 --- /dev/null +++ b/include/osmocom/msc/codec_mapping.h @@ -0,0 +1,65 @@ +/* Routines for translation between codec representations: SDP, CC/BSSMAP variants, MGCP, MNCC */ +#pragma once + +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/protocol/gsm_08_08.h> +#include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/msc/sdp_msg.h> +#include <osmocom/gsm/mncc.h> + +#define NO_MGCP_CODEC 0xffffffff + +extern const struct gsm_mncc_bearer_cap bearer_cap_empty; + +enum codec_frhr { + CODEC_FRHR_NONE = 0, + CODEC_FRHR_FR, + CODEC_FRHR_HR, +}; + +struct codec_mapping { + /* The sdp.payload_type number in a mapping is not necessarily imperative, but may just reflect the usual + * payload type number for a given codec. */ + struct sdp_audio_codec sdp; + /* The id that mgcp_client.h uses for this codec. Must be set in each mapping, because 0 means PCMU. */ + enum mgcp_codecs mgcp; + /* Nr of used entries in speech_ver[] below. */ + unsigned int speech_ver_count; + /* Entries to add to Speech Version lists when this codec is present, if any. */ + enum gsm48_bcap_speech_ver speech_ver[8]; + /* If applicable, one of GSM_TCHF_FRAME, GSM_TCHF_FRAME_EFR, GSM_TCHH_FRAME, GSM_TCH_FRAME_AMR; or zero. */ + uint32_t mncc_payload_msg_type; + /* Set to true if gsm0808_speech_codec below reflects a meaningful value. */ + bool has_gsm0808_speech_codec; + struct gsm0808_speech_codec gsm0808_speech_codec; + /* If applicable, entries to add to Permitted Speech lists when this codec is present; or zero. */ + enum gsm0808_permitted_speech perm_speech; + /* If applicable, indicator whether this codec can work on a GERAN half-rate lchan, or whether full-rate is + * required. Leave zero when this codec does not apply to GERAN. */ + enum codec_frhr frhr; +}; + +const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_ver speech_ver); +const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0808_speech_codec_type sct); +const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec(const struct gsm0808_speech_codec *sc); +const struct codec_mapping *codec_mapping_by_perm_speech(enum gsm0808_permitted_speech perm_speech); +const struct codec_mapping *codec_mapping_by_subtype_name(const char *subtype_name); +const struct codec_mapping *codec_mapping_by_mgcp_codec(enum mgcp_codecs mgcp); + +int bearer_cap_add_speech_ver(struct gsm_mncc_bearer_cap *bearer_cap, enum gsm48_bcap_speech_ver speech_ver); +int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codec *codec); +int sdp_audio_codecs_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codecs *ac); +int bearer_cap_set_radio(struct gsm_mncc_bearer_cap *bearer_cap); + +struct sdp_audio_codec *sdp_audio_codecs_add_speech_ver(struct sdp_audio_codecs *ac, + enum gsm48_bcap_speech_ver speech_ver); +struct sdp_audio_codec *sdp_audio_codecs_add_mgcp_codec(struct sdp_audio_codecs *ac, enum mgcp_codecs mgcp_codec); +void sdp_audio_codecs_from_bearer_cap(struct sdp_audio_codecs *ac, const struct gsm_mncc_bearer_cap *bc); + +int sdp_audio_codec_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct sdp_audio_codec *codec); +void sdp_audio_codecs_to_speech_codec_list(struct gsm0808_speech_codec_list *cl, const struct sdp_audio_codecs *ac); +void sdp_audio_codecs_from_speech_codec_list(struct sdp_audio_codecs *ac, const struct gsm0808_speech_codec_list *cl); + +int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct sdp_audio_codecs *ac); + +enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct sdp_audio_codec *codec); diff --git a/include/osmocom/msc/csd_bs.h b/include/osmocom/msc/csd_bs.h new file mode 100644 index 000000000..eee869266 --- /dev/null +++ b/include/osmocom/msc/csd_bs.h @@ -0,0 +1,54 @@ +/* 3GPP TS 122.002 Bearer Services */ +#pragma once + +#include <osmocom/gsm/mncc.h> +#include <osmocom/gsm/protocol/gsm_08_08.h> + +enum csd_bs { + CSD_BS_NONE, + + /* 3.1.1.1.2 */ + CSD_BS_21_T_V110_0k3, + CSD_BS_22_T_V110_1k2, + CSD_BS_24_T_V110_2k4, + CSD_BS_25_T_V110_4k8, + CSD_BS_26_T_V110_9k6, + + /* 3.1.1.2.2 */ + CSD_BS_21_NT_V110_0k3, + CSD_BS_22_NT_V110_1k2, + CSD_BS_24_NT_V110_2k4, + CSD_BS_25_NT_V110_4k8, + CSD_BS_26_NT_V110_9k6, + + /* 3.1.2.1.2 */ + CSD_BS_31_T_V110_1k2, + CSD_BS_32_T_V110_2k4, + CSD_BS_33_T_V110_4k8, + CSD_BS_34_T_V110_9k6, + + CSD_BS_MAX, +}; + +struct csd_bs_list { + unsigned int count; + enum csd_bs bs[CSD_BS_MAX]; +}; + +void csd_bs_list_add_bs(struct csd_bs_list *list, enum csd_bs bs); +int csd_bs_list_to_bearer_cap(struct gsm_mncc_bearer_cap *cap, const struct csd_bs_list *list); +void csd_bs_list_from_bearer_cap(struct csd_bs_list *list, const struct gsm_mncc_bearer_cap *cap); + +int csd_bs_to_str_buf(char *buf, size_t buflen, enum csd_bs bs); +char *csd_bs_to_str_c(void *ctx, enum csd_bs bs); +const char *csd_bs_to_str(enum csd_bs bs); + +int csd_bs_list_to_str_buf(char *buf, size_t buflen, const struct csd_bs_list *list); +char *csd_bs_list_to_str_c(void *ctx, const struct csd_bs_list *list); +const char *csd_bs_list_to_str(const struct csd_bs_list *list); + +void csd_bs_list_add_bs(struct csd_bs_list *list, enum csd_bs bs); +void csd_bs_list_remove(struct csd_bs_list *list, enum csd_bs bs); +void csd_bs_list_intersection(struct csd_bs_list *dest, const struct csd_bs_list *other); + +int csd_bs_list_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct csd_bs_list *list); diff --git a/include/osmocom/msc/csd_filter.h b/include/osmocom/msc/csd_filter.h new file mode 100644 index 000000000..51ffff706 --- /dev/null +++ b/include/osmocom/msc/csd_filter.h @@ -0,0 +1,53 @@ +/* Filter/overlay data rates for CSD, across MS, RAN and CN limitations */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Oliver Smith + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + */ +#pragma once + +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/mncc.h> +#include <osmocom/mgcp_client/mgcp_client.h> + +#include <osmocom/msc/csd_bs.h> +#include <osmocom/msc/sdp_msg.h> + +/* Combine various data rate selections to obtain a resulting set allowed by + * all of them. Members reflect the different entities/stages that select data + * rates in CSD. Call csd_filter_run() and obtain the resulting set in + * csd_filter.result. */ +struct csd_filter { + /* The fixed set available on the RAN type, per definition. */ + struct csd_bs_list ran; + /* The services advertised by the MS Bearer Capabilities */ + struct csd_bs_list ms; + /* If known, the set the current RAN cell allows / has available. This + * may not be available if the BSC does not issue this information + * early enough. Should be ignored if empty. */ + struct csd_bs_list bss; + + /* After a channel was assigned, this reflects the chosen BS. */ + enum csd_bs assignment; +}; + +void csd_filter_set_ran(struct csd_filter *filter, enum osmo_rat_type ran_type); +int csd_filter_run(struct csd_filter *filter, struct sdp_msg *result, const struct sdp_msg *remote); + +int csd_filter_to_str_buf(char *buf, size_t buflen, const struct csd_filter *filter, + const struct sdp_msg *result, const struct sdp_msg *remote); +char *csd_filter_to_str_c(void *ctx, const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote); +const char *csd_filter_to_str(const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote); diff --git a/include/osmocom/msc/db.h b/include/osmocom/msc/db.h index d9463a684..fc1781bd6 100644 --- a/include/osmocom/msc/db.h +++ b/include/osmocom/msc/db.h @@ -1,5 +1,6 @@ /* (C) 2008 by Jan Luebbe <jluebbe@debian.org> * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2022 by Harald Welte <laforge@osmocom.org> * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -30,7 +31,7 @@ struct gsm_network; struct gsm_sms; /* one time initialisation */ -int db_init(const char *name); +int db_init(void *ctx, const char *fname, bool enable_sqlite_logging); int db_prepare(void); int db_fini(void); @@ -39,12 +40,12 @@ int db_sms_store(struct gsm_sms *sms); struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id); struct gsm_sms *db_sms_get_next_unsent(struct gsm_network *net, unsigned long long min_sms_id, - unsigned int max_failed); + int max_failed); struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net, const char *last_msisdn, - unsigned int max_failed); + int max_failed); struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub, - unsigned int max_failed); + int max_failed); int db_sms_mark_delivered(struct gsm_sms *sms); int db_sms_inc_deliver_attempts(struct gsm_sms *sms); int db_sms_delete_by_msisdn(const char *msisdn); diff --git a/include/osmocom/msc/debug.h b/include/osmocom/msc/debug.h index 0d08ceb11..9925a3cb0 100644 --- a/include/osmocom/msc/debug.h +++ b/include/osmocom/msc/debug.h @@ -6,6 +6,8 @@ enum { DRLL, DCC, + DBCC, + DGCC, DMM, DRR, DLCLS, @@ -24,5 +26,6 @@ enum { DBSSAP, DSGS, DSS, + DASCI, Debug_LastEntry, }; diff --git a/include/osmocom/msc/gsm_04_08.h b/include/osmocom/msc/gsm_04_08.h index bfc8027db..cd5074eb6 100644 --- a/include/osmocom/msc/gsm_04_08.h +++ b/include/osmocom/msc/gsm_04_08.h @@ -45,6 +45,11 @@ int gsm48_send_rr_app_info(struct msc_a *msc_a, uint8_t apdu_id, uint8_t apdu_le int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_class); int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, uint8_t power_command, uint8_t ho_ref); +void gsm48_cc_rx_setup_cn_local_rtp_port_known(struct gsm_trans *trans); +void gsm48_cc_rx_call_conf_cn_local_rtp_port_known(struct gsm_trans *trans); +int cc_on_cn_local_rtp_port_known(struct gsm_trans *trans); +int cc_on_assignment_done(struct gsm_trans *trans); + int mncc_tx_to_cc(struct gsm_network *net, void *arg); /* convert a ASCII phone number to call-control BCD */ diff --git a/include/osmocom/msc/gsm_04_11.h b/include/osmocom/msc/gsm_04_11.h index 19aaa3a5e..17a31ecdd 100644 --- a/include/osmocom/msc/gsm_04_11.h +++ b/include/osmocom/msc/gsm_04_11.h @@ -28,7 +28,8 @@ int gsm411_send_sms(struct gsm_network *net, int gsm411_send_rp_data(struct gsm_network *net, struct vlr_subscr *vsub, size_t sm_rp_oa_len, const uint8_t *sm_rp_oa, size_t sm_rp_ud_len, const uint8_t *sm_rp_ud, - bool sm_rp_mmts_ind); + bool sm_rp_mmts_ind, const uint8_t *gsup_source_name, + size_t gsup_source_name_len); void gsm411_sapi_n_reject(struct msc_a *msc_a); diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h index 34d42db2b..119f093db 100644 --- a/include/osmocom/msc/gsm_data.h +++ b/include/osmocom/msc/gsm_data.h @@ -16,9 +16,11 @@ #include <osmocom/crypt/utran_cipher.h> #include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/mgcp_client/mgcp_client_pool.h> #include <osmocom/msc/msc_common.h> #include <osmocom/msc/neighbor_ident.h> +#include <osmocom/msc/sms_queue.h> #include "gsm_data_shared.h" #include "osmux.h" @@ -214,8 +216,10 @@ struct gsm_network { struct { struct osmo_tdef *tdefs; - struct mgcp_client_conf conf; - struct mgcp_client *client; + struct mgcp_client_conf *conf; + /* MGW pool, also includes the single MGCP client as fallback if no + * pool is configured. */ + struct mgcp_client_pool *mgw_pool; } mgw; struct { @@ -263,10 +267,17 @@ struct gsm_network { /* Whether to use lcls on the network */ bool lcls_permitted; - char *sms_db_file_path; + /* SMS queue config parameters */ + struct sms_queue_config *sms_queue_cfg; + + /* ASCI feature support */ + struct { + bool enable; + struct llist_head gcr_lists; + } asci; }; -struct osmo_esme; +struct smpp_esme; enum gsm_sms_source_id { SMS_SOURCE_UNKNOWN = 0, @@ -295,7 +306,7 @@ struct gsm_sms { } gsm411; struct { - struct osmo_esme *esme; + struct smpp_esme *esme; uint32_t sequence_nr; int transaction_mode; char msg_id[16]; diff --git a/include/osmocom/msc/gsup_client_mux.h b/include/osmocom/msc/gsup_client_mux.h index 07f17c260..501b81dbe 100644 --- a/include/osmocom/msc/gsup_client_mux.h +++ b/include/osmocom/msc/gsup_client_mux.h @@ -28,6 +28,7 @@ int gsup_client_mux_start(struct gsup_client_mux *gcm, const char *gsup_server_a struct ipaccess_unit *ipa_dev); int gsup_client_mux_tx(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_msg); +void gsup_client_mux_tx_set_source(const struct gsup_client_mux *gcm, struct osmo_gsup_message *gsup_msg); void gsup_client_mux_tx_error_reply(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_orig, enum gsm48_gmm_cause cause); diff --git a/include/osmocom/msc/mncc.h b/include/osmocom/msc/mncc.h index 06a5dccc0..d258630c5 100644 --- a/include/osmocom/msc/mncc.h +++ b/include/osmocom/msc/mncc.h @@ -125,6 +125,14 @@ struct gsm_call { #define MNCC_F_KEYPAD 0x1000 #define MNCC_F_SIGNAL 0x2000 #define MNCC_F_GCR 0x4000 +#define MNCC_F_HIGHL_COMPAT 0x8000 +#define MNCC_F_LOWL_COMPAT 0x10000 + +/* UPDATEME when adding new MNCC_F_* entries above */ +#define MNCC_F_ALL 0x1ffff + +#define GSM_MAX_LOWL_COMPAT 16 /* (18 with TLV) */ +#define GSM_MAX_HIGHL_COMPAT 3 /* (5 with TLV) */ struct gsm_mncc { /* context based information */ @@ -167,6 +175,20 @@ struct gsm_mncc { /* A buffer to contain SDP ('\0' terminated) */ char sdp[1024]; + + /* Additional information that extends current socket interface version. */ + + /* The content requals of Low Layer compatibility IE, described in 3GPP TS 24.008 §10.5.4.18. */ + struct gsm_mncc_lowl_compat { + uint8_t len; + uint8_t compat[GSM_MAX_LOWL_COMPAT]; + } llc; + + /* The content requals of High Layer compatibility IE, described in 3GPP TS 24.008 §10.5.4.16. */ + struct gsm_mncc_highl_compat { + uint8_t len; + uint8_t compat[GSM_MAX_HIGHL_COMPAT]; + } hlc; }; struct gsm_data_frame { @@ -216,7 +238,6 @@ union mncc_msg { const char *get_mncc_name(int value); void mncc_set_cause(struct gsm_mncc *data, int loc, int val); -void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg); /* input from CC code into mncc_builtin */ int int_mncc_recv(struct gsm_network *net, struct msgb *msg); diff --git a/include/osmocom/msc/mncc_call.h b/include/osmocom/msc/mncc_call.h index e887cbe7a..084edd5e1 100644 --- a/include/osmocom/msc/mncc_call.h +++ b/include/osmocom/msc/mncc_call.h @@ -1,6 +1,6 @@ /* Handle an MNCC managed call (external MNCC). */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/include/osmocom/msc/msc_a.h b/include/osmocom/msc/msc_a.h index f94420a01..4099d4cd2 100644 --- a/include/osmocom/msc/msc_a.h +++ b/include/osmocom/msc/msc_a.h @@ -1,6 +1,6 @@ /* MSC-A role: main subscriber management */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -37,12 +37,18 @@ #include <osmocom/msc/neighbor_ident.h> struct ran_infra; +struct vgcs_bss; +struct vgcs_bss_cell; #define MSC_A_USE_LOCATION_UPDATING "lu" #define MSC_A_USE_CM_SERVICE_CC "cm_service_cc" +#define MSC_A_USE_CM_SERVICE_GCC "cm_service_gcc" +#define MSC_A_USE_CM_SERVICE_BCC "cm_service_bcc" #define MSC_A_USE_CM_SERVICE_SMS "cm_service_sms" #define MSC_A_USE_CM_SERVICE_SS "cm_service_ss" #define MSC_A_USE_PAGING_RESPONSE "paging-response" +#define MSC_A_USE_GCC "gcc" +#define MSC_A_USE_BCC "bcc" #define MSC_A_USE_CC "cc" #define MSC_A_USE_SMS "sms" #define MSC_A_USE_SMS_MMTS "sms_mmts" @@ -121,6 +127,9 @@ struct msc_a { * \-------RTP--> (ISUP) <--RTP--> <--RTP--> */ struct { + /* Codec List (BSS Supported) as received during Complete Layer 3 Information */ + struct gsm0808_speech_codec_list compl_l3_codec_list_bss_supported; + /* All of the RTP stream handling */ struct call_leg *call_leg; struct mncc_call *mncc_forwarding_to_remote_ran; @@ -180,7 +189,8 @@ struct msc_a *msc_a_for_vsub(const struct vlr_subscr *vsub, bool valid_conn_only void msc_a_pending_cm_service_req_add(struct msc_a *msc_a, enum osmo_cm_service_type type); unsigned int msc_a_pending_cm_service_req_count(struct msc_a *msc_a, enum osmo_cm_service_type type); void msc_a_pending_cm_service_req_del(struct msc_a *msc_a, enum osmo_cm_service_type type); -bool msc_a_require_ciphering(const struct msc_a *msc_a); +bool msc_a_is_ciphering_to_be_attempted(const struct msc_a *msc_a); +bool msc_a_is_ciphering_required(const struct msc_a *msc_a); #define msc_a_ran_down(A,B,C) \ _msc_a_ran_down(A,B,C, __FILE__, __LINE__) @@ -204,13 +214,18 @@ void msc_a_up_ciph_res(struct msc_a *msc_a, bool success, const char *imeisv); bool msc_a_is_accepted(const struct msc_a *msc_a); bool msc_a_is_establishing_auth_ciph(const struct msc_a *msc_a); +int msc_a_ensure_cn_local_rtp(struct msc_a *msc_a, struct gsm_trans *cc_trans); int msc_a_try_call_assignment(struct gsm_trans *cc_trans); +void msc_a_tx_assignment_cmd(struct msc_a *msc_a); -const char *msc_a_cm_service_type_to_use(enum osmo_cm_service_type cm_service_type); +const char *msc_a_cm_service_type_to_use(struct msc_a *msc_a, enum osmo_cm_service_type cm_service_type); void msc_a_release_cn(struct msc_a *msc_a); void msc_a_release_mo(struct msc_a *msc_a, enum gsm48_gsm_cause gsm_cause); +int msc_a_rx_vgcs_bss(struct vgcs_bss *bss, struct ran_conn *from_conn, struct msgb *msg); +int msc_a_rx_vgcs_cell(struct vgcs_bss_cell *cell, struct ran_conn *from_conn, struct msgb *msg); + int msc_a_ran_decode_cb(struct osmo_fsm_inst *msc_a_fi, void *data, const struct ran_msg *msg); int msc_a_vlr_set_cipher_mode(void *_msc_a, bool umts_aka, bool retrieve_imeisv); diff --git a/include/osmocom/msc/msc_ho.h b/include/osmocom/msc/msc_ho.h index 99956f1e6..aedb622dc 100644 --- a/include/osmocom/msc/msc_ho.h +++ b/include/osmocom/msc/msc_ho.h @@ -1,6 +1,6 @@ /* MSC Handover API */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -31,7 +31,7 @@ #include <osmocom/msc/neighbor_ident.h> #include <osmocom/msc/ran_msg.h> #include <osmocom/msc/mncc_call.h> - +#include <osmocom/msc/sdp_msg.h> struct gsm0808_handover_required; @@ -81,7 +81,7 @@ struct msc_ho_state { struct osmo_sockaddr_str ran_remote_rtp; /* The codec from Handover Request Acknowledge. */ bool codec_present; - enum mgcp_codecs codec; + struct gsm0808_speech_codec codec; /* Inter-MSC voice forwarding via MNCC, to the remote MSC. The Prepare Handover Response sent us the * Handover Number the remote MSC assigned. This is a call to that Handover Number, via PBX. @@ -92,7 +92,7 @@ struct msc_ho_state { struct { /* Saved RTP IP:port and codec in case we need to roll back */ struct osmo_sockaddr_str ran_remote_rtp; - enum mgcp_codecs codec; + struct sdp_audio_codecs codecs; } old_cell; }; diff --git a/include/osmocom/msc/msc_t.h b/include/osmocom/msc/msc_t.h index 39b3abca0..876c11d5e 100644 --- a/include/osmocom/msc/msc_t.h +++ b/include/osmocom/msc/msc_t.h @@ -30,7 +30,7 @@ struct msc_t { struct { struct an_apdu ho_request; struct gsm0808_cell_id cell_id_target; - uint32_t callref; + uint32_t call_id; char handover_number[16]; /* No libosmocore definition for MSISDN_MAXLEN? */ struct call_leg *call_leg; struct mncc_call *mncc_forwarding_to_remote_cn; diff --git a/include/osmocom/msc/msc_vgcs.h b/include/osmocom/msc/msc_vgcs.h new file mode 100644 index 000000000..2b2f45d31 --- /dev/null +++ b/include/osmocom/msc/msc_vgcs.h @@ -0,0 +1,228 @@ +/* Handle a call via VGCS/VBCS (Voice Group/Broadcast Call Service). */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ +#pragma once + +#include <osmocom/msc/transaction.h> + +#define GSM44068_ALLOC_SIZE 2048 +#define GSM44068_ALLOC_HEADROOM 256 + +static inline struct msgb *gsm44068_msgb_alloc_name(const char *name) +{ + return msgb_alloc_headroom(GSM44068_ALLOC_SIZE, GSM44068_ALLOC_HEADROOM, name); +} + +/* VGCS/VBS "call control" connection to each BSS */ +struct vgcs_bss { + struct llist_head list; /* List entry */ + struct llist_head cell_list; /* List of cells */ + struct gsm_trans *trans; /* Back pointer to transaction */ + struct osmo_fsm_inst *fi; /* State machine of each BSS */ + struct ran_conn *conn; /* RAN ("SCCP") connection */ + enum trans_type trans_type; /* Transaction type */ + uint32_t callref; /* Callref */ + int pc; /* Point code for debug purpose */ +}; + +/* VGCS/VBS "resource control" connection to each cell in BSS */ +struct vgcs_bss_cell { + struct llist_head list_bss; /* List entry in vgcs_bss */ + struct llist_head list_mgw; /* List entry in MGW endpoint */ + struct vgcs_bss *bss; /* Back pointer to vgcs_bss */ + struct vgcs_mgw_ep *mgw; /* Back pointer to vgcs_mgw_ep */ + struct osmo_fsm_inst *fi; /* State machine of each cell */ + int cell_id; /* Id of cell (BTS) to use */ + struct ran_conn *conn; /* RAN ("SCCP") connection */ + enum trans_type trans_type; /* Transaction type */ + uint32_t callref; /* Callref */ + int call_id; /* Id of call (used for MGW connections) */ + int pc; /* Point code for debug purpose */ + bool assigned; /* Flags if assignment is complete */ + struct rtp_stream *rtps; /* MGW connection process */ +}; + +/* VGCS/VBS MGW endpoint for each call */ +struct vgcs_mgw_ep { + struct llist_head cell_list; /* List of cells with connections */ + struct llist_head list; /* List entry */ + struct osmo_fsm_inst *fi; /* State machine of each cell */ + struct osmo_mgcpc_ep *mgw_ep; /* MGW endpoint */ +}; + +/* Events for the GCC/BCC state machine. + * There is no primitive definition like MNGCC-* oder MNBCC-* in the standard. */ +enum vgcs_gcc_fsm_event { + /* The network sets up a call. */ + VGCS_GCC_EV_NET_SETUP, + /* The network requests termination. */ + VGCS_GCC_EV_NET_TERM, + /* The user sets up a call. */ + VGCS_GCC_EV_USER_SETUP, + /* The user requests termination. */ + VGCS_GCC_EV_USER_TERM, + /* BSS completed call establishment (all BSCs) */ + VGCS_GCC_EV_BSS_ESTABLISHED, + /* Assignment was completed. */ + VGCS_GCC_EV_BSS_ASSIGN_CPL, + /* Assignment failed. */ + VGCS_GCC_EV_BSS_ASSIGN_FAIL, + /* BSS released call establishment (all BSCs) */ + VGCS_GCC_EV_BSS_RELEASED, + /* Inactivity timeout */ + VGCS_GCC_EV_TIMEOUT, +}; + +/* 3GPP TS 44.068 6.1.2.2 States of GCC/BCC */ +enum vgcs_gcc_fsm_state { + /* No call. Initial state when instance is created. */ + VGCS_GCC_ST_N0_NULL = 0, + /* An MS wants to establish a call. */ + VGCS_GCC_ST_N1_CALL_INITIATED, + /* Call established in at least one cell. */ + VGCS_GCC_ST_N2_CALL_ACTIVE, + /* Channel activation is requested, CONNECT already sent to MS. */ + VGCS_GCC_ST_N3_CALL_EST_PROC, + /* Call termination is requested, waiting for all cells to confirm. */ + VGCS_GCC_ST_N4_TERMINATION_REQ, +}; + +const char *vgcs_bcc_gcc_state_name(struct osmo_fsm_inst *fi); + +/* Events for the VGCS/VBS "call control" state machine */ +enum vgcs_bss_fsm_event { + /* Start a VGCS/VBS call using VGCS/VBS SETUP message */ + VGCS_BSS_EV_SETUP, + /* VGCS/VBS SETUP ACK is received */ + VGCS_BSS_EV_SETUP_ACK, + /* VGCS/VBS SETUP REFUSE is received */ + VGCS_BSS_EV_SETUP_REFUSE, + /* VGCS/VBS ASSIGNMENT complete or failed */ + VGCS_BSS_EV_ACTIVE_OR_FAIL, + /* Talker request */ + VGCS_BSS_EV_UL_REQUEST, + /* Talker established uplink */ + VGCS_BSS_EV_UL_REQUEST_CNF, + /* Talker send app data */ + VGCS_BSS_EV_UL_APP_DATA, + /* Talker send signaling data */ + VGCS_BSS_EV_BSS_DTAP, + /* Talker becomes listener */ + VGCS_BSS_EV_UL_RELEASE, + /* Release channel towards BSS */ + VGCS_BSS_EV_CLEAR, + /* Channel closed from BSS */ + VGCS_BSS_EV_CLOSE, + /* Release is complete */ + VGCS_BSS_EV_RELEASED, +}; + +/* States of the VGCS/VBS "call control" state machine */ +enum vgcs_bss_fsm_state { + /* No call. Initial state when instance is created. */ + VGCS_BSS_ST_NULL = 0, + /* VGCS/VBS SETUP is sent towards BSC */ + VGCS_BSS_ST_SETUP, + /* VGCS/VBS ASSIGNMENT REQUEST is sent towards BSC */ + VGCS_BSS_ST_ASSIGNMENT, + /* VGCS/VBS is establised */ + VGCS_BSS_ST_ACTIVE, + /* CLEAR COMMAND was sent */ + VGCS_BSS_ST_RELEASE, +}; + +/* Events for the VGCS/VBS "resource control" state machine */ +enum vgcs_cell_fsm_event { + /* RTP stream gone */ + VGCS_CELL_EV_RTP_STREAM_GONE, + /* RTP stream remote addr available */ + VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE, + /* RTP stream established */ + VGCS_CELL_EV_RTP_STREAM_ESTABLISHED, + /* Start a VGCS/VBS channel using VGCS/VBS ASSIGNMENT message */ + VGCS_CELL_EV_ASSIGN, + /* VGCS/VBS ASSIGNMENT RESULT is received */ + VGCS_CELL_EV_ASSIGN_RES, + /* VGCS/VBS ASSIGNMENT FAILURE is received */ + VGCS_CELL_EV_ASSIGN_FAIL, + /* Release channel towards BSS */ + VGCS_CELL_EV_CLEAR, + /* Channel closed from BSS */ + VGCS_CELL_EV_CLOSE, + /* Release is complete */ + VGCS_CELL_EV_RELEASED, +}; + +/* States of the VGCS/VBS "resource control" state machine */ +enum vgcs_cell_fsm_state { + /* No call. Initial state when instance is created. */ + VGCS_CELL_ST_NULL = 0, + /* VGCS/VBS ASSIGNMENT REQUEST is sent towards BSC */ + VGCS_CELL_ST_ASSIGNMENT, + /* Channel is establised */ + VGCS_CELL_ST_ACTIVE, + /* CLEAR COMMAND was sent */ + VGCS_CELL_ST_RELEASE, +}; + +/* Events for the VGCS/VBS MGW endpoint state machine */ +enum vgcs_mgw_ep_fsm_event { + /* MGW endpoint gone */ + VGCS_MGW_EP_EV_FREE, + /* Destroy MGW endpoint */ + VGCS_MGW_EP_EV_CLEAR, +}; + +/* States of the VGCS/VBS MGW endpoint state machine */ +enum vgcs_mgw_ep_fsm_state { + VGCS_MGW_EP_ST_NULL = 0, + /* MGW endpoint allocated */ + VGCS_MGW_EP_ST_ACTIVE, +}; + +const char *gsm44068_group_id_string(uint32_t callref); + +struct gcr; + +int gsm44068_rcv_rr(struct msc_a *msc_a, struct msgb *msg); +int gsm44068_rcv_bcc_gcc(struct msc_a *msc_a, struct gsm_trans *trans, struct msgb *msg); +const char *vgcs_vty_initiate(struct gsm_network *gsmnet, struct gcr *gcr); +const char *vgcs_vty_terminate(struct gsm_network *gsmnet, struct gcr *gcr); +void gsm44068_bcc_gcc_trans_free(struct gsm_trans *trans); + +void vgcs_vbs_setup_ack(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_vbs_setup_refuse(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_vbs_assign_result(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg); +void vgcs_vbs_assign_fail(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg); +void vgcs_vbs_queuing_ind(struct vgcs_bss_cell *cell); +void vgcs_uplink_request(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_uplink_request_cnf(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_app_data(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_bss_dtap(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_uplink_release_ind(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_vbs_assign_status(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg); +void vgcs_vbs_clear_req_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg); +void vgcs_vbs_clear_cpl_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg); +void vgcs_vbs_clear_req(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_vbs_clear_cpl(struct vgcs_bss *bss, const struct ran_msg *ran_msg); +void vgcs_vbs_caller_assign_cpl(struct gsm_trans *trans); +void vgcs_vbs_caller_assign_fail(struct gsm_trans *trans); diff --git a/include/osmocom/msc/paging.h b/include/osmocom/msc/paging.h index 4de679df7..f8ebf9e3b 100644 --- a/include/osmocom/msc/paging.h +++ b/include/osmocom/msc/paging.h @@ -40,6 +40,7 @@ struct paging_request { struct paging_request *paging_request_start(struct vlr_subscr *vsub, enum paging_cause cause, paging_cb_t paging_cb, struct gsm_trans *trans, const char *label); +void paging_request_join_vsub(struct vlr_subscr *keep_vsub, struct vlr_subscr *discarding_vsub); void paging_request_remove(struct paging_request *pr); void paging_response(struct msc_a *msc_a); diff --git a/include/osmocom/msc/ran_conn.h b/include/osmocom/msc/ran_conn.h index 7aa50df07..cdaa02652 100644 --- a/include/osmocom/msc/ran_conn.h +++ b/include/osmocom/msc/ran_conn.h @@ -18,9 +18,17 @@ struct ran_conn { uint32_t sccp_conn_id; /* MSC role that this RAN connection belongs to. This will be either an msc_i (currently active - * connection) or an msc_t (transitory new connection during Handover). */ + * connection) or an msc_t (transitory new connection during Handover). + * Used for usual L3 ran_conn to a subscriber. */ struct osmo_fsm_inst *msc_role; + /* For VGCS/VBS, we have additional N connections to BSS. When receiving messages for a group call peer, + * dispatch to the VGCS management. */ + struct { + void *bss; + void *cell; + } vgcs; + bool closing; }; diff --git a/include/osmocom/msc/ran_infra.h b/include/osmocom/msc/ran_infra.h index 38c424f09..262a9c82e 100644 --- a/include/osmocom/msc/ran_infra.h +++ b/include/osmocom/msc/ran_infra.h @@ -4,6 +4,7 @@ #include <osmocom/gsm/gsup.h> #include <osmocom/msc/sccp_ran.h> #include <osmocom/msc/ran_msg.h> +#include <osmocom/msc/sdp_msg.h> struct osmo_tdef; @@ -25,6 +26,10 @@ struct ran_infra { const ran_dec_l2_t ran_dec_l2; const ran_encode_t ran_encode; struct sccp_ran_inst *sri; + /* To always set up the MGW endpoint facing the RAN side with specific codecs, list those here. Otherwise leave + * empty (to use the result of codecs filtering). This exists for IuCS, to always set the MGW endpoint facing + * RAN to IUFP, to decapsulate the IuUP headers. */ + struct sdp_audio_codecs force_mgw_codecs_to_ran; }; extern struct ran_infra msc_ran_infra[]; diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h index 32b24a01f..dc1483cb5 100644 --- a/include/osmocom/msc/ran_msg.h +++ b/include/osmocom/msc/ran_msg.h @@ -69,6 +69,26 @@ enum ran_msg_type { RAN_MSG_HANDOVER_SUCCEEDED, RAN_MSG_HANDOVER_COMPLETE, RAN_MSG_HANDOVER_FAILURE, + RAN_MSG_VGCS_VBS_SETUP, + RAN_MSG_VGCS_VBS_SETUP_ACK, + RAN_MSG_VGCS_VBS_SETUP_REFUSE, + RAN_MSG_VGCS_VBS_ASSIGN_REQ, + RAN_MSG_VGCS_VBS_ASSIGN_RES, + RAN_MSG_VGCS_VBS_ASSIGN_FAIL, + RAN_MSG_VGCS_VBS_QUEUING_IND, + RAN_MSG_UPLINK_REQUEST, + RAN_MSG_UPLINK_REQUEST_ACK, + RAN_MSG_UPLINK_REQUEST_CNF, + RAN_MSG_UPLINK_APPLICATION_DATA, + RAN_MSG_UPLINK_RELEASE_IND, + RAN_MSG_UPLINK_REJECT_CMD, + RAN_MSG_UPLINK_RELEASE_CMD, + RAN_MSG_UPLINK_SEIZED_CMD, + RAN_MSG_VGCS_ADDITIONAL_INFO, + RAN_MSG_VGCS_VBS_AREA_CELL_INFO, + RAN_MSG_VGCS_VBS_ASSIGN_STATUS, + RAN_MSG_VGCS_SMS, + RAN_MSG_NOTIFICATION_DATA, }; extern const struct value_string ran_msg_type_names[]; @@ -89,6 +109,8 @@ struct ran_assignment_command { bool call_id_present; uint32_t call_id; struct osmo_lcls *lcls; + bool callref_present; + struct gsm0808_group_callref callref; }; struct ran_cipher_mode_command { @@ -162,7 +184,8 @@ struct ran_handover_request_ack { struct osmo_sockaddr_str remote_rtp; bool codec_present; - enum mgcp_codecs codec; + struct gsm0808_speech_codec codec; + bool codec_with_iuup; }; struct ran_handover_command { @@ -240,7 +263,8 @@ struct ran_msg { struct { struct osmo_sockaddr_str remote_rtp; bool codec_present; - enum mgcp_codecs codec; + struct gsm0808_speech_codec codec; + bool codec_with_iuup; const struct gsm0808_speech_codec_list *codec_list_bss_supported; bool osmux_present; uint8_t osmux_cid; @@ -268,6 +292,33 @@ struct ran_msg { } handover_failure; struct ran_handover_request handover_request; struct ran_handover_request_ack handover_request_ack; + struct gsm0808_vgcs_vbs_setup vgcs_vbs_setup; + struct gsm0808_vgcs_vbs_setup_ack vgcs_vbs_setup_ack; + struct { + enum gsm0808_cause cause; + } vgcs_vbs_setup_refuse; + struct gsm0808_vgcs_vbs_assign_req vgcs_vbs_assign_req; + struct gsm0808_vgcs_vbs_assign_res vgcs_vbs_assign_res; + struct gsm0808_vgcs_vbs_assign_fail vgcs_vbs_assign_fail; + struct gsm0808_uplink_request uplink_request; + struct gsm0808_uplink_request_ack uplink_request_ack; + struct gsm0808_uplink_request_cnf uplink_request_cnf; + struct gsm0808_uplink_app_data uplink_app_data; + struct gsm0808_uplink_release_ind uplink_release_ind; + struct gsm0808_uplink_seized_cmd uplink_seized_cmd; + struct gsm0808_uplink_reject_cmd uplink_reject_cmd; + struct { + enum gsm0808_cause cause; + } uplink_release_cmd; + struct { + struct gsm0808_talker_identity talker_identity; + } vgcs_additional_info; + struct gsm0808_vgcs_vbs_area_cell_info vgcs_vbs_area_cell_info; + struct gsm0808_vgcs_vbs_assign_stat vgcs_vbs_assign_stat; + struct { + struct gsm0808_sms_to_vgcs sms_to_vgcs; + } vgcs_sms; + struct gsm0808_notification_data notification_data; }; }; diff --git a/include/osmocom/msc/rtp_stream.h b/include/osmocom/msc/rtp_stream.h index c53c4f179..5bc01440f 100644 --- a/include/osmocom/msc/rtp_stream.h +++ b/include/osmocom/msc/rtp_stream.h @@ -5,6 +5,7 @@ #include <osmocom/core/sockaddr_str.h> #include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/msc/sdp_msg.h> struct gsm_trans; @@ -25,7 +26,8 @@ static inline const char *rtp_direction_name(enum rtp_direction val) /* A single bidirectional RTP hop between remote and MGW's local RTP port. */ struct rtp_stream { struct osmo_fsm_inst *fi; - struct call_leg *parent_call_leg; + uint32_t event_avail; + uint32_t event_estab; enum rtp_direction dir; uint32_t call_id; @@ -37,13 +39,14 @@ struct rtp_stream { struct osmo_sockaddr_str remote; bool remote_sent_to_mgw; - bool codec_known; - enum mgcp_codecs codec; - bool codec_sent_to_mgw; + bool codecs_known; + struct sdp_audio_codecs codecs; + bool codecs_sent_to_mgw; struct osmo_mgcpc_ep_ci *ci; enum mgcp_connection_mode crcx_conn_mode; + bool mode_sent_to_mgw; /* configured to use Osmux */ bool use_osmux; @@ -58,14 +61,19 @@ struct rtp_stream { #define RTP_STREAM_FMT "local=" RTP_IP_PORT_FMT ",remote=" RTP_IP_PORT_FMT #define RTP_STREAM_ARGS(RS) RTP_IP_PORT_ARGS(&(RS)->local), RTP_IP_PORT_ARGS(&(RS)->remote), -struct rtp_stream *rtp_stream_alloc(struct call_leg *parent_call_leg, enum rtp_direction dir, - uint32_t call_id, struct gsm_trans *for_trans); +struct rtp_stream *rtp_stream_alloc(struct osmo_fsm_inst *parent_fi, uint32_t event_gone, uint32_t event_avail, + uint32_t event_estab, enum rtp_direction dir, uint32_t call_id, + struct gsm_trans *for_trans); int rtp_stream_ensure_ci(struct rtp_stream *rtps, struct osmo_mgcpc_ep *at_endpoint); int rtp_stream_do_mdcx(struct rtp_stream *rtps); -void rtp_stream_set_codec(struct rtp_stream *rtps, enum mgcp_codecs codec); +bool rtp_stream_set_codecs_from_mgcp_codec(struct rtp_stream *rtps, enum mgcp_codecs codec); +void rtp_stream_set_one_codec(struct rtp_stream *rtps, const struct sdp_audio_codec *codec); +void rtp_stream_set_codecs(struct rtp_stream *rtps, const struct sdp_audio_codecs *codecs); +void rtp_stream_set_mode(struct rtp_stream *rtps, enum mgcp_connection_mode mode); void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_sockaddr_str *r); +void rtp_stream_set_remote_addr_and_codecs(struct rtp_stream *rtps, const struct sdp_msg *sdp); void rtp_stream_set_remote_osmux_cid(struct rtp_stream *rtps, uint8_t osmux_cid); int rtp_stream_commit(struct rtp_stream *rtps); diff --git a/include/osmocom/msc/sdp_msg.h b/include/osmocom/msc/sdp_msg.h index 7ac6036f6..e3879f6af 100644 --- a/include/osmocom/msc/sdp_msg.h +++ b/include/osmocom/msc/sdp_msg.h @@ -4,17 +4,28 @@ #include <osmocom/core/utils.h> #include <osmocom/core/sockaddr_str.h> +#include <osmocom/msc/csd_bs.h> + extern const struct value_string sdp_msg_payload_type_names[]; static inline const char *sdp_msg_payload_type_name(unsigned int payload_type) { return get_value_string(sdp_msg_payload_type_names, payload_type); } int sdp_subtype_name_to_payload_type(const char *subtype_name); +enum sdp_mode_e { + SDP_MODE_UNSET = 0, + SDP_MODE_SENDONLY = 1, + SDP_MODE_RECVONLY = 2, + SDP_MODE_SENDRECV = 3, + SDP_MODE_INACTIVE = 4, +}; + struct sdp_audio_codec { + /* Payload type number, like 3 for GSM-FR. */ unsigned int payload_type; /* Like "GSM", "AMR", "EFR", ... */ char subtype_name[16]; unsigned int rate; - char fmtp[64]; + char fmtp[256]; }; struct sdp_audio_codecs { @@ -25,44 +36,52 @@ struct sdp_audio_codecs { struct sdp_msg { struct osmo_sockaddr_str rtp; unsigned int ptime; + enum sdp_mode_e mode; struct sdp_audio_codecs audio_codecs; + struct csd_bs_list bearer_services; }; -#define foreach_sdp_audio_codec(/* struct sdp_audio_codec* */ CODEC, \ - /* struct sdp_audio_codecs* */ AC) \ +#define sdp_audio_codecs_foreach(/* struct sdp_audio_codec* */ CODEC, \ + /* struct sdp_audio_codecs* */ AC) \ for (CODEC = (AC)->codec; \ (CODEC - (AC)->codec) < OSMO_MIN((AC)->count, ARRAY_SIZE((AC)->codec)); \ CODEC++) const char *sdp_msg_line_end(const char *src); -int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b); +bool sdp_audio_codec_is_set(const struct sdp_audio_codec *a); +int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b, + bool cmp_fmtp, bool cmp_payload_type); +int sdp_audio_codecs_cmp(const struct sdp_audio_codecs *a, const struct sdp_audio_codecs *b, + bool cmp_fmtp, bool cmp_payload_type); -struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigned int payload_type, - const char *subtype_name, unsigned int rate, const char *fmtp); -struct sdp_audio_codec *sdp_audio_codec_add_copy(struct sdp_audio_codecs *ac, - const struct sdp_audio_codec *codec); -int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec); -struct sdp_audio_codec *sdp_audio_codec_by_payload_type(struct sdp_audio_codecs *ac, - unsigned int payload_type, bool create); -struct sdp_audio_codec *sdp_audio_codec_by_descr(struct sdp_audio_codecs *ac, - const struct sdp_audio_codec *codec); +struct sdp_audio_codec *sdp_audio_codecs_add(struct sdp_audio_codecs *ac, unsigned int payload_type, + const char *subtype_name, unsigned int rate, const char *fmtp); +struct sdp_audio_codec *sdp_audio_codecs_add_copy(struct sdp_audio_codecs *ac, + const struct sdp_audio_codec *codec); +int sdp_audio_codecs_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec); +struct sdp_audio_codec *sdp_audio_codecs_by_payload_type(struct sdp_audio_codecs *ac, + unsigned int payload_type, bool create); +struct sdp_audio_codec *sdp_audio_codecs_by_descr(struct sdp_audio_codecs *ac, + const struct sdp_audio_codec *codec); void sdp_audio_codecs_intersection(struct sdp_audio_codecs *ac_dest, const struct sdp_audio_codecs *ac_other, bool translate_payload_type_numbers); void sdp_audio_codecs_select(struct sdp_audio_codecs *ac, struct sdp_audio_codec *codec); -int sdp_msg_to_str(char *dst, size_t dst_size, const struct sdp_msg *sdp); -int sdp_msg_from_str(struct sdp_msg *sdp, const char *src); +int sdp_msg_to_sdp_str_buf(char *dst, size_t dst_size, const struct sdp_msg *sdp); +int sdp_msg_from_sdp_str(struct sdp_msg *sdp, const char *src); + +int sdp_audio_codec_to_str_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec); +char *sdp_audio_codec_to_str_c(void *ctx, const struct sdp_audio_codec *codec); +const char *sdp_audio_codec_to_str(const struct sdp_audio_codec *codec); -int sdp_audio_codec_name_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec); -char *sdp_audio_codec_name_c(void *ctx, const struct sdp_audio_codec *codec); -const char *sdp_audio_codec_name(const struct sdp_audio_codec *codec); +int sdp_audio_codecs_to_str_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac); +char *sdp_audio_codecs_to_str_c(void *ctx, const struct sdp_audio_codecs *ac); +const char *sdp_audio_codecs_to_str(const struct sdp_audio_codecs *ac); -int sdp_audio_codecs_name_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac); -char *sdp_audio_codecs_name_c(void *ctx, const struct sdp_audio_codecs *ac); -const char *sdp_audio_codecs_name(const struct sdp_audio_codecs *ac); +int sdp_msg_to_str_buf(char *buf, size_t buflen, const struct sdp_msg *sdp); +char *sdp_msg_to_str_c(void *ctx, const struct sdp_msg *sdp); +const char *sdp_msg_to_str(const struct sdp_msg *sdp); -int sdp_msg_name_buf(char *buf, size_t buflen, const struct sdp_msg *sdp); -char *sdp_msg_name_c(void *ctx, const struct sdp_msg *sdp); -const char *sdp_msg_name(const struct sdp_msg *sdp); +void sdp_audio_codecs_set_csd(struct sdp_audio_codecs *ac); diff --git a/include/osmocom/msc/smpp.h b/include/osmocom/msc/smpp.h deleted file mode 100644 index bcdac8f0b..000000000 --- a/include/osmocom/msc/smpp.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -int smpp_openbsc_alloc_init(void *ctx); -int smpp_openbsc_start(struct gsm_network *net); diff --git a/include/osmocom/msc/sms_queue.h b/include/osmocom/msc/sms_queue.h index ef73baf04..a6e6aebd3 100644 --- a/include/osmocom/msc/sms_queue.h +++ b/include/osmocom/msc/sms_queue.h @@ -1,20 +1,32 @@ #ifndef SMS_QUEUE_H #define SMS_QUEUE_H +#include <stdbool.h> + struct gsm_network; struct gsm_sms_queue; struct vty; +struct sms_queue_config { + char *db_file_path; /* SMS database file path */ + int max_fail; /* maximum number of delivery failures */ + int max_pending; /* maximum number of gsm_sms_pending in RAM */ + bool delete_delivered; /* delete delivered SMS from DB? */ + bool delete_expired; /* delete expired SMS from DB? */ + unsigned int minimum_validity_mins; /* minimum validity period in minutes */ + unsigned int default_validity_mins; /* default validity period in minutes */ +}; + +struct sms_queue_config *sms_queue_cfg_alloc(void *ctx); + #define VSUB_USE_SMS_PENDING "SMS-pending" #define MSC_A_USE_SMS_PENDING "SMS-pending" -int sms_queue_start(struct gsm_network *, int in_flight); +int sms_queue_start(struct gsm_network *net); int sms_queue_trigger(struct gsm_sms_queue *); /* vty helper functions */ int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty); -int sms_queue_set_max_pending(struct gsm_sms_queue *, int max); -int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail); int sms_queue_clear(struct gsm_sms_queue *); int sms_queue_sms_is_pending(struct gsm_sms_queue *smsq, unsigned long long sms_id); diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 14b89bb81..aa529e494 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -8,6 +8,8 @@ #include <osmocom/msc/mncc.h> #include <osmocom/msc/msc_a.h> #include <osmocom/msc/debug.h> +#include <osmocom/msc/codec_filter.h> +#include <osmocom/msc/csd_filter.h> #include <osmocom/gsm/gsm0411_smc.h> #include <osmocom/gsm/gsm0411_smr.h> @@ -16,15 +18,18 @@ struct vty; /* Used for late TID assignment */ #define TRANS_ID_UNASSIGNED 0xff +#define LOG_TRANS_CAT_SRC(trans, subsys, level, file, line, fmt, args...) \ + LOGPSRC(subsys, level, file, line, \ + "trans(%s %s callref-0x%x tid-%u%s) " fmt, \ + (trans) ? trans_name(trans) : "NULL", \ + (trans) ? ((trans)->msc_a ? (trans)->msc_a->c.fi->id : vlr_subscr_name((trans)->vsub)) : "NULL", \ + (trans) ? (trans)->callref : 0, \ + (trans) ? (trans)->transaction_id : 0, \ + (trans) && (trans)->paging_request ? ",PAGING" : "", \ + ##args) + #define LOG_TRANS_CAT(trans, subsys, level, fmt, args...) \ - LOGP(subsys, level, \ - "trans(%s %s callref-0x%x tid-%u%s) " fmt, \ - (trans) ? trans_name(trans) : "NULL", \ - (trans) ? ((trans)->msc_a ? (trans)->msc_a->c.fi->id : vlr_subscr_name((trans)->vsub)) : "NULL", \ - (trans) ? (trans)->callref : 0, \ - (trans) ? (trans)->transaction_id : 0, \ - (trans) && (trans)->paging_request ? ",PAGING" : "", \ - ##args) + LOG_TRANS_CAT_SRC(trans, subsys, level, __FILE__, __LINE__, fmt, ##args) #define LOG_TRANS(trans, level, fmt, args...) \ LOG_TRANS_CAT(trans, (trans) ? (trans)->log_subsys : DMSC, level, fmt, ##args) @@ -38,6 +43,8 @@ enum bridge_state { }; enum trans_type { + TRANS_GCC = GSM48_PDISC_GROUP_CC, + TRANS_BCC = GSM48_PDISC_BCAST_CC, TRANS_CC = GSM48_PDISC_CC, TRANS_SMS = GSM48_PDISC_SMS, TRANS_USSD = GSM48_PDISC_NC_SS, @@ -78,6 +85,9 @@ struct gsm_trans { /* reference from MNCC or other application */ uint32_t callref; + /* reference that may be used by MGW to identify a call */ + uint32_t call_id; + /* if traffic channel receive was requested */ int tch_recv; @@ -89,6 +99,25 @@ struct gsm_trans { union { struct { + /* State machine of setup process towards BSS */ + struct osmo_fsm_inst *fi; + /* BSS list with all VGCS/VBS calls */ + struct llist_head bss_list; + /* Inactivity timeout and timer */ + int inactivity_to; + struct osmo_timer_list timer_inactivity; + /* If talker's downlink shall be muted */ + bool mute_talker; + /* Indicator, if Uplink is used in one cell */ + bool uplink_busy; + /* BSS that uses the uplink */ + struct vgcs_bss *uplink_bss; + /* Cell that uses the uplink */ + struct vgcs_bss_cell *uplink_cell; + /* If uplink is used by the originator */ + bool uplink_originator; + } gcc; + struct { /* current call state */ int state; @@ -101,6 +130,14 @@ struct gsm_trans { struct gsm_mncc msg; /* stores setup/disconnect/release message */ bool mncc_initiated; /* Whether an MNCC Release is necessary on failure */ struct osmo_lcls *lcls; + /* SDP as last received from the remote call leg. */ + struct sdp_msg remote; + /* Track codec/CSD choices from BSS and remote call leg */ + struct codec_filter codecs; + struct csd_filter csd; + /* Resulting choice from codecs/bearer services and the + * local RTP address to be sent to the remote call leg. */ + struct sdp_msg local; } cc; struct { struct gsm411_smc_inst smc_inst; @@ -112,6 +149,9 @@ struct gsm_trans { bool sm_rp_mmts_ind; struct gsm_sms *sms; + + uint8_t *gsup_source_name; + size_t gsup_source_name_len; } sms; struct { /** @@ -140,7 +180,7 @@ struct gsm_trans { struct gsm_trans *trans_find_by_type(const struct msc_a *msc_a, enum trans_type type); struct gsm_trans *trans_find_by_id(const struct msc_a *msc_a, enum trans_type type, uint8_t trans_id); -struct gsm_trans *trans_find_by_callref(const struct gsm_network *net, +struct gsm_trans *trans_find_by_callref(const struct gsm_network *net, enum trans_type type, uint32_t callref); struct gsm_trans *trans_find_by_sm_rp_mr(const struct gsm_network *net, const struct vlr_subscr *vsub, @@ -162,6 +202,10 @@ void trans_conn_closed(const struct msc_a *msc_a); static inline int trans_log_subsys(enum trans_type type) { switch (type) { + case TRANS_GCC: + return DGCC; + case TRANS_BCC: + return DBCC; case TRANS_CC: case TRANS_SILENT_CALL: return DCC; diff --git a/include/osmocom/msc/transaction_cc.h b/include/osmocom/msc/transaction_cc.h new file mode 100644 index 000000000..963cb457a --- /dev/null +++ b/include/osmocom/msc/transaction_cc.h @@ -0,0 +1,39 @@ +/* Filter/overlay codec and CSD bearer service selections for voice calls/CSD, + * across MS, RAN and CN limitations + * + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Oliver Smith + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ + +#pragma once + +#include <osmocom/gsm/mncc.h> + +#include <osmocom/msc/codec_mapping.h> +#include <osmocom/msc/transaction.h> +#include <osmocom/msc/vlr.h> + +void trans_cc_filter_init(struct gsm_trans *trans); +void trans_cc_filter_set_ran(struct gsm_trans *trans, enum osmo_rat_type ran_type); +void trans_cc_filter_set_bss(struct gsm_trans *trans, struct msc_a *msc_a); +#define trans_cc_filter_run(TRANS_CC) _trans_cc_filter_run(__FILE__, __LINE__, TRANS_CC) +void _trans_cc_filter_run(const char *file, int line, struct gsm_trans *trans); +void trans_cc_filter_set_ms_from_bc(struct gsm_trans *trans, const struct gsm_mncc_bearer_cap *bcap); +void trans_cc_set_remote_from_bc(struct gsm_trans *trans, const struct gsm_mncc_bearer_cap *bcap); diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h index d752dfb65..a7707fd01 100644 --- a/include/osmocom/msc/vlr.h +++ b/include/osmocom/msc/vlr.h @@ -5,6 +5,8 @@ #include <osmocom/core/fsm.h> #include <osmocom/core/logging.h> #include <osmocom/core/use_count.h> +#include <osmocom/core/stat_item.h> +#include <osmocom/core/rate_ctr.h> #include <osmocom/gsm/protocol/gsm_23_003.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> #include <osmocom/gsm/gsm23003.h> @@ -65,7 +67,9 @@ enum vlr_lu_event { VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */ VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */ VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */ - VLR_ULA_E_AUTH_RES, /* Result of auth procedure */ + VLR_ULA_E_AUTH_SUCCESS, /* Successful result of auth procedure */ + VLR_ULA_E_AUTH_NO_INFO, /* HLR returned SAI NACK, possibly continue without auth */ + VLR_ULA_E_AUTH_FAILURE, /* Auth procedure failed */ VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */ VLR_ULA_E_ID_IMSI, /* IMSI received from MS */ VLR_ULA_E_ID_IMEI, /* IMEI received from MS */ @@ -253,6 +257,8 @@ struct vlr_ops { /* notify MSC/SGSN that the given subscriber has been associated * with this msc_conn_ref */ int (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub); + /* notify MSC that the given subscriber is no longer valid */ + void (*subscr_inval)(void *msc_conn_ref, struct vlr_subscr *vsub); }; /* An instance of the VLR codebase */ @@ -274,6 +280,8 @@ struct vlr_instance { uint8_t nri_bitlen; struct osmo_nri_ranges *nri_ranges; } cfg; + struct osmo_stat_item_group *statg; + struct rate_ctr_group *ctrg; /* A free-form pointer for use by the caller */ void *user_ctx; }; @@ -295,7 +303,8 @@ vlr_loc_update(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *old_lai, const struct osmo_location_area_id *new_lai, bool authentication_required, - bool ciphering_required, + bool is_ciphering_to_be_attempted, + bool is_ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran, bool assign_tmsi); @@ -432,6 +441,8 @@ enum proc_arq_vlr_event { PR_ARQ_E_START, PR_ARQ_E_ID_IMSI, PR_ARQ_E_AUTH_RES, + PR_ARQ_E_AUTH_NO_INFO, + PR_ARQ_E_AUTH_FAILURE, PR_ARQ_E_CIPH_RES, PR_ARQ_E_UPD_LOC_RES, PR_ARQ_E_TRACE_RES, @@ -459,7 +470,8 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, const struct osmo_mobile_identity *mi, const struct osmo_location_area_id *lai, bool authentication_required, - bool ciphering_required, + bool is_ciphering_to_be_attempted, + bool is_ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran); diff --git a/include/osmocom/msc/vlr_sgs.h b/include/osmocom/msc/vlr_sgs.h index 723144932..aade5d342 100644 --- a/include/osmocom/msc/vlr_sgs.h +++ b/include/osmocom/msc/vlr_sgs.h @@ -69,7 +69,7 @@ static inline const char *vlr_sgs_state_timer_name(enum vlr_sgs_state_tmr Ts) extern const struct value_string sgs_state_counter_names[]; static inline const char *vlr_sgs_state_counter_name(enum vlr_sgs_state_ctr Ns) { - return get_value_string(sgs_state_timer_names, Ns); + return get_value_string(sgs_state_counter_names, Ns); } /* This callback function is called when an SGs location update is complete */ diff --git a/include/osmocom/msc/vty.h b/include/osmocom/msc/vty.h index 2a3b18bdf..a7f1db7ca 100644 --- a/include/osmocom/msc/vty.h +++ b/include/osmocom/msc/vty.h @@ -17,6 +17,7 @@ extern struct cmd_element cfg_no_description_cmd; enum bsc_vty_node { GSMNET_NODE = _LAST_OSMOVTY_NODE + 1, + MGW_NODE, SUBSCR_NODE, MSC_NODE, MNCC_INT_NODE, @@ -24,11 +25,17 @@ enum bsc_vty_node { SMPP_ESME_NODE, HLR_NODE, CFG_SGS_NODE, + SMSC_NODE, + ASCI_NODE, + GCR_NODE, + VGC_NODE, + VBC_NODE, }; int bsc_vty_init_extra(void); void msc_vty_init(struct gsm_network *msc_network); +void smsc_vty_init(struct gsm_network *msc_network); struct gsm_network *gsmnet_from_vty(struct vty *vty); diff --git a/include/osmocom/smpp/Makefile.am b/include/osmocom/smpp/Makefile.am new file mode 100644 index 000000000..5ad34ad0d --- /dev/null +++ b/include/osmocom/smpp/Makefile.am @@ -0,0 +1,4 @@ +noinst_HEADERS = \ + smpp.h \ + smpp_smsc.h \ + $(NULL) diff --git a/include/osmocom/smpp/smpp.h b/include/osmocom/smpp/smpp.h new file mode 100644 index 000000000..a2832d304 --- /dev/null +++ b/include/osmocom/smpp/smpp.h @@ -0,0 +1,55 @@ +#pragma once + +#include <osmocom/msc/gsm_data.h> + +/* Length limits according to SMPP 3.4 spec including NUL-byte: */ +#define SMPP_SYS_ID_LEN 15 +#define SMPP_PASSWD_LEN 8 + +enum esme_read_state { + READ_ST_IN_LEN = 0, + READ_ST_IN_MSG = 1, +}; + +/* struct representing SMPP's External Short Messaging Entity */ +struct esme { + uint32_t own_seq_nr; + + struct osmo_wqueue wqueue; + enum esme_read_state read_state; + uint32_t read_len; + uint32_t read_idx; + struct msgb *read_msg; + + uint8_t smpp_version; + char system_id[SMPP_SYS_ID_LEN + 1]; + char password[SMPP_SYS_ID_LEN + 1]; +}; + +#define LOGPESME(ESME, LEVEL, FMT, ARGS...) \ + LOGP(DSMPP, LEVEL, "[%s] " FMT, (ESME)->system_id, ##ARGS) + +#define LOGPESMERR(ESME, FMT, ARGS...) \ + LOGPESME(ESME, LOGL_ERROR, "Error (%s) " FMT, smpp34_strerror, ##ARGS) + +/*! \brief Ugly wrapper. libsmpp34 should do this itself! */ +#define SMPP34_UNPACK(rc, type, str, data, len) { \ + memset(str, 0, sizeof(*str)); \ + rc = smpp34_unpack(type, str, data, len); } + +#define PACK_AND_SEND(esme, ptr) pack_and_send(esme, (ptr)->command_id, ptr) + +/*! \brief initialize the libsmpp34 data structure for a response */ +#define INIT_RESP(type, resp, req) { \ + memset((resp), 0, sizeof(*(resp))); \ + (resp)->command_length = 0; \ + (resp)->command_id = type; \ + (resp)->command_status = ESME_ROK; \ + (resp)->sequence_number = (req)->sequence_number; } + +struct esme *esme_alloc(void *ctx); +uint32_t smpp_msgb_cmdid(struct msgb *msg); +uint32_t esme_inc_seq_nr(struct esme *esme); +int pack_and_send(struct esme *esme, uint32_t type, void *ptr); +int smpp_msc_alloc_init(void *ctx); +int smpp_msc_start(struct gsm_network *net); diff --git a/src/libmsc/smpp_smsc.h b/include/osmocom/smpp/smpp_smsc.h index 4c0d70154..6d7647589 100644 --- a/src/libmsc/smpp_smsc.h +++ b/include/osmocom/smpp/smpp_smsc.h @@ -1,5 +1,4 @@ -#ifndef _SMPP_SMSC_H -#define _SMPP_SMSC_H +#pragma once #include <sys/socket.h> #include <netinet/in.h> @@ -8,24 +7,17 @@ #include <osmocom/core/msgb.h> #include <osmocom/core/write_queue.h> #include <osmocom/core/timer.h> +#include <osmocom/smpp/smpp.h> #include <smpp34.h> #include <smpp34_structs.h> #include <smpp34_params.h> -#define SMPP_SYS_ID_LEN 15 -#define SMPP_PASSWD_LEN 8 - #define MODE_7BIT 7 #define MODE_8BIT 8 struct msc_a; -enum esme_read_state { - READ_ST_IN_LEN = 0, - READ_ST_IN_MSG = 1, -}; - struct osmo_smpp_acl; struct osmo_smpp_addr { @@ -34,35 +26,24 @@ struct osmo_smpp_addr { char addr[21+1]; }; -struct osmo_esme { +/* struct wrapping ESME struct with additional SMSC-specific things like ACL, command list etc */ +struct smpp_esme { struct llist_head list; struct smsc *smsc; + struct esme *esme; struct osmo_smpp_acl *acl; int use; struct llist_head smpp_cmd_list; - uint32_t own_seq_nr; - - struct osmo_wqueue wqueue; - struct sockaddr_storage sa; - socklen_t sa_len; - - enum esme_read_state read_state; - uint32_t read_len; - uint32_t read_idx; - struct msgb *read_msg; - uint8_t smpp_version; - char system_id[SMPP_SYS_ID_LEN+1]; - uint8_t bind_flags; }; struct osmo_smpp_acl { struct llist_head list; struct smsc *smsc; - struct osmo_esme *esme; + struct smpp_esme *esme; char *description; char system_id[SMPP_SYS_ID_LEN+1]; char passwd[SMPP_PASSWD_LEN+1]; @@ -99,11 +80,11 @@ struct osmo_smpp_cmd { struct osmo_timer_list response_timer; }; -struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme, +struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct smpp_esme *esme, uint32_t sequence_number); void smpp_cmd_ack(struct osmo_smpp_cmd *cmd); void smpp_cmd_err(struct osmo_smpp_cmd *cmd, uint32_t status); -void smpp_cmd_flush_pending(struct osmo_esme *esme); +void smpp_cmd_flush_pending(struct smpp_esme *esme); struct smsc { struct osmo_fd listen_ofd; @@ -126,27 +107,26 @@ struct smsc *smpp_smsc_alloc_init(void *ctx); int smpp_smsc_conf(struct smsc *smsc, const char *bind_addr, uint16_t port); int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port); int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port); -void smpp_smsc_stop(struct smsc *smsc); -void smpp_esme_get(struct osmo_esme *esme); -void smpp_esme_put(struct osmo_esme *esme); +void smpp_esme_get(struct smpp_esme *esme); +void smpp_esme_put(struct smpp_esme *esme); -int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **emse); +int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct smpp_esme **emse); struct osmo_smpp_acl *smpp_acl_alloc(struct smsc *smsc, const char *sys_id); struct osmo_smpp_acl *smpp_acl_by_system_id(struct smsc *smsc, const char *sys_id); void smpp_acl_delete(struct osmo_smpp_acl *acl); -int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, +int smpp_tx_submit_r(struct smpp_esme *esme, uint32_t sequence_nr, uint32_t command_status, char *msg_id); -int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi, +int smpp_tx_alert(struct smpp_esme *esme, uint8_t ton, uint8_t npi, const char *addr, uint8_t avail_status); -int smpp_tx_deliver(struct osmo_esme *esme, struct deliver_sm_t *deliver); +int smpp_tx_deliver(struct smpp_esme *esme, struct deliver_sm_t *deliver); -int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, +int handle_smpp_submit(struct smpp_esme *esme, struct submit_sm_t *submit, struct submit_sm_resp_t *submit_r); int smpp_route_pfx_add(struct osmo_smpp_acl *acl, @@ -158,6 +138,7 @@ int smpp_vty_init(void); int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode); +time_t smpp_parse_time_format(const char *vp, time_t *t_now); struct gsm_sms; @@ -165,4 +146,3 @@ struct ran_conn; bool smpp_route_smpp_first(); int smpp_try_deliver(struct gsm_sms *sms, struct msc_a *msc_a); -#endif diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 deleted file mode 100644 index ca3639715..000000000 --- a/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -1,74 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) -# -# DESCRIPTION -# -# Check whether the given FLAG works with the current language's compiler -# or gives an error. (Warnings, however, are ignored) -# -# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on -# success/failure. -# -# If EXTRA-FLAGS is defined, it is added to the current language's default -# flags (e.g. CFLAGS) when the check is done. The check is thus made with -# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to -# force the compiler to issue an error when a bad flag is given. -# -# INPUT gives an alternative input source to AC_COMPILE_IFELSE. -# -# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this -# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. -# -# LICENSE -# -# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de> -# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com> -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU 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 General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see <http://www.gnu.org/licenses/>. -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 4 - -AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF -AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ - ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS - _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], - [AS_VAR_SET(CACHEVAR,[yes])], - [AS_VAR_SET(CACHEVAR,[no])]) - _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_VAR_IF(CACHEVAR,yes, - [m4_default([$2], :)], - [m4_default([$3], :)]) -AS_VAR_POPDEF([CACHEVAR])dnl -])dnl AX_CHECK_COMPILE_FLAGS diff --git a/src/Makefile.am b/src/Makefile.am index 4e7cea19b..746c80d0f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,20 +13,22 @@ AM_CFLAGS = \ $(COVERAGE_CFLAGS) \ $(NULL) -AM_LDFLAGS = \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGSM_LIBS) \ - $(COVERAGE_LDFLAGS) \ - $(NULL) - # Libraries SUBDIRS = \ libvlr \ libmsc \ $(NULL) +if BUILD_SMPP + +SUBDIRS += \ + libsmpputil \ + utils \ + $(NULL) + +endif + # Programs SUBDIRS += \ osmo-msc \ - utils \ $(NULL) diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am index e6a2dc164..dff4b2db0 100644 --- a/src/libmsc/Makefile.am +++ b/src/libmsc/Makefile.am @@ -20,9 +20,6 @@ AM_CFLAGS = \ $(LIBOSMONETIF_CFLAGS) \ $(NULL) -noinst_HEADERS = \ - $(NULL) - noinst_LIBRARIES = \ libmsc.a \ $(NULL) @@ -30,6 +27,10 @@ noinst_LIBRARIES = \ libmsc_a_SOURCES = \ call_leg.c \ cell_id_list.c \ + codec_filter.c \ + codec_mapping.c \ + csd_bs.c \ + csd_filter.c \ sccp_ran.c \ msc_vty.c \ db.c \ @@ -54,6 +55,7 @@ libmsc_a_SOURCES = \ msc_t.c \ msc_t_remote.c \ msc_ho.c \ + msc_vgcs.c \ neighbor_ident.c \ neighbor_ident_vty.c \ paging.c \ @@ -67,12 +69,16 @@ libmsc_a_SOURCES = \ sdp_msg.c \ silent_call.c \ sms_queue.c \ + smsc_vty.c \ transaction.c \ + transaction_cc.c \ msc_net_init.c \ ctrl_commands.c \ sgs_iface.c \ sgs_server.c \ sgs_vty.c \ + asci_gcr.c \ + asci_vty.c \ $(NULL) if BUILD_IU @@ -80,16 +86,3 @@ libmsc_a_SOURCES += \ ran_msg_iu.c \ $(NULL) endif - -if BUILD_SMPP -noinst_HEADERS += \ - smpp_smsc.h \ - $(NULL) - -libmsc_a_SOURCES += \ - smpp_smsc.c \ - smpp_openbsc.c \ - smpp_vty.c \ - smpp_utils.c \ - $(NULL) -endif diff --git a/src/libmsc/asci_gcr.c b/src/libmsc/asci_gcr.c new file mode 100644 index 000000000..220815136 --- /dev/null +++ b/src/libmsc/asci_gcr.c @@ -0,0 +1,175 @@ +/* Group Call Register (GCR) */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ + +#include <osmocom/msc/gsm_data.h> +#include <osmocom/msc/transaction.h> + +#include <osmocom/msc/asci_gcr.h> + +#define GCR_DEFAULT_TIMEOUT 60 + +static uint32_t pow10[9] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; + +/* Add cell to BSS list. */ +struct gcr_cell *gcr_add_cell(struct gcr_bss *bss, uint16_t cell_id) +{ + struct gcr_cell *c; + + c = talloc_zero(bss, struct gcr_cell); + if (!c) + return NULL; + c->cell_id = cell_id; + llist_add_tail(&c->list, &bss->cell_list); + + return c; +} + +/* Find cell entry in BSS list. */ +struct gcr_cell *gcr_find_cell(struct gcr_bss *bss, uint16_t cell_id) +{ + struct gcr_cell *c; + + llist_for_each_entry(c, &bss->cell_list, list) { + if (c->cell_id == cell_id) + return c; + } + + return NULL; +} + +/* Remove cell entry from BSS list. */ +void gcr_rm_cell(struct gcr_bss *bss, uint16_t cell_id) +{ + struct gcr_cell *c = gcr_find_cell(bss, cell_id); + + if (c) { + llist_del(&c->list); + talloc_free(c); + } +} + +/* Add BSS to GCR list. */ +struct gcr_bss *gcr_add_bss(struct gcr *gcr, int pc) +{ + struct gcr_bss *b; + + b = talloc_zero(gcr, struct gcr_bss); + if (!b) + return NULL; + INIT_LLIST_HEAD(&b->cell_list); + b->pc = pc; + llist_add_tail(&b->list, &gcr->bss_list); + + return b; +} + +/* Find BSS entry in GCR list. */ +struct gcr_bss *gcr_find_bss(struct gcr *gcr, int pc) +{ + struct gcr_bss *b; + + llist_for_each_entry(b, &gcr->bss_list, list) { + if (b->pc == pc) + return b; + } + + return NULL; +} + +/* Remove BSS entry from GCR list. */ +void gcr_rm_bss(struct gcr *gcr, int pc) +{ + struct gcr_bss *b = gcr_find_bss(gcr, pc); + + if (b) { + /* All cell definitons will be removed, as they are attached to BSS. */ + llist_del(&b->list); + talloc_free(b); + } +} + +/* Create a new (empty) GCR list. */ +struct gcr *gcr_create(struct gsm_network *gsmnet, enum trans_type trans_type, const char *group_id) +{ + struct gcr *gcr; + + gcr = talloc_zero(gsmnet, struct gcr); + if (!gcr) + return NULL; + + INIT_LLIST_HEAD(&gcr->bss_list); + gcr->trans_type = trans_type; + gcr->timeout = GCR_DEFAULT_TIMEOUT; + gcr->mute_talker = true; + osmo_strlcpy(gcr->group_id, group_id, sizeof(gcr->group_id)); + llist_add_tail(&gcr->list, &gsmnet->asci.gcr_lists); + + return gcr; +} + +/* Destroy a GCR list. */ +void gcr_destroy(struct gcr *gcr) +{ + /* All BSS definitons will be removed, as they are attached to GCR. */ + llist_del(&gcr->list); + talloc_free(gcr); +} + +/* Find GCR list by group ID. */ +struct gcr *gcr_by_group_id(struct gsm_network *gsmnet, enum trans_type trans_type, const char *group_id) +{ + struct gcr *gcr; + + llist_for_each_entry(gcr, &gsmnet->asci.gcr_lists, list) { + if (gcr->trans_type == trans_type && !strcmp(gcr->group_id, group_id)) + return gcr; + } + + return NULL; +} + +/* Find GCR list by callref. */ +struct gcr *gcr_by_callref(struct gsm_network *gsmnet, enum trans_type trans_type, uint32_t callref) +{ + struct gcr *most_specific_gcr = NULL, *gcr; + int a, b; + size_t most_specific_len = 0, l; + + llist_for_each_entry(gcr, &gsmnet->asci.gcr_lists, list) { + /* Compare only the digits in Group ID with the digits in callref. + * callref is an integer. Only the remainder, based on Group ID length, is checked. */ + l = strlen(gcr->group_id); + a = atoi(gcr->group_id); + OSMO_ASSERT(l < ARRAY_SIZE(pow10)); + b = callref % pow10[l]; + if (gcr->trans_type == trans_type && a == b) { + /* Get most specific GROUP ID, no matter what order they are stored. */ + if (l > most_specific_len) { + most_specific_gcr = gcr; + most_specific_len = l; + } + } + } + + return most_specific_gcr; +} diff --git a/src/libmsc/asci_vty.c b/src/libmsc/asci_vty.c new file mode 100644 index 000000000..a138eda51 --- /dev/null +++ b/src/libmsc/asci_vty.c @@ -0,0 +1,434 @@ +/* GCR interface to VTY */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ + +#include <osmocom/msc/vty.h> +#include <osmocom/msc/transaction.h> +#include <osmocom/msc/msc_vgcs.h> +#include <osmocom/msc/asci_vty.h> +#include <osmocom/msc/asci_gcr.h> + +static struct gsm_network *gsmnet; + +/*********************************************************************** + * ASCI Node + ***********************************************************************/ + +#define ASCI_STR "Advanced Speech Call Items\n" + +static void asci_disabled(struct vty *vty) +{ + vty_out(vty, "%%Advanced Speech Call Items are disabled.%s", VTY_NEWLINE); +} + +DEFUN(asci_call, asci_call_cmd, + "asci (initiate|terminate) (vgc|vbc) CALLREF", + ASCI_STR "Initiate a call\nTerminate a call\nVoice Group Call\nVoice Broadcast Call\nCall reference") +{ + struct gcr *gcr; + const char *error; + + if (!gsmnet->asci.enable) { + asci_disabled(vty); + return CMD_WARNING; + } + + gcr = gcr_by_group_id(gsmnet, (argv[1][1] == 'g') ? TRANS_GCC : TRANS_BCC, argv[2]); + if (!gcr) { + vty_out(vty, "%%Given call ref does not exist in GCR.%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (argv[0][0] == 'i') + error = vgcs_vty_initiate(gsmnet, gcr); + else + error = vgcs_vty_terminate(gsmnet, gcr); + if (error) { + vty_out(vty, "%%%s%s", error, VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +DEFUN(asci_show, asci_show_cmd, + "show asci calls", + SHOW_STR ASCI_STR "Show all Voice Group/Broadcast Calls") +{ + struct gsm_trans *trans; + const char *typestr; + struct vgcs_bss *bss; + struct vgcs_bss_cell *cell; + + if (!gsmnet->asci.enable) { + asci_disabled(vty); + return CMD_WARNING; + } + + llist_for_each_entry(trans, &gsmnet->trans_list, entry) { + if (trans->type == TRANS_GCC) + typestr = "Group"; + else if (trans->type == TRANS_BCC) + typestr = "Broadcast"; + else + continue; + vty_out(vty, "Call Reference %s (Voice %s Call).%s", gsm44068_group_id_string(trans->callref), + typestr, VTY_NEWLINE); + vty_out(vty, " Call state : %s%s", vgcs_bcc_gcc_state_name(trans->gcc.fi), VTY_NEWLINE); + vty_out(vty, " Uplink state: %s%s", (trans->gcc.uplink_busy) ? "busy" : "free", VTY_NEWLINE); + if (trans->gcc.uplink_busy) + vty_out(vty, " Talker : %s subscriber%s", + (trans->gcc.uplink_originator) ? "calling" : "other", VTY_NEWLINE); + llist_for_each_entry(bss, &trans->gcc.bss_list, list) { + vty_out(vty, " BSS %8s: listening%s%s", osmo_ss7_pointcode_print(NULL, bss->pc), + (trans->gcc.uplink_busy && bss == trans->gcc.uplink_bss) ? "+talking" : "", + VTY_NEWLINE); + llist_for_each_entry(cell, &bss->cell_list, list_bss) { + vty_out(vty, " Cell %6d: listening%s%s", cell->cell_id, + (trans->gcc.uplink_busy && cell == trans->gcc.uplink_cell) ? "+talking" : "", + VTY_NEWLINE); + } + } + } + + return CMD_SUCCESS; +} + +/*********************************************************************** + * GCR Config Node + ***********************************************************************/ + +static struct cmd_node asci_node = { + ASCI_NODE, + "%s(config-asci)# ", + 1, +}; + +static struct cmd_node gcr_node = { + GCR_NODE, + "%s(config-gcr)# ", + 1, +}; + +char conf_prompt[64]; + +static struct cmd_node vgc_node = { + VGC_NODE, + conf_prompt, + 1, +}; + +static struct cmd_node vbc_node = { + VBC_NODE, + conf_prompt, + 1, +}; + +DEFUN(cfg_asci, cfg_asci_cmd, + "asci", "Enable and configure " ASCI_STR) +{ + vty->node = ASCI_NODE; + return CMD_SUCCESS; +} + +DEFUN(cfg_enable_disable, cfg_enable_disable_cmd, + "(enable|disable)", "Enable " ASCI_STR "Disable " ASCI_STR) +{ + gsmnet->asci.enable = (argv[0][0] == 'e'); + return CMD_SUCCESS; +} + +DEFUN(cfg_gcr, cfg_gcr_cmd, + "gcr", "Configure Group Call Register") +{ + vty->node = GCR_NODE; + return CMD_SUCCESS; +} + +static bool valid_group_id(const char *id, struct vty *vty) +{ + int i; + + if (strlen(id) < 1 || strlen(id) > 8) { + vty_out(vty, "%%Given group ID is not valid. Use up to 8 numeric digits!%s", VTY_NEWLINE); + return false; + } + for (i = 0; i < strlen(id); i++) { + if (id[i] < '0' || id[i] > '9') { + vty_out(vty, "%%Given group ID is not valid. Use numeric digits only!%s", VTY_NEWLINE); + return false; + } + } + + return true; +} + +DEFUN(cfg_vgc, cfg_vgc_cmd, + "vgc ID", "Configure Voice Group Call\n" "Group ID") +{ + struct gcr *gcr; + + if (!valid_group_id(argv[0], vty)) + return CMD_WARNING; + + gcr = gcr_by_group_id(gsmnet, TRANS_GCC, argv[0]); + if (!gcr) + gcr = gcr_create(gsmnet, TRANS_GCC, argv[0]); + if (!gcr) + return CMD_WARNING; + + sprintf(conf_prompt, "%%s(vgc-%s)# ", gcr->group_id); + vty->node = VGC_NODE; + vty->index = gcr; + return CMD_SUCCESS; +} + +DEFUN(cfg_no_vgc, cfg_no_vgc_cmd, + "no vgc ID", NO_STR "Configure Voice Group Call\n" "Group ID") +{ + struct gcr *gcr; + + if (!valid_group_id(argv[0], vty)) + return CMD_WARNING; + + gcr = gcr_by_group_id(gsmnet, TRANS_GCC, argv[0]); + if (!gcr) { + vty_out(vty, "%%Voice group call with given group ID does not exit!%s", VTY_NEWLINE); + return CMD_WARNING; + } + gcr_destroy(gcr); + + return CMD_SUCCESS; +} + +DEFUN(cfg_vbc, cfg_vbc_cmd, + "vbc ID", "Configure Voice Broadcast Call\n" "Group ID") +{ + struct gcr *gcr; + + if (!valid_group_id(argv[0], vty)) + return CMD_WARNING; + + gcr = gcr_by_group_id(gsmnet, TRANS_BCC, argv[0]); + if (!gcr) + gcr = gcr_create(gsmnet, TRANS_BCC, argv[0]); + if (!gcr) + return CMD_WARNING; + + sprintf(conf_prompt, "%%s(vbc-%s)# ", gcr->group_id); + vty->node = VBC_NODE; + vty->index = gcr; + return CMD_SUCCESS; +} + +DEFUN(cfg_no_vbc, cfg_no_vbc_cmd, + "no vbc ID", NO_STR "Configure Voice Broadcast Call\n" "Group ID") +{ + struct gcr *gcr; + + if (!valid_group_id(argv[0], vty)) + return CMD_WARNING; + + gcr = gcr_by_group_id(gsmnet, TRANS_BCC, argv[0]); + if (!gcr) { + vty_out(vty, "%%Voice broadcast call with given group ID does not exit!%s", VTY_NEWLINE); + return CMD_WARNING; + } + gcr_destroy(gcr); + + return CMD_SUCCESS; +} + +DEFUN(cfg_mute, cfg_mute_cmd, + "mute-talker", "Mute talker's downlink") +{ + struct gcr *gcr = vty->index; + + gcr->mute_talker = true; + + return CMD_SUCCESS; +} + +DEFUN(cfg_unmute, cfg_unmute_cmd, + "unmute-talker", "Unmute talker's downlink") +{ + struct gcr *gcr = vty->index; + + gcr->mute_talker = false; + + return CMD_SUCCESS; +} + +DEFUN(cfg_timeout, cfg_timeout_cmd, + "timeout <1-65535>", "Set inactivity timer\n" "Timeout in seconds") +{ + struct gcr *gcr = vty->index; + + gcr->timeout = atoi(argv[0]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_timeout, cfg_no_timeout_cmd, + "no timeout", NO_STR "Unset inactivity timer") +{ + struct gcr *gcr = vty->index; + + gcr->timeout = 0; + + return CMD_SUCCESS; +} + +#define PC_ID_STR "Point code of MSC\nCell ID of BTS" + +DEFUN(cfg_no_cell, cfg_no_cell_cmd, + "no cell POINT_CODE [<0-65535>]", NO_STR "Remove BSS/cell from current group\n" PC_ID_STR) +{ + struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(0); + struct gcr *gcr = vty->index; + struct gcr_bss *bss; + int pc = osmo_ss7_pointcode_parse(ss7, argv[0]); + uint16_t cell_id; + + if (pc < 0 || !osmo_ss7_pc_is_valid((uint32_t)pc)) { + vty_out(vty, "Invalid point code (%s)%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + bss = gcr_find_bss(gcr, pc); + if (!bss) { + vty_out(vty, "%%Given BSS point code does not exit in list!%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (argc > 1) { + cell_id = atoi(argv[1]); + if (!gcr_find_cell(bss, cell_id)) { + vty_out(vty, "%%Given cell does not exit in list!%s", VTY_NEWLINE); + return CMD_WARNING; + } + + /* Remove cell only. Exit if there are still cells for this BSS. */ + gcr_rm_cell(bss, cell_id); + if (!llist_empty(&bss->cell_list)) + return CMD_SUCCESS; + } + + gcr_rm_bss(gcr, pc); + + return CMD_SUCCESS; +} + +DEFUN(cfg_cell, cfg_cell_cmd, + "cell POINT_CODE <0-65535>", "Add cell to current group\n" PC_ID_STR) +{ + struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(0); + struct gcr *gcr = vty->index; + struct gcr_bss *bss; + int pc = osmo_ss7_pointcode_parse(ss7, argv[0]); + uint16_t cell_id = atoi(argv[1]); + + if (pc < 0 || !osmo_ss7_pc_is_valid((uint32_t)pc)) { + vty_out(vty, "Invalid point code (%s)%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + bss = gcr_find_bss(gcr, pc); + if (!bss) + bss = gcr_add_bss(gcr, pc); + if (!bss) + return CMD_WARNING; + + if (gcr_find_cell(bss, cell_id)) + return CMD_SUCCESS; + + gcr_add_cell(bss, cell_id); + + return CMD_SUCCESS; +} + +static int config_write_asci(struct vty *vty) +{ + struct osmo_ss7_instance *ss7 = osmo_ss7_instance_find(0); + struct gcr *gcr; + struct gcr_bss *b; + struct gcr_cell *c; + + vty_out(vty, "asci%s", VTY_NEWLINE); + + vty_out(vty, " %s%s", (gsmnet->asci.enable) ? "enable" : "disable", VTY_NEWLINE); + + vty_out(vty, " gcr%s", VTY_NEWLINE); + + llist_for_each_entry(gcr, &gsmnet->asci.gcr_lists, list) { + vty_out(vty, " %s %s%s", (gcr->trans_type == TRANS_GCC) ? "vgc" : "vbc", gcr->group_id, VTY_NEWLINE); + if (gcr->trans_type == TRANS_GCC) { + if (gcr->timeout) + vty_out(vty, " timeout %d%s", gcr->timeout, VTY_NEWLINE); + else + vty_out(vty, " no timeout%s", VTY_NEWLINE); + } + if (gcr->mute_talker) + vty_out(vty, " mute-talker%s", VTY_NEWLINE); + else + vty_out(vty, " unmute-talker%s", VTY_NEWLINE); + if (llist_empty(&gcr->bss_list)) + vty_out(vty, " ! Please add cell(s) here!%s", VTY_NEWLINE); + llist_for_each_entry(b, &gcr->bss_list, list) { + llist_for_each_entry(c, &b->cell_list, list) + vty_out(vty, " cell %s %d%s", osmo_ss7_pointcode_print(ss7, b->pc), c->cell_id, VTY_NEWLINE); + } + } + + return CMD_SUCCESS; +} + +void asci_vty_init(struct gsm_network *msc_network) +{ + OSMO_ASSERT(gsmnet == NULL); + gsmnet = msc_network; + + install_element_ve(&asci_show_cmd); + /* enable node */ + install_element(ENABLE_NODE, &asci_call_cmd); + /* Config node */ + install_element(CONFIG_NODE, &cfg_asci_cmd); + install_node(&asci_node, config_write_asci); + install_element(ASCI_NODE, &cfg_enable_disable_cmd); + install_element(ASCI_NODE, &cfg_gcr_cmd); + install_node(&gcr_node, NULL); + install_element(GCR_NODE, &cfg_vgc_cmd); + install_element(GCR_NODE, &cfg_no_vgc_cmd); + install_node(&vgc_node, NULL); + install_element(GCR_NODE, &cfg_vbc_cmd); + install_element(GCR_NODE, &cfg_no_vbc_cmd); + install_node(&vbc_node, NULL); + install_element(VGC_NODE, &cfg_mute_cmd); + install_element(VGC_NODE, &cfg_unmute_cmd); + install_element(VGC_NODE, &cfg_timeout_cmd); + install_element(VGC_NODE, &cfg_no_timeout_cmd); + install_element(VGC_NODE, &cfg_cell_cmd); + install_element(VGC_NODE, &cfg_no_cell_cmd); + /* Add all VGC_NODEs again for VBC_NODEs. */ + install_element(VBC_NODE, &cfg_mute_cmd); + install_element(VBC_NODE, &cfg_unmute_cmd); + install_element(VBC_NODE, &cfg_cell_cmd); + install_element(VBC_NODE, &cfg_no_cell_cmd); +} diff --git a/src/libmsc/call_leg.c b/src/libmsc/call_leg.c index 056a3927c..59f2f636d 100644 --- a/src/libmsc/call_leg.c +++ b/src/libmsc/call_leg.c @@ -1,25 +1,21 @@ /* Implementation to manage two RTP streams that make up an MO or MT call leg's RTP forwarding. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <osmocom/core/fsm.h> #include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h> @@ -126,7 +122,13 @@ void call_leg_release(struct call_leg *cl) static void call_leg_mgw_endpoint_gone(struct call_leg *cl) { + struct mgcp_client *mgcp_client; int i; + + /* Put MGCP client back into MGW pool */ + mgcp_client = osmo_mgcpc_ep_client(cl->mgw_endpoint); + mgcp_client_pool_put(mgcp_client); + cl->mgw_endpoint = NULL; for (i = 0; i < ARRAY_SIZE(cl->rtp); i++) { if (!cl->rtp[i]) @@ -156,7 +158,8 @@ static void call_leg_fsm_establishing_established(struct osmo_fsm_inst *fi, uint } if (!established) break; - call_leg_state_chg(cl, CALL_LEG_ST_ESTABLISHED); + if (cl->fi->state != CALL_LEG_ST_ESTABLISHED) + call_leg_state_chg(cl, CALL_LEG_ST_ESTABLISHED); break; case CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE: @@ -186,6 +189,12 @@ void call_leg_fsm_established_onenter(struct osmo_fsm_inst *fi, uint32_t prev_st void call_leg_fsm_releasing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { + /* Trigger termination of children FSMs (rtp_stream(s)) before + * terminating ourselves, otherwise we are not able to receive + * CALL_LEG_EV_MGW_ENDPOINT_GONE from cl->mgw_endpoint (call_leg => + * rtp_stream => mgw_endpoint), because osmo_fsm disabled dispatching + * events to an FSM in process of terminating. */ + osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL); osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); } @@ -279,16 +288,24 @@ int call_leg_ensure_rtp_alloc(struct call_leg *cl, enum rtp_direction dir, uint3 if (cl->rtp[dir]) return 0; - if (!cl->mgw_endpoint) + if (!cl->mgw_endpoint) { + struct mgcp_client *mgcp_client = mgcp_client_pool_get(gsmnet->mgw.mgw_pool); + if (!mgcp_client) { + LOG_CALL_LEG(cl, LOGL_ERROR, + "cannot ensure MGW endpoint -- no MGW configured, check configuration!\n"); + return -ENODEV; + } cl->mgw_endpoint = osmo_mgcpc_ep_alloc(cl->fi, CALL_LEG_EV_MGW_ENDPOINT_GONE, - gsmnet->mgw.client, gsmnet->mgw.tdefs, cl->fi->id, - "%s", mgcp_client_rtpbridge_wildcard(gsmnet->mgw.client)); + mgcp_client, gsmnet->mgw.tdefs, cl->fi->id, + "%s", mgcp_client_rtpbridge_wildcard(mgcp_client)); + } if (!cl->mgw_endpoint) { LOG_CALL_LEG(cl, LOGL_ERROR, "failed to setup MGW endpoint\n"); return -EIO; } - cl->rtp[dir] = rtp_stream_alloc(cl, dir, call_id, for_trans); + cl->rtp[dir] = rtp_stream_alloc(cl->fi, CALL_LEG_EV_RTP_STREAM_GONE, CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE, + CALL_LEG_EV_RTP_STREAM_ESTABLISHED, dir, call_id, for_trans); OSMO_ASSERT(cl->rtp[dir]); return 0; } @@ -309,24 +326,25 @@ struct osmo_sockaddr_str *call_leg_local_ip(struct call_leg *cl, enum rtp_direct /* Make sure an MGW endpoint CI is set up for an RTP connection. * This is the one-stop for all to either completely set up a new endpoint connection, or to modify an existing one. * If not yet present, allocate the rtp_stream for the given direction. - * Then, call rtp_stream_set_codec() if codec_if_known is non-NULL, and/or rtp_stream_set_remote_addr() if + * Then, call rtp_stream_set_codecs() if codecs_if_known is non-NULL, and/or rtp_stream_set_remote_addr() if * remote_addr_if_known is non-NULL. * Finally make sure that a CRCX is sent out for this direction, if this has not already happened. * If the CRCX has already happened but new codec / remote_addr data was passed, call rtp_stream_commit() to trigger an * MDCX. */ int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans, - const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known) + const struct sdp_audio_codecs *codecs_if_known, + const struct osmo_sockaddr_str *remote_addr_if_known) { if (call_leg_ensure_rtp_alloc(cl, dir, call_id, for_trans)) return -EIO; - cl->rtp[dir]->crcx_conn_mode = cl->crcx_conn_mode[dir]; + rtp_stream_set_mode(cl->rtp[dir], cl->crcx_conn_mode[dir]); if (dir == RTP_TO_RAN && cl->ran_peer_supports_osmux) { cl->rtp[dir]->use_osmux = true; cl->rtp[dir]->remote_osmux_cid = -1; /* wildcard */ } - if (codec_if_known) - rtp_stream_set_codec(cl->rtp[dir], *codec_if_known); + if (codecs_if_known) + rtp_stream_set_codecs(cl->rtp[dir], codecs_if_known); if (remote_addr_if_known && osmo_sockaddr_str_is_nonzero(remote_addr_if_known)) rtp_stream_set_remote_addr(cl->rtp[dir], remote_addr_if_known); return rtp_stream_ensure_ci(cl->rtp[dir], cl->mgw_endpoint); @@ -335,22 +353,46 @@ int call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t cal int call_leg_local_bridge(struct call_leg *cl1, uint32_t call_id1, struct gsm_trans *trans1, struct call_leg *cl2, uint32_t call_id2, struct gsm_trans *trans2) { - enum mgcp_codecs codec; + struct sdp_audio_codecs *cn_codecs = NULL; cl1->local_bridge = cl2; cl2->local_bridge = cl1; - /* We may just copy the codec info we have for the RAN side of the first leg to the CN side of both legs. This - * also means that if both legs use different codecs the MGW must perform transcoding on the second leg. */ - if (!cl1->rtp[RTP_TO_RAN] || !cl1->rtp[RTP_TO_RAN]->codec_known) { - LOG_CALL_LEG(cl1, LOGL_ERROR, "RAN-side RTP stream codec is not known, not ready for bridging\n"); + /* Marry the two CN sides of the call legs. Call establishment should have made all efforts for these to be + * compatible. However, for local bridging, the codecs and payload type numbers must be exactly identical on + * both sides. Both sides may so far have different payload type numbers or slightly differing codecs, but it + * will only work when the SDP on the RTP_TO_CN sides of the call legs talk the same payload type numbers. + * So, simply take the SDP from one RTP_TO_CN side, and overwrite the other RTP_TO_CN side's SDP with it. + * If all goes to plan, the codecs will be identical, or possibly the MGW will do a conversion like AMR-BE to + * AMR-OA. In the worst case, the other call leg cannot transcode, and the call fails -- because codec + * negotiation did not do a good enough job. + * + * Copy one call leg's CN config to the other: + * + * call leg 1 call leg 2 + * ---MGW-ep------- ---MGW-ep------- + * RAN CN CN RAN + * AMR:112 AMR:112 AMR:96 AMR:96 + * | + * +-------+ + * | + * V + * AMR:112 AMR:112 AMR:112 AMR:96 + * ^MGW-endpoint converts payload type numbers between 112 and 96. + */ + if (cl1->rtp[RTP_TO_CN] && cl1->rtp[RTP_TO_CN]->codecs_known) + cn_codecs = &cl1->rtp[RTP_TO_CN]->codecs; + else if (cl2->rtp[RTP_TO_CN] && cl2->rtp[RTP_TO_CN]->codecs_known) + cn_codecs = &cl2->rtp[RTP_TO_CN]->codecs; + if (!cn_codecs) { + LOG_CALL_LEG(cl1, LOGL_ERROR, "RAN-side CN stream codec is not known, not ready for bridging\n"); + LOG_CALL_LEG(cl2, LOGL_ERROR, "RAN-side CN stream codec is not known, not ready for bridging\n"); return -EINVAL; } - codec = cl1->rtp[RTP_TO_RAN]->codec; call_leg_ensure_ci(cl1, RTP_TO_CN, call_id1, trans1, - &codec, &cl2->rtp[RTP_TO_CN]->local); + cn_codecs, &cl2->rtp[RTP_TO_CN]->local); call_leg_ensure_ci(cl2, RTP_TO_CN, call_id2, trans2, - &codec, &cl1->rtp[RTP_TO_CN]->local); + cn_codecs, &cl1->rtp[RTP_TO_CN]->local); return 0; } diff --git a/src/libmsc/cell_id_list.c b/src/libmsc/cell_id_list.c index ca7a6d43b..4bf3a76de 100644 --- a/src/libmsc/cell_id_list.c +++ b/src/libmsc/cell_id_list.c @@ -1,25 +1,21 @@ /* Manage a list of struct gsm0808_cell_id */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <osmocom/msc/cell_id_list.h> diff --git a/src/libmsc/codec_filter.c b/src/libmsc/codec_filter.c new file mode 100644 index 000000000..7511f9026 --- /dev/null +++ b/src/libmsc/codec_filter.c @@ -0,0 +1,163 @@ +/* Filter/overlay codec selections for a voice call, across MS, RAN and CN limitations */ +/* + * (C) 2019-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ + +#include <osmocom/gsm/protocol/gsm_08_08.h> + +#include <osmocom/msc/codec_filter.h> +#include <osmocom/msc/codec_mapping.h> +#include <osmocom/msc/debug.h> + +/* Add all known payload types encountered in GSM networks */ +static void sdp_add_all_geran_codecs(struct sdp_audio_codecs *ac) +{ + /* In order of preference. TODO: make configurable */ + static const enum gsm48_bcap_speech_ver mobile_codecs[] = { + GSM48_BCAP_SV_AMR_F /*!< 4 GSM FR V3 (FR AMR) */, + GSM48_BCAP_SV_AMR_H /*!< 5 GSM HR V3 (HR_AMR) */, + GSM48_BCAP_SV_EFR /*!< 2 GSM FR V2 (GSM EFR) */, + GSM48_BCAP_SV_FR /*!< 0 GSM FR V1 (GSM FR) */, + GSM48_BCAP_SV_HR /*!< 1 GSM HR V1 (GSM HR) */, + }; + int i; + for (i = 0; i < ARRAY_SIZE(mobile_codecs); i++) + sdp_audio_codecs_add_speech_ver(ac, mobile_codecs[i]); +} + +/* Add all known AMR payload types encountered in UTRAN networks */ +static void sdp_add_all_utran_codecs(struct sdp_audio_codecs *ac) +{ + /* In order of preference. TODO: make configurable */ + static const enum gsm48_bcap_speech_ver utran_codecs[] = { + GSM48_BCAP_SV_AMR_F /*!< 4 GSM FR V3 (FR AMR) */, + GSM48_BCAP_SV_AMR_H /*!< 5 GSM HR V3 (HR_AMR) */, + GSM48_BCAP_SV_AMR_OH /*!< 11 GSM HR V6 (OHR AMR) */, + GSM48_BCAP_SV_AMR_FW /*!< 8 GSM FR V5 (FR AMR-WB) */, + GSM48_BCAP_SV_AMR_OFW /*!< 6 GSM FR V4 (OFR AMR-WB) */, + GSM48_BCAP_SV_AMR_OHW /*!< 7 GSM HR V4 (OHR AMR-WB) */, + }; + int i; + for (i = 0; i < ARRAY_SIZE(utran_codecs); i++) + sdp_audio_codecs_add_speech_ver(ac, utran_codecs[i]); +} + +void codec_filter_set_ran(struct codec_filter *codec_filter, enum osmo_rat_type ran_type) +{ + codec_filter->ran = (struct sdp_audio_codecs){}; + + switch (ran_type) { + default: + case OSMO_RAT_GERAN_A: + sdp_add_all_geran_codecs(&codec_filter->ran); + break; + + case OSMO_RAT_UTRAN_IU: + sdp_add_all_utran_codecs(&codec_filter->ran); + break; + } +} + +void codec_filter_set_bss(struct codec_filter *codec_filter, + const struct gsm0808_speech_codec_list *codec_list_bss_supported) +{ + codec_filter->bss = (struct sdp_audio_codecs){}; + if (codec_list_bss_supported) + sdp_audio_codecs_from_speech_codec_list(&codec_filter->bss, codec_list_bss_supported); +} + +/* Render intersections of all known audio codec constraints to reach a resulting choice of favorite audio codec, plus + * possible set of alternative audio codecs, in codec_filter->result. (The result.rtp address remains unchanged.) */ +int codec_filter_run(struct codec_filter *codec_filter, struct sdp_msg *result, const struct sdp_msg *remote) +{ + struct sdp_audio_codecs *r = &result->audio_codecs; + struct sdp_audio_codec *a = &codec_filter->assignment; + *r = codec_filter->ran; + if (codec_filter->ms.count) + sdp_audio_codecs_intersection(r, &codec_filter->ms, false); + if (codec_filter->bss.count) + sdp_audio_codecs_intersection(r, &codec_filter->bss, false); + if (remote->audio_codecs.count) + sdp_audio_codecs_intersection(r, &remote->audio_codecs, true); + + if (sdp_audio_codec_is_set(a)) { + /* Assignment has completed, the chosen codec should be the first of the resulting SDP. + * If present, make sure this is listed in first place. + * If 'select' is NULL, the assigned codec is not present in the intersection of possible choices for + * TFO. Just omit the assigned codec from the filter result, and it is the CC code's responsibility to + * detect this and assign a working codec instead. */ + struct sdp_audio_codec *select = sdp_audio_codecs_by_descr(r, a); + if (select) + sdp_audio_codecs_select(r, select); + } + return 0; +} + +int codec_filter_to_str_buf(char *buf, size_t buflen, const struct codec_filter *codec_filter, + const struct sdp_msg *result, const struct sdp_msg *remote) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, result); + OSMO_STRBUF_PRINTF(sb, " (from:"); + + if (sdp_audio_codec_is_set(&codec_filter->assignment)) { + OSMO_STRBUF_PRINTF(sb, " assigned="); + OSMO_STRBUF_APPEND(sb, sdp_audio_codec_to_str_buf, &codec_filter->assignment); + } + + if (remote->audio_codecs.count + || osmo_sockaddr_str_is_nonzero(&remote->rtp)) { + OSMO_STRBUF_PRINTF(sb, " remote="); + OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, remote); + } + + if (codec_filter->ms.count) { + OSMO_STRBUF_PRINTF(sb, " MS={"); + OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->ms); + OSMO_STRBUF_PRINTF(sb, "}"); + } + + if (codec_filter->bss.count) { + OSMO_STRBUF_PRINTF(sb, " bss={"); + OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->bss); + OSMO_STRBUF_PRINTF(sb, "}"); + } + + OSMO_STRBUF_PRINTF(sb, " RAN={"); + OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &codec_filter->ran); + OSMO_STRBUF_PRINTF(sb, "}"); + + OSMO_STRBUF_PRINTF(sb, ")"); + + return sb.chars_needed; +} + +char *codec_filter_to_str_c(void *ctx, const struct codec_filter *codec_filter, const struct sdp_msg *result, + const struct sdp_msg *remote) +{ + OSMO_NAME_C_IMPL(ctx, 128, "codec_filter_to_str_c-ERROR", codec_filter_to_str_buf, codec_filter, result, remote) +} + +const char *codec_filter_to_str(const struct codec_filter *codec_filter, const struct sdp_msg *result, + const struct sdp_msg *remote) +{ + return codec_filter_to_str_c(OTC_SELECT, codec_filter, result, remote); +} diff --git a/src/libmsc/codec_mapping.c b/src/libmsc/codec_mapping.c new file mode 100644 index 000000000..bb5968f0e --- /dev/null +++ b/src/libmsc/codec_mapping.c @@ -0,0 +1,547 @@ +/* Routines for translation between codec representations: SDP, CC/BSSMAP variants, MGCP, MNCC */ +/* + * (C) 2019-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ +#include <string.h> + +#include <osmocom/gsm/mncc.h> + +#include <osmocom/msc/sdp_msg.h> +#include <osmocom/msc/codec_mapping.h> +#include <osmocom/msc/mncc.h> + +const struct codec_mapping codec_map[] = { + /* FIXME: sdp.fmtp handling is not done properly yet, proper mode-set and octet-align handling will follow in + * separate patches. */ + { + .sdp = { + .payload_type = 0, + .subtype_name = "PCMU", + .rate = 8000, + }, + .mgcp = CODEC_PCMU_8000_1, + }, + { + .sdp = { + .payload_type = 3, + .subtype_name = "GSM", + .rate = 8000, + }, + .mgcp = CODEC_GSM_8000_1, + .speech_ver_count = 1, + .speech_ver = { GSM48_BCAP_SV_FR }, + .mncc_payload_msg_type = GSM_TCHF_FRAME, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_FR1, + }, + .perm_speech = GSM0808_PERM_FR1, + .frhr = CODEC_FRHR_FR, + }, + { + .sdp = { + .payload_type = 8, + .subtype_name = "PCMA", + .rate = 8000, + }, + .mgcp = CODEC_PCMA_8000_1, + }, + { + .sdp = { + .payload_type = 18, + .subtype_name = "G729", + .rate = 8000, + }, + .mgcp = CODEC_G729_8000_1, + }, + { + .sdp = { + .payload_type = 110, + .subtype_name = "GSM-EFR", + .rate = 8000, + }, + .mgcp = CODEC_GSMEFR_8000_1, + .speech_ver_count = 1, + .speech_ver = { GSM48_BCAP_SV_EFR }, + .mncc_payload_msg_type = GSM_TCHF_FRAME_EFR, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_FR2, + }, + .perm_speech = GSM0808_PERM_FR2, + .frhr = CODEC_FRHR_FR, + }, + { + .sdp = { + .payload_type = 111, + .subtype_name = "GSM-HR-08", + .rate = 8000, + }, + .mgcp = CODEC_GSMHR_8000_1, + .speech_ver_count = 1, + .speech_ver = { GSM48_BCAP_SV_HR }, + .mncc_payload_msg_type = GSM_TCHH_FRAME, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_HR1, + }, + .perm_speech = GSM0808_PERM_HR1, + .frhr = CODEC_FRHR_HR, + }, + { + .sdp = { + /* 112 is just what we use by default. The other call leg may impose a different number. */ + .payload_type = 112, + .subtype_name = "AMR", + .rate = 8000, + /* AMR is always octet-aligned in 2G and 3G RAN, so this fmtp is signalled to remote call legs. + * So far, fmtp is ignored in incoming SIP SDP, so an incoming SDP without 'octet-align=1' will + * match with this entry; we will still reply with 'octet-align=1', which often works out. */ + .fmtp = "octet-align=1", + }, + .mgcp = CODEC_AMR_8000_1, + .speech_ver_count = 1, + .speech_ver = { GSM48_BCAP_SV_AMR_F }, + .mncc_payload_msg_type = GSM_TCH_FRAME_AMR, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_FR3, + .cfg = GSM0808_SC_CFG_DEFAULT_FR_AMR, + }, + .perm_speech = GSM0808_PERM_FR3, + .frhr = CODEC_FRHR_FR, + }, + { + /* Another entry like the above, to map HR3 to AMR, too. */ + .sdp = { + .payload_type = 112, + .subtype_name = "AMR", + .rate = 8000, + .fmtp = "octet-align=1", + }, + .mgcp = CODEC_AMR_8000_1, + .speech_ver_count = 2, + .speech_ver = { GSM48_BCAP_SV_AMR_H, GSM48_BCAP_SV_AMR_OH }, + .mncc_payload_msg_type = GSM_TCH_FRAME_AMR, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_HR3, + .cfg = GSM0808_SC_CFG_DEFAULT_HR_AMR, + }, + .perm_speech = GSM0808_PERM_HR3, + .frhr = CODEC_FRHR_HR, + }, + { + .sdp = { + .payload_type = 113, + .subtype_name = "AMR-WB", + .rate = 16000, + .fmtp = "octet-align=1", + }, + .mgcp = CODEC_AMRWB_16000_1, + .speech_ver_count = 2, + .speech_ver = { GSM48_BCAP_SV_AMR_OFW, GSM48_BCAP_SV_AMR_FW }, + .mncc_payload_msg_type = GSM_TCH_FRAME_AMR, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_FR5, + .cfg = GSM0808_SC_CFG_DEFAULT_FR_AMR_WB, + }, + .perm_speech = GSM0808_PERM_FR5, + .frhr = CODEC_FRHR_FR, + }, + { + /* Another entry like the above, to map HR4 to AMR-WB, too. */ + .sdp = { + .payload_type = 113, + .subtype_name = "AMR-WB", + .rate = 16000, + .fmtp = "octet-align=1", + }, + .mgcp = CODEC_AMRWB_16000_1, + .speech_ver_count = 1, + .speech_ver = { GSM48_BCAP_SV_AMR_OHW }, + .mncc_payload_msg_type = GSM_TCH_FRAME_AMR, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .fi = true, + .type = GSM0808_SCT_HR4, + .cfg = GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB, + }, + .perm_speech = GSM0808_PERM_HR4, + .frhr = CODEC_FRHR_HR, + }, + { + .sdp = { + .payload_type = 96, + .subtype_name = "VND.3GPP.IUFP", + .rate = 16000, + }, + .mgcp = CODEC_IUFP, + }, + { + .sdp = { + .payload_type = 120, + .subtype_name = "CLEARMODE", + .rate = 8000, + }, + .has_gsm0808_speech_codec = true, + .gsm0808_speech_codec = { + .pi = true, /* PI indicates CSDoIP is supported */ + .pt = false, /* PT indicates CSDoTDM is not supported */ + .type = GSM0808_SCT_CSD, + .cfg = 0, /* R2/R3 not set (redundancy not supported) */ + }, + .mgcp = CODEC_CLEARMODE, + }, +}; + +#define foreach_codec_mapping(CODEC_MAPPING) \ + for ((CODEC_MAPPING) = codec_map; (CODEC_MAPPING) < codec_map + ARRAY_SIZE(codec_map); (CODEC_MAPPING)++) + +const struct gsm_mncc_bearer_cap bearer_cap_empty = { + .speech_ver = { -1 }, + }; + +const struct codec_mapping *codec_mapping_by_speech_ver(enum gsm48_bcap_speech_ver speech_ver) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + int i; + for (i = 0; i < m->speech_ver_count; i++) + if (m->speech_ver[i] == speech_ver) + return m; + } + return NULL; +} + +const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec_type(enum gsm0808_speech_codec_type sct) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (!m->has_gsm0808_speech_codec) + continue; + if (m->gsm0808_speech_codec.type == sct) + return m; + } + return NULL; +} + +const struct codec_mapping *codec_mapping_by_gsm0808_speech_codec(const struct gsm0808_speech_codec *sc) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (!m->has_gsm0808_speech_codec) + continue; + if (m->gsm0808_speech_codec.type != sc->type) + continue; + /* Return only those where sc->cfg is a subset of m->gsm0808_speech_codec.cfg. */ + if ((m->gsm0808_speech_codec.cfg & sc->cfg) != sc->cfg) + continue; + return m; + } + return NULL; +} + +const struct codec_mapping *codec_mapping_by_perm_speech(enum gsm0808_permitted_speech perm_speech) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (m->perm_speech == perm_speech) + return m; + } + return NULL; +} + +const struct codec_mapping *codec_mapping_by_subtype_name(const char *subtype_name) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (!strcmp(m->sdp.subtype_name, subtype_name)) + return m; + } + return NULL; +} + +const struct codec_mapping *codec_mapping_by_mgcp_codec(enum mgcp_codecs mgcp) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (m->mgcp == mgcp) + return m; + } + return NULL; +} + +/* Append given Speech Version to the end of the Bearer Capabilities Speech Version array. Return 1 if added, zero + * otherwise (as in, return the number of items added). */ +int bearer_cap_add_speech_ver(struct gsm_mncc_bearer_cap *bearer_cap, enum gsm48_bcap_speech_ver speech_ver) +{ + int i; + for (i = 0; i < ARRAY_SIZE(bearer_cap->speech_ver) - 1; i++) { + if (bearer_cap->speech_ver[i] == speech_ver) + return 0; + if (bearer_cap->speech_ver[i] == -1) { + bearer_cap->speech_ver[i] = speech_ver; + bearer_cap->speech_ver[i+1] = -1; + return 1; + } + } + return 0; +} + +/* From the current speech_ver list present in the bearer_cap, set the bearer_cap.radio. + * If a HR speech_ver is present, set to GSM48_BCAP_RRQ_DUAL_FR, otherwise set to GSM48_BCAP_RRQ_FR_ONLY. */ +int bearer_cap_set_radio(struct gsm_mncc_bearer_cap *bearer_cap) +{ + bool hr_present = false; + int i; + for (i = 0; i < ARRAY_SIZE(bearer_cap->speech_ver) - 1; i++) { + const struct codec_mapping *m; + + if (bearer_cap->speech_ver[i] == -1) + break; + + m = codec_mapping_by_speech_ver(bearer_cap->speech_ver[i]); + + if (!m) + continue; + + if (m->frhr == CODEC_FRHR_HR) + hr_present = true; + } + + if (hr_present) + bearer_cap->radio = GSM48_BCAP_RRQ_DUAL_FR; + else + bearer_cap->radio = GSM48_BCAP_RRQ_FR_ONLY; + + return 0; +} + +/* Try to convert the SDP audio codec name to Speech Versions to append to Bearer Capabilities. + * Return the number of Speech Version entries added (some may add more than one, others may be unknown/unapplicable and + * return 0). */ +int sdp_audio_codec_add_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codec *codec) +{ + const struct codec_mapping *m; + int added = 0; + foreach_codec_mapping(m) { + int i; + if (strcmp(m->sdp.subtype_name, codec->subtype_name)) + continue; + /* TODO also match rate and fmtp? */ + for (i = 0; i < m->speech_ver_count; i++) + added += bearer_cap_add_speech_ver(bearer_cap, m->speech_ver[i]); + } + return added; +} + +/* Append all audio codecs found in given sdp_msg to Bearer Capability, by traversing all codec entries with + * sdp_audio_codec_add_to_bearer_cap(). Return the number of Speech Version entries added. + * Note that Speech Version entries are only appended, no previous entries are removed. + * Note that only the Speech Version entries are modified; to make a valid Bearer Capabiliy, at least bearer_cap->radio + * must also be set (before or after this function); see also bearer_cap_set_radio(). */ +int sdp_audio_codecs_to_bearer_cap(struct gsm_mncc_bearer_cap *bearer_cap, const struct sdp_audio_codecs *ac) +{ + const struct sdp_audio_codec *codec; + int added = 0; + + sdp_audio_codecs_foreach(codec, ac) { + added += sdp_audio_codec_add_to_bearer_cap(bearer_cap, codec); + } + + return added; +} + +/* Convert Speech Version to SDP audio codec and append to SDP message struct. */ +struct sdp_audio_codec *sdp_audio_codecs_add_speech_ver(struct sdp_audio_codecs *ac, + enum gsm48_bcap_speech_ver speech_ver) +{ + const struct codec_mapping *m; + struct sdp_audio_codec *ret = NULL; + foreach_codec_mapping(m) { + int i; + for (i = 0; i < m->speech_ver_count; i++) { + if (m->speech_ver[i] == speech_ver) { + ret = sdp_audio_codecs_add_copy(ac, &m->sdp); + break; + } + } + } + return ret; +} + +struct sdp_audio_codec *sdp_audio_codecs_add_mgcp_codec(struct sdp_audio_codecs *ac, enum mgcp_codecs mgcp_codec) +{ + const struct codec_mapping *m = codec_mapping_by_mgcp_codec(mgcp_codec); + if (!m) + return NULL; + return sdp_audio_codecs_add_copy(ac, &m->sdp); +} + +void sdp_audio_codecs_from_bearer_cap(struct sdp_audio_codecs *ac, const struct gsm_mncc_bearer_cap *bc) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(bc->speech_ver); i++) { + if (bc->speech_ver[i] == -1) + break; + sdp_audio_codecs_add_speech_ver(ac, bc->speech_ver[i]); + } +} + +/* Append an entry for the given sdp_audio_codec to the gsm0808_speech_codec_list. + * Return 0 if an entry was added, -ENOENT when there is no mapping to gsm0808_speech_codec for the given + * sdp_audio_codec, and -ENOSPC when scl is full and nothing could be added. */ +int sdp_audio_codec_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct sdp_audio_codec *codec) +{ + const struct codec_mapping *m = codec_mapping_by_subtype_name(codec->subtype_name); + if (!m) + return -ENOENT; + if (!m->has_gsm0808_speech_codec) + return -ENOENT; + if (scl->len >= ARRAY_SIZE(scl->codec)) + return -ENOSPC; + scl->codec[scl->len] = m->gsm0808_speech_codec; + /* FIXME: apply AMR configuration according to codec->fmtp */ + scl->len++; + return 0; +} + +void sdp_audio_codecs_to_speech_codec_list(struct gsm0808_speech_codec_list *scl, const struct sdp_audio_codecs *ac) +{ + const struct sdp_audio_codec *codec; + + *scl = (struct gsm0808_speech_codec_list){}; + + sdp_audio_codecs_foreach(codec, ac) { + int rc = sdp_audio_codec_to_speech_codec_list(scl, codec); + if (rc == -ENOSPC) + break; + } +} + +void sdp_audio_codecs_from_speech_codec_list(struct sdp_audio_codecs *ac, const struct gsm0808_speech_codec_list *cl) +{ + int i; + for (i = 0; i < cl->len; i++) { + const struct gsm0808_speech_codec *sc = &cl->codec[i]; + const struct codec_mapping *m = codec_mapping_by_gsm0808_speech_codec(sc); + if (!m) + continue; + sdp_audio_codecs_add_copy(ac, &m->sdp); + /* FIXME: for AMR, apply sc->cfg to the added codec's fmtp */ + } +} + +int sdp_audio_codecs_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct sdp_audio_codecs *ac) +{ + const struct sdp_audio_codec *codec; + bool fr_present = false; + int first_fr_idx = -1; + bool hr_present = false; + int first_hr_idx = -1; + int idx = -1; + + *ct = (struct gsm0808_channel_type){ + .ch_indctr = GSM0808_CHAN_SPEECH, + }; + + sdp_audio_codecs_foreach(codec, ac) { + const struct codec_mapping *m; + int i; + bool dup; + idx++; + foreach_codec_mapping(m) { + if (strcmp(m->sdp.subtype_name, codec->subtype_name)) + continue; + + switch (m->perm_speech) { + default: + continue; + + case GSM0808_PERM_FR1: + case GSM0808_PERM_FR2: + case GSM0808_PERM_FR3: + case GSM0808_PERM_FR4: + case GSM0808_PERM_FR5: + fr_present = true; + if (first_fr_idx < 0) + first_fr_idx = idx; + break; + + case GSM0808_PERM_HR1: + case GSM0808_PERM_HR2: + case GSM0808_PERM_HR3: + case GSM0808_PERM_HR4: + case GSM0808_PERM_HR6: + hr_present = true; + if (first_hr_idx < 0) + first_hr_idx = idx; + break; + } + + /* Avoid duplicates */ + dup = false; + for (i = 0; i < ct->perm_spch_len; i++) { + if (ct->perm_spch[i] == m->perm_speech) { + dup = true; + break; + } + } + if (dup) + continue; + + ct->perm_spch[ct->perm_spch_len] = m->perm_speech; + ct->perm_spch_len++; + } + } + + if (fr_present && hr_present) { + if (first_fr_idx <= first_hr_idx) + ct->ch_rate_type = GSM0808_SPEECH_FULL_PREF; + else + ct->ch_rate_type = GSM0808_SPEECH_HALF_PREF; + } else if (fr_present && !hr_present) + ct->ch_rate_type = GSM0808_SPEECH_FULL_BM; + else if (!fr_present && hr_present) + ct->ch_rate_type = GSM0808_SPEECH_HALF_LM; + else + return -EINVAL; + return 0; +} + +enum mgcp_codecs sdp_audio_codec_to_mgcp_codec(const struct sdp_audio_codec *codec) +{ + const struct codec_mapping *m; + foreach_codec_mapping(m) { + if (!sdp_audio_codec_cmp(&m->sdp, codec, false, false)) + return m->mgcp; + } + return NO_MGCP_CODEC; +} diff --git a/src/libmsc/csd_bs.c b/src/libmsc/csd_bs.c new file mode 100644 index 000000000..ab0b64309 --- /dev/null +++ b/src/libmsc/csd_bs.c @@ -0,0 +1,517 @@ +/* 3GPP TS 122.002 Bearer Services */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Oliver Smith + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ +#include <errno.h> + +#include <osmocom/msc/csd_bs.h> +#include <osmocom/msc/debug.h> + +/* csd_bs related below */ + +struct csd_bs_map { + /* BS number (20, 21, ...) */ + unsigned int num; + /* Access Structure (1: asynchronous, 0: synchronous) */ + bool async; + /* QoS Attribute (1: transparent, 0: non-transparent) */ + bool transp; + /* Rate Adaption (V110, V120 etc.) */ + enum gsm48_bcap_ra ra; + /* Fixed Network User Rate */ + unsigned int rate; +}; + +static const struct csd_bs_map bs_map[] = { + /* 3.1.1.1.2 */ + [CSD_BS_21_T_V110_0k3] = { + .num = 21, + .async = true, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 300, + }, + [CSD_BS_22_T_V110_1k2] = { + .num = 22, + .async = true, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 1200, + }, + [CSD_BS_24_T_V110_2k4] = { + .num = 24, + .async = true, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 2400, + }, + [CSD_BS_25_T_V110_4k8] = { + .num = 25, + .async = true, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 4800, + }, + [CSD_BS_26_T_V110_9k6] = { + .num = 26, + .async = true, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 9600, + }, + + /* 3.1.1.2.2 */ + [CSD_BS_21_NT_V110_0k3] = { + .num = 21, + .async = true, + .transp = false, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 300, + }, + [CSD_BS_22_NT_V110_1k2] = { + .num = 22, + .async = true, + .transp = false, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 1200, + }, + [CSD_BS_24_NT_V110_2k4] = { + .num = 24, + .async = true, + .transp = false, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 2400, + }, + [CSD_BS_25_NT_V110_4k8] = { + .num = 25, + .async = true, + .transp = false, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 4800, + }, + [CSD_BS_26_NT_V110_9k6] = { + .num = 26, + .async = true, + .transp = false, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 9600, + }, + + /* 3.1.2.1.2 */ + [CSD_BS_31_T_V110_1k2] = { + .num = 31, + .async = false, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 1200, + }, + [CSD_BS_32_T_V110_2k4] = { + .num = 32, + .async = false, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 2400, + }, + [CSD_BS_33_T_V110_4k8] = { + .num = 33, + .async = false, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 4800, + }, + [CSD_BS_34_T_V110_9k6] = { + .num = 34, + .async = false, + .transp = true, + .ra = GSM48_BCAP_RA_V110_X30, + .rate = 9600, + }, +}; + +osmo_static_assert(ARRAY_SIZE(bs_map) == CSD_BS_MAX, _invalid_size_bs_map); + +bool csd_bs_is_transp(enum csd_bs bs) +{ + return bs_map[bs].transp; +} + +/* Short single-line representation, convenient for logging. + * Like "BS25NT" */ +int csd_bs_to_str_buf(char *buf, size_t buflen, enum csd_bs bs) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + const struct csd_bs_map *map = &bs_map[bs]; + + OSMO_STRBUF_PRINTF(sb, "BS%u%s", + map->num, + map->transp ? "T" : "NT"); + + if (map->ra != GSM48_BCAP_RA_V110_X30) + OSMO_STRBUF_PRINTF(sb, "-RA=%d", map->ra); + + return sb.chars_needed; +} + +char *csd_bs_to_str_c(void *ctx, enum csd_bs bs) +{ + OSMO_NAME_C_IMPL(ctx, 32, "csd_bs_to_str_c-ERROR", csd_bs_to_str_buf, bs) +} + +const char *csd_bs_to_str(enum csd_bs bs) +{ + return csd_bs_to_str_c(OTC_SELECT, bs); +} + +static int csd_bs_to_gsm0808_data_rate_transp(enum csd_bs bs, uint8_t *ch_rate_type) +{ + switch (bs_map[bs].rate) { + case 300: + *ch_rate_type = GSM0808_DATA_FULL_PREF; + return GSM0808_DATA_RATE_TRANSP_600; + case 1200: + *ch_rate_type = GSM0808_DATA_FULL_PREF; + return GSM0808_DATA_RATE_TRANSP_1k2; + case 2400: + *ch_rate_type = GSM0808_DATA_FULL_PREF; + return GSM0808_DATA_RATE_TRANSP_2k4; + case 4800: + *ch_rate_type = GSM0808_DATA_FULL_PREF; + return GSM0808_DATA_RATE_TRANSP_4k8; + case 9600: + *ch_rate_type = GSM0808_DATA_FULL_BM; + return GSM0808_DATA_RATE_TRANSP_9k6; + } + return -EINVAL; +} + +static int csd_bs_to_gsm0808_data_rate_non_transp(enum csd_bs bs, uint8_t *ch_rate_type) +{ + uint16_t rate = bs_map[bs].rate; + + if (rate < 6000) { + *ch_rate_type = GSM0808_DATA_FULL_PREF; + return GSM0808_DATA_RATE_NON_TRANSP_6k0; + } + if (rate < 12000) { + *ch_rate_type = GSM0808_DATA_FULL_BM; + return GSM0808_DATA_RATE_NON_TRANSP_12k0; + } + + return -EINVAL; +} + +static int csd_bs_to_gsm0808_data_rate_non_transp_allowed(enum csd_bs bs) +{ + uint16_t rate = bs_map[bs].rate; + + if (rate < 6000) + return GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_6k0; + if (rate < 12000) + return GSM0808_DATA_RATE_NON_TRANSP_ALLOWED_12k0; + + return -EINVAL; +} + +enum csd_bs csd_bs_from_bearer_cap(const struct gsm_mncc_bearer_cap *cap, bool transp) +{ + enum gsm48_bcap_ra ra = cap->data.rate_adaption; + enum gsm48_bcap_user_rate rate = cap->data.user_rate; + bool async = cap->data.async; + + /* 3.1kHz CSD calls won't have the rate adaptation field set + but do require rate adaptation. */ + if (cap->data.interm_rate && !ra) + ra = GSM48_BCAP_RA_V110_X30; + + if (ra == GSM48_BCAP_RA_V110_X30 && async && transp) { + switch (rate) { + case GSM48_BCAP_UR_300: + return CSD_BS_21_T_V110_0k3; + case GSM48_BCAP_UR_1200: + return CSD_BS_22_T_V110_1k2; + case GSM48_BCAP_UR_2400: + return CSD_BS_24_T_V110_2k4; + case GSM48_BCAP_UR_4800: + return CSD_BS_25_T_V110_4k8; + case GSM48_BCAP_UR_9600: + return CSD_BS_26_T_V110_9k6; + default: + return CSD_BS_NONE; + } + } + + if (ra == GSM48_BCAP_RA_V110_X30 && async && !transp) { + switch (rate) { + case GSM48_BCAP_UR_300: + return CSD_BS_21_NT_V110_0k3; + case GSM48_BCAP_UR_1200: + return CSD_BS_22_NT_V110_1k2; + case GSM48_BCAP_UR_2400: + return CSD_BS_24_NT_V110_2k4; + case GSM48_BCAP_UR_4800: + return CSD_BS_25_NT_V110_4k8; + case GSM48_BCAP_UR_9600: + return CSD_BS_26_NT_V110_9k6; + default: + return CSD_BS_NONE; + } + } + + if (ra == GSM48_BCAP_RA_V110_X30 && !async && transp) { + switch (rate) { + case GSM48_BCAP_UR_1200: + return CSD_BS_31_T_V110_1k2; + case GSM48_BCAP_UR_2400: + return CSD_BS_32_T_V110_2k4; + case GSM48_BCAP_UR_4800: + return CSD_BS_33_T_V110_4k8; + case GSM48_BCAP_UR_9600: + return CSD_BS_34_T_V110_9k6; + default: + return CSD_BS_NONE; + } + } + + return CSD_BS_NONE; +} + +/* csd_bs_list related below */ + +int csd_bs_list_to_str_buf(char *buf, size_t buflen, const struct csd_bs_list *list) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + int i; + + if (!list->count) + OSMO_STRBUF_PRINTF(sb, "(no-bearer-services)"); + + for (i = 0; i < list->count; i++) { + if (i) + OSMO_STRBUF_PRINTF(sb, ","); + + OSMO_STRBUF_APPEND(sb, csd_bs_to_str_buf, list->bs[i]); + } + return sb.chars_needed; +} + +char *csd_bs_list_to_str_c(void *ctx, const struct csd_bs_list *list) +{ + OSMO_NAME_C_IMPL(ctx, 128, "csd_bs_list_to_str_c-ERROR", csd_bs_list_to_str_buf, list) +} + +const char *csd_bs_list_to_str(const struct csd_bs_list *list) +{ + return csd_bs_list_to_str_c(OTC_SELECT, list); +} + +bool csd_bs_list_has_bs(const struct csd_bs_list *list, enum csd_bs bs) +{ + int i; + + for (i = 0; i < list->count; i++) { + if (list->bs[i] == bs) + return true; + } + + return false; +} + +void csd_bs_list_add_bs(struct csd_bs_list *list, enum csd_bs bs) +{ + int i; + + if (!bs) + return; + + for (i = 0; i < list->count; i++) { + if (list->bs[i] == bs) + return; + } + + list->bs[i] = bs; + list->count++; +} + +void csd_bs_list_remove(struct csd_bs_list *list, enum csd_bs bs) +{ + int i; + bool found = false; + + for (i = 0; i < list->count; i++) { + if (list->bs[i] == bs) + found = true; + if (found && i + 1 < list->count) + list->bs[i] = list->bs[i + 1]; + } + + if (found) + list->count--; +} + +void csd_bs_list_intersection(struct csd_bs_list *dest, const struct csd_bs_list *other) +{ + int i; + + for (i = 0; i < dest->count; i++) { + if (csd_bs_list_has_bs(other, dest->bs[i])) + continue; + csd_bs_list_remove(dest, dest->bs[i]); + i--; + } +} + +int csd_bs_list_to_gsm0808_channel_type(struct gsm0808_channel_type *ct, const struct csd_bs_list *list) +{ + int i; + int rc; + + *ct = (struct gsm0808_channel_type){ + .ch_indctr = GSM0808_CHAN_DATA, + }; + + if (!list->count) + return -EINVAL; + + if (csd_bs_is_transp(list->bs[0])) { + ct->data_transparent = true; + rc = csd_bs_to_gsm0808_data_rate_transp(list->bs[0], &ct->ch_rate_type); + } else { + rc = csd_bs_to_gsm0808_data_rate_non_transp(list->bs[0], &ct->ch_rate_type); + } + + if (rc < 0) + return -EINVAL; + + ct->data_rate = rc; + + /* Other possible data rates allowed (3GPP TS 48.008 § 3.2.2.11, 5a) */ + if (!ct->data_transparent && list->count > 1) { + for (i = 1; i < list->count; i++) { + if (!csd_bs_is_transp(list->bs[i])) + continue; + + rc = csd_bs_to_gsm0808_data_rate_non_transp_allowed(list->bs[i]); + if (rc < 0) { + LOGP(DMSC, LOGL_DEBUG, "Failed to convert %s to allowed r i/f rate\n", + csd_bs_to_str(list->bs[i])); + continue; + } + + ct->data_rate_allowed |= rc; + } + if (ct->data_rate_allowed) + ct->data_rate_allowed_is_set = true; + } + + return 0; +} + +int csd_bs_list_to_bearer_cap(struct gsm_mncc_bearer_cap *cap, const struct csd_bs_list *list) +{ + *cap = (struct gsm_mncc_bearer_cap){ + .transfer = GSM_MNCC_BCAP_UNR_DIG, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_FR_ONLY, + }; + enum csd_bs bs; + int i; + + for (i = 0; i < list->count; i++) { + bs = list->bs[i]; + + cap->data.rate_adaption = GSM48_BCAP_RA_V110_X30; + cap->data.sig_access = GSM48_BCAP_SA_I440_I450; + cap->data.async = bs_map[bs].async; + if (bs_map[bs].transp) + cap->data.transp = GSM48_BCAP_TR_TRANSP; + else + cap->data.transp = GSM48_BCAP_TR_RLP; + + /* FIXME: proper values for sync/async (current: 8N1) */ + cap->data.nr_data_bits = 8; + cap->data.parity = GSM48_BCAP_PAR_NONE; + cap->data.nr_stop_bits = 1; + cap->data.modem_type = GSM48_BCAP_MT_NONE; + + switch (bs_map[bs].rate) { + case 300: + cap->data.user_rate = GSM48_BCAP_UR_300; + cap->data.interm_rate = GSM48_BCAP_IR_8k; + break; + case 1200: + cap->data.user_rate = GSM48_BCAP_UR_1200; + cap->data.interm_rate = GSM48_BCAP_IR_8k; + break; + case 2400: + cap->data.user_rate = GSM48_BCAP_UR_2400; + cap->data.interm_rate = GSM48_BCAP_IR_8k; + break; + case 4800: + cap->data.user_rate = GSM48_BCAP_UR_4800; + cap->data.interm_rate = GSM48_BCAP_IR_8k; + break; + case 9600: + cap->data.user_rate = GSM48_BCAP_UR_9600; + cap->data.interm_rate = GSM48_BCAP_IR_16k; + break; + default: + LOGP(DMSC, LOGL_ERROR, + "%s(): bs=%d (rate=%u) is not implemented\n", + __func__, bs, bs_map[bs].rate); + continue; + } + + /* FIXME: handle more than one list entry */ + return 1; + } + + return 0; +} + +void csd_bs_list_from_bearer_cap(struct csd_bs_list *list, const struct gsm_mncc_bearer_cap *cap) +{ + *list = (struct csd_bs_list){}; + + switch (cap->data.transp) { + case GSM48_BCAP_TR_TRANSP: + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, true)); + break; + case GSM48_BCAP_TR_RLP: /* NT */ + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, false)); + break; + case GSM48_BCAP_TR_TR_PREF: + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, true)); + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, false)); + break; + case GSM48_BCAP_TR_RLP_PREF: + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, false)); + csd_bs_list_add_bs(list, csd_bs_from_bearer_cap(cap, true)); + break; + } + + if (!list->count) { + LOGP(DMSC, LOGL_ERROR, "Failed to get bearer service from bearer capabilities ra=%d, async=%d," + " transp=%d, user_rate=%d\n", cap->data.rate_adaption, cap->data.async, cap->data.transp, + cap->data.user_rate); + return; + } +} diff --git a/src/libmsc/csd_filter.c b/src/libmsc/csd_filter.c new file mode 100644 index 000000000..0f428cffe --- /dev/null +++ b/src/libmsc/csd_filter.c @@ -0,0 +1,157 @@ +/* Filter/overlay bearer service selections across MS, RAN and CN limitations */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Oliver Smith + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ + +#include <osmocom/mgcp_client/mgcp_client.h> + +#include <osmocom/msc/csd_filter.h> + +static void add_all_geran_bs(struct csd_bs_list *list) +{ + /* See 3GPP TS 122.002 Bearer Services */ + /* In order of preference. TODO: make configurable */ + + /* GSM-R */ + csd_bs_list_add_bs(list, CSD_BS_24_T_V110_2k4); + csd_bs_list_add_bs(list, CSD_BS_25_T_V110_4k8); + csd_bs_list_add_bs(list, CSD_BS_26_T_V110_9k6); + + /* Other */ + csd_bs_list_add_bs(list, CSD_BS_21_T_V110_0k3); + csd_bs_list_add_bs(list, CSD_BS_22_T_V110_1k2); + csd_bs_list_add_bs(list, CSD_BS_21_NT_V110_0k3); + csd_bs_list_add_bs(list, CSD_BS_22_NT_V110_1k2); + csd_bs_list_add_bs(list, CSD_BS_24_NT_V110_2k4); + csd_bs_list_add_bs(list, CSD_BS_25_NT_V110_4k8); + csd_bs_list_add_bs(list, CSD_BS_26_NT_V110_9k6); + csd_bs_list_add_bs(list, CSD_BS_31_T_V110_1k2); + csd_bs_list_add_bs(list, CSD_BS_32_T_V110_2k4); + csd_bs_list_add_bs(list, CSD_BS_33_T_V110_4k8); + csd_bs_list_add_bs(list, CSD_BS_34_T_V110_9k6); +} + +static void add_all_utran_bs(struct csd_bs_list *list) +{ + /* See 3GPP TS 122.002 Bearer Services */ + /* In order of preference. TODO: make configurable */ + csd_bs_list_add_bs(list, CSD_BS_21_NT_V110_0k3); + csd_bs_list_add_bs(list, CSD_BS_22_NT_V110_1k2); + csd_bs_list_add_bs(list, CSD_BS_24_NT_V110_2k4); + csd_bs_list_add_bs(list, CSD_BS_25_NT_V110_4k8); + csd_bs_list_add_bs(list, CSD_BS_26_NT_V110_9k6); +} + +void csd_filter_set_ran(struct csd_filter *filter, enum osmo_rat_type ran_type) +{ + filter->ran = (struct csd_bs_list){}; + + switch (ran_type) { + default: + case OSMO_RAT_GERAN_A: + add_all_geran_bs(&filter->ran); + break; + case OSMO_RAT_UTRAN_IU: + add_all_utran_bs(&filter->ran); + break; + } +} + +int csd_filter_run(struct csd_filter *filter, struct sdp_msg *result, const struct sdp_msg *remote) +{ + struct csd_bs_list *r = &result->bearer_services; + enum csd_bs a = filter->assignment; + + *r = filter->ran; + + if (filter->ms.count) + csd_bs_list_intersection(r, &filter->ms); + if (filter->bss.count) + csd_bs_list_intersection(r, &filter->bss); + if (remote->bearer_services.count) + csd_bs_list_intersection(r, &remote->bearer_services); + + /* Future: If osmo-msc were able to trigger a re-assignment [...] see + * comment in codec_filter_run(). */ + + if (a) { + *r = (struct csd_bs_list){}; + csd_bs_list_add_bs(r, a); + } + + result->audio_codecs.count = 1; + result->audio_codecs.codec[0] = (struct sdp_audio_codec){ + .payload_type = CODEC_CLEARMODE, + .subtype_name = "CLEARMODE", + .rate = 8000, + }; + + return 0; +} + + +int csd_filter_to_str_buf(char *buf, size_t buflen, const struct csd_filter *filter, + const struct sdp_msg *result, const struct sdp_msg *remote) +{ + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, result); + OSMO_STRBUF_PRINTF(sb, " (from:"); + + if (filter->assignment) { + OSMO_STRBUF_PRINTF(sb, " assigned="); + OSMO_STRBUF_APPEND(sb, csd_bs_to_str_buf, filter->assignment); + } + + if (remote->bearer_services.count || osmo_sockaddr_str_is_nonzero(&remote->rtp)) { + OSMO_STRBUF_PRINTF(sb, " remote="); + OSMO_STRBUF_APPEND(sb, sdp_msg_to_str_buf, remote); + } + + if (filter->ms.count) { + OSMO_STRBUF_PRINTF(sb, " MS={"); + OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->ms); + OSMO_STRBUF_PRINTF(sb, "}"); + } + + if (filter->bss.count) { + OSMO_STRBUF_PRINTF(sb, " bss={"); + OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->bss); + OSMO_STRBUF_PRINTF(sb, "}"); + } + + OSMO_STRBUF_PRINTF(sb, " RAN={"); + OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &filter->ran); + OSMO_STRBUF_PRINTF(sb, "}"); + + OSMO_STRBUF_PRINTF(sb, ")"); + + return sb.chars_needed; +} + +char *csd_filter_to_str_c(void *ctx, const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote) +{ + OSMO_NAME_C_IMPL(ctx, 128, "csd_filter_to_str_c-ERROR", csd_filter_to_str_buf, filter, result, remote) +} + +const char *csd_filter_to_str(const struct csd_filter *filter, const struct sdp_msg *result, const struct sdp_msg *remote) +{ + return csd_filter_to_str_c(OTC_SELECT, filter, result, remote); +} diff --git a/src/libmsc/db.c b/src/libmsc/db.c index a1683beef..d12f04c13 100644 --- a/src/libmsc/db.c +++ b/src/libmsc/db.c @@ -1,7 +1,7 @@ -/* Simple HLR/VLR database backend using dbi */ +/* Simple HLR/VLR database backend using sqlite3 */ /* (C) 2008 by Jan Luebbe <jluebbe@debian.org> * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> - * (C) 2009 by Harald Welte <laforge@gnumonks.org> + * (C) 2009,2022 by Harald Welte <laforge@gnumonks.org> * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ #include <string.h> #include <errno.h> #include <time.h> -#include <dbi/dbi.h> +#include <sqlite3.h> #include <osmocom/msc/gsm_data.h> #include <osmocom/msc/gsm_subscriber.h> @@ -43,12 +43,36 @@ #include <osmocom/core/rate_ctr.h> #include <osmocom/core/utils.h> -static char *db_basename = NULL; -static char *db_dirname = NULL; -static dbi_conn conn; -static dbi_inst inst; +enum stmt_idx { + DB_STMT_SMS_STORE, + DB_STMT_SMS_GET, + DB_STMT_SMS_GET_NEXT_UNSENT, + DB_STMT_SMS_GET_UNSENT_FOR_SUBSCR, + DB_STMT_SMS_GET_NEXT_UNSENT_RR_MSISDN, + DB_STMT_SMS_MARK_DELIVERED, + DB_STMT_SMS_INC_DELIVER_ATTEMPTS, + DB_STMT_SMS_DEL_BY_MSISDN, + DB_STMT_SMS_DEL_BY_ID, + DB_STMT_SMS_DEL_EXPIRED, + DB_STMT_SMS_GET_VALID_UNTIL_BY_ID, + DB_STMT_SMS_GET_OLDEST_EXPIRED, + _NUM_DB_STMT +}; + +struct db_context { + char *fname; + sqlite3 *db; + sqlite3_stmt *stmt[_NUM_DB_STMT]; +}; + +static struct db_context *g_dbc; + -#define SCHEMA_REVISION "5" +/*********************************************************************** + * DATABASE SCHEMA AND MIGRATION + ***********************************************************************/ + +#define SCHEMA_REVISION "6" enum { SCHEMA_META, @@ -181,601 +205,540 @@ static const char *create_stmts[] = { ")", }; -static inline int next_row(dbi_result result) +/*********************************************************************** + * PREPARED STATEMENTS + ***********************************************************************/ + +/* don't change this order as the code assumes this ordering when dereferencing + * database query results! */ +#define SEL_COLUMNS \ + "id," \ + "strftime('%s',created)," \ + "sent," \ + "deliver_attempts," \ + "strftime('%s', valid_until)," \ + "reply_path_req," \ + "status_rep_req," \ + "is_report," \ + "msg_ref," \ + "protocol_id," \ + "data_coding_scheme," \ + "ud_hdr_ind," \ + "src_addr," \ + "src_ton," \ + "src_npi," \ + "dest_addr," \ + "dest_ton," \ + "dest_npi," \ + "user_data," \ + "header," \ + "text" + +enum db_sms_column_idx { + COL_ID, + COL_CREATED, + COL_SENT, + COL_DELIVER_ATTEMPTS, + COL_VALID_UNTIL, + COL_REPLY_PATH_REQ, + COL_STATUS_REP_REQ, + COL_IS_REPORT, + COL_MSG_REF, + COL_PROTOCOL_ID, + COL_DATA_CODING_SCHEME, + COL_UD_HDR_IND, + COL_SRC_ADDR, + COL_SRC_TON, + COL_SRC_NPI, + COL_DEST_ADDR, + COL_DEST_TON, + COL_DEST_NPI, + COL_USER_DATA, + COL_HEADER, + COL_TEXT, +}; + +static const char *stmt_sql[] = { + [DB_STMT_SMS_STORE] = + "INSERT INTO SMS " + "(created, valid_until, reply_path_req, status_rep_req, is_report, " + " msg_ref, protocol_id, data_coding_scheme, ud_hdr_ind, user_data, text, " + " dest_addr, dest_ton, dest_npi, src_addr, src_ton, src_npi) " + "VALUES " + "(datetime($created, 'unixepoch'), datetime($valid_until, 'unixepoch'), " + "$reply_path_req, $status_rep_req, $is_report, " + "$msg_ref, $protocol_id, $data_coding_scheme, $ud_hdr_ind, $user_data, $text, " + "$dest_addr, $dest_ton, $dest_npi, $src_addr, $src_ton, $src_npi)", + [DB_STMT_SMS_GET] = "SELECT " SEL_COLUMNS " FROM SMS WHERE SMS.id = $id", + [DB_STMT_SMS_GET_NEXT_UNSENT] = + "SELECT " SEL_COLUMNS " FROM SMS" + " WHERE sent IS NULL" + " AND id >= $id" + " AND deliver_attempts <= $attempts" + " ORDER BY id LIMIT 1", + [DB_STMT_SMS_GET_UNSENT_FOR_SUBSCR] = + "SELECT " SEL_COLUMNS " FROM SMS" + " WHERE sent IS NULL" + " AND dest_addr = $dest_addr" + " AND deliver_attempts <= $attempts" + " ORDER BY id LIMIT 1", + [DB_STMT_SMS_GET_NEXT_UNSENT_RR_MSISDN] = + "SELECT " SEL_COLUMNS " FROM SMS" + " WHERE sent IS NULL" + " AND dest_addr > $dest_addr" + " AND deliver_attempts <= $attempts" + " ORDER BY dest_addr, id LIMIT 1", + [DB_STMT_SMS_MARK_DELIVERED] = + "UPDATE SMS " + " SET sent = datetime('now') " + " WHERE id = $id", + [DB_STMT_SMS_INC_DELIVER_ATTEMPTS] = + "UPDATE SMS " + " SET deliver_attempts = deliver_attempts + 1 " + " WHERE id = $id", + [DB_STMT_SMS_DEL_BY_MSISDN] = + "DELETE FROM SMS WHERE src_addr=$src_addr OR dest_addr=$dest_addr", + [DB_STMT_SMS_DEL_BY_ID] = + "DELETE FROM SMS WHERE id = $id AND sent is NOT NULL", + [DB_STMT_SMS_DEL_EXPIRED] = + "DELETE FROM SMS WHERE id = $id", + [DB_STMT_SMS_GET_VALID_UNTIL_BY_ID] = + "SELECT strftime('%s', valid_until) FROM SMS WHERE id = $id", + [DB_STMT_SMS_GET_OLDEST_EXPIRED] = + "SELECT id, strftime('%s', valid_until) FROM SMS ORDER BY valid_until LIMIT 1", +}; + +/*********************************************************************** + * libsqlite3 helpers + ***********************************************************************/ + +/* libsqlite3 call-back for error logging */ +static void sql3_error_log_cb(void *arg, int err_code, const char *msg) { - if (!dbi_result_has_next_row(result)) - return 0; - return dbi_result_next_row(result); + LOGP(DDB, LOGL_ERROR, "SQLITE3: (%d) %s\n", err_code, msg); + osmo_log_backtrace(DDB, LOGL_ERROR); } -void db_error_func(dbi_conn conn, void *data) +/* libsqlite3 call-back for normal logging */ +static void sql3_sql_log_cb(void *arg, sqlite3 *s3, const char *stmt, int type) { - const char *msg; - dbi_conn_error(conn, &msg); - LOGP(DDB, LOGL_ERROR, "DBI: %s\n", msg); - osmo_log_backtrace(DDB, LOGL_ERROR); + switch (type) { + case 0: + LOGP(DDB, LOGL_DEBUG, "Opened database\n"); + break; + case 1: + LOGP(DDB, LOGL_DEBUG, "%s\n", stmt); + break; + case 2: + LOGP(DDB, LOGL_DEBUG, "Closed database\n"); + break; + default: + LOGP(DDB, LOGL_DEBUG, "Unknown %d\n", type); + break; + } } -static int update_db_revision_2(void) +/* remove statement bindings and reset statement to be re-executed */ +static void db_remove_reset(sqlite3_stmt *stmt) { - dbi_result result; + sqlite3_clear_bindings(stmt); + /* sqlite3_reset() just repeats an error code already evaluated during sqlite3_step(). */ + /* coverity[CHECKED_RETURN] */ + sqlite3_reset(stmt); +} - result = dbi_conn_query(conn, - "ALTER TABLE Subscriber " - "ADD COLUMN expire_lu " - "TIMESTAMP DEFAULT NULL"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to alter table Subscriber (upgrade from rev 2).\n"); - return -EINVAL; +/** bind blob arg and do proper cleanup in case of failure. If param_name is + * NULL, bind to the first parameter (useful for SQL statements that have only + * one parameter). */ +static bool db_bind_blob(sqlite3_stmt *stmt, const char *param_name, + const uint8_t *blob, size_t blob_len) +{ + int rc; + int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1; + if (idx < 1) { + LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n", + param_name); + return false; } - dbi_result_free(result); - - result = dbi_conn_query(conn, - "UPDATE Meta " - "SET value = '3' " - "WHERE key = 'revision'"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to update DB schema revision (upgrade from rev 2).\n"); - return -EINVAL; + rc = sqlite3_bind_blob(stmt, idx, blob, blob_len, SQLITE_STATIC); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Error binding blob to SQL parameter %s: %d\n", + param_name ? param_name : "#1", rc); + db_remove_reset(stmt); + return false; } - dbi_result_free(result); - - return 0; + return true; } -static void parse_tp_ud_from_result(struct gsm_sms *sms, dbi_result result) +/** bind text arg and do proper cleanup in case of failure. If param_name is + * NULL, bind to the first parameter (useful for SQL statements that have only + * one parameter). */ +static bool db_bind_text(sqlite3_stmt *stmt, const char *param_name, const char *text) { - const unsigned char *user_data; - unsigned int user_data_len; - unsigned int text_len; - const char *text; - - /* Retrieve TP-UDL (User-Data-Length) in octets (regardless of DCS) */ - user_data_len = dbi_result_get_field_length(result, "user_data"); - if (user_data_len > sizeof(sms->user_data)) { - LOGP(DDB, LOGL_ERROR, - "SMS TP-UD length %u is too big, truncating to %zu\n", - user_data_len, sizeof(sms->user_data)); - user_data_len = (uint8_t) sizeof(sms->user_data); + int rc; + int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1; + if (idx < 1) { + LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n", + param_name); + return false; } - sms->user_data_len = user_data_len; - - /* Retrieve the TP-UD (User-Data) itself */ - if (user_data_len > 0) { - user_data = dbi_result_get_binary(result, "user_data"); - memcpy(sms->user_data, user_data, user_data_len); + rc = sqlite3_bind_text(stmt, idx, text, -1, SQLITE_STATIC); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Error binding text to SQL parameter %s: %d\n", + param_name ? param_name : "#1", rc); + db_remove_reset(stmt); + return false; } + return true; +} - /* Retrieve the text length (excluding '\0') */ - text_len = dbi_result_get_field_length(result, "text"); - if (text_len >= sizeof(sms->text)) { - LOGP(DDB, LOGL_ERROR, - "SMS text length %u is too big, truncating to %zu\n", - text_len, sizeof(sms->text) - 1); - /* OSMO_STRLCPY_ARRAY() does truncation for us */ +/** bind int arg and do proper cleanup in case of failure. If param_name is + * NULL, bind to the first parameter (useful for SQL statements that have only + * one parameter). */ +static bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr) +{ + int rc; + int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1; + if (idx < 1) { + LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n", + param_name); + return false; } - - /* Retrieve the text parsed from TP-UD (User-Data) */ - text = dbi_result_get_string(result, "text"); - if (text) - OSMO_STRLCPY_ARRAY(sms->text, text); + rc = sqlite3_bind_int(stmt, idx, nr); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n", + param_name ? param_name : "#1", rc); + db_remove_reset(stmt); + return false; + } + return true; } -/** - * Copied from the normal sms_from_result_v3 to avoid having - * to make sure that the real routine will remain backward - * compatible. - */ -static struct gsm_sms *sms_from_result_v3(dbi_result result) +/** bind int64 arg and do proper cleanup in case of failure. If param_name is + * NULL, bind to the first parameter (useful for SQL statements that have only + * one parameter). */ +static bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr) { - struct gsm_sms *sms = sms_alloc(); - long long unsigned int sender_id; - const char *daddr; - char buf[32]; - char *quoted; - dbi_result result2; - const char *extension; - - if (!sms) - return NULL; - - sms->id = dbi_result_get_ulonglong(result, "id"); - - /* find extension by id, assuming that the subscriber still exists in - * the db */ - sender_id = dbi_result_get_ulonglong(result, "sender_id"); - snprintf(buf, sizeof(buf), "%llu", sender_id); - - dbi_conn_quote_string_copy(conn, buf, "ed); - result2 = dbi_conn_queryf(conn, - "SELECT extension FROM Subscriber " - "WHERE id = %s ", quoted); - free(quoted); - extension = dbi_result_get_string(result2, "extension"); - if (extension) - OSMO_STRLCPY_ARRAY(sms->src.addr, extension); - dbi_result_free(result2); - /* got the extension */ - - sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req"); - sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req"); - sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind"); - sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id"); - sms->data_coding_scheme = dbi_result_get_ulonglong(result, - "data_coding_scheme"); - - daddr = dbi_result_get_string(result, "dest_addr"); - if (daddr) - OSMO_STRLCPY_ARRAY(sms->dst.addr, daddr); - - /* Parse TP-UD, TP-UDL and decoded text */ - parse_tp_ud_from_result(sms, result); - - return sms; + int rc; + int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1; + if (idx < 1) { + LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n", + param_name); + return false; + } + rc = sqlite3_bind_int64(stmt, idx, nr); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n", + param_name ? param_name : "#1", rc); + db_remove_reset(stmt); + return false; + } + return true; } -static int update_db_revision_3(void) +/* callback for sqlite3_exec() below */ +static int db_rev_exec_cb(void *priv, int num_cols, char **vals, char **names) { - dbi_result result; - struct gsm_sms *sms; + char **rev_s = priv; + OSMO_ASSERT(!strcmp(names[0], "value")); + *rev_s = talloc_strdup(NULL, vals[0]); + return 0; +} - LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 3\n"); +static int check_db_revision(struct db_context *dbc) +{ + char *errstr = NULL; + char *rev_s; + int db_rev = 0; + int rc; - result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to begin transaction (upgrade from rev 3)\n"); + /* Make a query */ + rc = sqlite3_exec(dbc->db, "SELECT value FROM Meta WHERE key = 'revision'", + db_rev_exec_cb, &rev_s, &errstr); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Cannot execute SELECT value from META: %s\n", errstr); + sqlite3_free(errstr); return -EINVAL; } - dbi_result_free(result); - /* Rename old SMS table to be able create a new one */ - result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_3"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to rename the old SMS table (upgrade from rev 3).\n"); - goto rollback; - } - dbi_result_free(result); - - /* Create new SMS table with all the bells and whistles! */ - result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to create a new SMS table (upgrade from rev 3).\n"); - goto rollback; + if (!strcmp(rev_s, SCHEMA_REVISION)) { + /* Everything is fine */ + talloc_free(rev_s); + return 0; } - dbi_result_free(result); - /* Cycle through old messages and convert them to the new format */ - result = dbi_conn_query(conn, "SELECT * FROM SMS_3"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed fetch messages from the old SMS table (upgrade from rev 3).\n"); - goto rollback; - } - while (next_row(result)) { - sms = sms_from_result_v3(result); - if (db_sms_store(sms) != 0) { - LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 3).\n"); - sms_free(sms); - dbi_result_free(result); - goto rollback; - } - sms_free(sms); - } - dbi_result_free(result); + LOGP(DDB, LOGL_NOTICE, "Detected DB Revision %s, expected %s\n", rev_s, SCHEMA_REVISION); - /* Remove the temporary table */ - result = dbi_conn_query(conn, "DROP TABLE SMS_3"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to drop the old SMS table (upgrade from rev 3).\n"); - goto rollback; - } - dbi_result_free(result); - - /* We're done. Bump DB Meta revision to 4 */ - result = dbi_conn_query(conn, - "UPDATE Meta " - "SET value = '4' " - "WHERE key = 'revision'"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to update DB schema revision (upgrade from rev 3).\n"); - goto rollback; - } - dbi_result_free(result); + db_rev = atoi(rev_s); + talloc_free(rev_s); - result = dbi_conn_query(conn, "COMMIT TRANSACTION"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to commit the transaction (upgrade from rev 3)\n"); + /* Incremental migration waterfall */ + switch (db_rev) { + case 2: + case 3: + case 4: + LOGP(DDB, LOGL_FATAL, "You must use osmo-msc 1.1.0 to 1.8.0 to upgrade database " + "schema from '%u' to '5', sorry\n", db_rev); + break; + case 5: + LOGP(DDB, LOGL_FATAL, "The storage format of BINARY data in the database " + "has changed. In order to deliver any pending SMS in your database, " + "you must manually convert your database from " + "'%u' to '6'. Alternatively you can use a fresh, blank database " + "with this version of osmo-msc, sorry.\n", db_rev); + return -1; + break; + default: + LOGP(DDB, LOGL_FATAL, "Invalid database schema revision '%d'.\n", db_rev); return -EINVAL; - } else { - dbi_result_free(result); } - /* Shrink DB file size by actually wiping out SMS_3 table data */ - result = dbi_conn_query(conn, "VACUUM"); - if (!result) - LOGP(DDB, LOGL_ERROR, - "VACUUM failed. Ignoring it (upgrade from rev 3).\n"); - else - dbi_result_free(result); - return 0; -rollback: - result = dbi_conn_query(conn, "ROLLBACK TRANSACTION"); - if (!result) - LOGP(DDB, LOGL_ERROR, - "Rollback failed (upgrade from rev 3).\n"); - else - dbi_result_free(result); +//error: + LOGP(DDB, LOGL_FATAL, "Failed to update database from schema revision '%d'.\n", db_rev); + talloc_free(rev_s); + return -EINVAL; } -/* Just like v3, but there is a new message reference field for status reports, - * that is set to zero for existing entries since there is no way we can infer - * this. - */ -static struct gsm_sms *sms_from_result_v4(dbi_result result) -{ - struct gsm_sms *sms = sms_alloc(); - const char *addr; - - if (!sms) - return NULL; - - sms->id = dbi_result_get_ulonglong(result, "id"); - - sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req"); - sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req"); - sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind"); - sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id"); - sms->data_coding_scheme = dbi_result_get_ulonglong(result, - "data_coding_scheme"); +/*********************************************************************** + * USER API + ***********************************************************************/ - addr = dbi_result_get_string(result, "src_addr"); - OSMO_STRLCPY_ARRAY(sms->src.addr, addr); - sms->src.ton = dbi_result_get_ulonglong(result, "src_ton"); - sms->src.npi = dbi_result_get_ulonglong(result, "src_npi"); +int db_init(void *ctx, const char *fname, bool enable_sqlite_logging) +{ + unsigned int i; + int rc; + bool has_sqlite_config_sqllog = false; - addr = dbi_result_get_string(result, "dest_addr"); - OSMO_STRLCPY_ARRAY(sms->dst.addr, addr); - sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton"); - sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi"); + g_dbc = talloc_zero(ctx, struct db_context); + OSMO_ASSERT(g_dbc); - /* Parse TP-UD, TP-UDL and decoded text */ - parse_tp_ud_from_result(sms, result); + /* we are a single-threaded program; we want to avoid all the mutex/etc. overhead */ + sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); - return sms; -} + LOGP(DDB, LOGL_NOTICE, "Init database connection to '%s' using SQLite3 lib version %s\n", + fname, sqlite3_libversion()); -static int update_db_revision_4(void) -{ - dbi_result result; - struct gsm_sms *sms; - - LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 4\n"); + g_dbc->fname = talloc_strdup(g_dbc, fname); - result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to begin transaction (upgrade from rev 4)\n"); - return -EINVAL; + for (i = 0; i < 0xfffff; i++) { + const char *o = sqlite3_compileoption_get(i); + if (!o) + break; + LOGP(DDB, LOGL_DEBUG, "SQLite3 compiled with '%s'\n", o); + if (!strcmp(o, "ENABLE_SQLLOG")) + has_sqlite_config_sqllog = true; } - dbi_result_free(result); - /* Rename old SMS table to be able create a new one */ - result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_4"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to rename the old SMS table (upgrade from rev 4).\n"); - goto rollback; + if (enable_sqlite_logging) { + rc = sqlite3_config(SQLITE_CONFIG_LOG, sql3_error_log_cb, NULL); + if (rc != SQLITE_OK) + LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 error log callback\n"); } - dbi_result_free(result); - /* Create new SMS table with all the bells and whistles! */ - result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to create a new SMS table (upgrade from rev 4).\n"); - goto rollback; + if (has_sqlite_config_sqllog) { + rc = sqlite3_config(SQLITE_CONFIG_SQLLOG, sql3_sql_log_cb, NULL); + if (rc != SQLITE_OK) + LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 SQL log callback\n"); + } else { + LOGP(DDB, LOGL_DEBUG, "Not setting SQL log callback:" + " SQLite3 compiled without support for it\n"); } - dbi_result_free(result); - /* Cycle through old messages and convert them to the new format */ - result = dbi_conn_query(conn, "SELECT * FROM SMS_4"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed fetch messages from the old SMS table (upgrade from rev 4).\n"); - goto rollback; - } - while (next_row(result)) { - sms = sms_from_result_v4(result); - if (db_sms_store(sms) != 0) { - LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 4).\n"); - sms_free(sms); - dbi_result_free(result); - goto rollback; - } - sms_free(sms); + rc = sqlite3_open(g_dbc->fname, &g_dbc->db); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Unable to open DB; rc =%d\n", rc); + talloc_free(g_dbc); + return -1; } - dbi_result_free(result); - /* Remove the temporary table */ - result = dbi_conn_query(conn, "DROP TABLE SMS_4"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to drop the old SMS table (upgrade from rev 4).\n"); - goto rollback; + /* enable extended result codes */ + rc = sqlite3_extended_result_codes(g_dbc->db, 1); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Unable to enable SQLite3 extended result codes\n"); + /* non-fatal */ } - dbi_result_free(result); - - /* We're done. Bump DB Meta revision to 4 */ - result = dbi_conn_query(conn, - "UPDATE Meta " - "SET value = '5' " - "WHERE key = 'revision'"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to update DB schema revision (upgrade from rev 4).\n"); - goto rollback; - } - dbi_result_free(result); - result = dbi_conn_query(conn, "COMMIT TRANSACTION"); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to commit the transaction (upgrade from rev 4)\n"); - return -EINVAL; - } else { - dbi_result_free(result); + char *err_msg; + rc = sqlite3_exec(g_dbc->db, "PRAGMA journal_mode=WAL; PRAGMA synchronous = NORMAL;", 0, 0, &err_msg); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Unable to set Write-Ahead Logging: %s\n", err_msg); + sqlite3_free(err_msg); + /* non-fatal */ } - /* Shrink DB file size by actually wiping out SMS_4 table data */ - result = dbi_conn_query(conn, "VACUUM"); - if (!result) - LOGP(DDB, LOGL_ERROR, - "VACUUM failed. Ignoring it (upgrade from rev 4).\n"); - else - dbi_result_free(result); + rc = sqlite3_exec(g_dbc->db, "PRAGMA secure_delete=0;", 0, 0, &err_msg); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Unable to disable SECURE_DELETE: %s\n", err_msg); + sqlite3_free(err_msg); + /* non-fatal */ + } return 0; - -rollback: - result = dbi_conn_query(conn, "ROLLBACK TRANSACTION"); - if (!result) - LOGP(DDB, LOGL_ERROR, - "Rollback failed (upgrade from rev 4).\n"); - else - dbi_result_free(result); - return -EINVAL; } -static int check_db_revision(void) +int db_fini(void) { - dbi_result result; - const char *rev_s; - int db_rev = 0; - - /* Make a query */ - result = dbi_conn_query(conn, - "SELECT value FROM Meta " - "WHERE key = 'revision'"); + unsigned int i; + int rc; - if (!result) - return -EINVAL; - - if (!next_row(result)) { - dbi_result_free(result); - return -EINVAL; - } - - /* Fetch the DB schema revision */ - rev_s = dbi_result_get_string(result, "value"); - if (!rev_s) { - dbi_result_free(result); - return -EINVAL; - } - - if (!strcmp(rev_s, SCHEMA_REVISION)) { - /* Everything is fine */ - dbi_result_free(result); + if (!g_dbc) return 0; - } - - db_rev = atoi(rev_s); - dbi_result_free(result); - /* Incremental migration waterfall */ - switch (db_rev) { - case 2: - if (update_db_revision_2()) - goto error; - /* fall through */ - case 3: - if (update_db_revision_3()) - goto error; - /* fall through */ - case 4: - if (update_db_revision_4()) - goto error; - - /* The end of waterfall */ - break; - default: - LOGP(DDB, LOGL_FATAL, - "Invalid database schema revision '%d'.\n", db_rev); - return -EINVAL; + for (i = 0; i < ARRAY_SIZE(g_dbc->stmt); i++) { + /* it is ok to call finalize on NULL */ + sqlite3_finalize(g_dbc->stmt[i]); } - return 0; - -error: - LOGP(DDB, LOGL_FATAL, "Failed to update database " - "from schema revision '%d'.\n", db_rev); - return -EINVAL; -} - -static int db_configure(void) -{ - dbi_result result; + /* Ask sqlite3 to close DB */ + rc = sqlite3_close(g_dbc->db); + if (rc != SQLITE_OK) { /* Make sure it's actually closed! */ + LOGP(DDB, LOGL_ERROR, "Couldn't close database: (rc=%d) %s\n", + rc, sqlite3_errmsg(g_dbc->db)); + } - result = dbi_conn_query(conn, - "PRAGMA synchronous = FULL"); - if (!result) - return -EINVAL; + talloc_free(g_dbc); + g_dbc = NULL; - dbi_result_free(result); return 0; } -int db_init(const char *name) +/* run (execute) a series of SQL statements */ +static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count) { - dbi_initialize_r(NULL, &inst); - - LOGP(DDB, LOGL_NOTICE, "Init database connection to '%s' using %s\n", - name, dbi_version()); - - conn = dbi_conn_new_r("sqlite3", inst); - if (conn == NULL) { - LOGP(DDB, LOGL_FATAL, "Failed to create database connection to sqlite3 db '%s'; " - "Is the sqlite3 database driver for libdbi installed on this system?\n", name); - return 1; + int i; + for (i = 0; i < statements_count; i++) { + const char *stmt_str = statements[i]; + char *errmsg = NULL; + int rc; + + rc = sqlite3_exec(dbc->db, stmt_str, NULL, NULL, &errmsg); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "SQL error during SQL statement '%s': %s\n", stmt_str, errmsg); + sqlite3_free(errmsg); + return -1; + } } - - dbi_conn_error_handler( conn, db_error_func, NULL ); - - /* MySQL - dbi_conn_set_option(conn, "host", "localhost"); - dbi_conn_set_option(conn, "username", "your_name"); - dbi_conn_set_option(conn, "password", "your_password"); - dbi_conn_set_option(conn, "dbname", "your_dbname"); - dbi_conn_set_option(conn, "encoding", "UTF-8"); - */ - - /* SqLite 3 */ - db_basename = strdup(name); - db_dirname = strdup(name); - dbi_conn_set_option(conn, "sqlite3_dbdir", dirname(db_dirname)); - dbi_conn_set_option(conn, "dbname", basename(db_basename)); - - if (dbi_conn_connect(conn) < 0) - goto out_err; - return 0; - -out_err: - free(db_dirname); - free(db_basename); - db_dirname = db_basename = NULL; - return -1; } - int db_prepare(void) { - dbi_result result; - int i; + unsigned int i; + int rc; - for (i = 0; i < ARRAY_SIZE(create_stmts); i++) { - result = dbi_conn_query(conn, create_stmts[i]); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to create some table.\n"); - return 1; - } - dbi_result_free(result); + OSMO_ASSERT(g_dbc); + rc = db_run_statements(g_dbc, create_stmts, ARRAY_SIZE(create_stmts)); + if (rc < 0) { + LOGP(DDB, LOGL_ERROR, "Failed to create some table.\n"); + return 1; } - if (check_db_revision() < 0) { + if (check_db_revision(g_dbc) < 0) { LOGP(DDB, LOGL_FATAL, "Database schema revision invalid, " "please update your database schema\n"); return -1; } - db_configure(); - - return 0; -} - -int db_fini(void) -{ - dbi_conn_close(conn); - dbi_shutdown_r(inst); + /* prepare all SQL statements */ + for (i = 0; i < ARRAY_SIZE(g_dbc->stmt); i++) { + rc = sqlite3_prepare_v2(g_dbc->db, stmt_sql[i], -1, + &g_dbc->stmt[i], NULL); + if (rc != SQLITE_OK) { + LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_sql[i]); + return -1; + } + } - free(db_dirname); - free(db_basename); return 0; } /* store an [unsent] SMS to the database */ int db_sms_store(struct gsm_sms *sms) { - dbi_result result; - char *q_text, *q_daddr, *q_saddr; - unsigned char *q_udata = NULL; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_STORE]; time_t now, validity_timestamp; - - dbi_conn_quote_string_copy(conn, (char *)sms->text, &q_text); - dbi_conn_quote_string_copy(conn, (char *)sms->dst.addr, &q_daddr); - dbi_conn_quote_string_copy(conn, (char *)sms->src.addr, &q_saddr); - - /* Guard against zero-length input, as this may cause - * buffer overruns in libdbi / libdbdsqlite3. */ - if (sms->user_data_len > 0) { - dbi_conn_quote_binary_copy(conn, sms->user_data, - sms->user_data_len, - &q_udata); - } + int rc; now = time(NULL); validity_timestamp = now + sms->validity_minutes * 60; - result = dbi_conn_queryf(conn, - "INSERT INTO SMS " - "(created, valid_until, " - "reply_path_req, status_rep_req, is_report, " - "msg_ref, protocol_id, data_coding_scheme, " - "ud_hdr_ind, " - "user_data, text, " - "dest_addr, dest_ton, dest_npi, " - "src_addr, src_ton, src_npi) VALUES " - "(datetime('%lld', 'unixepoch'), datetime('%lld', 'unixepoch'), " - "%u, %u, %u, " - "%u, %u, %u, " - "%u, " - "%s, %s, " - "%s, %u, %u, " - "%s, %u, %u)", - (int64_t)now, (int64_t)validity_timestamp, - sms->reply_path_req, sms->status_rep_req, sms->is_report, - sms->msg_ref, sms->protocol_id, sms->data_coding_scheme, - sms->ud_hdr_ind, - q_udata, q_text, - q_daddr, sms->dst.ton, sms->dst.npi, - q_saddr, sms->src.ton, sms->src.npi); - free(q_text); - free(q_udata); - free(q_daddr); - free(q_saddr); - - if (!result) + db_bind_int64(stmt, "$created", (int64_t) now); + db_bind_int64(stmt, "$valid_until", (int64_t) validity_timestamp); + db_bind_int(stmt, "$reply_path_req", sms->reply_path_req); + db_bind_int(stmt, "$status_rep_req", sms->status_rep_req); + db_bind_int(stmt, "$is_report", sms->is_report); + db_bind_int(stmt, "$msg_ref", sms->msg_ref); + db_bind_int(stmt, "$protocol_id", sms->protocol_id); + db_bind_int(stmt, "$data_coding_scheme", sms->data_coding_scheme); + db_bind_int(stmt, "$ud_hdr_ind", sms->ud_hdr_ind); + /* FIXME: do we need to use legacy DBI compatible quoting of sms->user_data? */ + db_bind_blob(stmt, "$user_data", sms->user_data, sms->user_data_len); + db_bind_text(stmt, "$text", (char *)sms->text); + db_bind_text(stmt, "$dest_addr", (char *)sms->dst.addr); + db_bind_int(stmt, "$dest_ton", sms->dst.ton); + db_bind_int(stmt, "$dest_npi", sms->dst.npi); + db_bind_text(stmt, "$src_addr", (char *)sms->src.addr); + db_bind_int(stmt, "$src_ton", sms->src.ton); + db_bind_int(stmt, "$src_npi", sms->src.npi); + + /* execute statement */ + rc = sqlite3_step(stmt); + db_remove_reset(stmt); + if (rc != SQLITE_DONE) { + LOGP(DDB, LOGL_ERROR, "Cannot create SMS: SQL error: (%d) %s\n", rc, sqlite3_errmsg(g_dbc->db)); return -EIO; + } - dbi_result_free(result); + sms->id = sqlite3_last_insert_rowid(g_dbc->db); - sms->id = dbi_conn_sequence_last(conn, "id"); LOGP(DLSMS, LOGL_INFO, "Stored SMS id=%llu in DB\n", sms->id); + return 0; } -static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result result) +static void parse_tp_ud_from_result(struct gsm_sms *sms, sqlite3_stmt *stmt) +{ + const unsigned char *user_data; + unsigned int user_data_len; + unsigned int text_len; + const char *text; + + /* Retrieve TP-UDL (User-Data-Length) in octets (regardless of DCS) */ + user_data_len = sqlite3_column_bytes(stmt, COL_USER_DATA); + if (user_data_len > sizeof(sms->user_data)) { + LOGP(DDB, LOGL_ERROR, + "SMS TP-UD length %u is too big, truncating to %zu\n", + user_data_len, sizeof(sms->user_data)); + user_data_len = (uint8_t) sizeof(sms->user_data); + } + sms->user_data_len = user_data_len; + + /* Retrieve the TP-UD (User-Data) itself */ + if (user_data_len > 0) { + user_data = sqlite3_column_blob(stmt, COL_USER_DATA); + memcpy(sms->user_data, user_data, user_data_len); + } + + /* Retrieve the text length (excluding '\0') */ + text_len = sqlite3_column_bytes(stmt, COL_TEXT); + if (text_len >= sizeof(sms->text)) { + LOGP(DDB, LOGL_ERROR, + "SMS text length %u is too big, truncating to %zu\n", + text_len, sizeof(sms->text) - 1); + /* OSMO_STRLCPY_ARRAY() does truncation for us */ + } + + /* Retrieve the text parsed from TP-UD (User-Data) */ + text = (const char *)sqlite3_column_text(stmt, COL_TEXT); + if (text) + OSMO_STRLCPY_ARRAY(sms->text, text); +} + +static struct gsm_sms *sms_from_result(struct gsm_network *net, sqlite3_stmt *stmt) { struct gsm_sms *sms = sms_alloc(); const char *daddr, *saddr; @@ -784,24 +747,23 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul if (!sms) return NULL; - sms->id = dbi_result_get_ulonglong(result, "id"); + sms->id = sqlite3_column_int64(stmt, COL_ID); + + sms->created = sqlite3_column_int64(stmt, COL_CREATED); + validity_timestamp = sqlite3_column_int64(stmt, COL_VALID_UNTIL); - sms->created = dbi_result_get_datetime(result, "created"); - validity_timestamp = dbi_result_get_datetime(result, "valid_until"); sms->validity_minutes = (validity_timestamp - sms->created) / 60; - /* FIXME: those should all be get_uchar, but sqlite3 is braindead */ - sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req"); - sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req"); - sms->is_report = dbi_result_get_ulonglong(result, "is_report"); - sms->msg_ref = dbi_result_get_ulonglong(result, "msg_ref"); - sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind"); - sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id"); - sms->data_coding_scheme = dbi_result_get_ulonglong(result, - "data_coding_scheme"); - - sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi"); - sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton"); - daddr = dbi_result_get_string(result, "dest_addr"); + sms->reply_path_req = sqlite3_column_int(stmt, COL_REPLY_PATH_REQ); + sms->status_rep_req = sqlite3_column_int(stmt, COL_STATUS_REP_REQ); + sms->is_report = sqlite3_column_int(stmt, COL_IS_REPORT); + sms->msg_ref = sqlite3_column_int(stmt, COL_MSG_REF); + sms->ud_hdr_ind = sqlite3_column_int(stmt, COL_UD_HDR_IND); + sms->protocol_id = sqlite3_column_int(stmt, COL_PROTOCOL_ID); + sms->data_coding_scheme = sqlite3_column_int(stmt, COL_DATA_CODING_SCHEME); + + sms->dst.npi = sqlite3_column_int(stmt, COL_DEST_NPI); + sms->dst.ton = sqlite3_column_int(stmt, COL_DEST_TON); + daddr = (const char *)sqlite3_column_text(stmt, COL_DEST_ADDR); if (daddr) OSMO_STRLCPY_ARRAY(sms->dst.addr, daddr); @@ -809,78 +771,72 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul sms->receiver = vlr_subscr_find_by_msisdn(net->vlr, sms->dst.addr, VSUB_USE_SMS_RECEIVER); - sms->src.npi = dbi_result_get_ulonglong(result, "src_npi"); - sms->src.ton = dbi_result_get_ulonglong(result, "src_ton"); - saddr = dbi_result_get_string(result, "src_addr"); + sms->src.npi = sqlite3_column_int(stmt, COL_SRC_NPI); + sms->src.ton = sqlite3_column_int(stmt, COL_SRC_TON); + saddr = (const char *)sqlite3_column_text(stmt, COL_SRC_ADDR); if (saddr) OSMO_STRLCPY_ARRAY(sms->src.addr, saddr); /* Parse TP-UD, TP-UDL and decoded text */ - parse_tp_ud_from_result(sms, result); + parse_tp_ud_from_result(sms, stmt); return sms; } struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET]; struct gsm_sms *sms; + int rc; - result = dbi_conn_queryf(conn, - "SELECT * FROM SMS WHERE SMS.id = %llu", id); - if (!result) - return NULL; + db_bind_int64(stmt, "$id", id); - if (!next_row(result)) { - dbi_result_free(result); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + db_remove_reset(stmt); return NULL; } - sms = sms_from_result(net, result); - - dbi_result_free(result); + sms = sms_from_result(net, stmt); + db_remove_reset(stmt); return sms; } struct gsm_sms *db_sms_get_next_unsent(struct gsm_network *net, unsigned long long min_sms_id, - unsigned int max_failed) + int max_failed) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET_NEXT_UNSENT]; struct gsm_sms *sms; + int rc; - result = dbi_conn_queryf(conn, - "SELECT * FROM SMS" - " WHERE sent IS NULL" - " AND id >= %llu" - " AND deliver_attempts <= %u" - " ORDER BY id LIMIT 1", - min_sms_id, max_failed); + db_bind_int64(stmt, "$id", min_sms_id); + db_bind_int(stmt, "$attempts", max_failed); - if (!result) - return NULL; - - if (!next_row(result)) { - dbi_result_free(result); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + db_remove_reset(stmt); return NULL; } - sms = sms_from_result(net, result); - - dbi_result_free(result); + sms = sms_from_result(net, stmt); + db_remove_reset(stmt); return sms; } /* retrieve the next unsent SMS for a given subscriber */ struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub, - unsigned int max_failed) + int max_failed) { + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET_UNSENT_FOR_SUBSCR]; struct gsm_network *net = vsub->vlr->user_ctx; - dbi_result result; struct gsm_sms *sms; - char *q_msisdn; + int rc; if (!vsub->lu_complete) return NULL; @@ -889,60 +845,42 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub, if (*vsub->msisdn == '\0') return NULL; - dbi_conn_quote_string_copy(conn, vsub->msisdn, &q_msisdn); - result = dbi_conn_queryf(conn, - "SELECT * FROM SMS" - " WHERE sent IS NULL" - " AND dest_addr = %s" - " AND deliver_attempts <= %u" - " ORDER BY id LIMIT 1", - q_msisdn, max_failed); - free(q_msisdn); - - if (!result) - return NULL; + db_bind_text(stmt, "$dest_addr", vsub->msisdn); + db_bind_int(stmt, "$attempts", max_failed); - if (!next_row(result)) { - dbi_result_free(result); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + db_remove_reset(stmt); return NULL; } - sms = sms_from_result(net, result); - - dbi_result_free(result); + sms = sms_from_result(net, stmt); + db_remove_reset(stmt); return sms; } struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net, const char *last_msisdn, - unsigned int max_failed) + int max_failed) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET_NEXT_UNSENT_RR_MSISDN]; struct gsm_sms *sms; - char *q_last_msisdn; + int rc; - dbi_conn_quote_string_copy(conn, last_msisdn, &q_last_msisdn); - result = dbi_conn_queryf(conn, - "SELECT * FROM SMS" - " WHERE sent IS NULL" - " AND dest_addr > %s" - " AND deliver_attempts <= %u" - " ORDER BY dest_addr, id LIMIT 1", - q_last_msisdn, max_failed); - free(q_last_msisdn); - - if (!result) - return NULL; + db_bind_text(stmt, "$dest_addr", last_msisdn); + db_bind_int(stmt, "$attempts", max_failed); - if (!next_row(result)) { - dbi_result_free(result); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + db_remove_reset(stmt); return NULL; } - sms = sms_from_result(net, result); + sms = sms_from_result(net, stmt); - dbi_result_free(result); + db_remove_reset(stmt); return sms; } @@ -950,84 +888,100 @@ struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net, /* mark a given SMS as delivered */ int db_sms_mark_delivered(struct gsm_sms *sms) { - dbi_result result; + sqlite3_stmt *stmt; + int rc; - result = dbi_conn_queryf(conn, - "UPDATE SMS " - "SET sent = datetime('now') " - "WHERE id = %llu", sms->id); - if (!result) { + /* this only happens in unit tests that don't db_init() */ + if (!g_dbc) + return 0; + + stmt = g_dbc->stmt[DB_STMT_SMS_MARK_DELIVERED]; + db_bind_int64(stmt, "$id", sms->id); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + db_remove_reset(stmt); LOGP(DDB, LOGL_ERROR, "Failed to mark SMS %llu as sent.\n", sms->id); return 1; } - dbi_result_free(result); + db_remove_reset(stmt); return 0; } /* increase the number of attempted deliveries */ int db_sms_inc_deliver_attempts(struct gsm_sms *sms) { - dbi_result result; + sqlite3_stmt *stmt; + int rc; - result = dbi_conn_queryf(conn, - "UPDATE SMS " - "SET deliver_attempts = deliver_attempts + 1 " - "WHERE id = %llu", sms->id); - if (!result) { - LOGP(DDB, LOGL_ERROR, "Failed to inc deliver attempts for " - "SMS %llu.\n", sms->id); + /* this only happens in unit tests that don't db_init() */ + if (!g_dbc) + return 0; + + stmt = g_dbc->stmt[DB_STMT_SMS_INC_DELIVER_ATTEMPTS]; + db_bind_int64(stmt, "$id", sms->id); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + db_remove_reset(stmt); + LOGP(DDB, LOGL_ERROR, "Failed to inc deliver attempts for SMS %llu.\n", sms->id); return 1; } - dbi_result_free(result); + db_remove_reset(stmt); return 0; } /* Drop all pending SMS to or from the given extension */ int db_sms_delete_by_msisdn(const char *msisdn) { - dbi_result result; - char *q_msisdn; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_DEL_BY_MSISDN]; + int rc; + if (!msisdn || !*msisdn) return 0; - dbi_conn_quote_string_copy(conn, msisdn, &q_msisdn); - result = dbi_conn_queryf(conn, - "DELETE FROM SMS WHERE src_addr=%s OR dest_addr=%s", - q_msisdn, q_msisdn); - free(q_msisdn); + db_bind_text(stmt, "$src_addr", msisdn); + db_bind_text(stmt, "$dest_addr", msisdn); - if (!result) { - LOGP(DDB, LOGL_ERROR, - "Failed to delete SMS for %s\n", msisdn); + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + db_remove_reset(stmt); + LOGP(DDB, LOGL_ERROR, "Failed to delete SMS for %s\n", msisdn); return -1; } - dbi_result_free(result); + + db_remove_reset(stmt); return 0; } int db_sms_delete_sent_message_by_id(unsigned long long sms_id) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_DEL_BY_ID]; + int rc; + + db_bind_int64(stmt, "$id", sms_id); - result = dbi_conn_queryf(conn, - "DELETE FROM SMS WHERE id = %llu AND sent is NOT NULL", - sms_id); - if (!result) { + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + db_remove_reset(stmt); LOGP(DDB, LOGL_ERROR, "Failed to delete SMS %llu.\n", sms_id); return 1; } - dbi_result_free(result); + db_remove_reset(stmt); return 0; } - static int delete_expired_sms(unsigned long long sms_id, time_t validity_timestamp) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_DEL_EXPIRED]; time_t now; + int rc; now = time(NULL); @@ -1035,51 +989,55 @@ static int delete_expired_sms(unsigned long long sms_id, time_t validity_timesta if (validity_timestamp > now) return -1; - result = dbi_conn_queryf(conn, "DELETE FROM SMS WHERE id = %llu", sms_id); - if (!result) { + db_bind_int64(stmt, "$id", sms_id); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + db_remove_reset(stmt); LOGP(DDB, LOGL_ERROR, "Failed to delete SMS %llu.\n", sms_id); return -1; } - dbi_result_free(result); + + db_remove_reset(stmt); return 0; } int db_sms_delete_expired_message_by_id(unsigned long long sms_id) { - dbi_result result; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET_VALID_UNTIL_BY_ID]; time_t validity_timestamp; + int rc; - result = dbi_conn_queryf(conn, "SELECT valid_until FROM SMS WHERE id = %llu", sms_id); - if (!result) - return -1; - if (!next_row(result)) { - dbi_result_free(result); + db_bind_int64(stmt, "$id", sms_id); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW) { + db_remove_reset(stmt); return -1; } - validity_timestamp = dbi_result_get_datetime(result, "valid_until"); + validity_timestamp = sqlite3_column_int64(stmt, 0); - dbi_result_free(result); + db_remove_reset(stmt); return delete_expired_sms(sms_id, validity_timestamp); } void db_sms_delete_oldest_expired_message(void) { - dbi_result result; - - result = dbi_conn_queryf(conn, "SELECT id,valid_until FROM SMS " - "ORDER BY valid_until LIMIT 1"); - if (!result) - return; + OSMO_ASSERT(g_dbc); + sqlite3_stmt *stmt = g_dbc->stmt[DB_STMT_SMS_GET_OLDEST_EXPIRED]; + int rc; - if (next_row(result)) { + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { unsigned long long sms_id; time_t validity_timestamp; - sms_id = dbi_result_get_ulonglong(result, "id"); - validity_timestamp = dbi_result_get_datetime(result, "valid_until"); + sms_id = sqlite3_column_int64(stmt, 0); + validity_timestamp = sqlite3_column_int64(stmt, 1); delete_expired_sms(sms_id, validity_timestamp); } - dbi_result_free(result); + db_remove_reset(stmt); } diff --git a/src/libmsc/e_link.c b/src/libmsc/e_link.c index 0a2be795c..b26f53bc5 100644 --- a/src/libmsc/e_link.c +++ b/src/libmsc/e_link.c @@ -1,6 +1,6 @@ /* E-interface messaging over a GSUP connection */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index b5d46fda3..17350faad 100644 --- a/src/libmsc/gsm_04_08.c +++ b/src/libmsc/gsm_04_08.c @@ -36,6 +36,7 @@ #include <osmocom/msc/debug.h> #include <osmocom/msc/gsm_data.h> #include <osmocom/msc/gsm_04_08.h> +#include <osmocom/msc/msc_vgcs.h> #include <osmocom/msc/signal.h> #include <osmocom/msc/transaction.h> #include <osmocom/msc/vlr.h> @@ -119,12 +120,7 @@ static int gsm0408_loc_upd_acc(struct msc_a *msc_a, uint32_t send_tmsi) struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 LOC UPD ACC"); struct gsm48_hdr *gh; struct gsm48_loc_area_id *lai; - struct gsm_network *net = msc_a_net(msc_a); struct vlr_subscr *vsub = msc_a_vsub(msc_a); - struct osmo_location_area_id laid = { - .plmn = net->plmn, - .lac = vsub->cgi.lai.lac, - }; uint8_t *l; int rc; struct osmo_mobile_identity mi = {}; @@ -134,7 +130,7 @@ static int gsm0408_loc_upd_acc(struct msc_a *msc_a, uint32_t send_tmsi) gh->msg_type = GSM48_MT_MM_LOC_UPD_ACCEPT; lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai)); - gsm48_generate_lai2(lai, &laid); + gsm48_generate_lai2(lai, &vsub->cgi.lai); if (send_tmsi == GSM_RESERVED_TMSI) { /* we did not allocate a TMSI to the MS, so we need to @@ -246,7 +242,9 @@ static int msc_gsm48_tx_mm_serv_ack(struct msc_a *msc_a) return msc_a_tx_dtap_to_i(msc_a, msg); } -/* 9.2.6 CM service reject */ +/* 9.2.6 CM service reject. + * For an active and valid CM Service Request, instead use msc_vlr_tx_cm_serv_rej(), which also takes care of + * decrementing the use token for that service type. */ static int msc_gsm48_tx_mm_serv_rej(struct msc_a *msc_a, enum gsm48_reject_value value) { @@ -415,7 +413,8 @@ static int mm_rx_loc_upd_req(struct msc_a *msc_a, struct msgb *msg) net->vlr, msc_a, vlr_lu_type, tmsi, imsi, &old_lai, &msc_a->via_cell.lai, is_utran || net->authentication_required, - msc_a_require_ciphering(msc_a), + msc_a_is_ciphering_to_be_attempted(msc_a), + msc_a_is_ciphering_required(msc_a), lu->key_seq, osmo_gsm48_classmark1_is_r99(&lu->classmark1), is_utran, @@ -701,7 +700,6 @@ static int cm_serv_reuse_conn(struct msc_a *msc_a, const struct osmo_mobile_iden accept_reuse: LOG_MSC_A_CAT(msc_a, DMM, LOGL_DEBUG, "re-using already accepted connection\n"); - msc_a_get(msc_a, msc_a_cm_service_type_to_use(cm_serv_type)); msub_update_id(msc_a->c.msub); return net->vlr->ops.tx_cm_serv_acc(msc_a, cm_serv_type); } @@ -729,6 +727,14 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) struct osmo_mobile_identity mi; int rc; + /* There are two ways to respond with a CM Service Reject: + * Directly and only send the CM Service Reject with msc_gsm48_tx_mm_serv_rej(). + * Decrement the CM Service use count token and send the message with msc_vlr_tx_cm_serv_rej(). + * + * Until we accept the CM Service Request message as such, there is no use count placed for the service type. + * So in here use msc_gsm48_tx_mm_serv_rej() to respond. + */ + /* Make sure that both header and CM Service Request fit into the buffer */ if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*req)) { LOG_MSC_A(msc_a, LOGL_ERROR, "Rx CM SERVICE REQUEST: wrong message size (%u < %zu)\n", @@ -788,16 +794,19 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_INCORRECT_MESSAGE); } - if (!msc_a_cm_service_type_to_use(req->cm_service_type)) + if (!msc_a_cm_service_type_to_use(msc_a, req->cm_service_type)) return msc_gsm48_tx_mm_serv_rej(msc_a, GSM48_REJECT_SRV_OPT_NOT_SUPPORTED); + /* At this point, the CM Service Request message is being accepted. + * Increment the matching use token, and from here on use msc_vlr_tx_cm_serv_rej() to respond in case of + * failure. */ + msc_a_get(msc_a, msc_a_cm_service_type_to_use(msc_a, req->cm_service_type)); + if (msc_a_is_accepted(msc_a)) return cm_serv_reuse_conn(msc_a, &mi, req->cm_service_type); osmo_signal_dispatch(SS_SUBSCR, S_SUBSCR_IDENTITY, &mi); - msc_a_get(msc_a, msc_a_cm_service_type_to_use(req->cm_service_type)); - is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU); vlr_proc_acc_req(msc_a->c.fi, MSC_A_EV_AUTHENTICATED, MSC_A_EV_CN_CLOSE, NULL, @@ -806,7 +815,8 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) req->cm_service_type, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - msc_a_require_ciphering(msc_a), + msc_a_is_ciphering_to_be_attempted(msc_a), + msc_a_is_ciphering_required(msc_a), req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -932,7 +942,8 @@ static int gsm48_rx_cm_reest_req(struct msc_a *msc_a, struct msgb *msg) VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ, 0, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - msc_a_require_ciphering(msc_a), + msc_a_is_ciphering_to_be_attempted(msc_a), + msc_a_is_ciphering_required(msc_a), req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -1294,7 +1305,8 @@ static int gsm48_rx_rr_pag_resp(struct msc_a *msc_a, struct msgb *msg) net->vlr, msc_a, VLR_PR_ARQ_T_PAGING_RESP, 0, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - msc_a_require_ciphering(msc_a), + msc_a_is_ciphering_to_be_attempted(msc_a), + msc_a_is_ciphering_required(msc_a), pr->key_seq, osmo_gsm48_classmark2_is_r99(cm2, classmark2_len), is_utran); @@ -1396,6 +1408,9 @@ int gsm0408_rcv_rr(struct msc_a *msc_a, struct msgb *msg) case GSM48_MT_RR_APP_INFO: rc = gsm48_rx_rr_app_info(msc_a, msg); break; + case GSM48_MT_RR_UPLINK_RELEASE: + rc = gsm44068_rcv_rr(msc_a, msg); + break; default: LOG_MSC_A_CAT(msc_a, DRR, LOGL_NOTICE, "MSC: Unimplemented %s GSM 04.08 RR " "message\n", gsm48_rr_msg_name(gh->msg_type)); @@ -1508,13 +1523,14 @@ static int msc_vlr_tx_mm_info(void *msc_conn_ref) return gsm48_tx_mm_info(msc_a); } -/* VLR asks us to transmit a CM Service Reject */ +/* VLR asks us to transmit a CM Service Reject. + * Decrement the CM Service type's use token and send the CM Service Reject message. */ static int msc_vlr_tx_cm_serv_rej(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type, enum gsm48_reject_value cause) { struct msc_a *msc_a = msc_conn_ref; msc_gsm48_tx_mm_serv_rej(msc_a, cause); - msc_a_put(msc_a, msc_a_cm_service_type_to_use(cm_service_type)); + msc_a_put(msc_a, msc_a_cm_service_type_to_use(msc_a, cm_service_type)); return 0; } @@ -1556,6 +1572,24 @@ static int msc_vlr_subscr_assoc(void *msc_conn_ref, return 0; } +static void msc_vlr_subscr_inval(void *msc_conn_ref, struct vlr_subscr *vsub) +{ + /* Search vsub backwards to make sure msc_conn_ref is a valid msc_a instance. */ + struct msub *msub; + OSMO_ASSERT(vsub); + llist_for_each_entry(msub, &msub_list, entry) { + struct msc_a *msc_a; + if (msub->vsub != vsub) + continue; + + msc_a = msub_msc_a(msub); + if (msc_a) + msc_a_release_cn(msc_a); + + msub->vsub = NULL; + } +} + /* operations that we need to implement for libvlr */ const struct vlr_ops msc_vlr_ops = { .tx_auth_req = msc_vlr_tx_auth_req, @@ -1570,6 +1604,7 @@ const struct vlr_ops msc_vlr_ops = { .tx_mm_info = msc_vlr_tx_mm_info, .subscr_update = msc_vlr_subscr_update, .subscr_assoc = msc_vlr_subscr_assoc, + .subscr_inval = msc_vlr_subscr_inval, }; struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value) diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c index 6562daadd..63b1699ab 100644 --- a/src/libmsc/gsm_04_08_cc.c +++ b/src/libmsc/gsm_04_08_cc.c @@ -43,6 +43,7 @@ #include <osmocom/msc/gsm_09_11.h> #include <osmocom/msc/signal.h> #include <osmocom/msc/transaction.h> +#include <osmocom/msc/transaction_cc.h> #include <osmocom/msc/silent_call.h> #include <osmocom/msc/mncc_int.h> #include <osmocom/abis/e1_input.h> @@ -55,6 +56,8 @@ #include <osmocom/msc/rtp_stream.h> #include <osmocom/msc/mncc_call.h> #include <osmocom/msc/msc_t.h> +#include <osmocom/msc/sdp_msg.h> +#include <osmocom/msc/codec_mapping.h> #include <osmocom/gsm/gsm48.h> #include <osmocom/gsm/gsm0480.h> @@ -126,7 +129,7 @@ static void gsm48_start_guard_timer(struct gsm_trans *trans) /* Call Control */ -void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg) +static void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg) { net->mncc_recv(net, msg); } @@ -228,15 +231,82 @@ static void gsm48_stop_cc_timer(struct gsm_trans *trans) } } -static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, - int msg_type, struct gsm_mncc *mncc) +/* Log the MNCC tx and rx events. + * Depending on msg_type, also log whether RTP information is passed on. + * (This is particularly interesting for the doc/sequence_charts/msc_log_to_ladder.py) + */ +#define log_mncc_rx_tx(ARGS...) _log_mncc_rx_tx(__FILE__, __LINE__, ##ARGS) +static void _log_mncc_rx_tx(const char *file, int line, + struct gsm_trans *trans, const char *rx_tx, const union mncc_msg *mncc) +{ + const char *sdp = NULL; + struct sdp_msg sdp_msg = {}; + struct osmo_sockaddr addr = {}; + + if (!log_check_level(DMNCC, LOGL_DEBUG)) + return; + + switch (mncc->msg_type) { + case MNCC_RTP_CREATE: + case MNCC_RTP_CONNECT: + addr = (struct osmo_sockaddr){ .u.sas = mncc->rtp.addr }; + sdp = mncc->rtp.sdp; + break; + + case MNCC_SETUP_IND: + case MNCC_SETUP_REQ: + case MNCC_SETUP_COMPL_IND: + case MNCC_SETUP_COMPL_REQ: + case MNCC_SETUP_RSP: + case MNCC_SETUP_CNF: + case MNCC_CALL_CONF_IND: + case MNCC_CALL_PROC_REQ: + case MNCC_ALERT_IND: + case MNCC_ALERT_REQ: + sdp = mncc->signal.sdp; + break; + + default: + break; + } + + if (sdp && sdp[0]) { + int rc = sdp_msg_from_sdp_str(&sdp_msg, sdp); + if (rc != 0) { + LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_ERROR, file, line, "%s %s: invalid SDP message (trying anyway)\n", + rx_tx, + get_mncc_name(mncc->msg_type)); + LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "erratic SDP: %s\n", + osmo_quote_cstr_c(OTC_SELECT, sdp, -1)); + return; + } + LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "%s %s (RTP=%s)\n", + rx_tx, + get_mncc_name(mncc->msg_type), + sdp_msg_to_str(&sdp_msg)); + return; + } + + if (osmo_sockaddr_is_any(&addr) == 0) { + LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "%s %s (RTP=%s)\n", + rx_tx, + get_mncc_name(mncc->msg_type), + osmo_sockaddr_to_str_c(OTC_SELECT, &addr)); + return; + } + + LOG_TRANS_CAT_SRC(trans, DMNCC, LOGL_DEBUG, file, line, "%s %s\n", rx_tx, get_mncc_name(mncc->msg_type)); +} + +#define mncc_recvmsg(ARGS...) _mncc_recvmsg(__FILE__, __LINE__, ##ARGS) +static int _mncc_recvmsg(const char *file, int line, + struct gsm_network *net, struct gsm_trans *trans, int msg_type, struct gsm_mncc *mncc) { struct msgb *msg; unsigned char *data; - LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "tx %s\n", get_mncc_name(msg_type)); - mncc->msg_type = msg_type; + log_mncc_rx_tx(trans, "tx", (union mncc_msg *)mncc); msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC"); if (!msg) @@ -278,6 +348,8 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) if (trans->cc.mncc_initiated) { mncc_release_ind(trans->net, trans, trans->callref, GSM48_CAUSE_LOC_PRN_S_LU, + (trans->cc.state == GSM_CSTATE_CALL_RECEIVED) ? + GSM48_CC_CAUSE_USER_NOTRESPOND : GSM48_CC_CAUSE_RESOURCE_UNAVAIL); } @@ -351,8 +423,8 @@ static void cc_paging_cb(struct msc_a *msc_a, struct gsm_trans *trans) /* bridge channels of two transactions */ static int tch_bridge(struct gsm_network *net, const struct gsm_mncc_bridge *bridge) { - struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[0]); - struct gsm_trans *trans2 = trans_find_by_callref(net, bridge->callref[1]); + struct gsm_trans *trans1 = trans_find_by_callref(net, TRANS_CC, bridge->callref[0]); + struct gsm_trans *trans2 = trans_find_by_callref(net, TRANS_CC, bridge->callref[1]); struct call_leg *cl1; struct call_leg *cl2; @@ -377,7 +449,7 @@ static int tch_bridge(struct gsm_network *net, const struct gsm_mncc_bridge *bri cl1 = trans1->msc_a->cc.call_leg; cl2 = trans2->msc_a->cc.call_leg; - return call_leg_local_bridge(cl1, trans1->callref, trans1, cl2, trans2->callref, trans2); + return call_leg_local_bridge(cl1, trans1->call_id, trans1, cl2, trans2->call_id, trans2); } static int gsm48_cc_rx_status_enq(struct gsm_trans *trans, struct msgb *msg) @@ -396,6 +468,8 @@ static void gsm48_cc_timeout(void *arg) int l4_location = GSM48_CAUSE_LOC_PRN_S_LU; struct gsm_mncc mo_rel, l4_rel; + LOG_TRANS(trans, LOGL_INFO, "Timeout of T%x\n", trans->cc.Tcurrent); + memset(&mo_rel, 0, sizeof(struct gsm_mncc)); mo_rel.callref = trans->callref; memset(&l4_rel, 0, sizeof(struct gsm_mncc)); @@ -472,8 +546,8 @@ static void gsm48_cc_timeout(void *arg) static inline void disconnect_bridge(struct gsm_network *net, const struct gsm_mncc_bridge *bridge, int err) { - struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]); - struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]); + struct gsm_trans *trans0 = trans_find_by_callref(net, TRANS_CC, bridge->callref[0]); + struct gsm_trans *trans1 = trans_find_by_callref(net, TRANS_CC, bridge->callref[1]); struct gsm_mncc mx_rel; if (!trans0 || !trans1) return; @@ -534,6 +608,8 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) msgb_free(gcr_msg); } + OSMO_ASSERT(trans->msc_a); + tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* emergency setup is identified by msg_type */ if (msg_type == GSM48_MT_CC_EMERG_SETUP) { @@ -578,6 +654,20 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) gsm48_decode_called(&setup.called, TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1); } + /* low layer compatibility */ + if (TLVP_PRESENT(&tp, GSM48_IE_LOWL_COMPAT) && TLVP_LEN(&tp, GSM48_IE_LOWL_COMPAT) > 0 && + TLVP_LEN(&tp, GSM48_IE_LOWL_COMPAT) <= sizeof(setup.llc.compat)) { + setup.fields |= MNCC_F_LOWL_COMPAT; + setup.llc.len = TLVP_LEN(&tp, GSM48_IE_LOWL_COMPAT); + memcpy(setup.llc.compat, TLVP_VAL(&tp, GSM48_IE_LOWL_COMPAT), setup.llc.len); + } + /* high layer compatibility */ + if (TLVP_PRESENT(&tp, GSM48_IE_HIGHL_COMPAT) && TLVP_LEN(&tp, GSM48_IE_HIGHL_COMPAT) > 0 && + TLVP_LEN(&tp, GSM48_IE_HIGHL_COMPAT) <= sizeof(setup.hlc.compat)) { + setup.fields |= MNCC_F_HIGHL_COMPAT; + setup.hlc.len = TLVP_LEN(&tp, GSM48_IE_HIGHL_COMPAT); + memcpy(setup.hlc.compat, TLVP_VAL(&tp, GSM48_IE_HIGHL_COMPAT), setup.hlc.len); + } /* user-user */ if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { setup.fields |= MNCC_F_USERUSER; @@ -603,28 +693,145 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); } - new_cc_state(trans, GSM_CSTATE_INITIATED); + /* MO call leg starting, gather all codec information so far known: */ + trans_cc_filter_init(trans); + trans_cc_filter_set_ran(trans, trans->msc_a->c.ran->type); + trans_cc_filter_set_bss(trans, trans->msc_a); + if (setup.fields & MNCC_F_BEARER_CAP) + trans_cc_filter_set_ms_from_bc(trans, &trans->bearer_cap); + trans_cc_filter_run(trans); LOG_TRANS(trans, setup.emergency ? LOGL_NOTICE : LOGL_INFO, "%sSETUP to %s\n", setup.emergency ? "EMERGENCY_" : "", setup.called.number); rate_ctr_inc(rate_ctr_group_get_ctr(trans->net->msc_ctrs, MSC_CTR_CALL_MO_SETUP)); + new_cc_state(trans, GSM_CSTATE_INITIATED); + + /* To complete the MNCC_SETUP_IND, we need to provide an RTP address and port. First instruct the MGW to create + * a CN-side RTP conn, and continue with MNCC_SETUP_IND once that is done. Leave trans.cc in GSM_CSTATE_NULL and + * note down the msg_type to indicate that we indeed composed an MNCC_SETUP_IND for later. */ + setup.msg_type = MNCC_SETUP_IND; + trans->cc.msg = setup; + return msc_a_try_call_assignment(trans); + /* continue in gsm48_cc_rx_setup_cn_local_rtp_port_known() */ +} + +/* Callback for MNCC_SETUP_IND waiting for the core network RTP port to be established by the MGW (via msc_a) */ +void gsm48_cc_rx_setup_cn_local_rtp_port_known(struct gsm_trans *trans) +{ + struct msc_a *msc_a = trans->msc_a; + struct gsm_mncc setup = trans->cc.msg; + struct osmo_sockaddr_str *rtp_cn_local; + struct sdp_msg *sdp; + int rc; + + if (trans->cc.state != GSM_CSTATE_INITIATED + || setup.msg_type != MNCC_SETUP_IND) { + LOG_TRANS(trans, LOGL_ERROR, + "Unexpected CC state. Expected GSM_CSTATE_INITIATED and a buffered MNCC_SETUP_IND message," + " found CC state %d and msg_type %s\n", + trans->cc.state, get_mncc_name(setup.msg_type)); + trans->callref = 0; + trans_free(trans); + return; + } + + if (!msc_a) { + LOG_TRANS(trans, LOGL_ERROR, "No connection for CC trans\n"); + trans->callref = 0; + trans_free(trans); + return; + } + + /* 'setup' above has taken the value of trans->cc.msg, we can now clear that. */ + trans->cc.msg = (struct gsm_mncc){}; + + /* Insert the CN side RTP port now available into SDP and compose SDP string */ + rtp_cn_local = call_leg_local_ip(msc_a->cc.call_leg, RTP_TO_CN); + if (!osmo_sockaddr_str_is_nonzero(rtp_cn_local)) { + LOG_TRANS(trans, LOGL_ERROR, "Cannot compose SDP for MNCC_SETUP_IND: no RTP set up for the CN side\n"); + trans_free(trans); + return; + } + trans->cc.local.rtp = *rtp_cn_local; + + sdp = trans->cc.local.audio_codecs.count ? &trans->cc.local : NULL; + rc = sdp_msg_to_sdp_str_buf(setup.sdp, sizeof(setup.sdp), sdp); + if (rc >= sizeof(setup.sdp)) { + LOG_TRANS(trans, LOGL_ERROR, "MNCC_SETUP_IND: SDP too long (%d > %zu bytes)\n", rc, sizeof(setup.sdp)); + trans_free(trans); + return; + } + /* indicate setup to MNCC */ mncc_recvmsg(trans->net, trans, MNCC_SETUP_IND, &setup); +} - /* MNCC code will modify the channel asynchronously, we should - * ipaccess-bind only after the modification has been made to the - * lchan->tch_mode */ - return 0; +static void rx_mncc_sdp(struct gsm_trans *trans, uint32_t mncc_msg_type, const char *sdp, + const struct gsm_mncc_bearer_cap *bcap) +{ + struct codec_filter *codecs = &trans->cc.codecs; + struct call_leg *cl = trans->msc_a ? trans->msc_a->cc.call_leg : NULL; + struct rtp_stream *rtp_cn = cl ? cl->rtp[RTP_TO_CN] : NULL; + + if (sdp[0]) { + int rc = sdp_msg_from_sdp_str(&trans->cc.remote, sdp); + if (rc) + LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "rx %s: Failed to parse SDP: %d. Trying anyway.\n", + get_mncc_name(mncc_msg_type), rc); + } + + /* if there is no SDP information or we failed to parse it, try using the Bearer Cap from MNCC, if any. */ + if (!trans->cc.remote.audio_codecs.count && bcap) { + trans->cc.remote = (struct sdp_msg){}; + trans_cc_set_remote_from_bc(trans, bcap); + LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s Bearer Cap: remote=%s\n", + get_mncc_name(mncc_msg_type), sdp_msg_to_str(&trans->cc.remote)); + } + + if (!trans->cc.remote.audio_codecs.count) + LOG_TRANS(trans, LOGL_INFO, + "Got no information of remote audio codecs: neither SDP nor Bearer Capability. Trying anyway.\n"); + + trans_cc_filter_run(trans); + if (rtp_cn) { + rtp_stream_set_remote_addr_and_codecs(rtp_cn, &trans->cc.remote); + rtp_stream_commit(rtp_cn); + } + + /* See if we need to switch codecs to maintain TFO: has the remote side changed the codecs information? If we + * have already assigned a specific codec here, but the remote call leg has now chosen a different codec, we + * need to re-assign this call leg to match the remote leg. */ + if (!sdp_audio_codec_is_set(&codecs->assignment)) { + /* Voice channel assignment has not completed. Do not interfere. */ + return; + } + if (!trans->cc.remote.audio_codecs.count) { + /* Don't know remote codecs, nothing to do. */ + return; + } + if (sdp_audio_codecs_by_descr(&trans->cc.remote.audio_codecs, &codecs->assignment)) { + /* The assigned codec is part of the remote codec set. All is well. */ + /* TODO: maybe this should require exactly the *first* remote codec to match, because we cannot flexibly + * transcode, and assume the actual payload we will receive is listed in the first place? */ + return; + } + + /* We've already completed Assignment of a voice channel (some time ago), and now the remote side has changed + * to a mismatching codec (list). Try to re-assign this side to a matching codec. */ + LOG_TRANS(trans, LOGL_INFO, "Remote call leg mismatches assigned codec: %s\n", + codec_filter_to_str(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote)); + msc_a_tx_assignment_cmd(trans->msc_a); } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg) { - struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC STUP"); + struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC SETUP"); struct gsm48_hdr *gh; struct gsm_mncc *setup = arg; int rc, trans_id; + struct gsm_mncc_bearer_cap bearer_cap; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); @@ -660,13 +867,102 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg) gsm48_start_cc_timer(trans, 0x303, GSM48_T303); - /* bearer capability */ - if (setup->fields & MNCC_F_BEARER_CAP) { - /* Create a copy of the bearer capability in the transaction struct, so we - * can use this information later */ - memcpy(&trans->bearer_cap, &setup->bearer_cap, sizeof(trans->bearer_cap)); - gsm48_encode_bearer_cap(msg, 0, &setup->bearer_cap); + /* MT call leg is starting. Gather all codecs information so far known. + * (Usually) paging has succeeded, and now we're processing the MNCC Setup from the remote MO call leg. + * Initialize the codecs filter with this side's BSS' codec list, received at Complete Layer 3. + * We haven't received the MT MS's Bearer Capabilities yet; the Bearer Capabilities handled here are + * actually the remote call leg's Bearer Capabilities. */ + trans_cc_filter_init(trans); + trans_cc_filter_set_ran(trans, trans->msc_a->c.ran->type); + trans_cc_filter_set_bss(trans, trans->msc_a); + if (setup->fields & MNCC_F_BEARER_CAP) + trans->bearer_cap.transfer = setup->bearer_cap.transfer; + + switch (trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + /* if SDP is included in the MNCC, take that as definitive list of remote audio codecs. */ + rx_mncc_sdp(trans, setup->msg_type, setup->sdp, + (setup->fields & MNCC_F_BEARER_CAP) ? &setup->bearer_cap : NULL); + /* rx_mncc_sdp() has called trans_cc_filter_run(trans); */ + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + if (setup->fields & MNCC_F_BEARER_CAP) { + trans->cc.remote = (struct sdp_msg){}; + trans_cc_set_remote_from_bc(trans, &setup->bearer_cap); + LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s Bearer Cap: remote=%s\n", + get_mncc_name(setup->msg_type), sdp_msg_to_str(&trans->cc.remote)); + } else { + LOG_TRANS(trans, LOGL_INFO, + "Got no information of remote Bearer Capability. Trying anyway.\n"); + sdp_audio_codecs_set_csd(&trans->cc.codecs.ms); + } + trans_cc_filter_run(trans); + break; + default: + LOG_TRANS(trans, LOGL_ERROR, "Handling of information transfer capability %d not implemented\n", + trans->bearer_cap.transfer); + break; + } + + /* Compose Bearer Capability information that reflects only the codecs (Speech Versions) / CSD bearer services + * remaining after intersecting MS, BSS and remote call leg restrictions. To store in trans for later use, and + * to include in the outgoing CC Setup message. */ + switch (trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + bearer_cap = (struct gsm_mncc_bearer_cap){ + .speech_ver = { -1 }, + }; + sdp_audio_codecs_to_bearer_cap(&bearer_cap, &trans->cc.local.audio_codecs); + rc = bearer_cap_set_radio(&bearer_cap); + if (rc) { + LOG_TRANS(trans, LOGL_ERROR, "Error composing Bearer Capability for CC Setup\n"); + trans_free(trans); + msgb_free(msg); + return rc; + } + /* If no resulting codecs remain, error out. We cannot find a codec that matches both call legs. If the MGW were + * able to transcode, we could use non-identical codecs on each conn of the MGW endpoint, but we are aiming for + * finding a matching codec. */ + if (bearer_cap.speech_ver[0] == -1) { + LOG_TRANS(trans, LOGL_ERROR, "%s: no codec match possible: %s\n", + get_mncc_name(setup->msg_type), + codec_filter_to_str(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote)); + + /* incompatible codecs */ + rc = mncc_release_ind(trans->net, trans, trans->callref, + GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_INCOMPAT_DEST /* TODO: correct cause code? */); + trans->callref = 0; + trans_free(trans); + msgb_free(msg); + return rc; + } + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + if (csd_bs_list_to_bearer_cap(&bearer_cap, &trans->cc.local.bearer_services) == 0) { + LOG_TRANS(trans, LOGL_ERROR, "Error composing Bearer Capability for CC Setup\n"); + + /* incompatible codecs */ + rc = mncc_release_ind(trans->net, trans, trans->callref, + GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_INCOMPAT_DEST /* TODO: correct cause code? */); + trans->callref = 0; + trans_free(trans); + msgb_free(msg); + return rc; + } + break; } + + /* Create a copy of the bearer capability in the transaction struct, so we can use this information later */ + trans->bearer_cap = bearer_cap; + + gsm48_encode_bearer_cap(msg, 0, &bearer_cap); + /* facility */ if (setup->fields & MNCC_F_FACILITY) gsm48_encode_facility(msg, 0, &setup->facility); @@ -679,6 +975,12 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg) /* called party BCD number */ if (setup->fields & MNCC_F_CALLED) gsm48_encode_called(msg, &setup->called); + /* low layer compatibility */ + if (setup->fields & MNCC_F_LOWL_COMPAT && setup->llc.len > 0 && setup->llc.len <= sizeof(setup->llc.compat)) + msgb_tlv_put(msg, GSM48_IE_LOWL_COMPAT, setup->llc.len, setup->llc.compat); + /* high layer compatibility */ + if (setup->fields & MNCC_F_HIGHL_COMPAT && setup->hlc.len > 0 && setup->hlc.len <= sizeof(setup->hlc.compat)) + msgb_tlv_put(msg, GSM48_IE_HIGHL_COMPAT, setup->hlc.len, setup->hlc.compat); /* user-user */ if (setup->fields & MNCC_F_USERUSER) gsm48_encode_useruser(msg, 0, &setup->useruser); @@ -727,9 +1029,14 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) /* Create a copy of the bearer capability * in the transaction struct, so we can use * this information later */ - memcpy(&trans->bearer_cap,&call_conf.bearer_cap, + memcpy(&trans->bearer_cap, &call_conf.bearer_cap, sizeof(trans->bearer_cap)); + + /* This is the MT call leg's Call Conf, containing the MS Bearer Capabilities of the MT MS. + * Store in codecs filter. */ + trans_cc_filter_set_ms_from_bc(trans, &call_conf.bearer_cap); } + /* cause */ if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { call_conf.fields |= MNCC_F_CAUSE; @@ -746,8 +1053,6 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) /* IMSI of called subscriber */ OSMO_STRLCPY_ARRAY(call_conf.imsi, trans->vsub->imsi); - new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF); - /* Assign call (if not done yet) */ rc = msc_a_try_call_assignment(trans); @@ -756,8 +1061,47 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) if (rc) return rc; - return mncc_recvmsg(trans->net, trans, MNCC_CALL_CONF_IND, - &call_conf); + /* Directly ack with MNCC_CALL_CONF_IND, not yet containing SDP or RTP IP:port information. */ + new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF); + return mncc_recvmsg(trans->net, trans, MNCC_CALL_CONF_IND, &call_conf); +} + +static int mncc_recv_rtp(struct gsm_network *net, struct gsm_trans *trans, uint32_t callref, + int cmd, struct osmo_sockaddr_str *rtp_addr, uint32_t payload_type, + uint32_t payload_msg_type, const struct sdp_msg *sdp); + +static int gsm48_cc_mt_rtp_port_and_codec_known(struct gsm_trans *trans) +{ + struct msc_a *msc_a = trans->msc_a; + struct osmo_sockaddr_str *rtp_cn_local; + struct gsm_mncc_rtp; + + if (!msc_a) { + LOG_TRANS(trans, LOGL_ERROR, "No connection for CC trans\n"); + trans->callref = 0; + trans_free(trans); + return -EINVAL; + } + + /* Insert the CN side RTP port now available into SDP */ + rtp_cn_local = call_leg_local_ip(msc_a->cc.call_leg, RTP_TO_CN); + if (!rtp_cn_local) { + LOG_TRANS(trans, LOGL_ERROR, "Cannot compose SDP for MNCC_RTP_CREATE: no RTP set up for the CN side\n"); + trans_free(trans); + return -EINVAL; + } + trans->cc.local.rtp = *rtp_cn_local; + + trans_cc_filter_run(trans); + + /* If we haven't completed Assignment yet, don't sent MNCC_RTP_CREATE */ + if (!sdp_audio_codec_is_set(&trans->cc.codecs.assignment)) { + LOG_TRANS(trans, LOGL_DEBUG, "no codec confirmed by Assignment yet\n"); + return 0; + } + + return mncc_recv_rtp(msc_a_net(msc_a), trans, trans->callref, MNCC_RTP_CREATE, rtp_cn_local, 0, 0, + &trans->cc.local); } static int gsm48_cc_tx_call_proc_and_assign(struct gsm_trans *trans, void *arg) @@ -773,6 +1117,14 @@ static int gsm48_cc_tx_call_proc_and_assign(struct gsm_trans *trans, void *arg) /* bearer capability */ if (proceeding->fields & MNCC_F_BEARER_CAP) { + /* MNCC should not switch from e.g. CSD to speech */ + if (proceeding->bearer_cap.transfer != trans->bearer_cap.transfer) { + LOG_TRANS(trans, LOGL_ERROR, "Unexpected Information Transfer Capability %d from MNCC," + " transaction has %d\n", + proceeding->bearer_cap.transfer, + trans->bearer_cap.transfer); + return -EINVAL; + } gsm48_encode_bearer_cap(msg, 0, &proceeding->bearer_cap); memcpy(&trans->bearer_cap, &proceeding->bearer_cap, sizeof(trans->bearer_cap)); } @@ -797,6 +1149,7 @@ static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg) unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh); struct tlv_parsed tp; struct gsm_mncc alerting; + int rc; gsm48_stop_cc_timer(trans); gsm48_start_cc_timer(trans, 0x301, GSM48_T301); @@ -826,6 +1179,15 @@ static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg) new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED); + trans_cc_filter_run(trans); + rc = sdp_msg_to_sdp_str_buf(alerting.sdp, sizeof(alerting.sdp), &trans->cc.local); + if (rc >= sizeof(alerting.sdp)) { + LOG_TRANS(trans, LOGL_ERROR, "MNCC_ALERT_IND: SDP too long (%d > %zu bytes)\n", + rc, sizeof(alerting.sdp)); + trans_free(trans); + return -EINVAL; + } + return mncc_recvmsg(trans->net, trans, MNCC_ALERT_IND, &alerting); } @@ -835,6 +1197,7 @@ static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg) struct gsm_mncc *alerting = arg; struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CC ALERT"); struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + int rc; gh->msg_type = GSM48_MT_CC_ALERTING; @@ -850,7 +1213,13 @@ static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg) new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED); - return trans_tx_gsm48(trans, msg); + if (alerting->sdp[0]) + rx_mncc_sdp(trans, alerting->msg_type, alerting->sdp, + (alerting->fields & MNCC_F_BEARER_CAP) ? &alerting->bearer_cap : NULL); + + /* handle the MNCC event */ + rc = trans_tx_gsm48(trans, msg); + return rc; } static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg) @@ -896,6 +1265,10 @@ static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg) new_cc_state(trans, GSM_CSTATE_CONNECT_IND); + if (connect->sdp[0]) + rx_mncc_sdp(trans, connect->msg_type, connect->sdp, + (connect->fields & MNCC_F_BEARER_CAP) ? &connect->bearer_cap : NULL); + return trans_tx_gsm48(trans, msg); } @@ -938,6 +1311,8 @@ static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg) new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST); rate_ctr_inc(rate_ctr_group_get_ctr(trans->net->msc_ctrs, MSC_CTR_CALL_MT_CONNECT)); + trans_cc_filter_run(trans); + sdp_msg_to_sdp_str_buf(connect.sdp, sizeof(connect.sdp), &trans->cc.local); return mncc_recvmsg(trans->net, trans, MNCC_SETUP_CNF, &connect); } @@ -1648,7 +2023,7 @@ static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) static int mncc_recv_rtp(struct gsm_network *net, struct gsm_trans *trans, uint32_t callref, int cmd, struct osmo_sockaddr_str *rtp_addr, uint32_t payload_type, - uint32_t payload_msg_type) + uint32_t payload_msg_type, const struct sdp_msg *sdp) { uint8_t data[sizeof(struct gsm_mncc)]; struct gsm_mncc_rtp *rtp; @@ -1664,37 +2039,101 @@ static int mncc_recv_rtp(struct gsm_network *net, struct gsm_trans *trans, uint3 } rtp->payload_type = payload_type; rtp->payload_msg_type = payload_msg_type; + if (sdp) + sdp_msg_to_sdp_str_buf(rtp->sdp, sizeof(rtp->sdp), sdp); return mncc_recvmsg(net, trans, cmd, (struct gsm_mncc *)data); } static void mncc_recv_rtp_err(struct gsm_network *net, struct gsm_trans *trans, uint32_t callref, int cmd) { - mncc_recv_rtp(net, trans, callref, cmd, NULL, 0, 0); + mncc_recv_rtp(net, trans, callref, cmd, NULL, 0, 0, NULL); } -static int tch_rtp_create(struct gsm_network *net, uint32_t callref) +static int tch_rtp_create(struct gsm_network *net, const struct gsm_mncc_rtp *rtp) { struct gsm_trans *trans; /* Find callref */ - trans = trans_find_by_callref(net, callref); + trans = trans_find_by_callref(net, TRANS_CC, rtp->callref); if (!trans) { LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "RTP create for non-existing trans\n"); - mncc_recv_rtp_err(net, trans, callref, MNCC_RTP_CREATE); + mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CREATE); return -EIO; } log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub); if (!trans->msc_a) { LOG_TRANS_CAT(trans, DMNCC, LOGL_NOTICE, "RTP create for trans without conn\n"); - mncc_recv_rtp_err(net, trans, callref, MNCC_RTP_CREATE); + mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CREATE); return 0; } - LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s\n", get_mncc_name(MNCC_RTP_CREATE)); + log_mncc_rx_tx(trans, "rx", (const union mncc_msg *)rtp); /* Assign call (if not done yet) */ return msc_a_try_call_assignment(trans); } +int cc_on_cn_local_rtp_port_known(struct gsm_trans *cc_trans) +{ + /* Depending on MO or MT call, dispatch the event differently */ + switch (cc_trans->cc.state) { + case GSM_CSTATE_INITIATED: + if (cc_trans->cc.msg.msg_type != MNCC_SETUP_IND) { + LOG_TRANS(cc_trans, LOGL_ERROR, "Assuming MO call, expected MNCC_SETUP_IND to be prepared\n"); + return -EINVAL; + } + /* This is the MO call leg, waiting for a CN RTP be able to send initial MNCC_SETUP_IND. */ + gsm48_cc_rx_setup_cn_local_rtp_port_known(cc_trans); + return 0; + + case GSM_CSTATE_MO_TERM_CALL_CONF: + /* This is the MT call leg, waiting for a CN RTP to be able to send MNCC_CALL_CONF_IND. */ + return gsm48_cc_mt_rtp_port_and_codec_known(cc_trans); + + default: + LOG_TRANS(cc_trans, LOGL_ERROR, "CN RTP address available, but in unexpected state %d\n", + cc_trans->cc.state); + return -EINVAL; + } +} + +int cc_on_assignment_done(struct gsm_trans *trans) +{ + struct msc_a *msc_a = trans->msc_a; + + switch (trans->cc.state) { + case GSM_CSTATE_INITIATED: + case GSM_CSTATE_MO_CALL_PROC: + /* MO call, send ACK in form of an MNCC_RTP_CREATE (below) */ + break; + + case GSM_CSTATE_CALL_RECEIVED: + case GSM_CSTATE_MO_TERM_CALL_CONF: + /* MT call, send ACK in form of an MNCC_RTP_CREATE (below) */ + break; + + case GSM_CSTATE_ACTIVE: + /* already active. We decided to re-assign later on during the call - at time of writing this never + * happens. */ + case GSM_CSTATE_CALL_DELIVERED: + case GSM_CSTATE_CONNECT_IND: + /* MNCC has progressed past the initial assignment. Usually it means that this happened: after + * MNCC_ALERT_REQ, MO has triggered a re-assignment, to adjust MO's codec to MT's codec. */ + LOG_TRANS(trans, LOGL_DEBUG, "Re-Assignment complete\n"); + return 0; + + default: + LOG_TRANS(trans, LOGL_ERROR, "Assignment done in unexpected CC state: %d\n", trans->cc.state); + return -EINVAL; + } + + if (!call_leg_local_ip(msc_a->cc.call_leg, RTP_TO_CN)) { + LOG_TRANS(trans, LOGL_DEBUG, + "Assignment complete, but still waiting for the CRCX OK on the CN side RTP\n"); + return 0; + } + return gsm48_tch_rtp_create(trans); +} + /* Trigger TCH_RTP_CREATE acknowledgement */ int gsm48_tch_rtp_create(struct gsm_trans *trans) { @@ -1706,38 +2145,37 @@ int gsm48_tch_rtp_create(struct gsm_trans *trans) struct call_leg *cl = msc_a->cc.call_leg; struct osmo_sockaddr_str *rtp_cn_local; struct rtp_stream *rtp_cn = cl ? cl->rtp[RTP_TO_CN] : NULL; - uint32_t payload_type; - int payload_msg_type; - const struct mgcp_conn_peer *mgcp_info; + int mncc_payload_msg_type; + struct sdp_audio_codec *codec; + const struct codec_mapping *m; + struct sdp_audio_codecs *codecs; if (!rtp_cn) { LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "Cannot RTP CREATE to MNCC, no RTP set up for the CN side\n"); return -EINVAL; } - if (!rtp_cn->codec_known) { + trans_cc_filter_run(trans); + codecs = &trans->cc.local.audio_codecs; + if (!codecs->count) { LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, - "Cannot RTP CREATE to MNCC, no codec set up for the RTP CN side\n"); + "Cannot RTP CREATE to MNCC, there is no codec available\n"); return -EINVAL; } - /* Codec */ - payload_msg_type = mgcp_codec_to_mncc_payload_msg_type(rtp_cn->codec); - - /* Payload Type number */ - mgcp_info = osmo_mgcpc_ep_ci_get_rtp_info(rtp_cn->ci); - if (mgcp_info && mgcp_info->ptmap_len) - payload_type = map_codec_to_pt(mgcp_info->ptmap, mgcp_info->ptmap_len, rtp_cn->codec); - else - payload_type = rtp_cn->codec; + /* Populate the legacy MNCC codec elements: payload_type and payload_msg_type */ + codec = &codecs->codec[0]; + m = codec_mapping_by_subtype_name(codec->subtype_name); + mncc_payload_msg_type = m ? m->mncc_payload_msg_type : 0; rtp_cn_local = call_leg_local_ip(cl, RTP_TO_CN); if (!rtp_cn_local) { - LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "Cannot RTP CREATE to MNCC, no local RTP IP:port set up\n"); + LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "Cannot RTP CREATE to MNCC, no local RTP IP:port to CN set up\n"); return -EINVAL; } - return mncc_recv_rtp(net, trans, trans->callref, MNCC_RTP_CREATE, rtp_cn_local, payload_type, payload_msg_type); + return mncc_recv_rtp(net, trans, trans->callref, MNCC_RTP_CREATE, rtp_cn_local, + codec->payload_type, mncc_payload_msg_type, &trans->cc.local); } static int tch_rtp_connect(struct gsm_network *net, const struct gsm_mncc_rtp *rtp) @@ -1745,21 +2183,9 @@ static int tch_rtp_connect(struct gsm_network *net, const struct gsm_mncc_rtp *r struct gsm_trans *trans; struct call_leg *cl; struct rtp_stream *rtps; - struct osmo_sockaddr_str rtp_addr; - char ipbuf[INET6_ADDRSTRLEN]; - - /* FIXME: in *rtp we should get the codec information of the remote - * leg. We will have to populate trans->conn->rtp.codec_cn with a - * meaningful value based on this information but unfortunately we - * can't do that yet because the mncc API can not signal dynamic - * payload types yet. This must be fixed first. Also there may be - * additional members necessary in trans->conn->rtp because we - * somehow need to deal with dynamic payload types that do not - * comply to 3gpp's assumptions of payload type numbers on the A - * interface. See also related tickets: OS#3399 and OS1683 */ /* Find callref */ - trans = trans_find_by_callref(net, rtp->callref); + trans = trans_find_by_callref(net, TRANS_CC, rtp->callref); if (!trans) { LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "RTP connect for non-existing trans\n"); mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CONNECT); @@ -1772,26 +2198,23 @@ static int tch_rtp_connect(struct gsm_network *net, const struct gsm_mncc_rtp *r return -EIO; } - LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s %s:%u\n", get_mncc_name(MNCC_RTP_CONNECT), - osmo_sockaddr_ntop((const struct sockaddr*)&rtp->addr, ipbuf), - osmo_sockaddr_port((const struct sockaddr*)&rtp->addr)); + log_mncc_rx_tx(trans, "rx", (const union mncc_msg *)rtp); + + rx_mncc_sdp(trans, rtp->msg_type, rtp->sdp, NULL); cl = trans->msc_a->cc.call_leg; rtps = cl ? cl->rtp[RTP_TO_CN] : NULL; - - if (!rtps) { - LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "RTP connect for trans without ongoing call\n"); - mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CONNECT); - return -EINVAL; - } - - if (osmo_sockaddr_str_from_sockaddr(&rtp_addr, &rtp->addr) < 0) { - LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "RTP connect with invalid IP addr\n"); - mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CONNECT); - return -EINVAL; + if (rtps && !osmo_sockaddr_str_is_nonzero(&rtps->remote)) { + /* Didn't get an IP address from SDP. Try legacy MNCC IP address */ + struct osmo_sockaddr_str rtp_addr; + if (osmo_sockaddr_str_from_sockaddr(&rtp_addr, &rtp->addr) < 0) { + LOG_TRANS_CAT(trans, DMNCC, LOGL_ERROR, "RTP connect with invalid IP addr\n"); + mncc_recv_rtp_err(net, trans, rtp->callref, MNCC_RTP_CONNECT); + return -EINVAL; + } + rtp_stream_set_remote_addr(rtps, &rtp_addr); + rtp_stream_commit(rtps); } - rtp_stream_set_remote_addr(rtps, &rtp_addr); - rtp_stream_commit(rtps); return 0; } @@ -1869,7 +2292,7 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) disconnect_bridge(net, &msg->bridge, -rc); return rc; case MNCC_RTP_CREATE: - return tch_rtp_create(net, msg->rtp.callref); + return tch_rtp_create(net, &msg->rtp); case MNCC_RTP_CONNECT: return tch_rtp_connect(net, &msg->rtp); case MNCC_RTP_FREE: @@ -1890,7 +2313,7 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) data = &msg->signal; /* Find callref */ - trans = trans_find_by_callref(net, data->callref); + trans = trans_find_by_callref(net, TRANS_CC, data->callref); /* Callref unknown */ if (!trans) { @@ -1972,11 +2395,15 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) return -ENOMEM; } + /* Remember remote SDP, if any */ + rx_mncc_sdp(trans, data->msg_type, data->sdp, + (data->fields & MNCC_F_BEARER_CAP) ? &data->bearer_cap : NULL); + /* If subscriber has no conn */ if (!msc_a) { /* This condition will return before the common logging of the received MNCC message below, so * log it now. */ - LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s\n", get_mncc_name(msg->msg_type)); + log_mncc_rx_tx(trans, "rx", msg); /* store setup information until paging succeeds */ memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc)); @@ -2003,9 +2430,29 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) log_set_context(LOG_CTX_VLR_SUBSCR, trans->vsub); } - LOG_TRANS_CAT(trans, DMNCC, LOGL_DEBUG, "rx %s\n", get_mncc_name(msg->msg_type)); + log_mncc_rx_tx(trans, "rx", msg); - gsm48_start_guard_timer(trans); + /* + * The step of gsm48_start_guard_timer() needs to be done for + * major state-impacting MNCC messages, but not for those + * that are a mere pass-through to CC messages to MS. + */ + switch (msg->msg_type) { + case MNCC_PROGRESS_REQ: + case MNCC_NOTIFY_REQ: + case MNCC_FACILITY_REQ: + case MNCC_START_DTMF_RSP: + case MNCC_START_DTMF_REJ: + case MNCC_STOP_DTMF_RSP: + case MNCC_HOLD_CNF: + case MNCC_HOLD_REJ: + case MNCC_RETRIEVE_CNF: + case MNCC_RETRIEVE_REJ: + case MNCC_USERINFO_REQ: + break; + default: + gsm48_start_guard_timer(trans); + } trans->cc.mncc_initiated = true; if (trans->msc_a) @@ -2016,7 +2463,7 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) struct gsm_mncc rel = { .callref = data->callref, }; - LOG_TRANS(trans, LOGL_DEBUG, "rx %s in paging state\n", get_mncc_name(msg->msg_type)); + LOG_TRANS(trans, LOGL_DEBUG, "still paging\n"); mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_NORM_CALL_CLEAR); if (msg->msg_type == MNCC_REL_REQ) @@ -2026,9 +2473,6 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) trans->callref = 0; trans_free(trans); return rc; - } else { - LOG_TRANS(trans, LOGL_DEBUG, "rx %s in state %s\n", - get_mncc_name(msg->msg_type), gsm48_cc_state_name(trans->cc.state)); } /* Find function for current state and message */ diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c index 722973e77..aa87a192a 100644 --- a/src/libmsc/gsm_04_11.c +++ b/src/libmsc/gsm_04_11.c @@ -58,7 +58,7 @@ #include <osmocom/msc/paging.h> #ifdef BUILD_SMPP -#include "smpp_smsc.h" +#include <osmocom/smpp/smpp_smsc.h> #endif void *tall_gsms_ctx; @@ -626,6 +626,12 @@ static int gsm340_rx_tpdu(struct gsm_trans *trans, struct msgb *msg, osmo_hexdump(gsms->user_data, gsms->user_data_len)); gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp); + if (gsms->validity_minutes < net->sms_queue_cfg->minimum_validity_mins) { + LOG_TRANS(trans, LOGL_INFO, "Overriding user-provided validity period (%lu) " + "with minimum SMSC validity period (%u) minutes\n", gsms->validity_minutes, + net->sms_queue_cfg->minimum_validity_mins); + gsms->validity_minutes = net->sms_queue_cfg->minimum_validity_mins; + } rc = sms_route_mt_sms(trans, gsms); @@ -1224,7 +1230,8 @@ int gsm411_send_sms(struct gsm_network *net, int gsm411_send_rp_data(struct gsm_network *net, struct vlr_subscr *vsub, size_t sm_rp_oa_len, const uint8_t *sm_rp_oa, size_t sm_rp_ud_len, const uint8_t *sm_rp_ud, - bool sm_rp_mmts_ind) + bool sm_rp_mmts_ind, const uint8_t *gsup_source_name, + size_t gsup_source_name_len) { struct gsm_trans *trans; struct msgb *msg; @@ -1239,6 +1246,17 @@ int gsm411_send_rp_data(struct gsm_network *net, struct vlr_subscr *vsub, if (trans->msc_a != NULL) gsm411_handle_mmts_ind(trans); + /* Save GSUP source_name for subsequent response messages */ + if (gsup_source_name && gsup_source_name_len) { + trans->sms.gsup_source_name = talloc_memdup(trans, gsup_source_name, + gsup_source_name_len); + if (!trans->sms.gsup_source_name) { + trans_free(trans); + return -ENOMEM; + } + trans->sms.gsup_source_name_len = gsup_source_name_len; + } + /* Allocate a message buffer for to be encoded SMS */ msg = gsm411_msgb_alloc(); if (!msg) { @@ -1383,4 +1401,3 @@ void gsm411_sapi_n_reject(struct msc_a *msc_a) trans_free(trans); } } - diff --git a/src/libmsc/gsm_04_11_gsup.c b/src/libmsc/gsm_04_11_gsup.c index 7a47e9386..1afdfabbc 100644 --- a/src/libmsc/gsm_04_11_gsup.c +++ b/src/libmsc/gsm_04_11_gsup.c @@ -33,6 +33,7 @@ #include <osmocom/msc/vlr.h> #include <osmocom/msc/msub.h> #include <osmocom/msc/gsup_client_mux.h> +#include <osmocom/msc/msc_a.h> /* Common helper for preparing to be encoded GSUP message */ static void gsup_sm_msg_init(struct osmo_gsup_message *gsup_msg, @@ -97,6 +98,7 @@ int gsm411_gsup_mo_fwd_sm_req(struct gsm_trans *trans, struct msgb *msg, gsup_msg.sm_rp_ui_len = msgb_l4len(msg); gsup_msg.sm_rp_ui = (uint8_t *) msgb_sms(msg); + gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg); return gsup_client_mux_tx(trans->net->gcm, &gsup_msg); } @@ -119,6 +121,7 @@ int gsm411_gsup_mo_ready_for_sm_req(struct gsm_trans *trans, uint8_t sm_rp_mr) /* Indicate SMMA as the Alert Reason */ gsup_msg.sm_alert_rsn = OSMO_GSUP_SMS_SM_ALERT_RSN_MEM_AVAIL; + gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg); return gsup_client_mux_tx(trans->net->gcm, &gsup_msg); } @@ -197,6 +200,11 @@ int gsm411_gsup_mt_fwd_sm_res(struct gsm_trans *trans, uint8_t sm_rp_mr) gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT, trans->vsub->imsi, &sm_rp_mr); + /* Ensure routing through OsmoHLR to the MT-sending SMSC */ + gsup_msg.destination_name = trans->sms.gsup_source_name; + gsup_msg.destination_name_len = trans->sms.gsup_source_name_len; + gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg); + return gsup_client_mux_tx(trans->net->gcm, &gsup_msg); } @@ -214,6 +222,11 @@ int gsm411_gsup_mt_fwd_sm_err(struct gsm_trans *trans, gsup_sm_msg_init(&gsup_msg, OSMO_GSUP_MSGT_MT_FORWARD_SM_ERROR, trans->vsub->imsi, &sm_rp_mr); + /* Ensure routing through OsmoHLR to the MT-sending SMSC */ + gsup_msg.destination_name = trans->sms.gsup_source_name; + gsup_msg.destination_name_len = trans->sms.gsup_source_name_len; + gsup_client_mux_tx_set_source(trans->net->gcm, &gsup_msg); + /* SM-RP-Cause value */ gsup_msg.sm_rp_cause = &cause; @@ -258,7 +271,8 @@ static int gsm411_gsup_mt_handler(struct gsm_network *net, struct vlr_subscr *vs rc = gsm411_send_rp_data(net, vsub, gsup_msg->sm_rp_oa_len, gsup_msg->sm_rp_oa, gsup_msg->sm_rp_ui_len, gsup_msg->sm_rp_ui, - sm_rp_mmts_ind); + sm_rp_mmts_ind, gsup_msg->source_name, + gsup_msg->source_name_len); if (rc) { LOGP(DLSMS, LOGL_NOTICE, "Failed to send MT SMS, " "ignoring MT-forwardSM-Req message...\n"); diff --git a/src/libmsc/gsm_09_11.c b/src/libmsc/gsm_09_11.c index d94be480b..e29389015 100644 --- a/src/libmsc/gsm_09_11.c +++ b/src/libmsc/gsm_09_11.c @@ -441,7 +441,7 @@ int gsm0911_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_g log_set_context(LOG_CTX_VLR_SUBSCR, vsub); /* Attempt to find DTAP-transaction */ - trans = trans_find_by_callref(net, gsup_msg->session_id); + trans = trans_find_by_callref(net, TRANS_USSD, gsup_msg->session_id); /* Handle errors */ if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) { diff --git a/src/libmsc/gsup_client_mux.c b/src/libmsc/gsup_client_mux.c index e425651af..e27b6645d 100644 --- a/src/libmsc/gsup_client_mux.c +++ b/src/libmsc/gsup_client_mux.c @@ -1,25 +1,21 @@ /* Directing individual GSUP messages to their respective handlers. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <errno.h> @@ -140,6 +136,25 @@ int gsup_client_mux_tx(struct gsup_client_mux *gcm, const struct osmo_gsup_messa return osmo_gsup_client_send(gcm->gsup_client, msg); } +/* Set GSUP source_name to our local IPA name */ +void gsup_client_mux_tx_set_source(const struct gsup_client_mux *gcm, + struct osmo_gsup_message *gsup_msg) +{ + const char *local_msc_name; + + if (!gcm) + return; + if (!gcm->gsup_client) + return; + if (!gcm->gsup_client->ipa_dev) + return; + local_msc_name = gcm->gsup_client->ipa_dev->serno; + if (!local_msc_name) + return; + gsup_msg->source_name = (const uint8_t *) local_msc_name; + gsup_msg->source_name_len = strlen(local_msc_name) + 1; +} + /* Transmit GSUP error in response to original message */ void gsup_client_mux_tx_error_reply(struct gsup_client_mux *gcm, const struct osmo_gsup_message *gsup_orig, enum gsm48_gmm_cause cause) @@ -154,12 +169,15 @@ void gsup_client_mux_tx_error_reply(struct gsup_client_mux *gcm, const struct os .cause = cause, .message_type = OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type), .message_class = gsup_orig->message_class, + .destination_name = gsup_orig->source_name, + .destination_name_len = gsup_orig->source_name_len, /* RP-Message-Reference is mandatory for SM Service */ .sm_rp_mr = gsup_orig->sm_rp_mr, }; OSMO_STRLCPY_ARRAY(gsup_reply.imsi, gsup_orig->imsi); + gsup_client_mux_tx_set_source(gcm, &gsup_reply); /* For SS/USSD, it's important to keep both session state and ID IEs */ if (gsup_orig->session_state != OSMO_GSUP_SESSION_STATE_NONE) { diff --git a/src/libmsc/mncc.c b/src/libmsc/mncc.c index 0a38997bc..026dae025 100644 --- a/src/libmsc/mncc.c +++ b/src/libmsc/mncc.c @@ -110,8 +110,6 @@ void mncc_set_cause(struct gsm_mncc *data, int loc, int val) * MNCC validation code. Move to libosmocore once headers are merged ************************************************************************/ -#define MNCC_F_ALL 0x3fff - static int check_string_terminated(const char *str, unsigned int size) { int i; @@ -157,7 +155,7 @@ static int mncc_prim_check_sign(const struct gsm_mncc *mncc_prim) { int rc; - if (mncc_prim->fields & ~ MNCC_F_ALL) { + if (mncc_prim->fields & ~MNCC_F_ALL) { LOGP(DMNCC, LOGL_ERROR, "Unknown MNCC field mask 0x%x\n", mncc_prim->fields); return -EINVAL; } diff --git a/src/libmsc/mncc_builtin.c b/src/libmsc/mncc_builtin.c index cc3f55da6..647420155 100644 --- a/src/libmsc/mncc_builtin.c +++ b/src/libmsc/mncc_builtin.c @@ -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. - * */ @@ -89,10 +85,16 @@ static int mncc_setup_ind(struct gsm_call *call, goto out_reject; } - /* we currently only do speech */ - if (setup->bearer_cap.transfer != GSM_MNCC_BCAP_SPEECH) { + /* we currently only do speech and CSD */ + switch (setup->bearer_cap.transfer) { + case GSM_MNCC_BCAP_SPEECH: + case GSM_MNCC_BCAP_AUDIO: + case GSM_MNCC_BCAP_FAX_G3: + case GSM_MNCC_BCAP_UNR_DIG: + break; + default: LOGP(DMNCC, LOGL_NOTICE, "(call %x) We only support " - "voice calls\n", call->callref); + "voice calls and CSD\n", call->callref); mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_BEARER_CA_UNAVAIL); goto out_reject; diff --git a/src/libmsc/mncc_call.c b/src/libmsc/mncc_call.c index c9a6d56a4..557f2d749 100644 --- a/src/libmsc/mncc_call.c +++ b/src/libmsc/mncc_call.c @@ -2,7 +2,7 @@ /* At the time of writing, this is only used for inter-MSC handover: forward a voice stream to a remote MSC. * Maybe it makes sense to also use it for all "normal" external call management at some point. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -35,6 +35,7 @@ #include <osmocom/msc/rtp_stream.h> #include <osmocom/msc/msub.h> #include <osmocom/msc/vlr.h> +#include <osmocom/msc/codec_mapping.h> struct osmo_fsm mncc_call_fsm; static bool mncc_call_tx_rtp_create(struct mncc_call *mncc_call); @@ -262,37 +263,18 @@ static bool mncc_call_rx_rtp_create(struct mncc_call *mncc_call) return true; } - if (!mncc_call->rtps->codec_known) { + if (!mncc_call->rtps->codecs_known) { LOG_MNCC_CALL(mncc_call, LOGL_DEBUG, "Got RTP_CREATE, but RTP stream has no codec set\n"); return true; } LOG_MNCC_CALL(mncc_call, LOGL_DEBUG, "Got RTP_CREATE, responding with " OSMO_SOCKADDR_STR_FMT " %s\n", OSMO_SOCKADDR_STR_FMT_ARGS(&mncc_call->rtps->local), - osmo_mgcpc_codec_name(mncc_call->rtps->codec)); + sdp_audio_codecs_to_str(&mncc_call->rtps->codecs)); /* Already know what RTP IP:port to tell the MNCC. Send it. */ return mncc_call_tx_rtp_create(mncc_call); } -/* Convert enum mgcp_codecs to an gsm_mncc_rtp->payload_msg_type value. */ -uint32_t mgcp_codec_to_mncc_payload_msg_type(enum mgcp_codecs codec) -{ - switch (codec) { - default: - /* disclaimer: i have no idea what i'm doing. */ - case CODEC_GSM_8000_1: - return GSM_TCHF_FRAME; - case CODEC_GSMEFR_8000_1: - return GSM_TCHF_FRAME_EFR; - case CODEC_GSMHR_8000_1: - return GSM_TCHH_FRAME; - case CODEC_AMR_8000_1: - case CODEC_AMRWB_16000_1: - //return GSM_TCHF_FRAME; - return GSM_TCH_FRAME_AMR; - } -} - static bool mncc_call_tx_rtp_create(struct mncc_call *mncc_call) { if (!mncc_call->rtps || !osmo_sockaddr_str_is_nonzero(&mncc_call->rtps->local)) { @@ -313,9 +295,17 @@ static bool mncc_call_tx_rtp_create(struct mncc_call *mncc_call) return false; } - if (mncc_call->rtps->codec_known) { - mncc_msg.rtp.payload_type = 0; /* ??? */ - mncc_msg.rtp.payload_msg_type = mgcp_codec_to_mncc_payload_msg_type(mncc_call->rtps->codec); + if (mncc_call->rtps->codecs_known) { + struct sdp_audio_codec *codec = &mncc_call->rtps->codecs.codec[0]; + const struct codec_mapping *m = codec_mapping_by_subtype_name(codec->subtype_name); + + if (!m) { + mncc_call_error(mncc_call, "Failed to resolve audio codec '%s'\n", + sdp_audio_codec_to_str(codec)); + return false; + } + mncc_msg.rtp.payload_type = codec->payload_type; + mncc_msg.rtp.payload_msg_type = m->mncc_payload_msg_type; } if (mncc_call_tx(mncc_call, &mncc_msg)) diff --git a/src/libmsc/mncc_sock.c b/src/libmsc/mncc_sock.c index b76855fad..410449d6d 100644 --- a/src/libmsc/mncc_sock.c +++ b/src/libmsc/mncc_sock.c @@ -6,18 +6,14 @@ * All Rights Reserved * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. * */ @@ -75,9 +71,9 @@ static void mncc_sock_close(struct mncc_sock_state *state) LOGP(DMNCC, LOGL_NOTICE, "MNCC Socket has LOST connection\n"); + osmo_fd_unregister(bfd); close(bfd->fd); bfd->fd = -1; - osmo_fd_unregister(bfd); /* re-enable the generation of ACCEPT for new connections */ osmo_fd_read_enable(&state->listen_bfd); diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c index 74721d2de..db1d9983a 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -1,6 +1,6 @@ /* Code to manage a subscriber's MSC-A role */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -36,6 +36,7 @@ #include <osmocom/msc/signal.h> #include <osmocom/msc/vlr.h> #include <osmocom/msc/transaction.h> +#include <osmocom/msc/transaction_cc.h> #include <osmocom/msc/ran_peer.h> #include <osmocom/msc/ran_msg_a.h> #include <osmocom/msc/ran_msg_iu.h> @@ -46,6 +47,8 @@ #include <osmocom/msc/call_leg.h> #include <osmocom/msc/rtp_stream.h> #include <osmocom/msc/msc_ho.h> +#include <osmocom/msc/codec_mapping.h> +#include <osmocom/msc/msc_vgcs.h> #define MSC_A_USE_WAIT_CLEAR_COMPLETE "wait-Clear-Complete" @@ -106,7 +109,7 @@ struct msc_a *msc_a_fi_priv(struct osmo_fsm_inst *fi) return fi->priv; } -bool msc_a_require_ciphering(const struct msc_a *msc_a) +bool msc_a_is_ciphering_to_be_attempted(const struct msc_a *msc_a) { struct gsm_network *net = msc_a_net(msc_a); bool is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU); @@ -116,6 +119,18 @@ bool msc_a_require_ciphering(const struct msc_a *msc_a) return net->a5_encryption_mask > 0x1; } +bool msc_a_is_ciphering_required(const struct msc_a *msc_a) +{ + struct gsm_network *net = msc_a_net(msc_a); + bool is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU); + if (is_utran) + return net->uea_encryption_mask + && ((net->uea_encryption_mask & (1 << OSMO_UTRAN_UEA0)) == 0); + else + return net->a5_encryption_mask + && ((net->a5_encryption_mask & 0x1) == 0); +} + static void update_counters(struct osmo_fsm_inst *fi, bool conn_accepted) { struct msc_a *msc_a = fi->priv; @@ -167,7 +182,7 @@ static void evaluate_acceptance_outcome(struct osmo_fsm_inst *fi, bool conn_acce if (msc_a->complete_layer3_type == COMPLETE_LAYER3_LU) msc_a_put(msc_a, MSC_A_USE_LOCATION_UPDATING); - if (msc_a->complete_layer3_type == COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ) { + if (conn_accepted && msc_a->complete_layer3_type == COMPLETE_LAYER3_CM_RE_ESTABLISH_REQ) { /* Trigger new Assignment to recommence the voice call. A little dance here because normally we verify * that no CC trans is already active. */ struct gsm_trans *cc_trans = msc_a->cc.active_trans; @@ -474,6 +489,16 @@ static bool msc_a_fsm_has_active_transactions(struct osmo_fsm_inst *fi) __func__); return true; } + if (osmo_use_count_by(&msc_a->use_count, MSC_A_USE_CM_SERVICE_GCC)) { + LOG_MSC_A(msc_a, LOGL_DEBUG, "%s: still awaiting MO GCC request after a CM Service Request\n", + __func__); + return true; + } + if (osmo_use_count_by(&msc_a->use_count, MSC_A_USE_CM_SERVICE_BCC)) { + LOG_MSC_A(msc_a, LOGL_DEBUG, "%s: still awaiting MO BCC request after a CM Service Request\n", + __func__); + return true; + } if (osmo_use_count_by(&msc_a->use_count, MSC_A_USE_CM_SERVICE_SMS)) { LOG_MSC_A(msc_a, LOGL_DEBUG, "%s: still awaiting MO SMS after a CM Service Request\n", __func__); @@ -550,8 +575,68 @@ static void msc_a_fsm_authenticated(struct osmo_fsm_inst *fi, uint32_t event, vo } } +static struct call_leg *msc_a_ensure_call_leg(struct msc_a *msc_a, struct gsm_trans *for_cc_trans) +{ + struct call_leg *cl = msc_a->cc.call_leg; + struct gsm_network *net = msc_a_net(msc_a); + + /* Ensure that events about RTP endpoints coming from the msc_a->cc.call_leg know which gsm_trans to abort on + * error */ + if (!msc_a->cc.active_trans) + msc_a->cc.active_trans = for_cc_trans; + if (msc_a->cc.active_trans != for_cc_trans) { + LOG_TRANS(for_cc_trans, LOGL_ERROR, + "Cannot create call leg, another trans is already active for this conn\n"); + return NULL; + } + + if (!cl) { + cl = msc_a->cc.call_leg = call_leg_alloc(msc_a->c.fi, + MSC_EV_CALL_LEG_TERM, + MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, + MSC_EV_CALL_LEG_RTP_COMPLETE); + OSMO_ASSERT(cl); + + if (net->use_osmux != OSMUX_USAGE_OFF) { + struct msc_i *msc_i = msc_a_msc_i(msc_a); + if (msc_i->c.remote_to) { + /* TODO: investigate what to do in this case */ + LOG_MSC_A(msc_a, LOGL_ERROR, "Osmux not yet supported for inter-MSC"); + } else { + cl->ran_peer_supports_osmux = msc_i->ran_conn->ran_peer->remote_supports_osmux; + } + } + + } + return cl; +} + +int msc_a_ensure_cn_local_rtp(struct msc_a *msc_a, struct gsm_trans *cc_trans) +{ + struct call_leg *cl; + struct rtp_stream *rtp_to_ran; + + cl = msc_a_ensure_call_leg(msc_a, cc_trans); + if (!cl) + return -EINVAL; + rtp_to_ran = cl->rtp[RTP_TO_RAN]; + + if (call_leg_local_ip(cl, RTP_TO_CN)) { + /* Already has an RTP address and port towards the CN, continue right away. */ + return osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, cl->rtp[RTP_TO_CN]); + } + + /* No CN RTP address available yet, ask the MGW to create one. + * Set a codec to be used: if Assignment on the RAN side is already done, take the same codec as the RTP_TO_RAN. + * If no RAN side RTP is established, try to guess a preliminary codec from SDP -- before Assignment, picking a + * codec from the SDP is more politeness/avoiding confusion than necessity. The actual codec to be used would be + * determined later. If no codec could be determined, pass none for the time being. */ + return call_leg_ensure_ci(cl, RTP_TO_CN, cc_trans->call_id, cc_trans, + rtp_to_ran->codecs_known ? &rtp_to_ran->codecs : NULL, NULL); +} + /* The MGW has given us a local IP address for the RAN side. Ready to start the Assignment of a voice channel. */ -static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) +void msc_a_tx_assignment_cmd(struct msc_a *msc_a) { struct ran_msg msg; struct gsm_trans *cc_trans = msc_a->cc.active_trans; @@ -563,16 +648,53 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) return; } - /* Once a CI is known, we could also CRCX the CN side of the MGW endpoint, but it makes sense to wait for the - * codec to be determined by the Assignment Complete message, first. */ + trans_cc_filter_run(cc_trans); + LOG_TRANS(cc_trans, LOGL_DEBUG, "Sending Assignment Command\n"); - if (mncc_bearer_cap_to_channel_type(&channel_type, &cc_trans->bearer_cap)) { - LOG_MSC_A(msc_a, LOGL_ERROR, "Cannot compose Channel Type from bearer capabilities\n"); - trans_free(cc_trans); + switch (cc_trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + if (!cc_trans->cc.local.audio_codecs.count) { + LOG_TRANS(cc_trans, LOGL_ERROR, "Assignment not possible, no matching codec: %s\n", + codec_filter_to_str(&cc_trans->cc.codecs, &cc_trans->cc.local, &cc_trans->cc.remote)); + call_leg_release(msc_a->cc.call_leg); + return; + } + + /* Compose 48.008 Channel Type from the current set of codecs + * determined from both local and remote codec capabilities. */ + if (sdp_audio_codecs_to_gsm0808_channel_type(&channel_type, &cc_trans->cc.local.audio_codecs)) { + LOG_MSC_A(msc_a, LOGL_ERROR, "Cannot compose Channel Type (Permitted Speech) from codecs: %s\n", + codec_filter_to_str(&cc_trans->cc.codecs, &cc_trans->cc.local, &cc_trans->cc.remote)); + trans_free(cc_trans); + return; + } + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + if (!cc_trans->cc.local.bearer_services.count) { + LOG_TRANS(cc_trans, LOGL_ERROR, "Assignment not possible, no matching bearer service: %s\n", + csd_filter_to_str(&cc_trans->cc.csd, &cc_trans->cc.local, &cc_trans->cc.remote)); + call_leg_release(msc_a->cc.call_leg); + return; + } + + /* Compose 48.008 Channel Type from the current set of bearer + * services determined from local and remote capabilities. */ + if (csd_bs_list_to_gsm0808_channel_type(&channel_type, &cc_trans->cc.local.bearer_services)) { + LOG_MSC_A(msc_a, LOGL_ERROR, "Cannot compose channel type from: %s\n", + csd_filter_to_str(&cc_trans->cc.csd, &cc_trans->cc.local, &cc_trans->cc.remote)); + return; + } + break; + default: + LOG_TRANS(cc_trans, LOGL_ERROR, "Assignment not possible for information transfer capability %d\n", + cc_trans->bearer_cap.transfer); + call_leg_release(msc_a->cc.call_leg); return; } - /* The RAN side RTP address is known, so the voice Assignment can commence. */ + /* The RAN side RTP address is known, so the voice/CSD Assignment can commence. */ msg = (struct ran_msg){ .msg_type = RAN_MSG_ASSIGNMENT_COMMAND, .assignment_command = { @@ -581,7 +703,7 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) .osmux_present = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->use_osmux, .osmux_cid = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->local_osmux_cid, .call_id_present = true, - .call_id = cc_trans->callref, + .call_id = cc_trans->call_id, .lcls = cc_trans->cc.lcls, }, }; @@ -592,15 +714,6 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) } } -static void msc_a_call_leg_cn_local_addr_available(struct msc_a *msc_a, struct gsm_trans *cc_trans) -{ - if (gsm48_tch_rtp_create(cc_trans)) { - LOG_MSC_A(msc_a, LOGL_ERROR, "Cannot inform MNCC of RTP address\n"); - trans_free(cc_trans); - return; - } -} - static struct gsm_trans *find_waiting_call(struct msc_a *msc_a) { struct gsm_trans *trans; @@ -691,10 +804,10 @@ static void msc_a_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, vo rtps->use_osmux ? "yes" : "no", rtps->local_osmux_cid); switch (rtps->dir) { case RTP_TO_RAN: - msc_a_call_leg_ran_local_addr_available(msc_a); + msc_a_tx_assignment_cmd(msc_a); return; case RTP_TO_CN: - msc_a_call_leg_cn_local_addr_available(msc_a, rtps->for_trans); + cc_on_cn_local_rtp_port_known(rtps->for_trans); return; default: LOG_MSC_A(msc_a, LOGL_ERROR, "Invalid data for %s\n", osmo_fsm_event_name(fi->fsm, event)); @@ -773,6 +886,8 @@ static void msc_a_fsm_releasing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_ MSC_A_USE_CM_SERVICE_CC, MSC_A_USE_CM_SERVICE_SMS, MSC_A_USE_CM_SERVICE_SS, + MSC_A_USE_CM_SERVICE_GCC, + MSC_A_USE_CM_SERVICE_BCC, MSC_A_USE_PAGING_RESPONSE, }; @@ -884,6 +999,7 @@ static void msc_a_fsm_released(struct osmo_fsm_inst *fi, uint32_t event, void *d void msc_a_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) { struct msc_a *msc_a = msc_a_fi_priv(fi); + struct vlr_subscr *vsub = msc_a_vsub(msc_a); trans_conn_closed(msc_a); @@ -891,6 +1007,10 @@ void msc_a_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) LOG_MSC_A(msc_a, LOGL_ERROR, "Deallocating active transactions failed\n"); LOG_MSC_A_CAT(msc_a, DREF, LOGL_DEBUG, "max total use count was %d\n", msc_a->max_total_use_count); + + /* Invalidate the active conn in VLR subscriber state, if any. */ + if (vsub && vsub->msc_conn_ref == msc_a) + vsub->msc_conn_ref = NULL; } const struct value_string msc_a_fsm_event_names[] = { @@ -1273,6 +1393,10 @@ int msc_a_up_l3(struct msc_a *msc_a, struct msgb *msg) #endif switch (pdisc) { + case GSM48_PDISC_GROUP_CC: + case GSM48_PDISC_BCAST_CC: + rc = gsm44068_rcv_bcc_gcc(msc_a, NULL, msg); + break; case GSM48_PDISC_CC: rc = gsm0408_rcv_cc(msc_a, msg); break; @@ -1309,15 +1433,29 @@ int msc_a_up_l3(struct msc_a *msc_a, struct msgb *msg) static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct ran_msg *ac) { - struct gsm_trans *cc_trans = msc_a->cc.active_trans; + struct gsm_trans *cc_trans = msc_a->cc.active_trans, *gcc_trans; struct rtp_stream *rtps_to_ran = msc_a->cc.call_leg ? msc_a->cc.call_leg->rtp[RTP_TO_RAN] : NULL; + const struct gsm0808_speech_codec *codec_if_known = ac->assignment_complete.codec_present ? + &ac->assignment_complete.codec : NULL; + + /* For a voice group call, handling is performed by VGCS FSM */ + gcc_trans = trans_find_by_type(msc_a, TRANS_GCC); + if (gcc_trans) { + vgcs_vbs_caller_assign_cpl(gcc_trans); + return; + } + gcc_trans = trans_find_by_type(msc_a, TRANS_BCC); + if (gcc_trans) { + vgcs_vbs_caller_assign_cpl(gcc_trans); + return; + } if (!rtps_to_ran) { LOG_MSC_A(msc_a, LOGL_ERROR, "Rx Assignment Complete, but no RTP stream is set up\n"); return; } if (!cc_trans) { - LOG_MSC_A(msc_a, LOGL_ERROR, "Rx Assignment Complete, but CC transaction is active\n"); + LOG_MSC_A(msc_a, LOGL_ERROR, "Rx Assignment Complete, but no CC transaction is active\n"); return; } @@ -1328,24 +1466,76 @@ static void msc_a_up_call_assignment_complete(struct msc_a *msc_a, const struct return; } - /* Update RAN-side endpoint CI: */ - rtp_stream_set_codec(rtps_to_ran, ac->assignment_complete.codec); + if (codec_if_known) { + const struct codec_mapping *codec_assigned; + + /* Check for unexpected codec with CSD */ + switch (cc_trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + if (codec_if_known->type == GSM0808_SCT_CSD) + break; /* we're good */ + LOG_TRANS(cc_trans, LOGL_ERROR, "Unexpected codec in Assignment Complete for CSD: %s\n", + gsm0808_speech_codec_type_name(codec_if_known->type)); + call_leg_release(msc_a->cc.call_leg); + return; + default: + break; + } + + /* For 2G: + * - The Assignment Complete has returned a specific codec (e.g. FR3 for AMR FR). + * - Set this codec at the MGW endpoint facing the RAN. + * - Also set this codec at the MGW endpoint facing the CN -- we require an exact match on both call + * legs. + * - TODO: be aware of transcoding that the MGW is capable of, e.g. AMR octet-aligned to AMR + * bandwidth-efficient... + * + * For 3G: + * - ran_infra->force_mgw_codecs_to_ran sets VND.3GPP.IUFP as single codec at the MGW towards RAN. + * - ran_msg_iu.c always returns FR3 (AMR FR) for the assigned codec. Set that at the MGW towards CN. + * - So the MGW decapsulates IuUP <-> AMR + */ + codec_assigned = codec_mapping_by_gsm0808_speech_codec_type(codec_if_known->type); + /* TODO: use codec_mapping_by_gsm0808_speech_codec() to also match on codec_if_known->cfg */ + if (!codec_assigned) { + LOG_TRANS(cc_trans, LOGL_ERROR, "Unknown codec in Assignment Complete: %s\n", + gsm0808_speech_codec_type_name(codec_if_known->type)); + call_leg_release(msc_a->cc.call_leg); + return; + } + + /* Update RAN-side endpoint CI from Assignment result -- unless it is forced by the ran_infra, in which + * case it remains unchanged as passed to the earlier call of call_leg_ensure_ci(). */ + if (msc_a->c.ran->force_mgw_codecs_to_ran.count == 0) + rtp_stream_set_one_codec(rtps_to_ran, &codec_assigned->sdp); + + /* Update codec filter with Assignment result, for the CN side */ + cc_trans->cc.codecs.assignment = codec_assigned->sdp; + } else { + /* No codec passed in Assignment Complete, set 'codecs.assignment' to none. */ + cc_trans->cc.codecs.assignment = (struct sdp_audio_codec){}; + LOG_TRANS(cc_trans, LOGL_INFO, "Assignment Complete without voice codec\n"); + } + rtp_stream_set_remote_addr(rtps_to_ran, &ac->assignment_complete.remote_rtp); if (rtps_to_ran->use_osmux) rtp_stream_set_remote_osmux_cid(rtps_to_ran, ac->assignment_complete.osmux_cid); - rtp_stream_commit(rtps_to_ran); - /* Setup CN side endpoint CI: - * Now that - * - the first CI has been created and a definitive endpoint name is assigned to the call_leg's MGW - * endpoint, - * - the Assignment has chosen a speech codec - * go on to create the CN side RTP stream's CI. */ - if (call_leg_ensure_ci(msc_a->cc.call_leg, RTP_TO_CN, cc_trans->callref, cc_trans, - &ac->assignment_complete.codec, NULL)) { - LOG_MSC_A_CAT(msc_a, DCC, LOGL_ERROR, "Error creating MGW CI towards CN\n"); + /* Remember the Codec List (BSS Supported) */ + if (ac->assignment_complete.codec_list_bss_supported) + codec_filter_set_bss(&cc_trans->cc.codecs, ac->assignment_complete.codec_list_bss_supported); + + trans_cc_filter_run(cc_trans); + LOG_TRANS(cc_trans, LOGL_INFO, "Assignment Complete: RAN: %s, CN: %s\n", + sdp_audio_codecs_to_str(&rtps_to_ran->codecs), + sdp_audio_codecs_to_str(&cc_trans->cc.local.audio_codecs)); + + if (cc_on_assignment_done(cc_trans)) { + /* If an error occurred, it was logged in cc_assignment_done() */ call_leg_release(msc_a->cc.call_leg); return; } @@ -1362,6 +1552,18 @@ static void msc_a_up_call_assignment_failure(struct msc_a *msc_a, const struct r return; } + /* For a voice group call, release is performed by VGCS FSM */ + trans = trans_find_by_type(msc_a, TRANS_GCC); + if (trans) { + vgcs_vbs_caller_assign_fail(trans); + return; + } + trans = trans_find_by_type(msc_a, TRANS_BCC); + if (trans) { + vgcs_vbs_caller_assign_fail(trans); + return; + } + /* Otherwise, a silent call might be active */ trans = trans_find_by_type(msc_a, TRANS_SILENT_CALL); if (trans) { @@ -1427,6 +1629,20 @@ int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d) .lai.plmn = msc_a_net(msc_a)->plmn, }; gsm0808_cell_id_to_cgi(&msc_a->via_cell, msg->compl_l3.cell_id); + + /* If a codec list was sent along in the RAN_MSG_COMPL_L3, remember it for any upcoming codec + * resolution. */ + if (msg->compl_l3.codec_list_bss_supported) { + msc_a->cc.compl_l3_codec_list_bss_supported = *msg->compl_l3.codec_list_bss_supported; + if (log_check_level(msc_a->c.ran->log_subsys, LOGL_DEBUG)) { + struct sdp_audio_codecs ac = {}; + sdp_audio_codecs_from_speech_codec_list(&ac, &msc_a->cc.compl_l3_codec_list_bss_supported); + LOG_MSC_A(msc_a, LOGL_DEBUG, "Complete Layer 3: Codec List (BSS Supported): %s\n", + sdp_audio_codecs_to_str(&ac)); + } + } + + /* Submit the Complete Layer 3 Information DTAP */ rc = msc_a_up_l3(msc_a, msg->compl_l3.msg); if (!rc) { struct ran_conn *conn = msub_ran_conn(msc_a->c.msub); @@ -1554,6 +1770,136 @@ int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d) return rc; } +static int msc_a_rx_vgcs_bss_decoded(struct osmo_fsm_inst *caller_fi, void *caller_data, const struct ran_msg *msg) +{ + struct vgcs_bss *bss = caller_data; + struct msc_a *msc_a = (bss->trans) ? bss->trans->msc_a : NULL; + int rc = 0; + + switch (msg->msg_type) { + case RAN_MSG_VGCS_VBS_SETUP_ACK: + /* The BSS accepts VGCS/VBS and sends us supported features. */ + vgcs_vbs_setup_ack(bss, msg); + break; + case RAN_MSG_VGCS_VBS_SETUP_REFUSE: + /* The BSS refuses VGCS/VBS. */ + vgcs_vbs_setup_refuse(bss, msg); + break; + case RAN_MSG_UPLINK_REQUEST: + /* A mobile station requests the uplink on a VGCS channel. */ + vgcs_uplink_request(bss, msg); + break; + case RAN_MSG_UPLINK_REQUEST_CNF: + /* The uplink on a VGCS channel has been established. */ + vgcs_uplink_request_cnf(bss, msg); + break; + case RAN_MSG_UPLINK_APPLICATION_DATA: + /* Application data received on the uplink of a VGCS channel. */ + vgcs_app_data(bss, msg); + break; + case RAN_MSG_DTAP: + /* BSS confirms the release of the channel. */ + vgcs_bss_dtap(bss, msg); + break; + case RAN_MSG_UPLINK_RELEASE_IND: + /* A mobile station releases the uplink on a VGCS channel. */ + vgcs_uplink_release_ind(bss, msg); + break; + case RAN_MSG_CLEAR_REQUEST: + /* BSS indicated that the channel has been released. */ + vgcs_vbs_clear_req(bss, msg); + break; + case RAN_MSG_CLEAR_COMPLETE: + /* BSS confirms the release of the channel. */ + vgcs_vbs_clear_cpl(bss, msg); + break; + default: + LOG_MSC_A(msc_a, LOGL_ERROR, "VGCS message from BSS not implemented: %s\n", + ran_msg_type_name(msg->msg_type)); + rc = -ENOTSUP; + break; + } + return rc; +} + +int msc_a_rx_vgcs_bss(struct vgcs_bss *bss, struct ran_conn *from_conn, struct msgb *msg) +{ + struct ran_dec ran_dec; + + /* Feed through the decoding mechanism ran_msg. The decoded message arrives in msc_a_rx_vgcs_decoded() */ + ran_dec = (struct ran_dec) { + .caller_data = bss, + .decode_cb = msc_a_rx_vgcs_bss_decoded, + }; + struct ran_peer *ran_peer = from_conn->ran_peer; + struct ran_infra *ran = ran_peer->sri->ran; + if (!ran->ran_dec_l2) { + LOGP(DMSC, LOGL_ERROR, "No ran_dec_l2() defined for RAN type %s\n", + osmo_rat_type_name(ran->type)); + return -ENOTSUP; + } + return ran->ran_dec_l2(&ran_dec, msg); +} + +static int msc_a_rx_vgcs_cell_decoded(struct osmo_fsm_inst *caller_fi, void *caller_data, const struct ran_msg *msg) +{ + struct vgcs_bss_cell *cell = caller_data; + struct msc_a *msc_a = (cell->bss && cell->bss->trans) ? cell->bss->trans->msc_a : NULL; + int rc = 0; + + switch (msg->msg_type) { + case RAN_MSG_VGCS_VBS_ASSIGN_RES: + /* The BSS accepts VGCS/VBS channel assignment. */ + vgcs_vbs_assign_result(cell, msg); + break; + case RAN_MSG_VGCS_VBS_ASSIGN_FAIL: + /* The BSS refuses VGCS/VBS channel assignment. */ + vgcs_vbs_assign_fail(cell, msg); + break; + case RAN_MSG_VGCS_VBS_QUEUING_IND: + /* The BSS needs more time for VGCS/VBS channel assignment. */ + vgcs_vbs_queuing_ind(cell); + break; + case RAN_MSG_VGCS_VBS_ASSIGN_STATUS: + /* The BSS gives cell status about VGCS/VBS channel. */ + vgcs_vbs_assign_status(cell, msg); + break; + case RAN_MSG_CLEAR_REQUEST: + /* BSS indicated that the channel has been released. */ + vgcs_vbs_clear_req_channel(cell, msg); + break; + case RAN_MSG_CLEAR_COMPLETE: + /* BSS confirms the release of the channel. */ + vgcs_vbs_clear_cpl_channel(cell, msg); + break; + default: + LOG_MSC_A(msc_a, LOGL_ERROR, "Message from BSS leg not implemented: %s\n", + ran_msg_type_name(msg->msg_type)); + rc = -ENOTSUP; + break; + } + return rc; +} + +int msc_a_rx_vgcs_cell(struct vgcs_bss_cell *cell, struct ran_conn *from_conn, struct msgb *msg) +{ + struct ran_dec ran_dec; + + /* Feed through the decoding mechanism ran_msg. The decoded message arrives in msc_a_rx_vgcs_decoded() */ + ran_dec = (struct ran_dec) { + .caller_data = cell, + .decode_cb = msc_a_rx_vgcs_cell_decoded, + }; + struct ran_peer *ran_peer = from_conn->ran_peer; + struct ran_infra *ran = ran_peer->sri->ran; + if (!ran->ran_dec_l2) { + LOGP(DMSC, LOGL_ERROR, "No ran_dec_l2() defined for RAN type %s\n", + osmo_rat_type_name(ran->type)); + return -ENOTSUP; + } + return ran->ran_dec_l2(&ran_dec, msg); +} + static int msc_a_ran_dec_from_msc_t(struct msc_a *msc_a, struct msc_a_ran_dec_data *d) { struct msc_t *msc_t = msc_a_msc_t(msc_a); @@ -1659,12 +2005,9 @@ int _msc_a_msg_down(struct msc_a *msc_a, enum msc_role to_role, uint32_t to_role .an_proto = msc_a->c.ran->an_proto, .msg = msc_role_ran_encode(msc_a->c.fi, ran_msg), }; - int rc; if (!an_apdu.msg) return -EIO; - rc = _msub_role_dispatch(msc_a->c.msub, to_role, to_role_event, &an_apdu, file, line); - msgb_free(an_apdu.msg); - return rc; + return _msub_role_dispatch(msc_a->c.msub, to_role, to_role_event, &an_apdu, file, line); } int msc_a_tx_dtap_to_i(struct msc_a *msc_a, struct msgb *dtap) @@ -1725,45 +2068,49 @@ int msc_tx_common_id(struct msc_a *msc_a, enum msc_role to_role) static int msc_a_start_assignment(struct msc_a *msc_a, struct gsm_trans *cc_trans) { - struct call_leg *cl = msc_a->cc.call_leg; - struct msc_i *msc_i = msc_a_msc_i(msc_a); - struct gsm_network *net = msc_a_net(msc_a); + struct call_leg *cl; + bool cn_rtp_available; + bool ran_rtp_available; OSMO_ASSERT(!msc_a->cc.active_trans); msc_a->cc.active_trans = cc_trans; - OSMO_ASSERT(cc_trans && cc_trans->type == TRANS_CC); + cc_trans->cc.codecs.assignment = (struct sdp_audio_codec){}; - if (!cl) { - cl = msc_a->cc.call_leg = call_leg_alloc(msc_a->c.fi, - MSC_EV_CALL_LEG_TERM, - MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, - MSC_EV_CALL_LEG_RTP_COMPLETE); - OSMO_ASSERT(cl); - - /* HACK: We put the connection in loopback mode at the beginning to - * trick the hNodeB into doing the IuUP negotiation with itself. - * This is a hack we need because osmo-mgw does not support IuUP yet, see OS#2459. */ - if (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU) - cl->crcx_conn_mode[RTP_TO_RAN] = MGCP_CONN_LOOPBACK; - } + OSMO_ASSERT(cc_trans && cc_trans->type == TRANS_CC); + cl = msc_a_ensure_call_leg(msc_a, cc_trans); + if (!cl) + return -EINVAL; - if (net->use_osmux != OSMUX_USAGE_OFF) { - msc_i = msc_a_msc_i(msc_a); - if (msc_i->c.remote_to) { - /* TODO: investigate what to do in this case */ - LOG_MSC_A(msc_a, LOGL_ERROR, "Osmux not yet supported for inter-MSC"); - } else { - cl->ran_peer_supports_osmux = msc_i->ran_conn->ran_peer->remote_supports_osmux; - } + /* See if we can set a preliminary codec. If not, pass none for the time being. */ + trans_cc_filter_run(cc_trans); + + cn_rtp_available = call_leg_local_ip(cl, RTP_TO_CN); + ran_rtp_available = call_leg_local_ip(cl, RTP_TO_RAN); + + /* Set up RTP ports for both RAN and CN side. Even though we ask for both at the same time, the + * osmo_mgcpc_ep_fsm automagically waits for the first CRCX to complete before firing the second CRCX. The one + * issued first here will also be the first CRCX sent to the MGW. Usually both still need to be set up. */ + if (!cn_rtp_available) + call_leg_ensure_ci(cl, RTP_TO_CN, cc_trans->call_id, cc_trans, + &cc_trans->cc.local.audio_codecs, NULL); + if (!ran_rtp_available) { + struct sdp_audio_codecs *codecs; + if (msc_a->c.ran->force_mgw_codecs_to_ran.count) + codecs = &msc_a->c.ran->force_mgw_codecs_to_ran; + else + codecs = &cc_trans->cc.local.audio_codecs; + return call_leg_ensure_ci(cl, RTP_TO_RAN, cc_trans->call_id, cc_trans, codecs, NULL); } - /* This will lead to either MSC_EV_CALL_LEG_LOCAL_ADDR_AVAILABLE or MSC_EV_CALL_LEG_TERM. - * If the local address is already known, then immediately trigger. */ - if (call_leg_local_ip(cl, RTP_TO_RAN)) + /* Should these already be set up, immediately continue by retriggering the events signalling that the RTP + * ports are available. The ordering is: first CN, then RAN. */ + if (cn_rtp_available && ran_rtp_available) return osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, cl->rtp[RTP_TO_RAN]); - else - return call_leg_ensure_ci(msc_a->cc.call_leg, RTP_TO_RAN, cc_trans->callref, cc_trans, NULL, NULL); + else if (cn_rtp_available) + return osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, cl->rtp[RTP_TO_CN]); + /* Otherwise wait for MGCP response and continue from there. */ + return 0; } int msc_a_try_call_assignment(struct gsm_trans *cc_trans) @@ -1785,8 +2132,14 @@ int msc_a_try_call_assignment(struct gsm_trans *cc_trans) return msc_a_start_assignment(msc_a, cc_trans); } -const char *msc_a_cm_service_type_to_use(enum osmo_cm_service_type cm_service_type) +/* Map CM Service type to use token. + * Given a CM Service type, return a matching token intended for osmo_use_count. + * For unknown service type, return NULL. + */ +const char *msc_a_cm_service_type_to_use(struct msc_a *msc_a, enum osmo_cm_service_type cm_service_type) { + struct gsm_network *net = msc_a_net(msc_a); + switch (cm_service_type) { case GSM48_CMSERV_MO_CALL_PACKET: case GSM48_CMSERV_EMERGENCY: @@ -1798,6 +2151,18 @@ const char *msc_a_cm_service_type_to_use(enum osmo_cm_service_type cm_service_ty case GSM48_CMSERV_SUP_SERV: return MSC_A_USE_CM_SERVICE_SS; + case GSM48_CMSERV_VGCS: + if (net->asci.enable) + return MSC_A_USE_CM_SERVICE_GCC; + else + return NULL; + + case GSM48_CMSERV_VBS: + if (net->asci.enable) + return MSC_A_USE_CM_SERVICE_BCC; + else + return NULL; + default: return NULL; } diff --git a/src/libmsc/msc_a_remote.c b/src/libmsc/msc_a_remote.c index 84eff0730..3b9693e59 100644 --- a/src/libmsc/msc_a_remote.c +++ b/src/libmsc/msc_a_remote.c @@ -1,6 +1,6 @@ /* The MSC-A role implementation variant that forwards requests to/from a remote MSC. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -179,8 +179,6 @@ static void msc_a_remote_send_handover_failure(struct msc_a *msc_a, enum gsm0808 return; msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T, OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR, &an_apdu); - msgb_free(an_apdu.msg); - return; } /* [MSC-A---------------------] [MSC-B---------------------] diff --git a/src/libmsc/msc_ho.c b/src/libmsc/msc_ho.c index 6b8960e09..54a959d2c 100644 --- a/src/libmsc/msc_ho.c +++ b/src/libmsc/msc_ho.c @@ -1,25 +1,21 @@ /* MSC Handover implementation */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <osmocom/core/fsm.h> @@ -43,6 +39,7 @@ #include <osmocom/msc/call_leg.h> #include <osmocom/msc/rtp_stream.h> #include <osmocom/msc/mncc_call.h> +#include <osmocom/msc/codec_mapping.h> struct osmo_fsm msc_ho_fsm; @@ -383,6 +380,7 @@ static void msc_ho_send_handover_request(struct msc_a *msc_a) struct vlr_subscr *vsub = msc_a_vsub(msc_a); struct gsm_network *net = msc_a_net(msc_a); struct gsm0808_channel_type channel_type; + struct gsm0808_speech_codec_list scl = {}; struct gsm_trans *cc_trans = msc_a->cc.active_trans; struct ran_msg ran_enc_msg = { .msg_type = RAN_MSG_HANDOVER_REQUEST, @@ -403,8 +401,6 @@ static void msc_ho_send_handover_request(struct msc_a *msc_a) /* Don't send AoIP Transport Layer Address for inter-MSC Handover */ .rtp_ran_local = (msc_a->ho.new_cell.type == MSC_NEIGHBOR_TYPE_LOCAL_RAN_PEER) ? call_leg_local_ip(msc_a->cc.call_leg, RTP_TO_RAN) : NULL, - .call_id_present = true, - .call_id = cc_trans->callref, }, }; @@ -416,13 +412,49 @@ static void msc_ho_send_handover_request(struct msc_a *msc_a) osmo_hexdump_nospc_c(OTC_SELECT, msc_a->geran_encr.kc128, sizeof(msc_a->geran_encr.kc128)) : "-"); - if (msc_a->cc.active_trans) { - if (mncc_bearer_cap_to_channel_type(&channel_type, &msc_a->cc.active_trans->bearer_cap)) { - msc_ho_failed(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE, - "Failed to encode Bearer Cap to Channel Type\n"); + if (cc_trans) { + switch (cc_trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + if (sdp_audio_codecs_to_gsm0808_channel_type(&channel_type, + &cc_trans->cc.local.audio_codecs)) { + msc_ho_failed(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE, + "Failed to determine Channel Type for Handover Request message (speech)\n"); + return; + } + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + if (csd_bs_list_to_gsm0808_channel_type(&channel_type, &cc_trans->cc.local.bearer_services)) { + msc_ho_failed(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE, + "Failed to determine Channel Type for Handover Request message (CSD)\n"); + return; + } + break; + default: + msc_ho_failed(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE, "Failed to create" + " Handover Request message for information transfer capability %d\n", + cc_trans->bearer_cap.transfer); return; } + ran_enc_msg.handover_request.geran.channel_type = &channel_type; + ran_enc_msg.handover_request.call_id_present = true; + ran_enc_msg.handover_request.call_id = cc_trans->call_id; + + /* Call assignment is now capable of re-assigning to overcome a codec mismatch with the remote call leg. + * But for inter-MSC handover, that is not supported yet. So keep here the old limitation of only + * offering the assigned codec. */ + if (sdp_audio_codec_is_set(&cc_trans->cc.codecs.assignment)) + sdp_audio_codec_to_speech_codec_list(&scl, &cc_trans->cc.codecs.assignment); + else + sdp_audio_codecs_to_speech_codec_list(&scl, &cc_trans->cc.local.audio_codecs); + if (!scl.len) { + msc_ho_failed(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE, "Failed to compose" + " Codec List (MSC Preferred) for Handover Request message\n"); + return; + } + ran_enc_msg.handover_request.codec_list_msc_preferred = &scl; } gsm0808_cell_id_from_cgi(&ran_enc_msg.handover_request.cell_id_serving, CELL_IDENT_WHOLE_GLOBAL, &vsub->cgi); @@ -574,7 +606,7 @@ static int msc_ho_start_inter_msc_call_forwarding(struct msc_a *msc_a, struct ms /* Backup old cell's RTP IP:port and codec data */ msc_a->ho.old_cell.ran_remote_rtp = rtp_to_ran->remote; - msc_a->ho.old_cell.codec = rtp_to_ran->codec; + msc_a->ho.old_cell.codecs = rtp_to_ran->codecs; /* Blindly taken over from an MNCC trace of existing code: send an all-zero CCCAP: */ outgoing_call_req.fields |= MNCC_F_CCCAP; @@ -684,7 +716,7 @@ static void msc_ho_rx_request_ack(struct msc_a *msc_a, struct msc_a_ran_dec_data msc_a->ho.new_cell.codec = hra->ran_dec->handover_request_ack.codec; if (hra->ran_dec->handover_request_ack.codec_present) { LOG_HO(msc_a, LOGL_DEBUG, "Request Ack contains codec %s\n", - osmo_mgcpc_codec_name(msc_a->ho.new_cell.codec)); + gsm0808_speech_codec_type_name(msc_a->ho.new_cell.codec.type)); } } @@ -711,7 +743,7 @@ static void msc_ho_rtp_switch_to_new_cell(struct msc_a *msc_a) /* Backup old cell's RTP IP:port and codec data */ msc_a->ho.old_cell.ran_remote_rtp = rtp_to_ran->remote; - msc_a->ho.old_cell.codec = rtp_to_ran->codec; + msc_a->ho.old_cell.codecs = rtp_to_ran->codecs; LOG_HO(msc_a, LOGL_DEBUG, "Switching RTP stream to new cell: from " OSMO_SOCKADDR_STR_FMT " to " OSMO_SOCKADDR_STR_FMT "\n", OSMO_SOCKADDR_STR_FMT_ARGS(&msc_a->ho.old_cell.ran_remote_rtp), @@ -730,10 +762,18 @@ static void msc_ho_rtp_switch_to_new_cell(struct msc_a *msc_a) /* Switch over to the new peer */ rtp_stream_set_remote_addr(rtp_to_ran, &msc_a->ho.new_cell.ran_remote_rtp); - if (msc_a->ho.new_cell.codec_present) - rtp_stream_set_codec(rtp_to_ran, msc_a->ho.new_cell.codec); - else + if (msc_a->ho.new_cell.codec_present) { + const struct codec_mapping *m; + m = codec_mapping_by_gsm0808_speech_codec_type(msc_a->ho.new_cell.codec.type); + /* TODO: use codec_mapping_by_gsm0808_speech_codec() to also match on codec.cfg */ + if (!m) + LOG_HO(msc_a, LOGL_ERROR, "Cannot resolve codec: %s\n", + gsm0808_speech_codec_type_name(msc_a->ho.new_cell.codec.type)); + else + rtp_stream_set_one_codec(rtp_to_ran, &m->sdp); + } else { LOG_HO(msc_a, LOGL_ERROR, "No codec is set\n"); + } rtp_stream_commit(rtp_to_ran); } @@ -772,7 +812,7 @@ static void msc_ho_rtp_rollback_to_old_cell(struct msc_a *msc_a) /* Switch back to the old cell */ rtp_stream_set_remote_addr(rtp_to_ran, &msc_a->ho.old_cell.ran_remote_rtp); - rtp_stream_set_codec(rtp_to_ran, msc_a->ho.old_cell.codec); + rtp_stream_set_codecs(rtp_to_ran, &msc_a->ho.old_cell.codecs); rtp_stream_commit(rtp_to_ran); } diff --git a/src/libmsc/msc_i.c b/src/libmsc/msc_i.c index f7aab0db1..d3616f3ae 100644 --- a/src/libmsc/msc_i.c +++ b/src/libmsc/msc_i.c @@ -1,6 +1,6 @@ /* Code to manage a subscriber's MSC-I role */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/msc_i_remote.c b/src/libmsc/msc_i_remote.c index 7b9598423..c5d22a2e3 100644 --- a/src/libmsc/msc_i_remote.c +++ b/src/libmsc/msc_i_remote.c @@ -1,6 +1,6 @@ /* The MSC-I role implementation variant that forwards requests to/from a remote MSC. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/msc_net_init.c b/src/libmsc/msc_net_init.c index af23fe50d..1fc712aff 100644 --- a/src/libmsc/msc_net_init.c +++ b/src/libmsc/msc_net_init.c @@ -62,8 +62,6 @@ struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv) if (!net) return NULL; - net->sms_db_file_path = talloc_strdup(net, SMS_DEFAULT_DB_FILE_PATH); - net->plmn = (struct osmo_plmn_id){ .mcc=1, .mnc=1 }; /* Permit a compile-time default of A5/3 and A5/1 */ @@ -77,6 +75,7 @@ struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv) INIT_LLIST_HEAD(&net->trans_list); INIT_LLIST_HEAD(&net->upqueue); INIT_LLIST_HEAD(&net->neighbor_ident_list); + INIT_LLIST_HEAD(&net->asci.gcr_lists); /* init statistics */ net->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, 0); @@ -131,9 +130,15 @@ int msc_gsup_client_start(struct gsm_network *net) net->gcm = gsup_client_mux_alloc(net); OSMO_ASSERT(net->gcm); + /* If no IPA name is configured, we need to provide a default + * right here, in order for the defaulted name to get inserted + * as source_name in GSUP response messages. */ + if (!net->msc_ipa_name) + net->msc_ipa_name = "unnamed-MSC"; + ipa_dev = talloc_zero(net->gcm, struct ipaccess_unit); ipa_dev->unit_name = "MSC"; - ipa_dev->serno = net->msc_ipa_name; /* NULL unless configured via VTY */ + ipa_dev->serno = net->msc_ipa_name; ipa_dev->swversion = PACKAGE_NAME "-" PACKAGE_VERSION; *net->gcm = (struct gsup_client_mux){ diff --git a/src/libmsc/msc_t.c b/src/libmsc/msc_t.c index af0ddaaef..eb6c79784 100644 --- a/src/libmsc/msc_t.c +++ b/src/libmsc/msc_t.c @@ -1,6 +1,6 @@ /* The MSC-T role, a transitional RAN connection during Handover. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -38,6 +38,7 @@ #include <osmocom/msc/vlr.h> #include <osmocom/msc/msc_i.h> #include <osmocom/msc/gsm_data.h> +#include <osmocom/msc/codec_mapping.h> static struct osmo_fsm msc_t_fsm; @@ -145,7 +146,6 @@ static void msc_t_send_handover_failure(struct msc_t *msc_t, enum gsm0808_cause return; msub_role_dispatch(msc_t->c.msub, MSC_ROLE_A, MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE, &an_apdu); - msgb_free(an_apdu.msg); } static int msc_t_ho_request_decode_and_store_cb(struct osmo_fsm_inst *msc_t_fi, void *data, @@ -160,7 +160,7 @@ static int msc_t_ho_request_decode_and_store_cb(struct osmo_fsm_inst *msc_t_fi, } msc_t->inter_msc.cell_id_target = ran_dec->handover_request.cell_id_target; - msc_t->inter_msc.callref = ran_dec->handover_request.call_id; + msc_t->inter_msc.call_id = ran_dec->handover_request.call_id; /* TODO other parameters...? * Global Call Reference @@ -238,7 +238,6 @@ static int msc_t_find_ran_peer_from_ho_request(struct msc_t *msc_t) static int msc_t_send_stored_ho_request__decode_cb(struct osmo_fsm_inst *msc_t_fi, void *data, const struct ran_msg *ran_dec) { - int rc; struct an_apdu an_apdu; struct msc_t *msc_t = msc_t_priv(msc_t_fi); struct osmo_sockaddr_str *rtp_ran_local = data; @@ -263,9 +262,7 @@ static int msc_t_send_stored_ho_request__decode_cb(struct osmo_fsm_inst *msc_t_f }; if (!an_apdu.msg) return -EIO; - rc = msc_t_down_l2_co(msc_t, &an_apdu, true); - msgb_free(an_apdu.msg); - return rc; + return msc_t_down_l2_co(msc_t, &an_apdu, true); } /* The MGW endpoint is created, we know our AoIP Transport Layer Address and can send the Handover Request to the RAN @@ -361,8 +358,8 @@ void msc_t_fsm_wait_local_rtp_onenter(struct osmo_fsm_inst *fi, uint32_t prev_st MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, MSC_EV_CALL_LEG_RTP_COMPLETE); if (!msc_t->inter_msc.call_leg - || call_leg_ensure_ci(msc_t->inter_msc.call_leg, RTP_TO_RAN, msc_t->inter_msc.callref, NULL, NULL, NULL) - || call_leg_ensure_ci(msc_t->inter_msc.call_leg, RTP_TO_CN, msc_t->inter_msc.callref, NULL, NULL, NULL)) { + || call_leg_ensure_ci(msc_t->inter_msc.call_leg, RTP_TO_RAN, msc_t->inter_msc.call_id, NULL, NULL, NULL) + || call_leg_ensure_ci(msc_t->inter_msc.call_leg, RTP_TO_CN, msc_t->inter_msc.call_id, NULL, NULL, NULL)) { msc_t_error("Failed to set up call leg\n"); return; } @@ -452,11 +449,20 @@ static int msc_t_patch_and_send_ho_request_ack(struct msc_t *msc_t, const struct LOG_MSC_T(msc_t, LOGL_DEBUG, "No RTP IP:port in Handover Request Ack\n"); } if (r->codec_present) { - LOG_MSC_T(msc_t, LOGL_DEBUG, "From Handover Request Ack, got %s\n", - osmo_mgcpc_codec_name(r->codec)); - rtp_stream_set_codec(rtp_ran, r->codec); - if (rtp_cn) - rtp_stream_set_codec(rtp_cn, r->codec); + const struct codec_mapping *m = codec_mapping_by_gsm0808_speech_codec_type(r->codec.type); + /* TODO: use codec_mapping_by_gsm0808_speech_codec() to also match on codec.cfg */ + if (!m) { + LOG_MSC_T(msc_t, LOGL_ERROR, "Cannot resolve codec in Handover Request Ack: %s / %s\n", + gsm0808_speech_codec_type_name(r->codec.type), + m ? sdp_audio_codec_to_str(&m->sdp) : "(unknown)"); + } else { + LOG_MSC_T(msc_t, LOGL_DEBUG, "From Handover Request Ack, got codec %s / %s\n", + gsm0808_speech_codec_type_name(r->codec.type), + sdp_audio_codec_to_str(&m->sdp)); + rtp_stream_set_one_codec(rtp_ran, &m->sdp); + if (rtp_cn) + rtp_stream_set_one_codec(rtp_cn, &m->sdp); + } } else { LOG_MSC_T(msc_t, LOGL_DEBUG, "No codec in Handover Request Ack\n"); } @@ -472,9 +478,7 @@ static int msc_t_patch_and_send_ho_request_ack(struct msc_t *msc_t, const struct if (!an_apdu.msg) return -EIO; /* Send to remote MSC via msc_a_remote role */ - rc = msub_role_dispatch(msc_t->c.msub, MSC_ROLE_A, MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE, &an_apdu); - msgb_free(an_apdu.msg); - return rc; + return msub_role_dispatch(msc_t->c.msub, MSC_ROLE_A, MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE, &an_apdu); } static int msc_t_wait_ho_request_ack_decode_cb(struct osmo_fsm_inst *msc_t_fi, void *data, diff --git a/src/libmsc/msc_t_remote.c b/src/libmsc/msc_t_remote.c index 22c4e22fd..aea763337 100644 --- a/src/libmsc/msc_t_remote.c +++ b/src/libmsc/msc_t_remote.c @@ -1,6 +1,6 @@ /* The MSC-T role implementation variant that forwards requests to/from a remote MSC. */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/msc_vgcs.c b/src/libmsc/msc_vgcs.c new file mode 100644 index 000000000..264fa4953 --- /dev/null +++ b/src/libmsc/msc_vgcs.c @@ -0,0 +1,2765 @@ +/* Handle VGCS/VBCS calls. (Voice Group/Broadcast Call Service). */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: 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/>. + */ + +/* The process consists of four state machines: + * + * The call control state machine "GCC" handles the voice group/broadcast call. + * There is one instance for every call. It is mainly controlled by the calling + * subscriber. The state machine is described in 3GPP TS 44.068 / 44.069. + * One SCCP connection to the calling subscriber is associated with the state + * machine. Once the calling subscriber leaves or is assigned to the VGCS/VBS + * channel, the association to the MSC-A role is removed and the SCCP connection + * is closed. The state machine with the transaction still exists until the end + * of the call. + * + * The BSS control state machine "vgcs_bss_fsm" handles the call in each BSC. + * There are as many instances as there are BSCs where the call is placed to. + * The instances are linked to the call control in a 1:n relation. + * One SCCP connection for every BSC is associated with the state machine. + * It sets up the call in the BSC and handles the uplink control and signaling + * with the talking phone. + * + * The resource controling state machine "vgcs_cell_fsm" handles the channel for + * each BTS that has a VGCS for the call. The instances are linked to the BSS + * control in a 1:n relation. + * One SCCP connection for every cell is associated with each list entry. + * It assigns the VGCS/VBS channel and the conference bridge in the MGW. + * + * The MGW endpoint state machine "vgcs_mgw_ep_fsm" handles the endpoint + * connection for each call. It controls the clearing of the MGW connections + * in case of endpoint failure. All instances of the resource controlling state + * machine are linked to this state machine in a 1:n relation. + * + * Setup of a call: + * + * When the calling subscriber dials a group/broadcast call, the GCR is checked + * for an existing Group ID. If it exists, the call is setup towards the a given + * list of MSCs for this Group ID. Also the channels are assigned for a given + * list of cells for this Group ID. + * The call can also be initiated via VTY. + * + * Then the calling subscriber is assigned to the VGCS channel of the same cell + * where the call was initialized. Afterwards the call is connected. The calling + * subscriber may then stay on the uplink or release it. + * + * Uplink control: + * + * Any BSC may indicate a talking subscriber. If there is no talking subscriber + * yet, the uplink is granted, otherwise it is rejected. If the uplink is in + * use on one BSC, all other BSCs will be blocked. If the uplink becomes free, + * all other BSCs will be unblocked. + * + * Termination of the call: + * + * The calling subscriber accesses the uplink. The it sends a termination + * request. This request is acknowledged by a termination command towards + * the calling subscriber. The call is cleared. + * The call can also be terminated via VTY and/or a timeout. + * + */ + +#include <osmocom/core/utils.h> +#include <osmocom/core/fsm.h> +#include <osmocom/gsm/protocol/gsm_44_068.h> +#include <osmocom/sigtran/sccp_helpers.h> +#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h> + +#include <osmocom/msc/gsm_data.h> +#include <osmocom/msc/sccp_ran.h> +#include <osmocom/msc/ran_infra.h> +#include <osmocom/msc/ran_peer.h> +#include <osmocom/msc/ran_msg_a.h> +#include <osmocom/msc/msub.h> +#include <osmocom/msc/debug.h> +#include <osmocom/msc/msc_a.h> +#include <osmocom/msc/vlr.h> +#include <osmocom/msc/rtp_stream.h> +#include <osmocom/msc/codec_mapping.h> +#include <osmocom/msc/msc_vgcs.h> +#include <osmocom/msc/asci_gcr.h> + +#define S(x) (1 << (x)) + +#define LOG_GCC(trans, level, fmt, args...) \ + LOGP((trans) ? ((trans->type == TRANS_GCC) ? DGCC : DBCC) : DASCI, level, \ + (trans) ? ((trans->type == TRANS_GCC) ? ("GCC callref %s: " fmt) : ("BCC callref %s: " fmt)) : "%s" fmt, \ + (trans) ? gsm44068_group_id_string(trans->callref) : "", ##args) +#define LOG_BSS(bss, level, fmt, args...) \ + LOGP(DASCI, level, \ + (bss->trans_type == TRANS_GCC) ? ("GCC callref %s, BSS #%s: " fmt) : ("BCC callref %s, BSS #%s: " fmt), \ + gsm44068_group_id_string(bss->callref), osmo_ss7_pointcode_print(NULL, bss->pc), ##args) +#define LOG_CELL(cell, level, fmt, args...) \ + LOGP(DASCI, level, \ + (cell->trans_type == TRANS_GCC) ? ("GCC callref %s, BSS #%s, CID %d: " fmt) \ + : ("BCC callref %s, BSS #%s, CID %d: " fmt), \ + gsm44068_group_id_string(cell->callref), osmo_ss7_pointcode_print(NULL, cell->pc), cell->cell_id, ##args) + +static struct osmo_fsm vgcs_bcc_fsm; +static struct osmo_fsm vgcs_gcc_fsm; +static struct osmo_fsm vgcs_bss_fsm; +static struct osmo_fsm vgcs_cell_fsm; +static struct osmo_fsm vgcs_mgw_ep_fsm; + +static __attribute__((constructor)) void vgcs_fsm_init(void) +{ + OSMO_ASSERT(osmo_fsm_register(&vgcs_bcc_fsm) == 0); + OSMO_ASSERT(osmo_fsm_register(&vgcs_gcc_fsm) == 0); + OSMO_ASSERT(osmo_fsm_register(&vgcs_bss_fsm) == 0); + OSMO_ASSERT(osmo_fsm_register(&vgcs_cell_fsm) == 0); + OSMO_ASSERT(osmo_fsm_register(&vgcs_mgw_ep_fsm) == 0); +} + +const char *gsm44068_group_id_string(uint32_t callref) +{ + static char string[9]; + + snprintf(string, sizeof(string), "%08u", callref); + string[sizeof(string) - 1] = '\0'; + + return string; +} + +/* Resolve ran peer from point-code */ +static struct ran_peer *ran_peer_for_pc(struct gsm_network *msc_network, int pc) +{ + struct sccp_ran_inst *sri; + struct osmo_sccp_addr addr = {}; + struct ran_peer *rp; + + sri = msc_network->a.sri; + if (!osmo_sccp_get_ss7(sri->sccp)) { + LOGP(DASCI, LOGL_ERROR, "No SS7???\n"); + return NULL; + } + osmo_sccp_make_addr_pc_ssn(&addr, pc, sri->ran->ssn); + rp = ran_peer_find_by_addr(sri, &addr); + + return rp; +} + +/* Encode message and send towards BSC. */ +int ran_encode_and_send(struct osmo_fsm_inst *fi, struct ran_msg *ran_msg, struct ran_conn *conn, bool initial) +{ + struct msgb *l3_msg; + int rc; + + l3_msg = ran_a_encode(fi, ran_msg); + if (!l3_msg) { + LOGP(DASCI, LOGL_ERROR, "ran_a_encode() failed.\n"); + return -EINVAL; + } + rc = ran_conn_down_l2_co(conn, l3_msg, initial); + msgb_free(l3_msg); + + return rc; +} + +/* Transmit DTAP message to talker + * This is used for sending group/broadcast call control messages. */ +int tx_dtap_to_talker(struct vgcs_bss *bss, struct msgb *l3_msg) +{ + struct ran_msg ran_msg; + struct gsm48_hdr *gh = msgb_l3(l3_msg) ? : l3_msg->data; + uint8_t pdisc = gsm48_hdr_pdisc(gh); + int rc; + + + LOG_BSS(bss, LOGL_DEBUG, "Sending DTAP: %s %s\n", + gsm48_pdisc_name(pdisc), gsm48_pdisc_msgtype_name(pdisc, gsm48_hdr_msg_type(gh))); + + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_DTAP, + .dtap = l3_msg, + }; + + rc = ran_encode_and_send(bss->fi, &ran_msg, bss->conn, false); + + return rc; +} + +/* + * GCC/BCC Message transcoding + */ + +static void _add_cause_ie(struct msgb *msg, uint8_t cause, uint8_t *diag, uint8_t diag_len) +{ + uint8_t *ie = msgb_put(msg, 2 + diag_len); + + ie[0] = 1 + diag_len; + ie[1] = cause; + if (diag && diag_len) { + ie[1] |= 0x80; + memcpy(ie + 2, diag, diag_len); + } +} + +static void _add_callref_ie(struct msgb *msg, uint32_t callref, bool with_prio, uint8_t prio) +{ + uint32_t ie; + + ie = callref << 5; + if (with_prio) + ie |= 0x10 | (prio << 1); + msgb_put_u32(msg, ie); +} + +static int _msg_too_short(void) +{ + LOGP(DASCI, LOGL_ERROR, "MSG too short.\n"); + return -EINVAL; +} + +static int _ie_invalid(void) +{ + LOGP(DASCI, LOGL_ERROR, "IE invalid.\n"); + return -EINVAL; +} + +static int _rx_callref(uint8_t *ie, unsigned int remaining_len, uint32_t *callref, bool *with_prio, uint8_t *prio) +{ + uint8_t ie_len; + + ie_len = sizeof(uint32_t); + if (remaining_len < ie_len) + return _msg_too_short(); + *callref = osmo_load32be(ie) >> 5; + if (ie[3] & 0x10) { + *with_prio = true; + *prio = (ie[3] >> 1) & 0x7; + } else + *with_prio = false; + + return ie_len; +} + +/* 3GPP TS 44.068 Clause 8.1 */ +static int gsm44068_tx_connect(struct gsm_trans *trans, uint8_t pdisc, uint32_t callref, bool with_prio, uint8_t prio, + uint8_t oi, uint8_t talker_prio, bool with_sms, uint8_t sms_dc, uint8_t sms_gp) +{ + struct msgb *msg = gsm44068_msgb_alloc_name("GSM 44.068 TX CONNECT"); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + uint8_t ie; + + gh->proto_discr = pdisc; + gh->msg_type = OSMO_GSM44068_MSGT_CONNECT; + _add_callref_ie(msg, callref, with_prio, prio); + ie = (talker_prio << 4) | oi; + msgb_put_u8(msg, ie); + if (with_sms) { + ie = OSMO_GSM44068_IEI_SMS_INDICATIONS | (sms_dc << 1) | sms_gp; + msgb_put_u8(msg, ie); + } + + /* Send to calling subscriber, depending on the link he is. */ + if (trans->msc_a) + return msc_a_tx_dtap_to_i(trans->msc_a, msg); + if (trans->gcc.uplink_bss) + return tx_dtap_to_talker(trans->gcc.uplink_bss, msg); + msgb_free(msg); + return -EIO; +} + +/* The Get Status procedure is not used by the current implementation. + * It is commented out, so it can be used in the future. + * The idea is to have a complete set of GCC/BCC message transcoding. + */ +#if 0 +/* 3GPP TS 44.068 Clause 8.2 */ +static int gsm44068_tx_get_status(struct gsm_trans *trans, uint8_t pdisc, struct osmo_mobile_identity *mi) +{ + struct msgb *msg = gsm44068_msgb_alloc_name("GSM 44.068 TX GET STATUS"); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + + gh->proto_discr = pdisc; + gh->msg_type = OSMO_GSM44068_MSGT_GET_STATUS; + if (mi) { + uint8_t *l; + int rc; + + l = msgb_tl_put(msg, OSMO_GSM44068_IEI_MOBILE_IDENTITY); + rc = osmo_mobile_identity_encode_msgb(msg, mi, false); + if (rc < 0) { + msgb_free(msg); + return -EINVAL; + } + *l = rc; + } + + /* Send to calling subscriber, depending on the link he is. */ + if (trans->msc_a) + return msc_a_tx_dtap_to_i(trans->msc_a, msg); + if (trans->gcc.uplink_bss) + return tx_dtap_to_talker(trans->gcc.uplink_bss, msg); + msgb_free(msg); + return -EIO; +} +#endif + +/* 3GPP TS 44.068 Clause 8.3 and 8.3a */ +static int gsm44068_rx_immediate_setup(struct msgb *msg, uint8_t *talker_prio, uint8_t *key_seq, + struct gsm48_classmark2 *cm2, struct osmo_mobile_identity *mi, + uint32_t *callref, bool *with_prio, uint8_t *prio, char *user_user) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + unsigned int remaining_len = msgb_l3len(msg) - sizeof(*gh); + uint8_t *ie = gh->data; + uint8_t ie_len; + uint64_t otdi; + int i; + int rc; + + /* Talker priority / Cyphering key sequence */ + if (remaining_len < 1) + return _msg_too_short(); + *talker_prio = ie[0] & 0x07; + *key_seq = (ie[0] >> 4) & 0x07; + remaining_len -= 1; + ie += 1; + + /* Mobile station classmark 2 */ + if (remaining_len < 4) + return _msg_too_short(); + ie_len = ie[0]; + if (remaining_len < ie_len + 1) + return _msg_too_short(); + if (ie_len != 3) + return _ie_invalid(); + memcpy(cm2, ie + 1, ie_len); + remaining_len -= ie_len + 1; + ie += ie_len + 1; + + /* Mobile indentity */ + if (gh->msg_type == OSMO_GSM44068_MSGT_IMMEDIATE_SETUP) { + /* IMMEDIATE SETUP uses IMSI/TMSI */ + if (remaining_len < 2) + return _msg_too_short(); + ie_len = ie[0]; + if (remaining_len < ie_len + 1) + return _msg_too_short(); + rc = osmo_mobile_identity_decode(mi, ie + 1, ie_len, false); + if (rc) { + LOGP(DMM, LOGL_ERROR, "Failure to decode Mobile Identity in GCC/BCC IMMEDDIATE SETUP" + " (rc=%d)\n", rc); + return -EINVAL; + } + remaining_len -= ie_len + 1; + ie += ie_len + 1; + } else { + /* IMMEDIATE SETUP 2 uses TMSI only */ + if (remaining_len < 4) + return _msg_too_short(); + mi->type = GSM_MI_TYPE_TMSI; + mi->tmsi = osmo_load32be(ie); + remaining_len -= 4; + ie += 4; + } + + /* Call reference */ + rc = _rx_callref(ie, remaining_len, callref, with_prio, prio); + if (rc < 0) + return rc; + remaining_len -= rc; + ie += rc; + + /* OTID */ + if (gh->msg_type == OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2 && user_user) { + ie_len = 5; + if (remaining_len < ie_len) + return _msg_too_short(); + otdi = osmo_load32be(ie + 1) | ((uint64_t)ie[0] << 32); + + for (i = 0; i < 12; i++) { + user_user[i] = (otdi % 10) + '0'; + otdi /= 10; + } + user_user[i] = '\0'; + remaining_len -= ie_len; + ie += ie_len; + } else if (user_user) + user_user[0] = '\0'; + + return 0; +} + +/* 3GPP TS 44.068 Clause 8.4 */ +static int gsm44068_tx_set_parameter(struct gsm_trans *trans, uint8_t pdisc, uint8_t da, uint8_t ua, uint8_t comm, + uint8_t oi) +{ + struct msgb *msg = gsm44068_msgb_alloc_name("GSM 44.068 TX SET PARAMETER"); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + uint8_t ie; + + gh->proto_discr = pdisc; + gh->msg_type = OSMO_GSM44068_MSGT_SET_PARAMETER; + ie = (da << 3) | (ua << 2) | (comm << 1) | oi; + msgb_put_u8(msg, ie); + + /* Send to calling subscriber, depending on the link he is. */ + if (trans->msc_a) + return msc_a_tx_dtap_to_i(trans->msc_a, msg); + if (trans->gcc.uplink_bss) + return tx_dtap_to_talker(trans->gcc.uplink_bss, msg); + msgb_free(msg); + return -EIO; +} + +/* 3GPP TS 44.068 Clause 8.5 */ +static int gsm44068_rx_setup(struct msgb *msg, bool *with_talker_prio, uint8_t *talker_prio, + uint32_t *callref, bool *with_prio, uint8_t *prio, char *user_user) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + unsigned int remaining_len = msgb_l3len(msg) - sizeof(*gh); + uint8_t *ie = gh->data; + struct tlv_parsed tp; + struct tlv_p_entry *tlv; + int rc; + + /* Call reference */ + rc = _rx_callref(ie, remaining_len, callref, with_prio, prio); + if (rc < 0) + return rc; + remaining_len -= rc; + ie += rc; + + rc = tlv_parse(&tp, &osmo_gsm44068_att_tlvdef, ie, remaining_len, 0, 0); + if (rc < 0) + return _ie_invalid(); + + /* User-user */ + tlv = TLVP_GET(&tp, OSMO_GSM44068_IEI_USER_USER); + if (tlv && tlv->len && tlv->len <= 1 + 12 && user_user) { + memcpy(user_user, tlv->val, tlv->len - 1); + user_user[tlv->len - 1] = '\0'; + } + + /* Talker priority */ + tlv = TLVP_GET(&tp, OSMO_GSM44068_IEI_TALKER_PRIORITY); + if (tlv && tlv->len) { + *with_talker_prio = true; + *talker_prio = tlv->val[0] & 0x07; + } else + *with_talker_prio = false; + + return 0; +} + +/* 3GPP TS 44.068 Clause 8.6 */ +static int gsm44068_rx_status(struct msgb *msg, uint8_t *cause, uint8_t *diag, uint8_t *diag_len, + bool *with_call_state, enum osmo_gsm44068_call_state *call_state, + bool *with_state_attrs, uint8_t *da, uint8_t *ua, uint8_t *comm, uint8_t *oi) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + unsigned int remaining_len = msgb_l3len(msg) - sizeof(*gh); + uint8_t *ie = gh->data; + uint8_t ie_len; + struct tlv_parsed tp; + struct tlv_p_entry *tlv; + int rc; + + /* Cause */ + if (remaining_len < 2 || ie[0] < remaining_len - 2) + return _msg_too_short(); + ie_len = ie[0]; + if (remaining_len < ie_len + 1) + return _msg_too_short(); + if (ie_len < 1) + return _ie_invalid(); + *cause = ie[1] & 0x7f; + *diag_len = ie_len - 1; + if (*diag_len) + memcpy(diag, ie + 2, ie_len - 1); + remaining_len -= ie_len + 1; + ie += ie_len + 1; + + rc = tlv_parse(&tp, &osmo_gsm44068_att_tlvdef, ie, remaining_len, 0, 0); + if (rc < 0) + return _ie_invalid(); + + /* Call state */ + tlv = TLVP_GET(&tp, OSMO_GSM44068_IEI_CALL_STATE); + if (tlv) { + *with_call_state = true; + *call_state = tlv->val[0] & 0x7; + } else + *with_call_state = false; + + /* State attributes */ + tlv = TLVP_GET(&tp, OSMO_GSM44068_IEI_STATE_ATTRIBUTES); + if (tlv) { + *with_state_attrs = true; + *da = (tlv->val[0] >> 3) & 0x1; + *ua = (tlv->val[0] >> 2) & 0x1; + *comm = (tlv->val[0] >> 1) & 0x1; + *oi = tlv->val[0] & 0x1; + } else + *with_state_attrs = false; + + return 0; +} + +/* 3GPP TS 44.068 Clause 8.7 and 8.8 */ +static int gsm44068_tx_termination(struct msc_a *msc_a, struct vgcs_bss *bss, uint8_t pdisc, uint8_t msg_type, + uint8_t cause, uint8_t *diag, uint8_t diag_len) +{ + struct msgb *msg = gsm44068_msgb_alloc_name("GSM 44.068 TX TERMINATION"); + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + + gh->proto_discr = pdisc; + gh->msg_type = msg_type; + _add_cause_ie(msg, cause, diag, diag_len); + + /* Send to calling subscriber, depending on the link he is. */ + if (msc_a) + return msc_a_tx_dtap_to_i(msc_a, msg); + if (bss) + return tx_dtap_to_talker(bss, msg); + msgb_free(msg); + return -EIO; +} + +/* 3GPP TS 44.068 Clause 8.9 */ +static int gsm44068_rx_termination_req(struct msgb *msg, uint32_t *callref, bool *with_prio, uint8_t *prio, + bool *with_talker_prio, uint8_t *talker_prio) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + unsigned int remaining_len = msgb_l3len(msg) - sizeof(*gh); + uint8_t *ie = gh->data; + struct tlv_parsed tp; + struct tlv_p_entry *tlv; + int rc; + + /* Call reference */ + rc = _rx_callref(ie, remaining_len, callref, with_prio, prio); + if (rc < 0) + return rc; + remaining_len -= rc; + ie += rc; + + rc = tlv_parse(&tp, &osmo_gsm44068_att_tlvdef, ie, remaining_len, 0, 0); + if (rc < 0) + return _ie_invalid(); + + /* Talker priority */ + tlv = TLVP_GET(&tp, OSMO_GSM44068_IEI_TALKER_PRIORITY); + if (tlv && tlv->len) { + *with_talker_prio = true; + *talker_prio = tlv->val[0] & 0x07; + } else + *with_talker_prio = false; + + return 0; +} + +/* + * GCC/BCC state machine - handles calling subscriber process + */ + +static const struct value_string vgcs_gcc_fsm_event_names[] = { + OSMO_VALUE_STRING(VGCS_GCC_EV_NET_SETUP), + OSMO_VALUE_STRING(VGCS_GCC_EV_NET_TERM), + OSMO_VALUE_STRING(VGCS_GCC_EV_USER_SETUP), + OSMO_VALUE_STRING(VGCS_GCC_EV_USER_TERM), + OSMO_VALUE_STRING(VGCS_GCC_EV_BSS_ESTABLISHED), + OSMO_VALUE_STRING(VGCS_GCC_EV_BSS_ASSIGN_CPL), + OSMO_VALUE_STRING(VGCS_GCC_EV_BSS_ASSIGN_FAIL), + OSMO_VALUE_STRING(VGCS_GCC_EV_BSS_RELEASED), + OSMO_VALUE_STRING(VGCS_GCC_EV_TIMEOUT), + { } +}; + +static int gcc_establish_bss(struct gsm_trans *trans) +{ + struct gsm_network *net = trans->net; + struct vgcs_mgw_ep *mgw = NULL; + struct mgcp_client *mgcp_client; + struct gcr *gcr; + struct gcr_bss *b; + struct gcr_cell *c; + struct vgcs_bss *bss; + struct vgcs_bss_cell *cell; + struct osmo_fsm_inst *fi; + struct ran_peer *rp; + + /* Failure should not happen, because it has been checked before. */ + gcr = gcr_by_callref(trans->net, trans->type, trans->callref); + if (!gcr) + return -EINVAL; + + /* Allocate MGW endpoint. */ + mgcp_client = mgcp_client_pool_get(trans->net->mgw.mgw_pool); + if (!mgcp_client) { + LOG_GCC(trans, LOGL_ERROR, "No MGW client, please check config.\n"); + goto err_mgw; + } + fi = osmo_fsm_inst_alloc(&vgcs_mgw_ep_fsm, net, NULL, LOGL_DEBUG, NULL); + if (!fi) { + LOG_GCC(trans, LOGL_ERROR, "No memory for VGCS MSG state machine.\n"); + goto err_mgw; + } + osmo_fsm_inst_update_id(fi, "vgcs-mgw-ep"); + osmo_fsm_inst_state_chg(fi, VGCS_MGW_EP_ST_ACTIVE, 0, 0); + mgw = talloc_zero(fi, struct vgcs_mgw_ep); + if (!mgw) { + LOG_GCC(trans, LOGL_ERROR, "No memory for MGW ep structure.\n"); + osmo_fsm_inst_free(fi); + goto err_mgw; + } + mgw->fi = fi; + fi->priv = mgw; + INIT_LLIST_HEAD(&mgw->cell_list); + mgw->mgw_ep = osmo_mgcpc_ep_alloc(mgw->fi, VGCS_MGW_EP_EV_FREE, + mgcp_client, trans->net->mgw.tdefs, mgw->fi->id, + "%s", mgcp_client_rtpbridge_wildcard(mgcp_client)); + if (!mgw->mgw_ep) { + LOG_GCC(trans, LOGL_ERROR, "No memory for MGW endpoint state machine.\n"); + goto err_mgw; + } + + /* Create BSS list structures. */ + LOG_GCC(trans, LOGL_DEBUG, "Creating BSS list structure with cell list structures.\n"); + llist_for_each_entry(b, &gcr->bss_list, list) { + LOG_GCC(trans, LOGL_DEBUG, " -> BSS with PC %s.\n", osmo_ss7_pointcode_print(NULL, b->pc)); + /* Resolve ran_peer. */ + rp = ran_peer_for_pc(trans->net, b->pc); + if (!rp) { + LOG_GCC(trans, LOGL_ERROR, "Failed to resolve point code %s, skipping BSS!\n", + osmo_ss7_pointcode_print(NULL, b->pc)); + continue; + } + /* Create state machine. */ + fi = osmo_fsm_inst_alloc(&vgcs_bss_fsm, net, NULL, LOGL_DEBUG, NULL); + if (!fi) { + LOG_GCC(trans, LOGL_ERROR, "No memory for state machine.\n"); + break; + } + /* Create call structure. */ + bss = talloc_zero(fi, struct vgcs_bss); + if (!bss) { + LOG_GCC(trans, LOGL_ERROR, "No memory for BSS call structure.\n"); + osmo_fsm_inst_free(fi); + break; + } + bss->fi = fi; + fi->priv = bss; + INIT_LLIST_HEAD(&bss->cell_list); + bss->trans = trans; + bss->trans_type = trans->type; + bss->callref = trans->callref; + bss->pc = b->pc; + /* Create ran connection. */ + bss->conn = ran_conn_create_outgoing(rp); + if (!bss->conn) { + LOG_GCC(trans, LOGL_ERROR, "Failed to create RAN connection.\n"); + osmo_fsm_inst_free(bss->fi); + continue; + } + bss->conn->vgcs.bss = bss; + /* Create cell list structures. */ + llist_for_each_entry(c, &b->cell_list, list) { + LOG_GCC(trans, LOGL_DEBUG, " -> Cell ID %d.\n", c->cell_id); + /* Create state machine. */ + fi = osmo_fsm_inst_alloc(&vgcs_cell_fsm, net, NULL, LOGL_DEBUG, NULL); + if (!fi) { + LOG_GCC(trans, LOGL_ERROR, "No memory for state machine.\n"); + break; + } + /* Create cell structure. */ + cell = talloc_zero(fi, struct vgcs_bss_cell); + if (!cell) { + LOG_GCC(trans, LOGL_ERROR, "No memory for BSS cell structure.\n"); + osmo_fsm_inst_free(fi); + break; + } + cell->fi = fi; + fi->priv = cell; + osmo_fsm_inst_update_id_f(cell->fi, "vgcs-cell-%d", c->cell_id); + cell->trans_type = trans->type; + cell->callref = trans->callref; + cell->pc = b->pc; + cell->cell_id = c->cell_id; + cell->call_id = trans->call_id; + /* Create ran connection. */ + cell->conn = ran_conn_create_outgoing(rp); + if (!cell->conn) { + LOG_GCC(trans, LOGL_ERROR, "Failed to create RAN connection.\n"); + osmo_fsm_inst_free(cell->fi); + continue; + } + cell->conn->vgcs.cell = cell; + /* Attach to cell list of BSS and MGW endpoint */ + llist_add_tail(&cell->list_bss, &bss->cell_list); + cell->bss = bss; + llist_add_tail(&cell->list_mgw, &mgw->cell_list); + cell->mgw = mgw; + } + /* No cell? */ + if (llist_empty(&bss->cell_list)) { + LOG_GCC(trans, LOGL_DEBUG, " -> No Cell in this BSS.\n"); + osmo_fsm_inst_free(bss->fi); + break; + } + /* Attach to transaction list */ + llist_add_tail(&bss->list, &trans->gcc.bss_list); + /* Trigger VGCS/VBS SETUP */ + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_SETUP, NULL); + } + /* No BSS? */ + if (llist_empty(&trans->gcc.bss_list)) { + /* Also destroy MGW, because this list is empty too! */ + LOG_GCC(trans, LOGL_NOTICE, "No BSS found, please check your VTY configuration and add cells.\n"); + goto err_mgw; + } + return 0; + +err_mgw: + if (mgw) { + if (mgw->mgw_ep) { + /* This will also free FSM instance and vgcs_mgw_ep structure. */ + osmo_fsm_inst_dispatch(mgw->fi, VGCS_MGW_EP_EV_CLEAR, NULL); + return -EINVAL; + } + osmo_fsm_inst_free(mgw->fi); + } + return -EINVAL; +} + +/* Send Assignment Request to the calling subscriber. + * This is used to assign the subscriber from early assigned channel to the VGCS/VBS channel. */ +static int gcc_assign(struct gsm_trans *trans) +{ + struct ran_msg tx_ran_msg; + struct gsm0808_channel_type channel_type; + struct vgcs_bss *bss = NULL, *b; + + /* No assignment, because the calling subscriber is already assigned or there is no calling subscriber. */ + if (!trans->msc_a) + return 0; + + /* Check calling subscriber's MSC */ + struct ran_conn *conn = msub_ran_conn(trans->msc_a->c.msub); + if (!conn) { + LOG_GCC(trans, LOGL_ERROR, "Calling subscriber has no ran_conn????\n"); + return -EINVAL; + } + llist_for_each_entry(b, &trans->gcc.bss_list, list) { + if (osmo_sccp_addr_ri_cmp(&conn->ran_peer->peer_addr, &b->conn->ran_peer->peer_addr)) + continue; + bss = b; + break; + } + if (!bss) { + LOG_GCC(trans, LOGL_ERROR, "Calling subscriber comes from BSC that has no VGCS call.\n"); + return -EINVAL; + } + + /* For now we support GSM/FR V1 only. This shall be supported by all MS. */ + channel_type = (struct gsm0808_channel_type) { + .ch_indctr = GSM0808_CHAN_SPEECH, + .ch_rate_type = GSM0808_SPEECH_FULL_BM, + .perm_spch_len = 1, + .perm_spch[0] = GSM0808_PERM_FR1, + }; + + /* Send assignment to VGCS channel */ + tx_ran_msg = (struct ran_msg) { + .msg_type = RAN_MSG_ASSIGNMENT_COMMAND, + .assignment_command = { + .channel_type = &channel_type, + .callref_present = true, + .callref = { + .sf = (trans->type == TRANS_GCC), + }, + }, + }; + osmo_store32be_ext(trans->callref >> 3, &tx_ran_msg.assignment_command.callref.call_ref_hi, 3); + tx_ran_msg.assignment_command.callref.call_ref_lo = trans->callref & 0x7; + if (msc_a_ran_down(trans->msc_a, MSC_ROLE_I, &tx_ran_msg)) { + LOG_GCC(trans, LOGL_ERROR, "Cannot send Assignment\n"); + return -EIO; + } + + /* Assign Talker to BSS of the calling subscriber. */ + trans->gcc.uplink_bss = bss; + + return 0; +} + +/* Send CONNECT to the calling subscriber. */ +static void gcc_connect(struct gsm_trans *trans) +{ + uint8_t pdisc = (trans->type == TRANS_GCC) ? GSM48_PDISC_GROUP_CC : GSM48_PDISC_BCAST_CC; + int rc; + + /* Send CONNECT towards MS. */ + rc = gsm44068_tx_connect(trans, + pdisc | (trans->transaction_id << 4), + trans->callref, 0, 0, 1, 0, 0, 0, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send CONNECT towards MS. Continue anyway.\n"); +} + +/* Release dedicated (SDCCH) channel of calling subscriber after assigning to VGCS */ +static void release_msc_a(struct gsm_trans *trans) +{ + struct msc_a *msc_a = trans->msc_a; + + if (!msc_a) + return; + + trans->msc_a = NULL; + switch (trans->type) { + case TRANS_GCC: + msc_a_put(msc_a, MSC_A_USE_GCC); + break; + case TRANS_BCC: + msc_a_put(msc_a, MSC_A_USE_BCC); + break; + default: + break; + } +} + +/* Send TERMINATE to the calling/talking subscriber, then destroy transaction. */ +static void gcc_terminate_and_destroy(struct gsm_trans *trans, enum osmo_gsm44068_cause cause) +{ + uint8_t pdisc = (trans->type == TRANS_GCC) ? GSM48_PDISC_GROUP_CC : GSM48_PDISC_BCAST_CC; + int rc; + + /* Send TERMINATION towards MS. */ + rc = gsm44068_tx_termination(trans->msc_a, trans->gcc.uplink_bss, + pdisc | (trans->transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION, + cause, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION towards MS. Continue anyway.\n"); + + /* Destroy transaction, note that also _gsm44068_gcc_trans_free() will be called by trans_free(). + * There the complete state machine is destroyed. */ + trans->callref = 0; + trans_free(trans); +} + +/* Send TERMINATION REJECT to the calling/talking subscriber. */ +static void gcc_termination_reject(struct gsm_trans *trans, enum osmo_gsm44068_cause cause) +{ + uint8_t pdisc = (trans->type == TRANS_GCC) ? GSM48_PDISC_GROUP_CC : GSM48_PDISC_BCAST_CC; + int rc; + + /* Send TERMINATION towards MS. */ + rc = gsm44068_tx_termination(trans->msc_a, trans->gcc.uplink_bss, + pdisc | (trans->transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION_REJECT, + cause, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION REJECT towards MS.\n"); +} + +/* Start inactivity timer. + * This timer is used to terminate the call, if the radio connection to the caller gets lost. */ +static void start_inactivity_timer(struct gsm_trans *trans) +{ + if (trans->gcc.inactivity_to) { + LOG_GCC(trans, LOGL_DEBUG, "Set inactivity timer to %d seconds.\n", trans->gcc.inactivity_to); + osmo_timer_schedule(&trans->gcc.timer_inactivity, trans->gcc.inactivity_to, 0); + } +} + +static void stop_inactivity_timer(struct gsm_trans *trans) +{ + if (osmo_timer_pending(&trans->gcc.timer_inactivity)) { + LOG_GCC(trans, LOGL_DEBUG, "Stop pending inactivity timer.\n"); + osmo_timer_del(&trans->gcc.timer_inactivity); + } +} + +static void inactivity_timer_cb(void *data) +{ + struct gsm_trans *trans = data; + + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_TIMEOUT, NULL); +} + +/* Set the parameters of the talker. (downlink mute/unmute, uplink unmute, COMM=T, originator) */ +static int set_parameter(struct gsm_trans *trans) +{ + uint8_t pdisc = (trans->type == TRANS_GCC) ? GSM48_PDISC_GROUP_CC : GSM48_PDISC_BCAST_CC; + int rc; + + rc = gsm44068_tx_set_parameter(trans, pdisc | (trans->transaction_id << 4), + !trans->gcc.mute_talker, 1, 1, trans->gcc.uplink_originator); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send SET PARAMETER towards MS.\n"); + return rc; +} + +/* Check in which cell the uplink is used and set "uplink_cell". */ +static int set_uplink_cell(struct vgcs_bss *bss, struct gsm0808_cell_id *cell_id_ie, uint16_t cell_id) +{ + struct vgcs_bss_cell *cell; + + if (cell_id_ie) { + /* Get cell ID to determine talker channel. */ + switch (cell_id_ie->id_discr) { + case CELL_IDENT_CI: + cell_id = cell_id_ie->id.ci; + break; + case CELL_IDENT_LAC_AND_CI: + cell_id = cell_id_ie->id.lac_and_ci.ci; + break; + default: + LOG_BSS(bss, LOGL_DEBUG, "Cannot idenitfy cell, please fix!\n"); + return -EINVAL; + } + } + + /* Search for cell ID. */ + bss->trans->gcc.uplink_cell = NULL; + llist_for_each_entry(cell, &bss->cell_list, list_bss) { + if (cell->cell_id == cell_id) { + LOG_BSS(bss, LOGL_DEBUG, "Talker is talking on cell %d.\n", cell->cell_id); + bss->trans->gcc.uplink_cell = cell; + return 0; + } + } + + LOG_BSS(bss, LOGL_DEBUG, "Cell ID %d is not in list of current BSS, please fix!\n", cell_id); + return -EINVAL; +} + +/* Set the MGW conference mode. + * All cells are listening to the conference. If there is a talker, this cell is also transmitting to the conference. */ +static int set_mgw_conference(struct gsm_trans *trans) +{ + struct vgcs_bss *bss; + struct vgcs_bss_cell *cell; + struct rtp_stream *rtps; + int rc; + + /* All cells without talker are listening */ + llist_for_each_entry(bss, &trans->gcc.bss_list, list) { + llist_for_each_entry(cell, &bss->cell_list, list_bss) { + if (!(rtps = cell->rtps)) + continue; + if (rtps->crcx_conn_mode != MGCP_CONN_SEND_ONLY) { + LOG_CELL(cell, LOGL_DEBUG, "Setting cell %d into listening mode.\n", cell->cell_id); + rtp_stream_set_mode(rtps, MGCP_CONN_SEND_ONLY); + rc = rtp_stream_commit(rtps); + if (rc < 0) + LOG_CELL(cell, LOGL_ERROR, "Failed to commit parameters to RTP stream " + "for cell %d.\n", cell->cell_id); + } + } + } + + if (trans->gcc.uplink_cell && trans->gcc.uplink_cell->rtps) { + cell = trans->gcc.uplink_cell; + rtps = cell->rtps; + LOG_CELL(cell, LOGL_DEBUG, "Setting cell %d into listening mode.\n", cell->cell_id); + rtp_stream_set_mode(rtps, MGCP_CONN_CONFECHO); + rc = rtp_stream_commit(rtps); + if (rc < 0) + LOG_CELL(cell, LOGL_ERROR, "Failed to commit parameters to RTP stream " + "for cell %d.\n", cell->cell_id); + } + + return 0; +} + +static void _assign_complete(struct gsm_trans *trans, bool send_connect) +{ + uint16_t cell_id; + + OSMO_ASSERT(trans->msc_a); + + /* Change state. */ + osmo_fsm_inst_state_chg(trans->gcc.fi, VGCS_GCC_ST_N2_CALL_ACTIVE, 0, 0); + /* Get cell ID. */ + cell_id = trans->msc_a->via_cell.cell_identity; + /* Releasing dedicated channel. */ + release_msc_a(trans); + /* Send CONNECT to the calling subscriber. */ + if (send_connect) + gcc_connect(trans); + /* Set parameter. */ + set_parameter(trans); + /* Start inactivity timer, if uplink is free. */ + if (!trans->gcc.uplink_busy) + start_inactivity_timer(trans); + /* Set cell of current talker. */ + set_uplink_cell(trans->gcc.uplink_bss, NULL, cell_id); + /* Set MGW conference. */ + set_mgw_conference(trans); +} + +#define CONNECT_OPTION false + +static void vgcs_gcc_fsm_n0_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct gsm_trans *trans = fi->priv; + int rc; + + switch (event) { + case VGCS_GCC_EV_NET_SETUP: + /* Establish call towards all BSSs. */ + LOG_GCC(trans, LOGL_DEBUG, "Setup by network, trying to establish cells.\n"); + rc = gcc_establish_bss(trans); + if (rc < 0) { + LOG_GCC(trans, LOGL_NOTICE, "Failed to setup call to any cell.\n"); + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + } + /* Keep state until established or released. */ + break; + case VGCS_GCC_EV_NET_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by network, destroying call.\n"); + /* Destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_USER_SETUP: + LOG_GCC(trans, LOGL_DEBUG, "Setup by MS, trying to establish cells.\n"); + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_GCC_ST_N1_CALL_INITIATED, 0, 0); + /* Establish call towards all BSSs. */ + rc = gcc_establish_bss(trans); + if (rc < 0) { + LOG_GCC(trans, LOGL_NOTICE, "Failed to setup call to any cell.\n"); + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + } + if (CONNECT_OPTION) { + /* Send CONNECT to the calling subscriber. */ + gcc_connect(trans); + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_GCC_ST_N3_CALL_EST_PROC, 0, 0); + } + break; + case VGCS_GCC_EV_BSS_ESTABLISHED: + LOG_GCC(trans, LOGL_DEBUG, "All cells establised, for a group call, sending CONNECT to caller.\n"); + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_GCC_ST_N2_CALL_ACTIVE, 0, 0); + /* Start inactivity timer, if uplink is free. */ + if (!trans->gcc.uplink_busy) + start_inactivity_timer(trans); + break; + case VGCS_GCC_EV_BSS_RELEASED: + LOG_GCC(trans, LOGL_DEBUG, "All group call in all cells failed, destroying call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_gcc_fsm_n1_call_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct gsm_trans *trans = fi->priv; + int rc; + + switch (event) { + case VGCS_GCC_EV_NET_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by network, destroying call.\n"); + /* Destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_USER_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by user, destroying call.\n"); + /* Send TERMINATE to the calling subscriber and destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_BSS_ESTABLISHED: + LOG_GCC(trans, LOGL_DEBUG, "All cells establised, for a group call, assign caller to VGCS.\n"); + /* Send assignment to the calling subscriber. */ + rc = gcc_assign(trans); + if (rc < 0) { + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + } + break; + case VGCS_GCC_EV_BSS_ASSIGN_CPL: + LOG_GCC(trans, LOGL_DEBUG, "Assignment complete, sending CONNECT to caller, releasing channel.\n"); + /* Handle assignment complete */ + _assign_complete(trans, true); + break; + case VGCS_GCC_EV_BSS_ASSIGN_FAIL: + LOG_GCC(trans, LOGL_DEBUG, "Assignment failed, releasing call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + case VGCS_GCC_EV_BSS_RELEASED: + LOG_GCC(trans, LOGL_DEBUG, "All group call in all cells failed, destroying call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_gcc_fsm_n2_call_active(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct gsm_trans *trans = fi->priv; + + switch (event) { + case VGCS_GCC_EV_NET_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by network, destroying call.\n"); + /* Destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_USER_TERM: + if (!trans->gcc.uplink_originator) { + LOG_GCC(trans, LOGL_ERROR, "Termination by user, but it is not the originator.\n"); + gcc_termination_reject(trans, OSMO_GSM44068_CAUSE_USER_NOT_ORIGINATOR); + break; + } + LOG_GCC(trans, LOGL_DEBUG, "Termination by user, destroying call.\n"); + /* Send TERMINATE to the calling subscriber and destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_BSS_RELEASED: + LOG_GCC(trans, LOGL_DEBUG, "All group call in all cells failed, destroying call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + case VGCS_GCC_EV_TIMEOUT: + LOG_GCC(trans, LOGL_DEBUG, "Termination by inactivity timer, destroying call.\n"); + /* Destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_gcc_fsm_n3_call_est_proc(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct gsm_trans *trans = fi->priv; + int rc; + + switch (event) { + case VGCS_GCC_EV_NET_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by network, destroying call.\n"); + /* Destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_USER_TERM: + LOG_GCC(trans, LOGL_DEBUG, "Termination by user, destroying call.\n"); + /* Send TERMINATE to the calling subscriber and destroy group call in all cells. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + case VGCS_GCC_EV_BSS_ESTABLISHED: + LOG_GCC(trans, LOGL_DEBUG, "All cells establised, for a group call, assign caller to VGCS.\n"); + /* Send assignment to the calling subscriber. */ + rc = gcc_assign(trans); + if (rc < 0) { + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + } + break; + case VGCS_GCC_EV_BSS_ASSIGN_CPL: + LOG_GCC(trans, LOGL_DEBUG, "Assignment complete, sending CONNECT to caller, releasing channel.\n"); + /* Handle assignment complete */ + _assign_complete(trans, false); + break; + case VGCS_GCC_EV_BSS_ASSIGN_FAIL: + LOG_GCC(trans, LOGL_DEBUG, "Assignment failed, releasing call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + case VGCS_GCC_EV_BSS_RELEASED: + LOG_GCC(trans, LOGL_DEBUG, "All group call in all cells failed, destroying call.\n"); + /* Send TERMINATE to the calling subscriber. */ + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + break; + default: + OSMO_ASSERT(false); + } +} + +static const struct osmo_fsm_state vgcs_gcc_fsm_states[] = { + [VGCS_GCC_ST_N0_NULL] = { + .name = "NULL (N0)", + .in_event_mask = S(VGCS_GCC_EV_NET_SETUP) | + S(VGCS_GCC_EV_NET_TERM) | + S(VGCS_GCC_EV_USER_SETUP) | + S(VGCS_GCC_EV_BSS_ESTABLISHED) | + S(VGCS_GCC_EV_BSS_RELEASED), + .out_state_mask = S(VGCS_GCC_ST_N1_CALL_INITIATED) | + S(VGCS_GCC_ST_N2_CALL_ACTIVE), + .action = vgcs_gcc_fsm_n0_null, + }, + [VGCS_GCC_ST_N1_CALL_INITIATED] = { + .name = "CALL INITATED (N1)", + .in_event_mask = S(VGCS_GCC_EV_NET_TERM) | + S(VGCS_GCC_EV_USER_TERM) | + S(VGCS_GCC_EV_BSS_ESTABLISHED) | + S(VGCS_GCC_EV_BSS_ASSIGN_CPL) | + S(VGCS_GCC_EV_BSS_ASSIGN_FAIL) | + S(VGCS_GCC_EV_BSS_RELEASED), + .out_state_mask = S(VGCS_GCC_ST_N0_NULL) | + S(VGCS_GCC_ST_N2_CALL_ACTIVE) | + S(VGCS_GCC_ST_N3_CALL_EST_PROC), + .action = vgcs_gcc_fsm_n1_call_initiated, + }, + [VGCS_GCC_ST_N2_CALL_ACTIVE] = { + .name = "CALL ACTIVE (N2)", + .in_event_mask = S(VGCS_GCC_EV_NET_TERM) | + S(VGCS_GCC_EV_USER_TERM) | + S(VGCS_GCC_EV_BSS_RELEASED) | + S(VGCS_GCC_EV_TIMEOUT), + .out_state_mask = S(VGCS_GCC_ST_N0_NULL), + .action = vgcs_gcc_fsm_n2_call_active, + }, + [VGCS_GCC_ST_N3_CALL_EST_PROC] = { + .name = "CALL EST PROCEEDING (N3)", + .in_event_mask = S(VGCS_GCC_EV_NET_TERM) | + S(VGCS_GCC_EV_USER_TERM) | + S(VGCS_GCC_EV_BSS_ESTABLISHED) | + S(VGCS_GCC_EV_BSS_ASSIGN_CPL) | + S(VGCS_GCC_EV_BSS_ASSIGN_FAIL) | + S(VGCS_GCC_EV_BSS_RELEASED), + .out_state_mask = S(VGCS_GCC_ST_N2_CALL_ACTIVE) | + S(VGCS_GCC_ST_N0_NULL), + .action = vgcs_gcc_fsm_n3_call_est_proc, + }, + // We don't need a state to wait for the group call to be terminated in all cells +}; + +static struct osmo_fsm vgcs_bcc_fsm = { + .name = "bcc", + .states = vgcs_gcc_fsm_states, + .num_states = ARRAY_SIZE(vgcs_gcc_fsm_states), + .log_subsys = DBCC, + .event_names = vgcs_gcc_fsm_event_names, +}; + +static struct osmo_fsm vgcs_gcc_fsm = { + .name = "gcc", + .states = vgcs_gcc_fsm_states, + .num_states = ARRAY_SIZE(vgcs_gcc_fsm_states), + .log_subsys = DGCC, + .event_names = vgcs_gcc_fsm_event_names, +}; + +const char *vgcs_bcc_gcc_state_name(struct osmo_fsm_inst *fi) +{ + return vgcs_gcc_fsm_states[fi->state].name; +} + +static int update_uplink_state(struct vgcs_bss *bss, bool uplink_busy); + +/* Receive RR messages from calling subscriber, prior assignment to VGCS/VBS. */ +int gsm44068_rcv_rr(struct msc_a *msc_a, struct msgb *msg) +{ + struct gsm_trans *trans = NULL; + struct gsm48_hdr *gh; + uint8_t msg_type; + + gh = msgb_l3(msg); + msg_type = gsm48_hdr_msg_type(gh); + + /* Find transaction. */ + trans = trans_find_by_type(msc_a, TRANS_GCC); + if (!trans) + trans = trans_find_by_type(msc_a, TRANS_BCC); + + if (!trans) { + LOG_GCC(trans, LOGL_ERROR, "No VGCS/VBS transaction.\n"); + return -EINVAL; + } + + /* In case the phone releases uplink prior being assigned to a VGCS */ + if (msg_type == GSM48_MT_RR_UPLINK_RELEASE) { + struct vgcs_bss *bss; + + LOG_GCC(trans, LOGL_INFO, "Received UPLINK RELEASE on initial channel.\n"); + /* Clear the busy flag and unblock all cells. */ + trans->gcc.uplink_bss = NULL; + trans->gcc.uplink_cell = NULL; + trans->gcc.uplink_busy = false; + llist_for_each_entry(bss, &trans->gcc.bss_list, list) { + /* Update uplink state. */ + update_uplink_state(bss, trans->gcc.uplink_busy); + } + /* Start inactivity timer. */ + start_inactivity_timer(bss->trans); + /* Next, the MS will switch to the VGCS as listener. Nothing else to do here. */ + } + + return 0; +} + +/* Allocation of transaction for group call */ +static struct gsm_trans *trans_alloc_vgcs(struct gsm_network *net, + struct vlr_subscr *vsub, + enum trans_type trans_type, uint8_t transaction_id, + uint32_t callref, + struct gcr *gcr, + bool uplink_busy) +{ + struct gsm_trans *trans; + + trans = trans_alloc(net, vsub, trans_type, transaction_id, callref); + if (!trans) { + LOG_GCC(trans, LOGL_ERROR, "No memory for trans.\n"); + return NULL; + } + /* The uplink is busy when the call is started until the calling subscriber releases. */ + trans->gcc.uplink_busy = uplink_busy; + trans->gcc.uplink_originator = true; + INIT_LLIST_HEAD(&trans->gcc.bss_list); + trans->gcc.inactivity_to = gcr->timeout; + trans->gcc.mute_talker = gcr->mute_talker; + trans->gcc.timer_inactivity.data = trans; + trans->gcc.timer_inactivity.cb = inactivity_timer_cb; + trans->gcc.fi = osmo_fsm_inst_alloc((trans_type == TRANS_GCC) ? &vgcs_gcc_fsm : &vgcs_bcc_fsm, + trans, trans, LOGL_DEBUG, NULL); + if (!trans->gcc.fi) { + LOG_GCC(trans, LOGL_ERROR, "No memory for state machine.\n"); + trans_free(trans); + return NULL; + } + + return trans; +} + +/* Create transaction from incoming voice group/broadcast call. */ +static struct gsm_trans *trans_create_bcc_gcc(struct msc_a *msc_a, enum trans_type trans_type, uint8_t transaction_id, + uint8_t pdisc, uint8_t msg_type, uint32_t callref) +{ + struct gsm_network *net; + struct vlr_subscr *vsub; + struct gsm_trans *trans = NULL; + struct gcr *gcr; + int rc; + + if (!msc_a) { + LOG_GCC(trans, LOGL_ERROR, "Invalid conn: no msc_a\n"); + return NULL; + } + net = msc_a_net(msc_a); + vsub = msc_a_vsub(msc_a); + + if (!vsub) { + LOG_GCC(trans, LOGL_ERROR, "Invalid conn: no subscriber\n"); + return NULL; + } + + /* An earlier CM Service Request for this CC message now has concluded */ + if (!osmo_use_count_by(&msc_a->use_count, + (trans_type == TRANS_GCC) ? MSC_A_USE_CM_SERVICE_GCC : MSC_A_USE_CM_SERVICE_BCC)) + LOG_MSC_A(msc_a, LOGL_ERROR, + "Creating new %s transaction without prior CM Service Request.\n", + get_value_string(trans_type_names, trans_type)); + else + msc_a_put(msc_a, + (trans_type == TRANS_GCC) ? MSC_A_USE_CM_SERVICE_GCC : MSC_A_USE_CM_SERVICE_BCC); + + /* A transaction must be created with a SETUP message. */ + if (msg_type != OSMO_GSM44068_MSGT_IMMEDIATE_SETUP + && msg_type != OSMO_GSM44068_MSGT_SETUP + && msg_type != OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2) { + LOG_GCC(trans, LOGL_ERROR, "No transaction and message is not a SETUP.\n"); + return NULL; + } + + /* Check if callref already exists. */ + trans = trans_find_by_callref(net, trans_type, callref); + if (trans) { + LOG_GCC(trans, LOGL_INFO, "Call to existing %s with callref %s, rejecting!\n", + trans_type_name(trans_type), gsm44068_group_id_string(callref)); + rc = gsm44068_tx_termination(msc_a, NULL, + pdisc | (transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION, + OSMO_GSM44068_CAUSE_BUSY, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION towards MS.\n"); + return 0; + } + + /* Check GCR for Group ID. */ + gcr = gcr_by_callref(net, trans_type, callref); + if (!gcr) { + LOG_GCC(trans, LOGL_INFO, "No Group configured for %s callref %s, rejecting!\n", + trans_type_name(trans_type), gsm44068_group_id_string(callref)); + // FIXME: Better cause value for a group that does not exist ? + rc = gsm44068_tx_termination(msc_a, NULL, + pdisc | (transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION, + OSMO_GSM44068_CAUSE_REQUESTED_SERVICE_NOT_SUB, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION towards MS.\n"); + return 0; + } + + /* Create transaction, uplink is busy. */ + trans = trans_alloc_vgcs(net, vsub, trans_type, transaction_id, callref, gcr, true); + if (!trans) { + rc = gsm44068_tx_termination(msc_a, NULL, + pdisc | (transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION, + OSMO_GSM44068_CAUSE_NETWORK_FAILURE, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION towards MS.\n"); + return NULL; + } + + if (osmo_fsm_inst_dispatch(msc_a->c.fi, MSC_A_EV_TRANSACTION_ACCEPTED, trans)) { + LOG_MSC_A(msc_a, LOGL_ERROR, "Not allowed to accept %s transaction.\n", + get_value_string(trans_type_names, trans_type)); + gcc_terminate_and_destroy(trans, OSMO_GSM44068_CAUSE_NETWORK_FAILURE); + return NULL; + } + + /* Assign transaction */ + msc_a_get(msc_a, (trans_type == TRANS_GCC) ? MSC_A_USE_GCC : MSC_A_USE_BCC); + trans->msc_a = msc_a; + trans->dlci = 0; /* main DCCH */ + + return trans; +} + +/* Receive GCC/BCC messages from calling subscriber, depending on the PDISC used. */ +int gsm44068_rcv_bcc_gcc(struct msc_a *msc_a, struct gsm_trans *trans, struct msgb *msg) +{ + struct gsm48_hdr *gh = msgb_l3(msg); + uint8_t msg_type = gsm48_hdr_msg_type(gh); + uint8_t pdisc = gsm48_hdr_pdisc(gh); + uint8_t transaction_id = gsm48_hdr_trans_id_flip_ti(gh); + enum trans_type trans_type = (pdisc == GSM48_PDISC_GROUP_CC) ? TRANS_GCC : TRANS_BCC; + + uint8_t key_seq; + bool talker_prio_requested; + bool with_talker_prio; + uint8_t talker_prio; + struct gsm48_classmark2 cm2; + struct osmo_mobile_identity mi; + uint32_t callref; + bool with_prio; + uint8_t prio; + char user_user[64] = ""; + uint8_t cause; + uint8_t diag[256]; + uint8_t diag_len; + bool with_call_state; + enum osmo_gsm44068_call_state call_state; + bool with_state_attrs; + uint8_t da, ua, comm, oi; + int rc = 0; + + /* Remove sequence number (bit 7) from message type. */ + msg_type &= 0xbf; + + /* Parse messages. */ + switch (msg_type) { + case OSMO_GSM44068_MSGT_SETUP: + rc = gsm44068_rx_setup(msg, &talker_prio_requested, &talker_prio, &callref, &with_prio, &prio, + user_user); + break; + case OSMO_GSM44068_MSGT_IMMEDIATE_SETUP: + case OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2: + rc = gsm44068_rx_immediate_setup(msg, &talker_prio, &key_seq, &cm2, &mi, &callref, &with_prio, &prio, + user_user); + break; + case OSMO_GSM44068_MSGT_STATUS: + rc = gsm44068_rx_status(msg, &cause, diag, &diag_len, &with_call_state, &call_state, + &with_state_attrs, &da, &ua, &comm, &oi); + break; + case OSMO_GSM44068_MSGT_TERMINATION_REQUEST: + rc = gsm44068_rx_termination_req(msg, &callref, &with_prio, &prio, &with_talker_prio, &talker_prio); + break; + default: + LOG_GCC(trans, LOGL_ERROR, "Invalid message type: 0x%02x\n", msg_type); + return -EINVAL; + } + if (rc < 0) + return rc; + + /* Find transaction, if called from msc_a. */ + if (!trans) + trans = trans_find_by_id(msc_a, trans_type, transaction_id); + + /* Create transaction for SETUP message. */ + if (!trans) { + trans = trans_create_bcc_gcc(msc_a, trans_type, transaction_id, pdisc, msg_type, callref); + if (!trans) + return -EINVAL; + } else { + /* A phone may not call while a VGCS is already active */ + if (msg_type == OSMO_GSM44068_MSGT_IMMEDIATE_SETUP + || msg_type == OSMO_GSM44068_MSGT_SETUP + || msg_type == OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2) { + LOG_GCC(trans, LOGL_ERROR, "Received SETUP while call is already set up, rejecting.\n"); + rc = gsm44068_tx_termination(msc_a, NULL, + pdisc | (transaction_id << 4), + OSMO_GSM44068_MSGT_TERMINATION, + OSMO_GSM44068_CAUSE_NETWORK_FAILURE, NULL, 0); + if (rc < 0) + LOG_GCC(trans, LOGL_ERROR, "Failed to send TERMINATION towards MS.\n"); + return -EINVAL; + } + } + + /* Handle received GCC messages (trigger state machine). */ + switch (msg_type) { + case OSMO_GSM44068_MSGT_IMMEDIATE_SETUP: + case OSMO_GSM44068_MSGT_SETUP: + case OSMO_GSM44068_MSGT_IMMEDIATE_SETUP_2: + LOG_GCC(trans, LOGL_INFO, "Received SETUP.\n"); + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_USER_SETUP, NULL); + break; + case OSMO_GSM44068_MSGT_STATUS: + LOG_GCC(trans, LOGL_NOTICE, "Received STATUS with cause %d (%s).\n", cause, + get_value_string(osmo_gsm44068_cause_names, cause)); + if (diag_len) + LOG_GCC(trans, LOGL_NOTICE, " -> diagnostics: %s\n", osmo_hexdump(diag, diag_len)); + if (with_call_state) + LOG_GCC(trans, LOGL_NOTICE, " -> call state %s\n", + get_value_string(osmo_gsm44068_call_state_names, call_state)); + break; + case OSMO_GSM44068_MSGT_TERMINATION_REQUEST: + LOG_GCC(trans, LOGL_INFO, "Received TERMINATRION REQUEST.\n"); + if (callref != trans->callref) { + LOG_GCC(trans, LOGL_NOTICE, "Received callref 0x%x does not match!\n", callref); + break; + } + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_USER_TERM, NULL); + break; + } + + return 0; +} + +static void bss_clear(struct vgcs_bss *bss, uint8_t cause, bool notify_trans); + +/* Call Control Specific transaction release. + * gets called by trans_free, DO NOT CALL YOURSELF! */ +void gsm44068_bcc_gcc_trans_free(struct gsm_trans *trans) +{ + struct vgcs_bss *bss, *bss2; + + /* Free FSM. */ + if (trans->gcc.fi) { + osmo_fsm_inst_state_chg(trans->gcc.fi, VGCS_GCC_ST_N0_NULL, 0, 0); + osmo_fsm_inst_term(trans->gcc.fi, OSMO_FSM_TERM_REGULAR, NULL); + } + + /* Remove relations to cells. + * We must loop safe, because bss_clear() will detach every call control instance from list. */ + llist_for_each_entry_safe(bss, bss2, &trans->gcc.bss_list, list) + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_CLEAR, NULL); + + /* Stop inactivity timer. */ + stop_inactivity_timer(trans); +} + +/* Create a new call from VTY command. */ +const char *vgcs_vty_initiate(struct gsm_network *gsmnet, struct gcr *gcr) +{ + enum trans_type trans_type; + uint32_t callref; + struct gsm_trans *trans; + + /* Get callref from stored suffix. Caller cannot choose a prefix. */ + trans_type = gcr->trans_type; + callref = atoi(gcr->group_id); + + /* Check if callref already exists. */ + trans = trans_find_by_callref(gsmnet, trans_type, callref); + if (trans) { + LOG_GCC(trans, LOGL_INFO, "Call to existing %s with callref %s, rejecting!\n", + trans_type_name(trans_type), gsm44068_group_id_string(callref)); + return "Call already exists."; + } + + /* Create transaction, uplink is free. */ + trans = trans_alloc_vgcs(gsmnet, NULL, trans_type, 0, callref, gcr, false); + if (!trans) { + LOG_GCC(trans, LOGL_ERROR, "No memory for trans.\n"); + return "Failed to create call."; + } + + LOG_GCC(trans, LOGL_INFO, "VTY initiates call.\n"); + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_NET_SETUP, NULL); + + return NULL; +} + +/* Destroy a call from VTY command. */ +const char *vgcs_vty_terminate(struct gsm_network *gsmnet, struct gcr *gcr) +{ + enum trans_type trans_type; + uint32_t callref; + struct gsm_trans *trans; + + /* Get callref from stored suffix. Caller cannot choose a prefix. */ + trans_type = gcr->trans_type; + callref = atoi(gcr->group_id); + + /* Check if callref exists. */ + trans = trans_find_by_callref(gsmnet, trans_type, callref); + if (!trans) + return "Call does not exist."; + + LOG_GCC(trans, LOGL_INFO, "VTY terminates call.\n"); + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_NET_TERM, NULL); + + return NULL; +} + +/* + * BSS state machine - handles all BSS "call control" instances + */ + +static const struct value_string vgcs_bss_fsm_event_names[] = { + OSMO_VALUE_STRING(VGCS_BSS_EV_SETUP), + OSMO_VALUE_STRING(VGCS_BSS_EV_SETUP_ACK), + OSMO_VALUE_STRING(VGCS_BSS_EV_SETUP_REFUSE), + OSMO_VALUE_STRING(VGCS_BSS_EV_ACTIVE_OR_FAIL), + OSMO_VALUE_STRING(VGCS_BSS_EV_UL_REQUEST), + OSMO_VALUE_STRING(VGCS_BSS_EV_UL_REQUEST_CNF), + OSMO_VALUE_STRING(VGCS_BSS_EV_UL_APP_DATA), + OSMO_VALUE_STRING(VGCS_BSS_EV_BSS_DTAP), + OSMO_VALUE_STRING(VGCS_BSS_EV_UL_RELEASE), + OSMO_VALUE_STRING(VGCS_BSS_EV_CLEAR), + OSMO_VALUE_STRING(VGCS_BSS_EV_CLOSE), + OSMO_VALUE_STRING(VGCS_BSS_EV_RELEASED), + { } +}; + +/* Blocks or unblocks uplinks of a BSS. */ +static int update_uplink_state(struct vgcs_bss *bss, bool uplink_busy) +{ + struct ran_msg ran_msg; + int rc; + + if (uplink_busy) { + /* Send UPLINK SEIZED COMMAND to BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Sending (VGCS) UPLINK SEIZED COMMAND towards BSS.\n"); + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_UPLINK_SEIZED_CMD, + .uplink_seized_cmd = { + .cause = GSM0808_CAUSE_CALL_CONTROL, + }, + }; + } else { + /* Send UPLINK RELEASE COMMAND to BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Sending (VGCS) UPLINK RELEASE COMMAND towards BSS.\n"); + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_UPLINK_RELEASE_CMD, + .uplink_release_cmd = { + .cause = GSM0808_CAUSE_CALL_CONTROL, + }, + }; + } + + rc = ran_encode_and_send(bss->fi, &ran_msg, bss->conn, false); + + return rc; +} + +/* Clear the connection towards BSS. + * The instance is removed soon, so it is detached from transaction and cells. */ +static void bss_clear(struct vgcs_bss *bss, uint8_t cause, bool notify_trans) +{ + struct ran_msg ran_msg; + struct gsm_trans *trans = bss->trans; + struct vgcs_bss_cell *cell, *cell2; + + /* Must detach us from transaction. */ + if (bss->trans) { + /* Remove pointer to talking BSS and cell. */ + if (bss == bss->trans->gcc.uplink_bss) { + bss->trans->gcc.uplink_bss = NULL; + bss->trans->gcc.uplink_cell = NULL; + } + llist_del(&bss->list); + bss->trans = NULL; + } + + /* Change state. */ + osmo_fsm_inst_state_chg(bss->fi, VGCS_BSS_ST_RELEASE, 0, 0); + + /* Send Clear Command to BSS. */ + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_CLEAR_COMMAND, + .clear_command = { + .gsm0808_cause = cause, + }, + }; + if (bss->conn) { + LOG_BSS(bss, LOGL_DEBUG, "Sending CLEAR COMMAND for call controling channel.\n"); + ran_encode_and_send(bss->fi, &ran_msg, bss->conn, false); + } + + /* Trigger clear of all cells. Be safe, because the process will remove cells from list. */ + llist_for_each_entry_safe(cell, cell2, &bss->cell_list, list_bss) + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_CLEAR, NULL); + + /* Detach us from all BSS, if still linked */ + llist_for_each_entry_safe(cell, cell2, &bss->cell_list, list_bss) { + llist_del(&cell->list_bss); + cell->bss = NULL; + } + + /* If all BS are gone, notify calling subscriber process. */ + if (notify_trans && trans && llist_empty(&trans->gcc.bss_list)) { + LOG_BSS(bss, LOGL_DEBUG, "Notify calling user process, that all BSSs are cleared.\n"); + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_BSS_RELEASED, NULL); + } +} + +/* When finally the BSS connection is released. (CLEAR COMPLETE response) + * The instance is removed, so it is detached from transaction and cells, if not already. */ +static void bss_destroy(struct vgcs_bss *bss) +{ + struct vgcs_bss_cell *cell, *cell2; + + LOG_BSS(bss, LOGL_DEBUG, "Removing BSS call controling instance.\n"); + + /* Must detach us from transaction, if not already. */ + if (bss->trans) { + /* Remove pointer to talking BSS and cell. */ + if (bss == bss->trans->gcc.uplink_bss) { + bss->trans->gcc.uplink_bss = NULL; + bss->trans->gcc.uplink_cell = NULL; + } + llist_del(&bss->list); + bss->trans = NULL; + } + + /* Detach us from RAN connection. */ + if (bss->conn) { + if (bss->conn->vgcs.bss == bss) + bss->conn->vgcs.bss = NULL; + if (bss->conn->vgcs.cell == bss) + bss->conn->vgcs.cell = NULL; + ran_conn_close(bss->conn); + bss->conn = NULL; + } + + /* Detach us from all BSS, if still linked */ + llist_for_each_entry_safe(cell, cell2, &bss->cell_list, list_bss) { + llist_del(&cell->list_bss); + cell->bss = NULL; + } + + /* Free FSM. (should be allocated) */ + osmo_fsm_inst_state_chg(bss->fi, VGCS_BSS_ST_NULL, 0, 0); + osmo_fsm_inst_term(bss->fi, OSMO_FSM_TERM_REGULAR, NULL); +} + +/* Get identity of talker. + * This is required to detect if the talker is the calling subscriber. */ +static int talker_identity(struct vgcs_bss *bss, uint8_t *l3, int l3_len) +{ + struct osmo_mobile_identity mi; + int rc; + + rc = osmo_mobile_identity_decode_from_l3_buf(&mi, l3, l3_len, false); + if (rc < 0) { + LOG_BSS(bss, LOGL_DEBUG, "Talker's Identity cannot be decoded.\n"); + return rc; + } + + switch (mi.type) { + case GSM_MI_TYPE_IMSI: + if (!bss->trans->vsub) + break; + LOG_BSS(bss, LOGL_DEBUG, "Talker's sends IMSI %s, originator has IMSI %s.\n", + mi.imsi, bss->trans->vsub->imsi); + if (!strcmp(mi.imsi, bss->trans->vsub->imsi)) + return 1; + break; + case GSM_MI_TYPE_TMSI: + if (!bss->trans->vsub) + break; + LOG_BSS(bss, LOGL_DEBUG, "Talker's sends TMSI 0x%08x, originator has TMSI 0x%08x.\n", + mi.tmsi, bss->trans->vsub->tmsi); + if (mi.tmsi == bss->trans->vsub->tmsi) + return 1; + break; + default: + LOG_BSS(bss, LOGL_DEBUG, "Talker's Identity is not IMSI nor TMSI.\n"); + return -EINVAL; + } + + return 0; +} + +static void vgcs_bss_fsm_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss *bss = fi->priv; + struct ran_msg ran_msg; + + switch (event) { + case VGCS_BSS_EV_SETUP: + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_BSS_ST_SETUP, 0, 0); + /* Send VGCS/VBS SETUP to BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Sending VGCS/VBS SETUP towards BSS.\n"); + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_VGCS_VBS_SETUP, + .vgcs_vbs_setup = { + .callref = { + .sf = (bss->trans->type == TRANS_GCC), + }, + .vgcs_feature_flags_present = true, + }, + }; + osmo_store32be_ext(bss->callref >> 3, &ran_msg.vgcs_vbs_setup.callref.call_ref_hi, 3); + ran_msg.vgcs_vbs_setup.callref.call_ref_lo = bss->callref & 0x7; + /* First message, so we must set "initial" to "true". */ + ran_encode_and_send(fi, &ran_msg, bss->conn, true); + break; + case VGCS_BSS_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_BSS(bss, LOGL_DEBUG, "Received clearing from calling user process.\n"); + bss_clear(bss, GSM0808_CAUSE_CALL_CONTROL, false); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_bss_fsm_setup(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss *bss = fi->priv; + struct vgcs_bss_cell *cell, *cell2; + + switch (event) { + case VGCS_BSS_EV_SETUP_ACK: + /* Receive VGCS/VBS SETUP ACK from BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Received VGCS/VBS SETUP ACK from BSS.\n"); + /* Send current uplink state to this BSS. */ + if (bss->trans) + update_uplink_state(bss, bss->trans->gcc.uplink_busy); + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_BSS_ST_ASSIGNMENT, 0, 0); + /* Trigger VGCS/VBS ASSIGNMENT */ + llist_for_each_entry_safe(cell, cell2, &bss->cell_list, list_bss) + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_ASSIGN, NULL); + /* If all failed, clear call. */ + if (llist_empty(&bss->cell_list)) { + LOG_BSS(bss, LOGL_NOTICE, "All VGCS/VBS assignments failed.\n"); + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + } + break; + case VGCS_BSS_EV_SETUP_REFUSE: + /* Received VGCS/VBS SETUP REFUSE from BSS. */ + LOG_BSS(bss, LOGL_NOTICE, "Received VGCS/VBS SETUP REFUSE from BSS.\n"); + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + case VGCS_BSS_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_BSS(bss, LOGL_DEBUG, "Received clearing from calling user process.\n"); + bss_clear(bss, GSM0808_CAUSE_CALL_CONTROL, false); + break; + case VGCS_BSS_EV_CLOSE: + /* The SCCP connection from the MSC has been closed. */ + LOG_BSS(bss, LOGL_NOTICE, "Received SCCP connecting closing from MSC.\n"); + if (bss->conn) { + bss->conn->vgcs.bss = NULL; + bss->conn = NULL; + } + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_bss_fsm_assignment(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss *bss = fi->priv; + struct vgcs_bss_cell *c; + bool assigned; + + switch (event) { + case VGCS_BSS_EV_ACTIVE_OR_FAIL: + /* If all gone, clear call. */ + if (llist_empty(&bss->cell_list)) { + LOG_BSS(bss, LOGL_NOTICE, "All VGCS/VBS assignments failed.\n"); + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + } + /* Is there a response for all cells? + * This means that all the channels have a positive response + * There is no channel with negative response, because a + * negative response will remove the channel. */ + assigned = true; + llist_for_each_entry(c, &bss->cell_list, list_bss) { + if (!c->assigned) + assigned = false; + } + if (!assigned) + break; + LOG_BSS(bss, LOGL_DEBUG, "All VGCS/VBS assignments have responded.\n"); + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_BSS_ST_ACTIVE, 0, 0); + /* Notify calling subscriber process. */ + LOG_BSS(bss, LOGL_DEBUG, "Notify calling user process, that all BSSs are connected.\n"); + if (bss->trans) + osmo_fsm_inst_dispatch(bss->trans->gcc.fi, VGCS_GCC_EV_BSS_ESTABLISHED, NULL); + break; + case VGCS_BSS_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_BSS(bss, LOGL_DEBUG, "Received clearing from calling user process.\n"); + bss_clear(bss, GSM0808_CAUSE_CALL_CONTROL, false); + break; + case VGCS_BSS_EV_CLOSE: + /* The SCCP connection from the MSC has been closed. */ + LOG_BSS(bss, LOGL_NOTICE, "Received SCCP connecting closing from MSC.\n"); + if (bss->conn) { + bss->conn->vgcs.bss = NULL; + bss->conn = NULL; + } + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_bss_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss *bss = fi->priv, *other; + struct ran_msg *rx_ran_msg = data; + struct ran_msg tx_ran_msg; + int rc; + + switch (event) { + case VGCS_BSS_EV_UL_REQUEST: + LOG_BSS(bss, LOGL_DEBUG, "Listener changed to talker.\n"); + if (!bss->trans) + break; + /* Someone is talking. Check if there is no other uplink already busy. + * This should not happen, since all other cells are blocked (SEIZED) as soon as the uplink was + * requested. This may happen due to a race condition, where the uplink was requested before the + * UPLINK SEIZED COMMAND has been received by BSS. */ + if (bss->trans->gcc.uplink_busy) { + /* Send UPLINK REJECT COMMAND to BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Sending (VGCS) UPLINK REJECT COMMAND towards BSS.\n"); + tx_ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_UPLINK_REJECT_CMD, + .uplink_reject_cmd = { + .cause = GSM0808_CAUSE_CALL_CONTROL, + }, + }; + ran_encode_and_send(fi, &tx_ran_msg, bss->conn, false); + break; + } + /* Send UPLINK REQUEST ACKNOWLEDGE to BSS. */ + LOG_BSS(bss, LOGL_DEBUG, "Sending (VGCS) UPLINK REQUEST ACKNOWLEDGE towards BSS.\n"); + tx_ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_UPLINK_REQUEST_ACK, + }; + ran_encode_and_send(fi, &tx_ran_msg, bss->conn, false); + /* Set the busy flag and block all other cells. */ + bss->trans->gcc.uplink_bss = bss; + bss->trans->gcc.uplink_busy = true; + bss->trans->gcc.uplink_originator = false; + llist_for_each_entry(other, &bss->trans->gcc.bss_list, list) { + if (other == bss) + continue; + /* Update uplink state. */ + update_uplink_state(bss, bss->trans->gcc.uplink_busy); + } + /* Stop inactivity timer. */ + stop_inactivity_timer(bss->trans); + break; + case VGCS_BSS_EV_UL_REQUEST_CNF: + LOG_BSS(bss, LOGL_DEBUG, "Talker established uplink.\n"); + if (!bss->trans) + break; + if (!bss->trans->gcc.uplink_busy || bss->trans->gcc.uplink_bss != bss) { + LOG_BSS(bss, LOGL_ERROR, "Got UL REQUEST CNF, but we did not granted uplink.\n"); + break; + } + /* Determine if talker is the originator of the call. */ + rc = talker_identity(bss, rx_ran_msg->uplink_request_cnf.l3.l3, + rx_ran_msg->uplink_request_cnf.l3.l3_len); + if (rc > 0) { + bss->trans->gcc.uplink_originator = true; + LOG_BSS(bss, LOGL_DEBUG, "Talker is the originator of the call.\n"); + } + /* Set parameter. */ + set_parameter(bss->trans); + /* Set cell of current talker. */ + set_uplink_cell(bss, &rx_ran_msg->uplink_request_cnf.cell_identifier, 0); + /* Set MGW conference. */ + set_mgw_conference(bss->trans); + break; + case VGCS_BSS_EV_UL_APP_DATA: + LOG_BSS(bss, LOGL_DEBUG, "Talker sends application data on uplink.\n"); + if (!bss->trans) + break; + if (!bss->trans->gcc.uplink_busy || bss->trans->gcc.uplink_bss != bss) { + LOG_BSS(bss, LOGL_ERROR, "Got UP APP DATA, but we did not granted uplink.\n"); + break; + } + // FIXME: Use L3 info and feed to app. + break; + case VGCS_BSS_EV_BSS_DTAP: + LOG_BSS(bss, LOGL_DEBUG, "Talker sends DTAP message.\n"); + if (!bss->trans) + break; + if (!bss->trans->gcc.uplink_busy || bss->trans->gcc.uplink_bss != bss) { + LOG_BSS(bss, LOGL_ERROR, "Got DTAP from BSS, but we did not granted uplink.\n"); + break; + } + gsm44068_rcv_bcc_gcc(NULL, bss->trans, rx_ran_msg->dtap); + break; + case VGCS_BSS_EV_UL_RELEASE: + LOG_BSS(bss, LOGL_DEBUG, "Talker released uplink.\n"); + if (!bss->trans) + break; + if (bss->trans->type == TRANS_BCC) { + LOG_BSS(bss, LOGL_DEBUG, "This is a broadcast call, terminating call.\n"); + gcc_terminate_and_destroy(bss->trans, OSMO_GSM44068_CAUSE_NORMAL_CALL_CLEARING); + break; + } + if (!bss->trans->gcc.uplink_busy) { + LOG_BSS(bss, LOGL_NOTICE, "Got uplink release, but no uplink busy.\n"); + break; + } + /* Talker release the uplink. Ignore, if not from the current talking cell. */ + if (bss->trans->gcc.uplink_bss != bss) { + LOG_BSS(bss, LOGL_NOTICE, "Got uplink release, but uplink busy in other cell.\n"); + break; + } + /* Clear the busy flag and unblock all other cells. */ + bss->trans->gcc.uplink_bss = NULL; + bss->trans->gcc.uplink_cell = NULL; + bss->trans->gcc.uplink_busy = false; + llist_for_each_entry(other, &bss->trans->gcc.bss_list, list) { + if (other == bss) + continue; + /* Update uplink state. */ + if (bss->trans) + update_uplink_state(bss, bss->trans->gcc.uplink_busy); + } + /* Set MGW conference. */ + set_mgw_conference(bss->trans); + /* Start inactivity timer. */ + start_inactivity_timer(bss->trans); + break; + case VGCS_BSS_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_BSS(bss, LOGL_DEBUG, "Received clearing from calling user process.\n"); + bss_clear(bss, GSM0808_CAUSE_CALL_CONTROL, false); + break; + case VGCS_BSS_EV_CLOSE: + /* The SCCP connection from the MSC has been closed. */ + LOG_BSS(bss, LOGL_NOTICE, "Received SCCP connecting closing from MSC.\n"); + if (bss->conn) { + bss->conn->vgcs.bss = NULL; + bss->conn = NULL; + } + bss_clear(bss, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC, true); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_bss_fsm_release(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss *bss = fi->priv; + + switch (event) { + case VGCS_BSS_EV_CLOSE: + /* The SCCP connection from the MSC has been closed while waitring fro CLEAR COMPLETE. */ + LOG_BSS(bss, LOGL_NOTICE, "Received SCCP closing collision.\n"); + bss_destroy(bss); + break; + case VGCS_BSS_EV_RELEASED: + LOG_BSS(bss, LOGL_DEBUG, "Received CLEAR COMPLETE from BSS, we are done!\n"); + bss_destroy(bss); + break; + default: + OSMO_ASSERT(false); + } +} + +static const struct osmo_fsm_state vgcs_bss_fsm_states[] = { + [VGCS_BSS_ST_NULL] = { + .name = "NULL", + .in_event_mask = S(VGCS_BSS_EV_SETUP) | + S(VGCS_BSS_EV_CLEAR), + .out_state_mask = S(VGCS_BSS_ST_SETUP), + .action = vgcs_bss_fsm_null, + }, + [VGCS_BSS_ST_SETUP] = { + .name = "SETUP sent", + .in_event_mask = S(VGCS_BSS_EV_SETUP_ACK) | + S(VGCS_BSS_EV_SETUP_REFUSE) | + S(VGCS_BSS_EV_CLEAR) | + S(VGCS_BSS_EV_CLOSE), + .out_state_mask = S(VGCS_BSS_ST_ASSIGNMENT) | + S(VGCS_BSS_ST_RELEASE), + .action = vgcs_bss_fsm_setup, + }, + [VGCS_BSS_ST_ASSIGNMENT] = { + .name = "ASSIGNMENT Sent", + .in_event_mask = S(VGCS_BSS_EV_ACTIVE_OR_FAIL) | + S(VGCS_BSS_EV_CLEAR) | + S(VGCS_BSS_EV_CLOSE), + .out_state_mask = S(VGCS_BSS_ST_ACTIVE) | + S(VGCS_BSS_ST_RELEASE), + .action = vgcs_bss_fsm_assignment, + }, + [VGCS_BSS_ST_ACTIVE] = { + .name = "VGCS/VBS Active", + .in_event_mask = S(VGCS_BSS_EV_UL_REQUEST) | + S(VGCS_BSS_EV_UL_REQUEST_CNF) | + S(VGCS_BSS_EV_UL_APP_DATA) | + S(VGCS_BSS_EV_BSS_DTAP) | + S(VGCS_BSS_EV_UL_RELEASE) | + S(VGCS_BSS_EV_CLEAR) | + S(VGCS_BSS_EV_CLOSE), + .out_state_mask = S(VGCS_BSS_ST_RELEASE), + .action = vgcs_bss_fsm_active, + }, + [VGCS_BSS_ST_RELEASE] = { + .name = "Releasing VGCS/VBS control", + .in_event_mask = S(VGCS_BSS_EV_CLEAR) | + S(VGCS_BSS_EV_RELEASED), + .out_state_mask = S(VGCS_BSS_ST_NULL), + .action = vgcs_bss_fsm_release, + }, +}; + +static struct osmo_fsm vgcs_bss_fsm = { + .name = "vgcs_bss", + .states = vgcs_bss_fsm_states, + .num_states = ARRAY_SIZE(vgcs_bss_fsm_states), + .log_subsys = DASCI, + .event_names = vgcs_bss_fsm_event_names, +}; + +/* The BSS accepts VGCS/VBS and sends us supported features. */ +void vgcs_vbs_setup_ack(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_SETUP_ACK, (void *)ran_msg); +} + +/* The BSS refuses VGCS/VBS. */ +void vgcs_vbs_setup_refuse(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_SETUP_REFUSE, (void *)ran_msg); +} + +/* The BSS needs more time for VGCS/VBS channel assignment. */ +void vgcs_vbs_queuing_ind(struct vgcs_bss_cell *cell) +{ + if (!cell->bss) + return; +} + +/* A mobile station requests the uplink on a VGCS channel. */ +void vgcs_uplink_request(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_UL_REQUEST, (void *)ran_msg); +} + +/* The uplink on a VGCS channel has been established. */ +void vgcs_uplink_request_cnf(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_UL_REQUEST_CNF, (void *)ran_msg); +} + +/* Application data received on the uplink of a VGCS channel. */ +void vgcs_app_data(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_UL_APP_DATA, (void *)ran_msg); +} + +/* Application data received on the uplink of a VGCS channel. */ +void vgcs_bss_dtap(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_BSS_DTAP, (void *)ran_msg); +} + +/* A mobile station releases the uplink on a VGCS channel. */ +void vgcs_uplink_release_ind(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + if (!bss->trans) + return; + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_UL_RELEASE, (void *)ran_msg); +} + +/* The BSS gives cell status about VGCS/VBS channel. */ +void vgcs_vbs_assign_status(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg) +{ + if (!cell->bss) + return; +} + +void vgcs_vbs_caller_assign_cpl(struct gsm_trans *trans) +{ + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_BSS_ASSIGN_CPL, NULL); +} + +void vgcs_vbs_caller_assign_fail(struct gsm_trans *trans) +{ + osmo_fsm_inst_dispatch(trans->gcc.fi, VGCS_GCC_EV_BSS_ASSIGN_FAIL, NULL); +} + +/* BSS indicated that the channel has been released. */ +void vgcs_vbs_clear_req(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_CLOSE, (void *)ran_msg); +} + +/* BSS indicated that the channel has been released. */ +void vgcs_vbs_clear_cpl(struct vgcs_bss *bss, const struct ran_msg *ran_msg) +{ + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_RELEASED, (void *)ran_msg); +} + +/* + * Cell resource state machine - handles all "resource control" instances + */ + +static const struct value_string vgcs_cell_fsm_event_names[] = { + OSMO_VALUE_STRING(VGCS_CELL_EV_RTP_STREAM_GONE), + OSMO_VALUE_STRING(VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE), + OSMO_VALUE_STRING(VGCS_CELL_EV_RTP_STREAM_ESTABLISHED), + OSMO_VALUE_STRING(VGCS_CELL_EV_ASSIGN), + OSMO_VALUE_STRING(VGCS_CELL_EV_ASSIGN_RES), + OSMO_VALUE_STRING(VGCS_CELL_EV_ASSIGN_FAIL), + OSMO_VALUE_STRING(VGCS_CELL_EV_CLEAR), + OSMO_VALUE_STRING(VGCS_CELL_EV_CLOSE), + OSMO_VALUE_STRING(VGCS_CELL_EV_RELEASED), + { } +}; + +static void cell_destroy(struct vgcs_bss_cell *cell); + +/* Clear the connection towards BSS. + * Relations to the BSS and transaction is removed. */ +static void cell_clear(struct vgcs_bss_cell *cell, uint8_t cause) +{ + struct ran_msg ran_msg; + + /* Must detach us from BSS. */ + if (cell->bss) { + /* Remove pointer to talking channel. */ + if (cell->bss->trans && cell->bss->trans->gcc.uplink_cell == cell) + cell->bss->trans->gcc.uplink_cell = NULL; + llist_del(&cell->list_bss); + cell->bss = NULL; + } + + /* Change state. */ + if (cell->fi->state != VGCS_CELL_ST_RELEASE) + osmo_fsm_inst_state_chg(cell->fi, VGCS_CELL_ST_RELEASE, 0, 0); + + /* If there is no event to wait for, we can just destroy. */ + if (!cell->conn && !cell->rtps) { + cell_destroy(cell); + return; + } + + /* Send Clear Command to BSS. */ + if (cell->conn) { + ran_msg = (struct ran_msg){ + .msg_type = RAN_MSG_CLEAR_COMMAND, + .clear_command = { + .gsm0808_cause = cause, + }, + }; + LOG_CELL(cell, LOGL_DEBUG, "Sending CLEAR COMMAND for call controling channel.\n"); + ran_encode_and_send(cell->fi, &ran_msg, cell->conn, false); + } + + /* Clear RTP stream. This may trigger VGCS_CELL_EV_RTP_STREAM_GONE within this release function. */ + if (cell->rtps) + rtp_stream_release(cell->rtps); +} + +/* When finally the BSS connection is released. (CLEAR COMPLETE response) + * Relations to the BSS and transaction is removed, if not already. */ +static void cell_destroy(struct vgcs_bss_cell *cell) +{ + struct vgcs_mgw_ep *mgw; + + /* close RAN conn */ + if (cell->conn) { + cell->conn->vgcs.cell = NULL; + ran_conn_close(cell->conn); + cell->conn = NULL; + } + + /* Detach from BSS now. Check, to prevent race condition. */ + if (cell->bss) { + /* Remove pointer to talking channel. */ + if (cell->bss->trans && cell->bss->trans->gcc.uplink_cell == cell) + cell->bss->trans->gcc.uplink_cell = NULL; + llist_del(&cell->list_bss); + cell->bss = NULL; + } + + /* Detach from MGW now. Check, to prevent race condition. */ + if (cell->mgw) { + mgw = cell->mgw; + llist_del(&cell->list_mgw); + cell->mgw = NULL; + /* Destroy MGW endpoint, if list is empty. */ + if (llist_empty(&mgw->cell_list)) + osmo_fsm_inst_dispatch(mgw->fi, VGCS_MGW_EP_EV_CLEAR, NULL); + } + + LOG_CELL(cell, LOGL_DEBUG, "Detroy connection to cell.\n"); + + /* Free FSM. (should be allocated) */ + osmo_fsm_inst_state_chg(cell->fi, VGCS_CELL_ST_NULL, 0, 0); + osmo_fsm_inst_term(cell->fi, OSMO_FSM_TERM_REGULAR, NULL); +} + +static void vgcs_cell_fsm_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss_cell *cell = fi->priv; + const struct codec_mapping *cm; + int rc; + + switch (event) { + case VGCS_CELL_EV_ASSIGN: + LOG_CELL(cell, LOGL_DEBUG, "Received assignment from BSS controling process.\n"); + /* Allocate rtps stream. */ + cell->rtps = rtp_stream_alloc(cell->fi, VGCS_CELL_EV_RTP_STREAM_GONE, + VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE, + VGCS_CELL_EV_RTP_STREAM_ESTABLISHED, RTP_TO_RAN, cell->call_id, + NULL); + if (!cell->rtps) { + LOG_CELL(cell, LOGL_DEBUG, "Failed to allocate RTP stream, cannot continue.\n"); + cell_destroy(cell); + break; + } + /* Hard coded codec: GSM V1 */ + cm = codec_mapping_by_gsm0808_speech_codec_type(GSM0808_SCT_FR1); + if (!cm) { + LOG_CELL(cell, LOGL_DEBUG, "Selected codec not supported, cannot continue.\n"); + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + } + rtp_stream_set_one_codec(cell->rtps, &cm->sdp); + /* Set initial mode. */ + rtp_stream_set_mode(cell->rtps, MGCP_CONN_RECV_ONLY); + /* Commit RTP stream. */ + if (!cell->bss || !cell->bss->trans) { + LOG_CELL(cell, LOGL_DEBUG, "No BSS/transaction, cannot continue.\n"); + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + } + if (!cell->mgw || !cell->mgw->mgw_ep) { + LOG_CELL(cell, LOGL_DEBUG, "No MGW endpoint, cannot continue.\n"); + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + } + rc = rtp_stream_ensure_ci(cell->rtps, cell->mgw->mgw_ep); + if (rc < 0) { + LOG_CELL(cell, LOGL_DEBUG, "Failed to trigger RTP stream CI.\n"); + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + } + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_CELL_ST_ASSIGNMENT, 0, 0); + break; + case VGCS_CELL_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_CELL(cell, LOGL_DEBUG, "Received clearing from BSS controling process.\n"); + cell_clear(cell, GSM0808_CAUSE_CALL_CONTROL); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_cell_fsm_assignment(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss_cell *cell = fi->priv; + struct ran_msg *rx_ran_msg = data; + struct ran_msg tx_ran_msg; + struct osmo_sockaddr_str ss; + const struct codec_mapping *cm; + struct vgcs_bss *bss; + int rc; + + switch (event) { + case VGCS_CELL_EV_RTP_STREAM_GONE: + /* The RTP stream failed. */ + LOG_CELL(cell, LOGL_ERROR, "RTP stream of MGW failed.\n"); + cell->rtps = NULL; + goto channel_fail; + break; + case VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE: + /* The RTP stream sends its peer. */ + if (!osmo_sockaddr_str_is_nonzero(&cell->rtps->local)) { + LOG_CELL(cell, LOGL_ERROR, "Invalid RTP address received from MGW: " OSMO_SOCKADDR_STR_FMT "\n", + OSMO_SOCKADDR_STR_FMT_ARGS(&cell->rtps->local)); + goto channel_fail; + } + LOG_CELL(cell, LOGL_DEBUG, + "MGW endpoint's RTP address available for the CI %s: " OSMO_SOCKADDR_STR_FMT " (osmux=%s:%d)\n", + rtp_direction_name(cell->rtps->dir), OSMO_SOCKADDR_STR_FMT_ARGS(&cell->rtps->local), + cell->rtps->use_osmux ? "yes" : "no", cell->rtps->local_osmux_cid); + /* Send VGCS/VBS ASSIGNMENT REQUEST to BSS */ + LOG_CELL(cell, LOGL_DEBUG, "Sending VGCS/VBS ASSIGNMENT REQUEST towards BSS.\n"); + tx_ran_msg = (struct ran_msg) { + .msg_type = RAN_MSG_VGCS_VBS_ASSIGN_REQ, + .vgcs_vbs_assign_req = { + /* For now we support GSM/FR V1 only. This shall be supported by all MS. */ + .channel_type = { + .ch_indctr = GSM0808_CHAN_SPEECH, + .ch_rate_type = GSM0808_SPEECH_FULL_BM, + .perm_spch_len = 1, + .perm_spch[0] = GSM0808_PERM_FR1, + }, + /* For now we want a channel without any delay. */ + .ass_req = GSM0808_ASRQ_IMMEDIATE, + .callref = { + .sf = (cell->trans_type == TRANS_GCC), + }, + /* We need to identify the cell only. */ + .cell_identifier = { + .id_discr = CELL_IDENT_CI, + .id.ci = cell->cell_id, + }, + .aoip_transport_layer_present = true, + .call_id_present = true, + .call_id = cell->call_id, + .codec_list_present = true, + .codec_list_msc_preferred = { + .len = 1, + .codec[0] = { + .fi = 1, + .type = GSM0808_SCT_FR1, + .cfg = 0, + }, + }, + }, + }; + osmo_store32be_ext(cell->callref >> 3, &tx_ran_msg.vgcs_vbs_assign_req.callref.call_ref_hi, 3); + tx_ran_msg.vgcs_vbs_assign_req.callref.call_ref_lo = cell->callref & 0x7; + osmo_sockaddr_str_to_sockaddr(&cell->rtps->local, &tx_ran_msg.vgcs_vbs_assign_req.aoip_transport_layer); + /* First message, so we must set "initial" to "true". */ + ran_encode_and_send(fi, &tx_ran_msg, cell->conn, true); + break; + case VGCS_CELL_EV_RTP_STREAM_ESTABLISHED: + /* The RTP stream established. */ + LOG_CELL(cell, LOGL_DEBUG, "RTP stream is established.\n"); + break; + case VGCS_CELL_EV_ASSIGN_RES: + /* Receive VGCS/VBS ASSIGNMENT RESULT from BSS. */ + LOG_CELL(cell, LOGL_DEBUG, "Received VGCS/VBS ASSIGNMENT RESULT from BSS.\n"); + cell->assigned = true; + if (!rx_ran_msg->vgcs_vbs_assign_res.aoip_transport_layer_present + && !rx_ran_msg->vgcs_vbs_assign_res.codec_present + && !rx_ran_msg->vgcs_vbs_assign_res.call_id_present) { + LOG_CELL(cell, LOGL_ERROR, "Mandatory IEs missing.\n"); + goto channel_fail; + } + /* Send remote peer to RTP stream. */ + if (osmo_sockaddr_str_from_sockaddr(&ss, &rx_ran_msg->vgcs_vbs_assign_res.aoip_transport_layer)) { + LOG_CELL(cell, LOGL_ERROR, "Cannot RTP-CONNECT, invalid RTP IP:port in incoming MNCC " + "message\n"); + goto channel_fail; + } + rtp_stream_set_remote_addr(cell->rtps, &ss); + /* Send remote codec to RTP stream. */ + cm = codec_mapping_by_gsm0808_speech_codec_type(rx_ran_msg->vgcs_vbs_assign_res.codec_msc_chosen.type); + if (!cm) { + LOG_CELL(cell, LOGL_ERROR, "Chosen codec by BSC is not supported by MSC.\n"); + goto channel_fail; + } + rtp_stream_set_one_codec(cell->rtps, &cm->sdp); + /* Set listening mode. */ + rtp_stream_set_mode(cell->rtps, MGCP_CONN_SEND_ONLY); + /* Commit RTP stream. */ + rc = rtp_stream_commit(cell->rtps); + if (rc < 0) { + LOG_CELL(cell, LOGL_ERROR, "Failed to commit parameters to RTP stream.\n"); + goto channel_fail; + } + /* Change state. */ + osmo_fsm_inst_state_chg(fi, VGCS_CELL_ST_ACTIVE, 0, 0); + /* Notify BSS FSM about channel activation. */ + if (cell->bss) + osmo_fsm_inst_dispatch(cell->bss->fi, VGCS_BSS_EV_ACTIVE_OR_FAIL, NULL); + break; + case VGCS_CELL_EV_ASSIGN_FAIL: + /* Received VGCS/VBS ASSIGNMENT FAILURE from BSS. */ + LOG_CELL(cell, LOGL_NOTICE, "Received VGCS/VBS ASSIGNMENT FAILURE from BSS.\n"); +channel_fail: + bss = cell->bss; + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + /* Notify BSS FSM about channel failure. */ + if (bss) + osmo_fsm_inst_dispatch(bss->fi, VGCS_BSS_EV_ACTIVE_OR_FAIL, NULL); + break; + case VGCS_CELL_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_CELL(cell, LOGL_DEBUG, "Received clearing from BSS controling process.\n"); + cell_clear(cell, GSM0808_CAUSE_CALL_CONTROL); + break; + case VGCS_CELL_EV_CLOSE: + /* The SCCP connection from the MSC has been closed. */ + LOG_CELL(cell, LOGL_NOTICE, "Received SCCP connecting closing from MSC.\n"); + if (cell->conn) { + cell->conn->vgcs.bss = NULL; + cell->conn = NULL; + } + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_cell_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss_cell *cell = fi->priv; + + switch (event) { + case VGCS_CELL_EV_RTP_STREAM_GONE: + /* The RTP stream failed. */ + LOG_CELL(cell, LOGL_ERROR, "RTP stream of MGW failed.\n"); + cell->rtps = NULL; + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + case VGCS_CELL_EV_RTP_STREAM_ESTABLISHED: + /* The RTP stream established. */ + LOG_CELL(cell, LOGL_DEBUG, "RTP stream is established.\n"); + break; + case VGCS_CELL_EV_CLEAR: + /* The calling user process requested clearing of VGCS/VBS call. */ + LOG_CELL(cell, LOGL_DEBUG, "Received clearing from BSS controling process.\n"); + cell_clear(cell, GSM0808_CAUSE_CALL_CONTROL); + break; + case VGCS_CELL_EV_CLOSE: + /* The SCCP connection from the MSC has been closed. */ + LOG_CELL(cell, LOGL_NOTICE, "Received SCCP connecting closing from MSC.\n"); + if (cell->conn) { + cell->conn->vgcs.bss = NULL; + cell->conn = NULL; + } + cell_clear(cell, GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC); + break; + default: + OSMO_ASSERT(false); + } +} + +static void vgcs_cell_fsm_release(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_bss_cell *cell = fi->priv; + + switch (event) { + case VGCS_CELL_EV_RTP_STREAM_GONE: + /* The RTP stream gone. */ + LOG_CELL(cell, LOGL_ERROR, "RTP stream gone.\n"); + cell->rtps = NULL; + /* Wait for RAN conn. */ + if (cell->conn) + break; + cell_destroy(cell); + break; + case VGCS_CELL_EV_CLEAR: + case VGCS_CELL_EV_RELEASED: + if (event == VGCS_CELL_EV_CLEAR) { + /* The SCCP connection from the MSC has been closed while waiting for CLEAR COMPLETE. */ + LOG_CELL(cell, LOGL_NOTICE, "Received SCCP closing collision.\n"); + } else + LOG_CELL(cell, LOGL_DEBUG, "Received CLEAR COMPLETE from BSS, we are done!\n"); + /* Wait for RTP stream. */ + if (cell->rtps) { + /* close RAN conn */ + if (cell->conn) { + cell->conn->vgcs.cell = NULL; + ran_conn_close(cell->conn); + cell->conn = NULL; + } + break; + } + cell_destroy(cell); + break; + default: + OSMO_ASSERT(false); + } +} + +static const struct osmo_fsm_state vgcs_cell_fsm_states[] = { + [VGCS_CELL_ST_NULL] = { + .name = "NULL", + .in_event_mask = S(VGCS_CELL_EV_ASSIGN) | + S(VGCS_CELL_EV_CLEAR), + .out_state_mask = S(VGCS_CELL_ST_ASSIGNMENT), + .action = vgcs_cell_fsm_null, + }, + [VGCS_CELL_ST_ASSIGNMENT] = { + .name = "ASSIGNMENT Sent", + .in_event_mask = S(VGCS_CELL_EV_RTP_STREAM_GONE) | + S(VGCS_CELL_EV_RTP_STREAM_ADDR_AVAILABLE) | + S(VGCS_CELL_EV_RTP_STREAM_ESTABLISHED) | + S(VGCS_CELL_EV_ASSIGN_RES) | + S(VGCS_CELL_EV_ASSIGN_FAIL) | + S(VGCS_CELL_EV_CLEAR) | + S(VGCS_CELL_EV_CLOSE), + .out_state_mask = S(VGCS_CELL_ST_ACTIVE) | + S(VGCS_CELL_ST_RELEASE), + .action = vgcs_cell_fsm_assignment, + }, + [VGCS_CELL_ST_ACTIVE] = { + .name = "VGCS/VBS channel active", + .in_event_mask = S(VGCS_CELL_EV_RTP_STREAM_GONE) | + S(VGCS_CELL_EV_RTP_STREAM_ESTABLISHED) | + S(VGCS_CELL_EV_CLEAR) | + S(VGCS_CELL_EV_CLOSE), + .out_state_mask = S(VGCS_CELL_ST_RELEASE), + .action = vgcs_cell_fsm_active, + }, + [VGCS_CELL_ST_RELEASE] = { + .name = "Releasing VGCS/VBS channel", + .in_event_mask = S(VGCS_CELL_EV_RTP_STREAM_GONE) | + S(VGCS_CELL_EV_CLEAR) | + S(VGCS_CELL_EV_RELEASED), + .out_state_mask = S(VGCS_CELL_ST_NULL), + .action = vgcs_cell_fsm_release, + }, +}; + +static struct osmo_fsm vgcs_cell_fsm = { + .name = "vgcs_cell", + .states = vgcs_cell_fsm_states, + .num_states = ARRAY_SIZE(vgcs_cell_fsm_states), + .log_subsys = DASCI, + .event_names = vgcs_cell_fsm_event_names, +}; + +/* The BSS accepts VGCS/VBS channel assignment. */ +void vgcs_vbs_assign_result(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg) +{ + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_ASSIGN_RES, (void *)ran_msg); +} + +/* The BSS refuses VGCS/VBS channel assignment. */ +void vgcs_vbs_assign_fail(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg) +{ + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_ASSIGN_FAIL, (void *)ran_msg); +} + +/* BSS indicated that the channel has been released. */ +void vgcs_vbs_clear_req_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg) +{ + LOG_CELL(cell, LOGL_DEBUG, "Received CLEAR REQUEST for resource controling channel from BSS.\n"); + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_CLOSE, (void *)ran_msg); +} + +/* BSS confirms the release of channel. */ +void vgcs_vbs_clear_cpl_channel(struct vgcs_bss_cell *cell, const struct ran_msg *ran_msg) +{ + LOG_CELL(cell, LOGL_DEBUG, "Received CLEAR COMPLETE for resource controling channel from BSS.\n"); + osmo_fsm_inst_dispatch(cell->fi, VGCS_CELL_EV_RELEASED, (void *)ran_msg); +} + +/* + * MGW endpoint FSM + */ + +static const struct value_string vgcs_mgw_ep_fsm_event_names[] = { + OSMO_VALUE_STRING(VGCS_MGW_EP_EV_FREE), + OSMO_VALUE_STRING(VGCS_MGW_EP_EV_CLEAR), + { } +}; + +static void vgcs_mgw_ep_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct vgcs_mgw_ep *mgw = fi->priv; + struct vgcs_bss_cell *cell, *cell2; + struct mgcp_client *mgcp_client; + + switch (event) { + case VGCS_MGW_EP_EV_FREE: + LOGP(DASCI, LOGL_DEBUG, "MGW connection closed, removing all cell instances.\n"); + llist_for_each_entry_safe(cell, cell2, &mgw->cell_list, list_mgw) { + if (cell->rtps) + cell->rtps->ci = NULL; + llist_del(&cell->list_mgw); + cell->mgw = NULL; + } + /* Put MGCP client back into MGW pool. */ + mgcp_client = osmo_mgcpc_ep_client(mgw->mgw_ep); + mgcp_client_pool_put(mgcp_client); + /* Destroy this instance. */ + osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL); + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); + break; + case VGCS_MGW_EP_EV_CLEAR: + if (!llist_empty(&mgw->cell_list)) + break; + LOGP(DASCI, LOGL_DEBUG, "Cell list of MGW instance is now empty, dropping.\n"); + /* Destroy this instance. */ + osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL); + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); + break; + default: + OSMO_ASSERT(false); + } +} + +static const struct osmo_fsm_state vgcs_mgw_ep_fsm_states[] = { + [VGCS_MGW_EP_ST_NULL] = { + .name = "NULL", + .out_state_mask = S(VGCS_MGW_EP_ST_ACTIVE), + }, + [VGCS_MGW_EP_ST_ACTIVE] = { + .name = "MGW endpoint allocated", + .in_event_mask = S(VGCS_MGW_EP_EV_FREE) | + S(VGCS_MGW_EP_EV_CLEAR), + .out_state_mask = S(VGCS_MGW_EP_ST_NULL), + .action = vgcs_mgw_ep_fsm_active, + }, +}; + +static struct osmo_fsm vgcs_mgw_ep_fsm = { + .name = "vgcs_mgw_ep", + .states = vgcs_mgw_ep_fsm_states, + .num_states = ARRAY_SIZE(vgcs_mgw_ep_fsm_states), + .log_subsys = DASCI, + .event_names = vgcs_mgw_ep_fsm_event_names, +}; diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index 4dd834b36..1f389f455 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -1,5 +1,5 @@ /* MSC interface to quagga VTY */ -/* (C) 2016-2018 by sysmocom s.m.f.c. GmbH <info@sysmocom.de> +/* (C) 2016-2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c) * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org> * (C) 2009-2011 by Holger Hans Peter Freyther @@ -68,6 +68,7 @@ #include <osmocom/msc/sccp_ran.h> #include <osmocom/msc/ran_peer.h> #include <osmocom/msc/ran_infra.h> +#include <osmocom/msc/asci_vty.h> static struct gsm_network *gsmnet = NULL; @@ -131,19 +132,23 @@ DEFUN(cfg_net_mnc, DEFUN(cfg_net_name_short, cfg_net_name_short_cmd, - "short name NAME", + "short name .NAME", "Set the short GSM network name\n" NAME_CMD_STR NAME_STR) { - osmo_talloc_replace_string(gsmnet, &gsmnet->name_short, argv[0]); + if (gsmnet->name_short != NULL) + talloc_free(gsmnet->name_short); + gsmnet->name_short = argv_concat(argv, argc, 0); return CMD_SUCCESS; } DEFUN(cfg_net_name_long, cfg_net_name_long_cmd, - "long name NAME", + "long name .NAME", "Set the long GSM network name\n" NAME_CMD_STR NAME_STR) { - osmo_talloc_replace_string(gsmnet, &gsmnet->name_long, argv[0]); + if (gsmnet->name_long != NULL) + talloc_free(gsmnet->name_long); + gsmnet->name_long = argv_concat(argv, argc, 0); return CMD_SUCCESS; } @@ -390,6 +395,8 @@ static int config_write_net(struct vty *vty) if (!gsmnet->call_waiting) vty_out(vty, " no call-waiting%s", VTY_NEWLINE); + mgcp_client_pool_config_write(vty, " "); + return CMD_SUCCESS; } @@ -410,12 +417,12 @@ DEFUN(cfg_msc, cfg_msc_cmd, #define MNCC_GUARD_TIMEOUT_STR "Set global guard timer for mncc interface activity\n" #define MNCC_GUARD_TIMEOUT_VALUE_STR "guard timer value (sec.)\n" -DEFUN(cfg_sms_database, cfg_sms_database_cmd, +DEFUN_DEPRECATED(cfg_sms_database, cfg_sms_database_cmd, "sms-database PATH", "Set the path to the MSC-SMS database file\n" "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n") { - osmo_talloc_replace_string(gsmnet, &gsmnet->sms_db_file_path, argv[0]); + osmo_talloc_replace_string(gsmnet, &gsmnet->sms_queue_cfg->db_file_path, argv[0]); return CMD_SUCCESS; } @@ -754,10 +761,10 @@ DEFUN(show_nri, show_nri_cmd, static int config_write_msc(struct vty *vty) { vty_out(vty, "msc%s", VTY_NEWLINE); - if (gsmnet->sms_db_file_path && strcmp(gsmnet->sms_db_file_path, SMS_DEFAULT_DB_FILE_PATH)) - vty_out(vty, " sms-database %s%s", gsmnet->sms_db_file_path, VTY_NEWLINE); if (gsmnet->mncc_sock_path) vty_out(vty, " mncc external %s%s", gsmnet->mncc_sock_path, VTY_NEWLINE); + else + vty_out(vty, " mncc internal%s", VTY_NEWLINE); vty_out(vty, " mncc guard-timeout %i%s", gsmnet->mncc_guard_timeout, VTY_NEWLINE); vty_out(vty, " ncss guard-timeout %i%s", @@ -1860,51 +1867,6 @@ DEFUN(show_stats, return CMD_SUCCESS; } -DEFUN(show_smsqueue, - show_smsqueue_cmd, - "show sms-queue", - SHOW_STR "Display SMSqueue statistics\n") -{ - sms_queue_stats(gsmnet->sms_queue, vty); - return CMD_SUCCESS; -} - -DEFUN(smsqueue_trigger, - smsqueue_trigger_cmd, - "sms-queue trigger", - "SMS Queue\n" "Trigger sending messages\n") -{ - sms_queue_trigger(gsmnet->sms_queue); - return CMD_SUCCESS; -} - -DEFUN(smsqueue_max, - smsqueue_max_cmd, - "sms-queue max-pending <1-500>", - "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n") -{ - sms_queue_set_max_pending(gsmnet->sms_queue, atoi(argv[0])); - return CMD_SUCCESS; -} - -DEFUN(smsqueue_clear, - smsqueue_clear_cmd, - "sms-queue clear", - "SMS Queue\n" "Clear the queue of pending SMS\n") -{ - sms_queue_clear(gsmnet->sms_queue); - return CMD_SUCCESS; -} - -DEFUN(smsqueue_fail, - smsqueue_fail_cmd, - "sms-queue max-failure <1-500>", - "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n") -{ - sms_queue_set_max_failure(gsmnet->sms_queue, atoi(argv[0])); - return CMD_SUCCESS; -} - DEFUN(cfg_mncc_int, cfg_mncc_int_cmd, "mncc-int", "Configure internal MNCC handler") @@ -2031,7 +1993,7 @@ DEFUN(cfg_hlr_ipa_name, "Set the IPA name of this MSC\n" "A unique name for this MSC. For example: PLMN + redundancy server number: MSC-901-70-0. " "This name is used for GSUP routing and must be set if more than one MSC is connected to the HLR. " - "The default is 'MSC-00-00-00-00-00-00'.\n") + "The default is 'unnamed-MSC'.\n") { if (vty->type != VTY_FILE) { vty_out(vty, "The IPA name cannot be changed at run-time; " @@ -2080,6 +2042,8 @@ void msc_vty_init(struct gsm_network *msc_network) install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd); install_element(GSMNET_NODE, &cfg_net_call_wait_cmd); install_element(GSMNET_NODE, &cfg_net_no_call_wait_cmd); + mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, NULL, msc_network->mgw.mgw_pool); + install_element(CONFIG_NODE, &cfg_msc_cmd); install_node(&msc_node, config_write_msc); @@ -2113,11 +2077,15 @@ void msc_vty_init(struct gsm_network *msc_network) /* Timer configuration commands (generic osmo_tdef API) */ osmo_tdef_vty_groups_init(MSC_NODE, msc_tdef_group); - mgcp_client_vty_init(msc_network, MSC_NODE, &msc_network->mgw.conf); + /* Deprecated: Old MGCP config without pooling support in MSC node: */ + mgcp_client_vty_init(msc_network, MSC_NODE, msc_network->mgw.conf); + #ifdef BUILD_IU ranap_iu_vty_init(MSC_NODE, (enum ranap_nsap_addr_enc*)&msc_network->iu.rab_assign_addr_enc); #endif sgs_vty_init(); + smsc_vty_init(msc_network); + asci_vty_init(msc_network); osmo_fsm_vty_add_cmds(); @@ -2143,14 +2111,9 @@ void msc_vty_init(struct gsm_network *msc_network) install_element_ve(&subscriber_mstest_open_cmd); install_element_ve(&subscriber_paging_cmd); install_element_ve(&show_stats_cmd); - install_element_ve(&show_smsqueue_cmd); install_element_ve(&logging_fltr_imsi_cmd); install_element(ENABLE_NODE, &ena_subscr_expire_cmd); - install_element(ENABLE_NODE, &smsqueue_trigger_cmd); - install_element(ENABLE_NODE, &smsqueue_max_cmd); - install_element(ENABLE_NODE, &smsqueue_clear_cmd); - install_element(ENABLE_NODE, &smsqueue_fail_cmd); install_element(ENABLE_NODE, &subscriber_send_pending_sms_cmd); install_element(ENABLE_NODE, &subscriber_sms_delete_all_cmd); diff --git a/src/libmsc/msub.c b/src/libmsc/msub.c index 112703a13..ac93665a7 100644 --- a/src/libmsc/msub.c +++ b/src/libmsc/msub.c @@ -1,6 +1,6 @@ /* Manage all MSC roles of a connected subscriber (MSC-A, MSC-I, MSC-T) */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -544,6 +544,8 @@ void msc_role_forget_conn(struct osmo_fsm_inst *role, struct ran_conn *conn) *conn_p = NULL; } +/* NOTE: the resulting message buffer will be attached to OTC_SELECT, so its lifetime + * is limited by the current select() loop iteration. Use talloc_steal() to avoid this. */ struct msgb *msc_role_ran_encode(struct osmo_fsm_inst *fi, const struct ran_msg *ran_msg) { struct msc_role_common *c = fi->priv; @@ -556,6 +558,8 @@ struct msgb *msc_role_ran_encode(struct osmo_fsm_inst *fi, const struct ran_msg msg = c->ran->ran_encode(fi, ran_msg); if (!msg) LOGPFSML(fi, LOGL_ERROR, "Failed to encode %s\n", ran_msg_type_name(ran_msg->msg_type)); + else + talloc_steal(OTC_SELECT, msg); return msg; } diff --git a/src/libmsc/neighbor_ident.c b/src/libmsc/neighbor_ident.c index 5120e168e..b3cdf17c4 100644 --- a/src/libmsc/neighbor_ident.c +++ b/src/libmsc/neighbor_ident.c @@ -1,6 +1,6 @@ /* Manage identity of neighboring BSS cells for inter-MSC handover. */ /* - * (C) 2018-2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2018-2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/paging.c b/src/libmsc/paging.c index 8fbe81097..9b3dad5d2 100644 --- a/src/libmsc/paging.c +++ b/src/libmsc/paging.c @@ -1,5 +1,5 @@ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -120,6 +120,34 @@ struct paging_request *paging_request_start(struct vlr_subscr *vsub, enum paging return pr; } +/* Two subscribers (e.g. an old TMSI and a new TMSI) turn out to have the same identity, so in order to discard one of + * them, transfer any pending Paging requests to the vsub that will survive. */ +void paging_request_join_vsub(struct vlr_subscr *keep_vsub, struct vlr_subscr *discarding_vsub) +{ + struct paging_request *pr; + + if (!discarding_vsub->cs.is_paging) + return; + + /* transfer all Paging Response callbacks */ + while ((pr = llist_first_entry_or_null(&discarding_vsub->cs.requests, struct paging_request, entry))) { + llist_del(&pr->entry); + talloc_steal(keep_vsub, pr); + llist_add_tail(&pr->entry, &keep_vsub->cs.requests); + } + + /* make sure a Paging use count is present on keep_vsub, if needed */ + if (!keep_vsub->cs.is_paging && !llist_empty(&keep_vsub->cs.requests)) { + vlr_subscr_get(keep_vsub, VSUB_USE_PAGING); + keep_vsub->cs.is_paging = true; + } + + /* Already made sure at the top of this function that discarding_vsub->cs.is_paging == true */ + discarding_vsub->cs.is_paging = false; + osmo_timer_del(&discarding_vsub->cs.paging_response_timer); + vlr_subscr_put(discarding_vsub, VSUB_USE_PAGING); +} + void paging_request_remove(struct paging_request *pr) { struct gsm_trans *trans = pr->trans; diff --git a/src/libmsc/ran_conn.c b/src/libmsc/ran_conn.c index 8418c9eb5..07638016a 100644 --- a/src/libmsc/ran_conn.c +++ b/src/libmsc/ran_conn.c @@ -1,7 +1,7 @@ /* MSC RAN connection implementation */ /* - * (C) 2016-2018 by sysmocom s.m.f.c. <info@sysmocom.de> + * (C) 2016-2018 by sysmocom s.f.m.c. <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr diff --git a/src/libmsc/ran_infra.c b/src/libmsc/ran_infra.c index c0eaa1ac2..6a178403f 100644 --- a/src/libmsc/ran_infra.c +++ b/src/libmsc/ran_infra.c @@ -1,6 +1,6 @@ /* Lookup table for various RAN implementations */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -108,6 +108,16 @@ struct ran_infra msc_ran_infra[] = { .ran_dec_l2 = ran_iu_decode_l2, .ran_encode = ran_iu_encode, #endif + .force_mgw_codecs_to_ran = { + .count = 1, + .codec = { + { + .payload_type = 96, + .subtype_name = "VND.3GPP.IUFP", + .rate = 16000, + }, + }, + }, }, [OSMO_RAT_EUTRAN_SGS] = { .type = OSMO_RAT_EUTRAN_SGS, diff --git a/src/libmsc/ran_msg.c b/src/libmsc/ran_msg.c index 46816a961..3e4b20c50 100644 --- a/src/libmsc/ran_msg.c +++ b/src/libmsc/ran_msg.c @@ -1,25 +1,21 @@ /* Common bits for RAN message handling */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <osmocom/core/utils.h> @@ -55,6 +51,25 @@ const struct value_string ran_msg_type_names[] = { { RAN_MSG_HANDOVER_DETECT, "HANDOVER_DETECT" }, { RAN_MSG_HANDOVER_COMPLETE, "HANDOVER_COMPLETE" }, { RAN_MSG_HANDOVER_FAILURE, "HANDOVER_FAILURE" }, + { RAN_MSG_VGCS_VBS_SETUP, "VGCS_VBS_SETUP" }, + { RAN_MSG_VGCS_VBS_SETUP_ACK, "VGCS_VBS_SETUP_ACK" }, + { RAN_MSG_VGCS_VBS_SETUP_REFUSE, "VGCS_VBS_SETUP_REFUSE" }, + { RAN_MSG_VGCS_VBS_ASSIGN_REQ, "VGCS_VBS_ASSIGN_REQ" }, + { RAN_MSG_VGCS_VBS_ASSIGN_RES, "VGCS_VBS_ASSIGN_RES" }, + { RAN_MSG_VGCS_VBS_ASSIGN_FAIL, "VGCS_VBS_ASSIGN_FAIL" }, + { RAN_MSG_VGCS_VBS_QUEUING_IND, "VGCS_VBS_QUEUING_IND" }, + { RAN_MSG_UPLINK_REQUEST, "UPLINK_REQUEST" }, + { RAN_MSG_UPLINK_REQUEST_ACK, "UPLINK_REQUEST_ACK" }, + { RAN_MSG_UPLINK_REQUEST_CNF, "UPLINK_REQUEST_CNF" }, + { RAN_MSG_UPLINK_APPLICATION_DATA, "UPLINK_APPLICATION_DATA" }, + { RAN_MSG_UPLINK_RELEASE_IND, "UPLINK_RELEASE_IND" }, + { RAN_MSG_UPLINK_REJECT_CMD, "UPLINK_REJECT_CMD" }, + { RAN_MSG_UPLINK_RELEASE_CMD, "UPLINK_RELEASE_CMD" }, + { RAN_MSG_UPLINK_SEIZED_CMD, "UPLINK_SEIZED_CMD" }, + { RAN_MSG_VGCS_ADDITIONAL_INFO, "VGCS_ADDITIONAL_INFO" }, + { RAN_MSG_VGCS_VBS_AREA_CELL_INFO, "VGCS_VBS_AREA_CELL_INFO" }, + { RAN_MSG_VGCS_VBS_ASSIGN_STATUS, "VGCS_VBS_ASSIGN_STATUS" }, + { RAN_MSG_VGCS_SMS, "VGCS_SMS" }, {} }; diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c index b50259d04..d9041204a 100644 --- a/src/libmsc/ran_msg_a.c +++ b/src/libmsc/ran_msg_a.c @@ -1,25 +1,21 @@ /* BSSAP/BSSMAP encoding and decoding for MSC */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <osmocom/core/byteswap.h> @@ -108,7 +104,7 @@ static int ran_a_decode_l3_compl(struct ran_dec *ran_dec, struct msgb *msg, stru .id = cil.id_list[0], }; - /* Parse Layer 3 Information element */ + /* Parse Layer 3 Information element; point ran_dec_msg->compl_l3.msg to the L3 Info data */ msg->l3h = (uint8_t*)ie_l3_info->val; msgb_l3trim(msg, ie_l3_info->len); @@ -242,34 +238,26 @@ enum mgcp_codecs ran_a_mgcp_codec_from_sc(const struct gsm0808_speech_codec *sc) switch (sc->type) { case GSM0808_SCT_FR1: return CODEC_GSM_8000_1; - break; case GSM0808_SCT_FR2: return CODEC_GSMEFR_8000_1; - break; case GSM0808_SCT_FR3: return CODEC_AMR_8000_1; - break; case GSM0808_SCT_FR4: return CODEC_AMRWB_16000_1; - break; case GSM0808_SCT_FR5: return CODEC_AMRWB_16000_1; - break; case GSM0808_SCT_HR1: return CODEC_GSMHR_8000_1; - break; case GSM0808_SCT_HR3: return CODEC_AMR_8000_1; - break; case GSM0808_SCT_HR4: return CODEC_AMRWB_16000_1; - break; case GSM0808_SCT_HR6: return CODEC_AMRWB_16000_1; - break; + case GSM0808_SCT_CSD: + return CODEC_CLEARMODE; default: return CODEC_PCMU_8000_1; - break; } } @@ -280,7 +268,6 @@ static int ran_a_decode_assignment_complete(struct ran_dec *ran_dec, struct msgb struct tlv_p_entry *ie_codec_list_bss_supported = TLVP_GET(tp, GSM0808_IE_SPEECH_CODEC_LIST); struct tlv_p_entry *ie_osmux_cid = TLVP_GET(tp, GSM0808_IE_OSMO_OSMUX_CID); struct sockaddr_storage rtp_addr; - struct gsm0808_speech_codec sc; struct gsm0808_speech_codec_list codec_list_bss_supported; int rc; struct ran_msg ran_dec_msg = { @@ -313,14 +300,14 @@ static int ran_a_decode_assignment_complete(struct ran_dec *ran_dec, struct msgb if (ie_speech_codec) { /* Decode Speech Codec (Chosen) element */ - rc = gsm0808_dec_speech_codec(&sc, ie_speech_codec->val, ie_speech_codec->len); + rc = gsm0808_dec_speech_codec(&ran_dec_msg.assignment_complete.codec, + ie_speech_codec->val, ie_speech_codec->len); if (rc < 0) { LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Assignment Complete: unable to decode IE Speech Codec (Chosen)" " (rc=%d).\n", rc); return -EINVAL; } ran_dec_msg.assignment_complete.codec_present = true; - ran_dec_msg.assignment_complete.codec = ran_a_mgcp_codec_from_sc(&sc); } if (ie_codec_list_bss_supported) { @@ -676,13 +663,12 @@ static int ran_a_decode_handover_request_ack(struct ran_dec *ran_dec, const stru } if (ie_chosen_speech_version) { - struct gsm0808_speech_codec sc; ran_dec_msg.handover_request_ack.chosen_speech_version = ie_chosen_speech_version->val[0]; /* the codec may be extrapolated from this Speech Version or below from Speech Codec */ - gsm0808_speech_codec_from_chan_type(&sc, ran_dec_msg.handover_request_ack.chosen_speech_version); - ran_dec_msg.handover_request_ack.codec_present = true; - ran_dec_msg.handover_request_ack.codec = ran_a_mgcp_codec_from_sc(&sc); + if (gsm0808_speech_codec_from_chan_type(&ran_dec_msg.handover_request_ack.codec, + ran_dec_msg.handover_request_ack.chosen_speech_version) == 0) + ran_dec_msg.handover_request_ack.codec_present = true; } if (ie_aoip_transp_addr) { @@ -697,14 +683,12 @@ static int ran_a_decode_handover_request_ack(struct ran_dec *ran_dec, const stru } if (ie_speech_codec) { - struct gsm0808_speech_codec sc; - if (gsm0808_dec_speech_codec(&sc, ie_speech_codec->val, ie_speech_codec->len) < 0) + /* the codec may be extrapolated from above Speech Version or from this Speech Codec */ + if (gsm0808_dec_speech_codec(&ran_dec_msg.handover_request_ack.codec, + ie_speech_codec->val, ie_speech_codec->len) < 0) LOG_RAN_A_DEC_MSG(LOGL_ERROR, "unable to decode IE Speech Codec (Chosen)\n"); - else { - /* the codec may be extrapolated from above Speech Version or from this Speech Codec */ + else ran_dec_msg.handover_request_ack.codec_present = true; - ran_dec_msg.handover_request_ack.codec = ran_a_mgcp_codec_from_sc(&sc); - } } return ran_decoded(ran_dec, &ran_dec_msg); @@ -750,6 +734,439 @@ static int ran_a_decode_handover_failure(struct ran_dec *ran_dec, const struct m return ran_decoded(ran_dec, &ran_dec_msg); } +static int ran_a_decode_vgcs_vbs_setup_ack(struct ran_dec *ran_dec, const struct msgb *msg, const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_SETUP_ACK, + .msg_name = "BSSMAP VGCS/VBS SETUP ACKNOWLEDGE", + }; + struct gsm0808_vgcs_vbs_setup_ack *r = &ran_dec_msg.vgcs_vbs_setup_ack; + int rc; + + const struct tlv_p_entry *ie_flags = TLVP_GET(tp, GSM0808_IE_VGCS_FEATURE_FLAGS); + + /* VGCS Feature Flags, 3.2.2.88 */ + if (ie_flags) { + rc = gsm0808_dec_vgcs_feature_flags(&r->flags, ie_flags->val, ie_flags->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Unable to decode VGCS/VBS Feature Flags\n"); + return -EINVAL; + } + r->vgcs_feature_flags_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_vgcs_vbs_setup_refuse(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_SETUP_REFUSE, + .msg_name = "BSSMAP VGCS/VBS SETUP REFUSE", + }; + + const struct tlv_p_entry *ie_cause = TLVP_GET(tp, GSM0808_IE_CAUSE); + + /* Cause, 3.2.2.5 */ + if (!ie_cause || ie_cause->len < 1) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cause\n"); + return -EINVAL; + } + ran_dec_msg.vgcs_vbs_setup_refuse.cause = ie_cause->val[0]; + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_vgcs_vbs_assign_res(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_ASSIGN_RES, + .msg_name = "BSSMAP VGCS/VBS ASSIGNMENT RESULT", + }; + struct gsm0808_vgcs_vbs_assign_res *r = &ran_dec_msg.vgcs_vbs_assign_res; + int rc; + + const struct tlv_p_entry *ie_channel_type = TLVP_GET(tp, GSM0808_IE_CHANNEL_TYPE); + const struct tlv_p_entry *ie_cell_id = TLVP_GET(tp, GSM0808_IE_CELL_IDENTIFIER); + const struct tlv_p_entry *ie_chosen_channel = TLVP_GET(tp, GSM0808_IE_CHOSEN_CHANNEL); + const struct tlv_p_entry *ie_cic = TLVP_GET(tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE); + const struct tlv_p_entry *ie_circuit_pool = TLVP_GET(tp, GSM0808_IE_CIRCUIT_POOL); + const struct tlv_p_entry *ie_aoip = TLVP_GET(tp, GSM0808_IE_AOIP_TRASP_ADDR); + const struct tlv_p_entry *ie_call_id = TLVP_GET(tp, GSM0808_IE_CALL_ID); + + /* Channel Type, 3.2.2.11 */ + if (!ie_channel_type) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Channel Type\n"); + return -EINVAL; + } + if (gsm0808_dec_channel_type(&r->channel_type, ie_channel_type->val, ie_channel_type->len) <= 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Failed to decode Channel Type IE\n"); + return -EINVAL; + } + + /* Cell Identifier, 3.2.2.17 */ + if (!ie_cell_id) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cell Identifier\n"); + return -EINVAL; + } + rc = gsm0808_dec_cell_id(&r->cell_identifier, ie_cell_id->val, ie_cell_id->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + + /* Chosen Channel, 3.2.2.33 */ + if (ie_chosen_channel) { + r->chosen_channel = ie_chosen_channel->val[0]; + r->chosen_channel_present = true; + } + + /* Circuit Identity Code, 3.2.2.2 */ + if (ie_cic) { + if (ie_cic->len != 2) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Circuit Identity Code has invalid length.\n"); + return -EINVAL; + } + r->cic = *(uint16_t *)ie_cic->val; + r->cic_present = true; + } + + /* Circuit Pool, 3.2.2.45 */ + if (ie_circuit_pool) { + r->circuit_pool = ie_circuit_pool->val[0]; + r->circuit_pool_present = true; + } + + /* AoIP Transport Layer Address (BSS), 3.2.2.102 */ + if (ie_aoip) { + if (gsm0808_dec_aoip_trasp_addr(&r->aoip_transport_layer, ie_aoip->val, ie_aoip->len) < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "unable to decode AoIP transport address\n"); + return -EINVAL; + } + r->aoip_transport_layer_present = true; + } + + if (ie_call_id) { + if (ie_call_id->len != 4) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Call Identifier has invalid length.\n"); + return -EINVAL; + } + r->call_id = osmo_load32le(ie_call_id->val); + r->call_id_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_vgcs_vbs_assign_fail(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_ASSIGN_FAIL, + .msg_name = "BSSMAP VGCS/VBS ASSIGNMENT FAILURE", + }; + struct gsm0808_vgcs_vbs_assign_fail *r = &ran_dec_msg.vgcs_vbs_assign_fail; + int rc; + + const struct tlv_p_entry *ie_cause = TLVP_GET(tp, GSM0808_IE_CAUSE); + const struct tlv_p_entry *ie_circuit_pool = TLVP_GET(tp, GSM0808_IE_CIRCUIT_POOL); + const struct tlv_p_entry *ie_circuit_pool_list = TLVP_GET(tp, GSM0808_IE_CIRCUIT_POOL_LIST); + const struct tlv_p_entry *ie_codec_list_bss_supported = TLVP_GET(tp, GSM0808_IE_SPEECH_CODEC_LIST); + + /* Cause, 3.2.2.5 */ + if (!ie_cause || ie_cause->len < 1) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cause\n"); + return -EINVAL; + } + r->cause = ie_cause->val[0]; + + /* Circuit Pool, 3.2.2.45 */ + if (ie_circuit_pool) { + r->circuit_pool = ie_circuit_pool->val[0]; + r->circuit_pool_present = true; + } + + /* Circuit Pool List, 3.2.2.46 */ + if (ie_circuit_pool_list && ie_circuit_pool_list->len) { + if (ie_circuit_pool_list->len > CIRCUIT_POOL_LIST_MAXLEN) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Circuit Pool List has invalid length.\n"); + return -EINVAL; + } + memcpy(r->cpl.pool, ie_circuit_pool_list->val, ie_circuit_pool_list->len); + r->cpl.list_len = ie_circuit_pool_list->len; + r->cpl_present = true; + } + + /* Codec List (BSS Supported) 3.2.2.103 */ + if (ie_codec_list_bss_supported) { + rc = gsm0808_dec_speech_codec_list(&r->codec_list_bss_supported, + ie_codec_list_bss_supported->val, ie_codec_list_bss_supported->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, + "Complete Layer 3 Information: unable to decode IE Codec List (BSS Supported)" + " (rc=%d), continuing anyway\n", rc); + /* This IE is not critical, do not abort with error. */ + } else + r->codec_list_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_vgcs_vbs_queuing_ind(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_QUEUING_IND, + .msg_name = "BSSMAP VGCS/VBS QUEUING INDICATION", + }; + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_uplink_request(struct ran_dec *ran_dec, const struct msgb *msg, const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_UPLINK_REQUEST, + .msg_name = "BSSMAP UPLINK REQUEST", + }; + struct gsm0808_uplink_request *r = &ran_dec_msg.uplink_request; + int rc; + + const struct tlv_p_entry *ie_talker_priority = TLVP_GET(tp, GSM0808_IE_TALKER_PRIORITY); + const struct tlv_p_entry *ie_cell_id = TLVP_GET(tp, GSM0808_IE_CELL_IDENTIFIER); + const struct tlv_p_entry *ie_l3_info = TLVP_GET(tp, GSM0808_IE_LAYER_3_INFORMATION); + const struct tlv_p_entry *ie_mi = TLVP_GET(tp, GSM0808_IE_MOBILE_IDENTITY); + + /* Talker Priority, 3.2.2.89 */ + if (ie_talker_priority) { + r->talker_priority = ie_talker_priority->val[0] & 0x03; + r->talker_priority_present = true; + } + + /* Cell Identifier, 3.2.2.17 */ + if (ie_cell_id) { + rc = gsm0808_dec_cell_id(&r->cell_identifier, ie_cell_id->val, ie_cell_id->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + } + + /* Layer 3 Information, 3.2.2.24 */ + if (ie_l3_info && ie_l3_info->len) { + if (ie_l3_info->len > LAYER_3_INFORMATION_MAXLEN) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Call Identifier has invalid length.\n"); + return -EINVAL; + } + memcpy(r->l3.l3, ie_l3_info->val, ie_l3_info->len); + r->l3.l3_len = ie_l3_info->len; + r->l3_present = true; + } + + /* Mobile Identity, 3.2.2.41 */ + if (ie_mi) { + rc = osmo_mobile_identity_decode(&r->mi, ie_mi->val, ie_mi->len, false); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Mobile Identity gave rc=%d\n", rc); + return -EINVAL; + } + r->mi_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_uplink_request_cnf(struct ran_dec *ran_dec, const struct msgb *msg, const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_UPLINK_REQUEST_CNF, + .msg_name = "BSSMAP UPLINK REQUEST CONFIRM", + }; + struct gsm0808_uplink_request_cnf *r = &ran_dec_msg.uplink_request_cnf; + int rc; + + const struct tlv_p_entry *ie_cell_id = TLVP_GET(tp, GSM0808_IE_CELL_IDENTIFIER); + const struct tlv_p_entry *ie_talker_identity = TLVP_GET(tp, GSM0808_IE_TALKER_IDENTITY); + const struct tlv_p_entry *ie_l3_info = TLVP_GET(tp, GSM0808_IE_LAYER_3_INFORMATION); + + /* Cell Identifier, 3.2.2.17 */ + if (!ie_cell_id) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cell Identifier\n"); + return -EINVAL; + } + rc = gsm0808_dec_cell_id(&r->cell_identifier, ie_cell_id->val, ie_cell_id->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + + /* Talker Identity, 3.2.2.91 */ + if (ie_talker_identity) { + rc = gsm0808_dec_talker_identity(&r->talker_identity, ie_talker_identity->val, ie_talker_identity->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Talker Identity gave rc=%d\n", rc); + return -EINVAL; + } + r->talker_identity_present = true; + } + + /* Layer 3 Information, 3.2.2.24 */ + if (!ie_l3_info) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Layer 3 Information\n"); + return -EINVAL; + } + if (ie_l3_info->len > LAYER_3_INFORMATION_MAXLEN) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Call Identifier has invalid length.\n"); + return -EINVAL; + } + memcpy(r->l3.l3, ie_l3_info->val, ie_l3_info->len); + r->l3.l3_len = ie_l3_info->len; + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_uplink_application_data(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_UPLINK_APPLICATION_DATA, + .msg_name = "BSSMAP UPLINK APPLICATION DATA", + }; + struct gsm0808_uplink_app_data *r = &ran_dec_msg.uplink_app_data; + int rc; + + const struct tlv_p_entry *ie_cell_id = TLVP_GET(tp, GSM0808_IE_CELL_IDENTIFIER); + const struct tlv_p_entry *ie_l3_info = TLVP_GET(tp, GSM0808_IE_LAYER_3_INFORMATION); + const struct tlv_p_entry *ie_app_data = TLVP_GET(tp, GSM0808_IE_APP_DATA); + + /* Cell Identifier, 3.2.2.17 */ + if (!ie_cell_id) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cell Identifier\n"); + return -EINVAL; + } + rc = gsm0808_dec_cell_id(&r->cell_identifier, ie_cell_id->val, ie_cell_id->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + + /* Layer 3 Information, 3.2.2.24 */ + if (!ie_l3_info) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Layer 3 Information\n"); + return -EINVAL; + } + if (ie_l3_info->len > LAYER_3_INFORMATION_MAXLEN) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Call Identifier has invalid length.\n"); + return -EINVAL; + } + memcpy(r->l3.l3, ie_l3_info->val, ie_l3_info->len); + r->l3.l3_len = ie_l3_info->len; + + /* Application Data Information, 3.2.2.100 */ + if (!ie_app_data || ie_app_data->len < 1) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Application Data Information\n"); + return -EINVAL; + } + r->bt_ind = ie_app_data->val[0] & 0x01; + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_uplink_release_ind(struct ran_dec *ran_dec, const struct msgb *msg, const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_UPLINK_RELEASE_IND, + .msg_name = "BSSMAP UPLINK RELEASE INDICATION", + }; + struct gsm0808_uplink_release_ind *r = &ran_dec_msg.uplink_release_ind; + + const struct tlv_p_entry *ie_cause = TLVP_GET(tp, GSM0808_IE_CAUSE); + const struct tlv_p_entry *ie_talker_priority = TLVP_GET(tp, GSM0808_IE_TALKER_PRIORITY); + + /* Cause, 3.2.2.5 */ + if (!ie_cause || ie_cause->len < 1) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Mandatory IE missing: Cause\n"); + return -EINVAL; + } + r->cause = ie_cause->val[0]; + + /* Talker Priority, 3.2.2.89 */ + if (ie_talker_priority) { + r->talker_priority = ie_talker_priority->val[0] & 0x03; + r->talker_priority_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + +static int ran_a_decode_vgcs_vbs_assign_status(struct ran_dec *ran_dec, const struct msgb *msg, + const struct tlv_parsed *tp) +{ + struct ran_msg ran_dec_msg = { + .msg_type = RAN_MSG_VGCS_VBS_ASSIGN_STATUS, + .msg_name = "BSSMAP VGCS/VBS ASSIGNMENT STATUS", + }; + struct gsm0808_vgcs_vbs_assign_stat *r = &ran_dec_msg.vgcs_vbs_assign_stat; + int rc; + + const struct tlv_p_entry *ie_cils_est = TLVP_GET(tp, GSM0808_IE_CELL_ID_LIST_SEG_EST_CELLS); + const struct tlv_p_entry *ie_cils_tbe = TLVP_GET(tp, GSM0808_IE_CELL_ID_LIST_SEG_CELLS_TBE); + const struct tlv_p_entry *ie_cils_rel = TLVP_GET(tp, GSM0808_IE_CELL_ID_LIST_SEG_REL_CELLS); + const struct tlv_p_entry *ie_cils_ne = TLVP_GET(tp, GSM0808_IE_CELL_ID_LIST_SEG_NE_CELLS); + const struct tlv_p_entry *ie_cell_status = TLVP_GET(tp, GSM0808_IE_VGCS_VBS_CELL_STATUS); + + /* Cell Identifier List Segment, 3.2.2.27b */ + if (ie_cils_est) { + rc = gsm0808_dec_cell_id_list_segment(&r->cils_est, ie_cils_est->val, ie_cils_est->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + r->cils_est_present = true; + } + + /* Cell Identifier List Segment, 3.2.2.27c */ + if (ie_cils_tbe) { + rc = gsm0808_dec_cell_id_list_segment(&r->cils_tbe, ie_cils_tbe->val, ie_cils_tbe->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + r->cils_tbe_present = true; + } + + /* Cell Identifier List Segment, 3.2.2.27e */ + if (ie_cils_rel) { + rc = gsm0808_dec_cell_id_list_segment(&r->cils_rel, ie_cils_rel->val, ie_cils_rel->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + r->cils_rel_present = true; + } + + /* Cell Identifier List Segment, 3.2.2.27f */ + if (ie_cils_ne) { + rc = gsm0808_dec_cell_id_list_segment(&r->cils_ne, ie_cils_ne->val, ie_cils_ne->len); + if (rc < 0) { + LOG_RAN_A_DEC_MSG(LOGL_ERROR, "Decoding Cell Identifier gave rc=%d\n", rc); + return -EINVAL; + } + r->cils_ne_present = true; + } + + /* VGCS/VBS Cell Status, 3.2.2.94 */ + if (ie_cell_status && ie_cell_status->len) { + r->cell_status = ie_cell_status->val[0] & 0x73; + r->cell_status_present = true; + } + + return ran_decoded(ran_dec, &ran_dec_msg); +} + static int ran_a_decode_bssmap(struct ran_dec *ran_dec, struct msgb *bssmap) { struct tlv_parsed tp[2]; @@ -821,6 +1238,26 @@ static int ran_a_decode_bssmap(struct ran_dec *ran_dec, struct msgb *bssmap) return ran_a_decode_sapi_n_reject(ran_dec, bssmap, tp); case BSS_MAP_MSG_LCLS_NOTIFICATION: return ran_a_decode_lcls_notification(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_SETUP_ACK: + return ran_a_decode_vgcs_vbs_setup_ack(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE: + return ran_a_decode_vgcs_vbs_setup_refuse(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT: + return ran_a_decode_vgcs_vbs_assign_res(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE: + return ran_a_decode_vgcs_vbs_assign_fail(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION: + return ran_a_decode_vgcs_vbs_queuing_ind(ran_dec, bssmap, tp); + case BSS_MAP_MSG_UPLINK_RQST: + return ran_a_decode_uplink_request(ran_dec, bssmap, tp); + case BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION: + return ran_a_decode_uplink_request_cnf(ran_dec, bssmap, tp); + case BSS_MAP_MSG_UPLINK_APP_DATA: + return ran_a_decode_uplink_application_data(ran_dec, bssmap, tp); + case BSS_MAP_MSG_UPLINK_RELEASE_INDICATION: + return ran_a_decode_uplink_release_ind(ran_dec, bssmap, tp); + case BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_STATUS: + return ran_a_decode_vgcs_vbs_assign_status(ran_dec, bssmap, tp); /* From current RAN peer, the Handover origin: */ case BSS_MAP_MSG_HANDOVER_REQUIRED: @@ -909,23 +1346,33 @@ static int ran_a_channel_type_to_speech_codec_list(struct gsm0808_speech_codec_l int rc; memset(scl, 0, sizeof(*scl)); - for (i = 0; i < ct->perm_spch_len; i++) { - rc = gsm0808_speech_codec_from_chan_type(&scl->codec[i], ct->perm_spch[i]); - if (rc != 0) - return -EINVAL; + + switch (ct->ch_indctr) { + case GSM0808_CHAN_DATA: + scl->codec[0] = (struct gsm0808_speech_codec) { + .pi = true, /* PI indicates CSDoIP is supported */ + .pt = false, /* PT indicates CSDoTDM is not supported */ + .type = GSM0808_SCT_CSD, + .cfg = 0, /* R2/R3 not set (redundancy not supported) */ + }; + scl->len = 1; + break; + case GSM0808_CHAN_SPEECH: + for (i = 0; i < ct->perm_spch_len; i++) { + rc = gsm0808_speech_codec_from_chan_type(&scl->codec[i], ct->perm_spch[i]); + if (rc != 0) + return -EINVAL; + } + scl->len = i; + break; + default: + OSMO_ASSERT(0); + break; } - scl->len = i; return 0; } -static void _gsm0808_assignment_extend_osmux(struct msgb *msg, uint8_t cid) -{ - OSMO_ASSERT(msg->l3h[1] == msgb_l3len(msg) - 2); /*TL not in len */ - msgb_tv_put(msg, GSM0808_IE_OSMO_OSMUX_CID, cid); - msg->l3h[1] = msgb_l3len(msg) - 2; -} - /* Compose a BSSAP Assignment Command. * Passing an RTP address is optional. * The msub is passed merely for error logging. */ @@ -945,7 +1392,7 @@ static struct msgb *ran_a_make_assignment_command(struct osmo_fsm_inst *log_fi, return NULL; } - if (ac->channel_type->ch_indctr == GSM0808_CHAN_SPEECH) { + if (ac->channel_type->ch_indctr == GSM0808_CHAN_SPEECH || ac->channel_type->ch_indctr == GSM0808_CHAN_DATA) { rc = ran_a_channel_type_to_speech_codec_list(&scl, ac->channel_type); if (rc < 0) { LOG_RAN_A_ENC(log_fi, LOGL_ERROR, "Assignment Command: Cannot translate Channel Type to Speech Codec List\n"); @@ -1006,8 +1453,19 @@ static struct msgb *ran_a_make_assignment_command(struct osmo_fsm_inst *log_fi, msg = gsm0808_create_ass2(ac->channel_type, NULL, use_rtp_addr, use_scl, call_id, NULL, ac->lcls); + if (msg == NULL) { + LOG_RAN_A_ENC(log_fi, LOGL_ERROR, + "Failed to encode BSSMAP Assignment Request message\n"); + return NULL; + } + + /* Append optional IEs: Group Call Reference and Osmux CID */ + OSMO_ASSERT(msg->l3h[1] == msgb_l3len(msg) - 2); /* TL not in len */ + if (ac->callref_present) + gsm0808_enc_group_callref(msg, &ac->callref); if (ac->osmux_present) - _gsm0808_assignment_extend_osmux(msg, ac->osmux_cid); + msgb_tv_put(msg, GSM0808_IE_OSMO_OSMUX_CID, ac->osmux_cid); + msg->l3h[1] = msgb_l3len(msg) - 2; return msg; } @@ -1283,6 +1741,36 @@ static struct msgb *_ran_a_encode(struct osmo_fsm_inst *caller_fi, const struct case RAN_MSG_HANDOVER_FAILURE: return ran_a_make_handover_failure(caller_fi, ran_enc_msg); + case RAN_MSG_VGCS_VBS_SETUP: + return gsm0808_create_vgcs_vbs_setup(&ran_enc_msg->vgcs_vbs_setup); + + case RAN_MSG_VGCS_VBS_ASSIGN_REQ: + return gsm0808_create_vgcs_vbs_assign_req(&ran_enc_msg->vgcs_vbs_assign_req); + + case RAN_MSG_UPLINK_REQUEST_ACK: + return gsm0808_create_uplink_request_ack(&ran_enc_msg->uplink_request_ack); + + case RAN_MSG_UPLINK_REJECT_CMD: + return gsm0808_create_uplink_reject_cmd(&ran_enc_msg->uplink_reject_cmd); + + case RAN_MSG_UPLINK_RELEASE_CMD: + return gsm0808_create_uplink_release_cmd(ran_enc_msg->uplink_release_cmd.cause); + + case RAN_MSG_UPLINK_SEIZED_CMD: + return gsm0808_create_uplink_seized_cmd(&ran_enc_msg->uplink_seized_cmd); + + case RAN_MSG_VGCS_ADDITIONAL_INFO: + return gsm0808_create_vgcs_additional_info(&ran_enc_msg->vgcs_additional_info.talker_identity); + + case RAN_MSG_VGCS_VBS_AREA_CELL_INFO: + return gsm0808_create_vgcs_vbs_area_cell_info(&ran_enc_msg->vgcs_vbs_area_cell_info); + + case RAN_MSG_VGCS_SMS: + return gsm0808_create_vgcs_sms(&ran_enc_msg->vgcs_sms.sms_to_vgcs); + + case RAN_MSG_NOTIFICATION_DATA: + return gsm0808_create_notification_data(&ran_enc_msg->notification_data); + default: LOG_RAN_A_ENC(caller_fi, LOGL_ERROR, "Unimplemented RAN-encode message type: %s\n", ran_msg_type_name(ran_enc_msg->msg_type)); diff --git a/src/libmsc/ran_msg_iu.c b/src/libmsc/ran_msg_iu.c index 6705ab8be..37cdf1065 100644 --- a/src/libmsc/ran_msg_iu.c +++ b/src/libmsc/ran_msg_iu.c @@ -1,25 +1,21 @@ /* RANAP encoding and decoding for MSC */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * Author: Neels Hofmeyr * - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: AGPL-3.0+ * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * 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 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. + * GNU Affero General Public License for more details. */ #include <asn1c/asn1helpers.h> @@ -157,7 +153,16 @@ static int ran_iu_decode_rab_assignment_response_decode_setup_ies(struct ran_dec .msg_type = RAN_MSG_ASSIGNMENT_COMPLETE, .msg_name = "RANAP RAB Assignment Response", .assignment_complete = { - .codec = CODEC_AMR_8000_1, + /* For codec compatibility resolution, indicate AMR-FR */ + .codec_present = true, + .codec = { + .fi = true, + .type = GSM0808_SCT_FR3, + .cfg = GSM0808_SC_CFG_DEFAULT_FR_AMR, + }, + /* Indicate that (at least) the first MGW endpoint towards RAN needs to expect VND.3GPP.IUFP + * that encapsulates the AMR-FR RTP payload. */ + .codec_with_iuup = true, }, }; if (osmo_sockaddr_str_from_str(&ran_dec_msg->assignment_complete.remote_rtp, addr, port)) { @@ -375,7 +380,10 @@ static struct msgb *ran_iu_make_rab_assignment(struct osmo_fsm_inst *caller_fi, static struct msgb *ran_iu_make_security_mode_command(struct osmo_fsm_inst *caller_fi, const struct ran_cipher_mode_command *cm) { - bool use_encryption = cm->utran.uea_encryption_mask > (1 << OSMO_UTRAN_UEA0); + /* TODO: make the choice of available UIA algorithms configurable */ + const uint8_t uia_mask = (1 << OSMO_UTRAN_UIA1) | (1 << OSMO_UTRAN_UIA2); + const uint8_t uea_mask = cm->utran.uea_encryption_mask & ~(1 << OSMO_UTRAN_UEA0); + bool use_encryption = uea_mask != 0x00; LOG_RAN_IU_ENC(caller_fi, LOGL_DEBUG, "Tx RANAP SECURITY MODE COMMAND to RNC, IK=%s, CK=%s\n", osmo_hexdump_nospc(cm->vec->ik, 16), @@ -384,7 +392,9 @@ static struct msgb *ran_iu_make_security_mode_command(struct osmo_fsm_inst *call * in the case of A5? */ return ranap_new_msg_sec_mod_cmd2(cm->vec->ik, use_encryption ? cm->vec->ck : NULL, - RANAP_KeyStatus_new, 0x06, cm->utran.uea_encryption_mask); + RANAP_KeyStatus_new, + (uia_mask << 1), /* API treats LSB as UIA0 */ + uea_mask); } diff --git a/src/libmsc/ran_peer.c b/src/libmsc/ran_peer.c index fcb5f5ad2..860444334 100644 --- a/src/libmsc/ran_peer.c +++ b/src/libmsc/ran_peer.c @@ -1,5 +1,5 @@ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -33,6 +33,7 @@ #include <osmocom/msc/vlr.h> #include <osmocom/msc/ran_conn.h> #include <osmocom/msc/cell_id_list.h> +#include <osmocom/msc/msc_vgcs.h> static struct osmo_fsm ran_peer_fsm; @@ -118,7 +119,12 @@ void ran_peer_discard_all_conns(struct ran_peer *rp) struct ran_conn *conn, *next; ran_peer_for_each_ran_conn_safe(conn, next, rp) { - ran_conn_discard(conn); + /* Tell VGCS FSM that the connections have been cleared. */ + if (conn->vgcs.bss) + vgcs_vbs_clear_cpl(conn->vgcs.bss, NULL); + else if (conn->vgcs.cell) + vgcs_vbs_clear_cpl_channel(conn->vgcs.cell, NULL); + else ran_conn_discard(conn); } } @@ -393,18 +399,22 @@ void ran_peer_st_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data) OSMO_ASSERT(ctx->conn); OSMO_ASSERT(ctx->msg); - if (!ctx->conn->msc_role) { + if (ctx->conn->msc_role) { + /* "normal" A connection, dispatch to MSC-I or MSC-T */ + an_apdu = (struct an_apdu){ + .an_proto = rp->sri->ran->an_proto, + .msg = ctx->msg, + }; + osmo_fsm_inst_dispatch(ctx->conn->msc_role, MSC_EV_FROM_RAN_UP_L2, &an_apdu); + } else if (ctx->conn->vgcs.bss) { + /* VGCS call related */ + msc_a_rx_vgcs_bss(ctx->conn->vgcs.bss, ctx->conn, ctx->msg); + } else if (ctx->conn->vgcs.cell) { + /* VGCS channel related */ + msc_a_rx_vgcs_cell(ctx->conn->vgcs.cell, ctx->conn, ctx->msg); + } else LOG_RAN_PEER(rp, LOGL_ERROR, "Rx CO message on conn that is not associated with any MSC role\n"); - return; - } - - an_apdu = (struct an_apdu){ - .an_proto = rp->sri->ran->an_proto, - .msg = ctx->msg, - }; - - osmo_fsm_inst_dispatch(ctx->conn->msc_role, MSC_EV_FROM_RAN_UP_L2, &an_apdu); return; case RAN_PEER_EV_MSG_DOWN_CO_INITIAL: diff --git a/src/libmsc/rtp_stream.c b/src/libmsc/rtp_stream.c index 29025204f..eb9ba7e52 100644 --- a/src/libmsc/rtp_stream.c +++ b/src/libmsc/rtp_stream.c @@ -1,5 +1,5 @@ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -28,6 +28,7 @@ #include <osmocom/msc/transaction.h> #include <osmocom/msc/call_leg.h> #include <osmocom/msc/rtp_stream.h> +#include <osmocom/msc/codec_mapping.h> #define LOG_RTPS(rtps, level, fmt, args...) \ LOGPFSML(rtps->fi, level, fmt, ##args) @@ -78,10 +79,12 @@ void rtp_stream_update_id(struct rtp_stream *rtps) OSMO_STRBUF_PRINTF(sb, ":no-remote-port"); else if (!rtps->remote_sent_to_mgw) OSMO_STRBUF_PRINTF(sb, ":remote-port-not-sent"); - if (!rtps->codec_known) - OSMO_STRBUF_PRINTF(sb, ":no-codec"); - else if (!rtps->codec_sent_to_mgw) - OSMO_STRBUF_PRINTF(sb, ":codec-not-sent"); + if (!rtps->codecs_known) + OSMO_STRBUF_PRINTF(sb, ":no-codecs"); + else if (!rtps->codecs_sent_to_mgw) + OSMO_STRBUF_PRINTF(sb, ":codecs-not-sent"); + if (!rtps->codecs_sent_to_mgw) + OSMO_STRBUF_PRINTF(sb, ":mode-not-sent"); if (rtps->use_osmux) { if (rtps->remote_osmux_cid < 0) OSMO_STRBUF_PRINTF(sb, ":no-remote-osmux-cid"); @@ -107,13 +110,14 @@ void rtp_stream_update_id(struct rtp_stream *rtps) /* Allocate RTP stream under a call leg. This is one RTP connection from some remote entity with address and port to a * local RTP address and port. call_id is stored for sending in MGCP transactions and as logging context. for_trans is * optional, merely stored for reference by callers, and appears as log context if not NULL. */ -struct rtp_stream *rtp_stream_alloc(struct call_leg *parent_call_leg, enum rtp_direction dir, - uint32_t call_id, struct gsm_trans *for_trans) +struct rtp_stream *rtp_stream_alloc(struct osmo_fsm_inst *parent_fi, uint32_t event_gone, uint32_t event_avail, + uint32_t event_estab, enum rtp_direction dir, uint32_t call_id, + struct gsm_trans *for_trans) { struct osmo_fsm_inst *fi; struct rtp_stream *rtps; - fi = osmo_fsm_inst_alloc_child(&rtp_stream_fsm, parent_call_leg->fi, CALL_LEG_EV_RTP_STREAM_GONE); + fi = osmo_fsm_inst_alloc_child(&rtp_stream_fsm, parent_fi, event_gone); OSMO_ASSERT(fi); rtps = talloc(fi, struct rtp_stream); @@ -121,12 +125,14 @@ struct rtp_stream *rtp_stream_alloc(struct call_leg *parent_call_leg, enum rtp_d fi->priv = rtps; *rtps = (struct rtp_stream){ .fi = fi, - .parent_call_leg = parent_call_leg, + .event_avail = event_avail, + .event_estab = event_estab, .call_id = call_id, .for_trans = for_trans, .dir = dir, .local_osmux_cid = -2, .remote_osmux_cid = -2, + .crcx_conn_mode = MGCP_CONN_NONE, /* Use connection's default mode. */ }; rtp_stream_update_id(rtps); @@ -141,7 +147,7 @@ static void check_established(struct rtp_stream *rtps) && osmo_sockaddr_str_is_nonzero(&rtps->remote) && rtps->remote_sent_to_mgw && (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) - && rtps->codec_known) + && rtps->codecs_known) rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHED); } @@ -168,17 +174,18 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui if (crcx_info->x_osmo_osmux_use) rtps->local_osmux_cid = crcx_info->x_osmo_osmux_cid; rtp_stream_update_id(rtps); - osmo_fsm_inst_dispatch(fi->proc.parent, CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE, rtps); + osmo_fsm_inst_dispatch(fi->proc.parent, rtps->event_avail, rtps); check_established(rtps); - if ((!rtps->remote_sent_to_mgw || !rtps->codec_sent_to_mgw) + if ((!rtps->remote_sent_to_mgw || !rtps->codecs_sent_to_mgw || !rtps->mode_sent_to_mgw) && osmo_sockaddr_str_is_nonzero(&rtps->remote) && (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) - && rtps->codec_known) { + && rtps->codecs_known) { LOG_RTPS(rtps, LOGL_DEBUG, - "local ip:port set;%s%s%s triggering MDCX to send the new settings\n", - (!rtps->remote_sent_to_mgw)? " remote ip:port not yet sent," : "", - (!rtps->codec_sent_to_mgw)? " codec not yet sent," : "", + "local ip:port set;%s%s%s%s triggering MDCX to send the new settings\n", + (!rtps->remote_sent_to_mgw) ? " remote ip:port not yet sent," : "", + (!rtps->codecs_sent_to_mgw) ? " codecs not yet sent," : "", + (!rtps->mode_sent_to_mgw) ? " mode not yet sent," : "", (rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw) ? "Osmux CID not yet sent,": ""); rtp_stream_do_mdcx(rtps); } @@ -192,7 +199,8 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui case RTP_STREAM_EV_CRCX_FAIL: case RTP_STREAM_EV_MDCX_FAIL: rtps->remote_sent_to_mgw = false; - rtps->codec_sent_to_mgw = false; + rtps->codecs_sent_to_mgw = false; + rtps->mode_sent_to_mgw = false; rtps->remote_osmux_cid_sent_to_mgw = false; rtp_stream_update_id(rtps); rtp_stream_state_chg(rtps, RTP_STREAM_ST_DISCARDING); @@ -206,7 +214,7 @@ static void rtp_stream_fsm_establishing_established(struct osmo_fsm_inst *fi, ui void rtp_stream_fsm_established_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { struct rtp_stream *rtps = fi->priv; - osmo_fsm_inst_dispatch(fi->proc.parent, CALL_LEG_EV_RTP_STREAM_ESTABLISHED, rtps); + osmo_fsm_inst_dispatch(fi->proc.parent, rtps->event_estab, rtps); } static int rtp_stream_fsm_timer_cb(struct osmo_fsm_inst *fi) @@ -307,13 +315,30 @@ static int rtp_stream_do_mgcp_verb(struct rtp_stream *rtps, enum mgcp_verb verb, .x_osmo_osmux_cid = rtps->remote_osmux_cid, }; - if (verb == MGCP_VERB_CRCX) - verb_info.conn_mode = rtps->crcx_conn_mode; - - if (rtps->codec_known) { - verb_info.codecs[0] = rtps->codec; - verb_info.codecs_len = 1; - rtps->codec_sent_to_mgw = true; + verb_info.conn_mode = rtps->crcx_conn_mode; + + if (rtps->codecs_known) { + /* Send the list of codecs to the MGW. Ideally we would just feed the SDP directly, but for legacy + * reasons we still need to translate to a struct mgcp_conn_peer representation to send it. */ + struct sdp_audio_codec *codec; + int i = 0; + sdp_audio_codecs_foreach(codec, &rtps->codecs) { + const struct codec_mapping *m = codec_mapping_by_subtype_name(codec->subtype_name); + if (!m) { + LOG_RTPS(rtps, LOGL_ERROR, "Cannot map codec '%s' to MGCP: codec is unknown\n", + codec->subtype_name); + continue; + } + verb_info.codecs[i] = m->mgcp; + verb_info.ptmap[i] = (struct ptmap){ + .codec = m->mgcp, + .pt = codec->payload_type, + }; + i++; + verb_info.codecs_len = i; + verb_info.ptmap_len = i; + } + rtps->codecs_sent_to_mgw = true; } if (osmo_sockaddr_str_is_nonzero(&rtps->remote)) { int rc = osmo_strlcpy(verb_info.addr, rtps->remote.ip, sizeof(verb_info.addr)); @@ -324,6 +349,10 @@ static int rtp_stream_do_mgcp_verb(struct rtp_stream *rtps, enum mgcp_verb verb, verb_info.port = rtps->remote.port; rtps->remote_sent_to_mgw = true; } + rtps->mode_sent_to_mgw = true; + if (rtps->use_osmux && rtps->remote_osmux_cid >= 0) + rtps->remote_osmux_cid_sent_to_mgw = true; + rtp_stream_update_id(rtps); osmo_mgcpc_ep_ci_request(rtps->ci, verb, &verb_info, rtps->fi, ok_event, fail_event, NULL); return 0; @@ -357,47 +386,91 @@ void rtp_stream_release(struct rtp_stream *rtps) } /* After setting up a remote RTP address or a new codec, call this to trigger an MDCX. - * The MDCX will only trigger if all data needed by an endpoint is available (both RTP address and codec) and if at + * The MDCX will only trigger if all data needed by an endpoint is available (RTP address, codecs and mode) and if at * least one of them has not yet been sent to the MGW in a previous CRCX or MDCX. */ int rtp_stream_commit(struct rtp_stream *rtps) { - if (!rtps->ci) { - LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no MGW endpoint CI set up\n"); - return -1; - } if (!osmo_sockaddr_str_is_nonzero(&rtps->remote)) { LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no remote RTP address known\n"); return -1; } - if (!rtps->codec_known) { - LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no codec known\n"); + if (!rtps->codecs_known) { + LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no codecs known\n"); return -1; } - if (rtps->remote_sent_to_mgw && rtps->codec_sent_to_mgw) { - LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: both remote RTP address and codec already set up at MGW\n"); + if (rtps->remote_sent_to_mgw && rtps->codecs_sent_to_mgw && rtps->mode_sent_to_mgw) { + LOG_RTPS(rtps, LOGL_DEBUG, + "Not committing: remote RTP address, codecs and mode are already set up at MGW\n"); return 0; } + if (!rtps->ci) { + LOG_RTPS(rtps, LOGL_DEBUG, "Not committing: no MGW endpoint CI set up\n"); + return -1; + } - LOG_RTPS(rtps, LOGL_DEBUG, "Committing: Tx MDCX to update the MGW: updating%s%s%s\n", + LOG_RTPS(rtps, LOGL_DEBUG, "Committing: Tx MDCX to update the MGW: updating%s%s%s%s\n", rtps->remote_sent_to_mgw ? "" : " remote-RTP-IP-port", - rtps->codec_sent_to_mgw ? "" : " codec", + rtps->codecs_sent_to_mgw ? "" : " codecs", + rtps->mode_sent_to_mgw ? "" : " mode", (!rtps->use_osmux || rtps->remote_osmux_cid_sent_to_mgw) ? "" : " remote-Osmux-CID"); return rtp_stream_do_mdcx(rtps); } -void rtp_stream_set_codec(struct rtp_stream *rtps, enum mgcp_codecs codec) +void rtp_stream_set_codecs(struct rtp_stream *rtps, const struct sdp_audio_codecs *codecs) +{ + if (!codecs || !codecs->count) + return; + if (sdp_audio_codecs_cmp(&rtps->codecs, codecs, false, true) == 0) { + LOG_RTPS(rtps, LOGL_DEBUG, "no change: codecs already set to %s\n", + sdp_audio_codecs_to_str(&rtps->codecs)); + return; + } + if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED) + rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHING); + LOG_RTPS(rtps, LOGL_DEBUG, "setting codecs to %s\n", sdp_audio_codecs_to_str(codecs)); + rtps->codecs = *codecs; + rtps->codecs_known = true; + rtps->codecs_sent_to_mgw = false; + rtp_stream_update_id(rtps); +} + +void rtp_stream_set_mode(struct rtp_stream *rtps, enum mgcp_connection_mode mode) { + if (rtps->crcx_conn_mode == mode) + return; if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED) rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHING); - LOG_RTPS(rtps, LOGL_DEBUG, "setting codec to %s\n", osmo_mgcpc_codec_name(codec)); - rtps->codec = codec; - rtps->codec_known = true; - rtps->codec_sent_to_mgw = false; + LOG_RTPS(rtps, LOGL_DEBUG, "setting mode to %s\n", mgcp_client_cmode_name(mode)); + rtps->mode_sent_to_mgw = false; + rtps->crcx_conn_mode = mode; rtp_stream_update_id(rtps); } +/* Convenience shortcut to call rtp_stream_set_codecs() with a list of only one sdp_audio_codec record. */ +void rtp_stream_set_one_codec(struct rtp_stream *rtps, const struct sdp_audio_codec *codec) +{ + struct sdp_audio_codecs codecs = {}; + sdp_audio_codecs_add_copy(&codecs, codec); + rtp_stream_set_codecs(rtps, &codecs); +} + +/* For legacy, rather use rtp_stream_set_codecs() with a full codecs list. */ +bool rtp_stream_set_codecs_from_mgcp_codec(struct rtp_stream *rtps, enum mgcp_codecs codec) +{ + struct sdp_audio_codecs codecs = {}; + if (!sdp_audio_codecs_add_mgcp_codec(&codecs, codec)) + return false; + rtp_stream_set_codecs(rtps, &codecs); + return true; +} + void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_sockaddr_str *r) { + if (osmo_sockaddr_str_cmp(&rtps->remote, r) == 0) { + LOG_RTPS(rtps, LOGL_DEBUG, "remote addr already " OSMO_SOCKADDR_STR_FMT ", no change\n", + OSMO_SOCKADDR_STR_FMT_ARGS(r)); + return; + } if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED) rtp_stream_state_chg(rtps, RTP_STREAM_ST_ESTABLISHING); LOG_RTPS(rtps, LOGL_DEBUG, "setting remote addr to " OSMO_SOCKADDR_STR_FMT "\n", OSMO_SOCKADDR_STR_FMT_ARGS(r)); @@ -406,6 +479,13 @@ void rtp_stream_set_remote_addr(struct rtp_stream *rtps, const struct osmo_socka rtp_stream_update_id(rtps); } +void rtp_stream_set_remote_addr_and_codecs(struct rtp_stream *rtps, const struct sdp_msg *sdp) +{ + rtp_stream_set_codecs(rtps, &sdp->audio_codecs); + if (osmo_sockaddr_str_is_nonzero(&sdp->rtp)) + rtp_stream_set_remote_addr(rtps, &sdp->rtp); +} + void rtp_stream_set_remote_osmux_cid(struct rtp_stream *rtps, uint8_t osmux_cid) { if (rtps->fi->state == RTP_STREAM_ST_ESTABLISHED) @@ -425,7 +505,8 @@ bool rtp_stream_is_established(struct rtp_stream *rtps) if (rtps->fi->state != RTP_STREAM_ST_ESTABLISHED) return false; if (!rtps->remote_sent_to_mgw - || !rtps->codec_sent_to_mgw + || !rtps->codecs_sent_to_mgw + || !rtps->mode_sent_to_mgw || (rtps->use_osmux && !rtps->remote_osmux_cid_sent_to_mgw)) return false; return true; diff --git a/src/libmsc/sccp_ran.c b/src/libmsc/sccp_ran.c index 99317b500..9907f200d 100644 --- a/src/libmsc/sccp_ran.c +++ b/src/libmsc/sccp_ran.c @@ -1,5 +1,5 @@ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ diff --git a/src/libmsc/sdp_msg.c b/src/libmsc/sdp_msg.c index 6170e8eb4..9b4cd988c 100644 --- a/src/libmsc/sdp_msg.c +++ b/src/libmsc/sdp_msg.c @@ -1,6 +1,6 @@ /* Minimalistic SDP parse/compose implementation, focused on GSM audio codecs */ /* - * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * All Rights Reserved * * SPDX-License-Identifier: AGPL-3.0+ @@ -30,31 +30,89 @@ #include <osmocom/msc/debug.h> #include <osmocom/msc/sdp_msg.h> +bool sdp_audio_codec_is_set(const struct sdp_audio_codec *a) +{ + return a && a->subtype_name[0]; +} + /* Compare name, rate and fmtp, returning typical cmp result: 0 on match, and -1 / 1 on mismatch. - * Do *not* compare the payload_type number. + * If cmp_fmtp is false, do *not* compare the fmtp string; if true, compare fmtp 1:1 as strings. + * If cmp_payload_type is false, do *not* compare the payload_type number. * The fmtp is only string-compared -- e.g. if AMR parameters appear in a different order, it amounts to a mismatch even * though all parameters are the same. */ -int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b) +int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_codec *b, + bool cmp_fmtp, bool cmp_payload_type) { - int rc; + int cmp; if (a == b) return 0; if (!a) return -1; if (!b) return 1; - rc = strncmp(a->subtype_name, b->subtype_name, sizeof(a->subtype_name)); - if (rc) - return rc; + cmp = strncmp(a->subtype_name, b->subtype_name, sizeof(a->subtype_name)); + if (cmp) + return cmp; + cmp = OSMO_CMP(a->rate, b->rate); + if (cmp) + return cmp; + if (cmp_fmtp) { + cmp = strncmp(a->fmtp, b->fmtp, sizeof(a->fmtp)); + if (cmp) + return cmp; + } + if (cmp_payload_type) { + cmp = OSMO_CMP(a->payload_type, b->payload_type); + if (cmp) + return cmp; + } + return 0; +} - if (a->rate < b->rate) +/* Compare two lists of audio codecs, returning typical cmp result: 0 on match, and -1 / 1 on mismatch. + * The ordering in the two lists may differ, except that the first codec in 'a' must also be the first codec in 'b'. + * This is because the first codec typically expresses the preferred codec to use. + * If cmp_fmtp is false, do *not* compare the fmtp strings; if true, compare fmtp 1:1 as strings. + * If cmp_payload_type is false, do *not* compare the payload_type numbers. + * The fmtp is only string-compared -- e.g. if AMR parameters appear in a different order, it amounts to a mismatch even + * though all parameters are the same. */ +int sdp_audio_codecs_cmp(const struct sdp_audio_codecs *a, const struct sdp_audio_codecs *b, + bool cmp_fmtp, bool cmp_payload_type) +{ + const struct sdp_audio_codec *codec_a; + const struct sdp_audio_codec *codec_b; + int cmp; + if (a == b) + return 0; + if (!a) return -1; - if (a->rate > b->rate) + if (!b) return 1; - rc = strncmp(a->fmtp, b->fmtp, sizeof(a->fmtp)); - if (rc) - return rc; + cmp = OSMO_CMP(a->count, b->count); + if (cmp) + return cmp; + + if (!a->count) + return 0; + + /* The first codec is the "chosen" codec and should match. The others may appear in different order. */ + cmp = sdp_audio_codec_cmp(&a->codec[0], &b->codec[0], cmp_fmtp, cmp_payload_type); + if (cmp) + return cmp; + + /* See if each codec in a is also present in b */ + sdp_audio_codecs_foreach(codec_a, a) { + bool match_found = false; + sdp_audio_codecs_foreach(codec_b, b) { + if (!sdp_audio_codec_cmp(codec_a, codec_b, cmp_fmtp, cmp_payload_type)) { + match_found = true; + break; + } + } + if (!match_found) + return -1; + } return 0; } @@ -63,13 +121,13 @@ int sdp_audio_codec_cmp(const struct sdp_audio_codec *a, const struct sdp_audio_ * The payload_type must exist in sdp_msg_payload_type_names. * Return the audio codec created or already existing for this payload type number. */ -struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigned int payload_type, - const char *subtype_name, unsigned int rate, const char *fmtp) +struct sdp_audio_codec *sdp_audio_codecs_add(struct sdp_audio_codecs *ac, unsigned int payload_type, + const char *subtype_name, unsigned int rate, const char *fmtp) { struct sdp_audio_codec *codec; /* Does an entry already exist? */ - codec = sdp_audio_codec_by_payload_type(ac, payload_type, false); + codec = sdp_audio_codecs_by_payload_type(ac, payload_type, false); if (codec) { /* Already exists, sanity check */ if (!codec->subtype_name[0]) @@ -88,7 +146,7 @@ struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigne } /* None exists, create codec entry for this payload type number */ - codec = sdp_audio_codec_by_payload_type(ac, payload_type, true); + codec = sdp_audio_codecs_by_payload_type(ac, payload_type, true); /* NULL means unable to add an entry */ if (!codec) return NULL; @@ -96,56 +154,62 @@ struct sdp_audio_codec *sdp_audio_codec_add(struct sdp_audio_codecs *ac, unsigne OSMO_STRLCPY_ARRAY(codec->subtype_name, subtype_name); if (fmtp) OSMO_STRLCPY_ARRAY(codec->fmtp, fmtp); + codec->rate = rate; return codec; } -struct sdp_audio_codec *sdp_audio_codec_add_copy(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) +struct sdp_audio_codec *sdp_audio_codecs_add_copy(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) { - return sdp_audio_codec_add(ac, codec->payload_type, codec->subtype_name, codec->rate, - codec->fmtp[0] ? codec->fmtp : NULL); + return sdp_audio_codecs_add(ac, codec->payload_type, codec->subtype_name, codec->rate, + codec->fmtp[0] ? codec->fmtp : NULL); } -struct sdp_audio_codec *sdp_audio_codec_by_payload_type(struct sdp_audio_codecs *ac, unsigned int payload_type, - bool create) +/* Find or create an entry for the given payload_type number in the given list of codecs. + * If the given payload_type number is already present in ac, return the first matching entry. + * If no such payload_type number is present: a) return NULL if create == false; + * b) If create == true, add a mostly empty codec entry to the end of ac with the given payload_type number, and return + * the created entry. + * If create == true, a NULL return value means that there was no unused entry left in ac to add this payload_type. + */ +struct sdp_audio_codec *sdp_audio_codecs_by_payload_type(struct sdp_audio_codecs *ac, unsigned int payload_type, + bool create) { struct sdp_audio_codec *codec; - foreach_sdp_audio_codec(codec, ac) { + sdp_audio_codecs_foreach(codec, ac) { if (codec->payload_type == payload_type) return codec; } - if (!create) return NULL; - /* Not found; codec points after the last entry now. */ - if ((codec - ac->codec) >= ARRAY_SIZE(ac->codec)) + if (ac->count >= ARRAY_SIZE(ac->codec)) return NULL; + codec = &ac->codec[ac->count]; *codec = (struct sdp_audio_codec){ .payload_type = payload_type, .rate = 8000, }; - - ac->count = (codec - ac->codec) + 1; + ac->count++; return codec; } -/* Return a given sdp_msg's codec entry that matches the subtype_name, rate and fmtp of the given codec, or NULL if no - * match is found. Comparison is made by sdp_audio_codec_cmp(). */ -struct sdp_audio_codec *sdp_audio_codec_by_descr(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) +/* Return a given sdp_msg's codec entry that matches the subtype_name and rate of the given codec, or NULL if no + * match is found. Comparison is made by sdp_audio_codec_cmp(cmp_payload_type=false). */ +struct sdp_audio_codec *sdp_audio_codecs_by_descr(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) { struct sdp_audio_codec *i; - foreach_sdp_audio_codec(i, ac) { - if (!sdp_audio_codec_cmp(i, codec)) + sdp_audio_codecs_foreach(i, ac) { + if (!sdp_audio_codec_cmp(i, codec, false, false)) return i; } return NULL; } -/* Remove the codec entry pointed at by 'codec'. 'codec' must point at an entry of 'sdp' (to use an external codec - * instance, use sdp_audio_codec_by_descr()). +/* Remove the codec entry pointed at by 'codec'. 'codec' must point at an entry of 'ac'. + * To use any external codec instance, use sdp_audio_codecs_remove(ac, sdp_audio_codecs_by_descr(ac, codec)). * Return 0 on success, -ENOENT if codec does not point at the sdp->codec array. */ -int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) +int sdp_audio_codecs_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_codec *codec) { struct sdp_audio_codec *i; if ((codec < ac->codec) @@ -154,7 +218,7 @@ int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_c /* Move all following entries one up */ ac->count--; - foreach_sdp_audio_codec(i, ac) { + sdp_audio_codecs_foreach(i, ac) { if (i < codec) continue; *i = *(i+1); @@ -162,13 +226,29 @@ int sdp_audio_codec_remove(struct sdp_audio_codecs *ac, const struct sdp_audio_c return 0; } +static const char * const sdp_mode_str[] = { + [SDP_MODE_UNSET] = "-", + [SDP_MODE_SENDONLY] = "sendonly", + [SDP_MODE_RECVONLY] = "recvonly", + [SDP_MODE_SENDRECV] = "sendrecv", + [SDP_MODE_INACTIVE] = "inactive", +}; + /* Convert struct sdp_msg to the actual SDP protocol representation */ -int sdp_msg_to_str(char *dst, size_t dst_size, const struct sdp_msg *sdp) +int sdp_msg_to_sdp_str_buf(char *dst, size_t dst_size, const struct sdp_msg *sdp) { const struct sdp_audio_codec *codec; struct osmo_strbuf sb = { .buf = dst, .len = dst_size }; - const char *ip = sdp->rtp.ip[0] ? sdp->rtp.ip : "0.0.0.0"; - char ipv = osmo_ip_str_type(ip) == AF_INET6 ? '6' : '4'; + const char *ip; + char ipv; + + if (!sdp) { + OSMO_STRBUF_PRINTF(sb, "%s", ""); + return sb.chars_needed; + } + + ip = sdp->rtp.ip[0] ? sdp->rtp.ip : "0.0.0.0"; + ipv = (osmo_ip_str_type(ip) == AF_INET6) ? '6' : '4'; OSMO_STRBUF_PRINTF(sb, "v=0\r\n" @@ -181,23 +261,25 @@ int sdp_msg_to_str(char *dst, size_t dst_size, const struct sdp_msg *sdp) sdp->rtp.port); /* Append all payload type numbers to 'm=audio <port> RTP/AVP 3 4 112' line */ - foreach_sdp_audio_codec(codec, &sdp->audio_codecs) + sdp_audio_codecs_foreach(codec, &sdp->audio_codecs) OSMO_STRBUF_PRINTF(sb, " %d", codec->payload_type); OSMO_STRBUF_PRINTF(sb, "\r\n"); /* Add details for all codecs */ - foreach_sdp_audio_codec(codec, &sdp->audio_codecs) { - if (codec->subtype_name[0]) { - OSMO_STRBUF_PRINTF(sb, "a=rtpmap:%d %s/%d\r\n", codec->payload_type, codec->subtype_name, - codec->rate > 0? codec->rate : 8000); - } - + sdp_audio_codecs_foreach(codec, &sdp->audio_codecs) { + if (!sdp_audio_codec_is_set(codec)) + continue; + OSMO_STRBUF_PRINTF(sb, "a=rtpmap:%d %s/%d\r\n", codec->payload_type, codec->subtype_name, + codec->rate > 0 ? codec->rate : 8000); if (codec->fmtp[0]) OSMO_STRBUF_PRINTF(sb, "a=fmtp:%d %s\r\n", codec->payload_type, codec->fmtp); } OSMO_STRBUF_PRINTF(sb, "a=ptime:%d\r\n", sdp->ptime > 0? sdp->ptime : 20); + if (sdp->mode != SDP_MODE_UNSET && sdp->mode < ARRAY_SIZE(sdp_mode_str)) + OSMO_STRBUF_PRINTF(sb, "a=%s\r\n", sdp_mode_str[sdp->mode]); + return sb.chars_needed; } @@ -223,11 +305,9 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) #define A_FMTP "fmtp:" #define A_PTIME "ptime:" #define A_RTCP "rtcp:" -#define A_SENDRECV "sendrecv" -#define A_SENDONLY "sendonly" -#define A_RECVONLY "recvonly" if (osmo_str_startswith(src, A_RTPMAP)) { + /* "a=rtpmap:3 GSM/8000" */ char *audio_name; unsigned int channels = 1; if (sscanf(src, A_RTPMAP "%u", &payload_type) != 1) @@ -237,7 +317,7 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) if (!audio_name || audio_name >= sdp_msg_line_end(src)) return -EINVAL; - codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true); + codec = sdp_audio_codecs_by_payload_type(&sdp->audio_codecs, payload_type, true); if (!codec) return -ENOSPC; @@ -249,6 +329,7 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) } else if (osmo_str_startswith(src, A_FMTP)) { + /* "a=fmtp:112 octet-align=1;mode-set=0,1,2,3" */ char *fmtp_str; const char *line_end = sdp_msg_line_end(src); if (sscanf(src, A_FMTP "%u", &payload_type) != 1) @@ -261,7 +342,7 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) if (fmtp_str >= line_end) return -EINVAL; - codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true); + codec = sdp_audio_codecs_by_payload_type(&sdp->audio_codecs, payload_type, true); if (!codec) return -ENOSPC; @@ -270,6 +351,7 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) } else if (osmo_str_startswith(src, A_PTIME)) { + /* "a=ptime:20" */ if (sscanf(src, A_PTIME "%u", &sdp->ptime) != 1) return -EINVAL; @@ -279,16 +361,24 @@ int sdp_parse_attrib(struct sdp_msg *sdp, const char *src) /* TODO? */ } - else if (osmo_str_startswith(src, A_SENDRECV)) { - /* TODO? */ + else if (osmo_str_startswith(src, sdp_mode_str[SDP_MODE_SENDRECV])) { + /* "a=sendrecv" */ + sdp->mode = SDP_MODE_SENDRECV; } - else if (osmo_str_startswith(src, A_SENDONLY)) { - /* TODO? */ + else if (osmo_str_startswith(src, sdp_mode_str[SDP_MODE_SENDONLY])) { + /* "a=sendonly" */ + sdp->mode = SDP_MODE_SENDONLY; } - else if (osmo_str_startswith(src, A_RECVONLY)) { - /* TODO? */ + else if (osmo_str_startswith(src, sdp_mode_str[SDP_MODE_RECVONLY])) { + /* "a=recvonly" */ + sdp->mode = SDP_MODE_RECVONLY; + } + + else if (osmo_str_startswith(src, sdp_mode_str[SDP_MODE_INACTIVE])) { + /* "a=inactive" */ + sdp->mode = SDP_MODE_INACTIVE; } return 0; @@ -347,7 +437,7 @@ static int sdp_parse_media_description(struct sdp_msg *sdp, const char *src) if (sscanf(payload_type_str, "%u", &payload_type) < 1) return -EINVAL; - codec = sdp_audio_codec_by_payload_type(&sdp->audio_codecs, payload_type, true); + codec = sdp_audio_codecs_by_payload_type(&sdp->audio_codecs, payload_type, true); if (!codec) return -ENOSPC; @@ -383,7 +473,7 @@ static int sdp_parse_connection_info(struct sdp_msg *sdp, const char *src) } /* Parse SDP string into struct sdp_msg. Return 0 on success, negative on error. */ -int sdp_msg_from_str(struct sdp_msg *sdp, const char *src) +int sdp_msg_from_sdp_str(struct sdp_msg *sdp, const char *src) { const char *pos; *sdp = (struct sdp_msg){}; @@ -452,8 +542,8 @@ next_line: } /* Leave only those codecs in 'ac_dest' that are also present in 'ac_other'. - * The matching is made by sdp_audio_codec_cmp(), i.e. payload_type numbers are not compared and fmtp parameters are - * compared 1:1 as plain strings. + * The matching is made by sdp_audio_codec_cmp(cmp_payload_type=false), i.e. payload_type numbers are not compared and + * fmtp parameters are compared 1:1 as plain strings. * If translate_payload_type_numbers has an effect if ac_dest and ac_other have mismatching payload_type numbers for the * same SDP codec descriptions. If translate_payload_type_numbers is true, take the payload_type numbers from ac_other. * If false, keep payload_type numbers in ac_dest unchanged. */ @@ -466,10 +556,10 @@ void sdp_audio_codecs_intersection(struct sdp_audio_codecs *ac_dest, const struc struct sdp_audio_codec *other; OSMO_ASSERT(i < ARRAY_SIZE(ac_dest->codec)); - other = sdp_audio_codec_by_descr((struct sdp_audio_codecs*)ac_other, codec); + other = sdp_audio_codecs_by_descr((struct sdp_audio_codecs *)ac_other, codec); if (!other) { - OSMO_ASSERT(sdp_audio_codec_remove(ac_dest, codec) == 0); + OSMO_ASSERT(sdp_audio_codecs_remove(ac_dest, codec) == 0); i--; continue; } @@ -505,53 +595,56 @@ void sdp_audio_codecs_select(struct sdp_audio_codecs *ac, struct sdp_audio_codec /* Short single-line representation of an SDP audio codec, convenient for logging. * Like "AMR/8000:octet-align=1#122" */ -int sdp_audio_codec_name_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec) +int sdp_audio_codec_to_str_buf(char *buf, size_t buflen, const struct sdp_audio_codec *codec) { struct osmo_strbuf sb = { .buf = buf, .len = buflen }; OSMO_STRBUF_PRINTF(sb, "%s", codec->subtype_name); + if (codec->rate != 8000) + OSMO_STRBUF_PRINTF(sb, "/%u", codec->rate); if (codec->fmtp[0]) OSMO_STRBUF_PRINTF(sb, ":%s", codec->fmtp); + OSMO_STRBUF_PRINTF(sb, "#%d", codec->payload_type); return sb.chars_needed; } -char *sdp_audio_codec_name_c(void *ctx, const struct sdp_audio_codec *codec) +char *sdp_audio_codec_to_str_c(void *ctx, const struct sdp_audio_codec *codec) { - OSMO_NAME_C_IMPL(ctx, 32, "sdp_audio_codec_name_c-ERROR", sdp_audio_codec_name_buf, codec) + OSMO_NAME_C_IMPL(ctx, 32, "sdp_audio_codec_to_str_c-ERROR", sdp_audio_codec_to_str_buf, codec) } -const char *sdp_audio_codec_name(const struct sdp_audio_codec *codec) +const char *sdp_audio_codec_to_str(const struct sdp_audio_codec *codec) { - return sdp_audio_codec_name_c(OTC_SELECT, codec); + return sdp_audio_codec_to_str_c(OTC_SELECT, codec); } /* Short single-line representation of a list of SDP audio codecs, convenient for logging */ -int sdp_audio_codecs_name_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac) +int sdp_audio_codecs_to_str_buf(char *buf, size_t buflen, const struct sdp_audio_codecs *ac) { struct osmo_strbuf sb = { .buf = buf, .len = buflen }; const struct sdp_audio_codec *codec; if (!ac->count) OSMO_STRBUF_PRINTF(sb, "(no-codecs)"); - foreach_sdp_audio_codec(codec, ac) { + sdp_audio_codecs_foreach(codec, ac) { bool first = (codec == ac->codec); if (!first) OSMO_STRBUF_PRINTF(sb, ","); - OSMO_STRBUF_APPEND(sb, sdp_audio_codec_name_buf, codec); + OSMO_STRBUF_APPEND(sb, sdp_audio_codec_to_str_buf, codec); } return sb.chars_needed; } -char *sdp_audio_codecs_name_c(void *ctx, const struct sdp_audio_codecs *ac) +char *sdp_audio_codecs_to_str_c(void *ctx, const struct sdp_audio_codecs *ac) { - OSMO_NAME_C_IMPL(ctx, 128, "sdp_audio_codecs_name_c-ERROR", sdp_audio_codecs_name_buf, ac) + OSMO_NAME_C_IMPL(ctx, 128, "sdp_audio_codecs_to_str_c-ERROR", sdp_audio_codecs_to_str_buf, ac) } -const char *sdp_audio_codecs_name(const struct sdp_audio_codecs *ac) +const char *sdp_audio_codecs_to_str(const struct sdp_audio_codecs *ac) { - return sdp_audio_codecs_name_c(OTC_SELECT, ac); + return sdp_audio_codecs_to_str_c(OTC_SELECT, ac); } /* Short single-line representation of an SDP message, convenient for logging */ -int sdp_msg_name_buf(char *buf, size_t buflen, const struct sdp_msg *sdp) +int sdp_msg_to_str_buf(char *buf, size_t buflen, const struct sdp_msg *sdp) { struct osmo_strbuf sb = { .buf = buf, .len = buflen }; if (!sdp) { @@ -561,17 +654,33 @@ int sdp_msg_name_buf(char *buf, size_t buflen, const struct sdp_msg *sdp) OSMO_STRBUF_PRINTF(sb, OSMO_SOCKADDR_STR_FMT, OSMO_SOCKADDR_STR_FMT_ARGS(&sdp->rtp)); OSMO_STRBUF_PRINTF(sb, "{"); - OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_name_buf, &sdp->audio_codecs); + OSMO_STRBUF_APPEND(sb, sdp_audio_codecs_to_str_buf, &sdp->audio_codecs); + if (sdp->bearer_services.count) { + OSMO_STRBUF_PRINTF(sb, ","); + OSMO_STRBUF_APPEND(sb, csd_bs_list_to_str_buf, &sdp->bearer_services); + } OSMO_STRBUF_PRINTF(sb, "}"); return sb.chars_needed; } -char *sdp_msg_name_c(void *ctx, const struct sdp_msg *sdp) +char *sdp_msg_to_str_c(void *ctx, const struct sdp_msg *sdp) { - OSMO_NAME_C_IMPL(ctx, 128, "sdp_msg_name_c-ERROR", sdp_msg_name_buf, sdp) + OSMO_NAME_C_IMPL(ctx, 128, "sdp_msg_to_str_c-ERROR", sdp_msg_to_str_buf, sdp) } -const char *sdp_msg_name(const struct sdp_msg *sdp) +const char *sdp_msg_to_str(const struct sdp_msg *sdp) { - return sdp_msg_name_c(OTC_SELECT, sdp); + return sdp_msg_to_str_c(OTC_SELECT, sdp); +} + +void sdp_audio_codecs_set_csd(struct sdp_audio_codecs *ac) +{ + *ac = (struct sdp_audio_codecs){ + .count = 1, + .codec = {{ + .payload_type = 120, + .subtype_name = "CLEARMODE", + .rate = 8000, + }}, + }; } diff --git a/src/libmsc/sgs_iface.c b/src/libmsc/sgs_iface.c index ad73289ef..a845ab84b 100644 --- a/src/libmsc/sgs_iface.c +++ b/src/libmsc/sgs_iface.c @@ -124,7 +124,7 @@ static void subscr_conn_toss(struct vlr_subscr *vsub) LOG_MSUB(msub, LOGL_ERROR, "Force releasing previous subscriber connection: an SGs connection for this" " subscriber is being initiated\n"); - msc_a_release_mo(msub_msc_a(msub), GSM48_REJECT_CONGESTION); + msc_a_release_mo(msub_msc_a(msub), GSM_CAUSE_AUTH_FAILED); /* TODO: is this strong enough? After this, it should be completely disassociated with this subscriber. */ } diff --git a/src/libmsc/silent_call.c b/src/libmsc/silent_call.c index 3b95a901f..4de12b9e2 100644 --- a/src/libmsc/silent_call.c +++ b/src/libmsc/silent_call.c @@ -140,7 +140,11 @@ int gsm_silent_call_start(struct vlr_subscr *vsub, struct vty *vty) { struct gsm_network *net = vsub->vlr->user_ctx; - struct gsm_trans *trans = trans_alloc(net, vsub, TRANS_SILENT_CALL, 0, 0); + struct gsm_trans *trans; + + trans = trans_alloc(net, vsub, TRANS_SILENT_CALL, 0, 0); + if (trans == NULL) + return -ENODEV; trans->silent_call.ct = *ct; if (traffic_dst_ip) { diff --git a/src/libmsc/smpp_utils.c b/src/libmsc/smpp_utils.c deleted file mode 100644 index 7fffdd27a..000000000 --- a/src/libmsc/smpp_utils.c +++ /dev/null @@ -1,61 +0,0 @@ - -/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * 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/>. - */ - - -#include "smpp_smsc.h" -#include <osmocom/core/logging.h> - -int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode) -{ - if ((dcs & 0xF0) == 0xF0) { - if (dcs & 0x04) { - /* bit 2 == 1: 8bit data */ - *data_coding = 0x02; - *mode = MODE_8BIT; - } else { - /* bit 2 == 0: default alphabet */ - *data_coding = 0x01; - *mode = MODE_7BIT; - } - } else if ((dcs & 0xE0) == 0) { - switch (dcs & 0xC) { - case 0: - *data_coding = 0x01; - *mode = MODE_7BIT; - break; - case 4: - *data_coding = 0x02; - *mode = MODE_8BIT; - break; - case 8: - *data_coding = 0x08; /* UCS-2 */ - *mode = MODE_8BIT; - break; - default: - goto unknown_mo; - } - } else { -unknown_mo: - LOGP(DLSMS, LOGL_ERROR, "SMPP MO Unknown Data Coding 0x%02x\n", dcs); - return -1; - } - - return 0; - -} diff --git a/src/libmsc/sms_queue.c b/src/libmsc/sms_queue.c index 6098a5324..9f18f4feb 100644 --- a/src/libmsc/sms_queue.c +++ b/src/libmsc/sms_queue.c @@ -40,38 +40,113 @@ #include <osmocom/msc/vlr.h> #include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/rate_ctr.h> +#include <osmocom/core/stat_item.h> #include <osmocom/vty/vty.h> -/* - * One pending SMS that we wait for. - */ +enum smsq_stat_item_idx { + SMSQ_STAT_SMS_RAM_PENDING, +}; + +static const struct osmo_stat_item_desc smsq_stat_item_desc[] = { + [SMSQ_STAT_SMS_RAM_PENDING] = { "ram:pending", + "Number of SMSs in the in-RAM pending delivery queue" }, +}; + +static const struct osmo_stat_item_group_desc smsq_statg_desc = { + "sms_queue", + "SMS queue", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(smsq_stat_item_desc), + smsq_stat_item_desc, +}; + +enum smsq_rate_ctr_idx { + SMSQ_CTR_SMS_DELIVERY_ATTEMPTS, + SMSQ_CTR_SMS_DELIVERY_ACK, + SMSQ_CTR_SMS_DELIVERY_ERR, + SMSQ_CTR_SMS_DELIVERY_NOMEM, + SMSQ_CTR_SMS_DELIVERY_TIMEOUT, +}; + +static const struct rate_ctr_desc smsq_ctr_desc[] = { + [SMSQ_CTR_SMS_DELIVERY_ATTEMPTS] = { "delivery:attempts", + "Attempted MT SMS deliveries to subscriber" }, + [SMSQ_CTR_SMS_DELIVERY_ACK] = { "deliver:ack", + "Successful MT SMS delivery to subscriber" }, + [SMSQ_CTR_SMS_DELIVERY_ERR] = { "deliver:error", + "Erroneous MT SMS delivery" }, + [SMSQ_CTR_SMS_DELIVERY_NOMEM] = { "deliver:no_memory", + "Failed MT SMS delivery due to no memory on MS" }, + [SMSQ_CTR_SMS_DELIVERY_TIMEOUT] = { "deliver:paging_timeout", + "Failed MT SMS delivery due to paging timeout (MS gone?)" }, +}; + +static const struct rate_ctr_group_desc smsq_ctrg_desc = { + "sms_queue", + "SMS queue", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(smsq_ctr_desc), + smsq_ctr_desc, +}; + +#define smsq_rate_ctr_inc(smsq, idx) \ + rate_ctr_inc(rate_ctr_group_get_ctr((smsq)->ctrg, idx)) +#define smsq_rate_ctr_add(smsq, idx, val) \ + rate_ctr_add(rate_ctr_group_get_ctr((smsq)->ctrg, idx), val) + +#define smsq_stat_item_inc(smsq, idx) \ + osmo_stat_item_inc(osmo_stat_item_group_get_item((smsq)->statg, idx), 1) +#define smsq_stat_item_dec(smsq, idx) \ + osmo_stat_item_dec(osmo_stat_item_group_get_item((smsq)->statg, idx), 1) +#define smsq_stat_item_set(smsq, idx, val) \ + osmo_stat_item_set(osmo_stat_item_group_get_item((smsq)->statg, idx), val) + + +/* One in-RAM record of a "pending SMS". This is not the SMS itself, but merely + * a pointer to the database record. It holds a reference on the vlr_subscriber + * and some counters. While this object exists in RAM, we are regularly attempting + * to deliver the related SMS. */ struct gsm_sms_pending { - struct llist_head entry; + struct llist_head entry; /* gsm_sms_queue.pending_sms */ - struct vlr_subscr *vsub; - struct msc_a *msc_a; - unsigned long long sms_id; - int failed_attempts; - int resend; + struct vlr_subscr *vsub; /* destination subscriber for this SMS */ + struct msc_a *msc_a; /* MSC_A associated with this SMS */ + unsigned long long sms_id; /* unique ID (in SQL database) of this SMS */ + int failed_attempts; /* count of failed deliver attempts so far */ + int resend; /* should we try re-sending it (now) ? */ }; +/* (global) state of the SMS queue. */ struct gsm_sms_queue { - struct osmo_timer_list resend_pending; - struct osmo_timer_list push_queue; + struct osmo_timer_list resend_pending; /* timer triggering sms_resend_pending() */ + struct osmo_timer_list push_queue; /* timer triggering sms_submit_pending() */ struct gsm_network *network; - int max_fail; - int max_pending; - int pending; - - struct llist_head pending_sms; + struct llist_head pending_sms; /* list of gsm_sms_pending */ + struct sms_queue_config *cfg; + int pending; /* current number of gsm_sms_pending in RAM */ + /* last MSISDN for which we read SMS from the database and created gsm_sms_pending records */ char last_msisdn[GSM23003_MSISDN_MAX_DIGITS+1]; + + /* statistics / counters */ + struct osmo_stat_item_group *statg; + struct rate_ctr_group *ctrg; }; +/* private wrapper function to make sure we count all SMS delivery attempts */ +static void _gsm411_send_sms(struct gsm_network *net, struct vlr_subscr *vsub, struct gsm_sms *sms) +{ + smsq_rate_ctr_inc(net->sms_queue, SMSQ_CTR_SMS_DELIVERY_ATTEMPTS); + gsm411_send_sms(net, vsub, sms); +} + static int sms_subscr_cb(unsigned int, unsigned int, void *, void *); static int sms_sms_cb(unsigned int, unsigned int, void *, void *); +/* look-up a 'gsm_sms_pending' for the given sms_id; return NULL if none */ static struct gsm_sms_pending *sms_find_pending(struct gsm_sms_queue *smsq, unsigned long long sms_id) { @@ -85,11 +160,13 @@ static struct gsm_sms_pending *sms_find_pending(struct gsm_sms_queue *smsq, return NULL; } +/* do we currently have a gsm_sms_pending object for the given SMS id? */ int sms_queue_sms_is_pending(struct gsm_sms_queue *smsq, unsigned long long sms_id) { return sms_find_pending(smsq, sms_id) != NULL; } +/* find the first pending SMS (in RAM) for the given subscriber */ static struct gsm_sms_pending *sms_subscriber_find_pending( struct gsm_sms_queue *smsq, struct vlr_subscr *vsub) @@ -104,12 +181,14 @@ static struct gsm_sms_pending *sms_subscriber_find_pending( return NULL; } +/* do we have any pending SMS (in RAM) for the given subscriber? */ static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq, struct vlr_subscr *vsub) { return sms_subscriber_find_pending(smsq, vsub) != NULL; } +/* allocate a new gsm_sms_pending record and fill it with information from 'sms' */ static struct gsm_sms_pending *sms_pending_from(struct gsm_sms_queue *smsq, struct gsm_sms *sms) { @@ -122,16 +201,26 @@ static struct gsm_sms_pending *sms_pending_from(struct gsm_sms_queue *smsq, vlr_subscr_get(sms->receiver, VSUB_USE_SMS_PENDING); pending->vsub = sms->receiver; pending->sms_id = sms->id; + llist_add_tail(&pending->entry, &smsq->pending_sms); + + smsq->pending += 1; + smsq_stat_item_inc(smsq, SMSQ_STAT_SMS_RAM_PENDING); + return pending; } -static void sms_pending_free(struct gsm_sms_pending *pending) +/* release a gsm_sms_pending object */ +static void sms_pending_free(struct gsm_sms_queue *smsq, struct gsm_sms_pending *pending) { + smsq->pending -= 1; + smsq_stat_item_dec(smsq, SMSQ_STAT_SMS_RAM_PENDING); vlr_subscr_put(pending->vsub, VSUB_USE_SMS_PENDING); llist_del(&pending->entry); talloc_free(pending); } +/* this sets the 'resend' flag of the gsm_sms_pending and schedules + * the timer for re-sending */ static void sms_pending_resend(struct gsm_sms_pending *pending) { struct gsm_network *net = pending->vsub->vlr->user_ctx; @@ -148,6 +237,8 @@ static void sms_pending_resend(struct gsm_sms_pending *pending) osmo_timer_schedule(&smsq->resend_pending, 1, 0); } +/* call-back when a pending SMS has failed; try another re-send if number of + * attempts is < smsq->max_fail */ static void sms_pending_failed(struct gsm_sms_pending *pending, int paging_error) { struct gsm_network *net = pending->vsub->vlr->user_ctx; @@ -158,17 +249,16 @@ static void sms_pending_failed(struct gsm_sms_pending *pending, int paging_error pending->sms_id, pending->failed_attempts); smsq = net->sms_queue; - if (pending->failed_attempts < smsq->max_fail) + if (pending->failed_attempts < smsq->cfg->max_fail) return sms_pending_resend(pending); - sms_pending_free(pending); - smsq->pending -= 1; + sms_pending_free(smsq, pending); } -/* - * Resend all SMS that are scheduled for a resend. This is done to - * avoid an immediate failure. - */ +/* Resend all SMS that are scheduled for a resend. This is done to + * avoid an immediate failure. This iterates over all the (in RAM) + * pending_sms records, checks for resend == true, reads them from the + * DB and attempts to send them via _gsm411_send_sms() */ static void sms_resend_pending(void *_data) { struct gsm_sms_pending *pending, *tmp; @@ -183,12 +273,11 @@ static void sms_resend_pending(void *_data) /* the sms is gone? Move to the next */ if (!sms) { - sms_pending_free(pending); - smsq->pending -= 1; + sms_pending_free(smsq, pending); sms_queue_trigger(smsq); } else { pending->resend = 0; - gsm411_send_sms(smsq->network, sms->receiver, sms); + _gsm411_send_sms(smsq->network, sms->receiver, sms); } } } @@ -244,14 +333,14 @@ struct gsm_sms *smsq_take_next_sms(struct gsm_network *net, return NULL; } -/** - * I will submit up to max_pending - pending SMS to the - * subsystem. - */ +/* read up to 'max_pending' pending SMS from the database and add them to the in-memory + * sms_queue; trigger the first delivery attempt. 'submit' in this context means + * "read from the database and add to the in-memory gsm_sms_queue" and is not to be + * confused with the SMS SUBMIT operation a MS performs when sending a MO-SMS. */ static void sms_submit_pending(void *_data) { struct gsm_sms_queue *smsq = _data; - int attempts = smsq->max_pending - smsq->pending; + int attempts = smsq->cfg->max_pending - smsq->pending; int initialized = 0; unsigned long long first_sub = 0; int attempted = 0, rounds = 0; @@ -309,6 +398,7 @@ static void sms_submit_pending(void *_data) continue; } + /* allocate a new gsm_sms_pending object in RAM */ pending = sms_pending_from(smsq, sms); if (!pending) { LOGP(DLSMS, LOGL_ERROR, @@ -318,17 +408,16 @@ static void sms_submit_pending(void *_data) } attempted += 1; - smsq->pending += 1; - llist_add_tail(&pending->entry, &smsq->pending_sms); - gsm411_send_sms(smsq->network, sms->receiver, sms); + _gsm411_send_sms(smsq->network, sms->receiver, sms); } while (attempted < attempts && rounds < 1000); LOGP(DLSMS, LOGL_DEBUG, "SMSqueue added %d messages in %d rounds\n", attempted, rounds); } -/** - * Send the next SMS or trigger the queue - */ +/* obtain the next pending SMS for given subscriber from database, + * create gsm_sms_pending object and attempt first delivery. If there + * are no SMS pending for the given subscriber, call sms_submit_pending() + * to read more SMS (for any subscriber) into the in-RAM pending queue */ static void sms_send_next(struct vlr_subscr *vsub) { struct gsm_network *net = vsub->vlr->user_ctx; @@ -340,7 +429,7 @@ static void sms_send_next(struct vlr_subscr *vsub) OSMO_ASSERT(!sms_subscriber_is_pending(smsq, vsub)); /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX); + sms = db_sms_get_unsent_for_subscr(vsub, INT_MAX); if (!sms) goto no_pending_sms; @@ -356,9 +445,7 @@ static void sms_send_next(struct vlr_subscr *vsub) goto no_pending_sms; } - smsq->pending += 1; - llist_add_tail(&pending->entry, &smsq->pending_sms); - gsm411_send_sms(smsq->network, sms->receiver, sms); + _gsm411_send_sms(smsq->network, sms->receiver, sms); return; no_pending_sms: @@ -366,9 +453,7 @@ no_pending_sms: sms_submit_pending(net->sms_queue); } -/* - * Kick off the queue again. - */ +/* Trigger a call to sms_submit_pending() in one second */ int sms_queue_trigger(struct gsm_sms_queue *smsq) { LOGP(DLSMS, LOGL_DEBUG, "Triggering SMS queue\n"); @@ -379,7 +464,26 @@ int sms_queue_trigger(struct gsm_sms_queue *smsq) return 0; } -int sms_queue_start(struct gsm_network *network, int max_pending) +/* allocate + initialize SMS queue configuration with some default values */ +struct sms_queue_config *sms_queue_cfg_alloc(void *ctx) +{ + struct sms_queue_config *sqcfg = talloc_zero(ctx, struct sms_queue_config); + OSMO_ASSERT(sqcfg); + + sqcfg->max_pending = 20; + sqcfg->max_fail = 1; + sqcfg->delete_delivered = true; + sqcfg->delete_expired = true; + sqcfg->default_validity_mins = 7 * 24 * 60; /* 7 days */ + sqcfg->minimum_validity_mins = 1; + sqcfg->db_file_path = talloc_strdup(ctx, SMS_DEFAULT_DB_FILE_PATH); + + return sqcfg; +} + +/* initialize the sms_queue subsystem and read the first batch of SMS from + * the database for delivery */ +int sms_queue_start(struct gsm_network *network) { struct gsm_sms_queue *sms = talloc_zero(network, struct gsm_sms_queue); if (!sms) { @@ -387,22 +491,48 @@ int sms_queue_start(struct gsm_network *network, int max_pending) return -1; } - osmo_signal_register_handler(SS_SUBSCR, sms_subscr_cb, network); - osmo_signal_register_handler(SS_SMS, sms_sms_cb, network); + sms->cfg = network->sms_queue_cfg; + sms->statg = osmo_stat_item_group_alloc(sms, &smsq_statg_desc, 0); + if (!sms->statg) + goto err_free; + + sms->ctrg = rate_ctr_group_alloc(sms, &smsq_ctrg_desc, 0); + if (!sms->ctrg) + goto err_statg; network->sms_queue = sms; INIT_LLIST_HEAD(&sms->pending_sms); - sms->max_fail = 1; sms->network = network; - sms->max_pending = max_pending; osmo_timer_setup(&sms->push_queue, sms_submit_pending, sms); osmo_timer_setup(&sms->resend_pending, sms_resend_pending, sms); + osmo_signal_register_handler(SS_SUBSCR, sms_subscr_cb, network); + osmo_signal_register_handler(SS_SMS, sms_sms_cb, network); + + if (db_init(sms, sms->cfg->db_file_path, true)) { + LOGP(DMSC, LOGL_FATAL, "DB: Failed to init database: %s\n", + osmo_quote_str(sms->cfg->db_file_path, -1)); + return -1; + } + + if (db_prepare()) { + LOGP(DMSC, LOGL_FATAL, "DB: Failed to prepare database.\n"); + return -1; + } + sms_submit_pending(sms); return 0; + +err_statg: + osmo_stat_item_group_free(sms->statg); +err_free: + talloc_free(sms); + + return -ENOMEM; } +/* call-back: Given subscriber is now ready for short messages. */ static int sub_ready_for_sm(struct gsm_network *net, struct vlr_subscr *vsub) { struct gsm_sms *sms; @@ -432,14 +562,15 @@ static int sub_ready_for_sm(struct gsm_network *net, struct vlr_subscr *vsub) } /* Now try to deliver any pending SMS to this sub */ - sms = db_sms_get_unsent_for_subscr(vsub, UINT_MAX); + sms = db_sms_get_unsent_for_subscr(vsub, INT_MAX); if (!sms) return -1; - gsm411_send_sms(net, vsub, sms); + _gsm411_send_sms(net, vsub, sms); return 0; } +/* call-back for SS_SUBSCR signals */ static int sms_subscr_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { @@ -452,10 +583,12 @@ static int sms_subscr_cb(unsigned int subsys, unsigned int signal, return sub_ready_for_sm(handler_data, vsub); } +/* call-back for SS_SMS signals */ static int sms_sms_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { struct gsm_network *network = handler_data; + struct gsm_sms_queue *smq = network->sms_queue; struct sms_signal_data *sig_sms = signal_data; struct gsm_sms_pending *pending; struct vlr_subscr *vsub; @@ -463,7 +596,7 @@ static int sms_sms_cb(unsigned int subsys, unsigned int signal, /* We got a new SMS and maybe should launch the queue again. */ if (signal == S_SMS_SUBMITTED || signal == S_SMS_SMMA) { /* TODO: For SMMA we might want to re-use the radio connection. */ - sms_queue_trigger(network->sms_queue); + sms_queue_trigger(smq); return 0; } @@ -476,26 +609,27 @@ static int sms_sms_cb(unsigned int subsys, unsigned int signal, * sms that are not in our control as we just have a channel * open anyway. */ - pending = sms_find_pending(network->sms_queue, sig_sms->sms->id); + pending = sms_find_pending(smq, sig_sms->sms->id); if (!pending) return 0; switch (signal) { case S_SMS_DELIVERED: + smsq_rate_ctr_inc(smq, SMSQ_CTR_SMS_DELIVERY_ACK); /* Remember the subscriber and clear the pending entry */ - network->sms_queue->pending -= 1; vsub = pending->vsub; vlr_subscr_get(vsub, __func__); - db_sms_delete_sent_message_by_id(pending->sms_id); - sms_pending_free(pending); + if (smq->cfg->delete_delivered) + db_sms_delete_sent_message_by_id(pending->sms_id); + sms_pending_free(smq, pending); /* Attempt to send another SMS to this subscriber */ sms_send_next(vsub); vlr_subscr_put(vsub, __func__); break; case S_SMS_MEM_EXCEEDED: - network->sms_queue->pending -= 1; - sms_pending_free(pending); - sms_queue_trigger(network->sms_queue); + smsq_rate_ctr_inc(smq, SMSQ_CTR_SMS_DELIVERY_NOMEM); + sms_pending_free(smq, pending); + sms_queue_trigger(smq); break; case S_SMS_UNKNOWN_ERROR: /* @@ -509,10 +643,12 @@ static int sms_sms_cb(unsigned int subsys, unsigned int signal, * should flag the SMS as bad. */ if (sig_sms->paging_result) { + smsq_rate_ctr_inc(smq, SMSQ_CTR_SMS_DELIVERY_ERR); /* BAD SMS? */ db_sms_inc_deliver_attempts(sig_sms->sms); sms_pending_failed(pending, 0); } else { + smsq_rate_ctr_inc(smq, SMSQ_CTR_SMS_DELIVERY_TIMEOUT); sms_pending_failed(pending, 1); } break; @@ -522,7 +658,8 @@ static int sms_sms_cb(unsigned int subsys, unsigned int signal, } /* While here, attempt to remove an expired SMS from the DB. */ - db_sms_delete_oldest_expired_message(); + if (smq->cfg->delete_expired) + db_sms_delete_oldest_expired_message(); return 0; } @@ -533,7 +670,7 @@ int sms_queue_stats(struct gsm_sms_queue *smsq, struct vty *vty) struct gsm_sms_pending *pending; vty_out(vty, "SMSqueue with max_pending: %d pending: %d%s", - smsq->max_pending, smsq->pending, VTY_NEWLINE); + smsq->cfg->max_pending, smsq->pending, VTY_NEWLINE); llist_for_each_entry(pending, &smsq->pending_sms, entry) vty_out(vty, " SMS Pending for Subscriber: %llu SMS: %llu Failed: %d.%s", @@ -542,22 +679,6 @@ int sms_queue_stats(struct gsm_sms_queue *smsq, struct vty *vty) return 0; } -int sms_queue_set_max_pending(struct gsm_sms_queue *smsq, int max_pending) -{ - LOGP(DLSMS, LOGL_NOTICE, "SMSqueue old max: %d new: %d\n", - smsq->max_pending, max_pending); - smsq->max_pending = max_pending; - return 0; -} - -int sms_queue_set_max_failure(struct gsm_sms_queue *smsq, int max_fail) -{ - LOGP(DLSMS, LOGL_NOTICE, "SMSqueue max failure old: %d new: %d\n", - smsq->max_fail, max_fail); - smsq->max_fail = max_fail; - return 0; -} - int sms_queue_clear(struct gsm_sms_queue *smsq) { struct gsm_sms_pending *pending, *tmp; @@ -565,9 +686,8 @@ int sms_queue_clear(struct gsm_sms_queue *smsq) llist_for_each_entry_safe(pending, tmp, &smsq->pending_sms, entry) { LOGP(DLSMS, LOGL_NOTICE, "SMSqueue clearing for sub %llu\n", pending->vsub->id); - sms_pending_free(pending); + sms_pending_free(smsq, pending); } - smsq->pending = 0; return 0; } diff --git a/src/libmsc/smsc_vty.c b/src/libmsc/smsc_vty.c new file mode 100644 index 000000000..f30907f4b --- /dev/null +++ b/src/libmsc/smsc_vty.c @@ -0,0 +1,214 @@ +/* SMSC interface to VTY */ +/* (C) 2016-2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c) + * (C) 2009-2022 by Harald Welte <laforge@gnumonks.org> + * (C) 2009-2011 by Holger Hans Peter Freyther + * All Rights Reserved + * + * 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/>. + * + */ + +#include "config.h" + +#include <osmocom/vty/command.h> +#include <osmocom/vty/logging.h> +#include <osmocom/vty/misc.h> + +#include <osmocom/msc/vty.h> +#include <osmocom/msc/gsm_data.h> +#include <osmocom/msc/sms_queue.h> + + +static struct gsm_network *gsmnet; +static struct sms_queue_config *smqcfg; + +/*********************************************************************** + * SMSC Config Node + ***********************************************************************/ + +static struct cmd_node smsc_node = { + SMSC_NODE, + "%s(config-smsc)# ", + 1, +}; + +DEFUN(cfg_smsc, cfg_smsc_cmd, + "smsc", "Configure SMSC options") +{ + vty->node = SMSC_NODE; + return CMD_SUCCESS; +} + +DEFUN(cfg_sms_database, cfg_sms_database_cmd, + "database PATH", + "Set the path to the MSC-SMS database file\n" + "Relative or absolute file system path to the database file (default is '" SMS_DEFAULT_DB_FILE_PATH "')\n") +{ + osmo_talloc_replace_string(smqcfg, &smqcfg->db_file_path, argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_sms_queue_max, cfg_sms_queue_max_cmd, + "queue max-pending <1-500>", + "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n") +{ + smqcfg->max_pending = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_sms_queue_fail, cfg_sms_queue_fail_cmd, + "queue max-failure <1-500>", + "SMS Queue\n" "Maximum number of delivery failures before giving up\n" "Amount\n") +{ + smqcfg->max_fail = atoi(argv[0]); + return CMD_SUCCESS; +} + +#define DB_STR "SMS Database Configuration\n" + +DEFUN(cfg_sms_db_del_delivered, cfg_sms_db_del_delivered_cmd, + "database delete-delivered (0|1)", + DB_STR "Configure if delivered SMS are deleted from DB\n" + "Do not delete SMS after delivery\n" + "Delete SMS after delivery\n") +{ + smqcfg->delete_delivered = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_sms_db_del_expired, cfg_sms_db_del_expired_cmd, + "database delete-expired (0|1)", + DB_STR "Configure if expired SMS are deleted from DB\n" + "Do not delete SMS after expiration of validity period\n" + "Delete SMS after expiration of validity period\n") +{ + smqcfg->delete_expired = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_sms_def_val_per, cfg_sms_def_val_per_cmd, + "validity-period (minimum|default) <1-5256000>", + "Configure validity period for SMS\n" + "Minimum SMS validity period in minutes\n" + "Default SMS validity period in minutes\n" + "Validity period in minutes\n") +{ + if (!strcmp(argv[0], "minimum")) + smqcfg->minimum_validity_mins = atoi(argv[1]); + else + smqcfg->default_validity_mins = atoi(argv[1]); + return CMD_SUCCESS; +} + + +/*********************************************************************** + * View / Enable Node + ***********************************************************************/ + +DEFUN(show_smsqueue, + show_smsqueue_cmd, + "show sms-queue", + SHOW_STR "Display SMSqueue statistics\n") +{ + sms_queue_stats(gsmnet->sms_queue, vty); + return CMD_SUCCESS; +} + +DEFUN(smsqueue_trigger, + smsqueue_trigger_cmd, + "sms-queue trigger", + "SMS Queue\n" "Trigger sending messages\n") +{ + sms_queue_trigger(gsmnet->sms_queue); + return CMD_SUCCESS; +} + +DEFUN(smsqueue_max, + smsqueue_max_cmd, + "sms-queue max-pending <1-500>", + "SMS Queue\n" "SMS to deliver in parallel\n" "Amount\n") +{ + int max_pending = atoi(argv[0]); + vty_out(vty, "%% SMSqueue old max: %d new: %d%s", + smqcfg->max_pending, max_pending, VTY_NEWLINE); + smqcfg->max_pending = max_pending; + return CMD_SUCCESS; +} + +DEFUN(smsqueue_clear, + smsqueue_clear_cmd, + "sms-queue clear", + "SMS Queue\n" "Clear the queue of pending SMS\n") +{ + sms_queue_clear(gsmnet->sms_queue); + return CMD_SUCCESS; +} + +DEFUN(smsqueue_fail, + smsqueue_fail_cmd, + "sms-queue max-failure <1-500>", + "SMS Queue\n" "Maximum amount of delivery failures\n" "Amount\n") +{ + int max_fail = atoi(argv[0]); + vty_out(vty, "%% SMSqueue max failure old: %d new: %d%s", + smqcfg->max_fail, max_fail, VTY_NEWLINE); + smqcfg->max_fail = max_fail; + return CMD_SUCCESS; +} + +static int config_write_smsc(struct vty *vty) +{ + vty_out(vty, "smsc%s", VTY_NEWLINE); + + if (smqcfg->db_file_path && strcmp(smqcfg->db_file_path, SMS_DEFAULT_DB_FILE_PATH)) + vty_out(vty, " database %s%s", smqcfg->db_file_path, VTY_NEWLINE); + + vty_out(vty, " queue max-pending %u%s", smqcfg->max_pending, VTY_NEWLINE); + vty_out(vty, " queue max-failure %u%s", smqcfg->max_fail, VTY_NEWLINE); + + vty_out(vty, " database delete-delivered %u%s", smqcfg->delete_delivered, VTY_NEWLINE); + vty_out(vty, " database delete-expired %u%s", smqcfg->delete_expired, VTY_NEWLINE); + + vty_out(vty, " validity-period minimum %u%s", smqcfg->minimum_validity_mins, VTY_NEWLINE); + vty_out(vty, " validity-period default %u%s", smqcfg->default_validity_mins, VTY_NEWLINE); + + return 0; +} + +void smsc_vty_init(struct gsm_network *msc_network) +{ + OSMO_ASSERT(gsmnet == NULL); + gsmnet = msc_network; + smqcfg = msc_network->sms_queue_cfg; + + /* config node */ + install_element(CONFIG_NODE, &cfg_smsc_cmd); + install_node(&smsc_node, config_write_smsc); + install_element(SMSC_NODE, &cfg_sms_database_cmd); + install_element(SMSC_NODE, &cfg_sms_queue_max_cmd); + install_element(SMSC_NODE, &cfg_sms_queue_fail_cmd); + install_element(SMSC_NODE, &cfg_sms_db_del_delivered_cmd); + install_element(SMSC_NODE, &cfg_sms_db_del_expired_cmd); + install_element(SMSC_NODE, &cfg_sms_def_val_per_cmd); + + /* enable node */ + install_element(ENABLE_NODE, &smsqueue_trigger_cmd); + install_element(ENABLE_NODE, &smsqueue_max_cmd); + install_element(ENABLE_NODE, &smsqueue_clear_cmd); + install_element(ENABLE_NODE, &smsqueue_fail_cmd); + + /* view / enable node */ + install_element_ve(&show_smsqueue_cmd); +} diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c index 25c0e3c50..7ae4c7d92 100644 --- a/src/libmsc/transaction.c +++ b/src/libmsc/transaction.c @@ -29,6 +29,7 @@ #include <osmocom/msc/msub.h> #include <osmocom/msc/paging.h> #include <osmocom/msc/silent_call.h> +#include <osmocom/msc/msc_vgcs.h> void *tall_trans_ctx; @@ -73,16 +74,17 @@ struct gsm_trans *trans_find_by_id(const struct msc_a *msc_a, /*! Find a transaction by call reference * \param[in] net Network in which we should search + * \param[in] type Transaction type (e.g. TRANS_CC) * \param[in] callref Call Reference of transaction * \returns Matching transaction, if any */ -struct gsm_trans *trans_find_by_callref(const struct gsm_network *net, +struct gsm_trans *trans_find_by_callref(const struct gsm_network *net, enum trans_type type, uint32_t callref) { struct gsm_trans *trans; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->callref == callref) + if (trans->callref == callref && trans->type == type) return trans; } return NULL; @@ -151,13 +153,19 @@ struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac lcls->gcr.node = ss7->cfg.primary_pc; /* net id from Q.1902.3 3-5 bytes, this function gives 3 bytes exactly */ - osmo_plmn_to_bcd(lcls->gcr.net, &trans->net->plmn); + osmo_plmn_to_bcd(lcls->gcr.net, &trans->msc_a->via_cell.lai.plmn); - osmo_store32be(trans->callref, lcls->gcr.cr); - osmo_store16be(use_lac ? trans->msc_a->via_cell.lai.lac : trans->msc_a->via_cell.cell_identity, lcls->gcr.cr + 3); - LOGP(DCC, LOGL_INFO, "LCLS: allocated %s-based CR-ID %s\n", use_lac ? "LAC" : "CI", - osmo_hexdump(lcls->gcr.cr, 5)); + /* TS 29.205 Table B.2.1.9.2 Call Reference ID + * 3 octets Call ID + 2 octets BSS ID + */ + lcls->gcr.cr[2] = (trans->callref >> 0) & 0xff; + lcls->gcr.cr[1] = (trans->callref >> 8) & 0xff; + lcls->gcr.cr[0] = (trans->callref >> 16) & 0xff; + osmo_store16be(use_lac ? trans->msc_a->via_cell.lai.lac : trans->msc_a->via_cell.cell_identity, &lcls->gcr.cr[3]); + + LOGP(DCC, LOGL_INFO, "LCLS: allocated %s-based CR-ID %sfor callref 0x%04x\n", use_lac ? "LAC" : "CI", + osmo_hexdump(lcls->gcr.cr, 5), trans->callref); lcls->config = GSM0808_LCLS_CFG_BOTH_WAY; lcls->control = GSM0808_LCLS_CSC_CONNECT; @@ -175,8 +183,10 @@ static const char *trans_vsub_use(enum trans_type type) return get_value_string_or_null(trans_type_names, type) ? : "trans-type-unknown"; } +static uint32_t new_call_id = 1; + /*! Allocate a new transaction and add it to network list - * \param[in] net Netwokr in which we allocate transaction + * \param[in] net Network in which we allocate transaction * \param[in] subscr Subscriber for which we allocate transaction * \param[in] protocol Protocol (CC/SMS/...) * \param[in] callref Call Reference @@ -190,8 +200,8 @@ struct gsm_trans *trans_alloc(struct gsm_network *net, int subsys = trans_log_subsys(type); struct gsm_trans *trans; - /* a valid subscriber is indispensable */ - if (vsub == NULL) { + /* A valid subscriber is indispensable, except for voice group/broadcast calls. */ + if (vsub == NULL && type != TRANS_GCC && type != TRANS_BCC) { LOGP(subsys, LOGL_ERROR, "unable to alloc transaction, invalid subscriber (NULL)\n"); return NULL; } @@ -206,13 +216,15 @@ struct gsm_trans *trans_alloc(struct gsm_network *net, .log_subsys = subsys, .transaction_id = trans_id, .callref = callref, + .call_id = new_call_id++, .net = net, /* empty bearer_cap: make sure the speech_ver array is empty */ .bearer_cap = { .speech_ver = { -1 }, }, }; - vlr_subscr_get(vsub, trans_vsub_use(type)); + if (vsub) + vlr_subscr_get(vsub, trans_vsub_use(type)); llist_add_tail(&trans->entry, &net->trans_list); LOG_TRANS(trans, LOGL_DEBUG, "New transaction\n"); @@ -230,6 +242,14 @@ void trans_free(struct gsm_trans *trans) LOG_TRANS(trans, LOGL_DEBUG, "Freeing transaction\n"); switch (trans->type) { + case TRANS_GCC: + gsm44068_bcc_gcc_trans_free(trans); + usage_token = MSC_A_USE_GCC; + break; + case TRANS_BCC: + gsm44068_bcc_gcc_trans_free(trans); + usage_token = MSC_A_USE_BCC; + break; case TRANS_CC: _gsm48_cc_trans_free(trans); usage_token = MSC_A_USE_CC; @@ -341,6 +361,8 @@ void trans_conn_closed(const struct msc_a *msc_a) } const struct value_string trans_type_names[] = { + { TRANS_GCC, "GCC" }, + { TRANS_BCC, "BCC" }, { TRANS_CC, "CC" }, { TRANS_SMS, "SMS" }, { TRANS_USSD, "NCSS" }, @@ -351,6 +373,10 @@ const struct value_string trans_type_names[] = { uint8_t trans_type_to_gsm48_proto(enum trans_type type) { switch (type) { + case TRANS_GCC: + return GSM48_PDISC_GROUP_CC; + case TRANS_BCC: + return GSM48_PDISC_BCAST_CC; case TRANS_CC: case TRANS_SILENT_CALL: return GSM48_PDISC_CC; @@ -375,6 +401,12 @@ const char *trans_name(const struct gsm_trans *trans) trans_type_name(trans->type), gsm48_cc_state_name(trans->cc.state)); return namebuf; + case TRANS_GCC: + case TRANS_BCC: + snprintf(namebuf, sizeof(namebuf), "%s:%s", + trans_type_name(trans->type), gsm44068_group_id_string(trans->callref)); + return namebuf; + default: return trans_type_name(trans->type); } diff --git a/src/libmsc/transaction_cc.c b/src/libmsc/transaction_cc.c new file mode 100644 index 000000000..2a540bfa5 --- /dev/null +++ b/src/libmsc/transaction_cc.c @@ -0,0 +1,120 @@ +/* Filter/overlay codec and CSD bearer service selections for voice calls/CSD, + * across MS, RAN and CN limitations + * + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Oliver Smith + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * 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/>. + */ + +#include <osmocom/msc/transaction_cc.h> +#include <osmocom/msc/codec_filter.h> +#include <osmocom/msc/csd_filter.h> + +void trans_cc_filter_init(struct gsm_trans *trans) +{ + trans->cc.codecs = (struct codec_filter){}; + trans->cc.csd = (struct csd_filter){}; +} + +void trans_cc_filter_set_ran(struct gsm_trans *trans, enum osmo_rat_type ran_type) +{ + codec_filter_set_ran(&trans->cc.codecs, ran_type); + csd_filter_set_ran(&trans->cc.csd, ran_type); +} + +void trans_cc_filter_set_bss(struct gsm_trans *trans, struct msc_a *msc_a) +{ + codec_filter_set_bss(&trans->cc.codecs, &msc_a->cc.compl_l3_codec_list_bss_supported); + + /* For CSD, there is no list of supported bearer services passed in + * Complete Layer 3. TODO: make it configurable? */ +} + +void _trans_cc_filter_run(const char *file, int line, struct gsm_trans *trans) +{ + switch (trans->bearer_cap.transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + codec_filter_run(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote); + LOG_TRANS_CAT_SRC(trans, DCC, LOGL_DEBUG, file, line, "codecs: %s\n", + codec_filter_to_str(&trans->cc.codecs, &trans->cc.local, &trans->cc.remote)); + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + csd_filter_run(&trans->cc.csd, &trans->cc.local, &trans->cc.remote); + LOG_TRANS_CAT_SRC(trans, DCC, LOGL_DEBUG, file, line, "codec/BS: %s\n", + csd_filter_to_str(&trans->cc.csd, &trans->cc.local, &trans->cc.remote)); + break; + default: + LOG_TRANS_CAT_SRC(trans, DCC, LOGL_ERROR, file, line, + "Handling of information transfer capability %d not implemented\n", + trans->bearer_cap.transfer); + break; + } +} + +void trans_cc_filter_set_ms_from_bc(struct gsm_trans *trans, const struct gsm_mncc_bearer_cap *bcap) +{ + trans->cc.codecs.ms = (struct sdp_audio_codecs){0}; + trans->cc.csd.ms = (struct csd_bs_list){0}; + + if (!bcap) + return; + + switch (bcap->transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + sdp_audio_codecs_from_bearer_cap(&trans->cc.codecs.ms, bcap); + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + sdp_audio_codecs_set_csd(&trans->cc.codecs.ms); + csd_bs_list_from_bearer_cap(&trans->cc.csd.ms, bcap); + break; + default: + LOG_TRANS(trans, LOGL_ERROR, "Handling of information transfer capability %d not implemented\n", + bcap->transfer); + break; + } +} + +void trans_cc_set_remote_from_bc(struct gsm_trans *trans, const struct gsm_mncc_bearer_cap *bcap) +{ + trans->cc.remote.audio_codecs = (struct sdp_audio_codecs){0}; + trans->cc.remote.bearer_services = (struct csd_bs_list){0}; + + if (!bcap) + return; + + switch (bcap->transfer) { + case GSM48_BCAP_ITCAP_SPEECH: + sdp_audio_codecs_from_bearer_cap(&trans->cc.remote.audio_codecs, bcap); + break; + case GSM48_BCAP_ITCAP_3k1_AUDIO: + case GSM48_BCAP_ITCAP_FAX_G3: + case GSM48_BCAP_ITCAP_UNR_DIG_INF: + sdp_audio_codecs_set_csd(&trans->cc.remote.audio_codecs); + csd_bs_list_from_bearer_cap(&trans->cc.remote.bearer_services, bcap); + break; + default: + LOG_TRANS(trans, LOGL_ERROR, "Handling of information transfer capability %d not implemented\n", + bcap->transfer); + break; + } +} diff --git a/src/libsmpputil/Makefile.am b/src/libsmpputil/Makefile.am new file mode 100644 index 000000000..b180ddf6f --- /dev/null +++ b/src/libsmpputil/Makefile.am @@ -0,0 +1,25 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) +AM_CFLAGS= \ + -Wall \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) \ + $(LIBOSMOSCCP_CFLAGS) \ + $(LIBOSMOGSM_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ + $(LIBOSMOMGCPCLIENT_CFLAGS) \ + $(LIBOSMOGSUPCLIENT_CFLAGS) \ + $(LIBSMPP34_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +noinst_HEADERS = \ + $(NULL) + +noinst_LIBRARIES = libsmpputil.a + +libsmpputil_a_SOURCES = \ + smpp_utils.c \ + smpp_vty.c \ + smpp_msc.c \ + smpp_smsc.c \ + $(NULL) diff --git a/src/libmsc/smpp_openbsc.c b/src/libsmpputil/smpp_msc.c index 54cd75b9a..0c2a9282f 100644 --- a/src/libmsc/smpp_openbsc.c +++ b/src/libsmpputil/smpp_msc.c @@ -1,6 +1,6 @@ /* OpenBSC SMPP 3.4 interface, SMSC-side implementation */ -/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org> +/* (C) 2012-2022 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -24,6 +24,7 @@ #include <string.h> #include <stdint.h> #include <errno.h> +#include <time.h> #include <smpp34.h> #include <smpp34_structs.h> @@ -47,8 +48,7 @@ #include <osmocom/msc/gsm_subscriber.h> #include <osmocom/msc/vlr.h> #include <osmocom/msc/msc_a.h> - -#include "smpp_smsc.h" +#include <osmocom/smpp/smpp_smsc.h> #define VSUB_USE_SMPP "SMPP" #define VSUB_USE_SMPP_CMD "SMPP-cmd" @@ -122,6 +122,8 @@ static int smpp34_submit_tlv_msg_payload(const struct tlv_t *t, static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, const struct submit_sm_t *submit) { + time_t t_now = time(NULL); + time_t t_validity_absolute; const uint8_t *sms_msg = NULL; unsigned int sms_msg_len = 0; struct vlr_subscr *dest; @@ -239,10 +241,16 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, } if (mode == MODE_7BIT) { - uint8_t ud_len = 0, padbits = 0; + unsigned int ud_len = 0, padbits = 0; sms->data_coding_scheme = GSM338_DCS_1111_7BIT; if (sms->ud_hdr_ind) { ud_len = *sms_msg + 1; + if (ud_len > sms_msg_len) { + sms_free(sms); + LOGP(DLSMS, LOGL_ERROR, "invalid ud_len=%u > sms_msg_len=%u\n", ud_len, + sms_msg_len); + return ESME_RINVPARLEN; + } printf("copying %u bytes user data...\n", ud_len); memcpy(sms->user_data, sms_msg, OSMO_MIN(ud_len, sizeof(sms->user_data))); @@ -258,12 +266,25 @@ static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net, sms->user_data_len = sms_msg_len; } + t_validity_absolute = smpp_parse_time_format((const char *) submit->validity_period, &t_now); + if (!t_validity_absolute) + sms->validity_minutes = net->sms_queue_cfg->default_validity_mins; + else + sms->validity_minutes = (t_validity_absolute - t_now) / 60; + + if (sms->validity_minutes < net->sms_queue_cfg->minimum_validity_mins) { + LOGP(DLSMS, LOGL_INFO, "SMS to %s: Overriding ESME-provided validity period (%lu) " + "with minimum SMSC validity period (%u) minutes\n", submit->destination_addr, + sms->validity_minutes, net->sms_queue_cfg->minimum_validity_mins); + sms->validity_minutes = net->sms_queue_cfg->minimum_validity_mins; + } + *psms = sms; return ESME_ROK; } /*! \brief handle incoming libsmpp34 ssubmit_sm_t from remote ESME */ -int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, +int handle_smpp_submit(struct smpp_esme *esme, struct submit_sm_t *submit, struct submit_sm_resp_t *submit_r) { struct gsm_sms *sms; @@ -314,7 +335,7 @@ int handle_smpp_submit(struct osmo_esme *esme, struct submit_sm_t *submit, static void alert_all_esme(struct smsc *smsc, struct vlr_subscr *vsub, uint8_t smpp_avail_status) { - struct osmo_esme *esme; + struct smpp_esme *esme; llist_for_each_entry(esme, &smsc->esme_list, list) { /* we currently send an alert notification to each ESME that is @@ -326,9 +347,7 @@ static void alert_all_esme(struct smsc *smsc, struct vlr_subscr *vsub, continue; } if (esme->acl && !esme->acl->alert_notifications) { - LOGP(DSMPP, LOGL_DEBUG, - "[%s] is not set to receive Alert Notifications\n", - esme->system_id); + LOGPESME(esme->esme, LOGL_DEBUG, "is not set to receive Alert Notifications\n"); continue; } if (esme->acl && esme->acl->deliver_src_imsi) { @@ -572,7 +591,7 @@ static void smpp_cmd_free(struct osmo_smpp_cmd *cmd) talloc_free(cmd); } -void smpp_cmd_flush_pending(struct osmo_esme *esme) +void smpp_cmd_flush_pending(struct smpp_esme *esme) { struct osmo_smpp_cmd *cmd, *next; @@ -640,7 +659,7 @@ static void smpp_deliver_sm_cb(void *data) smpp_cmd_err(data, ESME_RSYSERR); } -static int smpp_cmd_enqueue(struct osmo_esme *esme, +static int smpp_cmd_enqueue(struct smpp_esme *esme, struct vlr_subscr *vsub, struct gsm_sms *sms, uint32_t sequence_number) { @@ -669,7 +688,7 @@ static int smpp_cmd_enqueue(struct osmo_esme *esme, return 0; } -struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme, +struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct smpp_esme *esme, uint32_t sequence_nr) { struct osmo_smpp_cmd *cmd; @@ -681,7 +700,7 @@ struct osmo_smpp_cmd *smpp_cmd_find_by_seqnum(struct osmo_esme *esme, return NULL; } -static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, +static int deliver_to_esme(struct smpp_esme *esme, struct gsm_sms *sms, struct msc_a *msc_a) { struct deliver_sm_t deliver; @@ -769,6 +788,7 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, sms->msg_ref); ret = smpp_tx_deliver(esme, &deliver); + destroy_tlv(deliver.tlv); if (ret < 0) return ret; @@ -780,8 +800,6 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms, deliver.sequence_number); } -static struct smsc *g_smsc; - bool smpp_route_smpp_first() { return (bool)(g_smsc->smpp_first); @@ -789,7 +807,7 @@ bool smpp_route_smpp_first() int smpp_try_deliver(struct gsm_sms *sms, struct msc_a *msc_a) { - struct osmo_esme *esme; + struct smpp_esme *esme; struct osmo_smpp_addr dst; int rc; @@ -811,8 +829,8 @@ struct smsc *smsc_from_vty(struct vty *v) return g_smsc; } -/*! \brief Allocate the OpenBSC SMPP interface struct and init VTY. */ -int smpp_openbsc_alloc_init(void *ctx) +/*! \brief Allocate the OsmoMSC SMPP interface struct and init VTY. */ +int smpp_msc_alloc_init(void *ctx) { g_smsc = smpp_smsc_alloc_init(ctx); if (!g_smsc) { @@ -823,9 +841,9 @@ int smpp_openbsc_alloc_init(void *ctx) return smpp_vty_init(); } -/*! \brief Launch the OpenBSC SMPP interface with the parameters set from VTY. +/*! \brief Launch the OsmoMSC SMPP interface with the parameters set from VTY. */ -int smpp_openbsc_start(struct gsm_network *net) +int smpp_msc_start(struct gsm_network *net) { int rc; g_smsc->priv = net; @@ -846,4 +864,3 @@ int smpp_openbsc_start(struct gsm_network *net) return 0; } - diff --git a/src/libmsc/smpp_smsc.c b/src/libsmpputil/smpp_smsc.c index 4581865b9..34e24c513 100644 --- a/src/libmsc/smpp_smsc.c +++ b/src/libsmpputil/smpp_smsc.c @@ -40,15 +40,9 @@ #include <osmocom/core/talloc.h> #include <osmocom/gsm/protocol/gsm_04_11.h> -#include "smpp_smsc.h" - #include <osmocom/msc/debug.h> #include <osmocom/msc/gsm_data.h> - -/*! \brief Ugly wrapper. libsmpp34 should do this itself! */ -#define SMPP34_UNPACK(rc, type, str, data, len) \ - memset(str, 0, sizeof(*str)); \ - rc = smpp34_unpack(type, str, data, len) +#include <osmocom/smpp/smpp_smsc.h> enum emse_bind { ESME_BIND_RX = 0x01, @@ -165,12 +159,12 @@ void smpp_acl_delete(struct osmo_smpp_acl *acl) /* kill any active ESMEs */ if (acl->esme) { - struct osmo_esme *esme = acl->esme; + struct esme *esme = acl->esme->esme; osmo_fd_unregister(&esme->wqueue.bfd); close(esme->wqueue.bfd.fd); esme->wqueue.bfd.fd = -1; - esme->acl = NULL; - smpp_esme_put(esme); + smpp_esme_put(acl->esme); + acl->esme = NULL; } /* delete all routes for this ACL */ @@ -237,17 +231,17 @@ int smpp_route_pfx_del(struct osmo_smpp_acl *acl, /*! \brief increaes the use/reference count */ -void smpp_esme_get(struct osmo_esme *esme) +void smpp_esme_get(struct smpp_esme *esme) { esme->use++; } -static void esme_destroy(struct osmo_esme *esme) +static void esme_destroy(struct smpp_esme *esme) { - osmo_wqueue_clear(&esme->wqueue); - if (esme->wqueue.bfd.fd >= 0) { - osmo_fd_unregister(&esme->wqueue.bfd); - close(esme->wqueue.bfd.fd); + osmo_wqueue_clear(&esme->esme->wqueue); + if (esme->esme->wqueue.bfd.fd >= 0) { + osmo_fd_unregister(&esme->esme->wqueue.bfd); + close(esme->esme->wqueue.bfd.fd); } smpp_cmd_flush_pending(esme); llist_del(&esme->list); @@ -256,7 +250,7 @@ static void esme_destroy(struct osmo_esme *esme) talloc_free(esme); } -static uint32_t esme_inc_seq_nr(struct osmo_esme *esme) +uint32_t esme_inc_seq_nr(struct esme *esme) { esme->own_seq_nr++; if (esme->own_seq_nr > 0x7fffffff) @@ -266,7 +260,7 @@ static uint32_t esme_inc_seq_nr(struct osmo_esme *esme) } /*! \brief decrease the use/reference count, free if it is 0 */ -void smpp_esme_put(struct osmo_esme *esme) +void smpp_esme_put(struct smpp_esme *esme) { esme->use--; if (esme->use <= 0) @@ -274,7 +268,7 @@ void smpp_esme_put(struct osmo_esme *esme) } /*! \brief try to find a SMPP route (ESME) for given destination */ -int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **pesme) +int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct smpp_esme **pesme) { struct osmo_smpp_route *r; struct osmo_smpp_acl *acl = NULL; @@ -314,16 +308,14 @@ int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struc } if (acl && acl->esme) { - struct osmo_esme *esme; + struct smpp_esme *esme; DEBUGP(DSMPP, "ACL even has ESME, we can route to it!\n"); esme = acl->esme; if (esme->bind_flags & ESME_BIND_RX) { *pesme = esme; return 0; } else - LOGP(DSMPP, LOGL_NOTICE, "[%s] is matching route, " - "but not bound for Rx, discarding MO SMS\n", - esme->system_id); + LOGPESME(esme->esme, LOGL_NOTICE, "is matching route, but not bound for Rx, discarding MO SMS\n"); } *pesme = NULL; @@ -333,37 +325,31 @@ int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struc return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED; } - -/*! \brief initialize the libsmpp34 data structure for a response */ -#define INIT_RESP(type, resp, req) { \ - memset((resp), 0, sizeof(*(resp))); \ - (resp)->command_length = 0; \ - (resp)->command_id = type; \ - (resp)->command_status = ESME_ROK; \ - (resp)->sequence_number = (req)->sequence_number; \ -} - /*! \brief pack a libsmpp34 data strcutrure and send it to the ESME */ -#define PACK_AND_SEND(esme, ptr) pack_and_send(esme, (ptr)->command_id, ptr) -static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr) +int pack_and_send(struct esme *esme, uint32_t type, void *ptr) { - struct msgb *msg = msgb_alloc(4096, "SMPP_Tx"); + struct msgb *msg; int rc, rlen; + + /* the socket was closed. Avoid allocating + enqueueing msgb, see + * https://osmocom.org/issues/3278 */ + if (esme->wqueue.bfd.fd == -1) + return -EIO; + + msg = msgb_alloc(4096, "SMPP_Tx"); if (!msg) return -ENOMEM; rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr); if (rc != 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme, "during smpp34_pack()\n"); msgb_free(msg); return -EINVAL; } msgb_put(msg, rlen); if (osmo_wqueue_enqueue(&esme->wqueue, msg) != 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Write queue full. Dropping message\n", - esme->system_id); + LOGPESME(esme, LOGL_ERROR, "Write queue full. Dropping message\n"); msgb_free(msg); return -EAGAIN; } @@ -371,7 +357,7 @@ static int pack_and_send(struct osmo_esme *esme, uint32_t type, void *ptr) } /*! \brief transmit a generic NACK to a remote ESME */ -static int smpp_tx_gen_nack(struct osmo_esme *esme, uint32_t seq, uint32_t status) +static int smpp_tx_gen_nack(struct esme *esme, uint32_t seq, uint32_t status) { struct generic_nack_t nack; char buf[SMALL_BUFF]; @@ -381,19 +367,11 @@ static int smpp_tx_gen_nack(struct osmo_esme *esme, uint32_t seq, uint32_t statu nack.sequence_number = seq; nack.command_status = status; - LOGP(DSMPP, LOGL_ERROR, "[%s] Tx GENERIC NACK: %s\n", - esme->system_id, str_command_status(status, buf)); + LOGPESME(esme, LOGL_ERROR, "Tx GENERIC NACK: %s\n", str_command_status(status, buf)); return PACK_AND_SEND(esme, &nack); } -/*! \brief retrieve SMPP command ID from a msgb */ -static inline uint32_t smpp_msgb_cmdid(struct msgb *msg) -{ - uint8_t *tmp = msgb_data(msg) + 4; - return ntohl(*(uint32_t *)tmp); -} - /*! \brief retrieve SMPP sequence number from a msgb */ static inline uint32_t smpp_msgb_seq(struct msgb *msg) { @@ -402,7 +380,7 @@ static inline uint32_t smpp_msgb_seq(struct msgb *msg) } /*! \brief handle an incoming SMPP generic NACK */ -static int smpp_handle_gen_nack(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_gen_nack(struct esme *esme, struct msgb *msg) { struct generic_nack_t nack; char buf[SMALL_BUFF]; @@ -411,18 +389,16 @@ static int smpp_handle_gen_nack(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, GENERIC_NACK, &nack, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme, "in smpp34_unpack()\n"); return rc; } - LOGP(DSMPP, LOGL_ERROR, "[%s] Rx GENERIC NACK: %s\n", - esme->system_id, str_command_status(nack.command_status, buf)); + LOGPESME(esme, LOGL_ERROR, "Rx GENERIC NACK: %s\n", str_command_status(nack.command_status, buf)); return 0; } -static int _process_bind(struct osmo_esme *esme, uint8_t if_version, +static int _process_bind(struct smpp_esme *esme, uint8_t if_version, uint32_t bind_flags, const char *sys_id, const char *passwd) { @@ -435,9 +411,9 @@ static int _process_bind(struct osmo_esme *esme, uint8_t if_version, return ESME_RALYBND; esme->smpp_version = if_version; - snprintf(esme->system_id, sizeof(esme->system_id), "%s", sys_id); + snprintf(esme->esme->system_id, sizeof(esme->esme->system_id), "%s", sys_id); - acl = smpp_acl_by_system_id(esme->smsc, esme->system_id); + acl = smpp_acl_by_system_id(esme->smsc, esme->esme->system_id); if (!esme->smsc->accept_all) { if (!acl) { /* This system is unknown */ @@ -461,7 +437,7 @@ static int _process_bind(struct osmo_esme *esme, uint8_t if_version, /*! \brief handle an incoming SMPP BIND RECEIVER */ -static int smpp_handle_bind_rx(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_bind_rx(struct smpp_esme *esme, struct msgb *msg) { struct bind_receiver_t bind; struct bind_receiver_resp_t bind_r; @@ -470,8 +446,7 @@ static int smpp_handle_bind_rx(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, BIND_RECEIVER, &bind, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } @@ -484,22 +459,21 @@ static int smpp_handle_bind_rx(struct osmo_esme *esme, struct msgb *msg) (const char *)bind.system_id, (const char *)bind.password); bind_r.command_status = rc; - return PACK_AND_SEND(esme, &bind_r); + return PACK_AND_SEND(esme->esme, &bind_r); } /*! \brief handle an incoming SMPP BIND TRANSMITTER */ -static int smpp_handle_bind_tx(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_bind_tx(struct smpp_esme *esme, struct msgb *msg) { struct bind_transmitter_t bind; struct bind_transmitter_resp_t bind_r; - struct tlv_t tlv; + struct tlv_t tlv = {}; int rc; SMPP34_UNPACK(rc, BIND_TRANSMITTER, &bind, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } @@ -521,13 +495,13 @@ static int smpp_handle_bind_tx(struct osmo_esme *esme, struct msgb *msg) tlv.value.val16 = esme->smpp_version; build_tlv(&bind_r.tlv, &tlv); - rc = PACK_AND_SEND(esme, &bind_r); + rc = PACK_AND_SEND(esme->esme, &bind_r); destroy_tlv(bind_r.tlv); return rc; } /*! \brief handle an incoming SMPP BIND TRANSCEIVER */ -static int smpp_handle_bind_trx(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_bind_trx(struct smpp_esme *esme, struct msgb *msg) { struct bind_transceiver_t bind; struct bind_transceiver_resp_t bind_r; @@ -536,8 +510,7 @@ static int smpp_handle_bind_trx(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, BIND_TRANSCEIVER, &bind, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } @@ -550,11 +523,11 @@ static int smpp_handle_bind_trx(struct osmo_esme *esme, struct msgb *msg) (const char *)bind.system_id, (const char *)bind.password); bind_r.command_status = rc; - return PACK_AND_SEND(esme, &bind_r); + return PACK_AND_SEND(esme->esme, &bind_r); } /*! \brief handle an incoming SMPP UNBIND */ -static int smpp_handle_unbind(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_unbind(struct smpp_esme *esme, struct msgb *msg) { struct unbind_t unbind; struct unbind_resp_t unbind_r; @@ -563,14 +536,13 @@ static int smpp_handle_unbind(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, UNBIND, &unbind, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } INIT_RESP(UNBIND_RESP, &unbind_r, &unbind); - LOGP(DSMPP, LOGL_INFO, "[%s] Rx UNBIND\n", esme->system_id); + LOGPESME(esme->esme, LOGL_INFO, "Rx UNBIND\n"); if (esme->bind_flags == 0) { unbind_r.command_status = ESME_RINVBNDSTS; @@ -579,11 +551,11 @@ static int smpp_handle_unbind(struct osmo_esme *esme, struct msgb *msg) esme->bind_flags = 0; err: - return PACK_AND_SEND(esme, &unbind_r); + return PACK_AND_SEND(esme->esme, &unbind_r); } /*! \brief handle an incoming SMPP ENQUIRE LINK */ -static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_enq_link(struct smpp_esme *esme, struct msgb *msg) { struct enquire_link_t enq; struct enquire_link_resp_t enq_r; @@ -592,22 +564,21 @@ static int smpp_handle_enq_link(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, ENQUIRE_LINK, &enq, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } - LOGP(DSMPP, LOGL_DEBUG, "[%s] Rx Enquire Link\n", esme->system_id); + LOGPESME(esme->esme, LOGL_DEBUG, "Rx Enquire Link\n"); INIT_RESP(ENQUIRE_LINK_RESP, &enq_r, &enq); - LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx Enquire Link Response\n", esme->system_id); + LOGPESME(esme->esme, LOGL_DEBUG, "Tx Enquire Link Response\n"); - return PACK_AND_SEND(esme, &enq_r); + return PACK_AND_SEND(esme->esme, &enq_r); } /*! \brief send a SUBMIT-SM RESPONSE to a remote ESME */ -int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, +int smpp_tx_submit_r(struct smpp_esme *esme, uint32_t sequence_nr, uint32_t command_status, char *msg_id) { struct submit_sm_resp_t submit_r; @@ -619,7 +590,7 @@ int smpp_tx_submit_r(struct osmo_esme *esme, uint32_t sequence_nr, submit_r.sequence_number= sequence_nr; snprintf((char *) submit_r.message_id, sizeof(submit_r.message_id), "%s", msg_id); - return PACK_AND_SEND(esme, &submit_r); + return PACK_AND_SEND(esme->esme, &submit_r); } static const struct value_string smpp_avail_strs[] = { @@ -630,7 +601,7 @@ static const struct value_string smpp_avail_strs[] = { }; /*! \brief send an ALERT_NOTIFICATION to a remote ESME */ -int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi, +int smpp_tx_alert(struct smpp_esme *esme, uint8_t ton, uint8_t npi, const char *addr, uint8_t avail_status) { struct alert_notification_t alert; @@ -641,7 +612,7 @@ int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi, alert.command_length = 0; alert.command_id = ALERT_NOTIFICATION; alert.command_status = ESME_ROK; - alert.sequence_number = esme_inc_seq_nr(esme); + alert.sequence_number = esme_inc_seq_nr(esme->esme); alert.source_addr_ton = ton; alert.source_addr_npi = npi; snprintf((char *)alert.source_addr, sizeof(alert.source_addr), "%s", addr); @@ -651,29 +622,28 @@ int smpp_tx_alert(struct osmo_esme *esme, uint8_t ton, uint8_t npi, tlv.value.val08 = avail_status; build_tlv(&alert.tlv, &tlv); - LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx ALERT_NOTIFICATION (%s/%u/%u): %s\n", - esme->system_id, alert.source_addr, alert.source_addr_ton, - alert.source_addr_npi, - get_value_string(smpp_avail_strs, avail_status)); + LOGPESME(esme->esme, LOGL_DEBUG, "Tx ALERT_NOTIFICATION (%s/%u/%u): %s\n", + alert.source_addr, alert.source_addr_ton, + alert.source_addr_npi, + get_value_string(smpp_avail_strs, avail_status)); - rc = PACK_AND_SEND(esme, &alert); + rc = PACK_AND_SEND(esme->esme, &alert); destroy_tlv(alert.tlv); return rc; } /* \brief send a DELIVER-SM message to given ESME */ -int smpp_tx_deliver(struct osmo_esme *esme, struct deliver_sm_t *deliver) +int smpp_tx_deliver(struct smpp_esme *esme, struct deliver_sm_t *deliver) { - deliver->sequence_number = esme_inc_seq_nr(esme); + deliver->sequence_number = esme_inc_seq_nr(esme->esme); - LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx DELIVER-SM (from %s)\n", - esme->system_id, deliver->source_addr); + LOGPESME(esme->esme, LOGL_DEBUG, "Tx DELIVER-SM (from %s)\n", deliver->source_addr); - return PACK_AND_SEND(esme, deliver); + return PACK_AND_SEND(esme->esme, deliver); } /*! \brief handle an incoming SMPP DELIVER-SM RESPONSE */ -static int smpp_handle_deliver_resp(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_deliver_resp(struct smpp_esme *esme, struct msgb *msg) { struct deliver_sm_resp_t deliver_r; struct osmo_smpp_cmd *cmd; @@ -683,16 +653,14 @@ static int smpp_handle_deliver_resp(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, DELIVER_SM_RESP, &deliver_r, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } cmd = smpp_cmd_find_by_seqnum(esme, deliver_r.sequence_number); if (!cmd) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Rx DELIVER-SM RESP !? (%s)\n", - esme->system_id, get_value_string(smpp_status_strs, - deliver_r.command_status)); + LOGPESME(esme->esme, LOGL_ERROR, "Rx DELIVER-SM RESP !? (%s)\n", + get_value_string(smpp_status_strs, deliver_r.command_status)); return -1; } @@ -701,15 +669,14 @@ static int smpp_handle_deliver_resp(struct osmo_esme *esme, struct msgb *msg) else smpp_cmd_err(cmd, deliver_r.command_status); - LOGP(DSMPP, LOGL_INFO, "[%s] Rx DELIVER-SM RESP (%s)\n", - esme->system_id, get_value_string(smpp_status_strs, - deliver_r.command_status)); + LOGPESME(esme->esme, LOGL_INFO, "Rx DELIVER-SM RESP (%s)\n", + get_value_string(smpp_status_strs, deliver_r.command_status)); return 0; } /*! \brief handle an incoming SMPP SUBMIT-SM */ -static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg) +static int smpp_handle_submit(struct smpp_esme *esme, struct msgb *msg) { struct submit_sm_t submit; struct submit_sm_resp_t submit_r; @@ -719,8 +686,7 @@ static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg) SMPP34_UNPACK(rc, SUBMIT_SM, &submit, msgb_data(msg), msgb_length(msg)); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error in smpp34_unpack():%s\n", - esme->system_id, smpp34_strerror); + LOGPESMERR(esme->esme, "in smpp34_unpack()\n"); return rc; } @@ -728,34 +694,34 @@ static int smpp_handle_submit(struct osmo_esme *esme, struct msgb *msg) if (!(esme->bind_flags & ESME_BIND_TX)) { submit_r.command_status = ESME_RINVBNDSTS; - return PACK_AND_SEND(esme, &submit_r); + destroy_tlv(submit.tlv); + return PACK_AND_SEND(esme->esme, &submit_r); } - LOGP(DSMPP, LOGL_INFO, "[%s] Rx SUBMIT-SM (%s/%u/%u)\n", - esme->system_id, submit.destination_addr, - submit.dest_addr_ton, submit.dest_addr_npi); + LOGPESME(esme->esme, LOGL_INFO, "Rx SUBMIT-SM (%s/%u/%u)\n", + submit.destination_addr, submit.dest_addr_ton, submit.dest_addr_npi); INIT_RESP(SUBMIT_SM_RESP, &submit_r, &submit); rc = handle_smpp_submit(esme, &submit, &submit_r); + destroy_tlv(submit.tlv); if (rc == 0) - return PACK_AND_SEND(esme, &submit_r); + return PACK_AND_SEND(esme->esme, &submit_r); return rc; } /*! \brief one complete SMPP PDU from the ESME has been received */ -static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg __uses) +static int smpp_pdu_rx(struct smpp_esme *esme, struct msgb *msg __uses) { uint32_t cmd_id = smpp_msgb_cmdid(msg); int rc = 0; - LOGP(DSMPP, LOGL_DEBUG, "[%s] smpp_pdu_rx(%s)\n", esme->system_id, - msgb_hexdump(msg)); + LOGPESME(esme->esme, LOGL_DEBUG, "smpp_pdu_rx(%s)\n", msgb_hexdump(msg)); switch (cmd_id) { case GENERIC_NACK: - rc = smpp_handle_gen_nack(esme, msg); + rc = smpp_handle_gen_nack(esme->esme, msg); break; case BIND_RECEIVER: rc = smpp_handle_bind_rx(esme, msg); @@ -786,13 +752,11 @@ static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg __uses) case QUERY_SM: case REPLACE_SM: case SUBMIT_MULTI: - LOGP(DSMPP, LOGL_NOTICE, "[%s] Unimplemented PDU Command " - "0x%08x\n", esme->system_id, cmd_id); + LOGPESME(esme->esme, LOGL_NOTICE, "Unimplemented PDU Command 0x%08x\n", cmd_id); break; default: - LOGP(DSMPP, LOGL_ERROR, "[%s] Unknown PDU Command 0x%08x\n", - esme->system_id, cmd_id); - rc = smpp_tx_gen_nack(esme, smpp_msgb_seq(msg), ESME_RINVCMDID); + LOGPESME(esme->esme, LOGL_ERROR, "Unknown PDU Command 0x%08x\n", cmd_id); + rc = smpp_tx_gen_nack(esme->esme, smpp_msgb_seq(msg), ESME_RINVCMDID); break; } @@ -819,7 +783,8 @@ static int smpp_pdu_rx(struct osmo_esme *esme, struct msgb *msg __uses) /* !\brief call-back when per-ESME TCP socket has some data to be read */ static int esme_link_read_cb(struct osmo_fd *ofd) { - struct osmo_esme *esme = ofd->data; + struct smpp_esme *e = ofd->data; + struct esme *esme = e->esme; uint32_t len; uint8_t *lenptr = (uint8_t *) &len; uint8_t *cur; @@ -831,8 +796,7 @@ static int esme_link_read_cb(struct osmo_fd *ofd) rdlen = sizeof(uint32_t) - esme->read_idx; rc = read(ofd->fd, lenptr + esme->read_idx, rdlen); if (rc < 0) - LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %zd (%s)\n", - esme->system_id, rc, strerror(errno)); + LOGPESME(esme, LOGL_ERROR, "read returned %zd (%s)\n", rc, strerror(errno)); OSMO_FD_CHECK_READ(rc, dead_socket); esme->read_idx += rc; @@ -840,8 +804,7 @@ static int esme_link_read_cb(struct osmo_fd *ofd) if (esme->read_idx >= sizeof(uint32_t)) { esme->read_len = ntohl(len); if (esme->read_len < 8 || esme->read_len > UINT16_MAX) { - LOGP(DSMPP, LOGL_ERROR, "[%s] length invalid %u\n", - esme->system_id, esme->read_len); + LOGPESME(esme, LOGL_ERROR, "length invalid %u\n", esme->read_len); goto dead_socket; } @@ -860,15 +823,15 @@ static int esme_link_read_cb(struct osmo_fd *ofd) rdlen = esme->read_len - esme->read_idx; rc = read(ofd->fd, msg->tail, OSMO_MIN(rdlen, msgb_tailroom(msg))); if (rc < 0) - LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %zd (%s)\n", - esme->system_id, rc, strerror(errno)); + LOGPESME(esme, LOGL_ERROR, "read returned %zd (%s)\n", + rc, strerror(errno)); OSMO_FD_CHECK_READ(rc, dead_socket); esme->read_idx += rc; msgb_put(msg, rc); if (esme->read_idx >= esme->read_len) { - rc = smpp_pdu_rx(esme, esme->read_msg); + rc = smpp_pdu_rx(e, esme->read_msg); msgb_free(esme->read_msg); esme->read_msg = NULL; esme->read_idx = 0; @@ -884,64 +847,77 @@ dead_socket: osmo_fd_unregister(&esme->wqueue.bfd); close(esme->wqueue.bfd.fd); esme->wqueue.bfd.fd = -1; - if (esme->acl) - esme->acl->esme = NULL; - smpp_esme_put(esme); + if (e->acl) + e->acl->esme = NULL; + smpp_esme_put(e); - return 0; + return -EBADF; } /* call-back of write queue once it wishes to write a message to the socket */ static int esme_link_write_cb(struct osmo_fd *ofd, struct msgb *msg) { - struct osmo_esme *esme = ofd->data; + struct smpp_esme *esme = ofd->data; int rc; rc = write(ofd->fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) { - osmo_fd_unregister(&esme->wqueue.bfd); - close(esme->wqueue.bfd.fd); - esme->wqueue.bfd.fd = -1; + osmo_fd_unregister(&esme->esme->wqueue.bfd); + close(esme->esme->wqueue.bfd.fd); + esme->esme->wqueue.bfd.fd = -1; if (esme->acl) esme->acl->esme = NULL; smpp_esme_put(esme); } else if (rc < msgb_length(msg)) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Short write\n", esme->system_id); + LOGPESME(esme->esme, LOGL_ERROR, "Short write\n"); return -1; } return 0; } +struct esme *esme_alloc(void *ctx) +{ + struct esme *e = talloc_zero(ctx, struct esme); + if (!e) + return NULL; + + e->own_seq_nr = rand(); + esme_inc_seq_nr(e); + osmo_wqueue_init(&e->wqueue, 10); + + return e; +} + /* callback for already-accepted new TCP socket */ static int link_accept_cb(struct smsc *smsc, int fd, struct sockaddr_storage *s, socklen_t s_len) { - struct osmo_esme *esme = talloc_zero(smsc, struct osmo_esme); + struct smpp_esme *esme = talloc_zero(smsc, struct smpp_esme); if (!esme) { close(fd); return -ENOMEM; } + esme->esme = esme_alloc(esme); + if (!esme->esme) { + close(fd); + return -ENOMEM; + } + INIT_LLIST_HEAD(&esme->smpp_cmd_list); smpp_esme_get(esme); - esme->own_seq_nr = rand(); - esme_inc_seq_nr(esme); esme->smsc = smsc; - osmo_wqueue_init(&esme->wqueue, 10); - osmo_fd_setup(&esme->wqueue.bfd, fd, OSMO_FD_READ, osmo_wqueue_bfd_cb, esme, 0); + osmo_fd_setup(&esme->esme->wqueue.bfd, fd, OSMO_FD_READ, osmo_wqueue_bfd_cb, esme, 0); - if (osmo_fd_register(&esme->wqueue.bfd) != 0) { + if (osmo_fd_register(&esme->esme->wqueue.bfd) != 0) { close(fd); talloc_free(esme); return -EIO; } - esme->wqueue.read_cb = esme_link_read_cb; - esme->wqueue.write_cb = esme_link_write_cb; - - esme->sa_len = OSMO_MIN(sizeof(esme->sa), s_len); - memcpy(&esme->sa, s, esme->sa_len); + esme->esme->wqueue.read_cb = esme_link_read_cb; + esme->esme->wqueue.write_cb = esme_link_write_cb; llist_add_tail(&esme->list, &smsc->esme_list); @@ -992,6 +968,16 @@ int smpp_smsc_conf(struct smsc *smsc, const char *bind_addr, uint16_t port) return 0; } +/*! /brief Close SMPP connection. */ +static void smpp_smsc_stop(struct smsc *smsc) +{ + if (smsc->listen_ofd.fd > 0) { + close(smsc->listen_ofd.fd); + smsc->listen_ofd.fd = 0; + osmo_fd_unregister(&smsc->listen_ofd); + } +} + /*! \brief Bind to given address and port and accept connections. * \param[in] bind_addr Local IP address, may be NULL for any. * \param[in] port TCP port number, may be 0 for default SMPP (2775). @@ -1000,23 +986,17 @@ int smpp_smsc_start(struct smsc *smsc, const char *bind_addr, uint16_t port) { int rc; - /* default port for SMPP */ - if (!port) - port = 2775; - - smpp_smsc_stop(smsc); - LOGP(DSMPP, LOGL_NOTICE, "SMPP at %s %d\n", - bind_addr? bind_addr : "0.0.0.0", port); + bind_addr ? bind_addr : "0.0.0.0", port ? port : SMPP_PORT); rc = osmo_sock_init_ofd(&smsc->listen_ofd, AF_UNSPEC, SOCK_STREAM, - IPPROTO_TCP, bind_addr, port, + IPPROTO_TCP, bind_addr, port ? port : SMPP_PORT, OSMO_SOCK_F_BIND); if (rc < 0) return rc; /* store new address and port */ - rc = smpp_smsc_conf(smsc, bind_addr, port); + rc = smpp_smsc_conf(smsc, bind_addr, port ? port : SMPP_PORT); if (rc) smpp_smsc_stop(smsc); return rc; @@ -1028,19 +1008,11 @@ int smpp_smsc_restart(struct smsc *smsc, const char *bind_addr, uint16_t port) { int rc; + smpp_smsc_stop(smsc); + rc = smpp_smsc_start(smsc, bind_addr, port); if (rc) /* if there is an error, try to re-bind to the old port */ return smpp_smsc_start(smsc, smsc->bind_addr, smsc->listen_port); return 0; } - -/*! /brief Close SMPP connection. */ -void smpp_smsc_stop(struct smsc *smsc) -{ - if (smsc->listen_ofd.fd > 0) { - close(smsc->listen_ofd.fd); - smsc->listen_ofd.fd = 0; - osmo_fd_unregister(&smsc->listen_ofd); - } -} diff --git a/src/libsmpputil/smpp_utils.c b/src/libsmpputil/smpp_utils.c new file mode 100644 index 000000000..bada97217 --- /dev/null +++ b/src/libsmpputil/smpp_utils.c @@ -0,0 +1,174 @@ + +/* (C) 2012-2022 by Harald Welte <laforge@gnumonks.org> + * + * All Rights Reserved + * + * 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/>. + */ + +#include "config.h" + +#include <time.h> + +#include <osmocom/core/logging.h> +#include <osmocom/netif/stream.h> +#include <osmocom/smpp/smpp_smsc.h> + +/*! \brief retrieve SMPP command ID from a msgb */ +uint32_t smpp_msgb_cmdid(struct msgb *msg) +{ + uint8_t *tmp = msgb_data(msg) + 4; + return ntohl(*(uint32_t *)tmp); +} + +int smpp_determine_scheme(uint8_t dcs, uint8_t *data_coding, int *mode) +{ + if ((dcs & 0xF0) == 0xF0) { + if (dcs & 0x04) { + /* bit 2 == 1: 8bit data */ + *data_coding = 0x02; + *mode = MODE_8BIT; + } else { + /* bit 2 == 0: default alphabet */ + *data_coding = 0x01; + *mode = MODE_7BIT; + } + } else if ((dcs & 0xE0) == 0) { + switch (dcs & 0xC) { + case 0: + *data_coding = 0x01; + *mode = MODE_7BIT; + break; + case 4: + *data_coding = 0x02; + *mode = MODE_8BIT; + break; + case 8: + *data_coding = 0x08; /* UCS-2 */ + *mode = MODE_8BIT; + break; + default: + goto unknown_mo; + } + } else { +unknown_mo: + LOGP(DLSMS, LOGL_ERROR, "SMPP MO Unknown Data Coding 0x%02x\n", dcs); + return -1; + } + + return 0; + +} + +/* convert a 'struct tm' holding relative time to an absolute one by adding it to t_now */ +static void relative2absolute(struct tm *tm, time_t t_now) +{ + struct tm tm_now; + + localtime_r(&t_now, &tm_now); + + tm->tm_year += tm_now.tm_year; + tm->tm_mon += tm_now.tm_mon; + tm->tm_mday += tm_now.tm_mday; + tm->tm_hour += tm_now.tm_hour; + tm->tm_min += tm_now.tm_min; + tm->tm_sec += tm_now.tm_sec; +} + +#ifndef HAVE_TIMEGM +/* for systems without a timegm() function, provide a reimplementation */ +static time_t timegm(struct tm *tm) +{ + const char *orig_tz = getenv("TZ"); + time_t ret; + + setenv("TZ", "UTC", 1); + + ret = mktime(tm); + + if (orig_tz) + setenv("TZ", orig_tz, 1); + else + unsetenv("TZ"); + + return ret; +} +#endif + + +/*! Parse a SMPP time format as defined in SMPP v3.4 7.1.1. + * \param[in] vp string containing the time as encoded in SMPP v3.4 + * \param[in] t_now pointer to a time value for 'now'. Can be NULL, then we call time() ourselves. + * \returns time_t value in seconds since the epoch of the absolute decoded time */ +time_t smpp_parse_time_format(const char *vp, time_t *t_now) +{ + unsigned int year, month, day, hour, minute, second, tenth, gmt_off_quarter; + char plus_minus_relative; + int gmt_off_minutes; + struct tm tm; + time_t ret; + int rc; + + memset(&tm, 0, sizeof(tm)); + + if (vp[0] == '\0') + return 0; + + /* YYMMDDhhmmsstnnp (where p can be -, + or R) */ + rc = sscanf(vp, "%2u%2u%2u%2u%2u%2u%1u%2u%c", &year, &month, &day, &hour, &minute, + &second, &tenth, &gmt_off_quarter, &plus_minus_relative); + if (rc != 9) + return (time_t) -1; + + tm.tm_year = year; + /* month handling differs between absolute/relative below... */ + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = minute; + tm.tm_sec = second; + tm.tm_isdst = 0; + + switch (plus_minus_relative) { + case '+': /* time is in quarter hours advanced compared to UTC */ + if (year < 70) + tm.tm_year += 100; + tm.tm_mon = month - 1; + gmt_off_minutes = 15 * gmt_off_quarter; + tm.tm_min -= gmt_off_minutes; + ret = timegm(&tm); + break; + case '-': /* time is in quarter hours retared compared to UTC */ + if (year < 70) + tm.tm_year += 100; + tm.tm_mon = month - 1; + gmt_off_minutes = 15 * gmt_off_quarter; + tm.tm_min += gmt_off_minutes; + ret = timegm(&tm); + break; + case 'R': + /* relative time */ + tm.tm_mon = month; + if (t_now) + relative2absolute(&tm, *t_now); + else + relative2absolute(&tm, time(NULL)); + /* here we do want local time, as we're passing local time in above! */ + ret = mktime(&tm); + break; + default: + return (time_t) -1; + } + + return ret; +} diff --git a/src/libmsc/smpp_vty.c b/src/libsmpputil/smpp_vty.c index 31e209085..c6e642161 100644 --- a/src/libmsc/smpp_vty.c +++ b/src/libsmpputil/smpp_vty.c @@ -30,11 +30,11 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/utils.h> +#include <osmocom/core/socket.h> #include <osmocom/core/talloc.h> #include <osmocom/msc/vty.h> - -#include "smpp_smsc.h" +#include <osmocom/smpp/smpp_smsc.h> struct smsc *smsc_from_vty(struct vty *v); @@ -80,8 +80,8 @@ static int smpp_local_tcp(struct vty *vty, const char *bind_addr, uint16_t port) { struct smsc *smsc = smsc_from_vty(vty); - int is_running = smsc->listen_ofd.fd > 0; - int same_bind_addr; + bool is_running = smsc->listen_ofd.fd > 0; + bool same_bind_addr; int rc; /* If it is not up yet, don't rebind, just set values. */ @@ -522,19 +522,12 @@ DEFUN(cfg_esme_no_alert_notif, cfg_esme_no_alert_notif_cmd, } -static void dump_one_esme(struct vty *vty, struct osmo_esme *esme) +static void dump_one_esme(struct vty *vty, struct smpp_esme *esme) { - char host[128], serv[128]; - - host[0] = 0; - serv[0] = 0; - getnameinfo((const struct sockaddr *) &esme->sa, esme->sa_len, - host, sizeof(host), serv, sizeof(serv), NI_NUMERICSERV); - vty_out(vty, "ESME System ID: %s, Password: %s, SMPP Version %02x%s", - esme->system_id, esme->acl ? esme->acl->passwd : "", + esme->esme->system_id, esme->acl ? esme->acl->passwd : "", esme->smpp_version, VTY_NEWLINE); - vty_out(vty, " Connected from: %s:%s%s", host, serv, VTY_NEWLINE); + vty_out(vty, " Connection %s%s", osmo_sock_get_name(tall_vty_ctx, esme->esme->wqueue.bfd.fd), VTY_NEWLINE); if (esme->smsc->def_route == esme->acl) vty_out(vty, " Is current default route%s", VTY_NEWLINE); } @@ -544,7 +537,7 @@ DEFUN(show_esme, show_esme_cmd, SHOW_STR "SMPP Interface\n" "SMPP External SMS Entity\n") { struct smsc *smsc = smsc_from_vty(vty); - struct osmo_esme *esme; + struct smpp_esme *esme; llist_for_each_entry(esme, &smsc->esme_list, list) dump_one_esme(vty, esme); diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index fc23b370d..cb5794f30 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -36,6 +36,7 @@ #include <osmocom/msc/vlr.h> #include <osmocom/msc/debug.h> #include <osmocom/msc/gsup_client_mux.h> +#include <osmocom/msc/paging.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -51,10 +52,139 @@ #define SGSN_SUBSCR_MAX_RETRIES 3 #define SGSN_SUBSCR_RETRY_INTERVAL 10 +enum vlr_stat_item_idx { + VLR_STAT_SUBSCRIBER_COUNT, + VLR_STAT_PDP_COUNT, +}; + +static const struct osmo_stat_item_desc vlr_stat_item_desc[] = { + [VLR_STAT_SUBSCRIBER_COUNT] = { "subscribers", + "Number of subscribers present in VLR" }, + [VLR_STAT_PDP_COUNT] = { "pdp", + "Number of PDP records present in VLR" }, +}; + +static const struct osmo_stat_item_group_desc vlr_statg_desc = { + "vlr", + "visitor location register", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(vlr_stat_item_desc), + vlr_stat_item_desc, +}; + +enum vlr_rate_ctr_idx { + VLR_CTR_GSUP_RX_UNKNOWN_IMSI, + VLR_CTR_GSUP_RX_PURGE_NO_SUBSCR, + VLR_CTR_GSUP_RX_TUPLES, + VLR_CTR_GSUP_RX_UL_RES, + VLR_CTR_GSUP_RX_UL_ERR, + VLR_CTR_GSUP_RX_SAI_RES, + VLR_CTR_GSUP_RX_SAI_ERR, + VLR_CTR_GSUP_RX_ISD_REQ, + VLR_CTR_GSUP_RX_CANCEL_REQ, + VLR_CTR_GSUP_RX_CHECK_IMEI_RES, + VLR_CTR_GSUP_RX_CHECK_IMEI_ERR, + VLR_CTR_GSUP_RX_PURGE_MS_RES, + VLR_CTR_GSUP_RX_PURGE_MS_ERR, + VLR_CTR_GSUP_RX_DELETE_DATA_REQ, + VLR_CTR_GSUP_RX_UNKNOWN, + + VLR_CTR_GSUP_TX_UL_REQ, + VLR_CTR_GSUP_TX_ISD_RES, + VLR_CTR_GSUP_TX_SAI_REQ, + VLR_CTR_GSUP_TX_PURGE_MS_REQ, + VLR_CTR_GSUP_TX_CHECK_IMEI_REQ, + VLR_CTR_GSUP_TX_AUTH_FAIL_REP, + VLR_CTR_GSUP_TX_CANCEL_RES, + + VLR_CTR_DETACH_BY_REQ, + VLR_CTR_DETACH_BY_CANCEL, + VLR_CTR_DETACH_BY_T3212, +}; + +static const struct rate_ctr_desc vlr_ctr_desc[] = { + [VLR_CTR_GSUP_RX_UNKNOWN_IMSI] = { "gsup:rx:unknown_imsi", + "Received GSUP messages for unknown IMSI" }, + [VLR_CTR_GSUP_RX_PURGE_NO_SUBSCR] = { "gsup:rx:purge_no_subscr", + "Received GSUP purge for unknown subscriber" }, + [VLR_CTR_GSUP_RX_TUPLES] = { "gsup:rx:auth_tuples", + "Received GSUP authentication tuples" }, + [VLR_CTR_GSUP_RX_UL_RES] = { "gsup:rx:upd_loc:res", + "Received GSUP Update Location Result messages" }, + [VLR_CTR_GSUP_RX_UL_ERR] = { "gsup:rx:upd_loc:err", + "Received GSUP Update Location Error messages" }, + [VLR_CTR_GSUP_RX_SAI_RES] = { "gsup:rx:send_auth_info:res", + "Received GSUP Send Auth Info Result messages" }, + [VLR_CTR_GSUP_RX_SAI_ERR] = { "gsup:rx:send_auth_info:err", + "Received GSUP Send Auth Info Error messages" }, + [VLR_CTR_GSUP_RX_ISD_REQ] = { "gsup:rx:ins_sub_data:req", + "Received GSUP Insert Subscriber Data Request messages" }, + [VLR_CTR_GSUP_RX_CANCEL_REQ] = { "gsup:rx:cancel:req", + "Received GSUP Cancel Subscriber messages" }, + [VLR_CTR_GSUP_RX_CHECK_IMEI_RES] = { "gsup:rx:check_imei:res", + "Received GSUP Check IMEI Result messages" }, + [VLR_CTR_GSUP_RX_CHECK_IMEI_ERR] = { "gsup:rx:check_imei:err", + "Received GSUP Check IMEI Error messages" }, + [VLR_CTR_GSUP_RX_PURGE_MS_RES] = { "gsup:rx:purge_ms:res", + "Received GSUP Purge MS Result messages" }, + [VLR_CTR_GSUP_RX_PURGE_MS_ERR] = { "gsup:rx:purge_ms:err", + "Received GSUP Purge MS Error messages" }, + [VLR_CTR_GSUP_RX_DELETE_DATA_REQ] = { "gsup:rx:del_sub_data:req", + "Received GSUP Delete Subscriber Data Request messages" }, + [VLR_CTR_GSUP_RX_UNKNOWN] = { "gsup:rx:unknown_msgtype", + "Received GSUP message of unknown type" }, + + [VLR_CTR_GSUP_TX_UL_REQ] = { "gsup:tx:upd_loc:req", + "Transmitted GSUP Update Location Request messages" }, + [VLR_CTR_GSUP_TX_ISD_RES] = { "gsup:tx:ins_sub_data:res", + "Transmitted GSUP Insert Subscriber Data Result messages" }, + [VLR_CTR_GSUP_TX_SAI_REQ] = { "gsup:tx:send_auth_info:res", + "Transmitted GSUP Send Auth Info Request messages" }, + [VLR_CTR_GSUP_TX_PURGE_MS_REQ] = { "gsup:tx:purge_ms:req", + "Transmitted GSUP Purge MS Request messages" }, + [VLR_CTR_GSUP_TX_CHECK_IMEI_REQ] = { "gsup:tx:check_imei:req", + "Transmitted GSUP Check IMEI Request messages" }, + [VLR_CTR_GSUP_TX_AUTH_FAIL_REP] = { "gsup:tx:auth_fail:rep", + "Transmitted GSUP Auth Fail Report messages" }, + [VLR_CTR_GSUP_TX_CANCEL_RES] = { "gsup:tx:cancel:res", + "Transmitted GSUP Cancel Result messages" }, + + [VLR_CTR_DETACH_BY_REQ] = { "detach:imsi_det_req", + "VLR Subscriber Detach by IMSI DETACH REQ" }, + [VLR_CTR_DETACH_BY_CANCEL] = { "detach:gsup_cancel_req", + "VLR Subscriber Detach by GSUP CANCEL REQ" }, + [VLR_CTR_DETACH_BY_T3212] = { "detach:t3212_timeout", + "VLR Subscriber Detach by T3212 timeout" }, +}; + +static const struct rate_ctr_group_desc vlr_ctrg_desc = { + "vlr", + "visitor location register", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(vlr_ctr_desc), + vlr_ctr_desc, +}; + + +#define vlr_rate_ctr_inc(vlr, idx) \ + rate_ctr_inc(rate_ctr_group_get_ctr((vlr)->ctrg, idx)) +#define vlr_rate_ctr_add(vlr, idx, val) \ + rate_ctr_add(rate_ctr_group_get_ctr((vlr)->ctrg, idx), val) + +#define vlr_stat_item_inc(vlr, idx) \ + osmo_stat_item_inc(osmo_stat_item_group_get_item((vlr)->statg, idx), 1) +#define vlr_stat_item_dec(vlr, idx) \ + osmo_stat_item_dec(osmo_stat_item_group_get_item((vlr)->statg, idx), 1) +#define vlr_stat_item_set(vlr, idx, val) \ + osmo_stat_item_set(osmo_stat_item_group_get_item((vlr)->statg, idx), val) + + /*********************************************************************** * Convenience functions ***********************************************************************/ +static int vlr_subscr_detach(struct vlr_subscr *vsub); + const struct value_string vlr_ciph_names[] = { OSMO_VALUE_STRING(VLR_CIPH_NONE), OSMO_VALUE_STRING(VLR_CIPH_A5_1), @@ -143,7 +273,8 @@ struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr, llist_for_each_entry(vsub, &vlr->subscribers, list) { if (vlr_subscr_matches_imsi(vsub, imsi)) { - vlr_subscr_get_src(vsub, use, file, line); + if (use) + vlr_subscr_get_src(vsub, use, file, line); return vsub; } } @@ -280,6 +411,7 @@ static struct vlr_subscr *_vlr_subscr_alloc(struct vlr_instance *vlr) vlr_sgs_fsm_create(vsub); llist_add_tail(&vsub->list, &vlr->subscribers); + vlr_stat_item_inc(vlr, VLR_STAT_SUBSCRIBER_COUNT); return vsub; } @@ -290,6 +422,8 @@ int vlr_subscr_purge(struct vlr_subscr *vsub) { struct osmo_gsup_message gsup_msg = {0}; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_PURGE_MS_REQ); + gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_REQUEST; /* provide HLR number in case we know it */ @@ -318,6 +452,7 @@ void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub, void vlr_subscr_free(struct vlr_subscr *vsub) { llist_del(&vsub->list); + vlr_stat_item_dec(vsub->vlr, VLR_STAT_SUBSCRIBER_COUNT); DEBUGP(DVLR, "freeing VLR subscr %s (max total use count was %d)\n", vlr_subscr_name(vsub), vsub->max_total_use_count); @@ -444,11 +579,63 @@ struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr, return vsub; } +static void dedup_vsub(struct vlr_subscr *exists, struct vlr_subscr *vsub) +{ + struct vlr_instance *vlr = exists->vlr; + int i; + int j; + LOGP(DVLR, LOGL_NOTICE, + "There is an existing subscriber for IMSI %s used by %s, replacing with new VLR subscr: %s used by %s\n", + exists->imsi, osmo_use_count_to_str_c(OTC_SELECT, &exists->use_count), + vlr_subscr_name(vsub), + osmo_use_count_to_str_c(OTC_SELECT, &vsub->use_count)); + + /* Take over some state from the previous vsub */ + paging_request_join_vsub(vsub, exists); + if (!vsub->msisdn[0]) + OSMO_STRLCPY_ARRAY(vsub->msisdn, exists->msisdn); + if (!vsub->name[0]) + OSMO_STRLCPY_ARRAY(vsub->name, exists->name); + /* Copy valid auth tuples we may already have, to reduce the need to ask for new ones from the HLR */ + for (i = 0; i < ARRAY_SIZE(exists->auth_tuples); i++) { + if (exists->auth_tuples[i].key_seq == VLR_KEY_SEQ_INVAL) + continue; + for (j = 0; j < ARRAY_SIZE(vsub->auth_tuples); j++) { + if (vsub->auth_tuples[j].key_seq != VLR_KEY_SEQ_INVAL) + continue; + vsub->auth_tuples[j] = exists->auth_tuples[i]; + } + } + + if (exists->msc_conn_ref) + LOGVSUBP(LOGL_ERROR, vsub, + "There is an existing VLR entry for this same subscriber with an active connection." + " That should not be possible. Discarding old subscriber entry %s.\n", + exists->imsi); + + if (vlr->ops.subscr_inval) + vlr->ops.subscr_inval(exists->msc_conn_ref, exists); + vlr_subscr_free(exists); +} + void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi) { + struct vlr_subscr *exists; if (!vsub) return; + /* If the same IMSI is already set, nothing changes. */ + if (!strcmp(vsub->imsi, imsi)) + return; + + /* We've just learned about this new IMSI, our primary key in the VLR. make sure to invalidate any prior VLR + * entries for this IMSI. */ + exists = vlr_subscr_find_by_imsi(vsub->vlr, imsi, NULL); + + if (exists) + dedup_vsub(exists, vsub); + + /* Set the IMSI on the new subscriber, here. */ if (OSMO_STRLCPY_ARRAY(vsub->imsi, imsi) >= sizeof(vsub->imsi)) { LOGP(DVLR, LOGL_NOTICE, "IMSI was truncated: full IMSI=%s, truncated IMSI=%s\n", imsi, vsub->imsi); @@ -578,7 +765,8 @@ void vlr_subscr_expire_lu(void *data) continue; LOGP(DVLR, LOGL_DEBUG, "%s: Location Update expired\n", vlr_subscr_name(vsub)); - vlr_subscr_rx_imsi_detach(vsub); + vlr_rate_ctr_inc(vlr, VLR_CTR_DETACH_BY_T3212); + vlr_subscr_detach(vsub); } done: @@ -594,13 +782,15 @@ done: /* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */ /* see GSM 09.02, B.1, gprsSubscriptionData */ struct sgsn_subscriber_pdp_data { - struct llist_head list; - - unsigned int context_id; - uint16_t pdp_type; - char apn_str[GSM_APN_LENGTH]; - uint8_t qos_subscribed[20]; - size_t qos_subscribed_len; + struct llist_head list; + + unsigned int context_id; + enum gsm48_pdp_type_org pdp_type_org; + enum gsm48_pdp_type_nr pdp_type_nr; + struct osmo_sockaddr pdp_address[2]; + char apn_str[GSM_APN_LENGTH]; + uint8_t qos_subscribed[20]; + size_t qos_subscribed_len; }; struct sgsn_subscriber_pdp_data * @@ -611,6 +801,7 @@ vlr_subscr_pdp_data_alloc(struct vlr_subscr *vsub) pdata = talloc_zero(vsub, struct sgsn_subscriber_pdp_data); llist_add_tail(&pdata->list, &vsub->ps.pdp_list); + vlr_stat_item_inc(vsub->vlr, VLR_STAT_PDP_COUNT); return pdata; } @@ -622,6 +813,7 @@ static int vlr_subscr_pdp_data_clear(struct vlr_subscr *vsub) llist_for_each_entry_safe(pdp, pdp2, &vsub->ps.pdp_list, list) { llist_del(&pdp->list); + vlr_stat_item_dec(vsub->vlr, VLR_STAT_PDP_COUNT); talloc_free(pdp); count += 1; } @@ -692,6 +884,8 @@ int vlr_subscr_req_lu(struct vlr_subscr *vsub) struct osmo_gsup_message gsup_msg = {0}; int rc; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_UL_REQ); + gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST; gsup_msg.cn_domain = vsub->vlr->cfg.is_ps ? OSMO_GSUP_CN_DOMAIN_PS : OSMO_GSUP_CN_DOMAIN_CS; rc = vlr_subscr_tx_gsup_message(vsub, &gsup_msg); @@ -705,6 +899,8 @@ int vlr_subscr_req_sai(struct vlr_subscr *vsub, { struct osmo_gsup_message gsup_msg = {0}; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_SAI_REQ); + gsup_msg.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST; gsup_msg.auts = auts; gsup_msg.rand = auts_rand; @@ -732,6 +928,8 @@ int vlr_subscr_tx_req_check_imei(const struct vlr_subscr *vsub) gsup_msg.imei_enc = imei_enc; gsup_msg.imei_enc_len = len; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_CHECK_IMEI_REQ); + /* Send CHECK_IMEI_REQUEST */ OSMO_STRLCPY_ARRAY(gsup_msg.imsi, vsub->imsi); return gsup_client_mux_tx(vsub->vlr->gcm, &gsup_msg); @@ -745,6 +943,8 @@ int vlr_subscr_tx_auth_fail_rep(const struct vlr_subscr *vsub) .message_type = OSMO_GSUP_MSGT_AUTH_FAIL_REPORT, }; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_AUTH_FAIL_REP); + OSMO_STRLCPY_ARRAY(gsup_msg.imsi, vsub->imsi); return gsup_client_mux_tx(vsub->vlr->gcm, &gsup_msg); } @@ -778,6 +978,7 @@ void vlr_subscr_update_tuples(struct vlr_subscr *vsub, } LOGVSUBP(LOGL_DEBUG, vsub, "Received %u auth tuples\n", got_tuples); + vlr_rate_ctr_add(vsub->vlr, VLR_CTR_GSUP_RX_TUPLES, got_tuples); if (!got_tuples) { /* FIXME what now? */ @@ -879,7 +1080,10 @@ static void vlr_subscr_gsup_insert_data(struct vlr_subscr *vsub, } OSMO_ASSERT(pdp_data != NULL); - pdp_data->pdp_type = pdp_info->pdp_type; + pdp_data->pdp_type_org = pdp_info->pdp_type_org; + pdp_data->pdp_type_nr = pdp_info->pdp_type_nr; + memcpy(&pdp_data->pdp_address[0], &pdp_info->pdp_address[0], sizeof(pdp_data->pdp_address[0])); + memcpy(&pdp_data->pdp_address[1], &pdp_info->pdp_address[1], sizeof(pdp_data->pdp_address[1])); osmo_apn_to_str(pdp_data->apn_str, pdp_info->apn_enc, pdp_info->apn_enc_len); memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len); @@ -894,6 +1098,8 @@ static int vlr_subscr_handle_isd_req(struct vlr_subscr *vsub, { struct osmo_gsup_message gsup_reply = {0}; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_ISD_RES); + vlr_subscr_gsup_insert_data(vsub, gsup); vsub->vlr->ops.subscr_update(vsub); @@ -1060,6 +1266,8 @@ static int vlr_subscr_handle_cancel_req(struct vlr_subscr *vsub, int rc, is_update_procedure = !gsup_msg->cancel_type || gsup_msg->cancel_type == OSMO_GSUP_CANCEL_TYPE_UPDATE; + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_GSUP_TX_CANCEL_RES); + LOGVSUBP(LOGL_INFO, vsub, "Cancelling MS subscriber (%s)\n", is_update_procedure ? "update procedure" : "subscription withdraw"); @@ -1070,7 +1278,8 @@ static int vlr_subscr_handle_cancel_req(struct vlr_subscr *vsub, vlr_gmm_cause_to_mm_cause(gsup_msg->cause, &gsm48_rej); vlr_subscr_cancel_attach_fsm(vsub, fsm_cause, gsm48_rej); - vlr_subscr_rx_imsi_detach(vsub); + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_DETACH_BY_CANCEL); + vlr_subscr_detach(vsub); return rc; } @@ -1113,42 +1322,58 @@ int vlr_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_ switch (gsup->message_type) { case OSMO_GSUP_MSGT_PURGE_MS_RESULT: case OSMO_GSUP_MSGT_PURGE_MS_ERROR: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_PURGE_NO_SUBSCR); return vlr_rx_gsup_purge_no_subscr(vlr, gsup); default: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_UNKNOWN_IMSI); return vlr_rx_gsup_unknown_imsi(vlr, gsup); } } switch (gsup->message_type) { case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_SAI_RES); + rc = vlr_subscr_handle_sai_res(vsub, gsup); + break; case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_SAI_ERR); rc = vlr_subscr_handle_sai_res(vsub, gsup); break; case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_ISD_REQ); rc = vlr_subscr_handle_isd_req(vsub, gsup); break; case OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_CANCEL_REQ); rc = vlr_subscr_handle_cancel_req(vsub, gsup); break; case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_UL_RES); rc = vlr_subscr_handle_lu_res(vsub, gsup); break; case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_UL_ERR); rc = vlr_subscr_handle_lu_err(vsub, gsup); break; case OSMO_GSUP_MSGT_PURGE_MS_ERROR: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_PURGE_MS_ERR); + goto out_unimpl; case OSMO_GSUP_MSGT_PURGE_MS_RESULT: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_PURGE_MS_RES); + goto out_unimpl; case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST: - LOGVSUBP(LOGL_ERROR, vsub, - "Rx GSUP msg_type=%d not yet implemented\n", - gsup->message_type); - rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; - break; + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_DELETE_DATA_REQ); + goto out_unimpl; case OSMO_GSUP_MSGT_CHECK_IMEI_ERROR: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_CHECK_IMEI_ERR); + rc = vlr_subscr_handle_check_imei(vsub, gsup); + break; case OSMO_GSUP_MSGT_CHECK_IMEI_RESULT: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_CHECK_IMEI_RES); rc = vlr_subscr_handle_check_imei(vsub, gsup); break; default: + vlr_rate_ctr_inc(vlr, VLR_CTR_GSUP_RX_UNKNOWN); LOGP(DLGSUP, LOGL_ERROR, "GSUP Message type not handled by VLR: %d\n", gsup->message_type); rc = -EINVAL; break; @@ -1156,6 +1381,11 @@ int vlr_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_ vlr_subscr_put(vsub, __func__); return rc; + +out_unimpl: + LOGVSUBP(LOGL_ERROR, vsub, "Rx GSUP msg_type=%d not yet implemented\n", gsup->message_type); + vlr_subscr_put(vsub, __func__); + return -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; } /* MSC->VLR: Subscriber has provided IDENTITY RESPONSE */ @@ -1236,8 +1466,7 @@ bool vlr_subscr_expire(struct vlr_subscr *vsub) return false; } -/* See TS 23.012 version 9.10.0 4.3.2.1 "Process Detach_IMSI_VLR" */ -int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub) +static int vlr_subscr_detach(struct vlr_subscr *vsub) { /* paranoia: should any LU or PARQ FSMs still be running, stop them. */ vlr_subscr_cancel_attach_fsm(vsub, OSMO_FSM_TERM_ERROR, GSM48_REJECT_CONGESTION); @@ -1253,6 +1482,13 @@ int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub) return 0; } +/* See TS 23.012 version 9.10.0 4.3.2.1 "Process Detach_IMSI_VLR" */ +int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub) +{ + vlr_rate_ctr_inc(vsub->vlr, VLR_CTR_DETACH_BY_REQ); + return vlr_subscr_detach(vsub); +} + /* Tear down any running FSMs due to MSC connection timeout. * Visit all vsub->*_fsm pointers and give them a queue to send a final reject * message before the entire connection is torn down. @@ -1291,6 +1527,14 @@ struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops) vlr->cfg.nri_bitlen = OSMO_NRI_BITLEN_DEFAULT; vlr->cfg.nri_ranges = osmo_nri_ranges_alloc(vlr); + vlr->statg = osmo_stat_item_group_alloc(vlr, &vlr_statg_desc, 0); + if (!vlr->statg) + goto err_free; + + vlr->ctrg = rate_ctr_group_alloc(vlr, &vlr_ctrg_desc, 0); + if (!vlr->ctrg) + goto err_statg; + /* reset shared timer definitions */ osmo_tdefs_reset(msc_tdefs_vlr); @@ -1304,6 +1548,12 @@ struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops) vlr_sgs_fsm_init(); return vlr; + +err_statg: + osmo_stat_item_group_free(vlr->statg); +err_free: + talloc_free(vlr); + return NULL; } int vlr_start(struct vlr_instance *vlr, struct gsup_client_mux *gcm) diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c index 8daaaad68..629625ea4 100644 --- a/src/libvlr/vlr_access_req_fsm.c +++ b/src/libvlr/vlr_access_req_fsm.c @@ -40,6 +40,8 @@ static const struct value_string proc_arq_vlr_event_names[] = { OSMO_VALUE_STRING(PR_ARQ_E_START), OSMO_VALUE_STRING(PR_ARQ_E_ID_IMSI), OSMO_VALUE_STRING(PR_ARQ_E_AUTH_RES), + OSMO_VALUE_STRING(PR_ARQ_E_AUTH_NO_INFO), + OSMO_VALUE_STRING(PR_ARQ_E_AUTH_FAILURE), OSMO_VALUE_STRING(PR_ARQ_E_CIPH_RES), OSMO_VALUE_STRING(PR_ARQ_E_UPD_LOC_RES), OSMO_VALUE_STRING(PR_ARQ_E_TRACE_RES), @@ -67,7 +69,12 @@ struct proc_arq_priv { uint32_t tmsi; struct osmo_location_area_id lai; bool authentication_required; - bool ciphering_required; + /* is_ciphering_to_be_attempted: true when any A5/n > 0 are enabled. Ciphering is allowed, always attempt to get Auth Info from + * the HLR. */ + bool is_ciphering_to_be_attempted; + /* is_ciphering_required: true when A5/0 is disabled. If we cannot get Auth Info from the HLR, reject the + * subscriber. */ + bool is_ciphering_required; uint8_t key_seq; bool is_r99; bool is_utran; @@ -267,12 +274,12 @@ static void _proc_arq_vlr_node2_post_ciph(struct osmo_fsm_inst *fi) _proc_arq_vlr_node2_post_vlr(fi); } -/* Determine if sending of CMC/SMC is required */ -static bool is_cmc_smc_required(struct proc_arq_priv *par) +/* Return true when CipherModeCmd / SecurityModeCmd should be attempted. */ +static bool is_cmc_smc_to_be_attempted(struct proc_arq_priv *par) { /* UTRAN: always send SecModeCmd, even if ciphering is not required. * GERAN: avoid sending CiphModeCmd if ciphering is not required. */ - return par->is_utran || par->ciphering_required; + return par->is_utran || par->is_ciphering_to_be_attempted; } static void _proc_arq_vlr_node2(struct osmo_fsm_inst *fi) @@ -283,7 +290,10 @@ static void _proc_arq_vlr_node2(struct osmo_fsm_inst *fi) LOGPFSM(fi, "%s()\n", __func__); - if (!is_cmc_smc_required(par)) { + /* Continue with ciphering, if enabled. + * If auth/ciph is optional and the HLR returned no auth info, continue without ciphering. */ + if (!is_cmc_smc_to_be_attempted(par) + || (vsub->sec_ctx == VLR_SEC_CTX_NONE && !par->is_ciphering_required)) { _proc_arq_vlr_node2_post_ciph(fi); return; } @@ -314,13 +324,13 @@ static void _proc_arq_vlr_node2(struct osmo_fsm_inst *fi) osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_CIPH, 0, 0); } -static bool is_auth_required(struct proc_arq_priv *par) +static bool is_auth_to_be_attempted(struct proc_arq_priv *par) { /* The cases where the authentication procedure should be used * are defined in 3GPP TS 33.102 */ /* For now we use a default value passed in to vlr_lu_fsm(). */ return par->authentication_required || - (par->ciphering_required && !auth_try_reuse_tuple(par->vsub, par->key_seq)); + (par->is_ciphering_to_be_attempted && !auth_try_reuse_tuple(par->vsub, par->key_seq)); } /* after the IMSI is known */ @@ -334,11 +344,13 @@ static void proc_arq_vlr_fn_post_imsi(struct osmo_fsm_inst *fi) OSMO_ASSERT(vsub); /* TODO: Identity IMEI -> System Failure */ - if (is_auth_required(par)) { + if (is_auth_to_be_attempted(par)) { osmo_fsm_inst_state_chg(fi, PR_ARQ_S_WAIT_AUTH, 0, 0); vsub->auth_fsm = auth_fsm_start(vsub, fi, PR_ARQ_E_AUTH_RES, + PR_ARQ_E_AUTH_NO_INFO, + PR_ARQ_E_AUTH_FAILURE, par->is_r99, par->is_utran); } else { @@ -431,17 +443,34 @@ static void proc_arq_vlr_fn_w_obt_imsi(struct osmo_fsm_inst *fi, static void proc_arq_vlr_fn_w_auth(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct proc_arq_priv *par = fi->priv; enum gsm48_reject_value *cause = data; - OSMO_ASSERT(event == PR_ARQ_E_AUTH_RES); + switch (event) { + case PR_ARQ_E_AUTH_RES: + /* Node 2 */ + _proc_arq_vlr_node2(fi); + return; - if (!cause || *cause) { - proc_arq_fsm_done(fi, cause? *cause : GSM48_REJECT_NETWORK_FAILURE); + case PR_ARQ_E_AUTH_FAILURE: + proc_arq_fsm_done(fi, cause ? *cause : GSM48_REJECT_NETWORK_FAILURE); + return; + + case PR_ARQ_E_AUTH_NO_INFO: + /* HLR returned no auth info for the subscriber. Continue only if authentication is optional. */ + if (par->authentication_required) { + proc_arq_fsm_done(fi, cause ? *cause : GSM48_REJECT_NETWORK_FAILURE); + return; + } + LOGPFSML(fi, LOGL_INFO, + "Attaching subscriber without auth (auth is optional, and no auth info received from HLR)\n"); + /* Node 2 */ + _proc_arq_vlr_node2(fi); return; - } - /* Node 2 */ - _proc_arq_vlr_node2(fi); + default: + OSMO_ASSERT(false); + } } static void proc_arq_vlr_fn_w_ciph(struct osmo_fsm_inst *fi, @@ -546,7 +575,9 @@ static const struct osmo_fsm_state proc_arq_vlr_states[] = { }, [PR_ARQ_S_WAIT_AUTH] = { .name = OSMO_STRINGIFY(PR_ARQ_S_WAIT_AUTH), - .in_event_mask = S(PR_ARQ_E_AUTH_RES), + .in_event_mask = S(PR_ARQ_E_AUTH_RES) | + S(PR_ARQ_E_AUTH_NO_INFO) | + S(PR_ARQ_E_AUTH_FAILURE), .out_state_mask = S(PR_ARQ_S_DONE) | S(PR_ARQ_S_WAIT_CIPH) | S(PR_ARQ_S_WAIT_UPD_LOC_CHILD) | @@ -634,13 +665,17 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, const struct osmo_mobile_identity *mi, const struct osmo_location_area_id *lai, bool authentication_required, - bool ciphering_required, + bool is_ciphering_to_be_attempted, + bool is_ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran) { struct osmo_fsm_inst *fi; struct proc_arq_priv *par; + if (is_ciphering_required) + OSMO_ASSERT(is_ciphering_to_be_attempted); + fi = osmo_fsm_inst_alloc_child(&proc_arq_vlr_fsm, parent, parent_event_failure); if (!fi) @@ -657,7 +692,8 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, par->parent_event_failure = parent_event_failure; par->parent_event_data = parent_event_data; par->authentication_required = authentication_required; - par->ciphering_required = ciphering_required; + par->is_ciphering_to_be_attempted = is_ciphering_to_be_attempted; + par->is_ciphering_required = is_ciphering_required; par->key_seq = key_seq; par->is_r99 = is_r99; par->is_utran = is_utran; @@ -665,10 +701,10 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, LOGPFSM(fi, "rev=%s net=%s%s%s\n", is_r99 ? "R99" : "GSM", is_utran ? "UTRAN" : "GERAN", - (authentication_required || ciphering_required)? + (authentication_required || is_ciphering_to_be_attempted) ? " Auth" : " (no Auth)", - (authentication_required || ciphering_required)? - (ciphering_required? "+Ciph" : " (no Ciph)") + (authentication_required || is_ciphering_to_be_attempted) ? + (is_ciphering_to_be_attempted ? "+Ciph" : " (no Ciph)") : ""); if (is_utran && !authentication_required) diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c index a6b5cd271..b5052b072 100644 --- a/src/libvlr/vlr_auth_fsm.c +++ b/src/libvlr/vlr_auth_fsm.c @@ -51,6 +51,10 @@ struct auth_fsm_priv { bool auth_requested; int auth_tuple_max_reuse_count; /* see vlr->cfg instead */ + + uint32_t parent_event_success; + uint32_t parent_event_no_auth_info; + uint32_t parent_event_failure; }; /*********************************************************************** @@ -230,27 +234,50 @@ static void auth_fsm_onenter_failed(struct osmo_fsm_inst *fi, uint32_t prev_stat } } -static const char *vlr_auth_fsm_result_name(enum gsm48_reject_value result) -{ - if (!result) - return "PASSED"; - return get_value_string(gsm48_gmm_cause_names, result); -} +enum auth_fsm_result { + /* Authentication verified the subscriber. */ + AUTH_FSM_PASSED = 0, + /* HLR does not have authentication info for this subscriber. */ + AUTH_FSM_NO_AUTH_INFO, + /* Authentication was attempted but failed. */ + AUTH_FSM_FAILURE, +}; + +const char *auth_fsm_result_str[] = { + [AUTH_FSM_PASSED] = "PASSED", + [AUTH_FSM_NO_AUTH_INFO] = "NO_AUTH_INFO", + [AUTH_FSM_FAILURE] = "FAILURE", +}; /* Terminate the Auth FSM Instance and notify parent */ -static void auth_fsm_term(struct osmo_fsm_inst *fi, enum gsm48_reject_value result) +static void auth_fsm_term(struct osmo_fsm_inst *fi, enum auth_fsm_result result, enum gsm48_reject_value cause) { - LOGPFSM(fi, "Authentication terminating with result %s\n", - vlr_auth_fsm_result_name(result)); + struct auth_fsm_priv *afp = fi->priv; - /* Do one final state transition (mostly for logging purpose) */ - if (!result) + LOGPFSM(fi, "Authentication terminating with result %s%s%s\n", + auth_fsm_result_str[result], + cause ? ", cause " : "", + cause ? gsm48_reject_value_name(cause) : ""); + + /* Do one final state transition (mostly for logging purpose) + * and set the parent_term_event according to result */ + switch (result) { + case AUTH_FSM_PASSED: osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTHENTICATED, 0, 0); - else + fi->proc.parent_term_event = afp->parent_event_success; + break; + case AUTH_FSM_NO_AUTH_INFO: + osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTH_FAILED, 0, 0); + fi->proc.parent_term_event = afp->parent_event_no_auth_info; + break; + case AUTH_FSM_FAILURE: osmo_fsm_inst_state_chg(fi, VLR_SUB_AS_AUTH_FAILED, 0, 0); + fi->proc.parent_term_event = afp->parent_event_failure; + break; + } /* return the result to the parent FSM */ - osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, &result); + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, &cause); } static void auth_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause) @@ -275,7 +302,7 @@ static int _vlr_subscr_authenticate(struct osmo_fsm_inst *fi) LOGPFSML(fi, LOGL_ERROR, "A previous check ensured that an" " auth tuple was available, but now there is in fact" " none.\n"); - auth_fsm_term(fi, GSM48_REJECT_NETWORK_FAILURE); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_NETWORK_FAILURE); return -1; } @@ -356,16 +383,20 @@ static void auth_fsm_wait_ai(struct osmo_fsm_inst *fi, uint32_t event, switch (event) { case VLR_AUTH_E_HLR_SAI_ACK: if (!gsup->num_auth_vectors) { - auth_fsm_term(fi, GSM48_REJECT_NETWORK_FAILURE); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_NETWORK_FAILURE); return; } vlr_subscr_update_tuples(vsub, gsup); goto pass; - break; case VLR_AUTH_E_HLR_SAI_NACK: + /* HLR did not return Auth Info, hence cannot authenticate. (The caller may still decide to permit + * attaching without authentication) */ + vlr_gmm_cause_to_mm_cause(gsup->cause, &gsm48_rej); + auth_fsm_term(fi, AUTH_FSM_NO_AUTH_INFO, gsm48_rej); + break; case VLR_AUTH_E_HLR_SAI_ABORT: vlr_gmm_cause_to_mm_cause(gsup->cause, &gsm48_rej); - auth_fsm_term(fi, gsm48_rej); + auth_fsm_term(fi, AUTH_FSM_FAILURE, gsm48_rej); break; } @@ -398,10 +429,10 @@ static void auth_fsm_wait_auth_resp(struct osmo_fsm_inst *fi, uint32_t event, VLR_SUB_AS_WAIT_ID_IMSI, vlr_timer(vlr, 3270), 3270); } else { - auth_fsm_term(fi, GSM48_REJECT_ILLEGAL_MS); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_ILLEGAL_MS); } } else { - auth_fsm_term(fi, 0); + auth_fsm_term(fi, AUTH_FSM_PASSED, 0); } break; case VLR_AUTH_E_MS_AUTH_FAIL: @@ -413,7 +444,7 @@ static void auth_fsm_wait_auth_resp(struct osmo_fsm_inst *fi, uint32_t event, VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC, GSM_29002_TIMER_M, 0); } else - auth_fsm_term(fi, GSM48_REJECT_ILLEGAL_MS); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_ILLEGAL_MS); break; } } @@ -433,7 +464,7 @@ static void auth_fsm_wait_ai_resync(struct osmo_fsm_inst *fi, gsup->cause != GMM_CAUSE_IMSI_UNKNOWN) || (event == VLR_AUTH_E_HLR_SAI_ABORT)) { /* result = procedure error */ - auth_fsm_term(fi, GSM48_REJECT_NETWORK_FAILURE); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_NETWORK_FAILURE); } switch (event) { case VLR_AUTH_E_HLR_SAI_ACK: @@ -444,6 +475,7 @@ static void auth_fsm_wait_ai_resync(struct osmo_fsm_inst *fi, break; case VLR_AUTH_E_HLR_SAI_NACK: auth_fsm_term(fi, + AUTH_FSM_FAILURE, gsup->cause == GMM_CAUSE_IMSI_UNKNOWN? GSM48_REJECT_IMSI_UNKNOWN_IN_HLR : GSM48_REJECT_NETWORK_FAILURE); @@ -474,16 +506,16 @@ static void auth_fsm_wait_auth_resp_resync(struct osmo_fsm_inst *fi, vlr_timer(vlr, 3270), 3270); } else { /* Result = Aborted */ - auth_fsm_term(fi, GSM48_REJECT_SYNCH_FAILURE); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_SYNCH_FAILURE); } } else { /* Result = Pass */ - auth_fsm_term(fi, 0); + auth_fsm_term(fi, AUTH_FSM_PASSED, 0); } break; case VLR_AUTH_E_MS_AUTH_FAIL: /* Second failure: Result = Fail */ - auth_fsm_term(fi, GSM48_REJECT_SYNCH_FAILURE); + auth_fsm_term(fi, AUTH_FSM_FAILURE, GSM48_REJECT_SYNCH_FAILURE); break; } } @@ -593,23 +625,24 @@ struct osmo_fsm vlr_auth_fsm = { /* MSC->VLR: Start Procedure Authenticate_VLR (TS 23.012 Ch. 4.1.2.2) */ struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub, struct osmo_fsm_inst *parent, - uint32_t parent_term_event, + uint32_t parent_event_success, + uint32_t parent_event_no_auth_info, + uint32_t parent_event_failure, bool is_r99, bool is_utran) { struct osmo_fsm_inst *fi; struct auth_fsm_priv *afp; - fi = osmo_fsm_inst_alloc_child(&vlr_auth_fsm, parent, - parent_term_event); + fi = osmo_fsm_inst_alloc_child(&vlr_auth_fsm, parent, parent_event_failure); if (!fi) { - osmo_fsm_inst_dispatch(parent, parent_term_event, 0); + osmo_fsm_inst_dispatch(parent, parent_event_failure, 0); return NULL; } afp = talloc_zero(fi, struct auth_fsm_priv); if (!afp) { - osmo_fsm_inst_dispatch(parent, parent_term_event, 0); + osmo_fsm_inst_dispatch(parent, parent_event_failure, 0); return NULL; } @@ -618,6 +651,9 @@ struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub, afp->by_imsi = true; afp->is_r99 = is_r99; afp->is_utran = is_utran; + afp->parent_event_success = parent_event_success; + afp->parent_event_no_auth_info = parent_event_no_auth_info; + afp->parent_event_failure = parent_event_failure; fi->priv = afp; vsub->auth_fsm = fi; diff --git a/src/libvlr/vlr_auth_fsm.h b/src/libvlr/vlr_auth_fsm.h index 73ab53f3e..828384206 100644 --- a/src/libvlr/vlr_auth_fsm.h +++ b/src/libvlr/vlr_auth_fsm.h @@ -31,7 +31,9 @@ extern struct osmo_fsm vlr_auth_fsm; struct osmo_fsm_inst *auth_fsm_start(struct vlr_subscr *vsub, struct osmo_fsm_inst *parent, - uint32_t parent_term_event, + uint32_t parent_event_success, + uint32_t parent_event_no_auth_info, + uint32_t parent_event_failure, bool is_r99, bool is_utran); diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index 4f603b3ca..5d8f78bc2 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -469,6 +469,8 @@ static void lu_compl_vlr_wait_subscr_pres(struct osmo_fsm_inst *fi, lu_compl_vlr_new_tmsi(fi); return; } + /* else, any previously used TMSI is now invalid. */ + vsub->tmsi = GSM_RESERVED_TMSI; /* Location Updating Accept */ vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI); @@ -514,6 +516,8 @@ static void lu_compl_vlr_wait_imei(struct osmo_fsm_inst *fi, uint32_t event, /* Wait for TMSI ack */ return; } + /* else, any previously used TMSI is now invalid. */ + vsub->tmsi = GSM_RESERVED_TMSI; /* No TMSI needed, accept now. */ vlr->ops.tx_lu_acc(lcvp->msc_conn_ref, GSM_RESERVED_TMSI); @@ -642,7 +646,9 @@ static const struct value_string fsm_lu_event_names[] = { OSMO_VALUE_STRING(VLR_ULA_E_UPDATE_LA), OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_ACK), OSMO_VALUE_STRING(VLR_ULA_E_SEND_ID_NACK), - OSMO_VALUE_STRING(VLR_ULA_E_AUTH_RES), + OSMO_VALUE_STRING(VLR_ULA_E_AUTH_SUCCESS), + OSMO_VALUE_STRING(VLR_ULA_E_AUTH_NO_INFO), + OSMO_VALUE_STRING(VLR_ULA_E_AUTH_FAILURE), OSMO_VALUE_STRING(VLR_ULA_E_CIPH_RES), OSMO_VALUE_STRING(VLR_ULA_E_ID_IMSI), OSMO_VALUE_STRING(VLR_ULA_E_ID_IMEI), @@ -676,7 +682,12 @@ struct lu_fsm_priv { struct osmo_location_area_id old_lai; struct osmo_location_area_id new_lai; bool authentication_required; - bool ciphering_required; + /* is_ciphering_to_be_attempted: true when any A5/n > 0 are enabled. Ciphering is allowed, always attempt to get Auth Info from + * the HLR. */ + bool is_ciphering_to_be_attempted; + /* is_ciphering_required: true when A5/0 is disabled. If we cannot get Auth Info from the HLR, reject the + * subscriber. */ + bool is_ciphering_required; uint8_t key_seq; bool is_r99; bool is_utran; @@ -692,22 +703,22 @@ static bool lai_in_this_vlr(struct vlr_instance *vlr, return true; } -/* Determine if authentication is required */ -static bool is_auth_required(struct lu_fsm_priv *lfp) +/* Return true when authentication should be attempted. */ +static bool try_auth(struct lu_fsm_priv *lfp) { /* The cases where the authentication procedure should be used * are defined in 3GPP TS 33.102 */ /* For now we use a default value passed in to vlr_lu_fsm(). */ return lfp->authentication_required || - (lfp->ciphering_required && !auth_try_reuse_tuple(lfp->vsub, lfp->key_seq)); + (lfp->is_ciphering_to_be_attempted && !auth_try_reuse_tuple(lfp->vsub, lfp->key_seq)); } -/* Determine if sending of CMC/SMC is required */ -static bool is_cmc_smc_required(struct lu_fsm_priv *lfp) +/* Return true when CipherModeCmd / SecurityModeCmd should be attempted. */ +static bool is_cmc_smc_to_be_attempted(struct lu_fsm_priv *lfp) { /* UTRAN: always send SecModeCmd, even if ciphering is not required. * GERAN: avoid sending CiphModeCmd if ciphering is not required. */ - return lfp->is_utran || lfp->ciphering_required; + return lfp->is_utran || lfp->is_ciphering_to_be_attempted; } /* Determine if a HLR Update is required */ @@ -855,7 +866,10 @@ static void vlr_loc_upd_post_auth(struct osmo_fsm_inst *fi) OSMO_ASSERT(vsub); - if (!is_cmc_smc_required(lfp)) { + /* Continue with ciphering, if enabled. + * If auth/ciph is optional and the HLR returned no auth info, continue without ciphering. */ + if (!is_cmc_smc_to_be_attempted(lfp) + || (vsub->sec_ctx == VLR_SEC_CTX_NONE && !lfp->is_ciphering_required)) { vlr_loc_upd_post_ciph(fi); return; } @@ -900,12 +914,15 @@ static void vlr_loc_upd_node1(struct osmo_fsm_inst *fi) OSMO_ASSERT(vsub); - if (is_auth_required(lfp)) { + if (try_auth(lfp)) { /* Authenticate_VLR */ osmo_fsm_inst_state_chg(fi, VLR_ULA_S_WAIT_AUTH, LU_TIMEOUT_LONG, 0); vsub->auth_fsm = auth_fsm_start(lfp->vsub, - fi, VLR_ULA_E_AUTH_RES, + fi, + VLR_ULA_E_AUTH_SUCCESS, + VLR_ULA_E_AUTH_NO_INFO, + VLR_ULA_E_AUTH_FAILURE, lfp->is_r99, lfp->is_utran); } else { @@ -1138,17 +1155,32 @@ static void lu_fsm_wait_auth(struct osmo_fsm_inst *fi, uint32_t event, struct lu_fsm_priv *lfp = lu_fsm_fi_priv(fi); enum gsm48_reject_value *res = data; - OSMO_ASSERT(event == VLR_ULA_E_AUTH_RES); - lfp->upd_hlr_vlr_fsm = NULL; - if (!res || *res) { - lu_fsm_failure(fi, res? *res : GSM48_REJECT_NETWORK_FAILURE); + switch (event) { + case VLR_ULA_E_AUTH_SUCCESS: + /* Result == Pass */ + vlr_loc_upd_post_auth(fi); + return; + + case VLR_ULA_E_AUTH_FAILURE: + lu_fsm_failure(fi, res ? *res : GSM48_REJECT_NETWORK_FAILURE); + return; + + case VLR_ULA_E_AUTH_NO_INFO: + /* HLR returned no auth info for the subscriber. Continue only if authentication is optional. */ + if (lfp->authentication_required || lfp->is_ciphering_required) { + lu_fsm_failure(fi, res ? *res : GSM48_REJECT_NETWORK_FAILURE); + return; + } + LOGPFSML(fi, LOGL_INFO, + "Attaching subscriber without auth (auth is optional, and no auth info received from HLR)\n"); + vlr_loc_upd_post_auth(fi); return; - } - /* Result == Pass */ - vlr_loc_upd_post_auth(fi); + default: + OSMO_ASSERT(false); + } } static void lu_fsm_wait_ciph(struct osmo_fsm_inst *fi, uint32_t event, @@ -1363,7 +1395,9 @@ static const struct osmo_fsm_state vlr_lu_fsm_states[] = { .action = lu_fsm_wait_pvlr, }, [VLR_ULA_S_WAIT_AUTH] = { - .in_event_mask = S(VLR_ULA_E_AUTH_RES), + .in_event_mask = S(VLR_ULA_E_AUTH_SUCCESS) | + S(VLR_ULA_E_AUTH_NO_INFO) | + S(VLR_ULA_E_AUTH_FAILURE), .out_state_mask = S(VLR_ULA_S_WAIT_CIPH) | S(VLR_ULA_S_WAIT_LU_COMPL) | S(VLR_ULA_S_WAIT_HLR_UPD) | @@ -1475,7 +1509,8 @@ vlr_loc_update(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *old_lai, const struct osmo_location_area_id *new_lai, bool authentication_required, - bool ciphering_required, + bool is_ciphering_to_be_attempted, + bool is_ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran, bool assign_tmsi) @@ -1483,6 +1518,9 @@ vlr_loc_update(struct osmo_fsm_inst *parent, struct osmo_fsm_inst *fi; struct lu_fsm_priv *lfp; + if (is_ciphering_required) + OSMO_ASSERT(is_ciphering_to_be_attempted); + fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure); if (!fi) return NULL; @@ -1499,7 +1537,8 @@ vlr_loc_update(struct osmo_fsm_inst *parent, lfp->parent_event_failure = parent_event_failure; lfp->parent_event_data = parent_event_data; lfp->authentication_required = authentication_required; - lfp->ciphering_required = ciphering_required; + lfp->is_ciphering_to_be_attempted = is_ciphering_to_be_attempted; + lfp->is_ciphering_required = is_ciphering_required; lfp->key_seq = key_seq; lfp->is_r99 = is_r99; lfp->is_utran = is_utran; @@ -1514,10 +1553,10 @@ vlr_loc_update(struct osmo_fsm_inst *parent, LOGPFSM(fi, "rev=%s net=%s%s%s\n", is_r99 ? "R99" : "GSM", is_utran ? "UTRAN" : "GERAN", - (authentication_required || ciphering_required)? + (authentication_required || is_ciphering_to_be_attempted) ? " Auth" : " (no Auth)", - (authentication_required || ciphering_required)? - (ciphering_required? "+Ciph" : " (no Ciph)") + (authentication_required || is_ciphering_to_be_attempted) ? + (is_ciphering_to_be_attempted ? "+Ciph" : " (no Ciph)") : ""); if (is_utran && !authentication_required) diff --git a/src/osmo-msc/Makefile.am b/src/osmo-msc/Makefile.am index 7b56c7458..0380d5d1f 100644 --- a/src/osmo-msc/Makefile.am +++ b/src/osmo-msc/Makefile.am @@ -19,6 +19,7 @@ AM_CFLAGS = \ $(LIBOSMOSIGTRAN_CFLAGS) \ $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(LIBOSMOGSUPCLIENT_CFLAGS) \ + $(LIBSQLITE3_CFLAGS) \ $(NULL) AM_LDFLAGS = \ @@ -42,12 +43,20 @@ osmo_msc_LDADD = \ $(LIBOSMOCTRL_LIBS) \ $(LIBOSMOABIS_LIBS) \ $(LIBOSMONETIF_LIBS) \ - $(LIBSMPP34_LIBS) \ $(LIBOSMORANAP_LIBS) \ $(LIBASN1C_LIBS) \ $(LIBOSMOSIGTRAN_LIBS) \ $(LIBOSMOMGCPCLIENT_LIBS) \ $(LIBOSMOGSUPCLIENT_LIBS) \ - -ldbi \ + $(LIBSQLITE3_LIBS) \ -lsctp \ $(NULL) + +if BUILD_SMPP + +osmo_msc_LDADD += \ + $(top_builddir)/src/libsmpputil/libsmpputil.a \ + $(LIBSMPP34_LIBS) \ + $(NULL) + +endif diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c index 9657c716d..913bd212f 100644 --- a/src/osmo-msc/msc_main.c +++ b/src/osmo-msc/msc_main.c @@ -1,4 +1,4 @@ -/* OsmoMSC - Circuit-Switched Core Network (MSC+VLR+HLR+SMSC) implementation +/* OsmoMSC - Circuit-Switched Core Network (MSC+VLR+SMSC) implementation */ /* (C) 2016-2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> @@ -60,7 +60,7 @@ #include <osmocom/ctrl/control_if.h> #include <osmocom/ctrl/control_vty.h> #include <osmocom/ctrl/ports.h> -#include <osmocom/msc/smpp.h> +#include <osmocom/smpp/smpp.h> #include <osmocom/sigtran/osmo_ss7.h> #include <osmocom/mgcp_client/mgcp_client.h> #include <osmocom/msc/sgs_iface.h> @@ -100,12 +100,10 @@ void *tall_map_ctx = NULL; /* end deps from libbsc legacy. */ static struct { - const char *database_name; const char *config_file; int daemonize; const char *mncc_sock_path; } msc_cmdline_config = { - .database_name = NULL, .config_file = "osmo-msc.cfg", }; @@ -206,9 +204,9 @@ static void handle_options(int argc, char **argv) msc_cmdline_config.daemonize = 1; break; case 'l': - msc_cmdline_config.database_name = optarg; fprintf(stderr, "Command line argument '-%c' is deprecated, use VTY " - "parameter 'msc' / 'sms-database %s' instead.\n", c, optarg); + "parameter 'smsc' / 'database %s' instead.\n", c, optarg); + exit(2); break; case 'c': msc_cmdline_config.config_file = optarg; @@ -244,8 +242,8 @@ static void handle_options(int argc, char **argv) } } -struct gsm_network *msc_network_alloc(void *ctx, - mncc_recv_cb_t mncc_recv) +static struct gsm_network *msc_network_alloc(void *ctx, + mncc_recv_cb_t mncc_recv) { struct gsm_network *net = gsm_network_init(ctx, mncc_recv); if (!net) @@ -258,12 +256,14 @@ struct gsm_network *msc_network_alloc(void *ctx, MSC_HLR_REMOTE_IP_DEFAULT); net->gsup_server_port = MSC_HLR_REMOTE_PORT_DEFAULT; - mgcp_client_conf_init(&net->mgw.conf); + net->mgw.mgw_pool = mgcp_client_pool_alloc(net); + net->mgw.conf = mgcp_client_conf_alloc(net); net->call_waiting = true; net->lcls_permitted = false; net->mgw.tdefs = g_mgw_tdefs; osmo_tdefs_reset(net->mgw.tdefs); + net->sms_queue_cfg = sms_queue_cfg_alloc(ctx); return net; } @@ -318,6 +318,11 @@ static int msc_vty_go_parent(struct vty *vty) vty->node = CONFIG_NODE; vty->index = NULL; break; + case MGW_NODE: + OSMO_ASSERT(msc_network != NULL); + vty->node = GSMNET_NODE; + vty->index = msc_network; + break; case SMPP_ESME_NODE: vty->node = SMPP_NODE; vty->index = NULL; @@ -325,9 +330,19 @@ static int msc_vty_go_parent(struct vty *vty) case SMPP_NODE: case MSC_NODE: case MNCC_INT_NODE: + case ASCI_NODE: vty->node = CONFIG_NODE; vty->index = NULL; break; + case GCR_NODE: + vty->node = ASCI_NODE; + vty->index = NULL; + break; + case VGC_NODE: + case VBC_NODE: + vty->node = GCR_NODE; + vty->index = NULL; + break; case SUBSCR_NODE: vty->node = ENABLE_NODE; vty->index = NULL; @@ -434,6 +449,18 @@ static const struct log_info_cat msc_default_categories[] = { .color = "\033[1;32m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DBCC] = { + .name = "DBCC", + .description = "Layer3 Broadcast Call Control (BCC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DGCC] = { + .name = "DGCC", + .description = "Layer3 Group Call Control (GCC)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, [DMM] = { .name = "DMM", .description = "Layer3 Mobility Management (MM)", @@ -524,6 +551,11 @@ static const struct log_info_cat msc_default_categories[] = { .description = "Supplementary Services", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DASCI] = { + .name = "DASCI", + .description = "Advanced Speech Call Items", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, }; static int filter_fn(const struct log_context *ctx, struct log_target *tar) @@ -547,9 +579,49 @@ extern void *tall_gsms_ctx; extern void *tall_call_ctx; extern void *tall_trans_ctx; +static int msc_mgw_setup(void) +{ + struct mgcp_client *mgcp_client_single; + unsigned int pool_members_initalized; + + /* Initialize MGW pool. This initalizes and connects all MGCP clients that are currently configured in + * the pool. Adding additional MGCP clients to the pool is possible but the user has to configure and + * (re)connect them manually from the VTY. */ + if (!mgcp_client_pool_empty(msc_network->mgw.mgw_pool)) { + pool_members_initalized = mgcp_client_pool_connect(msc_network->mgw.mgw_pool); + if (!pool_members_initalized) { + LOGP(DMSC, LOGL_ERROR, "MGW pool failed to initialize any pool members\n"); + return -EINVAL; + } + LOGP(DMSC, LOGL_NOTICE, + "MGW pool with %u pool members configured, (ignoring MGW configuration in VTY node 'msc').\n", + pool_members_initalized); + return 0; + } + + /* Initialize and connect a single MGCP client. This MGCP client will appear as the one and only pool + * member if there is no MGW pool configured. */ + LOGP(DMSC, LOGL_NOTICE, "No MGW pool configured, using MGW configuration in VTY node 'msc'\n"); + mgcp_client_single = mgcp_client_init(msc_network, msc_network->mgw.conf); + if (!mgcp_client_single) { + LOGP(DMSC, LOGL_ERROR, "MGW (single) client initalization failed\n"); + return -EINVAL; + } + if (mgcp_client_connect(mgcp_client_single)) { + LOGP(DMSC, LOGL_ERROR, "MGW (single) connect failed at (%s:%u)\n", + msc_network->mgw.conf->remote_addr, + msc_network->mgw.conf->remote_port); + return -EINVAL; + } + mgcp_client_pool_register_single(msc_network->mgw.mgw_pool, mgcp_client_single); + + return 0; +} + int main(int argc, char **argv) { int rc; + int ret = 0; struct osmo_sccp_instance *sccp_a; struct osmo_sccp_instance *sccp_iu; @@ -576,6 +648,7 @@ int main(int argc, char **argv) osmo_fsm_log_addr(true); osmo_stats_init(tall_msc_ctx); + rate_ctr_init(tall_msc_ctx); /* For --version, vty_init() must be called before handling options */ vty_init(&msc_vty_info); @@ -608,7 +681,7 @@ int main(int argc, char **argv) } #ifdef BUILD_SMPP - if (smpp_openbsc_alloc_init(tall_msc_ctx) < 0) + if (smpp_msc_alloc_init(tall_msc_ctx) < 0) return -1; #endif sgs_iface_init(tall_msc_ctx, msc_network); @@ -642,8 +715,7 @@ int main(int argc, char **argv) DEBUGP(DMNCC, "Using internal MNCC handler.\n"); /* start telnet after reading config for vty_get_bind_addr() */ - rc = telnet_init_dynif(tall_msc_ctx, &msc_network, - vty_get_bind_addr(), OSMO_VTY_PORT_MSC); + rc = telnet_init_default(tall_msc_ctx, &msc_network, OSMO_VTY_PORT_MSC); if (rc < 0) return 2; @@ -652,13 +724,12 @@ int main(int argc, char **argv) * following code until iu_init() is legacy. */ #ifdef BUILD_SMPP - smpp_openbsc_start(msc_network); + smpp_msc_start(msc_network); #endif /* start control interface after reading config for * ctrl_vty_get_bind_addr() */ - msc_network->ctrl = ctrl_interface_setup_dynip(msc_network, ctrl_vty_get_bind_addr(), - OSMO_CTRL_PORT_MSC, NULL); + msc_network->ctrl = ctrl_interface_setup(msc_network, OSMO_CTRL_PORT_MSC, NULL); if (!msc_network->ctrl) { fprintf(stderr, "Failed to initialize control interface. Exiting.\n"); return -1; @@ -682,14 +753,6 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i /* TODO: is this used for crypto?? Improve randomness, at least we * should try to use the nanoseconds part of the current time. */ - if (msc_cmdline_config.database_name) - osmo_talloc_replace_string(msc_network, &msc_network->sms_db_file_path, msc_cmdline_config.database_name); - if (db_init(msc_network->sms_db_file_path)) { - fprintf(stderr, "DB: Failed to init database: %s\n", - osmo_quote_str((char*)msc_network->sms_db_file_path, -1)); - return 4; - } - if (msc_gsup_client_start(msc_network)) { fprintf(stderr, "Failed to start GSUP client\n"); exit(1); @@ -702,11 +765,6 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i exit(1); } - if (db_prepare()) { - fprintf(stderr, "DB: Failed to prepare database.\n"); - return 5; - } - signal(SIGINT, &signal_handler); signal(SIGTERM, &signal_handler); signal(SIGABRT, &signal_handler); @@ -715,25 +773,26 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i osmo_init_ignore_signals(); /* start the SMS queue */ - if (sms_queue_start(msc_network, 20) != 0) - return -1; - - msc_network->mgw.client = mgcp_client_init( - msc_network, &msc_network->mgw.conf); + if (sms_queue_start(msc_network) != 0) { + ret = -1; + goto error; + } - if (mgcp_client_connect(msc_network->mgw.client)) { - fprintf(stderr, "MGCPGW connect failed\n"); - return 7; + if (msc_mgw_setup() != 0) { + ret = 7; + goto error; } if (ss7_setup(tall_msc_ctx, &sccp_a, &sccp_iu)) { fprintf(stderr, "Setting up SCCP client failed.\n"); - return 8; + ret = 8; + goto error; } if (sgs_server_open(g_sgs)) { fprintf(stderr, "Starting SGs server failed\n"); - return 9; + ret = 9; + goto error; } msc_network->a.sri = sccp_ran_init(msc_network, sccp_a, OSMO_SCCP_SSN_BSSAP, @@ -741,7 +800,8 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i msc_network); if (!msc_network->a.sri) { fprintf(stderr, "Setting up A receiver failed\n"); - return 10; + ret = 10; + goto error; } LOGP(DMSC, LOGL_NOTICE, "A-interface: SCCP user %s, cs7-instance %u (%s)\n", osmo_sccp_user_name(msc_network->a.sri->scu), @@ -756,7 +816,8 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i msc_network); if (!msc_network->iu.sri) { fprintf(stderr, "Setting up IuCS receiver failed\n"); - return 11; + ret = 11; + goto error; } /* Compatibility with legacy osmo-hnbgw that was unable to properly handle RESET messages. */ @@ -775,7 +836,8 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i rc = osmo_daemonize(); if (rc < 0) { perror("Error during daemonize"); - return 6; + ret = 6; + goto error; } } @@ -798,6 +860,8 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i } } while (!osmo_select_shutdown_done()); +error: + db_fini(); log_fini(); /** @@ -816,5 +880,5 @@ TODO: we probably want some of the _net_ ctrl commands from bsc_base_ctrl_cmds_i */ talloc_report_full(NULL, stderr); talloc_disable_null_tracking(); - return 0; + return ret; } diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index cb0faf69f..606967245 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -34,12 +34,26 @@ smpp_mirror_SOURCES = \ smpp_mirror_CFLAGS = \ $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOSCCP_CFLAGS) \ + $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(LIBSMPP34_CFLAGS) \ $(NULL) smpp_mirror_LDADD = \ + $(top_builddir)/src/libsmpputil/libsmpputil.a \ + $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libvlr/libvlr.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBOSMONETIF_LIBS) \ $(LIBSMPP34_LIBS) \ + $(LIBOSMORANAP_LIBS) \ + $(LIBASN1C_LIBS) \ + $(LIBOSMOSIGTRAN_LIBS) \ + $(LIBOSMOMGCPCLIENT_LIBS) \ + $(LIBOSMOGSUPCLIENT_LIBS) \ + $(LIBSQLITE3_LIBS) \ + -lsctp \ $(NULL) endif diff --git a/src/utils/smpp_mirror.c b/src/utils/smpp_mirror.c index 72d15e39d..3356468ae 100644 --- a/src/utils/smpp_mirror.c +++ b/src/utils/smpp_mirror.c @@ -19,81 +19,10 @@ #include <osmocom/core/write_queue.h> #include <osmocom/msc/debug.h> +#include <osmocom/smpp/smpp.h> -/* FIXME: merge with smpp_smsc.c */ -#define SMPP_SYS_ID_LEN 16 -enum esme_read_state { - READ_ST_IN_LEN = 0, - READ_ST_IN_MSG = 1, -}; -/* FIXME: merge with smpp_smsc.c */ - -struct esme { - struct osmo_fd ofd; - - uint32_t own_seq_nr; - - struct osmo_wqueue wqueue; - enum esme_read_state read_state; - uint32_t read_len; - uint32_t read_idx; - struct msgb *read_msg; - - uint8_t smpp_version; - char system_id[SMPP_SYS_ID_LEN+1]; - char password[SMPP_SYS_ID_LEN+1]; -}; /* FIXME: merge with smpp_smsc.c */ -#define SMPP34_UNPACK(rc, type, str, data, len) \ - memset(str, 0, sizeof(*str)); \ - rc = smpp34_unpack(type, str, data, len) -#define INIT_RESP(type, resp, req) { \ - memset((resp), 0, sizeof(*(resp))); \ - (resp)->command_length = 0; \ - (resp)->command_id = type; \ - (resp)->command_status = ESME_ROK; \ - (resp)->sequence_number = (req)->sequence_number; \ -} -#define PACK_AND_SEND(esme, ptr) pack_and_send(esme, (ptr)->command_id, ptr) -static inline uint32_t smpp_msgb_cmdid(struct msgb *msg) -{ - uint8_t *tmp = msgb_data(msg) + 4; - return ntohl(*(uint32_t *)tmp); -} -static uint32_t esme_inc_seq_nr(struct esme *esme) -{ - esme->own_seq_nr++; - if (esme->own_seq_nr > 0x7fffffff) - esme->own_seq_nr = 1; - - return esme->own_seq_nr; -} -static int pack_and_send(struct esme *esme, uint32_t type, void *ptr) -{ - struct msgb *msg = msgb_alloc(4096, "SMPP_Tx"); - int rc, rlen; - if (!msg) - return -ENOMEM; - - rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr); - if (rc != 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n", - esme->system_id, smpp34_strerror); - msgb_free(msg); - return -EINVAL; - } - msgb_put(msg, rlen); - - if (osmo_wqueue_enqueue(&esme->wqueue, msg) != 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Write queue full. Dropping message\n", - esme->system_id); - msgb_free(msg); - return -EAGAIN; - } - return 0; -} -/* FIXME: merge with smpp_smsc.c */ static struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag) { @@ -188,8 +117,8 @@ static int bind_transceiver(struct esme *esme) memset(&bind, 0, sizeof(bind)); bind.command_id = BIND_TRANSCEIVER; bind.sequence_number = esme_inc_seq_nr(esme); - snprintf((char *)bind.system_id, sizeof(bind.system_id), "%s", esme->system_id); - snprintf((char *)bind.password, sizeof(bind.password), "%s", esme->password); + snprintf((char *)bind.system_id, SMPP_SYS_ID_LEN + 1, "%s", esme->system_id); + snprintf((char *)bind.password, SMPP_SYS_ID_LEN + 1, "%s", esme->password); snprintf((char *)bind.system_type, sizeof(bind.system_type), "mirror"); bind.interface_version = esme->smpp_version; @@ -238,8 +167,7 @@ static int esme_read_cb(struct osmo_fd *ofd) rdlen = sizeof(uint32_t) - esme->read_idx; rc = read(ofd->fd, lenptr + esme->read_idx, rdlen); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n", - esme->system_id, rc); + LOGPESME(esme, LOGL_ERROR, "read returned %d\n", rc); } else if (rc == 0) { goto dead_socket; } else @@ -265,8 +193,7 @@ static int esme_read_cb(struct osmo_fd *ofd) rdlen = esme->read_len - esme->read_idx; rc = read(ofd->fd, msg->tail, OSMO_MIN(rdlen, msgb_tailroom(msg))); if (rc < 0) { - LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n", - esme->system_id, rc); + LOGPESME(esme, LOGL_ERROR, "read returned %d\n", rc); } else if (rc == 0) { goto dead_socket; } else { @@ -305,7 +232,7 @@ static int esme_write_cb(struct osmo_fd *ofd, struct msgb *msg) esme->wqueue.bfd.fd = -1; exit(99); } else if (rc < msgb_length(msg)) { - LOGP(DSMPP, LOGL_ERROR, "[%s] Short write\n", esme->system_id); + LOGPESME(esme, LOGL_ERROR, "Short write\n"); return 0; } @@ -317,11 +244,8 @@ static int smpp_esme_init(struct esme *esme, const char *host, uint16_t port) int rc; if (port == 0) - port = 2775; + port = SMPP_PORT; - esme->own_seq_nr = rand(); - esme_inc_seq_nr(esme); - osmo_wqueue_init(&esme->wqueue, 10); esme->wqueue.bfd.data = esme; esme->wqueue.read_cb = esme_read_cb; esme->wqueue.write_cb = esme_write_cb; @@ -349,7 +273,7 @@ const struct log_info log_info = { int main(int argc, char **argv) { - struct esme esme; + struct esme *esme; char *host = "localhost"; int port = 0; int rc; @@ -357,20 +281,22 @@ int main(int argc, char **argv) msgb_talloc_ctx_init(ctx, 0); - memset(&esme, 0, sizeof(esme)); - osmo_init_logging2(ctx, &log_info); - snprintf((char *) esme.system_id, sizeof(esme.system_id), "mirror"); - snprintf((char *) esme.password, sizeof(esme.password), "mirror"); - esme.smpp_version = 0x34; + esme = esme_alloc(ctx); + if (!esme) + exit(2); + + snprintf((char *) esme->system_id, sizeof(esme->system_id), "mirror"); + snprintf((char *) esme->password, sizeof(esme->password), "mirror"); + esme->smpp_version = 0x34; if (argc >= 2) host = argv[1]; if (argc >= 3) port = atoi(argv[2]); - rc = smpp_esme_init(&esme, host, port); + rc = smpp_esme_init(esme, host, port); if (rc < 0) exit(1); diff --git a/tests/Makefile.am b/tests/Makefile.am index c7651589e..7ab3c377f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,6 +4,7 @@ SUBDIRS = \ db_sms \ sdp_msg \ mncc \ + csd \ $(NULL) if BUILD_SMPP @@ -37,7 +38,7 @@ EXTRA_DIST = \ vty_test_runner.py \ ctrl_test_runner.py \ smpp_test_runner.py \ - test_nodes.vty \ + $(srcdir)/*.vty \ $(NULL) TESTSUITE = $(srcdir)/testsuite @@ -48,7 +49,7 @@ DISTCLEANFILES = \ if ENABLE_EXT_TESTS # don't run multiple tests concurrently so that the ports don't conflict -python-tests: $(BUILT_SOURCES) +python-tests: $(MAKE) vty-test $(MAKE) ctrl-test if BUILD_SMPP @@ -56,11 +57,11 @@ if BUILD_SMPP endif else -python-tests: $(BUILT_SOURCES) +python-tests: echo "Not running python-based tests (determined at configure-time)" endif -vty-python-test: $(BUILT_SOURCES) +vty-python-test: $(top_builddir)/src/osmo-msc/osmo-msc if BUILD_IU IU=1 osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v IU=1 osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v @@ -69,7 +70,7 @@ else IU=0 osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v endif $(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v - rm -f $(top_builddir)/sms.db + rm -f $(top_builddir)/sms.db* # Run a specific transcript test with: 'make vty-transcript-test VTY_TEST=osmo-msc.vty' VTY_TEST ?= *.vty @@ -77,21 +78,21 @@ VTY_TEST ?= *.vty # To update the VTY script from current application behavior, # pass -u to vty_script_runner.py by doing: # make vty-transcript-test U=-u -vty-transcript-test: +vty-transcript-test: $(top_builddir)/src/osmo-msc/osmo-msc osmo_verify_transcript_vty.py -v \ -n OsmoMSC -p 4254 \ -r "$(top_builddir)/src/osmo-msc/osmo-msc -c $(top_srcdir)/doc/examples/osmo-msc/osmo-msc.cfg" \ $(U) $(srcdir)/$(VTY_TEST) - rm -f $(builddir)/sms.db + rm -f $(builddir)/sms.db* # don't run multiple tests concurrently so that the ports don't conflict vty-test: $(MAKE) vty-python-test $(MAKE) vty-transcript-test -ctrl-python-test: $(BUILT_SOURCES) +ctrl-python-test: $(top_builddir)/src/osmo-msc/osmo-msc $(srcdir)/ctrl_test_runner.py -w $(abs_top_builddir) -v - rm -f $(top_builddir)/sms.db + rm -f $(top_builddir)/sms.db* # To update the CTRL script from current application behavior, # pass -u to ctrl_script_runner.py by doing: @@ -104,9 +105,9 @@ ctrl-test: $(MAKE) ctrl-python-test $(MAKE) ctrl-transcript-test -smpp-test: +smpp-test:$(top_builddir)/src/osmo-msc/osmo-msc $(srcdir)/smpp_test_runner.py -w $(abs_top_builddir) -v - rm -f $(top_builddir)/sms.db + rm -f $(top_builddir)/sms.db* check-local: atconfig $(TESTSUITE) $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) diff --git a/tests/csd/Makefile.am b/tests/csd/Makefile.am new file mode 100644 index 000000000..581f7d402 --- /dev/null +++ b/tests/csd/Makefile.am @@ -0,0 +1,37 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBOSMOCORE_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -no-install \ + $(NULL) + +LDADD = \ + $(top_builddir)/src/libmsc/libmsc.a \ + $(LIBOSMOCORE_LIBS) \ + $(NULL) + +EXTRA_DIST = \ + csd_test.ok \ + csd_test.err \ + $(NULL) + +check_PROGRAMS = \ + csd_test \ + $(NULL) + +csd_test_SOURCES = \ + csd_test.c \ + $(NULL) + +.PHONY: update_exp +update_exp: + $(builddir)/csd_test >$(srcdir)/csd_test.ok 2>$(srcdir)/csd_test.err diff --git a/tests/csd/csd_test.c b/tests/csd/csd_test.c new file mode 100644 index 000000000..ad3b0daf4 --- /dev/null +++ b/tests/csd/csd_test.c @@ -0,0 +1,44 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <osmocom/core/application.h> +#include <osmocom/msc/csd_bs.h> +#include <osmocom/msc/debug.h> + +void test_csd_bs_list_remove(void) +{ + struct csd_bs_list list = { + .count = 3, + .bs = { + CSD_BS_21_T_V110_0k3, + CSD_BS_22_T_V110_1k2, + CSD_BS_24_T_V110_2k4, + }, + }; + + printf("=== %s ===\n", __func__); + printf("initial:\n"); + printf(" %s\n", csd_bs_list_to_str(&list)); + + printf("removing BS25T (not in the list):\n"); + csd_bs_list_remove(&list, CSD_BS_25_T_V110_4k8); + printf(" %s\n", csd_bs_list_to_str(&list)); + + printf("removing BS22T:\n"); + csd_bs_list_remove(&list, CSD_BS_22_T_V110_1k2); + printf(" %s\n", csd_bs_list_to_str(&list)); + + printf("removing BS24T:\n"); + csd_bs_list_remove(&list, CSD_BS_24_T_V110_2k4); + printf(" %s\n", csd_bs_list_to_str(&list)); + + printf("removing BS21T:\n"); + csd_bs_list_remove(&list, CSD_BS_21_T_V110_0k3); + printf(" %s\n", csd_bs_list_to_str(&list)); +} + +int main(void) +{ + test_csd_bs_list_remove(); + return 0; +} diff --git a/tests/csd/csd_test.err b/tests/csd/csd_test.err new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/csd/csd_test.err diff --git a/tests/csd/csd_test.ok b/tests/csd/csd_test.ok new file mode 100644 index 000000000..0beac462a --- /dev/null +++ b/tests/csd/csd_test.ok @@ -0,0 +1,11 @@ +=== test_csd_bs_list_remove === +initial: + BS21T,BS22T,BS24T +removing BS25T (not in the list): + BS21T,BS22T,BS24T +removing BS22T: + BS21T,BS24T +removing BS24T: + BS21T +removing BS21T: + (no-bearer-services) diff --git a/tests/ctrl_test_runner.py b/tests/ctrl_test_runner.py index d24cc0019..16d1e7cca 100755 --- a/tests/ctrl_test_runner.py +++ b/tests/ctrl_test_runner.py @@ -64,7 +64,9 @@ class TestCtrlBase(unittest.TestCase): def tearDown(self): self.disconnect() - osmoutil.end_proc(self.proc) + rc = osmoutil.end_proc(self.proc) + if rc is not None and rc != 0: + raise Exception("Process returned %d" % rc) def disconnect(self): if not (self.sock is None): diff --git a/tests/db_sms/Makefile.am b/tests/db_sms/Makefile.am index 4e850679d..9dabfe719 100644 --- a/tests/db_sms/Makefile.am +++ b/tests/db_sms/Makefile.am @@ -14,9 +14,14 @@ AM_CFLAGS = \ $(LIBOSMOSIGTRAN_CFLAGS) \ $(LIBOSMORANAP_CFLAGS) \ $(LIBOSMONETIF_CFLAGS) \ - $(LIBSMPP34_CFLAGS) \ $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(LIBOSMOGSUPCLIENT_CFLAGS) \ + $(LIBSQLITE3_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -no-install \ $(NULL) EXTRA_DIST = \ @@ -24,7 +29,7 @@ EXTRA_DIST = \ db_sms_test.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ db_sms_test \ $(NULL) @@ -36,7 +41,6 @@ db_sms_test_SOURCES = \ db_sms_test_LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libvlr/libvlr.a \ - $(LIBSMPP34_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ @@ -46,6 +50,6 @@ db_sms_test_LDADD = \ $(LIBASN1C_LIBS) \ $(LIBOSMOMGCPCLIENT_LIBS) \ $(LIBOSMOGSUPCLIENT_LIBS) \ + $(LIBSQLITE3_LIBS) \ $(LIBRARY_GSM) \ - -ldbi \ $(NULL) diff --git a/tests/db_sms/db_sms_test.c b/tests/db_sms/db_sms_test.c index 87dd79ebd..7c015d318 100644 --- a/tests/db_sms/db_sms_test.c +++ b/tests/db_sms/db_sms_test.c @@ -538,7 +538,7 @@ int main(int argc, char **argv) * the test output is not deterministic. Let's suppress this * message by increasing the log level to LOGL_ERROR. */ log_parse_category_mask(osmo_stderr_target, "DDB,7"); - rc = db_init(":memory:"); + rc = db_init(talloc_ctx, ":memory:", true); OSMO_ASSERT(rc == 0); /* HACK: relax log level back to LOGL_DEBUG (see note above) */ diff --git a/tests/mncc/Makefile.am b/tests/mncc/Makefile.am index ae859ab21..a4c296008 100644 --- a/tests/mncc/Makefile.am +++ b/tests/mncc/Makefile.am @@ -9,6 +9,11 @@ AM_CFLAGS = \ $(LIBOSMOCORE_CFLAGS) \ $(NULL) +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -no-install \ + $(NULL) + LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(LIBOSMOCORE_LIBS) \ @@ -19,7 +24,7 @@ EXTRA_DIST = \ mncc_test.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ mncc_test \ $(NULL) diff --git a/tests/mncc/mncc_test.c b/tests/mncc/mncc_test.c index f752cabbf..9532846f4 100644 --- a/tests/mncc/mncc_test.c +++ b/tests/mncc/mncc_test.c @@ -67,7 +67,7 @@ const struct log_info log_info = { int main(void) { - void *ctx = talloc_named_const(NULL, 0, "smpp_test"); + void *ctx = talloc_named_const(NULL, 0, "mncc_test"); osmo_init_logging2(ctx, &log_info); log_set_use_color(osmo_stderr_target, 0); log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); diff --git a/tests/mncc/mncc_test.ok b/tests/mncc/mncc_test.ok index 059e8080d..ca3ac6484 100644 --- a/tests/mncc/mncc_test.ok +++ b/tests/mncc/mncc_test.ok @@ -1,10 +1,10 @@ test_sdp_termination() struct gsm_mncc: -empty SDP: len=1876 sdplen=1026 sdp="\0" rc=0 +empty SDP: len=1896 sdplen=1046 sdp="\0" rc=0 empty SDP, shortest possible: len=851 sdplen=1 sdp="\0" rc=0 empty SDP, zero len: len=850 sdplen=0 sdp=- rc=-22 -terminated SDP str: len=1876 sdplen=1026 sdp="Privacy is a desirable marketing option\0" rc=0 +terminated SDP str: len=1896 sdplen=1046 sdp="Privacy is a desirable marketing option\0" rc=0 terminated SDP str, shortest possible: len=890 sdplen=40 sdp="Privacy is a desirable marketing option\0" rc=0 terminated SDP str, but len excludes nul: len=889 sdplen=39 sdp="Privacy is a desirable marketing option" rc=-22 terminated SDP str, but len too short: len=873 sdplen=23 sdp="Privacy is a desirable " rc=-22 diff --git a/tests/msc_vlr/Makefile.am b/tests/msc_vlr/Makefile.am index 0e150367c..cbdd6a409 100644 --- a/tests/msc_vlr/Makefile.am +++ b/tests/msc_vlr/Makefile.am @@ -8,7 +8,6 @@ AM_CFLAGS = \ -ggdb3 \ $(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) \ - $(LIBSMPP34_CFLAGS) \ $(LIBOSMOVTY_CFLAGS) \ $(LIBOSMOABIS_CFLAGS) \ $(LIBOSMOSIGTRAN_CFLAGS) \ @@ -17,6 +16,7 @@ AM_CFLAGS = \ $(LIBASN1C_CFLAGS) \ $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(LIBOSMOGSUPCLIENT_CFLAGS) \ + $(LIBSQLITE3_CFLAGS) \ $(NULL) AM_LDFLAGS = \ @@ -26,12 +26,13 @@ AM_LDFLAGS = \ -Wl,--wrap=osmo_get_rand_id \ -Wl,--wrap=ran_peers_down_paging \ -Wl,--wrap=call_leg_ensure_ci \ + $(COVERAGE_LDFLAGS) \ + -no-install \ $(NULL) LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libvlr/libvlr.a \ - $(LIBSMPP34_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ @@ -41,8 +42,8 @@ LDADD = \ $(LIBASN1C_LIBS) \ $(LIBOSMOMGCPCLIENT_LIBS) \ $(LIBOSMOGSUPCLIENT_LIBS) \ + $(LIBSQLITE3_LIBS) \ $(LIBRARY_GSM) \ - -ldbi \ $(NULL) noinst_HEADERS = \ @@ -76,7 +77,7 @@ EXTRA_DIST = \ msc_vlr_test_ss.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ msc_vlr_test_no_authen \ msc_vlr_test_gsm_authen \ msc_vlr_test_gsm_ciph \ diff --git a/tests/msc_vlr/msc_vlr_test_authen_reuse.err b/tests/msc_vlr/msc_vlr_test_authen_reuse.err index be2834811..1f8afb07f 100644 --- a/tests/msc_vlr/msc_vlr_test_authen_reuse.err +++ b/tests/msc_vlr/msc_vlr_test_authen_reuse.err @@ -66,7 +66,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -575,7 +575,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -1106,7 +1106,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -1721,7 +1721,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -2364,7 +2364,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -2755,7 +2755,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu diff --git a/tests/msc_vlr/msc_vlr_test_call.c b/tests/msc_vlr/msc_vlr_test_call.c index a547935b2..14c8ea304 100644 --- a/tests/msc_vlr/msc_vlr_test_call.c +++ b/tests/msc_vlr/msc_vlr_test_call.c @@ -24,6 +24,7 @@ #include "msc_vlr_tests.h" #include <osmocom/msc/gsm_04_08.h> +#include <osmocom/msc/codec_mapping.h> #define mncc_sends_to_cc(MSG_TYPE, MNCC) do { \ (MNCC)->msg_type = MSG_TYPE; \ @@ -163,11 +164,50 @@ static void lu_utran_tmsi() vlr_subscr_put(vsub, __func__); } +static void lu_geran_noauth(void) +{ + rx_from_ran = OSMO_RAT_GERAN_A; + net->authentication_required = false; + net->vlr->cfg.assign_tmsi = false; + + btw("Location Update request causes a GSUP LU request to HLR"); + lu_result_sent = RES_NONE; + gsup_expect_tx("04010809710000000156f0280102" VLR_TO_HLR); + ms_sends_msg("0508" /* MM LU */ + "7" /* ciph key seq: no key available */ + "0" /* LU type: normal */ + "09f107" "0017" /* LAI, LAC */ + "57" /* classmark 1: R99, early classmark, no power lvl */ + "089910070000106005" /* IMSI */ + "3303575886" /* classmark 2 */ + ); + OSMO_ASSERT(gsup_tx_confirmed); + VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); + + btw("HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT"); + gsup_rx("10010809710000000156f00804036470f1" HLR_TO_VLR, + "12010809710000000156f0" VLR_TO_HLR); + VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); + + btw("HLR also sends GSUP _UPDATE_LOCATION_RESULT"); + expect_bssap_clear(); + gsup_rx("06010809710000000156f0" HLR_TO_VLR, NULL); + + btw("LU was successful, and the conn has already been closed"); + VERBOSE_ASSERT(lu_result_sent, == RES_ACCEPT, "%d"); + VERBOSE_ASSERT(bssap_clear_sent, == true, "%d"); + + ran_sends_clear_complete(); + EXPECT_CONN_COUNT(0); +} + + static void test_call_mo() { struct gsm_mncc mncc = { .imsi = IMSI, }; + struct gsm_mncc_rtp mncc_rtp = {}; comment_start(); @@ -202,8 +242,9 @@ static void test_call_mo() BTW("a call is initiated"); - btw("SETUP gets forwarded to MNCC"); - cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + btw("CC SETUP causes CRCX towards CN and RAN"); + expect_crcx(RTP_TO_CN); + expect_crcx(RTP_TO_RAN); ms_sends_msg("0385" /* CC, seq = 2 -> 0x80 | CC Setup = 0x5 */ "0406600402000581" /* Bearer Capability */ "5e038121f3" /* Called Number BCD */ @@ -212,27 +253,27 @@ static void test_call_mo() "04026000" /* UMTS: AMR 2 | AMR */ "00021f00" /* GSM: HR AMR | FR AMR | GSM EFR | GSM HR | GSM FR */ ); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); + + btw("As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered"); + cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + crcx_ok(RTP_TO_CN); OSMO_ASSERT(cc_to_mncc_tx_confirmed); - mncc.callref = cc_to_mncc_tx_got_callref; + mncc.callref = mncc_rtp.callref = cc_to_mncc_tx_got_callref; - btw("MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN"); - expect_crcx(RTP_TO_RAN); - mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc); - OSMO_ASSERT(got_crcx); + btw("MNCC replies with MNCC_RTP_CREATE"); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); btw("MGW acknowledges the CRCX, triggering Assignment"); expect_iu_rab_assignment(); crcx_ok(RTP_TO_RAN); OSMO_ASSERT(iu_rab_assignment_sent); - btw("Assignment succeeds, triggering CRCX to CN"); - expect_crcx(RTP_TO_CN); - ms_sends_assignment_complete(CODEC_AMR_8000_1); - OSMO_ASSERT(got_crcx); - - btw("CN RTP address is available, trigger MNCC_RTP_CREATE"); + btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC"); cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); - crcx_ok(RTP_TO_CN); + ms_sends_assignment_complete("AMR"); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); btw("MNCC says that's fine"); dtap_expect_tx("8302" /* CC: Call Proceeding */); @@ -285,6 +326,34 @@ static void test_call_mt() struct gsm_mncc mncc = { .imsi = IMSI, .callref = 0x423, + .fields = MNCC_F_BEARER_CAP, + .bearer_cap = { + .speech_ver = { + GSM48_BCAP_SV_AMR_F, + GSM48_BCAP_SV_EFR, + GSM48_BCAP_SV_FR, + GSM48_BCAP_SV_AMR_H, + GSM48_BCAP_SV_HR, + -1 }, + }, + /* NOTE: below SDP includes only AMR, above bearer_cap includes more codecs. Ideally, these would match, + * but in reality the bearer cap in MNCC was never implemented properly. This test shows that above + * bearer_cap is ignored when SDP is present: In the CC Setup below, the Bearer Capability is only + * "04 04 60 04 05 8b" with speech versions '04' == GSM48_BCAP_SV_AMR_F and '05' == GSM48_BCAP_SV_AMR_H. + */ + .sdp = "v=0\r\n" + "o=OsmoMSC 0 0 IN IP4 10.23.23.1\r\n" + "s=GSM Call\r\n" + "c=IN IP4 10.23.23.1\r\n" + "t=0 0\r\n" + "m=audio 23 RTP/AVP 112\r\n" + "a=rtpmap:112 AMR/8000\r\n" + "a=fmtp:112 octet-align=1\r\n" + "a=ptime:20\r\n", + }; + + struct gsm_mncc_rtp mncc_rtp = { + .callref = 0x423, }; comment_start(); @@ -298,6 +367,7 @@ static void test_call_mt() paging_expect_imsi(IMSI); paging_sent = false; mncc_sends_to_cc(MNCC_SETUP_REQ, &mncc); + mncc.sdp[0] = '\0'; VERBOSE_ASSERT(paging_sent, == true, "%d"); @@ -316,22 +386,21 @@ static void test_call_mt() VERBOSE_ASSERT(security_mode_ctrl_sent, == true, "%d"); btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup"); - dtap_expect_tx("0305" /* CC: Setup */); + dtap_expect_tx("0305" /* CC: Setup */ "04 04 60 04 05 8b" /* Bearer Cap, speech ver of AMR-FR and AMR-HR */); ms_sends_security_mode_complete(1); btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND"); + expect_crcx(RTP_TO_CN); expect_crcx(RTP_TO_RAN); cc_to_mncc_expect_tx(IMSI, MNCC_CALL_CONF_IND); ms_sends_msg("8348" /* CC: Call Confirmed */ "0406600402000581" /* Bearer Capability */ "15020100" /* Call Control Capabilities */ "40080402600400021f00" /* Supported Codec List */); - OSMO_ASSERT(got_crcx); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); OSMO_ASSERT(cc_to_mncc_tx_confirmed); - btw("MNCC sends MNCC_RTP_CREATE"); - mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc); - btw("MGW acknowledges the CRCX to RAN, triggering Assignment"); expect_iu_rab_assignment(); crcx_ok(RTP_TO_RAN); @@ -339,22 +408,27 @@ static void test_call_mt() btw("Assignment completes, triggering CRCX to CN"); expect_crcx(RTP_TO_CN); - ms_sends_assignment_complete(CODEC_AMR_8000_1); - OSMO_ASSERT(got_crcx); + ms_sends_assignment_complete("AMR"); + + btw("MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP"); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); - btw("When the CN side RTP address is known, send MNCC_RTP_CREATE"); + btw("When the CN side RTP address is known, ack MNCC_RTP_CREATE with full SDP"); cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); crcx_ok(RTP_TO_CN); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); fake_time_passes(1, 23); cc_to_mncc_expect_tx("", MNCC_ALERT_IND); ms_sends_msg("8381" /* CC: Alerting */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); fake_time_passes(1, 23); cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_CNF); ms_sends_msg("83c7" /* CC: Connect */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); dtap_expect_tx("030f" /* CC: Connect Acknowledge */); mncc_sends_to_cc(MNCC_SETUP_COMPL_REQ, &mncc); @@ -388,6 +462,37 @@ static void test_call_mt2() struct gsm_mncc mncc = { .imsi = IMSI, .callref = 0x423, + .fields = MNCC_F_BEARER_CAP, + .bearer_cap = { + .speech_ver = { GSM48_BCAP_SV_FR, -1, }, + }, + /* NOTE: below SDP includes only AMR, above bearer_cap includes only GSM-FR. Ideally, these would match, + * but in reality the bearer cap in MNCC was never implemented properly. This test shows that above + * bearer_cap is ignored when SDP is present: In the CC Setup below, the Bearer Capability is only + * "04 04 60 04 05 8b" with speech versions '04' == GSM48_BCAP_SV_AMR_F and '05' == GSM48_BCAP_SV_AMR_H. + */ + .sdp = "v=0\r\n" + "o=OsmoMSC 0 0 IN IP4 10.23.23.1\r\n" + "s=GSM Call\r\n" + "c=IN IP4 10.23.23.1\r\n" + "t=0 0\r\n" + "m=audio 23 RTP/AVP 112\r\n" + "a=rtpmap:112 AMR/8000\r\n" + "a=fmtp:112 octet-align=1\r\n" + "a=ptime:20\r\n", + }; + + struct gsm_mncc_rtp mncc_rtp = { + .callref = 0x423, + .sdp = "v=0\r\n" + "o=OsmoMSC 0 0 IN IP4 10.23.23.1\r\n" + "s=GSM Call\r\n" + "c=IN IP4 10.23.23.1\r\n" + "t=0 0\r\n" + "m=audio 23 RTP/AVP 112\r\n" + "a=rtpmap:112 AMR/8000\r\n" + "a=fmtp:112 octet-align=1\r\n" + "a=ptime:20\r\n", }; comment_start(); @@ -419,21 +524,23 @@ static void test_call_mt2() VERBOSE_ASSERT(security_mode_ctrl_sent, == true, "%d"); btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup"); - dtap_expect_tx("0305" /* CC: Setup */); + dtap_expect_tx("0305" /* CC: Setup */ "04 04 60 04 05 8b" /* Bearer Cap, speech ver of AMR-FR and AMR-HR */); ms_sends_security_mode_complete(1); btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND"); + expect_crcx(RTP_TO_CN); expect_crcx(RTP_TO_RAN); cc_to_mncc_expect_tx(IMSI, MNCC_CALL_CONF_IND); ms_sends_msg("8348" /* CC: Call Confirmed */ "0406600402000581" /* Bearer Capability */ "15020100" /* Call Control Capabilities */ "40080402600400021f00" /* Supported Codec List */); - OSMO_ASSERT(got_crcx); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); OSMO_ASSERT(cc_to_mncc_tx_confirmed); - btw("MNCC sends MNCC_RTP_CREATE"); - mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc); + btw("MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP"); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); btw("MGW acknowledges the CRCX to RAN, triggering Assignment"); expect_iu_rab_assignment(); @@ -441,13 +548,13 @@ static void test_call_mt2() OSMO_ASSERT(iu_rab_assignment_sent); btw("Assignment completes, triggering CRCX to CN"); - expect_crcx(RTP_TO_CN); - ms_sends_assignment_complete(CODEC_AMR_8000_1); - OSMO_ASSERT(got_crcx); + ms_sends_assignment_complete("AMR"); - btw("When the CN side RTP address is known, send MNCC_RTP_CREATE"); + btw("When the CN side RTP address is known, ack MNCC_RTP_CREATE with full SDP"); cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); crcx_ok(RTP_TO_CN); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + fake_time_passes(1, 23); cc_to_mncc_expect_tx("", MNCC_ALERT_IND); @@ -481,6 +588,8 @@ static void test_call_mo_to_unknown() .imsi = IMSI, }; + struct gsm_mncc_rtp mncc_rtp = {}; + comment_start(); fake_time_start(); @@ -514,8 +623,9 @@ static void test_call_mo_to_unknown() BTW("a call is initiated"); - btw("SETUP gets forwarded to MNCC"); - cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + btw("CC SETUP causes CRCX towards CN and RAN"); + expect_crcx(RTP_TO_CN); + expect_crcx(RTP_TO_RAN); ms_sends_msg("0385" /* CC, seq = 2 -> 0x80 | CC Setup = 0x5 */ "0406600402000581" /* Bearer Capability */ "5e038121f3" /* Called Number BCD */ @@ -524,27 +634,27 @@ static void test_call_mo_to_unknown() "04026000" /* UMTS: AMR 2 | AMR */ "00021f00" /* GSM: HR AMR | FR AMR | GSM EFR | GSM HR | GSM FR */ ); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); + + btw("As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered"); + cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + crcx_ok(RTP_TO_CN); OSMO_ASSERT(cc_to_mncc_tx_confirmed); - mncc.callref = cc_to_mncc_tx_got_callref; + mncc.callref = mncc_rtp.callref = cc_to_mncc_tx_got_callref; - btw("MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN"); - expect_crcx(RTP_TO_RAN); - mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc); - OSMO_ASSERT(got_crcx); + btw("MNCC replies with MNCC_RTP_CREATE"); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); btw("MGW acknowledges the CRCX, triggering Assignment"); expect_iu_rab_assignment(); crcx_ok(RTP_TO_RAN); OSMO_ASSERT(iu_rab_assignment_sent); - btw("Assignment succeeds, triggering CRCX to CN"); - expect_crcx(RTP_TO_CN); - ms_sends_assignment_complete(CODEC_AMR_8000_1); - OSMO_ASSERT(got_crcx); - - btw("CN RTP address is available, trigger MNCC_RTP_CREATE"); + btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC"); cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); - crcx_ok(RTP_TO_CN); + ms_sends_assignment_complete("AMR"); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); btw("MNCC says that's fine"); dtap_expect_tx("8302" /* CC: Call Proceeding */); @@ -561,7 +671,6 @@ static void test_call_mo_to_unknown() expect_iu_release(); cc_to_mncc_expect_tx("", MNCC_REL_CNF); ms_sends_msg("036a" /* CC: Release Complete */); - OSMO_ASSERT(cc_to_mncc_tx_confirmed); OSMO_ASSERT(iu_release_sent); OSMO_ASSERT(cc_to_mncc_tx_confirmed); @@ -576,6 +685,7 @@ static void test_call_mo_to_unknown_timeout() struct gsm_mncc mncc = { .imsi = IMSI, }; + struct gsm_mncc_rtp mncc_rtp = {}; comment_start(); @@ -610,8 +720,9 @@ static void test_call_mo_to_unknown_timeout() BTW("a call is initiated"); - btw("SETUP gets forwarded to MNCC"); - cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + btw("CC SETUP causes CRCX towards CN and RAN"); + expect_crcx(RTP_TO_CN); + expect_crcx(RTP_TO_RAN); ms_sends_msg("0385" /* CC, seq = 2 -> 0x80 | CC Setup = 0x5 */ "0406600402000581" /* Bearer Capability */ "5e038121f3" /* Called Number BCD */ @@ -620,27 +731,27 @@ static void test_call_mo_to_unknown_timeout() "04026000" /* UMTS: AMR 2 | AMR */ "00021f00" /* GSM: HR AMR | FR AMR | GSM EFR | GSM HR | GSM FR */ ); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); + + btw("As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered"); + cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + crcx_ok(RTP_TO_CN); OSMO_ASSERT(cc_to_mncc_tx_confirmed); - mncc.callref = cc_to_mncc_tx_got_callref; + mncc.callref = mncc_rtp.callref = cc_to_mncc_tx_got_callref; - btw("MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN"); - expect_crcx(RTP_TO_RAN); - mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc); - OSMO_ASSERT(got_crcx); + btw("MNCC replies with MNCC_RTP_CREATE"); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); btw("MGW acknowledges the CRCX, triggering Assignment"); expect_iu_rab_assignment(); crcx_ok(RTP_TO_RAN); OSMO_ASSERT(iu_rab_assignment_sent); - btw("Assignment succeeds, triggering CRCX to CN"); - expect_crcx(RTP_TO_CN); - ms_sends_assignment_complete(CODEC_AMR_8000_1); - OSMO_ASSERT(got_crcx); - - btw("CN RTP address is available, trigger MNCC_RTP_CREATE"); + btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC"); cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); - crcx_ok(RTP_TO_CN); + ms_sends_assignment_complete("AMR"); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); btw("MNCC says that's fine"); dtap_expect_tx("8302" /* CC: Call Proceeding */); @@ -668,6 +779,862 @@ static void test_call_mo_to_unknown_timeout() comment_end(); } +#define LIST_END 0xffff + +struct codec_test { + const char *desc; + + /* What to send during Complete Layer 3 as Codec List (BSS Supported). List ends with a LIST_END entry */ + enum gsm0808_speech_codec_type mo_rx_compl_l3_codec_list_bss_supported[8]; + + /* What to send during CC Setup as MS Bearer Capability. List ends with a LIST_END entry */ + enum gsm48_bcap_speech_ver mo_rx_ms_bcap[8]; + + /* What codecs should osmo-msc send in the MNCC_SETUP_IND message. + * Just the SDP subtype names like "GSM", "GSM-EFR", "AMR", ..., list ends with NULL entry */ + const char *mo_tx_sdp_mncc_setup_ind[8]; + + /* What codecs the remote call leg should send as SDP via MNCC during MNCC_RTP_CREATE (if any). */ + const char *mo_rx_sdp_mncc_rtp_create[8]; + + /* What the MSC should send as Channel Type IE in the Assignment Command to the BSS. List ends with a + * LIST_END entry */ + enum gsm0808_permitted_speech mo_tx_assignment_perm_speech[8]; + + /* What codec to assign in the Assignment Complete's Codec (Chosen) IE. Just a subtype name. */ + const char *mo_rx_assigned_codec; + + /* MO acks the MNCC_RTP_CREATE with these codecs (if any). */ + const char *mo_tx_sdp_mncc_rtp_create[8]; + + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ +#define mt_rx_sdp_mncc_setup_req mo_tx_sdp_mncc_rtp_create + + enum gsm0808_speech_codec_type mt_rx_compl_l3_codec_list_bss_supported[8]; + bool expect_codec_mismatch_on_paging_response; + enum gsm48_bcap_speech_ver mt_tx_cc_setup_bcap[8]; + enum gsm48_bcap_speech_ver mt_rx_ms_bcap[8]; + bool expect_codec_mismatch_on_cc_call_conf; + const char *mt_tx_sdp_mncc_call_conf_ind[8]; + + enum gsm0808_permitted_speech mt_tx_assignment_perm_speech[8]; + const char *mt_rx_assigned_codec; + + const char *mt_rx_sdp_mncc_rtp_create[8]; + const char *mt_tx_sdp_mncc_rtp_create[8]; + + const char *mt_tx_sdp_mncc_alert_ind[8]; + + bool mo_expect_reassignment; + enum gsm0808_permitted_speech mo_tx_reassignment_perm_speech[8]; + const char *mo_rx_reassigned_codec; + + const char *mt_tx_sdp_mncc_setup_cnf[8]; + const char *mt_rx_sdp_mncc_setup_compl_req[8]; + + /* mo_rx_sdp_mncc_alert_req == mt_tx_sdp_mncc_alert_ind */ +#define mo_rx_sdp_mncc_alert_req mt_tx_sdp_mncc_alert_ind +#define mo_rx_sdp_mncc_setup_rsp mt_tx_sdp_mncc_alert_ind + + const char *mo_tx_sdp_mncc_setup_compl_ind[8]; +}; + +#define CODEC_LIST_ALL_GSM { \ + GSM0808_SCT_FR1, \ + GSM0808_SCT_FR2, \ + GSM0808_SCT_FR3, \ + GSM0808_SCT_HR1, \ + GSM0808_SCT_HR3, \ + LIST_END \ + } + +#define BCAP_ALL_GSM { \ + GSM48_BCAP_SV_AMR_F, \ + GSM48_BCAP_SV_AMR_H, \ + GSM48_BCAP_SV_AMR_OH, \ + GSM48_BCAP_SV_EFR, \ + GSM48_BCAP_SV_FR, \ + GSM48_BCAP_SV_HR, \ + LIST_END \ + } + +#define PERM_SPEECH_ALL_GSM { \ + GSM0808_PERM_FR3, \ + GSM0808_PERM_HR3, \ + GSM0808_PERM_FR2, \ + GSM0808_PERM_FR1, \ + GSM0808_PERM_HR1, \ + LIST_END \ + } + +#define SDP_CODECS_ALL_GSM { \ + "AMR", \ + "GSM-EFR", \ + "GSM", \ + "GSM-HR-08", \ + } + +static const struct codec_test codec_tests[] = { + { + .desc = "AMR picked by both MO and MT", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM, + .mo_rx_assigned_codec = "AMR", + .mo_tx_sdp_mncc_rtp_create = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = { + GSM48_BCAP_SV_AMR_F, + GSM48_BCAP_SV_AMR_H, + GSM48_BCAP_SV_AMR_OH, + GSM48_BCAP_SV_EFR, + GSM48_BCAP_SV_FR, + GSM48_BCAP_SV_HR, + LIST_END + }, + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { + GSM0808_PERM_FR3, + GSM0808_PERM_HR3, + GSM0808_PERM_FR2, + GSM0808_PERM_FR1, + GSM0808_PERM_HR1, + LIST_END + }, + .mt_rx_assigned_codec = "AMR", + .mt_tx_sdp_mncc_rtp_create = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_alert_ind = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_setup_cnf = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1", + .mo_rx_compl_l3_codec_list_bss_supported = { GSM0808_SCT_FR1, LIST_END }, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = { "GSM" }, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END }, + .mo_rx_assigned_codec = "GSM", + .mo_tx_sdp_mncc_rtp_create = { "GSM" }, + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = { GSM48_BCAP_SV_FR, LIST_END }, + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END }, + .mt_rx_assigned_codec = "GSM", + .mt_tx_sdp_mncc_rtp_create = { "GSM" }, + .mt_tx_sdp_mncc_alert_ind = { "GSM" }, + .mt_tx_sdp_mncc_setup_cnf = { "GSM" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "FR1 picked by MO from Bearer Cap, MT hence also picks FR1", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = { GSM48_BCAP_SV_FR, LIST_END }, + .mo_tx_sdp_mncc_setup_ind = { "GSM" }, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END }, + .mo_rx_assigned_codec = "GSM", + .mo_tx_sdp_mncc_rtp_create = { "GSM" }, + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = { GSM48_BCAP_SV_FR, LIST_END }, + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { GSM0808_PERM_FR1, LIST_END }, + .mt_rx_assigned_codec = "GSM", + .mt_tx_sdp_mncc_rtp_create = { "GSM" }, + .mt_tx_sdp_mncc_alert_ind = { "GSM" }, + .mt_tx_sdp_mncc_setup_cnf = { "GSM" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "FR1 picked by MT's Codec List (BSS Supported), hence MO re-assigns to FR1", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM, + .mo_rx_assigned_codec = "AMR", /* <- Early Assignment first picks a mismatching codec */ + .mo_tx_sdp_mncc_rtp_create = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + + /* This is the codec limitation this test verifies, Codec List (BSS Supported): */ + .mt_rx_compl_l3_codec_list_bss_supported = { GSM0808_SCT_FR1, LIST_END }, + + /* from above codec list, MSC derives the limited bcap sent in CC Setup to MS */ + .mt_tx_cc_setup_bcap = { + GSM48_BCAP_SV_FR, + LIST_END + }, + /* MS could do more, but it doesn't affect the choice of FR1 */ + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { + GSM0808_PERM_FR1, + LIST_END + }, + .mt_rx_assigned_codec = "GSM", + .mt_tx_sdp_mncc_rtp_create = { "GSM" }, + .mt_tx_sdp_mncc_alert_ind = { "GSM" }, + + .mo_expect_reassignment = true, + .mo_tx_reassignment_perm_speech = { + GSM0808_PERM_FR1, + LIST_END + }, + .mo_rx_reassigned_codec = "GSM", + + .mt_tx_sdp_mncc_setup_cnf = { "GSM" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "FR1 picked by MT's MS Bearer Capability, hence MO re-assigns to FR1", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM, + .mo_rx_assigned_codec = "AMR", /* <- Early Assignment first picks a mismatching codec */ + .mo_tx_sdp_mncc_rtp_create = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = BCAP_ALL_GSM, + + /* This is the codec limitation this test verifies: */ + .mt_rx_ms_bcap = { + GSM48_BCAP_SV_FR, + LIST_END + }, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { + GSM0808_PERM_FR1, + LIST_END + }, + .mt_rx_assigned_codec = "GSM", + .mt_tx_sdp_mncc_rtp_create = { "GSM" }, + .mt_tx_sdp_mncc_alert_ind = { "GSM" }, + + .mo_expect_reassignment = true, + .mo_tx_reassignment_perm_speech = { + GSM0808_PERM_FR1, + LIST_END + }, + .mo_rx_reassigned_codec = "GSM", + + .mt_tx_sdp_mncc_setup_cnf = { "GSM" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "AMR picked by both MO and MT, but MT assigns a different payload type number", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM, + .mo_rx_assigned_codec = "AMR", + .mo_tx_sdp_mncc_rtp_create = { "AMR", "GSM-EFR", "GSM", "GSM-HR-08" }, + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = { + GSM48_BCAP_SV_AMR_F, + GSM48_BCAP_SV_AMR_H, + GSM48_BCAP_SV_AMR_OH, + GSM48_BCAP_SV_EFR, + GSM48_BCAP_SV_FR, + GSM48_BCAP_SV_HR, + LIST_END + }, + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { + GSM0808_PERM_FR3, + GSM0808_PERM_HR3, + GSM0808_PERM_FR2, + GSM0808_PERM_FR1, + GSM0808_PERM_HR1, + LIST_END + }, + .mt_rx_assigned_codec = "AMR", + .mt_tx_sdp_mncc_rtp_create = { "AMR#96", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_alert_ind = { "AMR#96", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_setup_cnf = { "AMR#96", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, + + { + .desc = "AMR picked by both MO and MT, but MO assigns a different payload type number", + .mo_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mo_rx_ms_bcap = BCAP_ALL_GSM, + .mo_tx_sdp_mncc_setup_ind = SDP_CODECS_ALL_GSM, + .mo_rx_sdp_mncc_rtp_create = {}, + .mo_tx_assignment_perm_speech = PERM_SPEECH_ALL_GSM, + .mo_rx_assigned_codec = "AMR", + .mo_tx_sdp_mncc_rtp_create = { "AMR#98", "GSM-EFR", "GSM", "GSM-HR-08" }, + /* mt_rx_sdp_mncc_setup_req == mo_tx_sdp_mncc_rtp_create */ + .mt_rx_compl_l3_codec_list_bss_supported = CODEC_LIST_ALL_GSM, + .mt_tx_cc_setup_bcap = { + GSM48_BCAP_SV_AMR_F, + GSM48_BCAP_SV_AMR_H, + GSM48_BCAP_SV_AMR_OH, + GSM48_BCAP_SV_EFR, + GSM48_BCAP_SV_FR, + GSM48_BCAP_SV_HR, + LIST_END + }, + .mt_rx_ms_bcap = BCAP_ALL_GSM, + .mt_tx_sdp_mncc_call_conf_ind = {}, + .mt_rx_sdp_mncc_rtp_create = {}, + .mt_tx_assignment_perm_speech = { + GSM0808_PERM_FR3, + GSM0808_PERM_HR3, + GSM0808_PERM_FR2, + GSM0808_PERM_FR1, + GSM0808_PERM_HR1, + LIST_END + }, + .mt_rx_assigned_codec = "AMR", + .mt_tx_sdp_mncc_rtp_create = { "AMR#98", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_alert_ind = { "AMR#98", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mt_tx_sdp_mncc_setup_cnf = { "AMR#98", "GSM-EFR", "GSM", "GSM-HR-08" }, + .mo_tx_sdp_mncc_setup_compl_ind = {}, + }, +}; + +static char namebuf[4][1024]; +static int use_namebuf = 0; + +static const char *codec_list_name(const enum gsm0808_speech_codec_type compl_l3_codec_list_bss_supported[]) +{ + struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) }; + use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf); + + const enum gsm0808_speech_codec_type *pos; + sb.buf[0] = '\0'; + for (pos = compl_l3_codec_list_bss_supported; *pos != LIST_END; pos++) + OSMO_STRBUF_PRINTF(sb, " %s", gsm0808_speech_codec_type_name(*pos)); + return sb.buf; +} + +static const struct gsm0808_speech_codec_list *codec_list(const enum gsm0808_speech_codec_type compl_l3_codec_list_bss_supported[]) +{ + static struct gsm0808_speech_codec_list scl; + scl = (struct gsm0808_speech_codec_list){}; + const enum gsm0808_speech_codec_type *pos; + for (pos = compl_l3_codec_list_bss_supported; *pos != LIST_END; pos++) { + scl.codec[scl.len] = (struct gsm0808_speech_codec){ + .fi = true, + .type = *pos, + }; + scl.len++; + } + return &scl; +} + +static const char *bcap_name(const enum gsm48_bcap_speech_ver ms_bcap[]) +{ + struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) }; + use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf); + + const enum gsm48_bcap_speech_ver *pos; + sb.buf[0] = '\0'; + for (pos = ms_bcap; *pos != LIST_END; pos++) { + const struct codec_mapping *m = codec_mapping_by_speech_ver(*pos); + OSMO_STRBUF_PRINTF(sb, " %s", m ? m->sdp.subtype_name : "NULL"); + } + return sb.buf; +} + +static const char *perm_speech_name(const enum gsm0808_permitted_speech perm_speech[]) +{ + struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) }; + use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf); + + const enum gsm0808_permitted_speech *pos; + sb.buf[0] = '\0'; + for (pos = perm_speech; *pos != LIST_END; pos++) + OSMO_STRBUF_PRINTF(sb, " %s", gsm0808_permitted_speech_name(*pos)); + return sb.buf; +} + +static const char *strlist_name(const char *const*strs) +{ + struct osmo_strbuf sb = { .buf = namebuf[use_namebuf], .len = sizeof(namebuf[0]) }; + use_namebuf = (use_namebuf + 1) % ARRAY_SIZE(namebuf); + + const char * const *pos; + sb.buf[0] = '\0'; + for (pos = strs; *pos != NULL; pos++) + OSMO_STRBUF_PRINTF(sb, " %s", *pos); + return sb.buf; +} + +/* Split an input string of "AMR#96" into "AMR" and 96: copy the subtype name without the "#96" part to + * split_subtype_name_and_pt_nr which must be a char[16]. If pt_nr is non-NULL, write the 96 to *pt_nr. + */ +static void split_subtype_name_and_pt_nr(char subtype_name_wo_pt[], int *pt_nr, const char *input) +{ + char *hash; + osmo_strlcpy(subtype_name_wo_pt, input, 16); + hash = strchr(subtype_name_wo_pt, '#'); + if (hash) { + *hash = '\0'; + if (pt_nr) + *pt_nr = atoi(hash + 1); + } +} + +/* Validate that the codecs in sdp_str appear in the order as expected by the list of subtype names in expected_codecs. + * Ignore any payload type numbers ("#96") in expected_codecs. + */ +static bool validate_sdp(const char *func, const char *desc, + const char *sdp_str, const char * const expected_codecs[]) +{ + const char * const *expect_pos; + struct sdp_audio_codec *codec; + struct sdp_msg sdp; + if (sdp_msg_from_sdp_str(&sdp, sdp_str)) { + BTW("%s: %s: ERROR: failed to parse SDP\n%s", func, desc, sdp_str); + return false; + } + + expect_pos = expected_codecs; + sdp_audio_codecs_foreach(codec, &sdp.audio_codecs) { + char subtype_name_wo_pt[16]; + if (!*expect_pos) { + BTW("%s: %s: ERROR: did not expect %s", func, desc, codec->subtype_name); + return false; + } + split_subtype_name_and_pt_nr(subtype_name_wo_pt, NULL, *expect_pos); + if (strcmp(subtype_name_wo_pt, codec->subtype_name)) { + BTW("%s: %s: ERROR: mismatch: in idx %d, expect %s, got %s", func, desc, + (int)(expect_pos - expected_codecs), *expect_pos, codec->subtype_name); + return false; + } + expect_pos++; + + /* only match first codec */ + return true; + } + if (*expect_pos) { + BTW("%s: %s: ERROR: mismatch: expected %s to be listed, but not found", func, desc, *expect_pos); + return false; + } + return true; +} + +#define VALIDATE_SDP(GOT_SDP_STR, EXPECT_SDP_STR) do { \ + if (validate_sdp(__func__, t->desc, GOT_SDP_STR, EXPECT_SDP_STR)) { \ + btw("VALIDATE_SDP OK: " #GOT_SDP_STR " == " #EXPECT_SDP_STR " ==%s", strlist_name(EXPECT_SDP_STR)); \ + } else { \ + btw("Failed to validate SDP:\nexpected%s\ngot\n%s", \ + strlist_name(EXPECT_SDP_STR), GOT_SDP_STR); \ + OSMO_ASSERT(false); \ + } \ + } while (0) + +static bool validate_perm_speech(const char *func, const char *desc, + const struct gsm0808_channel_type *ct, + const enum gsm0808_permitted_speech perm_speech[]) +{ + const enum gsm0808_permitted_speech *pos; + const uint8_t *pos2 = ct->perm_spch; + for (pos = perm_speech; *pos != LIST_END; pos++, pos2++) { + if (pos2 - ct->perm_spch >= ct->perm_spch_len) { + BTW("%s: %s: ERROR: mismatch: expected %s to be listed, but not found", func, desc, + gsm0808_permitted_speech_name(*pos)); + return false; + } + if (*pos2 != *pos) { + BTW("%s: %s: ERROR: mismatch: in idx %d, expect %s", func, desc, + (int)(pos - perm_speech), gsm0808_permitted_speech_name(*pos)); + btw("in idx %d, got %s", (int)(pos - perm_speech), gsm0808_permitted_speech_name(*pos2)); + return false; + } + } + if (pos2 - ct->perm_spch < ct->perm_spch_len) { + BTW("%s: %s: ERROR: did not expect %s", func, desc, gsm0808_permitted_speech_name(*pos2)); + return false; + } + return true; +} + +#define VALIDATE_PERM_SPEECH(GOT_PERM_SPEECH, EXPECT_PERM_SPEECH) do { \ + if (validate_perm_speech(__func__, t->desc, GOT_PERM_SPEECH, EXPECT_PERM_SPEECH)) { \ + btw("VALIDATE_PERM_SPEECH OK: " #GOT_PERM_SPEECH " == " #EXPECT_PERM_SPEECH " ==%s", \ + perm_speech_name(EXPECT_PERM_SPEECH)); \ + } else { \ + btw("Failed to validate Permitted Speech:\nexpected%s", \ + perm_speech_name(EXPECT_PERM_SPEECH)); \ + btw("got:"); \ + int i; \ + for (i = 0; i < (GOT_PERM_SPEECH)->perm_spch_len; i++) { \ + btw("%s", gsm0808_permitted_speech_name((GOT_PERM_SPEECH)->perm_spch[i])); \ + } \ + OSMO_ASSERT(false); \ + } \ + } while (0) + +/* Compose a valid SDP string from the list of codec subtype names given. If a subtype name includes a payload type + * number ("AMR#96") then use that PT number in the SDP instead of the default from codec_mapping.c. */ +static struct sdp_msg *sdp_from_subtype_names(const char *const *subtype_names) +{ + static struct sdp_msg sdp; + sdp = (struct sdp_msg){}; + const char *const *subtype_name; + osmo_sockaddr_str_from_str(&sdp.rtp, "1.2.3.4", 56); + for (subtype_name = subtype_names; *subtype_name; subtype_name++) { + char subtype_name_wo_pt[16]; + const struct codec_mapping *m; + struct sdp_audio_codec *ac; + int set_pt = -1; + split_subtype_name_and_pt_nr(subtype_name_wo_pt, &set_pt, *subtype_name); + m = codec_mapping_by_subtype_name(subtype_name_wo_pt); + if (!m) { + BTW("ERROR: unknown subtype_name: %s", *subtype_name); + abort(); + } + ac = sdp_audio_codecs_add_copy(&sdp.audio_codecs, &m->sdp); + if (set_pt >= 0) + ac->payload_type = set_pt; + } + return &sdp; +} + +static int sdp_str_from_subtype_names(char *buf, size_t buflen, const char *const *subtype_names) +{ + if (!subtype_names[0]) { + buf[0] = '\0'; + return 0; + } + return sdp_msg_to_sdp_str_buf(buf, buflen, sdp_from_subtype_names(subtype_names)); +} + +static const char *bcap_hexstr(const enum gsm48_bcap_speech_ver ms_bcap[]) +{ + struct gsm_mncc_bearer_cap bcap = { + .transfer = GSM_MNCC_BCAP_SPEECH, + .speech_ver = { -1 }, + }; + const enum gsm48_bcap_speech_ver *pos; + for (pos = ms_bcap; *pos != LIST_END; pos++) + bearer_cap_add_speech_ver(&bcap, *pos); + bearer_cap_set_radio(&bcap); + struct msgb *msg = msgb_alloc(128, "bcap"); + gsm48_encode_bearer_cap(msg, 0, &bcap); + char *ret = osmo_hexdump_nospc(msg->data, msg->len); + msgb_free(msg); + return ret; +} + +static void test_codecs_mo(const struct codec_test *t) +{ + struct gsm_mncc mncc = { + .imsi = IMSI, + }; + + struct gsm_mncc_rtp mncc_rtp = {}; + + BTW("======================== MO call: %s", t->desc); + btw("CM Service Request with Codec List (BSS Supported) =%s", + codec_list_name(t->mo_rx_compl_l3_codec_list_bss_supported)); + + cm_service_result_sent = RES_NONE; + ms_sends_compl_l3("052471" + "03575886" /* classmark 2 */ + "089910070000106005" /* IMSI */, + codec_list(t->mo_rx_compl_l3_codec_list_bss_supported)); + VERBOSE_ASSERT(cm_service_result_sent, == RES_ACCEPT, "%d"); + EXPECT_ACCEPTED(true); + + btw("MS sends CC SETUP with Bearer Capability = %s", + bcap_name(t->mo_rx_ms_bcap)); + expect_crcx(RTP_TO_CN); + expect_crcx(RTP_TO_RAN); + ms_sends_msgf("0385" /* CC, seq = 2 -> 0x80 | CC Setup = 0x5 */ + "%s" /* Bearer Capability */ + "5e038121f3" /* Called Number BCD */ + "15020100" /* CC Capabilities */ + "4008" /* Supported Codec List */ + "04026000" /* UMTS: AMR 2 | AMR */ + "00021f00" /* GSM: HR AMR | FR AMR | GSM EFR | GSM HR | GSM FR */, + bcap_hexstr(t->mo_rx_ms_bcap) + ); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); + + btw("As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered"); + cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_IND); + crcx_ok(RTP_TO_CN); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + mncc.callref = mncc_rtp.callref = cc_to_mncc_tx_got_callref; + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_setup_ind); + + btw("MNCC replies with MNCC_RTP_CREATE"); + sdp_str_from_subtype_names(mncc_rtp.sdp, sizeof(mncc_rtp.sdp), t->mo_rx_sdp_mncc_rtp_create); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); + + btw("MGW acknowledges the CRCX, triggering Assignment with%s", perm_speech_name(t->mo_tx_assignment_perm_speech)); + expect_bssap_assignment(); + crcx_ok(RTP_TO_RAN); + OSMO_ASSERT(bssap_assignment_sent); + VALIDATE_PERM_SPEECH(&bssap_assignment_command_last_channel_type, t->mo_tx_assignment_perm_speech); + + btw("Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC"); + cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); + ms_sends_assignment_complete(t->mo_rx_assigned_codec); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_rtp_create); + + btw("MNCC says that's fine"); + dtap_expect_tx("8302" /* CC: Call Proceeding */); + mncc_sends_to_cc(MNCC_CALL_PROC_REQ, &mncc); + OSMO_ASSERT(dtap_tx_confirmed); + + fake_time_passes(1, 23); + + btw("The other call leg got established (not shown here), MNCC tells us so, with codecs {%s }", + strlist_name(t->mo_rx_sdp_mncc_alert_req)); + dtap_expect_tx("8301" /* CC: Call Alerting */); + + if (t->mo_expect_reassignment) { + btw("Expecting re-assignment"); + expect_bssap_assignment(); + } + + sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mo_rx_sdp_mncc_alert_req); + mncc_sends_to_cc(MNCC_ALERT_REQ, &mncc); + OSMO_ASSERT(dtap_tx_confirmed); + + if (t->mo_expect_reassignment) { + btw("Validating re-assignment"); + OSMO_ASSERT(bssap_assignment_sent); + VALIDATE_PERM_SPEECH(&bssap_assignment_command_last_channel_type, t->mo_tx_reassignment_perm_speech); + ms_sends_assignment_complete(t->mo_rx_reassigned_codec); + } + + dtap_expect_tx("8307" /* CC: Connect */); + sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mo_rx_sdp_mncc_setup_rsp); + mncc_sends_to_cc(MNCC_SETUP_RSP, &mncc); + OSMO_ASSERT(dtap_tx_confirmed); + + fake_time_passes(1, 23); + + cc_to_mncc_expect_tx("", MNCC_SETUP_COMPL_IND); + ms_sends_msg("03cf" /* CC: Connect Acknowledge */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mo_tx_sdp_mncc_setup_compl_ind); + + BTW("RTP stream goes ahead, not shown here."); + fake_time_passes(123, 45); + + BTW("Call ends"); + cc_to_mncc_expect_tx("", MNCC_DISC_IND); + ms_sends_msg("032502e090" /* CC: Disconnect, cause: Normal Call Clearing */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + + dtap_expect_tx("832d" /* CC: Release */); + mncc_sends_to_cc(MNCC_REL_REQ, &mncc); + OSMO_ASSERT(dtap_tx_confirmed); + + cc_to_mncc_expect_tx("", MNCC_REL_CNF); + expect_bssap_clear(); + ms_sends_msg("036a" /* CC: Release Complete */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + OSMO_ASSERT(bssap_clear_sent); + + ran_sends_clear_complete(); + EXPECT_CONN_COUNT(0); + BTW("======================== SUCCESS: MO call: %s", t->desc); +} + +static void test_codecs_mt(const struct codec_test *t) +{ + struct gsm_mncc mncc = { + .imsi = IMSI, + .callref = 0x423, + .fields = MNCC_F_BEARER_CAP, + .bearer_cap = { + .speech_ver = { GSM48_BCAP_SV_FR, -1, }, + }, + }; + struct gsm_mncc_rtp mncc_rtp = { + .callref = 0x423, + }; + + BTW("======================== MT call: %s", t->desc); + + BTW("MNCC asks us to setup a call, causing Paging"); + + paging_expect_imsi(IMSI); + paging_sent = false; + sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mt_rx_sdp_mncc_setup_req); + mncc_sends_to_cc(MNCC_SETUP_REQ, &mncc); + mncc.sdp[0] = '\0'; + + VERBOSE_ASSERT(paging_sent, == true, "%d"); + + btw("MS replies with Paging Response, with Codec List (BSS Supported) =%s", + codec_list_name(t->mt_rx_compl_l3_codec_list_bss_supported)); + + if (t->expect_codec_mismatch_on_paging_response) { + btw("VLR accepts, but MSC notices a codec mismatch and aborts"); + cc_to_mncc_expect_tx("", MNCC_REL_IND); + expect_bssap_clear(); + ms_sends_compl_l3("062707" + "03575886" /* classmark 2 */ + "089910070000106005" /* IMSI */, + codec_list(t->mt_rx_compl_l3_codec_list_bss_supported)); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + OSMO_ASSERT(bssap_clear_sent); + + ran_sends_clear_complete(); + EXPECT_CONN_COUNT(0); + + BTW("======================== SUCCESS: MT call: %s", t->desc); + return; + } + + btw("VLR accepts, MSC sends CC Setup with Bearer Capability = %s", + bcap_name(t->mt_tx_cc_setup_bcap)); + char *cc_setup_bcap = talloc_asprintf(msc_vlr_tests_ctx, "0305%s", + bcap_hexstr(t->mt_tx_cc_setup_bcap)); + dtap_expect_tx(cc_setup_bcap); + ms_sends_compl_l3("062707" + "03575886" /* classmark 2 */ + "089910070000106005" /* IMSI */, + codec_list(t->mt_rx_compl_l3_codec_list_bss_supported)); + OSMO_ASSERT(dtap_tx_confirmed); + talloc_free(cc_setup_bcap); + + btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND"); + expect_crcx(RTP_TO_CN); + expect_crcx(RTP_TO_RAN); + cc_to_mncc_expect_tx(IMSI, MNCC_CALL_CONF_IND); + ms_sends_msgf("8348" /* CC: Call Confirmed */ + "%s" /* Bearer Capability */ + "15020100" /* Call Control Capabilities */ + "40080402600400021f00" /* Supported Codec List */, + bcap_hexstr(t->mt_rx_ms_bcap) + ); + OSMO_ASSERT(crcx_scheduled(RTP_TO_CN)); + OSMO_ASSERT(crcx_scheduled(RTP_TO_RAN)); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_call_conf_ind); + + btw("MGW acknowledges the CRCX to RAN, triggering Assignment with%s", perm_speech_name(t->mt_tx_assignment_perm_speech)); + + if (t->expect_codec_mismatch_on_cc_call_conf) { + btw("MS Bearer Capability leads to a codec mismatch, Assignment aborts"); + + dtap_expect_tx("032d0802e1af" /* CC Release */); + cc_to_mncc_expect_tx("", MNCC_REL_IND); + expect_bssap_clear(); + crcx_ok(RTP_TO_RAN); + + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + OSMO_ASSERT(bssap_clear_sent); + + ran_sends_clear_complete(); + EXPECT_CONN_COUNT(0); + BTW("======================== SUCCESS: MT call: %s", t->desc); + return; + } + + expect_bssap_assignment(); + crcx_ok(RTP_TO_RAN); + OSMO_ASSERT(bssap_assignment_sent); + VALIDATE_PERM_SPEECH(&bssap_assignment_command_last_channel_type, t->mt_tx_assignment_perm_speech); + + btw("Assignment completes, triggering CRCX to CN"); + ms_sends_assignment_complete(t->mt_rx_assigned_codec); + + btw("MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP"); + sdp_str_from_subtype_names(mncc_rtp.sdp, sizeof(mncc_rtp.sdp), t->mt_rx_sdp_mncc_rtp_create); + mncc_sends_to_cc(MNCC_RTP_CREATE, &mncc_rtp); + + btw("When the CN side RTP address is known, ack MNCC_RTP_CREATE"); + cc_to_mncc_expect_tx("", MNCC_RTP_CREATE); + crcx_ok(RTP_TO_CN); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_rtp_create); + + fake_time_passes(1, 23); + + cc_to_mncc_expect_tx("", MNCC_ALERT_IND); + ms_sends_msg("8381" /* CC: Alerting */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_alert_ind); + + fake_time_passes(1, 23); + + cc_to_mncc_expect_tx(IMSI, MNCC_SETUP_CNF); + ms_sends_msg("83c7" /* CC: Connect */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + VALIDATE_SDP(cc_to_mncc_tx_last_sdp, t->mt_tx_sdp_mncc_setup_cnf); + + dtap_expect_tx("030f" /* CC: Connect Acknowledge */); + sdp_str_from_subtype_names(mncc.sdp, sizeof(mncc.sdp), t->mt_rx_sdp_mncc_setup_compl_req); + mncc_sends_to_cc(MNCC_SETUP_COMPL_REQ, &mncc); + + BTW("RTP stream goes ahead, not shown here."); + fake_time_passes(123, 45); + + BTW("Call ends"); + cc_to_mncc_expect_tx("", MNCC_DISC_IND); + ms_sends_msg("832502e090" /* CC: Disconnect, cause: Normal Call Clearing */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + + dtap_expect_tx("032d" /* CC: Release */); + mncc_sends_to_cc(MNCC_REL_REQ, &mncc); + OSMO_ASSERT(dtap_tx_confirmed); + + cc_to_mncc_expect_tx("", MNCC_REL_CNF); + expect_bssap_clear(); + ms_sends_msg("836a" /* CC: Release Complete */); + OSMO_ASSERT(cc_to_mncc_tx_confirmed); + OSMO_ASSERT(bssap_clear_sent); + + ran_sends_clear_complete(); + EXPECT_CONN_COUNT(0); + BTW("======================== SUCCESS: MT call: %s", t->desc); +} + +static void test_codecs(void) +{ + const struct codec_test *t; + clear_vlr(); + + comment_start(); + + fake_time_start(); + + lu_geran_noauth(); + + for (t = codec_tests; t - codec_tests < ARRAY_SIZE(codec_tests); t++) { + test_codecs_mo(t); + test_codecs_mt(t); + } + + EXPECT_CONN_COUNT(0); + clear_vlr(); + comment_end(); +} msc_vlr_test_func_t msc_vlr_tests[] = { test_call_mo, @@ -675,5 +1642,6 @@ msc_vlr_test_func_t msc_vlr_tests[] = { test_call_mt2, test_call_mo_to_unknown, test_call_mo_to_unknown_timeout, + test_codecs, NULL }; diff --git a/tests/msc_vlr/msc_vlr_test_call.err b/tests/msc_vlr/msc_vlr_test_call.err index ad2f8c7ad..6fae30e73 100644 --- a/tests/msc_vlr/msc_vlr_test_call.err +++ b/tests/msc_vlr/msc_vlr_test_call.err @@ -67,7 +67,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -275,7 +275,7 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE - a call is initiated -- SETUP gets forwarded to MNCC +- CC SETUP causes CRCX towards CN and RAN MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_SETUP DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP @@ -288,51 +288,78 @@ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx SETUP in state NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) SETUP to 123 DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state NULL -> INITIATED -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) SETUP to 123 -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_SETUP_IND - MSC --> MNCC: callref 0x80000001: MNCC_SETUP_IND -DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) -- MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN - MSC <-- MNCC: callref 0x80000001: MNCC_RTP_CREATE - -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_RTP_CREATE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Allocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) - MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000001 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x1 codecs=AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x1 codecs=VND.3GPP.IUFP/16000#96 DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to VND.3GPP.IUFP/16000#96 +DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112}) + MSC --> MNCC: callref 0x80000001: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000001: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_RTP_CREATE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier - MGW acknowledges the CRCX, triggering Assignment MGW --CRCX OK to RTP_TO_RAN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) Sending Assignment Command DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST -- Assignment succeeds, triggering CRCX to CN +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to :0 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Not committing: no MGW endpoint CI set up - MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000001 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -- CN RTP address is available, trigger MNCC_RTP_CREATE - MGW --CRCX OK to RTP_TO_CN--> MSC -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE -DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE -DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_RTP_CREATE +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) Assignment Complete: RAN: VND.3GPP.IUFP/16000#96, CN: AMR:octet-align=1#112 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x80000001: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ - MNCC says that's fine MSC <-- MNCC: callref 0x80000001: MNCC_CALL_PROC_REQ DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_CALL_PROC_REQ DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) stopping pending guard timer DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting guard timer with 180 seconds -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_CALL_PROC_REQ in state INITIATED DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state INITIATED -> MO_CALL_PROC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -347,7 +374,6 @@ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVIC DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_ALERT_REQ DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) stopping pending guard timer DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting guard timer with 180 seconds -DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_ALERT_REQ in state MO_CALL_PROC DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -359,7 +385,6 @@ DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_S DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_SETUP_RSP DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) stopping pending guard timer DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting guard timer with 180 seconds -DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_SETUP_RSP in state CALL_DELIVERED DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting timer T313 with 30 seconds DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state CALL_DELIVERED -> CONNECT_IND DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT @@ -378,6 +403,7 @@ DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) stopping pending guard timer DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_SETUP_COMPL_IND MSC --> MNCC: callref 0x80000001: MNCC_SETUP_COMPL_IND + DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) @@ -394,12 +420,12 @@ DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:C DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state ACTIVE -> DISCONNECT_IND DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_DISC_IND MSC --> MNCC: callref 0x80000001: MNCC_DISC_IND + DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) MSC <-- MNCC: callref 0x80000001: MNCC_REL_REQ DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_REL_REQ DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting guard timer with 180 seconds -DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) rx MNCC_REL_REQ in state DISCONNECT_IND DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) starting timer T308 with 10 seconds DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) new state DISCONNECT_IND -> RELEASE_REQ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE @@ -415,6 +441,7 @@ DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) stopping pending timer T308 DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000001 tid-8) tx MNCC_REL_CNF MSC --> MNCC: callref 0x80000001: MNCC_REL_CNF + DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer @@ -428,16 +455,16 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + msc_a_fsm_re DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-1:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_CN:no-CI){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483649:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated, including all deferred deallocations +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST @@ -539,7 +566,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -667,11 +694,21 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - lu_utran_tms - after a while, MNCC asks us to setup a call, causing Paging MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) New transaction -DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) rx MNCC_SETUP_REQ +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=10.23.23.1:23{AMR:octet-align=1#112}) DPAG Paging: IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 for MNCC: establish call: Starting paging paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 on UTRAN-Iu strcmp(paging_expecting_imsi, vsub->imsi) == 0 @@ -759,10 +796,11 @@ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RES DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu -- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 0305 +- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 030504046004058b - DTAP matches expected message DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - Paging: now used by 3 (attached,CC,active-conn) @@ -775,44 +813,62 @@ DRLL msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RES DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds -DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Allocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) - MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x2 codecs=AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x2 codecs=VND.3GPP.IUFP/16000#96 DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to VND.3GPP.IUFP/16000#96 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND -DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) -- MNCC sends MNCC_RTP_CREATE - MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE -DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE -DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) - MGW acknowledges the CRCX to RAN, triggering Assignment MGW --CRCX OK to RTP_TO_RAN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST - Assignment completes, triggering CRCX to CN DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to :0 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Not committing: no MGW endpoint CI set up - MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -- When the CN side RTP address is known, send MNCC_RTP_CREATE +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: VND.3GPP.IUFP/16000#96, CN: AMR:octet-align=1#112 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE with full SDP MGW --CRCX OK to RTP_TO_CN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) -DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ - Total time passed: 1.000023 s MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_ALERTING DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) @@ -822,8 +878,19 @@ DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED -DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) - Total time passed: 2.000046 s MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_CONNECT @@ -833,14 +900,24 @@ DRLL msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RES DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST -DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds -DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ in state CONNECT_REQUEST DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK @@ -863,12 +940,12 @@ DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:P DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND MSC --> MNCC: callref 0x423: MNCC_DISC_IND + DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) MSC <-- MNCC: callref 0x423: MNCC_REL_REQ DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds -DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ in state DISCONNECT_IND DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE @@ -884,6 +961,7 @@ DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF MSC --> MNCC: callref 0x423: MNCC_REL_CNF + DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x0 tid-0) Freeing transaction DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer @@ -897,16 +975,16 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + msc_a_fsm_re DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-2:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Deallocated, including all deferred deallocations +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Deallocated DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST @@ -1008,7 +1086,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -1136,11 +1214,21 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - lu_utran_tms - after a while, MNCC asks us to setup a call, causing Paging MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) New transaction -DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) rx MNCC_SETUP_REQ +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=10.23.23.1:23{AMR:octet-align=1#112}) DPAG Paging: IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 for MNCC: establish call: Starting paging paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 on UTRAN-Iu strcmp(paging_expecting_imsi, vsub->imsi) == 0 @@ -1228,10 +1316,11 @@ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RES DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu -- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 0305 +- DTAP --UTRAN-Iu--> MS: GSM48_MT_CC_SETUP: 030504046004058b - DTAP matches expected message DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - Paging: now used by 3 (attached,CC,active-conn) @@ -1244,44 +1333,71 @@ DRLL msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RES DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds -DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Allocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) - MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x423 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x3 codecs=AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x3 codecs=VND.3GPP.IUFP/16000#96 DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to VND.3GPP.IUFP/16000#96 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) -- MNCC sends MNCC_RTP_CREATE +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
-DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier - MGW acknowledges the CRCX to RAN, triggering Assignment MGW --CRCX OK to RTP_TO_RAN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST - Assignment completes, triggering CRCX to CN DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to :0 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Not committing: no MGW endpoint CI set up - MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x423 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: Allocated -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -- When the CN side RTP address is known, send MNCC_RTP_CREATE +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: VND.3GPP.IUFP/16000#96, CN: AMR:octet-align=1#112 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- When the CN side RTP address is known, ack MNCC_RTP_CREATE with full SDP MGW --CRCX OK to RTP_TO_CN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) -DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ - Total time passed: 1.000023 s MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_ALERTING DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) @@ -1291,8 +1407,19 @@ DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED -DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 remote=10.23.23.1:23{AMR:octet-align=1#112} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) - Total time passed: 16.000046 s - The call failed, the BSC sends a BSSMAP Clear Request @@ -1306,6 +1433,7 @@ DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTR DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_IND MSC --> MNCC: callref 0x423: MNCC_REL_IND + DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> RELEASE_REQ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: Sending DTAP: CC GSM48_MT_CC_RELEASE @@ -1319,16 +1447,16 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - CC: now used DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: - cc: now used by 0 (-) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-3:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_CN:no-CI){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP:trans-0:call-1059:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Deallocated, including all deferred deallocations +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){RELEASING}: Deallocated DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST @@ -1431,7 +1559,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -1639,7 +1767,7 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE - a call is initiated -- SETUP gets forwarded to MNCC +- CC SETUP causes CRCX towards CN and RAN MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_SETUP DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP @@ -1652,51 +1780,78 @@ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx SETUP in state NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) SETUP to 123 DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) new state NULL -> INITIATED -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) SETUP to 123 -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) tx MNCC_SETUP_IND - MSC --> MNCC: callref 0x80000002: MNCC_SETUP_IND -DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) -- MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN - MSC <-- MNCC: callref 0x80000002: MNCC_RTP_CREATE - -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_RTP_CREATE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Allocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) - MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000002 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x4 codecs=AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x4 codecs=VND.3GPP.IUFP/16000#96 DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to VND.3GPP.IUFP/16000#96 +DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112}) + MSC --> MNCC: callref 0x80000002: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000002: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_RTP_CREATE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier - MGW acknowledges the CRCX, triggering Assignment MGW --CRCX OK to RTP_TO_RAN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) Sending Assignment Command DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST -- Assignment succeeds, triggering CRCX to CN +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to :0 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Not committing: no MGW endpoint CI set up - MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000002 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -- CN RTP address is available, trigger MNCC_RTP_CREATE - MGW --CRCX OK to RTP_TO_CN--> MSC -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE -DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE -DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) tx MNCC_RTP_CREATE +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) Assignment Complete: RAN: VND.3GPP.IUFP/16000#96, CN: AMR:octet-align=1#112 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x80000002: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ - MNCC says that's fine MSC <-- MNCC: callref 0x80000002: MNCC_CALL_PROC_REQ DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_CALL_PROC_REQ DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) stopping pending guard timer DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) starting guard timer with 180 seconds -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_CALL_PROC_REQ in state INITIATED DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) new state INITIATED -> MO_CALL_PROC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -1710,7 +1865,6 @@ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVIC DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_REL_REQ DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) stopping pending guard timer DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) starting guard timer with 180 seconds -DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) rx MNCC_REL_REQ in state MO_CALL_PROC DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) starting timer T308 with 10 seconds DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) new state MO_CALL_PROC -> RELEASE_REQ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE @@ -1719,6 +1873,7 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE - DTAP matches expected message DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST - Total time passed: 10.000023 s +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) Timeout of T308 DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) starting timer T308 with 10 seconds DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -1733,6 +1888,7 @@ DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) stopping pending timer T308 DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000002 tid-8) tx MNCC_REL_CNF MSC --> MNCC: callref 0x80000002: MNCC_REL_CNF + DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer @@ -1746,16 +1902,16 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + msc_a_fsm_re DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-4:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_CN:no-CI){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483650:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated, including all deferred deallocations +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST @@ -1857,7 +2013,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -2065,7 +2221,7 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE - a call is initiated -- SETUP gets forwarded to MNCC +- CC SETUP causes CRCX towards CN and RAN MSC <--UTRAN-Iu-- MS: GSM48_MT_CC_SETUP DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP @@ -2078,51 +2234,78 @@ DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx SETUP in state NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) SETUP to 123 DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) new state NULL -> INITIATED -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) SETUP to 123 -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) tx MNCC_SETUP_IND - MSC --> MNCC: callref 0x80000003: MNCC_SETUP_IND -DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) -- MNCC replies with MNCC_RTP_CREATE, causing MGW endpoint CRCX to RAN - MSC <-- MNCC: callref 0x80000003: MNCC_RTP_CREATE - -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_RTP_CREATE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Allocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) - MGW <--CRCX to RTP_TO_RAN-- MSC: callref=0x80000003 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) codecs: :0{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x5 codecs=AMR:octet-align=1#112 DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x5 codecs=VND.3GPP.IUFP/16000#96 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to VND.3GPP.IUFP/16000#96 +DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112}) + MSC --> MNCC: callref 0x80000003: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000003: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_RTP_CREATE +DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier - MGW acknowledges the CRCX, triggering Assignment MGW --CRCX OK to RTP_TO_RAN--> MSC DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) Sending Assignment Command DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST -- Assignment succeeds, triggering CRCX to CN +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to :0 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Not committing: no MGW endpoint CI set up - MGW <--CRCX to RTP_TO_CN-- MSC: callref=0x80000003 -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: Allocated -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codec to AMR/8000/1 -- CN RTP address is available, trigger MNCC_RTP_CREATE - MGW --CRCX OK to RTP_TO_CN--> MSC -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE -DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE -DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) -DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) tx MNCC_RTP_CREATE +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) Assignment Complete: RAN: VND.3GPP.IUFP/16000#96, CN: AMR:octet-align=1#112 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={AMR:octet-align=1#112,AMR-WB/16000:octet-align=1#113}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112}) MSC --> MNCC: callref 0x80000003: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=ptime:20
+ - MNCC says that's fine MSC <-- MNCC: callref 0x80000003: MNCC_CALL_PROC_REQ DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_CALL_PROC_REQ DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) stopping pending guard timer DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) starting guard timer with 180 seconds -DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_CALL_PROC_REQ in state INITIATED DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) new state INITIATED -> MO_CALL_PROC DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -2136,7 +2319,6 @@ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVIC DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_REL_REQ DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) stopping pending guard timer DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) starting guard timer with 180 seconds -DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) rx MNCC_REL_REQ in state MO_CALL_PROC DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) starting timer T308 with 10 seconds DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) new state MO_CALL_PROC -> RELEASE_REQ DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE @@ -2146,6 +2328,7 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST - Despite our repeated CC Release Requests, the MS does not respond anymore - Total time passed: 10.000023 s +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) Timeout of T308 DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) starting timer T308 with 10 seconds DIUCS msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on UTRAN-Iu @@ -2154,9 +2337,11 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST - The CC Release times out and we still properly clear the conn - Total time passed: 20.000046 s +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) Timeout of T308 DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) Freeing transaction DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) tx MNCC_REL_CNF MSC --> MNCC: callref 0x80000003: MNCC_REL_CNF + DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) new state RELEASE_REQ -> NULL DCC trans(CC:NULL IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ callref-0x80000003 tid-8) stopping pending guard timer DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - CC: now used by 2 (attached,active-conn) @@ -2168,16 +2353,16 @@ DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + msc_a_fsm_re DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) DREF VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-5:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_CN:no-CI){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ)) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) -DCC rtp_stream(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ:trans-8:call-2147483651:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: Deferring: will deallocate with call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM -DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated, including all deferred deallocations +DCC call_leg(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){RELEASING}: Deallocated DREF msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on UTRAN-Iu DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST @@ -2210,3 +2395,4513 @@ DMSC msc_a(IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100:UTRAN-Iu:CM_SERVICE DVLR freeing VLR subscr IMSI-901700000010650:MSISDN-42342:TMSI-0x03020100 (max total use count was 4) ===== test_call_mo_to_unknown_timeout: SUCCESS +===== test_codecs +- Total time passed: 0.000000 s +- Location Update request causes a GSUP LU request to HLR + MSC <--GERAN-A-- MS: GSM48_MT_MM_LOC_UPD_REQUEST + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_LOC_UPD_REQUEST +DMM msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: LOCATION UPDATING REQUEST: MI=IMSI-901700000010650 LU-type=NORMAL +DMM msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: USIM: old LAI: 901-70-23 +DREF msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: + mm_rx_loc_upd_req: now used by 2 (rx_from_ms,mm_rx_loc_upd_req) +DREF msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: + lu: now used by 3 (rx_from_ms,mm_rx_loc_upd_req,lu) +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: Allocated +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: is child of msc_a(IMSI-901700000010650:GERAN-A:LU) +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: rev=R99 net=GERAN (no Auth) +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: Received Event VLR_ULA_E_UPDATE_LA +DREF VLR subscr unknown + _lu_fsm_associate_vsub: now used by 1 (_lu_fsm_associate_vsub) +DVLR set IMSI on subscriber; IMSI=901700000010650 id=901700000010650 +DVLR New subscr, IMSI: 901700000010650 +DREF VLR subscr IMSI-901700000010650 + active-conn: now used by 2 (_lu_fsm_associate_vsub,active-conn) +DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DREF VLR subscr IMSI-901700000010650 - _lu_fsm_associate_vsub: now used by 1 (active-conn) +DVLR set Last E-UTRAN PLMN ID on subscriber: (none) +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: vlr_loc_upd_node1_pre() +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: vlr_loc_upd_node1() +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: vlr_loc_upd_post_auth() +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: vlr_loc_upd_post_ciph() +DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:GERAN-A:LU){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: vlr_loc_upd_node_4() +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_IDLE}: state_chg to VLR_ULA_S_WAIT_HLR_UPD +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_INIT}: Allocated +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_INIT}: is child of vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_INIT}: Received Event UPD_HLR_VLR_E_START +GSUP --> HLR: OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: 04010809710000000156f02801020a0101 +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_INIT}: state_chg to UPD_HLR_VLR_S_WAIT_FOR_DATA +DREF msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - mm_rx_loc_upd_req: now used by 2 (rx_from_ms,lu) +DREF msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - rx_from_ms: now used by 1 (lu) + lu_result_sent == 0 +- HLR sends _INSERT_DATA_REQUEST, VLR responds with _INSERT_DATA_RESULT +<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: 10010809710000000156f00804036470f10a0101 +DREF VLR subscr IMSI-901700000010650 + vlr_gsup_rx: now used by 2 (active-conn,vlr_gsup_rx) +DVLR IMSI:901700000010650 has MSISDN:46071 +DVLR SUBSCR(IMSI-901700000010650:MSISDN-46071) VLR: update for IMSI=901700000010650 (MSISDN=46071) +GSUP --> HLR: OSMO_GSUP_MSGT_INSERT_DATA_RESULT: 12010809710000000156f00a0101 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_gsup_rx: now used by 1 (active-conn) +<-- GSUP rx OSMO_GSUP_MSGT_INSERT_DATA_REQUEST: vlr_gsupc_read_cb() returns 0 + lu_result_sent == 0 +- HLR also sends GSUP _UPDATE_LOCATION_RESULT +<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: 06010809710000000156f00a0101 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_gsup_rx: now used by 2 (active-conn,vlr_gsup_rx) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_HLR_LU_RES +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_WAIT_FOR_DATA}: Received Event UPD_HLR_VLR_E_UPD_LOC_ACK +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_WAIT_FOR_DATA}: state_chg to UPD_HLR_VLR_S_DONE +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_DONE}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_DONE}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_HLR_UPD}: Received Event VLR_ULA_E_UPD_HLR_COMPL +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_HLR_UPD}: state_chg to VLR_ULA_S_WAIT_LU_COMPL +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_INIT}: Allocated +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_INIT}: is child of vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_INIT}: Received Event LU_COMPL_VLR_E_START +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL +- sending LU Accept for IMSI-901700000010650:MSISDN-46071:GERAN-A:LU +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + attached: now used by 3 (active-conn,vlr_gsup_rx,attached) +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU)) +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_DONE}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DVLR lu_compl_vlr_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){LU_COMPL_VLR_S_DONE}: Deferring: will deallocate with upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_LU_COMPL}: state_chg to VLR_ULA_S_DONE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTHENTICATED}: - lu: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 5 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 3 (active-conn,vlr_gsup_rx,attached) +DVLR upd_hlr_vlr_fsm(IMSI-901700000010650:GERAN-A:LU){UPD_HLR_VLR_S_DONE}: Deallocated, including all deferred deallocations +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_gsup_rx: now used by 2 (active-conn,attached) +<-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0 +- LU was successful, and the conn has already been closed + lu_result_sent == 1 + bssap_clear_sent == 1 +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU)) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_DONE}: fsm_lu_cleanup called with cause OSMO_FSM_TERM_PARENT +DVLR vlr_lu_fsm(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:LU){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== MO call: AMR picked by both MO and MT +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000004 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x6 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x6 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000004: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == AMR GSM-EFR GSM GSM-HR-08 +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000004: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000004: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == AMR GSM-EFR GSM GSM-HR-08 +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000004: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 1.000023 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { AMR GSM-EFR GSM GSM-HR-08 } + MSC <-- MNCC: callref 0x80000004: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI){UNINITIALIZED}: no change: codecs already set to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <-- MNCC: callref 0x80000004: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 2.000046 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000004: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 125.000091 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000004: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000004: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000004 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000004: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-6:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: AMR picked by both MO and MT + + +- ======================== MT call: AMR picked by both MO and MT + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504076004050b020081 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x7 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x7 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == AMR GSM-EFR GSM GSM-HR-08 +- Total time passed: 126.000114 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == AMR GSM-EFR GSM GSM-HR-08 +- Total time passed: 127.000137 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == AMR GSM-EFR GSM GSM-HR-08 + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 250.000182 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-7:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: AMR picked by both MO and MT + + +- ======================== MO call: FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1 +- CM Service Request with Codec List (BSS Supported) = FR1 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000005 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: :0{GSM#3} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: :0{GSM#3} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x8 codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x8 codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x80000005: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == GSM +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000005: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x80000005: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == GSM +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000005: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 251.000205 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { GSM } + MSC <-- MNCC: callref 0x80000005: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <-- MNCC: callref 0x80000005: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 252.000228 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000005: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 375.000273 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000005: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000005: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000005 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000005: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-8:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1 + + +- ======================== MT call: FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1 + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{GSM#3} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{GSM#3}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = GSM + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504022080 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x9 codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x9 codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == GSM +- Total time passed: 376.000296 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == GSM +- Total time passed: 377.000319 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == GSM + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 500.000364 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-9:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: FR1 picked by MO from Codec List (BSS Supported), MT hence also picks FR1 + + +- ======================== MO call: FR1 picked by MO from Bearer Cap, MT hence also picks FR1 +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = GSM + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000006 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: :0{GSM#3} (from: MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: :0{GSM#3} (from: MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xa codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xa codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x80000006: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == GSM +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000006: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x80000006: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == GSM +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000006: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 501.000387 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { GSM } + MSC <-- MNCC: callref 0x80000006: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <-- MNCC: callref 0x80000006: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 502.000410 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000006: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 625.000455 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000006: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000006: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000006 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000006: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-10:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: FR1 picked by MO from Bearer Cap, MT hence also picks FR1 + + +- ======================== MT call: FR1 picked by MO from Bearer Cap, MT hence also picks FR1 + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{GSM#3} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{GSM#3}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = GSM + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504022080 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xb codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xb codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == GSM +- Total time passed: 626.000478 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == GSM +- Total time passed: 627.000501 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == GSM + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 750.000546 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-11:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: FR1 picked by MO from Bearer Cap, MT hence also picks FR1 + + +- ======================== MO call: FR1 picked by MT's Codec List (BSS Supported), hence MO re-assigns to FR1 +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000007 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xc codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xc codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000007: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == AMR GSM-EFR GSM GSM-HR-08 +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000007: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000007: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == AMR GSM-EFR GSM GSM-HR-08 +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000007: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 751.000569 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { GSM } +- Expecting re-assignment + MSC <-- MNCC: callref 0x80000007: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Remote call leg mismatches assigned codec: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Validating re-assignment +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_reassignment_perm_speech == FR1 +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: setting codecs to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: remote addr already 1.2.3.4:1234, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) Re-Assignment complete + MSC <-- MNCC: callref 0x80000007: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 752.000592 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000007: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 875.000637 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000007: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000007: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000007 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000007: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-12:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: FR1 picked by MT's Codec List (BSS Supported), hence MO re-assigns to FR1 + + +- ======================== MT call: FR1 picked by MT's Codec List (BSS Supported), hence MO re-assigns to FR1 + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 +- VLR accepts, MSC sends CC Setup with Bearer Capability = GSM + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504022080 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xd codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xd codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == GSM +- Total time passed: 876.000660 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == GSM +- Total time passed: 877.000683 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == GSM + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1000.000728 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-13:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: FR1 picked by MT's Codec List (BSS Supported), hence MO re-assigns to FR1 + + +- ======================== MO call: FR1 picked by MT's MS Bearer Capability, hence MO re-assigns to FR1 +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000008 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xe codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xe codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000008: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == AMR GSM-EFR GSM GSM-HR-08 +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000008: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000008: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == AMR GSM-EFR GSM GSM-HR-08 +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000008: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 1001.000751 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { GSM } +- Expecting re-assignment + MSC <-- MNCC: callref 0x80000008: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Remote call leg mismatches assigned codec: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Validating re-assignment +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_reassignment_perm_speech == FR1 +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: setting codecs to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: remote addr already 1.2.3.4:1234, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) Re-Assignment complete + MSC <-- MNCC: callref 0x80000008: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{GSM#3}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{GSM#3} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 1002.000774 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000008: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1125.000819 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000008: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000008: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000008 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000008: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-14:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: FR1 picked by MT's MS Bearer Capability, hence MO re-assigns to FR1 + + +- ======================== MT call: FR1 picked by MT's MS Bearer Capability, hence MO re-assigns to FR1 + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504076004050b020081 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0xf codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0xf codecs=GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to GSM#3 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI){UNINITIALIZED}: no change: codecs already set to GSM#3 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: GSM#3, CN: GSM#3 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == GSM +- Total time passed: 1126.000842 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == GSM +- Total time passed: 1127.000865 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{GSM#3} (from: assigned=GSM#3 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={GSM#3} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{GSM#3}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 3
+a=rtpmap:3 GSM/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == GSM + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1250.000910 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-15:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: FR1 picked by MT's MS Bearer Capability, hence MO re-assigns to FR1 + + +- ======================== MO call: AMR picked by both MO and MT, but MT assigns a different payload type number +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x80000009 tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x10 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x10 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000009: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == AMR GSM-EFR GSM GSM-HR-08 +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x80000009: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x80000009: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == AMR GSM-EFR GSM GSM-HR-08 +- MNCC says that's fine + MSC <-- MNCC: callref 0x80000009: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 1251.000933 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { AMR#96 GSM-EFR GSM GSM-HR-08 } + MSC <-- MNCC: callref 0x80000009: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 96 110 3 111
+a=rtpmap:96 AMR/8000
+a=fmtp:96 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <-- MNCC: callref 0x80000009: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 96 110 3 111
+a=rtpmap:96 AMR/8000
+a=fmtp:96 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to AMR:octet-align=1#96,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 1252.000956 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x80000009: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1375.001001 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x80000009: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x80000009: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 96 110 3 111
+a=rtpmap:96 AMR/8000
+a=fmtp:96 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x80000009 tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x80000009: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-16:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: AMR picked by both MO and MT, but MT assigns a different payload type number + + +- ======================== MT call: AMR picked by both MO and MT, but MT assigns a different payload type number + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504076004050b020081 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x11 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x11 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == AMR#96 GSM-EFR GSM GSM-HR-08 +- Total time passed: 1376.001024 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == AMR#96 GSM-EFR GSM GSM-HR-08 +- Total time passed: 1377.001047 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == AMR#96 GSM-EFR GSM GSM-HR-08 + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1500.001092 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-17:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: AMR picked by both MO and MT, but MT assigns a different payload type number + + +- ======================== MO call: AMR picked by both MO and MT, but MO assigns a different payload type number +- CM Service Request with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 + MSC <--GERAN-A-- MS: GSM48_MT_MM_CM_SERV_REQ + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ +DMM msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Rx CM SERVICE REQUEST cm_service_type=MO-Call +DREF msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: + cm_service_cc: now used by 2 (rx_from_ms,cm_service_cc) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 2 (attached,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 3 (attached,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: - rx_from_ms: now used by 1 (cm_service_cc) + cm_service_result_sent == 1 +msc_a_is_accepted() == true +- MS sends CC SETUP with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_CC_SETUP +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + rx_from_ms: now used by 2 (cm_service_cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: CC GSM48_MT_CC_SETUP +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,active-conn,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x8000000a tid-8) New transaction +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + cc: now used by 3 (cm_service_cc,rx_from_ms,cc) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cm_service_cc: now used by 2 (rx_from_ms,cc) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx SETUP in state NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting guard timer with 180 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) SETUP to 123 +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state NULL -> INITIATED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: :0{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x12 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x12 codecs=AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- As soon as the MGW port towards CN is created, MNCC_SETUP_IND is triggered + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) tx MNCC_SETUP_IND (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x8000000a: MNCC_SETUP_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_ind == AMR GSM-EFR GSM GSM-HR-08 +- MNCC replies with MNCC_RTP_CREATE + MSC <-- MNCC: callref 0x8000000a: MNCC_RTP_CREATE + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- MGW acknowledges the CRCX, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mo_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment succeeds, triggering MNCC_RTP_CREATE ack to MNCC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x8000000a: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 112 110 3 111
+a=rtpmap:112 AMR/8000
+a=fmtp:112 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_rtp_create == AMR#98 GSM-EFR GSM GSM-HR-08 +- MNCC says that's fine + MSC <-- MNCC: callref 0x8000000a: MNCC_CALL_PROC_REQ + +DMNCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx MNCC_CALL_PROC_REQ +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending guard timer +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting guard timer with 180 seconds +DCC trans(CC:INITIATED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state INITIATED -> MO_CALL_PROC +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CALL_PROC +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CALL_PROC: 8302 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- Total time passed: 1501.001115 s +- The other call leg got established (not shown here), MNCC tells us so, with codecs { AMR#98 GSM-EFR GSM GSM-HR-08 } + MSC <-- MNCC: callref 0x8000000a: MNCC_ALERT_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx MNCC_ALERT_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending guard timer +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting guard timer with 180 seconds +DCC trans(CC:MO_CALL_PROC IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state MO_CALL_PROC -> CALL_DELIVERED +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:56 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_ALERTING +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_ALERTING: 8301 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <-- MNCC: callref 0x8000000a: MNCC_SETUP_RSP +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx MNCC_SETUP_RSP (RTP=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending guard timer +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting guard timer with 180 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting timer T313 with 30 seconds +DCC trans(CC:CALL_DELIVERED IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state CALL_DELIVERED -> CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) codecs: 10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: no change: codecs already set to AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: remote addr already 1.2.3.4:56, no change +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT: 8307 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- Total time passed: 1502.001138 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT_ACK +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT_ACK +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx CONNECT_ACK in state CONNECT_IND +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending timer T313 +DCC trans(CC:CONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state CONNECT_IND -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending guard timer +DMNCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) tx MNCC_SETUP_COMPL_IND + MSC --> MNCC: callref 0x8000000a: MNCC_SETUP_COMPL_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mo_tx_sdp_mncc_setup_compl_ind == + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1625.001183 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x8000000a: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x8000000a: MNCC_REL_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 832d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x8000000a tid-8) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x8000000a: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ callref-0x0 tid-8) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ:trans-8:call-18:RTP_TO_CN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-56){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MO call: AMR picked by both MO and MT, but MO assigns a different payload type number + + +- ======================== MT call: AMR picked by both MO and MT, but MO assigns a different payload type number + + +- MNCC asks us to setup a call, causing Paging + MSC <-- MNCC: callref 0x423: MNCC_SETUP_REQ +v=0
+o=OsmoMSC 0 0 IN IP4 1.2.3.4
+s=GSM Call
+c=IN IP4 1.2.3.4
+t=0 0
+m=audio 56 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + mncc_tx_to_gsm_cc: now used by 2 (attached,mncc_tx_to_gsm_cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + CC: now used by 3 (attached,mncc_tx_to_gsm_cc,CC) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) New transaction +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) codecs: :0{(no-codecs)} (from: remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} RAN={(no-codecs)}) +DMNCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) rx MNCC_SETUP_REQ (RTP=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Starting paging + paging request (CALL_CONVERSATIONAL) to IMSI-901700000010650:MSISDN-46071 on GERAN-A + strcmp(paging_expecting_imsi, vsub->imsi) == 0 +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + Paging: now used by 4 (attached,mncc_tx_to_gsm_cc,CC,Paging) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - mncc_tx_to_gsm_cc: now used by 3 (attached,CC,Paging) + paging_sent == 1 +- MS replies with Paging Response, with Codec List (BSS Supported) = FR1 FR2 FR3 HR1 HR3 +- VLR accepts, MSC sends CC Setup with Bearer Capability = AMR AMR AMR GSM-EFR GSM GSM-HR-08 + MSC <--GERAN-A-- MS: GSM48_MT_RR_PAG_RESP + new conn +DMSC msub_fsm{active}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: Allocated +DMSC msc_a{MSC_A_ST_VALIDATE_L3}: is child of msub_fsm +DMSC msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_VALIDATE_L3 +DMSC dummy_msc_i{0}: Allocated +DMSC dummy_msc_i{0}: is child of msub_fsm +DREF msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: + rx_from_ms: now used by 1 (rx_from_ms) +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: RAN decode: COMPL_L3 +DBSSAP msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Complete Layer 3: Codec List (BSS Supported): GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111 +DRLL msc_a(unknown:GERAN-A:NONE){MSC_A_ST_VALIDATE_L3}: Dispatching 04.08 message: RR GSM48_MT_RR_PAG_RESP +DRR msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Rx PAGING RESPONSE IMSI-901700000010650 +DREF msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: + paging-response: now used by 2 (rx_from_ms,paging-response) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Allocated +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: is child of msc_a(IMSI-901700000010650:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: rev=R99 net=GERAN (no Auth) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: Received Event PR_ARQ_E_START +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + proc_arq_vlr_fn_init: now used by 4 (attached,CC,Paging,proc_arq_vlr_fn_init) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + active-conn: now used by 5 (attached,CC,Paging,proc_arq_vlr_fn_init,active-conn) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: Received Event MSC_A_EV_COMPLETE_LAYER_3_OK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_VALIDATE_L3}: state_chg to MSC_A_ST_AUTH_CIPH +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_vlr_fn_post_imsi() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_ciph() +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_node2_post_vlr() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_pres() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_trace() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: _proc_arq_vlr_post_imei() +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: proc_arq_fsm_done(PASSED) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_INIT}: state_chg to PR_ARQ_S_DONE +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Process Access Request result: PASSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_AUTHENTICATED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTH_CIPH}: state_chg to MSC_A_ST_AUTHENTICATED +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Paging Response action (success) +DPAG Paging: IMSI-901700000010650:MSISDN-46071 for MNCC: establish call: Removing Paging Request +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071 callref-0x423 tid-255) Paging succeeded +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: + cc: now used by 3 (rx_from_ms,paging-response,cc) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_TRANSACTION_ACCEPTED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_COMMUNICATING +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T303 with 30 seconds +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state NULL -> CALL_PRESENT +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_SETUP +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_SETUP: 030504076004050b020081 +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - Paging: now used by 4 (attached,CC,proc_arq_vlr_fn_init,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - paging-response: now used by 2 (rx_from_ms,cc) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - proc_arq_vlr_fn_init: now used by 3 (attached,CC,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND + MSC <--GERAN-A-- MS: GSM48_MT_CC_CALL_CONF +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CALL_CONF +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CALL_CONF in state CALL_PRESENT +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T303 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T310 with 30 seconds +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Starting call assignment +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Allocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: is child of msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MGW <--CRCX to RTP_TO_CN-- MSC: call_id=0x13 codecs=AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_CN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 + MGW <--CRCX to RTP_TO_RAN-- MSC: call_id=0x13 codecs=AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: Allocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){UNINITIALIZED}: is child of call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:CALL_PRESENT IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_PRESENT -> MO_TERM_CALL_CONF +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_CALL_CONF_IND + MSC --> MNCC: callref 0x423: MNCC_CALL_CONF_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_call_conf_ind == +- MGW acknowledges the CRCX to RAN, triggering Assignment with FR3 HR3 FR2 FR1 HR1 + MGW --CRCX OK to RTP_TO_RAN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_RAN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Sending Assignment Command +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: ASSIGNMENT_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +- VALIDATE_PERM_SPEECH OK: &bssap_assignment_command_last_channel_type == t->mt_tx_assignment_perm_speech == FR3 HR3 FR2 FR1 HR1 +- Assignment completes, triggering CRCX to CN +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: ASSIGNMENT_COMPLETE +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI){UNINITIALIZED}: setting codecs to AMR:octet-align=1#112 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI:local-10-23-23-1-23){UNINITIALIZED}: setting remote addr to 1.2.3.4:1234 +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Not committing: no MGW endpoint CI set up +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: :0{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment Complete: RAN: AMR:octet-align=1#112, CN: AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) Assignment complete, but still waiting for the CRCX OK on the CN side RTP +- MNCC sends MNCC_RTP_CREATE, which first waits for the CN side RTP + MSC <-- MNCC: callref 0x423: MNCC_RTP_CREATE + +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_RTP_CREATE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Assignment for this trans already started earlier +- When the CN side RTP address is known, ack MNCC_RTP_CREATE + MGW --CRCX OK to RTP_TO_CN--> MSC +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: Received Event CALL_LEG_EV_RTP_STREAM_ADDR_AVAILABLE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: MGW endpoint's RTP address available for the CI RTP_TO_CN: 10.23.23.1:23 (osmux=no:-2) +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_RTP_CREATE (RTP=10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_RTP_CREATE +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_rtp_create == AMR#98 GSM-EFR GSM GSM-HR-08 +- Total time passed: 1626.001206 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_ALERTING +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_ALERTING +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx ALERTING in state MO_TERM_CALL_CONF +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T310 +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T301 with 180 seconds +DCC trans(CC:MO_TERM_CALL_CONF IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state MO_TERM_CALL_CONF -> CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_ALERT_IND (RTP=10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_ALERT_IND +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_alert_ind == AMR#98 GSM-EFR GSM GSM-HR-08 +- Total time passed: 1627.001229 s + MSC <--GERAN-A-- MS: GSM48_MT_CC_CONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_CONNECT +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx CONNECT in state CALL_RECEIVED +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T301 +DCC trans(CC:CALL_RECEIVED IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CALL_RECEIVED -> CONNECT_REQUEST +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) codecs: 10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} (from: assigned=AMR:octet-align=1#112 remote=1.2.3.4:56{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111} MS={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111} bss={GSM#3,GSM-EFR#110,AMR:octet-align=1#112,GSM-HR-08#111} RAN={AMR:octet-align=1#112,GSM-EFR#110,GSM#3,GSM-HR-08#111}) +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_SETUP_CNF (RTP=10.23.23.1:23{AMR:octet-align=1#98,GSM-EFR#110,GSM#3,GSM-HR-08#111}) + MSC --> MNCC: callref 0x423: MNCC_SETUP_CNF +v=0
+o=OsmoMSC 0 0 IN IP4 10.23.23.1
+s=GSM Call
+c=IN IP4 10.23.23.1
+t=0 0
+m=audio 23 RTP/AVP 98 110 3 111
+a=rtpmap:98 AMR/8000
+a=fmtp:98 octet-align=1
+a=rtpmap:110 GSM-EFR/8000
+a=rtpmap:3 GSM/8000
+a=rtpmap:111 GSM-HR-08/8000
+a=ptime:20
+ +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) +- VALIDATE_SDP OK: cc_to_mncc_tx_last_sdp == t->mt_tx_sdp_mncc_setup_cnf == AMR#98 GSM-EFR GSM GSM-HR-08 + MSC <-- MNCC: callref 0x423: MNCC_SETUP_COMPL_REQ + +DMNCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_SETUP_COMPL_REQ +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:CONNECT_REQUEST IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state CONNECT_REQUEST -> ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending guard timer +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_CONNECT_ACK +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_CONNECT_ACK: 030f +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + + +- RTP stream goes ahead, not shown here. +- Total time passed: 1750.001274 s + + +- Call ends + MSC <--GERAN-A-- MS: GSM48_MT_CC_DISCONNECT +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_DISCONNECT +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx DISCONNECT in state ACTIVE +DCC trans(CC:ACTIVE IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state ACTIVE -> DISCONNECT_IND +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_DISC_IND + MSC --> MNCC: callref 0x423: MNCC_DISC_IND + +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 1 (cc) + MSC <-- MNCC: callref 0x423: MNCC_REL_REQ + +DMNCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx MNCC_REL_REQ +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting guard timer with 180 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) starting timer T308 with 10 seconds +DCC trans(CC:DISCONNECT_IND IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) new state DISCONNECT_IND -> RELEASE_REQ +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Sending DTAP: CC GSM48_MT_CC_RELEASE +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN encode: DTAP on GERAN-A +- DTAP --GERAN-A--> MS: GSM48_MT_CC_RELEASE: 032d +- DTAP matches expected message +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST + MSC <--GERAN-A-- MS: GSM48_MT_CC_RELEASE_COMPL +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: + rx_from_ms: now used by 2 (cc,rx_from_ms) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: RAN decode: DTAP +DRLL msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Dispatching 04.08 message: CC GSM48_MT_CC_RELEASE_COMPL +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) rx RELEASE_COMPL in state RELEASE_REQ +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) stopping pending timer T308 +DMNCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x423 tid-0) tx MNCC_REL_CNF + MSC --> MNCC: callref 0x423: MNCC_REL_CNF + +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) Freeing transaction +DCC trans(CC:RELEASE_REQ IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) new state RELEASE_REQ -> NULL +DCC trans(CC:NULL IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP callref-0x0 tid-0) stopping pending guard timer +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - CC: now used by 2 (attached,active-conn) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - cc: now used by 1 (rx_from_ms) +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: - rx_from_ms: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_COMMUNICATING}: state_chg to MSC_A_ST_RELEASING +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 4 (attached,active-conn,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 3 (attached,active-conn,msc_a_fsm_releasing_onenter) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){ESTABLISHING}: state_chg to RELEASING +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_RAN:no-CI:local-10-23-23-1-23:remote-1-2-3-4-1234){UNINITIALIZED}: Deallocated +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_CN:no-CI){UNINITIALIZED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_CN:no-CI){UNINITIALIZED}: Removing from parent call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DCC rtp_stream(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP:trans-0:call-19:RTP_TO_CN:no-CI){UNINITIALIZED}: Deallocated +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_EV_CALL_LEG_TERM +DCC call_leg(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){RELEASING}: Deallocated +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 2 (attached,active-conn) +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: RAN decode: CLEAR_COMPLETE +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: - wait-Clear-Complete: now used by 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: Received Event MSC_A_EV_UNUSED +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASING}: state_chg to MSC_A_ST_RELEASED +DBSSAP msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Released: msc_a use is 0 (-) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Removing from parent msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DVLR Process_Access_Request_VLR(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){PR_ARQ_S_DONE}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Removing from parent msub_fsm +DREF msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: max total use count was 3 +DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED +DMSC msub(IMSI-901700000010650:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000010650:MSISDN-46071) 1 MSC-I still active +DMSC msub_fsm{active}: state_chg to terminating +DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP)) +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Removing from parent msub_fsm +DMSC dummy_msc_i(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){0}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msub(IMSI-901700000010650:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000010650:MSISDN-46071 - active-conn: now used by 1 (attached) +DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP) +DMSC msc_a(IMSI-901700000010650:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations +- msub gone + llist_count(&msub_list) == 0 + + +- ======================== SUCCESS: MT call: AMR picked by both MO and MT, but MO assigns a different payload type number + llist_count(&msub_list) == 0 +DVLR freeing VLR subscr IMSI-901700000010650:MSISDN-46071 (max total use count was 5) +===== test_codecs: SUCCESS + diff --git a/tests/msc_vlr/msc_vlr_test_gsm_authen.err b/tests/msc_vlr/msc_vlr_test_gsm_authen.err index 648ad3ff5..94c169488 100644 --- a/tests/msc_vlr/msc_vlr_test_gsm_authen.err +++ b/tests/msc_vlr/msc_vlr_test_gsm_authen.err @@ -91,7 +91,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -680,7 +680,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -1220,7 +1220,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A: DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x03020100:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -1511,7 +1511,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -1824,7 +1824,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -2089,7 +2089,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -2355,7 +2355,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -2683,7 +2683,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -3271,12 +3271,12 @@ DMM msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: MM GSM AUTHENTIC DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000004620) AUTH on GERAN received SRES/RES: (0 bytes) DVLR SUBSCR(IMSI-901700000004620) AUTH SRES/RES missing -DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000004026f00a0101 DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000004620:GERAN-A:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err index 65553d72f..afea400c8 100644 --- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err +++ b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err @@ -65,7 +65,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -722,7 +722,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -1427,7 +1427,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -1747,7 +1747,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -2032,7 +2032,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -2394,7 +2394,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on GERAN-A @@ -2997,7 +2997,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DBSSAP msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: For A5/3, we still need Classmark 2 @@ -3646,7 +3646,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DBSSAP msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: For A5/3, we still need Classmark 2 diff --git a/tests/msc_vlr/msc_vlr_test_hlr_reject.err b/tests/msc_vlr/msc_vlr_test_hlr_reject.err index b92386517..305e1b814 100644 --- a/tests/msc_vlr/msc_vlr_test_hlr_reject.err +++ b/tests/msc_vlr/msc_vlr_test_hlr_reject.err @@ -43,11 +43,11 @@ DREF msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - rx_from_ms: n DREF VLR subscr IMSI-901700000004620 + vlr_gsup_rx: now used by 2 (active-conn,vlr_gsup_rx) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 2: IMSI unknown in HLR -DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result IMSI unknown in HLR +DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result NO_AUTH_INFO, cause IMSI_UNKNOWN_IN_HLR DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_NO_INFO - sending LU Reject for IMSI-901700000004620:GERAN-A:LU, cause 2 DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -142,11 +142,11 @@ DREF msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - rx_from_ms: n DREF VLR subscr IMSI-901700000004620 + vlr_gsup_rx: now used by 2 (active-conn,vlr_gsup_rx) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 17: Network failure -DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result Network failure +DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result NO_AUTH_INFO, cause NETWORK_FAILURE DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_NO_INFO - sending LU Reject for IMSI-901700000004620:GERAN-A:LU, cause 17 DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -266,7 +266,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -431,7 +431,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_W DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -595,7 +595,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -738,11 +738,11 @@ DREF msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - DREF VLR subscr IMSI-901700000004620:MSISDN-46071 + vlr_gsup_rx: now used by 3 (attached,active-conn,vlr_gsup_rx) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 17: Network failure -DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result Network failure +DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result NO_AUTH_INFO, cause NETWORK_FAILURE DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_NO_INFO - sending LU Reject for IMSI-901700000004620:MSISDN-46071:GERAN-A:LU, cause 17 DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -862,7 +862,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -1006,11 +1006,11 @@ DREF msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - DREF VLR subscr IMSI-901700000004620:MSISDN-46071 + vlr_gsup_rx: now used by 3 (attached,active-conn,vlr_gsup_rx) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_NACK DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: GSUP: rx Auth Info Error cause: 2: IMSI unknown in HLR -DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result IMSI unknown in HLR +DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result NO_AUTH_INFO, cause IMSI_UNKNOWN_IN_HLR DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_NO_INFO - sending LU Reject for IMSI-901700000004620:MSISDN-46071:GERAN-A:LU, cause 2 DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -1104,11 +1104,11 @@ DREF msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: - rx_from_ms: n <-- GSUP rx OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT: 0a010809710000004026f00a0101 DREF VLR subscr IMSI-901700000004620 + vlr_gsup_rx: now used by 2 (active-conn,vlr_gsup_rx) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Received Event VLR_AUTH_E_HLR_SAI_ACK -DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result Network failure +DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: Authentication terminating with result FAILURE, cause NETWORK_FAILURE DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_NEEDS_AUTH_WAIT_AI}: state_chg to VLR_SUB_AS_AUTH_FAILED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000004620:GERAN-A:LU, cause 17 DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE diff --git a/tests/msc_vlr/msc_vlr_test_ms_timeout.err b/tests/msc_vlr/msc_vlr_test_ms_timeout.err index 5ba3a8ffd..c4a73e35b 100644 --- a/tests/msc_vlr/msc_vlr_test_ms_timeout.err +++ b/tests/msc_vlr/msc_vlr_test_ms_timeout.err @@ -192,7 +192,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -775,7 +775,7 @@ DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000004620:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000004620:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DBSSAP msc_a(IMSI-901700000004620:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: For A5/3, we still need Classmark 2 diff --git a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err b/tests/msc_vlr/msc_vlr_test_reject_concurrency.err index 67b4819b9..25ccdfb64 100644 --- a/tests/msc_vlr/msc_vlr_test_reject_concurrency.err +++ b/tests/msc_vlr/msc_vlr_test_reject_concurrency.err @@ -1032,8 +1032,8 @@ DREF msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AU DBSSAP msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP DRLL msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Rx CM SERVICE REQUEST cm_service_type=Short-Messaging-Service -DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: re-using already accepted connection DREF msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + cm_service_sms: now used by 3 (2*cm_service_sms,rx_from_ms) +DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: re-using already accepted connection DBSSAP msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC DMSC msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN encode: DTAP on GERAN-A - DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 @@ -1842,8 +1842,8 @@ DREF msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHE DBSSAP msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: RAN decode: DTAP DRLL msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:PAGING_RESP){MSC_A_ST_AUTHENTICATED}: Dispatching 04.08 message: MM GSM48_MT_MM_CM_SERV_REQ DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Rx CM SERVICE REQUEST cm_service_type=Short-Messaging-Service -DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: re-using already accepted connection DREF msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: + cm_service_sms: now used by 3 (sms,rx_from_ms,cm_service_sms) +DMM msc_a(IMSI-901700000004620:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: re-using already accepted connection DBSSAP msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: Sending DTAP: MM GSM48_MT_MM_CM_SERV_ACC DMSC msc_a(IMSI-901700000004620:MSISDN-46071:GERAN-A:CM_SERVICE_REQ){MSC_A_ST_AUTHENTICATED}: RAN encode: DTAP on GERAN-A - DTAP --GERAN-A--> MS: GSM48_MT_MM_CM_SERV_ACC: 0521 diff --git a/tests/msc_vlr/msc_vlr_test_rest.err b/tests/msc_vlr/msc_vlr_test_rest.err index e64932537..3a6442e21 100644 --- a/tests/msc_vlr/msc_vlr_test_rest.err +++ b/tests/msc_vlr/msc_vlr_test_rest.err @@ -467,7 +467,6 @@ DRLL msc_a(TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Dispatching 04.08 me DMM IDENTITY RESPONSE: IMSI-901700000004620 DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620 DVLR vlr_lu_fsm(TMSI-0x23422342:GERAN-A:LU){VLR_ULA_S_WAIT_IMSI}: Received Event VLR_ULA_E_ID_IMSI -DVLR set IMSI on subscriber; IMSI=901700000004620 id=901700000004620 DVLR vlr_lu_fsm(TMSI-0x23422342:GERAN-A:LU){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_node1_pre() DVLR vlr_lu_fsm(TMSI-0x23422342:GERAN-A:LU){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_node1() DVLR vlr_lu_fsm(TMSI-0x23422342:GERAN-A:LU){VLR_ULA_S_WAIT_IMSI}: vlr_loc_upd_post_auth() @@ -528,7 +527,7 @@ DVLR lu_compl_vlr_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A: DVLR lu_compl_vlr_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){LU_COMPL_VLR_S_INIT}: state_chg to LU_COMPL_VLR_S_WAIT_SUB_PRES DVLR lu_compl_vlr_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){LU_COMPL_VLR_S_WAIT_SUB_PRES}: Received Event LU_COMPL_VLR_E_SUB_PRES_COMPL - sending LU Accept for IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 + attached: now used by 3 (active-conn,vlr_gsup_rx,attached) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 + attached: now used by 3 (active-conn,vlr_gsup_rx,attached) DVLR lu_compl_vlr_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){LU_COMPL_VLR_S_WAIT_SUB_PRES}: state_chg to LU_COMPL_VLR_S_DONE DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){VLR_ULA_S_WAIT_LU_COMPL}: Received Event VLR_ULA_E_LU_COMPL_SUCCESS DVLR lu_compl_vlr_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){LU_COMPL_VLR_S_DONE}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: upd_hlr_vlr_fsm(TMSI-0x23422342:GERAN-A:LU)) @@ -541,15 +540,15 @@ DREF msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_S DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_AUTHENTICATED}: Received Event MSC_A_EV_UNUSED DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_AUTHENTICATED}: state_chg to MSC_A_ST_RELEASING DBSSAP msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASING}: Releasing: msc_a use is 0 (-) -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 + msc_a_fsm_releasing_onenter: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 + vlr_subscr_cancel_attach_fsm: now used by 5 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 - vlr_subscr_cancel_attach_fsm: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 + msc_a_fsm_releasing_onenter: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 + vlr_subscr_cancel_attach_fsm: now used by 5 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter,vlr_subscr_cancel_attach_fsm) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 - vlr_subscr_cancel_attach_fsm: now used by 4 (active-conn,vlr_gsup_rx,attached,msc_a_fsm_releasing_onenter) DREF msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASING}: + wait-Clear-Complete: now used by 1 (wait-Clear-Complete) DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASING}: RAN encode: CLEAR_COMMAND on GERAN-A DMSC dummy_msc_i(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){0}: Received Event MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 - msc_a_fsm_releasing_onenter: now used by 3 (active-conn,vlr_gsup_rx,attached) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 - msc_a_fsm_releasing_onenter: now used by 3 (active-conn,vlr_gsup_rx,attached) DVLR upd_hlr_vlr_fsm(TMSI-0x23422342:GERAN-A:LU){UPD_HLR_VLR_S_DONE}: Deallocated, including all deferred deallocations -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 - vlr_gsup_rx: now used by 2 (active-conn,attached) +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 - vlr_gsup_rx: now used by 2 (active-conn,attached) <-- GSUP rx OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT: vlr_gsupc_read_cb() returns 0 bssap_clear_sent == 1 - LU was successful, and the conn has already been closed @@ -567,19 +566,19 @@ DVLR vlr_lu_fsm(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){VL DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASED}: Removing from parent msub_fsm DREF msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASED}: max total use count was 3 DMSC msub_fsm{active}: Received Event MSUB_EV_ROLE_TERMINATED -DMSC msub(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342) MSC-A terminated -DMSC msub(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342) 1 MSC-I still active +DMSC msub(IMSI-901700000004620:MSISDN-46071) MSC-A terminated +DMSC msub(IMSI-901700000004620:MSISDN-46071) 1 MSC-I still active DMSC msub_fsm{active}: state_chg to terminating DMSC msub_fsm{terminating}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_REGULAR, caused by: msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU)) DMSC dummy_msc_i(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){0}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU)) DMSC dummy_msc_i(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){0}: Removing from parent msub_fsm DMSC dummy_msc_i(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){0}: Deferring: will deallocate with msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU) -DMSC msub(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342) Free -DREF VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 - active-conn: now used by 1 (attached) +DMSC msub(IMSI-901700000004620:MSISDN-46071) Free +DREF VLR subscr IMSI-901700000004620:MSISDN-46071 - active-conn: now used by 1 (attached) DMSC msub_fsm{terminating}: Deferring: will deallocate with msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU) DMSC msc_a(IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342:GERAN-A:LU){MSC_A_ST_RELEASED}: Deallocated, including all deferred deallocations - msub gone llist_count(&msub_list) == 0 -DVLR freeing VLR subscr IMSI-901700000004620:MSISDN-46071:TMSI-0x23422342 (max total use count was 5) +DVLR freeing VLR subscr IMSI-901700000004620:MSISDN-46071 (max total use count was 5) ===== test_lu_unknown_tmsi: SUCCESS diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.err b/tests/msc_vlr/msc_vlr_test_umts_authen.err index 543c9d3c0..aacff394d 100644 --- a/tests/msc_vlr/msc_vlr_test_umts_authen.err +++ b/tests/msc_vlr/msc_vlr_test_umts_authen.err @@ -66,7 +66,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Au DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -673,7 +673,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -1304,7 +1304,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: A DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -1963,7 +1963,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP_RESY DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP_RESYNC}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_ciph() DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: COMMON_ID on GERAN-A @@ -2195,7 +2195,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP_RES DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP_RESYNC}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -2437,7 +2437,7 @@ DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP_RES DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP_RESYNC}: state_chg to VLR_SUB_AS_AUTHENTICATED DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTHENTICATED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_SUCCESS DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth() DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: RAN encode: CIPHER_MODE_COMMAND on UTRAN-Iu @@ -2647,12 +2647,12 @@ DMM msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: MM UMTS AUTHENTI DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on GERAN received SRES/RES: e229c19e791f2e (7 bytes) DVLR SUBSCR(IMSI-901700000010650) AUTH SRES/RES has invalid length: 7. Expected either 4 (GSM AKA) or 8 (UMTS AKA) -DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:GERAN-A:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -2763,12 +2763,12 @@ DMM msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: MM UMTS AUTHENT DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on UTRAN received RES: e229c19e791f2e (7 bytes) DVLR SUBSCR(IMSI-901700000010650) AUTH RES has invalid length: 7. Expected 8 (UMTS AKA) -DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:UTRAN-Iu:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -2879,12 +2879,12 @@ DMM msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: MM UMTS AUTHENTI DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on GERAN received SRES/RES: e229c19e791f2e4123 (9 bytes) DVLR SUBSCR(IMSI-901700000010650) AUTH SRES/RES has invalid length: 9. Expected either 4 (GSM AKA) or 8 (UMTS AKA) -DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:GERAN-A:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -2995,12 +2995,12 @@ DMM msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: MM UMTS AUTHENT DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on UTRAN received RES: e229c19e791f2e4123 (9 bytes) DVLR SUBSCR(IMSI-901700000010650) AUTH RES has invalid length: 9. Expected 8 (UMTS AKA) -DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:UTRAN-Iu:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -3111,12 +3111,12 @@ DMM msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: MM GSM AUTHENTIC DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on GERAN received SRES/RES: e229c19e (4 bytes) DVLR SUBSCR(IMSI-901700000010650) GSM AUTH failure: mismatching sres (expected sres=9b 36 ef df ) -DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:GERAN-A:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:GERAN-A:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:GERAN-A:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:GERAN-A:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE @@ -3227,12 +3227,12 @@ DMM msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: MM GSM AUTHENTI DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Received Event VLR_AUTH_E_MS_AUTH_RESP DVLR SUBSCR(IMSI-901700000010650) AUTH on UTRAN received RES: e229c19e (4 bytes) DVLR SUBSCR(IMSI-901700000010650) AUTH via UTRAN, cannot allow GSM AKA (MS is R99 capable, vec has UMTS AKA tokens, res_len=4 is INVALID on UTRAN) -DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result Illegal MS +DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: Authentication terminating with result FAILURE, cause ILLEGAL_MS DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_WAIT_RESP}: state_chg to VLR_SUB_AS_AUTH_FAILED GSUP --> HLR: OSMO_GSUP_MSGT_AUTH_FAIL_REPORT: 0b010809710000000156f00a0101 DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DVLR VLR_Authenticate(IMSI-901700000010650:UTRAN-Iu:LU){VLR_SUB_AS_AUTH_FAILED}: Removing from parent vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU) -DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES +DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_FAILURE - sending LU Reject for IMSI-901700000010650:UTRAN-Iu:LU, cause 3 DVLR vlr_lu_fsm(IMSI-901700000010650:UTRAN-Iu:LU){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_DONE DMSC msc_a(IMSI-901700000010650:UTRAN-Iu:LU){MSC_A_ST_AUTH_CIPH}: Received Event MSC_A_EV_CN_CLOSE diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c index fbd254018..062d8a35b 100644 --- a/tests/msc_vlr/msc_vlr_tests.c +++ b/tests/msc_vlr/msc_vlr_tests.c @@ -41,6 +41,7 @@ #include <osmocom/msc/msc_t.h> #include <osmocom/msc/call_leg.h> #include <osmocom/msc/rtp_stream.h> +#include <osmocom/msc/codec_mapping.h> #include "msc_vlr_tests.h" @@ -76,6 +77,7 @@ bool bssap_clear_sent = false; bool bssap_assignment_expected = false; bool bssap_assignment_sent = false; +struct gsm0808_channel_type bssap_assignment_command_last_channel_type; bool iu_rab_assignment_expected = false; bool iu_rab_assignment_sent = false; @@ -83,9 +85,10 @@ uint32_t cc_to_mncc_tx_expected_msg_type = 0; const char *cc_to_mncc_tx_expected_imsi = NULL; bool cc_to_mncc_tx_confirmed = false; uint32_t cc_to_mncc_tx_got_callref = 0; +char cc_to_mncc_tx_last_sdp[1024] = {}; -enum rtp_direction expecting_crcx = -1; -bool got_crcx = false; +bool expecting_crcx[2] = {}; +bool got_crcx[2] = {}; extern int ran_dec_dtap_undup_pdisc_ctr_bin(uint8_t pdisc); @@ -307,14 +310,18 @@ static int bssap_validate_cipher_mode_cmd(const struct ran_cipher_mode_command * return 0; } -static void bssap_validate_assignment_cmd() +static void bssap_validate_assignment_cmd(const struct ran_assignment_command *assignment_command) { OSMO_ASSERT(bssap_assignment_expected); bssap_assignment_expected = false; bssap_assignment_sent = true; + if (assignment_command->channel_type) + bssap_assignment_command_last_channel_type = *assignment_command->channel_type; + else + bssap_assignment_command_last_channel_type = (struct gsm0808_channel_type){}; } -static void iucs_validate_assignment_cmd() +static void iucs_validate_assignment_cmd(const struct ran_assignment_command *assignment_command) { OSMO_ASSERT(iu_rab_assignment_expected); iu_rab_assignment_expected = false; @@ -374,10 +381,10 @@ struct msgb *dont_ran_encode(struct osmo_fsm_inst *caller_fi, const struct ran_m case RAN_MSG_ASSIGNMENT_COMMAND: switch (ran_type) { case OSMO_RAT_GERAN_A: - bssap_validate_assignment_cmd(); + bssap_validate_assignment_cmd(&ran_enc_msg->assignment_command); break; case OSMO_RAT_UTRAN_IU: - iucs_validate_assignment_cmd(); + iucs_validate_assignment_cmd(&ran_enc_msg->assignment_command); break; default: OSMO_ASSERT(false); @@ -408,6 +415,16 @@ struct ran_infra test_ran_infra[] = { .log_subsys = DIUCS, .tdefs = msc_tdefs_utran, .ran_encode = dont_ran_encode, + .force_mgw_codecs_to_ran = { + .count = 1, + .codec = { + { + .payload_type = 96, + .subtype_name = "VND.3GPP.IUFP", + .rate = 16000, + }, + }, + }, }, }; @@ -419,7 +436,7 @@ static int fake_msc_a_ran_dec(const struct ran_msg *ran_dec_msg) return msc_a_ran_decode_cb(g_msub->role[MSC_ROLE_A], &d, ran_dec_msg); } -void rx_from_ms(struct msgb *msg) +void rx_from_ms(struct msgb *msg, const struct gsm0808_speech_codec_list *codec_list_bss_supported) { struct gsm48_hdr *gh = msgb_l3(msg); struct ran_msg ran_dec_msg; @@ -452,6 +469,7 @@ void rx_from_ms(struct msgb *msg) .compl_l3 = { .cell_id = &cell_id, .msg = msg, + .codec_list_bss_supported = codec_list_bss_supported, }, }; } else { @@ -479,7 +497,30 @@ void ms_sends_msg(const char *hex) msg = msgb_from_hex("ms_sends_msg", 1024, hex); msg->l1h = msg->l2h = msg->l3h = msg->data; - rx_from_ms(msg); + rx_from_ms(msg, NULL); + msgb_free(msg); +} + +void ms_sends_msgf(const char *fmt, ...) +{ + va_list ap; + char *hex; + + va_start(ap, fmt); + hex = talloc_vasprintf(msc_vlr_tests_ctx, fmt, ap); + va_end(ap); + + ms_sends_msg(hex); + talloc_free(hex); +} + +void ms_sends_compl_l3(const char *hex, const struct gsm0808_speech_codec_list *codec_list_bss_supported) +{ + struct msgb *msg; + + msg = msgb_from_hex("ms_sends_msg", 1024, hex); + msg->l1h = msg->l2h = msg->l3h = msg->data; + rx_from_ms(msg, codec_list_bss_supported); msgb_free(msg); } @@ -640,8 +681,8 @@ void clear_vlr() osmo_gettimeofday_override = false; - expecting_crcx = -1; - got_crcx = false; + memset(expecting_crcx, 0, sizeof(expecting_crcx)); + memset(got_crcx, 0, sizeof(got_crcx)); bssap_assignment_expected = false; bssap_assignment_sent = false; @@ -722,8 +763,18 @@ struct gsm_mncc *on_call_release_mncc_sends_to_cc_data = NULL; int mncc_recv(struct gsm_network *net, struct msgb *msg) { struct gsm_mncc *mncc = (void*)msg->data; - log("MSC --> MNCC: callref 0x%x: %s", mncc->callref, - get_mncc_name(mncc->msg_type)); + if (mncc->msg_type == MNCC_RTP_CREATE) { + struct gsm_mncc_rtp *rtp = (void *)msg->data; + log("MSC --> MNCC: callref 0x%x: %s\n%s", rtp->callref, + get_mncc_name(rtp->msg_type), + rtp->sdp); + OSMO_STRLCPY_ARRAY(cc_to_mncc_tx_last_sdp, rtp->sdp); + } else { + log("MSC --> MNCC: callref 0x%x: %s\n%s", mncc->callref, + get_mncc_name(mncc->msg_type), + mncc->sdp); + OSMO_STRLCPY_ARRAY(cc_to_mncc_tx_last_sdp, mncc->sdp); + } if (mncc->msg_type == MNCC_REL_IND && on_call_release_mncc_sends_to_cc_data) { @@ -835,27 +886,35 @@ struct rtp_stream fake_rtp[2] = { void expect_crcx(enum rtp_direction towards) { - OSMO_ASSERT(expecting_crcx == -1); - expecting_crcx = towards; - got_crcx = false; + OSMO_ASSERT(!expecting_crcx[towards]); + expecting_crcx[towards] = true; + got_crcx[towards] = false; +} + +bool crcx_scheduled(enum rtp_direction towards) +{ + return got_crcx[towards]; } /* override, requires '-Wl,--wrap=call_leg_ensure_ci' */ int __real_call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans, - const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known); + const struct sdp_audio_codecs *codecs_if_known, + const struct osmo_sockaddr_str *remote_addr_if_known); int __wrap_call_leg_ensure_ci(struct call_leg *cl, enum rtp_direction dir, uint32_t call_id, struct gsm_trans *for_trans, - const enum mgcp_codecs *codec_if_known, const struct osmo_sockaddr_str *remote_addr_if_known) + const struct sdp_audio_codecs *codecs_if_known, + const struct osmo_sockaddr_str *remote_addr_if_known) { if (!cl->rtp[dir]) { - log("MGW <--CRCX to %s-- MSC: callref=0x%x", rtp_direction_name(dir), call_id); + log("MGW <--CRCX to %s-- MSC: call_id=0x%x codecs=%s", rtp_direction_name(dir), call_id, + codecs_if_known ? sdp_audio_codecs_to_str(codecs_if_known) : "unset"); - OSMO_ASSERT(expecting_crcx == dir); - expecting_crcx = -1; - got_crcx = true; + OSMO_ASSERT(expecting_crcx[dir]); + expecting_crcx[dir] = false; + got_crcx[dir] = true; call_leg_ensure_rtp_alloc(cl, dir, call_id, for_trans); - if (codec_if_known) - rtp_stream_set_codec(cl->rtp[dir], *codec_if_known); + if (codecs_if_known) + rtp_stream_set_codecs(cl->rtp[dir], codecs_if_known); if (remote_addr_if_known && osmo_sockaddr_str_is_nonzero(remote_addr_if_known)) rtp_stream_set_remote_addr(cl->rtp[dir], remote_addr_if_known); } @@ -1000,16 +1059,22 @@ void ms_sends_security_mode_complete(uint8_t utran_encryption) g_msub = NULL; } -void ms_sends_assignment_complete(enum mgcp_codecs assigned_codec) +void ms_sends_assignment_complete(const char *sdp_codec_name) { struct ran_msg ran_dec; + const struct codec_mapping *m = codec_mapping_by_subtype_name(sdp_codec_name); + OSMO_ASSERT(m); + OSMO_ASSERT(m->has_gsm0808_speech_codec); ran_dec = (struct ran_msg){ .msg_type = RAN_MSG_ASSIGNMENT_COMPLETE, .assignment_complete = { - .codec = assigned_codec, + .codec_present = true, + .codec = m->gsm0808_speech_codec, + .codec_with_iuup = (rx_from_ran == OSMO_RAT_UTRAN_IU), }, }; + osmo_sockaddr_str_from_str(&ran_dec.assignment_complete.remote_rtp, "1.2.3.4", 1234); fake_msc_a_ran_dec(&ran_dec); if (!conn_exists(g_msub)) @@ -1135,6 +1200,7 @@ static void run_tests(int nr) struct gsm_network *test_net(void *ctx) { struct gsm_network *net = gsm_network_init(ctx, mncc_recv); + struct mgcp_client *client; net->gsup_server_addr_str = talloc_strdup(net, "no_gsup_server"); net->gsup_server_port = 0; @@ -1169,10 +1235,11 @@ struct gsm_network *test_net(void *ctx) INIT_LLIST_HEAD(&net->iu.sri->ran_conns); net->mgw.tdefs = g_mgw_tdefs; - mgcp_client_conf_init(&net->mgw.conf); net->mgw.tdefs = g_mgw_tdefs; - net->mgw.client = mgcp_client_init(net, &net->mgw.conf); - + net->mgw.conf = mgcp_client_conf_alloc(net); + net->mgw.mgw_pool = mgcp_client_pool_alloc(net); + client = mgcp_client_init(net, net->mgw.conf); + mgcp_client_pool_register_single(net->mgw.mgw_pool, client); return net; } diff --git a/tests/msc_vlr/msc_vlr_tests.h b/tests/msc_vlr/msc_vlr_tests.h index 1f83013b0..b0605f104 100644 --- a/tests/msc_vlr/msc_vlr_tests.h +++ b/tests/msc_vlr/msc_vlr_tests.h @@ -56,6 +56,8 @@ extern bool _log_lines; #define comment_start() fprintf(stderr, "===== %s\n", __func__); #define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__); +extern void *msc_vlr_tests_ctx; + extern struct msub *g_msub; extern struct gsm_network *net; extern void *msgb_ctx; @@ -116,6 +118,7 @@ extern uint32_t cc_to_mncc_tx_expected_msg_type; extern const char *cc_to_mncc_tx_expected_imsi; extern bool cc_to_mncc_tx_confirmed; extern uint32_t cc_to_mncc_tx_got_callref; +extern char cc_to_mncc_tx_last_sdp[1024]; extern struct gsm_mncc *on_call_release_mncc_sends_to_cc_data; @@ -148,6 +151,7 @@ static inline void expect_release_clear(enum osmo_rat_type via_ran) extern bool bssap_assignment_expected; extern bool bssap_assignment_sent; +extern struct gsm0808_channel_type bssap_assignment_command_last_channel_type; extern bool iu_rab_assignment_expected; extern bool iu_rab_assignment_sent; @@ -183,10 +187,12 @@ void paging_expect_imsi(const char *imsi); void paging_expect_tmsi(uint32_t tmsi); void ms_sends_msg(const char *hex); +void ms_sends_msgf(const char *fmt, ...); +void ms_sends_compl_l3(const char *hex, const struct gsm0808_speech_codec_list *codec_list_bss_supported); void ms_sends_classmark_update(const struct osmo_gsm48_classmark *classmark); void ms_sends_ciphering_mode_complete(const char *inner_nas_msg); void ms_sends_security_mode_complete(uint8_t utran_encryption); -void ms_sends_assignment_complete(enum mgcp_codecs assigned_codec); +void ms_sends_assignment_complete(const char *sdp_codec_name); void gsup_rx(const char *rx_hex, const char *expect_tx_hex); void send_sms(struct vlr_subscr *receiver, struct vlr_subscr *sender, @@ -275,5 +281,5 @@ extern const struct timeval fake_time_start_time; #define EUSE_TO_MSC_USSD "0a0103" #define MSC_USSD_TO_EUSE "0a0103" -extern bool got_crcx; void expect_crcx(enum rtp_direction towards); +bool crcx_scheduled(enum rtp_direction towards); diff --git a/tests/sdp_msg/Makefile.am b/tests/sdp_msg/Makefile.am index 7d8def9b2..f86e5f7a3 100644 --- a/tests/sdp_msg/Makefile.am +++ b/tests/sdp_msg/Makefile.am @@ -9,6 +9,11 @@ AM_CFLAGS = \ $(LIBOSMOCORE_CFLAGS) \ $(NULL) +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -no-install \ + $(NULL) + LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(LIBOSMOCORE_LIBS) \ @@ -19,7 +24,7 @@ EXTRA_DIST = \ sdp_msg_test.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ sdp_msg_test \ $(NULL) diff --git a/tests/sdp_msg/sdp_msg_test.c b/tests/sdp_msg/sdp_msg_test.c index b97127add..4798ae007 100644 --- a/tests/sdp_msg/sdp_msg_test.c +++ b/tests/sdp_msg/sdp_msg_test.c @@ -61,6 +61,7 @@ struct sdp_test_data sdp_tests[] = { "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-15\r\n" "a=ptime:20\r\n" + "a=sendrecv\r\n" , }, { @@ -116,6 +117,7 @@ struct sdp_test_data sdp_tests[] = { "a=rtpmap:101 telephone-event/8000\r\n" "a=fmtp:101 0-15\r\n" "a=ptime:20\r\n" + "a=sendrecv\r\n" , }, }; @@ -134,10 +136,10 @@ void test_parse_and_compose() printf("\n[%d]\n", i); dump_sdp(t->sdp_input, "sdp input: "); - sdp_msg_from_str(&sdp, t->sdp_input); - sdp_msg_to_str(str, sizeof(str), &sdp); + OSMO_ASSERT(sdp_msg_from_sdp_str(&sdp, t->sdp_input) == 0); + sdp_msg_to_sdp_str_buf(str, sizeof(str), &sdp); - dump_sdp(str, "sdp_msg_to_str: "); + dump_sdp(str, "sdp_msg_to_sdp_str_buf: "); if (strcmp(str, t->expect_sdp_str)) { int j; ok = false; @@ -344,7 +346,7 @@ struct sdp_intersect_test_data sdp_intersect_tests[] = { const char *sdp_msg_logstr(const struct sdp_msg *sdp) { static char buf[1024]; - sdp_msg_to_str(buf, sizeof(buf), sdp); + sdp_msg_to_sdp_str_buf(buf, sizeof(buf), sdp); return buf; } @@ -365,20 +367,20 @@ static void test_intersect() dump_sdp(t->sdp_a, "SDP A: "); dump_sdp(t->sdp_b, " SDP B: "); - rc = sdp_msg_from_str(&sdp_a, t->sdp_a); + rc = sdp_msg_from_sdp_str(&sdp_a, t->sdp_a); if (rc) { printf("ERROR parsing SDP A: %d\n", rc); break; } dump_sdp(sdp_msg_logstr(&sdp_a), "parsed SDP A: "); - rc = sdp_msg_from_str(&sdp_b, t->sdp_b); + rc = sdp_msg_from_sdp_str(&sdp_b, t->sdp_b); if (rc) { printf("ERROR parsing SDP A: %d\n", rc); break; } dump_sdp(sdp_msg_logstr(&sdp_b), "parsed SDP B: "); sdp_audio_codecs_intersection(&sdp_a.audio_codecs, &sdp_b.audio_codecs, false); - sdp_msg_to_str(str, sizeof(str), &sdp_a); + sdp_msg_to_sdp_str_buf(str, sizeof(str), &sdp_a); dump_sdp(str, "sdp_msg_intersection(a,b): "); if (strcmp(str, t->expect_intersection)) { @@ -524,30 +526,33 @@ static void test_select() struct sdp_msg sdp = {}; struct sdp_audio_codec *codec; char buf[1024]; + const char *expect_sdp; + printf("\n[%d]\n", i); - rc = sdp_msg_from_str(&sdp, t->sdp); + rc = sdp_msg_from_sdp_str(&sdp, t->sdp); if (rc) { printf("ERROR parsing SDP: %d\n", rc); break; } - printf("SDP: %s\n", sdp_audio_codecs_name(&sdp.audio_codecs)); - codec = sdp_audio_codec_by_payload_type(&sdp.audio_codecs, t->select_payload_type, false); + printf("SDP: %s\n", sdp_audio_codecs_to_str(&sdp.audio_codecs)); + codec = sdp_audio_codecs_by_payload_type(&sdp.audio_codecs, t->select_payload_type, false); OSMO_ASSERT(codec); - printf("Select: %s\n", sdp_audio_codec_name(codec)); + printf("Select: %s\n", sdp_audio_codec_to_str(codec)); sdp_audio_codecs_select(&sdp.audio_codecs, codec); - printf("SDP: %s\n", sdp_audio_codecs_name(&sdp.audio_codecs)); - sdp_msg_to_str(buf, sizeof(buf), &sdp); + printf("SDP: %s\n", sdp_audio_codecs_to_str(&sdp.audio_codecs)); + sdp_msg_to_sdp_str_buf(buf, sizeof(buf), &sdp); - if (strcmp(buf, t->expect_sdp ? : t->sdp)) { + expect_sdp = t->expect_sdp ? : t->sdp; + if (strcmp(buf, expect_sdp)) { int j; ok = false; printf("ERROR:\n"); dump_sdp(buf, "selection result: "); - dump_sdp(t->expect_sdp, "expect result: "); - for (j = 0; t->expect_sdp[j]; j++) { - if (t->expect_sdp[j] != buf[j]) { + dump_sdp(expect_sdp, "expect result: "); + for (j = 0; expect_sdp[j]; j++) { + if (expect_sdp[j] != buf[j]) { printf("ERROR at position %d, at:\n", j); dump_sdp(buf + j, " mismatch: "); break; diff --git a/tests/sdp_msg/sdp_msg_test.ok b/tests/sdp_msg/sdp_msg_test.ok index a7a3d5156..51a236b51 100644 --- a/tests/sdp_msg/sdp_msg_test.ok +++ b/tests/sdp_msg/sdp_msg_test.ok @@ -23,25 +23,26 @@ sdp input: a=rtpmap:101 telephone-event/8000\r\n sdp input: a=fmtp:101 0-15\r\n sdp input: a=ptime:20\r\n sdp input: a=sendrecv\r\n -sdp_msg_to_str: v=0\r\n -sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.121\r\n -sdp_msg_to_str: s=GSM Call\r\n -sdp_msg_to_str: c=IN IP4 192.168.11.121\r\n -sdp_msg_to_str: t=0 0\r\n -sdp_msg_to_str: m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n -sdp_msg_to_str: a=rtpmap:18 G729/8000\r\n -sdp_msg_to_str: a=rtpmap:0 PCMU/8000\r\n -sdp_msg_to_str: a=rtpmap:2 G726-32/8000\r\n -sdp_msg_to_str: a=rtpmap:4 G723/8000\r\n -sdp_msg_to_str: a=rtpmap:8 PCMA/8000\r\n -sdp_msg_to_str: a=rtpmap:96 G726-40/8000\r\n -sdp_msg_to_str: a=rtpmap:97 G726-24/8000\r\n -sdp_msg_to_str: a=rtpmap:98 G726-16/8000\r\n -sdp_msg_to_str: a=rtpmap:100 NSE/8000\r\n -sdp_msg_to_str: a=fmtp:100 192-193\r\n -sdp_msg_to_str: a=rtpmap:101 telephone-event/8000\r\n -sdp_msg_to_str: a=fmtp:101 0-15\r\n -sdp_msg_to_str: a=ptime:20\r\n +sdp_msg_to_sdp_str_buf: v=0\r\n +sdp_msg_to_sdp_str_buf: o=OsmoMSC 0 0 IN IP4 192.168.11.121\r\n +sdp_msg_to_sdp_str_buf: s=GSM Call\r\n +sdp_msg_to_sdp_str_buf: c=IN IP4 192.168.11.121\r\n +sdp_msg_to_sdp_str_buf: t=0 0\r\n +sdp_msg_to_sdp_str_buf: m=audio 10020 RTP/AVP 18 0 2 4 8 96 97 98 100 101\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:18 G729/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:0 PCMU/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:2 G726-32/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:4 G723/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:8 PCMA/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:96 G726-40/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:97 G726-24/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:98 G726-16/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:100 NSE/8000\r\n +sdp_msg_to_sdp_str_buf: a=fmtp:100 192-193\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:101 telephone-event/8000\r\n +sdp_msg_to_sdp_str_buf: a=fmtp:101 0-15\r\n +sdp_msg_to_sdp_str_buf: a=ptime:20\r\n +sdp_msg_to_sdp_str_buf: a=sendrecv\r\n [0] ok [1] @@ -55,15 +56,15 @@ sdp input: a=rtpmap:98 AMR/8000\r\n sdp input: a=fmtp:98 octet-align=1; mode-set=4\r\n sdp input: a=ptime:20\r\n sdp input: a=rtcp:16399 IN IP4 192.168.11.151\r\n -sdp_msg_to_str: v=0\r\n -sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.151\r\n -sdp_msg_to_str: s=GSM Call\r\n -sdp_msg_to_str: c=IN IP4 192.168.11.151\r\n -sdp_msg_to_str: t=0 0\r\n -sdp_msg_to_str: m=audio 16398 RTP/AVP 98\r\n -sdp_msg_to_str: a=rtpmap:98 AMR/8000\r\n -sdp_msg_to_str: a=fmtp:98 octet-align=1; mode-set=4\r\n -sdp_msg_to_str: a=ptime:20\r\n +sdp_msg_to_sdp_str_buf: v=0\r\n +sdp_msg_to_sdp_str_buf: o=OsmoMSC 0 0 IN IP4 192.168.11.151\r\n +sdp_msg_to_sdp_str_buf: s=GSM Call\r\n +sdp_msg_to_sdp_str_buf: c=IN IP4 192.168.11.151\r\n +sdp_msg_to_sdp_str_buf: t=0 0\r\n +sdp_msg_to_sdp_str_buf: m=audio 16398 RTP/AVP 98\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:98 AMR/8000\r\n +sdp_msg_to_sdp_str_buf: a=fmtp:98 octet-align=1; mode-set=4\r\n +sdp_msg_to_sdp_str_buf: a=ptime:20\r\n [1] ok [2] @@ -82,19 +83,20 @@ sdp input: a=fmtp:101 0-15\r\n sdp input: a=sendrecv\r\n sdp input: a=rtcp:30437\r\n sdp input: a=ptime:20\r\n -sdp_msg_to_str: v=0\r\n -sdp_msg_to_str: o=OsmoMSC 0 0 IN IP4 192.168.11.140\r\n -sdp_msg_to_str: s=GSM Call\r\n -sdp_msg_to_str: c=IN IP4 192.168.11.140\r\n -sdp_msg_to_str: t=0 0\r\n -sdp_msg_to_str: m=audio 30436 RTP/AVP 18 0 4 8 101\r\n -sdp_msg_to_str: a=rtpmap:18 G729/8000\r\n -sdp_msg_to_str: a=rtpmap:0 PCMU/8000\r\n -sdp_msg_to_str: a=rtpmap:4 G723/8000\r\n -sdp_msg_to_str: a=rtpmap:8 PCMA/8000\r\n -sdp_msg_to_str: a=rtpmap:101 telephone-event/8000\r\n -sdp_msg_to_str: a=fmtp:101 0-15\r\n -sdp_msg_to_str: a=ptime:20\r\n +sdp_msg_to_sdp_str_buf: v=0\r\n +sdp_msg_to_sdp_str_buf: o=OsmoMSC 0 0 IN IP4 192.168.11.140\r\n +sdp_msg_to_sdp_str_buf: s=GSM Call\r\n +sdp_msg_to_sdp_str_buf: c=IN IP4 192.168.11.140\r\n +sdp_msg_to_sdp_str_buf: t=0 0\r\n +sdp_msg_to_sdp_str_buf: m=audio 30436 RTP/AVP 18 0 4 8 101\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:18 G729/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:0 PCMU/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:4 G723/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:8 PCMA/8000\r\n +sdp_msg_to_sdp_str_buf: a=rtpmap:101 telephone-event/8000\r\n +sdp_msg_to_sdp_str_buf: a=fmtp:101 0-15\r\n +sdp_msg_to_sdp_str_buf: a=ptime:20\r\n +sdp_msg_to_sdp_str_buf: a=sendrecv\r\n [2] ok @@ -566,25 +568,25 @@ sdp_msg_intersection(a,b): a=ptime:20\r\n test_select [0] -SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR -Select: AMR:octet-align=1 -SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR +SDP: AMR:octet-align=1#112,GSM#3,GSM-HR-08#111,GSM-EFR#110 +Select: AMR:octet-align=1#112 +SDP: AMR:octet-align=1#112,GSM#3,GSM-HR-08#111,GSM-EFR#110 [0] ok [1] -SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR -Select: GSM -SDP: GSM,AMR:octet-align=1,GSM-HR-08,GSM-EFR +SDP: AMR:octet-align=1#112,GSM#3,GSM-HR-08#111,GSM-EFR#110 +Select: GSM#3 +SDP: GSM#3,AMR:octet-align=1#112,GSM-HR-08#111,GSM-EFR#110 [1] ok [2] -SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR -Select: GSM-HR-08 -SDP: GSM-HR-08,AMR:octet-align=1,GSM,GSM-EFR +SDP: AMR:octet-align=1#112,GSM#3,GSM-HR-08#111,GSM-EFR#110 +Select: GSM-HR-08#111 +SDP: GSM-HR-08#111,AMR:octet-align=1#112,GSM#3,GSM-EFR#110 [2] ok [3] -SDP: AMR:octet-align=1,GSM,GSM-HR-08,GSM-EFR -Select: GSM-EFR -SDP: GSM-EFR,AMR:octet-align=1,GSM,GSM-HR-08 +SDP: AMR:octet-align=1#112,GSM#3,GSM-HR-08#111,GSM-EFR#110 +Select: GSM-EFR#110 +SDP: GSM-EFR#110,AMR:octet-align=1#112,GSM#3,GSM-HR-08#111 [3] ok diff --git a/tests/smpp/Makefile.am b/tests/smpp/Makefile.am index 8d631198c..ff19d3d7c 100644 --- a/tests/smpp/Makefile.am +++ b/tests/smpp/Makefile.am @@ -11,12 +11,15 @@ AM_CFLAGS = \ $(LIBOSMOGSM_CFLAGS) \ $(LIBOSMOSCCP_CFLAGS) \ $(LIBOSMOABIS_CFLAGS) \ + $(LIBOSMOSCCP_CFLAGS) \ + $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(COVERAGE_CFLAGS) \ $(LIBSMPP34_CFLAGS) \ $(NULL) AM_LDFLAGS = \ $(COVERAGE_LDFLAGS) \ + -no-install \ $(NULL) EXTRA_DIST = \ @@ -24,16 +27,16 @@ EXTRA_DIST = \ smpp_test.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ smpp_test \ $(NULL) smpp_test_SOURCES = \ smpp_test.c \ - $(top_builddir)/src/libmsc/smpp_utils.c \ $(NULL) smpp_test_LDADD = \ + $(top_builddir)/src/libsmpputil/libsmpputil.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(NULL) diff --git a/tests/smpp/smpp_test.c b/tests/smpp/smpp_test.c index d86da5486..9b94c63f4 100644 --- a/tests/smpp/smpp_test.c +++ b/tests/smpp/smpp_test.c @@ -1,5 +1,6 @@ /* * (C) 2013 by Holger Hans Peter Freyther + * (C) 2022 by Harald Welte <laforge@osmocom.org> * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -21,12 +22,10 @@ #include <stdio.h> #include <osmocom/msc/debug.h> - +#include <osmocom/smpp/smpp_smsc.h> #include <osmocom/core/application.h> #include <osmocom/core/backtrace.h> -#include "smpp_smsc.h" - struct coding_test { uint8_t dcs; uint8_t coding; @@ -62,6 +61,41 @@ static void test_coding_scheme(void) } } +static const char *smpp_time_tests[] = { + "\0", + "220517175524000+", + "220517175524000-", + "220517175524004+", /* 1 hour advanced compared to GMT */ + "220517175524004-", /* 1 hour retarded compared to GMT */ + "000000010000000R", /* 1 hour */ + "000001000000000R", /* 1 day */ +}; + +static void test_smpp_parse_time_format(void) +{ + time_t t_now = 1652745600; /* 2022-05-17 00:00:00 UTC */ + char *orig_tz; + + printf("Testing SMPP time format parser\n"); + + /* relative time format conversion depends on the local time */ + orig_tz = getenv("TZ"); + setenv("TZ", "UTC", 1); + + for (unsigned int i = 0; i < ARRAY_SIZE(smpp_time_tests); i++) { + time_t t = smpp_parse_time_format(smpp_time_tests[i], &t_now); + char buf[32]; + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", gmtime(&t)); + printf("'%s': %ld == %s\n", smpp_time_tests[i], t, buf); + } + + if (orig_tz) + setenv("TZ", orig_tz, 1); + else + unsetenv("TZ"); + +} + static const struct log_info_cat smpp_mirror_default_categories[] = { [DSMPP] = { .name = "DSMPP", @@ -85,5 +119,7 @@ int main(int argc, char **argv) log_set_print_category_hex(osmo_stderr_target, 0); test_coding_scheme(); + test_smpp_parse_time_format(); + return EXIT_SUCCESS; } diff --git a/tests/smpp/smpp_test.ok b/tests/smpp/smpp_test.ok index fd44804d1..feb75a6ed 100644 --- a/tests/smpp/smpp_test.ok +++ b/tests/smpp/smpp_test.ok @@ -1 +1,9 @@ Testing coding scheme support +Testing SMPP time format parser +'': 0 == 1970-01-01 00:00:00 +'220517175524000+': 1652810124 == 2022-05-17 17:55:24 +'220517175524000-': 1652810124 == 2022-05-17 17:55:24 +'220517175524004+': 1652806524 == 2022-05-17 16:55:24 +'220517175524004-': 1652813724 == 2022-05-17 18:55:24 +'000000010000000R': 1652749200 == 2022-05-17 01:00:00 +'000001000000000R': 1652832000 == 2022-05-18 00:00:00 diff --git a/tests/sms_queue/Makefile.am b/tests/sms_queue/Makefile.am index 80189c793..055a22902 100644 --- a/tests/sms_queue/Makefile.am +++ b/tests/sms_queue/Makefile.am @@ -12,9 +12,16 @@ AM_CFLAGS = \ $(LIBOSMOABIS_CFLAGS) \ $(LIBOSMOSIGTRAN_CFLAGS) \ $(LIBOSMORANAP_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ $(LIBASN1C_CFLAGS) \ $(LIBOSMOMGCPCLIENT_CFLAGS) \ $(LIBOSMOGSUPCLIENT_CFLAGS) \ + $(LIBSQLITE3_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -no-install \ $(NULL) EXTRA_DIST = \ @@ -22,18 +29,18 @@ EXTRA_DIST = \ sms_queue_test.err \ $(NULL) -noinst_PROGRAMS = \ +check_PROGRAMS = \ sms_queue_test \ $(NULL) sms_queue_test_SOURCES = \ sms_queue_test.c \ + $(srcdir)/../stubs.c \ $(NULL) sms_queue_test_LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libvlr/libvlr.a \ - $(LIBSMPP34_LIBS) \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOVTY_LIBS) \ @@ -43,10 +50,11 @@ sms_queue_test_LDADD = \ $(LIBASN1C_LIBS) \ $(LIBOSMOMGCPCLIENT_LIBS) \ $(LIBOSMOGSUPCLIENT_LIBS) \ + $(LIBSQLITE3_LIBS) \ $(LIBRARY_GSM) \ - -ldbi \ $(NULL) sms_queue_test_LDFLAGS = \ -Wl,--wrap=db_sms_get_next_unsent_rr_msisdn \ + $(AM_LDFLAGS) \ $(NULL) diff --git a/tests/sms_queue/sms_queue_test.c b/tests/sms_queue/sms_queue_test.c index f681657aa..cc78e1491 100644 --- a/tests/sms_queue/sms_queue_test.c +++ b/tests/sms_queue/sms_queue_test.c @@ -277,24 +277,3 @@ int main(int argc, char **argv) return 0; } - -void osmo_stream_srv_link_set_data(struct osmo_stream_srv_link *link, void *data) {} -struct osmo_fd *osmo_stream_srv_get_ofd(struct osmo_stream_srv *srv) { return NULL; } -void osmo_stream_srv_destroy(struct osmo_stream_srv *conn) {} -struct osmo_stream_srv *osmo_stream_srv_create(void *ctx, struct osmo_stream_srv_link *link, - int fd, int (*cb)(struct osmo_stream_srv *conn), - int (*closed_cb)(struct osmo_stream_srv *conn), - void *data) { return NULL; } -void osmo_stream_srv_send(struct osmo_stream_srv *conn, struct msgb *msg) {} -void osmo_stream_srv_link_set_proto(struct osmo_stream_srv_link *link, uint16_t proto) {} -struct osmo_fd *osmo_stream_srv_link_get_ofd(struct osmo_stream_srv_link *link) { return NULL; } -struct osmo_stream_srv_link *osmo_stream_srv_link_create(void *ctx) { return NULL; } -void *osmo_stream_srv_get_data(struct osmo_stream_srv *conn) { return NULL; } -void osmo_stream_srv_link_set_nodelay(struct osmo_stream_srv_link *link, bool nodelay) {} -void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, int (*accept_cb) - (struct osmo_stream_srv_link *link, int fd)) {} -int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link) { return 0; } -void *osmo_stream_srv_link_get_data(struct osmo_stream_srv_link *link) { return NULL; } -void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, uint16_t port) {} -void osmo_stream_srv_link_set_addr(struct osmo_stream_srv_link *link, const char *addr) {} -int sctp_recvmsg(int sd, void *msg, size_t len, void *from, void *fromlen, void *info, int *msg_flags) { return 0; } diff --git a/tests/stubs.c b/tests/stubs.c index d011a312a..f4ccb48c7 100644 --- a/tests/stubs.c +++ b/tests/stubs.c @@ -37,7 +37,17 @@ void osmo_stream_srv_link_set_nodelay(struct osmo_stream_srv_link *link, bool no void osmo_stream_srv_link_set_accept_cb(struct osmo_stream_srv_link *link, int (*accept_cb) (struct osmo_stream_srv_link *link, int fd)) {} int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link) { return 0; } +void osmo_stream_srv_link_close(struct osmo_stream_srv_link *link) {} void *osmo_stream_srv_link_get_data(struct osmo_stream_srv_link *link) { return NULL; } +char *osmo_stream_srv_link_get_sockname(const struct osmo_stream_srv_link *link) { return NULL; } void osmo_stream_srv_link_set_port(struct osmo_stream_srv_link *link, uint16_t port) {} void osmo_stream_srv_link_set_addr(struct osmo_stream_srv_link *link, const char *addr) {} int sctp_recvmsg(int sd, void *msg, size_t len, void *from, void *fromlen, void *info, int *msg_flags) { return 0; } +struct gsm_sms; +struct msc_a; +struct gsm_trans; +struct smpp_esme; +bool smpp_route_smpp_first() { return false; } +void smpp_esme_put(struct smpp_esme *esme) { return; } +int smpp_try_deliver(struct gsm_sms *sms, struct msc_a *msc_a) { return 0; } +int sms_route_mt_sms(struct gsm_trans *trans, struct gsm_sms *gsms) { return 0; } diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty index 14f15a200..5e4b793b1 100644 --- a/tests/test_nodes.vty +++ b/tests/test_nodes.vty @@ -5,6 +5,8 @@ OsmoMSC(config)# list network msc sgs + smsc + asci mncc-int hlr ... @@ -14,8 +16,8 @@ OsmoMSC(config-net)# list ... network country code <1-999> mobile network code <0-999> - short name NAME - long name NAME + short name .NAME + long name .NAME encryption a5 <0-4> [<0-4>] [<0-4>] [<0-4>] [<0-4>] encryption uea <0-2> [<0-2>] [<0-2>] authentication (optional|required) @@ -26,6 +28,8 @@ OsmoMSC(config-net)# list no timezone call-waiting no call-waiting + mgw <0-255> + no mgw <0-255> OsmoMSC(config-net)# encryption? encryption Encryption options @@ -46,7 +50,6 @@ OsmoMSC(config-net)# exit OsmoMSC(config)# msc OsmoMSC(config-msc)# list ... - sms-database PATH assign-tmsi lcls-permitted no lcls-permitted @@ -73,10 +76,6 @@ OsmoMSC(config-msc)# list neighbor (a|iu) cgi <0-999> <0-999> <0-65535> <0-65535> (ran-pc|msc-ipa-name) RAN_PC_OR_MSC_IPA_NAME no neighbor (a|iu) (ran-pc|msc-ipa-name) RAN_PC_OR_MSC_IPA_NAME timer [(vlr|mgw|mncc|sccp|geran|utran|sgs)] [TNNNN] [(<0-2147483647>|default)] - mgw local-ip (A.B.C.D|X:X::X:X) - mgw local-port <0-65535> - mgw remote-ip (A.B.C.D|X:X::X:X) - mgw remote-port <0-65535> ... OsmoMSC(config-msc)# ncss? @@ -100,12 +99,16 @@ OsmoMSC(config-msc)# mncc external /path/not/used OsmoMSC(config-msc)# show running-config ... msc -... +... ! mncc internal mncc external /path/not/used -... +... ! mncc internal OsmoMSC(config-msc)# mncc internal OsmoMSC(config-msc)# show running-config +... +msc +... ! mncc external + mncc internal ... ! mncc external OsmoMSC(config-msc)# exit @@ -156,7 +159,9 @@ network authentication optional rrlp mode none mm info 1 +... msc + mncc internal mncc guard-timeout 180 ncss guard-timeout 30 assign-tmsi @@ -164,9 +169,6 @@ msc ... auth-tuple-max-reuse-count 3 auth-tuple-reuse-on-error 1 - mgw local-port 2728 - mgw remote-ip 127.0.0.1 - mgw remote-port 2427 mncc-int default-codec tch-f fr default-codec tch-h hr @@ -174,10 +176,21 @@ mncc-int hlr remote-ip 127.0.0.1 remote-port 4222 + ipa-name unnamed-MSC sgs local-port 29118 local-ip 0.0.0.0 vlr-name vlr.example.net +smsc + queue max-pending 20 + queue max-failure 1 + database delete-delivered 1 + database delete-expired 1 + validity-period minimum 1 + validity-period default 10080 +asci + disable + gcr end OsmoMSC# configure terminal diff --git a/tests/testsuite.at b/tests/testsuite.at index 58855f817..fbf594b48 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -121,3 +121,10 @@ cat $abs_srcdir/mncc/mncc_test.ok > expout cat $abs_srcdir/mncc/mncc_test.err > experr AT_CHECK([$abs_top_builddir/tests/mncc/mncc_test], [], [expout], [experr]) AT_CLEANUP + +AT_SETUP([csd_test]) +AT_KEYWORDS([csd_test]) +cat $abs_srcdir/csd/csd_test.ok > expout +cat $abs_srcdir/csd/csd_test.err > experr +AT_CHECK([$abs_top_builddir/tests/csd/csd_test], [], [expout], [experr]) +AT_CLEANUP diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py index 242114467..2dfa15534 100755 --- a/tests/vty_test_runner.py +++ b/tests/vty_test_runner.py @@ -65,7 +65,9 @@ class TestVTYBase(unittest.TestCase): if self.vty: self.vty._close_socket() self.vty = None - osmoutil.end_proc(self.proc) + rc = osmoutil.end_proc(self.proc) + if rc is not None and rc != 0: + raise Exception("Process returned %d" % rc) class TestVTYMSC(TestVTYBase): |