neels has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24411 )

Change subject: add bsc/BSC_Tests_VAMOS.ttcn
......................................................................

add bsc/BSC_Tests_VAMOS.ttcn

BSC_Tests_VAMOS.ttcn is separate from BSC_Tests.ttcn in order to
instruct osmo-bts-omldummy to pass BTS_FEAT_VAMOS == true in the OML BTS
attributes.

Add tests:
TC_chan_act_to_vamos()
TC_mode_modify_to_vamos_fr()
TC_mode_modify_to_vamos_hr()
TC_assign_to_secondary_lchan_fr()
TC_assign_to_secondary_lchan_hr()
TC_vamos_multiplex_tch_f_tch_f()
TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h()

Change-Id: I2c504099163a30ea102cbd26d3615ca2e5ce1e64
---
M bsc/BSC_Tests.ttcn
A bsc/BSC_Tests_VAMOS.ttcn
M library/L3_Templates.ttcn
M library/RSL_Types.ttcn
4 files changed, 859 insertions(+), 6 deletions(-)

Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 2b3703f..41deea1 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -20,6 +20,8 @@
  * level testing.
  */

+friend module BSC_Tests_VAMOS;
+
 import from Misc_Helpers all;
 import from General_Types all;
 import from Osmocom_Types all;
@@ -673,7 +675,7 @@
        uint8_t mp_exp_ms_power_level := 7;
 }

-private function f_gen_test_hdlr_pars(integer bssap_idx := 0) return 
TestHdlrParams {
+friend function f_gen_test_hdlr_pars(integer bssap_idx := 0) return 
TestHdlrParams {

        var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
        if (mp_bssap_cfg[bssap_idx].transport == BSSAP_TRANSPORT_AoIP) {
@@ -799,7 +801,7 @@
 }


-private function f_shutdown_helper() runs on test_CT {
+friend function f_shutdown_helper() runs on test_CT {
        all component.stop;
        setverdict(pass);
        mtc.stop;
@@ -1001,7 +1003,7 @@
                          "sccp-timer iar " & int2str(g_bsc_sccp_timer_iar)});
 }

-private function f_logp(TELNETasp_PT pt, charstring log_msg)
+friend function f_logp(TELNETasp_PT pt, charstring log_msg)
 {
        // log on TTCN3 log output
        log(log_msg);
@@ -6602,7 +6604,7 @@
        }
 }

