Review at  https://gerrit.osmocom.org/6398

WIP: Intra-BSC handover testing

Change-Id: Ic47e639a7c8640c736c84a44780fc8e111a64b52
---
M bsc/BSC_Tests.ttcn
M bsc/MSC_ConnectionHandler.ttcn
M library/L3_Templates.ttcn
3 files changed, 203 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks 
refs/changes/98/6398/1

diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 9ab3b2c..cccec49 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -1277,6 +1277,8 @@
        connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC);
        connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT);
        connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC);
+       connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT);
+       connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC);
        connect(vc_conn:BSSAP, g_bssap.vc_BSSMAP:CLIENT);
        connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT);
        vc_conn.start(derefers(fn)(id));
@@ -1553,6 +1555,71 @@
        vc_conn.done;
 }
 
+/* execute a "bts <0-255> trx <0-255> timeslot <0-7> sub-slot <0-7>" command 
on given Dchan */
+private function f_vty_ss_action(charstring suffix, integer bts_nr, integer 
trx_nr, RslChannelNr chan_nr)
+runs on MSC_ConnHdlr {
+       /* FIXME: resolve those from component-global state */
+       var integer ts_nr := chan_nr.tn;
+       var integer ss_nr;
+       if (ischosen(chan_nr.u.ch0)) {
+               ss_nr := 0;
+       } else if (ischosen(chan_nr.u.lm)) {
+               ss_nr := chan_nr.u.lm.sub_chan;
+       } else if (ischosen(chan_nr.u.sdcch4)) {
+               ss_nr := chan_nr.u.sdcch4.sub_chan;
+       } else if (ischosen(chan_nr.u.sdcch8)) {
+               ss_nr := chan_nr.u.sdcch8.sub_chan;
+       } else {
+               setverdict(fail, "Invalid ChanNr ", chan_nr);
+               self.stop;
+       }
+
+       var charstring cmd := "bts "&int2str(bts_nr)&" trx "&int2str(trx_nr)&
+                               " timeslot "&int2str(ts_nr)&" sub-slot 
"&int2str(ss_nr)&" ";
+       f_vty_transceive(BSCVTY, cmd & suffix);
+}
+
+private function f_vty_handover(integer bts_nr, integer trx_nr, RslChannelNr 
chan_nr,
+                               integer new_bts_nr)
+runs on MSC_ConnHdlr {
+       f_vty_ss_action("handover " & int2str(new_bts_nr), bts_nr, trx_nr, 
chan_nr);
+}
+
+/* intra-BSC hand-over between BTS0 and BTS1 */
+private function f_tc_ho_int(charstring id) runs on MSC_ConnHdlr {
+       var TestHdlrParams pars := valueof(t_def_TestHdlrPars);
+       var template PDU_BSSAP exp_compl := tr_BSSMAP_AssignmentComplete(omit, 
?);
+       var BSSMAP_IE_AoIP_TransportLayerAddress tla := 
valueof(ts_BSSMAP_IE_AoIP_TLA4('01020304'O, 2342));
+       var PDU_BSSAP ass_cmd := valueof(ts_BSSMAP_AssignmentReq(omit, tla));
+       const OCT8 kc := '0001020304050607'O;
+
+       ass_cmd.pdu.bssmap.assignmentRequest.channelType := 
valueof(ts_BSSMAP_IE_ChannelType);
+       ass_cmd.pdu.bssmap.assignmentRequest.codecList := 
valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+
+       f_establish_fully(pars, ass_cmd, exp_compl);
+
+       var HandoverState hs := {
+               rr_ho_cmpl_seen := false,
+               handover_done := false,
+               old_chan_nr := -
+       };
+       /* issue hand-over command on VTY */
+       f_vty_handover(0, 0, g_chan_nr, 1);
+       /* temporarily suspend DChan processing on BTS1 to avoid race with 
RSLEM_register */
+       f_rslem_suspend(RSL1_PROC);
+       alt {
+       [] as_handover(hs);
+       /* FIXME: somehow determine that the hand-over has completed, by MGCP 
MDCX? */
+       }
+}
+
+testcase TC_ho_int() runs on test_CT {
+       var MSC_ConnHdlr vc_conn;
+       f_init(2, true);
+       f_sleep(1.0);
+       vc_conn := f_start_handler(refers(f_tc_ho_int), testcasename());
+       vc_conn.done;
+}
 
 
 control {
@@ -1623,6 +1690,7 @@
        execute( TC_unsol_ho_fail() );
        execute( TC_err_82_short_msg() );
        execute( TC_err_84_unknown_msg() );
+       execute( TC_ho_int() );
 }
 
 }
diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn
index 5f1095a..b68b4f8 100644
--- a/bsc/MSC_ConnectionHandler.ttcn
+++ b/bsc/MSC_ConnectionHandler.ttcn
@@ -62,7 +62,8 @@
 type record MediaState {
        MgcpEndpoint    mgcp_ep,
        MgcpConnState   mgcp_conn[2],
-       BtsMediaState   bts
+       BtsMediaState   bts,
+       BtsMediaState   bts1 /* only during hand-over */
 };
 
 function f_MediaState_init(inout MediaState g_media, integer nr, HostName bts, 
HostName mgw) {
@@ -73,6 +74,17 @@
                rtp_pt := 0,
                bts := {
                        host := bts,
+                       port_nr := 9000 + nr*2
+               },
+               peer := -
+       }
+
+       g_media.bts1 := {
+               ipa_crcx_seen := false,
+               conn_id := nr,
+               rtp_pt := 0,
+               bts := {
+                       host := bts, /* FIXME */
                        port_nr := 9000 + nr*2
                },
                peer := -
@@ -166,9 +178,54 @@
                                                
oct2int(f_inet_addr(g_media.bts.peer.host)),
                                                g_media.bts.peer.port_nr,
                                                g_media.bts.rtp_pt));
-               //g_media.ipa_mdcx_seen := true;
+               //g_media.bts.ipa_mdcx_seen := true;
                repeat;
                }
+
+       /* on second (new) BTS during hand-over */
+       [not g_media.bts1.ipa_crcx_seen] 
RSL1.receive(tr_RSL_IPA_CRCX(g_chan_nr)) -> value rsl {
+               /* Extract parameters from request + use in response */
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       g_media.bts1.rtp_pt := ie.ipa_rtp_pt;
+               }
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
+                       g_media.bts1.rtp_pt := ie.ipa_rtp_pt2;
+               }
+               RSL1.send(ts_RSL_IPA_CRCX_ACK(g_chan_nr, g_media.bts1.conn_id,
+                                               
oct2int(f_inet_addr(g_media.bts1.bts.host)),
+                                               g_media.bts1.bts.port_nr,
+                                               g_media.bts1.rtp_pt));
+               g_media.bts1.ipa_crcx_seen := true;
+               repeat;
+               }
+       /* on second (new) BTS during hand-over */
+       [g_media.bts1.ipa_crcx_seen] RSL1.receive(tr_RSL_IPA_MDCX(g_chan_nr, 
?)) -> value rsl{
+               /* Extract conn_id, ip, port, rtp_pt2 from request + use in 
response */
+               f_rsl_find_ie(rsl, RSL_IE_IPAC_CONN_ID, ie);
+               if (g_media.bts1.conn_id != ie.ipa_conn_id) {
+                       setverdict(fail, "IPA MDCX for unknown ConnId", rsl);
+                       self.stop;
+               }
+               /* mandatory */
+               f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_IP, ie);
+               g_media.bts1.peer.host := f_inet_ntoa(int2oct(ie.ipa_remote_ip, 
4));
+               f_rsl_find_ie(rsl, RSL_IE_IPAC_REMOTE_PORT, ie);
+               g_media.bts1.peer.port_nr := ie.ipa_remote_port;
+               /* optional */
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD, ie)) {
+                       g_media.bts1.rtp_pt := ie.ipa_rtp_pt;
+               }
+               if (f_rsl_find_ie(rsl, RSL_IE_IPAC_RTP_PAYLOAD2, ie)) {
+                       g_media.bts1.rtp_pt := ie.ipa_rtp_pt2;
+               }
+               RSL1.send(ts_RSL_IPA_MDCX_ACK(g_chan_nr, g_media.bts1.conn_id,
+                                               
oct2int(f_inet_addr(g_media.bts1.peer.host)),
+                                               g_media.bts1.peer.port_nr,
+                                               g_media.bts1.rtp_pt));
+               //g_media.bts1.ipa_mdcx_seen := true;
+               repeat;
+               }
+
        [] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
                var SDP_Message sdp;
                var integer cid := f_get_free_mgcp_conn();
@@ -219,7 +276,7 @@
                                                        
int2str(mgcp_conn.sample_rate))),
                                valueof(ts_SDP_ptime(mgcp_conn.ptime)) } ));
                MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, 
mgcp_conn.conn_id, sdp));
-               //mgcp_mdcx_seen := true;
+               //g_media.mgcp_mdcx_seen := true;
                repeat;
        }
 }
@@ -635,5 +692,61 @@
        return bssap;
 }
 
+type record HandoverState {
+       /* Assignment related bits */
+       boolean rr_ho_cmpl_seen,
+       boolean handover_done,
+       RslChannelNr old_chan_nr
+};
+
+altstep as_handover(inout HandoverState st) runs on MSC_ConnHdlr {
+       var RSL_Message rsl;
+       [not st.rr_ho_cmpl_seen] RSL.receive(tr_RSL_DATA_REQ(g_chan_nr)) -> 
value rsl {
+               var PDU_ML3_NW_MS l3 := 
dec_PDU_ML3_NW_MS(rsl.ies[2].body.l3_info.payload);
+               log("Rx L3 from net: ", l3);
+               if (ischosen(l3.msgs.rrm.handoverCommand)) {
+                       var RslChannelNr new_chan_nr;
+                       var GsmArfcn arfcn;
+                       
f_ChDesc2RslChanNr(l3.msgs.rrm.handoverCommand.channelDescription2,
+                                          new_chan_nr, arfcn);
+                       /* FIXME: Determine TRX NR by ARFCN, instead of 
hard-coded TRX0! */
+
+                       /* register our component for this channel number at 
the RSL Emulation */
+                       f_rslem_register(0, new_chan_nr, RSL1_PROC);
+
+                       /* resume processing of RSL DChan messages, which was 
temporarily suspended
+                        * before performing a hand-over */
+                       f_rslem_resume(RSL1_PROC);
+
+                       /* send handover complete over the new channel */
+                       var PDU_ML3_MS_NW l3_tx := 
valueof(ts_RRM_HandoverComplete('00'O));
+                       RSL1.send(ts_RSL_DATA_IND(new_chan_nr, 
valueof(ts_RslLinkID_DCCH(0)),
+                                                 enc_PDU_ML3_MS_NW(l3_tx)));
+                       /* by default, send via the new channel from now */
+                       st.old_chan_nr := g_chan_nr;
+                       g_chan_nr := new_chan_nr;
+                       st.rr_ho_cmpl_seen := true;
+                       repeat;
+               } else {
+                       setverdict(fail, "Unexpected L3 received", l3);
+                       self.stop;
+               }
+               }
+       [st.rr_ho_cmpl_seen] as_Media();
+       [st.rr_ho_cmpl_seen] RSL.receive(tr_RSL_REL_REQ(st.old_chan_nr, 
tr_RslLinkID_DCCH(0))) {
+               RSL.send(ts_RSL_REL_CONF(st.old_chan_nr, 
valueof(ts_RslLinkID_DCCH(0))));
+               repeat;
+               }
+       [st.rr_ho_cmpl_seen] RSL.receive(tr_RSL_RF_CHAN_REL(st.old_chan_nr)) {
+               RSL.send(ts_RSL_RF_CHAN_REL_ACK(st.old_chan_nr));
+               /* unregister for old channel number in RSL emulation */
+               /* FIXME: Determine TRX NR by ARFCN, instead of hard-coded 
TRX0! */
+               f_rslem_unregister(0, st.old_chan_nr);
+               st.handover_done := true;
+               repeat;
+               }
+}
+
+
 
 }
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
index d2ee605..cfbf96b 100644
--- a/library/L3_Templates.ttcn
+++ b/library/L3_Templates.ttcn
@@ -338,6 +338,25 @@
        }
 }
 
+template (value) PDU_ML3_MS_NW ts_RRM_HandoverComplete(OCT1 cause) := {
+       discriminator := '0000'B, /* overwritten */
+       tiOrSkip := {
+               skipIndicator := '0000'B
+       },
+       msgs := {
+               rrm := {
+                       handoverComplete := {
+                               messageType := '00101100'B,
+                               rRCause := {
+                                       valuePart := cause
+                               },
+                               mobileObsservedTimeDiff := omit,
+                               mobileTimeDifferenceHyperframe := omit
+                       }
+               }
+       }
+}
+
 function ts_CM3_TLV(template (omit) OCTN cm3) return template 
MobileStationClassmark3_TLV {
        if (not isvalue(cm3)) {
                return omit;

-- 
To view, visit https://gerrit.osmocom.org/6398
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic47e639a7c8640c736c84a44780fc8e111a64b52
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <lafo...@gnumonks.org>

Reply via email to