-private function f_perform_clear(RSL_DCHAN_PT rsl, template PDU_ML3_NW_MS 
exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
+friend function f_perform_clear(RSL_DCHAN_PT rsl, template PDU_ML3_NW_MS 
exp_rr_rel_tmpl := tr_RRM_RR_RELEASE)
 runs on MSC_ConnHdlr {
        f_logp(BSCVTY, "MSC instructs BSC to clear channel");
        BSSAP.send(ts_BSSMAP_ClearCommand(0));
diff --git a/bsc/BSC_Tests_VAMOS.ttcn b/bsc/BSC_Tests_VAMOS.ttcn
new file mode 100644
index 0000000..bf487cf
--- /dev/null
+++ b/bsc/BSC_Tests_VAMOS.ttcn
@@ -0,0 +1,738 @@
+module BSC_Tests_VAMOS {
+
+/* Integration Tests for OsmoBSC
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <[email protected]>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This test suite tests OsmoBSC while emulating both multiple BTS + MS as
+ * well as the MSC. See README for more details.
+ *
+ * There are test cases that run in so-called 'handler mode' and test cases
+ * that run directly on top of the BSSAP and RSL CodecPorts.  The "handler 
mode"
+ * tests abstract the multiplexing/demultiplexing of multiple SCCP connections
+ * and/or RSL channels and are hence suitable for higher-level test cases, 
while
+ * the "raw" tests directly on top of the CodecPorts are more suitable for 
lower-
+ * level testing.
+ */
+
+import from BSC_Tests all;
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from GSM_Types all;
+import from IPL4asp_Types all;
+
+import from BSSAP_Types all;
+import from RAN_Adapter all;
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
+import from BSSAP_LE_Types all;
+import from BSSLAP_Types all;
+import from BSSAP_CodecPort all;
+import from BSSMAP_Templates all;
+import from IPA_Emulation all;
+import from IPA_CodecPort all;
+import from IPA_Types all;
+import from IPA_Testing all;
+import from RSL_Types all;
+import from RSL_Emulation all;
+import from MGCP_Emulation all;
+import from MGCP_Templates all;
+import from MGCP_Types all;
+import from MGCP_CodecPort all;
+
+import from Osmocom_CTRL_Functions all;
+import from Osmocom_CTRL_Types all;
+import from Osmocom_CTRL_Adapter all;
+
+import from StatsD_Types all;
+import from StatsD_CodecPort all;
+import from StatsD_CodecPort_CtrlFunct all;
+import from StatsD_Checker all;
+
+import from Osmocom_VTY_Functions all;
+import from TELNETasp_PortType all;
+
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_Types all;
+import from MobileL3_RRM_Types all;
+import from L3_Templates all;
+import from GSM_RR_Types all;
+
+import from SCCP_Templates all;
+import from BSSMAP_Templates all;
+import from BSSMAP_LE_Templates all;
+
+import from SCCPasp_Types all;
+
+import from GSM_SystemInformation all;
+import from GSM_RestOctets all;
+import from TCCConversion_Functions all;
+
+import from RAN_Emulation all;
+import from MSC_ConnectionHandler all;
+
+import from Native_Functions all;
+
+const integer NUM_BTS := 3;
+const integer NUM_MSC := 3;
+
+private function f_rsl_chan_nr_to_subslot(RslChannelNr chan_nr)
+return integer
+{
+       var integer subslot;
+       select (chan_nr) {
+               case (t_RslChanNr_Bm(?)) {
+                       /* TCH/F, always subslot 0 */
+                       subslot := 0;
+               }
+               case (t_RslChanNr_Lm(?, ?)) {
+                       /* TCH/H */
+                       subslot := chan_nr.u.lm.sub_chan;
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+                       /* TCH/F, always subslot 0 */
+                       subslot := 0;
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+                       /* TCH/H */
+                       subslot := chan_nr.u.lm.sub_chan;
+               }
+               case else {
+                       setverdict(fail, "unsupported RslChannelNr type in 
f_rsl_chan_nr_to_subslot()");
+                       mtc.stop;
+               }
+       }
+       return subslot;
+}
+
+private function f_rsl_chan_nr_to_rsl_cbits(RslChannelNr chan_nr)
+return BIT5
+{
+       var BIT5 rsl_cbits;
+       select (chan_nr) {
+               case (t_RslChanNr_Bm(?)) {
+                       rsl_cbits := '00001'B;
+               }
+               case (t_RslChanNr_Lm(?, ?)) {
+                       rsl_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* 
'0001x'B */
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+                       rsl_cbits := '11101'B;
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+                       rsl_cbits := int2bit(30 + chan_nr.u.lm.sub_chan, 5); /* 
'1111x'B */
+               }
+               case else {
+                       setverdict(fail, "unsupported RslChannelNr type in 
f_rsl_chan_nr_to_rsl_cbits()");
+                       mtc.stop;
+               }
+       }
+       return rsl_cbits;
+}
+
+private function f_rsl_chan_nr_to_rr_cbits(RslChannelNr chan_nr)
+return BIT5
+{
+       var BIT5 rr_cbits;
+       select (chan_nr) {
+               case (t_RslChanNr_Bm(?)) {
+                       rr_cbits := '00001'B;
+               }
+               case (t_RslChanNr_Lm(?, ?)) {
+                       rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* 
'0001x'B */
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+                       rr_cbits := '00001'B;
+                       /* In RR, there must *not* be Osmocom specific cbits */
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+                       rr_cbits := int2bit(2 + chan_nr.u.lm.sub_chan, 5); /* 
'0001x'B */
+                       /* In RR, there must *not* be Osmocom specific cbits */
+               }
+               case else {
+                       setverdict(fail, "unsupported RslChannelNr type in 
f_rsl_chan_nr_to_rr_cbits()");
+                       mtc.stop;
+               }
+       }
+       return rr_cbits;
+}
+
+private function f_rsl_chan_nr_to_chrt(RslChannelNr chan_nr, boolean vamos)
+return RSL_ChanRateType
+{
+       var boolean fr;
+       select (chan_nr) {
+               case (t_RslChanNr_Bm(?)) {
+                       fr := true;
+               }
+               case (t_RslChanNr_Lm(?, ?)) {
+                               fr := false;
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Bm(?)) {
+                       fr := true;
+               }
+               case (t_RslChanNr_Osmo_VAMOS_Lm(?, ?)) {
+                               fr := false;
+               }
+               case else {
+                       setverdict(fail, "unsupported RslChannelNr type in 
f_rsl_chan_nr_to_chrt()");
+                       mtc.stop;
+               }
+       }
+       if (fr) {
+               if (vamos) {
+                       return RSL_CHRT_OSMO_TCH_F_VAMOS;
+               } else {
+                       return RSL_CHRT_TCH_F;
+               }
+       } else {
+               if (vamos) {
+                       return RSL_CHRT_OSMO_TCH_H_VAMOS;
+               } else {
+                       return RSL_CHRT_TCH_H;
+               }
+       }
+}
+
+private function f_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr 
chan_nr)
+return charstring
+{
+       var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr);
+       return "lchan " & int2str(bts_nr) & " " & int2str(trx_nr) & " " & 
int2str(chan_nr.tn) & " " & int2str(subslot);
+}
+
+private function f_long_lchan_str(integer bts_nr, integer trx_nr, RslChannelNr 
chan_nr)
+return charstring
+{
+       var integer subslot := f_rsl_chan_nr_to_subslot(chan_nr);
+       return "bts " & int2str(bts_nr) & " trx " & int2str(trx_nr) & " 
timeslot " & int2str(chan_nr.tn) & " sub-slot " & int2str(subslot);
+}
+
+private function f_lchan_ensure_established(TELNETasp_PT vty, integer bts_nr, 
integer trx_nr, RslChannelNr chan_nr)
+{
+       var charstring lchan_str := f_lchan_str(bts_nr, trx_nr, chan_nr);
+       var charstring lchan_info := f_vty_transceive_ret(vty, "show " & 
lchan_str);
+       if (f_strstr(lchan_info, "State: ESTABLISHED") < 0) {
+               log("'show lchan' replied: ", lchan_info);
+               setverdict(fail, "lchan " & lchan_str & " is not in state 
ESTABLISHED");
+               mtc.stop;
+       }
+       setverdict(pass);
+}
+
+/* Activate a primary lchan in VAMOS speech mode */
+testcase TC_chan_act_to_vamos() runs on test_CT {
+       f_init_vty();
+
+       f_logp(BSCVTY, "TC_chan_act_to_vamos");
+
+       f_init(1, false);
+       f_sleep(1.0);
+
+       f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot 1 sub-slot 0 
activate-vamos fr");
+
+       var RSL_Message rsl;
+
+       rsl := f_exp_ipa_rx(0, tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV));
+
+       var RSL_IE_Body chan_mode_ie;
+       if (f_rsl_find_ie(rsl, RSL_IE_CHAN_MODE, chan_mode_ie) == false) {
+               setverdict(fail, "Cannot find RSL_IE_CHAN_MODE");
+               mtc.stop;
+       }
+       if (chan_mode_ie.chan_mode.ch_rate_type != RSL_CHRT_OSMO_TCH_F_VAMOS) {
+               setverdict(fail, "expected chan_mode.ch_rate_type == 
RSL_CHRT_OSMO_TCH_F_VAMOS");
+               mtc.stop;
+       }
+
+       var RSL_IE_Body osmo_tsc_ie;
+       if (f_rsl_find_ie(rsl, RSL_IE_OSMO_TRAINING_SEQUENCE, osmo_tsc_ie) == 
false) {
+               setverdict(fail, "Cannot find RSL_IE_OSMO_TRAINING_SEQUENCE");
+               mtc.stop;
+       }
+
+       var RslChannelNr chan_nr := rsl.ies[0].body.chan_nr;
+       f_ipa_tx(0, ts_RSL_CHAN_ACT_ACK(chan_nr, 23+10));
+
+       f_sleep(1.0);
+       f_lchan_ensure_established(BSCVTY, 0, 0, chan_nr);
+
+       f_shutdown_helper();
+}
+
+/* verify that DTAP passes through both ways with the right cbits */
+private function f_verify_dtap() runs on MSC_ConnHdlr
+{
+       var octetstring l3_data := '00010203040506'O;
+       var PDU_BSSAP rx_bssap_dtap;
+
+       /* MS to NW */
+       RSL.send(ts_RSL_DATA_IND(g_chan_nr, valueof(ts_RslLinkID_DCCH(0)), 
l3_data));
+       BSSAP.receive(tr_BSSAP_DTAP) -> value rx_bssap_dtap;
+       if (not match(rx_bssap_dtap.pdu.dtap, l3_data)) {
+               setverdict(fail, "unexpected L3 data");
+               mtc.stop;
+       }
+
+       /* NW to MS */
+       l3_data := '0800dcba9876543210'O;
+       BSSAP.send(ts_BSSAP_DTAP(l3_data, '00'O));
+       RSL.receive(tr_RSL_DATA_REQ(g_chan_nr, tr_RslLinkID_DCCH(0), l3_data));
+}
+
+
+private function f_est_lchan_and_mode_modify_to_vamos() runs on MSC_ConnHdlr {
+       var PDU_BSSAP ass_cmd := f_gen_ass_req(g_pars.use_osmux);
+       var template PDU_BSSAP exp_compl := f_gen_exp_compl(g_pars.use_osmux);
+
+       /* puzzle together the ASSIGNMENT REQ for given codec[s] */
+       if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+               ass_cmd.pdu.bssmap.assignmentRequest.codecList := 
g_pars.ass_codec_list;
+               
exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+                                                               
g_pars.ass_codec_list.codecElements[0];
+               if (isvalue(g_pars.expect_mr_s0_s7)) {
+                       
exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+                                                               
g_pars.expect_mr_s0_s7;
+               }
+       }
+       ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+                               
f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+       log("expecting ASS COMPL like this: ", exp_compl);
+
+       f_establish_fully(ass_cmd, exp_compl);
+
+       f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+
+       var charstring current_long_lchan_str := f_long_lchan_str(0, 0, 
g_chan_nr);
+       f_vty_transceive(BSCVTY, current_long_lchan_str & " modify vamos tsc 2 
3");
+
+       var RSL_Message rsl_rr;
+       RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl_rr;
+
+       var PDU_ML3_NW_MS l3 := 
dec_PDU_ML3_NW_MS(rsl_rr.ies[2].body.l3_info.payload);
+
+       var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+       template PDU_ML3_NW_MS expect_rr_modify := tr_RRM_ModeModify(
+               tr_ChannelDescription2_V(timeslotNumber := 
int2bit(g_chan_nr.tn, 3)),
+               tr_ChannelMode_V(mode := 'C1'O /* 1 1 0 0 0 0 0 1 speech full 
rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
+               extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet := 
'01'B));
+
+       if (not match(l3, expect_rr_modify)) {
+               log("expected: ", expect_rr_modify);
+               log("got: ", l3);
+               setverdict(fail, "RR channelModeModify message is not as 
expected");
+               mtc.stop;
+       }
+       
f_rsl_reply(ts_RRM_ModeModifyAck(l3.msgs.rrm.channelModeModify.channelDescription,
+                                        
l3.msgs.rrm.channelModeModify.channelMode,
+                                        
l3.msgs.rrm.channelModeModify.extendedTSCSet), rsl_rr);
+
+       var RSL_Message rsl;
+       RSL.receive(tr_RSL_MODE_MODIFY_REQ_with_OSMO_TSC(g_chan_nr, 
tr_RSL_ChanMode(f_rsl_chan_nr_to_chrt(g_chan_nr, true), RSL_CMOD_SP_GSM1),
+                           tsc_set := 1, /* 1 means TSC Set 2 (range 1-4 in 
spec tables and naming, 0-3 on the wire) */
+                           tsc := 3));
+       RSL.send(ts_RSL_MODE_MODIFY_ACK(g_chan_nr));
+       f_sleep(1.0);
+
+       f_lchan_ensure_established(BSCVTY, 0, 0, g_chan_nr);
+       f_verify_dtap();
+}
+
+private function f_TC_mode_modify_to_vamos(charstring id) runs on MSC_ConnHdlr 
{
+       f_est_lchan_and_mode_modify_to_vamos();
+}
+
+/* Modify a primary lchan into VAMOS speech mode */
+testcase TC_mode_modify_to_vamos_fr() runs on test_CT {
+       var TestHdlrParams pars := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+       vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
+       vc_conn.done;
+       f_shutdown_helper();
+}
+
+/* Modify a primary lchan into VAMOS speech mode */
+testcase TC_mode_modify_to_vamos_hr() runs on test_CT {
+       var TestHdlrParams pars := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+       vc_conn := f_start_handler(refers(f_TC_mode_modify_to_vamos), pars);
+       vc_conn.done;
+       f_shutdown_helper();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow 
lchan. */
+private function f_reassign_secondary_to_primary_lchan(RslChannelNr 
new_chan_nr) runs on MSC_ConnHdlr
+{
+       var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+       var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
+       var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
+
+       activate(as_Media_mgw());
+
+       f_rslem_register(0, new_chan_nr, RSL_PROC);
+       log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
+
+       f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & 
int2str(g_chan_nr.tn) & " vamos-sub-slot " & int2str(current_subslot)
+                        & " reassign-to trx 0 timeslot " & 
int2str(new_chan_nr.tn) & " sub-slot " & int2str(new_subslot));
+       /* RSL CHAN ACT is ACKed by RSL emulation */
+
+       var RSL_Message rsl;
+       var RSL_IE_Body ie;
+       var boolean b_unused;
+       interleave {
+       [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+               var PDU_ML3_NW_MS l3 := 
dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+               var template PDU_ML3_NW_MS expect_rr_assignment := 
tr_RR_AssignmentCommand(
+                       desc := tr_ChannelDescription2_V(timeslotNumber := 
int2bit(new_chan_nr.tn, 3),
+                                       channelTypeandTDMAOffset := 
new_rr_cbits),
+                       mode := tr_ChannelMode_TV(mode := '01'O
+                                                 /* 0 0 0 0 0 0 0 1 speech 
full rate or half rate version 1 (3GPP TS 44.018) */),
+                       extendedTSCSet := omit);
+               if (not match(l3, expect_rr_assignment)) {
+                       log("expected: ", expect_rr_assignment);
+                       log("got: ", l3);
+                       setverdict(fail, "RR assignmentCommand message is not 
as expected");
+                       mtc.stop;
+               }
+
+               var PDU_ML3_MS_NW l3_tx := 
valueof(ts_RRM_AssignmentComplete('00'O));
+               RSL.send(ts_RSL_EST_IND(new_chan_nr, 
valueof(ts_RslLinkID_DCCH(0)),
+                                       enc_PDU_ML3_MS_NW(l3_tx)));
+
+               }
+       [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
+               var uint7_t rtp_pt := 0;
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       rtp_pt := ie.ipa_rtp_pt;
+               }
+               RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
+                                               oct2int(f_inet_addr("1.2.3.4")),
+                                               4321,
+                                               rtp_pt));
+               }
+       [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
+               /* Extract conn_id, ip, port, rtp_pt2 from request + use in 
response */
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+               var uint16_t conn_id := ie.ipa_conn_id;
+               /* mandatory */
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+               var HostPort peer;
+               peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+               peer.port_nr := ie.ipa_remote_port;
+               var uint7_t rtp_pt := 0;
+               /* optional */
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       rtp_pt := ie.ipa_rtp_pt;
+               }
+               RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
+                                               oct2int(f_inet_addr(peer.host)),
+                                               peer.port_nr,
+                                               rtp_pt));
+               }
+       [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+       [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+               /*
+               RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
+                                      IPAC_PROTO_RSL_TRX0));
+               */
+               f_rslem_unregister(0, g_chan_nr, RSL_PROC);
+               g_chan_nr := new_chan_nr;
+               }
+       /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
+       }
+
+       setverdict(pass);
+
+       f_sleep(1.0);
+       f_vty_transceive(BSCVTY, "show lchan summary");
+
+       f_verify_dtap();
+}
+
+private function f_est_and_reassign_to_secondary_lchan(RslChannelNr 
new_chan_nr) runs on MSC_ConnHdlr
+{
+       var integer new_subslot := f_rsl_chan_nr_to_subslot(new_chan_nr);
+       var BIT5 new_rr_cbits := f_rsl_chan_nr_to_rr_cbits(new_chan_nr);
+
+       var PDU_BSSAP ass_cmd := f_gen_ass_req();
+       var template PDU_BSSAP exp_compl := f_gen_exp_compl();
+
+       /* puzzle together the ASSIGNMENT REQ for given codec[s] */
+       if (mp_bssap_cfg[0].transport == BSSAP_TRANSPORT_AoIP) {
+               ass_cmd.pdu.bssmap.assignmentRequest.codecList := 
g_pars.ass_codec_list;
+               
exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0] :=
+                                                               
g_pars.ass_codec_list.codecElements[0];
+               if (isvalue(g_pars.expect_mr_s0_s7)) {
+                       
exp_compl.pdu.bssmap.assignmentComplete.speechCodec.codecElements[0].s0_7 :=
+                                                               
g_pars.expect_mr_s0_s7;
+               }
+       }
+       ass_cmd.pdu.bssmap.assignmentRequest.channelType :=
+                               
f_BSSMAP_chtype_from_codec(g_pars.ass_codec_list.codecElements[0]);
+       log("expecting ASS COMPL like this: ", exp_compl);
+
+       f_establish_fully(ass_cmd, exp_compl);
+
+       var integer current_subslot := f_rsl_chan_nr_to_subslot(g_chan_nr);
+
+       f_sleep(1.0);
+
+       activate(as_Media_mgw());
+
+       f_rslem_register(0, new_chan_nr, RSL_PROC);
+       log("f_rslem_register(0, new_chan_nr = ", new_chan_nr, ")");
+
+       f_vty_transceive(BSCVTY, "bts 0 trx 0 timeslot " & 
int2str(g_chan_nr.tn) & " sub-slot " & int2str(current_subslot)
+                        & " reassign-to trx 0 timeslot " & 
int2str(new_chan_nr.tn) & " vamos-sub-slot " & int2str(new_subslot) & " tsc 4 
2");
+       /* RSL CHAN ACT is ACKed by RSL emulation */
+
+       var RSL_Message rsl;
+       var RSL_IE_Body ie;
+       var boolean b_unused;
+       interleave {
+       [] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> value rsl {
+               var PDU_ML3_NW_MS l3 := 
dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+               var template PDU_ML3_NW_MS expect_rr_assignment := 
tr_RR_AssignmentCommand(
+                       desc := tr_ChannelDescription2_V(timeslotNumber := 
int2bit(new_chan_nr.tn, 3),
+                                                        
channelTypeandTDMAOffset := new_rr_cbits),
+                       mode := tr_ChannelMode_TV(mode := 'C1'O
+                                                 /* 1 1 0 0 0 0 0 1 speech 
full rate or half rate version 1 in VAMOS mode (3GPP TS 44.018) */),
+                       extendedTSCSet := tr_ExtendedTSCSet_TV(cSDomainTSCSet 
:= '11'B
+                                                              /* 3 means TSC 
Set 4 (range 1-4 in spec tables and naming, 0-3 on the wire) */));
+               if (not match(l3, expect_rr_assignment)) {
+                       log("expected: ", expect_rr_assignment);
+                       log("got: ", l3);
+                       setverdict(fail, "RR assignmentCommand message is not 
as expected");
+                       mtc.stop;
+               }
+
+               var PDU_ML3_MS_NW l3_tx := 
valueof(ts_RRM_AssignmentComplete('00'O));
+               RSL.send(ts_RSL_EST_IND(new_chan_nr, 
valueof(ts_RslLinkID_DCCH(0)),
+                                       enc_PDU_ML3_MS_NW(l3_tx)));
+
+               }
+       [] RSL.receive(tr_RSL_IPA_CRCX(new_chan_nr)) -> value rsl {
+               var uint7_t rtp_pt := 0;
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       rtp_pt := ie.ipa_rtp_pt;
+               }
+               RSL.send(ts_RSL_IPA_CRCX_ACK(new_chan_nr, 123,
+                                               oct2int(f_inet_addr("1.2.3.4")),
+                                               4321,
+                                               rtp_pt));
+               }
+       [] RSL.receive(tr_RSL_IPA_MDCX(new_chan_nr, ?)) -> value rsl{
+               /* Extract conn_id, ip, port, rtp_pt2 from request + use in 
response */
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+               var uint16_t conn_id := ie.ipa_conn_id;
+               /* mandatory */
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+               var HostPort peer;
+               peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 4));
+               b_unused := f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+               peer.port_nr := ie.ipa_remote_port;
+               var uint7_t rtp_pt := 0;
+               /* optional */
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       rtp_pt := ie.ipa_rtp_pt;
+               }
+               RSL.send(ts_RSL_IPA_MDCX_ACK(new_chan_nr, conn_id,
+                                               oct2int(f_inet_addr(peer.host)),
+                                               peer.port_nr,
+                                               rtp_pt));
+               }
+       [] RSL.receive(tr_RSL_DEACT_SACCH(g_chan_nr)) {}
+       [] RSL.receive(tr_RSL_RF_CHAN_REL(g_chan_nr)) {
+               /*
+               RSL.send(ts_ASP_RSL_UD(ts_RSL_RF_CHAN_REL_ACK(g_chan_nr),
+                                      IPAC_PROTO_RSL_TRX0));
+               */
+               f_rslem_unregister(0, g_chan_nr, RSL_PROC);
+               g_chan_nr := new_chan_nr;
+               }
+       /* (There must be no RSL_MT_REL_REQ on the old lchan.) */
+       }
+
+       setverdict(pass);
+
+       f_sleep(1.0);
+       f_vty_transceive(BSCVTY, "show lchan summary");
+
+       f_verify_dtap();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow 
lchan.
+ * Also re-assign back to a primary lchan. */
+private function f_TC_assign_to_secondary_lchan_fr(charstring id) runs on 
MSC_ConnHdlr {
+       
f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(2)));
+       f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Bm(3)));
+       f_perform_clear(RSL);
+       f_sleep(1.0);
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow 
lchan. */
+testcase TC_assign_to_secondary_lchan_fr() runs on test_CT {
+       var TestHdlrParams pars := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+       vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_fr), 
pars);
+       vc_conn.done;
+       f_shutdown_helper();
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow 
lchan.
+ * Also re-assign back to a primary lchan. */
+private function f_TC_assign_to_secondary_lchan_hr(charstring id) runs on 
MSC_ConnHdlr {
+       
f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(6, 0)));
+       f_reassign_secondary_to_primary_lchan(valueof(t_RslChanNr_Lm(6, 1)));
+       f_perform_clear(RSL);
+       f_sleep(1.0);
+}
+
+/* Establish a primary lchan, and then do a re-assignment to a VAMOS shadow 
lchan. */
+testcase TC_assign_to_secondary_lchan_hr() runs on test_CT {
+       var TestHdlrParams pars := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+       vc_conn := f_start_handler(refers(f_TC_assign_to_secondary_lchan_hr), 
pars);
+       vc_conn.done;
+       f_shutdown_helper();
+}
+
+/* First, primary lchan of TC_vamos_multiplex_tch_f_tch_f() */
+private function f_TC_vamos_multiplex_tch_f_tch_f1(charstring id) runs on 
MSC_ConnHdlr {
+       f_est_lchan_and_mode_modify_to_vamos();
+       f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+}
+
+/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_f_tch_f() */
+private function f_TC_vamos_multiplex_tch_f_tch_f2(charstring id) runs on 
MSC_ConnHdlr {
+       
f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Bm(1)));
+}
+
+/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
+ * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
+ * first primary lchan. */
+testcase TC_vamos_multiplex_tch_f_tch_f() runs on test_CT {
+       var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn1;
+
+       var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn2;
+       pars2.imsi := '001014234234234'H;
+       pars2.media_nr := 2;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+       pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+       vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f1), 
pars1);
+       vc_conn1.done;
+
+       vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_f_tch_f2), 
pars2);
+       vc_conn2.done;
+       f_shutdown_helper();
+}
+
+/* First, primary lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() */
+private function f_TC_vamos_multiplex_tch_h_tch_h1(charstring id) runs on 
MSC_ConnHdlr {
+       f_est_lchan_and_mode_modify_to_vamos();
+       f_logp(BSCVTY, "f_est_lchan_and_mode_modify_to_vamos done");
+}
+
+/* Second, VAMOS shadow lchan of TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() 
*/
+private function f_TC_vamos_multiplex_tch_h_tch_h2(charstring id) runs on 
MSC_ConnHdlr {
+       
f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 0)));
+}
+
+private function f_TC_vamos_multiplex_tch_h_tch_h4(charstring id) runs on 
MSC_ConnHdlr {
+       
f_est_and_reassign_to_secondary_lchan(valueof(t_RslChanNr_Osmo_VAMOS_Lm(5, 1)));
+}
+
+/* Establish a primary lchan and modify it to VAMOS speech mode. Then establish
+ * another primary lchan, and re-assign it to the VAMOS secondary lchan of the
+ * first primary lchan. */
+testcase TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() runs on test_CT {
+       var TestHdlrParams pars1 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn1;
+       pars1.imsi := '001011111111111'H;
+       pars1.media_nr := 1;
+
+       var TestHdlrParams pars2 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn2;
+       pars2.imsi := '001012222222222'H;
+       pars2.media_nr := 2;
+
+       var TestHdlrParams pars3 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn3;
+       pars3.imsi := '001013333333333'H;
+       pars3.media_nr := 3;
+
+       var TestHdlrParams pars4 := f_gen_test_hdlr_pars();
+       var MSC_ConnHdlr vc_conn4;
+       pars4.imsi := '001014444444444'H;
+       pars4.media_nr := 4;
+
+       f_init(1, true);
+       f_sleep(1.0);
+
+       pars1.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+       pars2.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+       pars3.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+       pars4.ass_codec_list := valueof(ts_BSSMAP_IE_CodecList({ts_CodecHR}));
+
+       vc_conn1 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h1), 
pars1);
+       vc_conn1.done;
+
+       vc_conn2 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h2), 
pars2);
+       vc_conn2.done;
+
+       /* Also fill up the second subslot of the TCH/H timeslot */
+       vc_conn3 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h1), 
pars3);
+       vc_conn3.done;
+
+       vc_conn4 := f_start_handler(refers(f_TC_vamos_multiplex_tch_h_tch_h4), 
pars4);
+       vc_conn4.done;
+       f_shutdown_helper();
+}
+
+control {
+       execute( TC_chan_act_to_vamos() );
+       execute( TC_mode_modify_to_vamos_fr() );
+       execute( TC_mode_modify_to_vamos_hr() );
+       execute( TC_assign_to_secondary_lchan_fr() );
+       execute( TC_assign_to_secondary_lchan_hr() );
+       execute( TC_vamos_multiplex_tch_f_tch_f() );
+       execute( TC_vamos_multiplex_tch_h_tch_h_tch_h_tch_h() );
+}
+
+}
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
index 5d688de..53731c0 100644
--- a/library/L3_Templates.ttcn
+++ b/library/L3_Templates.ttcn
@@ -530,7 +530,51 @@
        }
 }

-template (value) PDU_ML3_MS_NW ts_RRM_ModeModifyAck(ChannelDescription2_V 
desc, ChannelMode_V mode) := {
+template ChannelDescription2_V tr_ChannelDescription2_V(template BIT3 
timeslotNumber := ?,
+                                                       template BIT5 
channelTypeandTDMAOffset := ?) := {
+       timeslotNumber := timeslotNumber,
+       channelTypeandTDMAOffset := channelTypeandTDMAOffset,
+       octet3 := ?,
+       octet4 := ?
+}
+
+template ChannelMode_V tr_ChannelMode_V(template OCT1 mode) := {
+       mode := mode
+}
+
+template ExtendedTSCSet_TV tr_ExtendedTSCSet_TV(template BIT2 cSDomainTSCSet 
:= ?) := {
+       elementIdentifier := '6D'O,
+       cSDomainTSCSet := cSDomainTSCSet,
+       secondPSDomainTSCAssigned := ?,
+       primaryPSDomainTSCSet := ?,
+       secondaryPSDomainTSCSet := ?,
+       secondaryPSDomainTSCValue := ?
+}
+
+template PDU_ML3_NW_MS tr_RRM_ModeModify(template ChannelDescription2_V desc 
:= ?,
+                                        template ChannelMode_V mode := ?,
+                                        template ExtendedTSCSet_TV 
extendedTSCSet) := {
+       discriminator := '0110'B,
+       tiOrSkip := {
+               skipIndicator := '0000'B
+       },
+       msgs := {
+               rrm := {
+                       channelModeModify := {
+                               messageType := '00010000'B,
+                               channelDescription := desc,
+                               channelMode := mode,
+                               vGCS_TargetModeIndication := omit,
+                               multiRateConfiguration := omit,
+                               vGCS_Ciphering_Parameters := omit,
+                               extendedTSCSet := extendedTSCSet
+                       }
+               }
+       }
+}
+
+template (value) PDU_ML3_MS_NW ts_RRM_ModeModifyAck(ChannelDescription2_V 
desc, ChannelMode_V mode,
+                                                   template (omit) 
ExtendedTSCSet_TV extendedTSCSet := omit) := {
        discriminator := '0000'B, /* overwritten */
        tiOrSkip := {
                skipIndicator := '0000'B
@@ -541,7 +585,7 @@
                                messageType := '00010111'B,
                                channelDescription := desc,
                                channelMode := mode,
-                               extendedTSCSet := omit
+                               extendedTSCSet := extendedTSCSet
                        }
                }
        }
@@ -584,6 +628,57 @@
        }
 }

+template ChannelMode_TV tr_ChannelMode_TV(template OCT1 mode) := {
+       elementIdentifier := '63'O,
+       mode := mode
+}
+
+template (present) PDU_ML3_NW_MS tr_RR_AssignmentCommand(
+               template ChannelDescription2_V desc := ?,
+               template ChannelMode_TV mode := ?,
+               template ExtendedTSCSet_TV extendedTSCSet := omit
+) := {
+       discriminator := '0110'B,
+       tiOrSkip := {
+               skipIndicator := '0000'B
+       },
+       msgs := {
+               rrm := {
+                       assignmentCommand := {
+                               messageType := '00101110'B,
+                               descrOf1stChAfterTime := desc,
+                               PowerCommand := ?,
+                               frequencyList_at := omit,
+                               cellChannelDescr := omit,
+                               descrMultislotAllocation := omit,
+                               modeOf1stChannel := mode,
+                               channelSet2 := omit,
+                               channelSet3 := omit,
+                               channelSet4 := omit,
+                               channelSet5 := omit,
+                               channelSet6 := omit,
+                               channelSet7 := omit,
+                               channelSet8 := omit,
+                               descrOf2ndChAfterTime := omit,
+                               modeOf2ndChannel := omit,
+                               mobileAllocation_at := omit,
+                               startingTime := omit,
+                               frequencyList_bt := omit,
+                               descrOf1stCh_bt := omit,
+                               descrOf2ndCh_bt := omit,
+                               frequencyChannelSequence := omit,
+                               mobileAllocation_bt := omit,
+                               cipherModeSetting := omit,
+                               vGCS_TargetModeIndication := omit,
+                               multiRateConfiguration := omit,
+                               vGCS_Ciphering_Parameters := omit,
+                               extendedTSCSet_afterTime := extendedTSCSet,
+                               extendedTSCSet_beforeTime := omit
+                       }
+               }
+       }
+}
+
 template (value) PDU_ML3_MS_NW ts_RRM_AssignmentComplete(OCT1 cause) := {
        discriminator := '0000'B, /* overwritten */
        tiOrSkip := {
diff --git a/library/RSL_Types.ttcn b/library/RSL_Types.ttcn
index 16ce506..10284b8 100644
--- a/library/RSL_Types.ttcn
+++ b/library/RSL_Types.ttcn
@@ -1515,6 +1515,24 @@
                        *
                }
        }
+
+       template RSL_Message tr_RSL_MODE_MODIFY_REQ_with_OSMO_TSC(template 
RslChannelNr chan_nr,
+                                                                 template 
RSL_IE_ChannelMode mode,
+                                                                 template 
uint8_t tsc_set := ?,
+                                                                 template 
uint8_t tsc := ?) := {
+               msg_disc := tr_RSL_MsgDisc(RSL_MDISC_DCHAN, false),
+               msg_type := RSL_MT_MODE_MODIFY_REQ,
+               ies := {
+                   tr_RSL_IE(RSL_IE_Body:{chan_nr := chan_nr}),
+                   tr_RSL_IE(RSL_IE_Body:{chan_mode := mode}),
+                   tr_RSL_IE(RSL_IE_Body:{osmo_training_sequence := {
+                                                       len := ?,
+                                                       tsc_set := tsc_set,
+                                                       tsc := tsc
+                                                 }
+                                         })
+               }
+       };

        /* 8.4.10 BTS -> BSC */
        template (value) RSL_Message ts_RSL_MODE_MODIFY_ACK(template (value) 
RslChannelNr chan_nr) := {

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/24411
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: I2c504099163a30ea102cbd26d3615ca2e5ce1e64
Gerrit-Change-Number: 24411
Gerrit-PatchSet: 15
Gerrit-Owner: neels <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: neels <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to