osmo-ttcn3-hacks/msc/BSC_ConnectionHandler.ttcn

2015 lines
63 KiB
Plaintext
Raw Normal View History

/* BSC Connection Handler of MSC test suite in TTCN-3
* (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
* (C) 2018-2019 sysmocom - s.f.m.c. GmbH
* (C) 2018 Vadim Yanitskiy <axilirator@gmail.com>
* All rights reserved.
*
* Released under the terms of GNU General Public License, Version 2 or
* (at your option) any later version.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
module BSC_ConnectionHandler {
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
import from Misc_Helpers all;
import from GSM_Types all;
import from IPL4asp_Types all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from RAN_Emulation all;
import from BSSMAP_Templates all;
import from RANAP_Constants all;
import from RANAP_IEs all;
import from RANAP_PDU_Contents all;
import from RANAP_PDU_Descriptions all;
import from RANAP_Templates all;
import from GSUP_Types all;
import from GSUP_Emulation all;
import from MNCC_Types all;
import from MNCC_Emulation all;
import from MGCP_Types all;
import from MGCP_Emulation all;
import from MGCP_Templates all;
import from SDP_Types all;
import from MobileL3_Types all;
import from MobileL3_CommonIE_Types all;
import from MobileL3_MM_Types all;
import from MobileL3_CC_Types all;
import from MobileL3_SMS_Types all;
import from L3_Templates all;
import from L3_Common all;
import from SMPP_Emulation all;
import from IPA_Emulation all;
import from Osmocom_CTRL_Functions all;
import from Osmocom_CTRL_Types all;
import from Osmocom_CTRL_Adapter all;
import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
import from SGsAP_Emulation all;
import from TCCConversion_Functions { function f_strstr };
modulepar {
boolean mp_expect_common_id := true;
}
/* this component represents a single subscriber connection */
type component BSC_ConnHdlr extends RAN_ConnHdlr, MNCC_ConnHdlr, GSUP_ConnHdlr, MGCP_ConnHdlr, SMPP_ConnHdlr, CTRL_Adapter_CT, SGsAP_ConnHdlr {
var BSC_ConnHdlrPars g_pars;
timer g_Tguard := 60.0;
port TELNETasp_PT MSCVTY;
}
type record BSC_ConnHdlrNetworkPars {
OCT1 kc_support,
boolean expect_tmsi,
boolean expect_auth,
boolean expect_ciph,
boolean expect_imei,
boolean expect_imei_early,
GSUP_IMEIResult check_imei_result,
boolean check_imei_error
}
type record BSC_ConnHdlrPars {
SCCP_PAR_Address sccp_addr_own,
SCCP_PAR_Address sccp_addr_peer,
BSSMAP_IE_CellIdentifier cell_id,
hexstring imei,
hexstring imsi,
hexstring msisdn,
OCT4 tmsi optional,
MobileStationClassmark1_V cm1,
BSSMAP_IE_ClassmarkInformationType2 cm2,
BSSMAP_IE_ClassmarkInformationType3 cm3 optional,
AuthVector vec optional,
BSC_ConnHdlrNetworkPars net,
boolean send_early_cm,
charstring ipa_ctrl_ip,
integer ipa_ctrl_port,
boolean ipa_ctrl_enable,
boolean mm_info,
boolean sgsap_enable,
boolean gsup_enable,
OCT4 gsup_sid,
integer ran_idx,
boolean use_umts_aka,
boolean ran_is_geran,
boolean use_osmux,
boolean use_ipv6,
boolean verify_cell_id
};
/* get a one-octet bitmaks of supported algorithms based on Classmark information */
function f_alg_mask_from_cm(BSSMAP_IE_ClassmarkInformationType2 cm2) return OCT1 {
var BIT8 res := '00000001'B; /* A5/0 always supported */
if (cm2.a5_1 == '0'B) {
res := res or4b '00000010'B;
}
if (cm2.classmarkInformationType2_oct5.a5_2 == '1'B ) {
res := res or4b '00000100'B;
}
if (cm2.classmarkInformationType2_oct5.a5_3 == '1'B) {
res := res or4b '00001000'B;
}
/* TODO: CM3 for A5/4 and beyond */
return bit2oct(res);
}
/* determine the best algorithm available within the bit-mask */
function f_best_alg_from_mask(OCT1 alg_in) return OCT1 {
var BIT8 alg := oct2bit(alg_in);
var BIT8 ordered_algs[8] := {
'10000000'B, '01000000'B, '00100000'B, '00010000'B,
'00001000'B, /* A5/3 */
'00000010'B, /* A5/1 */
'00000100'B, /* A5/2 */
'00000001'B /* A5/0 */ }
for (var integer i := 0; i < sizeof(ordered_algs); i := i+1) {
if (alg and4b ordered_algs[i] != '00000000'B) {
return bit2oct(ordered_algs[i]);
}
}
return '00'O;
}
/* return an integer like '1' for A5/1 based on a mask (with only one bit set */
function f_alg_from_mask(OCT1 mask_in) return integer {
var BIT8 mask := oct2bit(mask_in);
for (var integer i := 0; i < 8; i := i+1) {
if (mask and4b ('00000001'B << i) != '00000000'B) {
return i;
}
}
return -1;
}
/* altstep for the global guard timer */
private altstep as_Tguard() runs on BSC_ConnHdlr {
[] g_Tguard.timeout {
setverdict(fail, "Tguard timeout");
mtc.stop;
}
}
/* init function, called as first function in new BSC_ConnHdlr */
function f_init_handler(BSC_ConnHdlrPars pars, float t_guard := 60.0) runs on BSC_ConnHdlr {
/* make parameters available via component variable */
g_pars := pars;
/* Start guard timer and activate it as default */
g_Tguard.start(t_guard);
activate(as_Tguard());
/* Route all SMPP messages for our MSISDN to us */
f_create_smpp_expect(hex2str(pars.msisdn));
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
/* Route all SGs message for our IMSI to us */
if (g_pars.sgsap_enable == true) {
f_create_sgsap_expect(pars.imsi);
}
if (g_pars.ipa_ctrl_enable == true) {
f_ipa_ctrl_start(g_pars.ipa_ctrl_ip, g_pars.ipa_ctrl_port);
}
map(self:MSCVTY, system:MSCVTY);
f_vty_set_prompts(MSCVTY);
f_vty_transceive(MSCVTY, "enable");
}
/* Callback function from general RAN_Emulation whenever a connectionless
* BSSMAP message arrives. Canreturn a PDU_BSSAPthat should be sent in return */
private function BscUnitdataCallback(PDU_BSSAP bssap)
runs on RAN_Emulation_CT return template PDU_BSSAP {
var template PDU_BSSAP resp := omit;
log("BSSMAP_BscUnitdataCallback");
/* answer all RESET with RESET ACK */
if (match(bssap, tr_BSSMAP_Reset(g_ran_ops.use_osmux))){
log("BSSMAP_BscUnitdataCallback: Responding to RESET with RESET-ACK");
resp := ts_BSSMAP_ResetAck(g_ran_ops.use_osmux);
}
/* FIXME: Handle paging, etc. */
return resp;
}
private function RncUnitdataCallback(RANAP_PDU ranap)
runs on RAN_Emulation_CT return template RANAP_PDU {
var template RANAP_PDU resp := omit;
log("RANAP_RncUnitdataCallback");
/* answer all RESET with RESET ACK */
if (match(ranap, tr_RANAP_Reset())) {
log("RANAP_RncUnitdataCallback: Responding to RESET with RESET-ACK");
var CN_DomainIndicator dom;
dom := ranap.initiatingMessage.value_.Reset.protocolIEs[1].value_.cN_DomainIndicator;
resp := ts_RANAP_ResetAck(dom);
}
/* FIXME: Handle paging, etc. */
return resp;
}
const RanOps BSC_RanOps := {
/* Create call-back for inbound connections from MSC (hand-over) */
create_cb := refers(RAN_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(BscUnitdataCallback),
ranap_create_cb := refers(RAN_Emulation.RanapExpectedCreateCallback),
ranap_unitdata_cb := refers(RncUnitdataCallback),
ps_domain := false,
decode_dtap := true,
role_ms := true,
protocol := RAN_PROTOCOL_BSSAP,
transport := BSSAP_TRANSPORT_AoIP,
use_osmux := false,
sccp_addr_local := omit,
sccp_addr_peer := omit
}
private function MnccUnitdataCallback(MNCC_PDU mncc)
runs on MNCC_Emulation_CT return template MNCC_PDU {
log("Ignoring MNCC", mncc);
return omit;
}
const MnccOps BCC_MnccOps := {
create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(MnccUnitdataCallback)
}
/* Encode 'l3' and ask RAN_Emulation to create new connection with COMPL L3 INFO */
function f_bssap_compl_l3(PDU_ML3_MS_NW l3)
runs on BSC_ConnHdlr {
log("Sending COMPL L3: ", l3);
var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3);
BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, l3_enc))));
alt {
[] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) {}
[] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
setverdict(fail, "DISC.ind from SCCP");
mtc.stop;
}
}
}
/* generate Iu LAI from BSSAP CGI */
private function f_IuLAI_from_BssmapCI(BSSMAP_IE_CellIdentifier ci) return LAI {
var LAI lai;
if (ischosen(ci.cellIdentification.cI_CGI)) {
lai.pLMNidentity := ci.cellIdentification.cI_CGI.mcc_mnc;
lai.lAC := ci.cellIdentification.cI_CGI.lac;
} else if (ischosen(ci.cellIdentification.cI_SAI)) {
lai.pLMNidentity := ci.cellIdentification.cI_SAI.mcc_mnc;
lai.lAC := ci.cellIdentification.cI_SAI.lac;
} else if (ischosen(ci.cellIdentification.ci_LAC_RNC_CI)) {
lai.pLMNidentity := ci.cellIdentification.ci_LAC_RNC_CI.mcc_mnc;
lai.lAC := ci.cellIdentification.ci_LAC_RNC_CI.lac;
} else {
mtc.stop;
}
lai.iE_Extensions := omit;
return lai;
}
/* like f_bssap_compl_l3() but for 3G */
function f_ranap_initial_ue(PDU_ML3_MS_NW l3)
runs on BSC_ConnHdlr {
log("Sending InitialUE: ", l3);
var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3);
var RANAP_PDU ranap;
var LAI lai := f_IuLAI_from_BssmapCI(g_pars.cell_id);
var SAI sai := {
pLMNidentity := lai.pLMNidentity,
lAC := lai.lAC,
sAC := '0000'O, /* FIXME */
iE_Extensions := omit
};
var IuSignallingConnectionIdentifier sigc_id := int2bit(23, 24);
var GlobalRNC_ID grnc_id := {
pLMNidentity := lai.pLMNidentity,
rNC_ID := 2342 /* FIXME */
};
ranap := valueof(ts_RANAP_initialUE_CS(lai, sai, l3_enc, sigc_id, grnc_id));
BSSAP.send(ts_RANAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own, ranap));
alt {
[] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_CONF_IND) {}
[] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
setverdict(fail, "DISC.ind from SCCP");
mtc.stop;
}
}
}
/* Send BSSMAP Complete L3 or RANAP Initial UE depending on 2G/3G RAN type */
function f_cl3_or_initial_ue(PDU_ML3_MS_NW l3)
runs on BSC_ConnHdlr {
if (g_pars.ran_is_geran) {
f_bssap_compl_l3(l3);
} else {
f_ranap_initial_ue(l3);
}
}
type enumerated EstablishType {
EST_TYPE_MO_CALL,
EST_TYPE_EMERG_CALL,
EST_TYPE_PAG_RESP,
EST_TYPE_MO_SMS,
EST_TYPE_SS_ACT
};
/* helper function to fully establish a dedicated channel */
function f_establish_fully(EstablishType etype := EST_TYPE_MO_CALL)
runs on BSC_ConnHdlr {
var PDU_ML3_MS_NW l3_info;
var MobileIdentityLV mi;
/* If we have a TMSI, use TMSI instead of IMSI */
if (ispresent(g_pars.tmsi)) {
mi := valueof(ts_MI_TMSI_LV(g_pars.tmsi));
} else {
mi := valueof(ts_MI_IMSI_LV(g_pars.imsi));
}
select (etype) {
case (EST_TYPE_MO_CALL) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
}
case (EST_TYPE_EMERG_CALL) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_EMERG_CALL, mi));
}
case (EST_TYPE_PAG_RESP) {
l3_info := valueof(ts_PAG_RESP(mi));
}
case (EST_TYPE_MO_SMS) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_SMS, mi));
}
case (EST_TYPE_SS_ACT) {
l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_SS_ACT, mi));
}
}
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
f_cl3_or_initial_ue(l3_info);
f_verify_vty_lac_ci(verify_vlr := false);
f_mm_common();
if (g_pars.net.expect_ciph or not g_pars.ran_is_geran) {
/* implicit CM SERVICE ACCEPT? */
} else {
if (etype != EST_TYPE_PAG_RESP) {
/* explicit CM SERVICE ACCEPT */
BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC));
}
}
}
/* build a PDU_ML3_MS_NW containing a Location Update by IMSI */
function f_build_lu_imsi(hexstring imsi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
{
var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(imsi));
return f_build_lu(mi);
}
function f_build_lu_imei(hexstring imei) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
{
var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(imei));
return f_build_lu(mi);
}
function f_build_lu_tmsi(OCT4 tmsi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
{
var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV(tmsi));
return f_build_lu(mi);
}
private function f_build_lu(MobileIdentityLV mi) runs on BSC_ConnHdlr return PDU_ML3_MS_NW
{
var LocationAreaIdentification_V old_lai := { '62F220'O, '9999'O };
var PDU_ML3_MS_NW l3_info := valueof(ts_ML3_MO_LU_Req(valueof(ts_ML3_IE_LuType_Attach),
old_lai, mi, g_pars.cm1));
return l3_info;
}
altstep as_GSUP_SAI() runs on BSC_ConnHdlr {
var GSUP_IE auth_tuple;
[] GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi)) {
if (g_pars.use_umts_aka) {
g_pars.vec := f_gen_auth_vec_3g();
auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G3G(g_pars.vec.rand,
g_pars.vec.sres,
g_pars.vec.kc,
g_pars.vec.ik,
g_pars.vec.ck,
g_pars.vec.autn,
g_pars.vec.res));
GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
} else {
g_pars.vec := f_gen_auth_vec_2g();
auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(g_pars.vec.rand,
g_pars.vec.sres,
g_pars.vec.kc));
GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));
}
}
}
function f_mm_auth() runs on BSC_ConnHdlr
{
if (g_pars.net.expect_auth) {
as_GSUP_SAI();
if (g_pars.use_umts_aka) {
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ_3G(g_pars.vec.rand, g_pars.vec.autn)));
var OCT4 res := substr(g_pars.vec.res, 0, 4);
var OCT4 xres := substr(g_pars.vec.res, 4, 4);
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_3G(res, xres)));
} else {
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(g_pars.vec.rand)));
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G(g_pars.vec.sres)));
}
}
}
function f_mm_imei() runs on BSC_ConnHdlr
{
var PDU_DTAP_MT dtap_mt;
var GSUP_PDU gsup_msg;
var MobileIdentityLV mi;
if (not g_pars.net.expect_imei) {
return
}
/* MSC <-> BSC: ID req/rsp for IMEI */
alt {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMEI))) {
mi := valueof(ts_MI_IMEI_LV(g_pars.imei));
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp(mi)));
}
[] BSSAP.receive(tr_PDU_DTAP_MT(?)) -> value dtap_mt {
setverdict(fail, "Expected ID REQ for IMEI DTAP MT message, but got: ", dtap_mt);
mtc.stop;
}
}
/* MSC <-> HLR: Check IMEI req/res/err */
alt {
[g_pars.net.check_imei_error] GSUP.receive(tr_GSUP_CHECK_IMEI_REQ(g_pars.imsi, g_pars.imei)) {
GSUP.send(ts_GSUP_CHECK_IMEI_ERR(g_pars.imsi, 96 /* Invalid Mandatory Information */));
}
[not g_pars.net.check_imei_error] GSUP.receive(tr_GSUP_CHECK_IMEI_REQ(g_pars.imsi, g_pars.imei)) {
GSUP.send(ts_GSUP_CHECK_IMEI_RES(g_pars.imsi, g_pars.net.check_imei_result));
}
[] GSUP.receive(?) -> value gsup_msg {
setverdict(fail, "Expected CHECK IMEI REQ GSUP message (with IMEI:", g_pars.imei, " and IMSI: ",
g_pars.imsi, "), but got: ", gsup_msg);
mtc.stop;
}
}
}
function f_mm_imei_early() runs on BSC_ConnHdlr
{
var PDU_DTAP_MT dtap_mt;
var GSUP_PDU gsup_msg;
var MobileIdentityLV mi;
if (not g_pars.net.expect_imei_early) {
return
}
/* MSC <-> BSC: ID req/rsp for IMEISV */
alt {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_ID_Req(CM_ID_TYPE_IMEISV))) {
mi := valueof(ts_MI_IMEISV_LV(g_pars.imei));
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_MM_ID_Rsp(mi)));
}
[] BSSAP.receive(tr_PDU_DTAP_MT(?)) -> value dtap_mt {
setverdict(fail, "Expected ID REQ for IMEISV DTAP MT message, but got: ", dtap_mt);
mtc.stop;
}
}
/* MSC <-> HLR: Check IMEI req/res/err */
alt {
[g_pars.net.check_imei_error] GSUP.receive(tr_GSUP_CHECK_IMEI_REQ(g_pars.imsi, g_pars.imei)) {
GSUP.send(ts_GSUP_CHECK_IMEI_ERR(g_pars.imsi, 96 /* Invalid Mandatory Information */));
}
[not g_pars.net.check_imei_error] GSUP.receive(tr_GSUP_CHECK_IMEI_REQ(g_pars.imsi, g_pars.imei)) {
GSUP.send(ts_GSUP_CHECK_IMEI_RES(g_pars.imsi, g_pars.net.check_imei_result));
}
[] GSUP.receive(?) -> value gsup_msg {
setverdict(fail, "Expected CHECK IMEI REQ GSUP message (with IMEI:", g_pars.imei, " and IMSI: ",
g_pars.imsi, "), but got: ", gsup_msg);
mtc.stop;
}
}
}
function f_expect_common_id() runs on BSC_ConnHdlr
{
if (g_pars.ran_is_geran) {
if (mp_expect_common_id) {
BSSAP.receive(tr_BSSMAP_CommonId(g_pars.imsi));
}
} else {
BSSAP.receive(tr_RANAP_CommonId(imsi_hex2oct(g_pars.imsi)));
}
}
function f_mm_common() runs on BSC_ConnHdlr
{
f_mm_auth();
if (g_pars.ran_is_geran) {
if (g_pars.net.expect_ciph) {
var OCT1 a5_net := f_alg_mask_from_cm(g_pars.cm2);
var OCT1 a5_intersect := g_pars.net.kc_support and4b a5_net;
alt {
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(a5_intersect, g_pars.vec.kc)) {
var OCT1 a5_chosen := f_best_alg_from_mask(a5_intersect);
var integer a5_nr := f_alg_from_mask(a5_chosen);
BSSAP.send(ts_BSSMAP_CipherModeCompl(int2oct(a5_nr+1, 1)));
}
[] BSSAP.receive(tr_BSSMAP_CipherModeCmd(?, g_pars.vec.kc)) {
setverdict(fail, "Wrong ciphering algorithm mask in CiphModCmd");
mtc.stop;
}
}
/* FIXME: Send the best available algorithm */
}
f_expect_common_id();
} else { /* UTRAN */
alt {
[g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(uia_algs := ?,
uia_key := oct2bit(g_pars.vec.ik),
key_sts := ?,
uea_algs := ?,
uea_key := oct2bit(g_pars.vec.ck))) {
var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1*/
var EncryptionAlgorithm uea_chosen := 1; /*standard_UMTS_encryption_algorith_UEA1*/
BSSAP.send(ts_RANAP_SecurityModeCompleteEnc(uia_chosen, uea_chosen));
f_expect_common_id();
}
[g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmdEnc(?,?,?,?,?)) {
setverdict(fail, "Invalid SecurityModeCommand (ciphering case)");
mtc.stop;
}
[not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(uia_algs := ?,
uia_key := oct2bit(g_pars.vec.ik),
key_sts := ?)) {
var IntegrityProtectionAlgorithm uia_chosen := 0; /*standard_UMTS_integrity_algorithm_UIA1;*/
BSSAP.send(ts_RANAP_SecurityModeComplete(uia_chosen));
f_expect_common_id();
}
[not g_pars.net.expect_ciph] BSSAP.receive(tr_RANAP_SecurityModeCmd(?,?,?)) {
setverdict(fail, "Invalid SecurityModeCommand (non-ciphering case)");
mtc.stop;
}
}
}
}
function f_expect_mm_info() runs on BSC_ConnHdlr {
if (g_pars.mm_info == true) {
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_Info));
}
}
private function f_lac_ci_vty_str(BSSMAP_IE_CellIdentifier cell_id) return charstring
{
return "LAC / cell ID: "
& int2str(oct2int(cell_id.cellIdentification.cI_CGI.lac)) & " / "
& int2str(oct2int(cell_id.cellIdentification.cI_CGI.ci));
}
/* Get an IMSI's info and verify that the g_pars.cell_id is reflected in the info.
* Verify both the "LAC / cell ID" in the VLR and the "LAC / cell ID" in the "Connection:" part, if any.
* If verify_vlr == false, then only verify the "Connection:" part, and fail if there is no "Connection:"; this is
* useful when a conn has been established, but the subscriber has not been authenticated, so the VLR does not yet
* reflect the new conn's cell ID.
*/
function f_verify_vty_lac_ci(boolean verify_vlr := true) runs on BSC_ConnHdlr {
if (not g_pars.ran_is_geran) {
log("Skipping f_verify_vty_lac_ci(), disabled for Iu");
setverdict(pass);
return;
}
if (not g_pars.verify_cell_id) {
/* Skip this verification; either the TC expects no cell id to end up being accepted, or this was
* disabled globally to test an older osmo-msc which doesn't store the cell id properly yet. */
log("Skipping f_verify_vty_lac_ci()");
setverdict(pass);
return;
}
var charstring vty_cmd := "show subscriber imsi " & hex2str(g_pars.imsi) & " conn";
var charstring result := f_vty_transceive_ret(MSCVTY, vty_cmd);
var charstring expect_lac_ci := "LAC / cell ID: "
& int2str(oct2int(g_pars.cell_id.cellIdentification.cI_CGI.lac)) & " / "
& int2str(oct2int(g_pars.cell_id.cellIdentification.cI_CGI.ci));
var boolean vlr_matches := false;
var boolean connection_present := false;
var boolean connection_matches := false;
/* There are two occurences of LAC / cell ID: once for the VLR record, and once for the active connection. The
* active connection part starts with 'Connection:'. If there is no active connection, that part is omitted.
* So, first find out whether there is a 'Connection:' part. Then verify the LAC / cell ID above 'Connection:'
* and below 'Connection:', separately.
*/
var integer connection_start := f_strstr(result, "Connection:");
connection_present := (connection_start >= 0);
var integer lac_ci_match := f_strstr(result, expect_lac_ci);
if (connection_present) {
if (lac_ci_match > connection_start) {
/* The first match is below 'Connection:', so the VLR part above it did not match. */
vlr_matches := false;
connection_matches := true;
} else if (lac_ci_match >= 0) {
/* The first match is above 'Connection:', so the VLR part matches. */
vlr_matches := true;
/* Now find a match below 'Connection:' */
lac_ci_match := f_strstr(result, expect_lac_ci, connection_start);
connection_matches := (lac_ci_match > 0);
}
} else {
/* There is no 'Connection:', so a match, if any, is from the VLR part. */
vlr_matches := (lac_ci_match >= 0);
}
if (verify_vlr) {
if (not vlr_matches) {
setverdict(fail, vty_cmd, " shows mismatching LAC / cell ID in the VLR part, expecting: ",
expect_lac_ci, " -- got: ", result);
return;
} else {
log("f_verify_vty_lac_ci(): VLR record matches ", expect_lac_ci);
setverdict(pass);
}
}
if (connection_present) {
if (not connection_matches) {
setverdict(fail, vty_cmd, " shows mismatching LAC cell ID in the 'Connection' part, expecting: ",
expect_lac_ci, " -- got: ", result);
} else {
log("f_verify_vty_lac_ci(): Active connection matches ", expect_lac_ci);
setverdict(pass);
}
}
if (not verify_vlr and not connection_present) {
setverdict(fail, "f_verify_vty_lac_ci(verify_vlr := false) called, which requires an active connection, but there is no 'Connection:' part to verify in ", result);
}
}
function f_perform_lu()
runs on BSC_ConnHdlr {
var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
var PDU_DTAP_MT dtap_mt;
/* tell GSUP dispatcher to send this IMSI to us */
f_create_gsup_expect(hex2str(g_pars.imsi));
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
if (g_pars.ran_is_geran) {
f_bssap_compl_l3(l3_lu);
if (g_pars.send_early_cm) {
BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
}
} else {
f_ranap_initial_ue(l3_lu);
}
/* at this point the conn has been established, but the subscriber has not been authenticated, so the VLR does
* not yet reflect this conn's cell ID. */
f_verify_vty_lac_ci(verify_vlr := false);
f_mm_imei_early();
f_mm_common();
f_msc_lu_hlr();
f_mm_imei();
f_accept_reject_lu();
/* FIXME: there could be pending SMS or other common procedures by the MSC, let's ignore them */
f_expect_clear();
setverdict(pass);
}
function f_msc_lu_hlr() runs on BSC_ConnHdlr
{
/* Expect MSC to perform LU with HLR */
GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));
}
function f_accept_reject_lu() runs on BSC_ConnHdlr {
var PDU_DTAP_MT dtap_mt;
alt {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {
var PDU_ML3_LocationUpdateAccept lu_acc := dtap_mt.dtap.msgs.mm.locationUpdateAccept;
if (g_pars.net.expect_tmsi) {
if (not ispresent(lu_acc.mobileIdentityTLV) or
not ischosen(lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi)) {
setverdict(fail, "Expected TMSI but no TMSI was allocated");
mtc.stop;
} else {
g_pars.tmsi := lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets;
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
}
} else {
if (ispresent(lu_acc.mobileIdentityTLV) and
ischosen(lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi)) {
setverdict(fail, "Expected no TMSI but TMSI was allocated");
mtc.stop;
}
}
}
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
setverdict(fail, "Expected LU ACK, but received LU REJ");
mtc.stop;
}
}
/* Wait for MM-Information (if enabled) */
f_expect_mm_info();
setverdict(pass);
}
function f_expect_lu_reject(template OCT1 cause := ?) runs on BSC_ConnHdlr {
var PDU_DTAP_MT dtap_mt;
timer T := 5.0;
T.start;
alt {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej(cause))) {
setverdict(pass);
}
[] BSSAP.receive(tr_PDU_DTAP_MT(?)) -> value dtap_mt {
setverdict(fail, "Expected LU reject BSSAP message, got: ", dtap_mt);
}
[] T.timeout {
setverdict(fail, "Timeout waiting for LU reject");
}
}
}
function f_foo() runs on BSC_ConnHdlr{
/* SCCP CC handled by RAN_Emulation_CT.main() */
/* Expect auth, if enabled */
/* TODO: ISD */
/* Expect encr, if enabled */
/* Expect encr, if enabled */
/* Expect ASS CMD, if chan_type != requested */
/* Send ASS CMPL in successful case */
/* Expect AoIP port/ip information for RTP stream */
/* Expect MSC-originated MGCP to our simulated MGW */
/* Verify Counters via CTRL */
/* re-configure MSC behaviour via VTY */
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
type record CrcxResponse {
integer resp, /* 1 = reply with OK, 0 = do not reply, -1 = reply with error */
HostName mgw_rtp_ip,
PortNumber mgw_rtp_port,
MgcpConnectionId mgcp_connection_id /* MGCP Connection ID BSS Side */
}
/* parameters related to a (MO?) voice call */
type record CallParameters {
/* CC related parameters */
hexstring called_party, /* whom are we calling */
integer transaction_id optional, /* which TS 04.08 CC transaction ID to use */
boolean mo_call, /* For a MO call, the transaction_id was allocated by the MS,
important to set the TI flag properly */
BearerCapability_TLV bearer_cap, /* which bearer capabilities to claim */
boolean emergency, /* is this an emergency call? */
/* MNCC related parameters */
uint32_t mncc_callref optional, /* call reference on the MNCC side */
MNCC_bearer_cap mncc_bearer_cap optional, /* MNCC-side bearer capabilities */
HostName mncc_rtp_ip optional, /* MNCC Side RTP IP */
PortNumber mncc_rtp_port optional, /* MNCC Side RTP port */
/* RTP related parameters */
HostName bss_rtp_ip optional, /* BSS Side RTP IP */
PortNumber bss_rtp_port optional, /* BSS Side RTP Port */
HostName mss_rtp_ip optional, /* MSS Side RTP IP */
PortNumber mss_rtp_port optional, /* MSS Side RTP Port */
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
integer got_crcx_count,
CrcxResponse mgw_conn_1,
CrcxResponse mgw_conn_2,
uint7_t rtp_payload_type, /* dynamic RTP payload type */
charstring rtp_sdp_format, /* AMR/8000 or the like */
boolean mgw_drop_dlcx optional, /* Provoke errors by not responding to DLCX
(f_mt_call and f_mt_call) */
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
boolean stop_after_cc_setup, /* Special case: stop call establish after CC Setup */
boolean ran_clear_when_alerting, /* Special case: send Clear upon CC Alerting */
boolean expect_release, /* Special case: expect call establish to cause direct CC Rel */
MgcpCallId mgcp_call_id optional, /* MGCP Call ID; CallAgent allocated */
MgcpEndpoint mgcp_ep optional /* MGCP Endpoint, CallAgent or MGW allocated */,
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
boolean use_osmux, /* MSC is expected to use Osmux for this call */
integer got_osmux_count
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
template (value) CallParameters t_CallParams(hexstring called := '12345'H, integer tid := 0) := {
called_party := called,
transaction_id := tid,
mo_call := false,
bearer_cap := valueof(ts_Bcap_voice),
emergency := false,
mncc_callref := omit,
mncc_bearer_cap := valueof(ts_MNCC_bcap_voice),
mncc_rtp_ip := "42.23.11.5",
mncc_rtp_port := 423,
bss_rtp_ip := "9.8.7.6",
bss_rtp_port := 9000,
mss_rtp_ip := omit,
mss_rtp_port := omit,
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
got_crcx_count := 0,
mgw_conn_1 := {
resp := 1,
mgw_rtp_ip := "1.1.1.1",
mgw_rtp_port := 10000,
mgcp_connection_id := '11111'H
},
mgw_conn_2 := {
resp := 1,
mgw_rtp_ip := "2.2.2.2",
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
mgw_rtp_port := 11000,
mgcp_connection_id := '22222'H
},
rtp_payload_type := 98,
rtp_sdp_format := "AMR/8000",
mgw_drop_dlcx := false,
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
stop_after_cc_setup := false,
ran_clear_when_alerting := false,
expect_release := false,
mgcp_call_id := omit,
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
mgcp_ep := "rtpbridge/1@mgw",
use_osmux := false,
got_osmux_count := 0
};
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
/* Allocate a call reference and send SETUP via MNCC to MSC */
function f_mt_call_initate(inout CallParameters cpars)
runs on BSC_ConnHdlr {
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
cpars.mo_call := false;
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
cpars.mncc_callref := f_rnd_int(2147483648);
MNCC.send(ts_MNCC_SETUP_req(cpars.mncc_callref, hex2str(g_pars.msisdn),
hex2str(cpars.called_party), hex2str(g_pars.imsi)));
}
private template (value) SDP_Message ts_SDP_CRCX_CN(CallParameters cpars) :=
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
cpars.mgw_conn_2.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) });
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
/* Complete call, begin with a paging response message via BSSAP */
function f_mt_call_complete(inout CallParameters cpars)
runs on BSC_ConnHdlr {
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
var template MgcpResponse mgcp_resp;
var MgcpOsmuxCID osmux_cid;
var PDU_BSSAP bssap;
f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
f_establish_fully(EST_TYPE_PAG_RESP);
log("f_mt_call_complete 1");
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
cpars.got_osmux_count := 0;
/* MS <- MSC: Expect CC SETUP */
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
/* MS -> MSC: ALERTING */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_ALERTING(cpars.transaction_id)));
MNCC.receive(tr_MNCC_ALERT_ind(cpars.mncc_callref));
log("f_mt_call_complete 2");
/* Create MGCP expect */
f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
/* Ask MSC via MNCC to create the RTP socket on the MSC/MGW side */
MNCC.send(ts_MNCC_RTP_CREATE(cpars.mncc_callref));
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
/* First MGCP CRCX */
MGCP.receive(tr_CRCX) -> value mgcp_cmd {
log("f_mt_call_complete 3");
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (not f_handle_crcx(cpars, mgcp_cmd)) {
return;
}
}
if (g_pars.ran_is_geran) {
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?);
interleave {
/* Second MGCP CRCX (this time for MSS/CN side) */
[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
log("f_mt_call_complete 4");
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (not f_handle_crcx(cpars, mgcp_cmd)) {
break;
}
}
/* MSC acknowledges the MNCC_CREATE to the MNCC handler */
[] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref)) {
log("f_mt_call_complete 5");
}
/* expect the MSC to trigger a BSSMAP ASSIGNMENT */
[] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass)) -> value bssap {
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
var template BSSMAP_IE_AoIP_TransportLayerAddress tla;
var BSSMAP_IE_SpeechCodec codec;
var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
log("f_mt_call_complete 6");
tla := f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port);
codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
if (cpars.use_osmux) {
if (not ispresent(bssap.pdu.bssmap.assignmentRequest.osmuxCID)) {
setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE");
mtc.stop;
}
osmuxCID := valueof(ts_OsmuxCID(0));
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (not match(bssap.pdu.bssmap.assignmentRequest.osmuxCID, osmuxCID)) {
setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE. Expected ", osmuxCID, " Got ", bssap.pdu.bssmap.assignmentRequest.osmuxCID);
mtc.stop;
}
bssap := valueof(ts_BSSMAP_AssignmentComplete(omit, tla, codec, osmuxCID));
} else {
bssap := valueof(ts_BSSMAP_AssignmentComplete(omit, tla, codec));
}
BSSAP.send(bssap);
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CONNECT(cpars.transaction_id)));
}
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7");
var octetstring ip;
var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
if (is_ipv6) {
ip := f_inet6_addr(cpars.mncc_rtp_ip);
} else {
ip := f_inet_addr(cpars.mncc_rtp_ip);
}
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
is_ipv6, ip,
cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mt_call_complete 8");
var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
if (cpars.use_osmux) {
osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
if (osmux_cid != 0) { /* we expect MSC to use specific CID here */
setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != 0");
mtc.stop;
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
/* MDCX setting up the CN side remote RTP address received from MNCC CONNECT */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
var SDP_Message sdp;
log("f_mt_call_complete 9");
if (isvalue(mgcp_cmd.sdp)) {
sdp := mgcp_cmd.sdp;
if (sdp.media_list[0].media_field.ports.port_number != cpars.mncc_rtp_port) {
setverdict(fail, "Wrong MDCX Connection port received, expected ", cpars.mncc_rtp_port, " and received ", sdp.media_list[0].media_field.ports.port_number)
mtc.stop;
}
if (sdp.connection.conn_addr.addr != cpars.mncc_rtp_ip) {
setverdict(fail, "Wrong MDCX Connection address received, expected ", cpars.mncc_rtp_ip, " and received ", sdp.connection.conn_addr.addr)
mtc.stop;
}
}
sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
cpars.mgw_conn_2.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
}
}
} else {
interleave {
[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
log("f_mt_call_complete 4.iu");
if (not f_handle_crcx(cpars, mgcp_cmd)) {
break;
}
}
/* MSC acknowledges the MNCC_CREATE to the MNCC handler */
[] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref)) {
log("f_mt_call_complete 5.iu");
}
[] BSSAP.receive(tr_RANAP_RabAssReq(?)) {
log("f_mt_call_complete 6.iu");
var RAB_SetupOrModifiedList l := {
{
{
id := id_RAB_SetupOrModifiedItem,
criticality := ignore,
value_ := {
rAB_SetupOrModifiedItem := {
rAB_ID := int2bit(23, 8),
transportLayerAddress := hex2bit( '350001c0a8021500000000000000000000000000'H),
iuTransportAssociation := {
bindingID := '040c0000'O
},
dl_dataVolumes := omit,
iE_Extensions := omit
}
}
}
}
};
BSSAP.send(ts_RANAP_RabAssResp(l));
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CONNECT(cpars.transaction_id)));
}
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7.iu");
var octetstring ip;
var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
if (is_ipv6) {
ip := f_inet6_addr(cpars.mncc_rtp_ip);
} else {
ip := f_inet_addr(cpars.mncc_rtp_ip);
}
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
is_ipv6, ip,
cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mt_call_complete 8.iu");
var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
if (cpars.use_osmux) {
osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
if (osmux_cid != 0) { /* we expect MSC to use specific CID here */
setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != 0");
mtc.stop;
}
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
/* MDCX setting up the CN side remote RTP address received from MNCC CONNECT */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mt_call_complete 9.iu");
var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
cpars.mgw_conn_2.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_2.mgcp_connection_id, sdp));
}
}
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (cpars.use_osmux == (cpars.got_osmux_count != 0)) {
log("Osmux ok: use_osmux = ", cpars.use_osmux, " got_osmux_count = ", cpars.got_osmux_count);
} else {
setverdict(fail, "Osmux failure: use_osmux = ", cpars.use_osmux, " got_osmux_count = ", cpars.got_osmux_count);
mtc.stop;
}
log("f_mt_call_complete DONE");
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
}
function f_expect_paging(boolean by_tmsi := true)
runs on BSC_ConnHdlr {
if (g_pars.ran_is_geran) {
BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
} else {
BSSAP.receive(tr_RANAP_Paging(cs_domain, imsi_hex2oct(g_pars.imsi)));
}
}
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
function f_mt_call_establish(inout CallParameters cpars)
runs on BSC_ConnHdlr {
/* Initiate the call via MNCC */
f_mt_call_initate(cpars);
/* BSC <- MSC: Expect paging. FIXME: By TMSI or not? */
f_ran_register_imsi(g_pars.imsi, g_pars.tmsi);
f_expect_paging()
WIP: MSC_Tests: Add SGs testcases This extens MSC_Tests.ttcn with an initial set of SGs interface test cases for RESET, LU, DETACH, PAGING, SMS and CSFB procedures In particular the following testcases are added: - TC_sgsap_reset: isolated reset procedure test - TC_sgsap_lu: isolated location update with TMSI realloc - TC_sgsap_lu_imsi_reject: location update, reject case - TC_sgsap_lu_and_nothing: location update with failed TMSI realloc - TC_sgsap_expl_imsi_det_eps: detach from EPS serveces - TC_sgsap_expl_imsi_det_noneps: detach from non-EPS services - TC_sgsap_paging_rej: isolated paging, reject case - TC_sgsap_paging_subscr_rej: isolated paging, subscr rejects call - TC_sgsap_paging_ue_unr: isolated paging, ue is unreachable - TC_sgsap_paging_and_nothing: page, but don't respond - TC_sgsap_paging_and_lu: check paging followed by an LU - TC_sgsap_mt_sms: mobile terminated SMS through SGs Interface - TC_sgsap_mo_sms: mobile originated SMS through SGs Interface - TC_sgsap_mt_sms_and_nothing: trigger SMS, but don't respond to paging - TC_sgsap_mt_sms_and_reject: trigger SMS, but reject paging - TC_sgsap_unexp_ud: Send unexpected unitdata (SGs Association: NULL) - TC_sgsap_unsol_ud: Send unsolicited unitdata (subscriber not in VLR) - TC_bssap_lu_sgsap_lu_and_mt_call: LU on 2G, LU on SGs and CSFB call - TC_sgsap_lu_and_mt_call: LU on SGs, and CSFB call Change-Id: I38543c35a9e74cea276e58d1d7ef01ef07ffe858 Depends: osmo-msc I73359925fc1ca72b33a1466e6ac41307f2f0b11d Related: OS#3645
2018-12-06 10:56:27 +00:00
/* Complete the call via BSSAP */
f_mt_call_complete(cpars);
setverdict(pass);
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
/* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters.
* Return true when an OK reply was sent, false otherwise.
* Count occurence of Osmux, include Osmux parameters in the reply if necessary. */
function f_handle_crcx(inout CallParameters cpars, MgcpCommand mgcp_cmd)
runs on BSC_ConnHdlr
return boolean {
var CrcxResponse conn := cpars.mgw_conn_1;
if (cpars.got_crcx_count > 0) {
conn := cpars.mgw_conn_2;
}
cpars.got_crcx_count := cpars.got_crcx_count + 1;
var MgcpMessage mgcp_msg := {
command := mgcp_cmd
}
var template MgcpResponse mgcp_resp;
var MgcpOsmuxCID osmux_cid;
var MgcpCallId call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
if (ispresent(cpars.mgcp_call_id)) {
if (cpars.mgcp_call_id != call_id) {
setverdict(fail, "CRCX contained unexpected call id. Expected:", cpars.mgcp_call_id, " got:", call_id);
mtc.stop;
}
} else {
cpars.mgcp_call_id := call_id;
}
/* When the endpoint contains a wildcard we keep the endpoint
* identifier we have set up in cpars. Otherwise we use the
* endpoint name that the call agent has supplied */
if (match(mgcp_cmd.line.ep, t_MGCP_EP_wildcard) == false) {
cpars.mgcp_ep := mgcp_cmd.line.ep;
}
if (conn.resp == -1) {
/* Reply with error */
var MgcpResponse mgcp_rsp := {
line := {
code := "542",
trans_id := mgcp_cmd.line.trans_id,
string := "FORCED_FAIL"
},
sdp := omit
}
var MgcpParameter mgcp_rsp_param := {
code := "Z",
val := cpars.mgcp_ep
};
mgcp_rsp.params[0] := mgcp_rsp_param;
MGCP.send(mgcp_rsp);
return false;
}
if (conn.resp == 0) {
/* Do not reply at all */
return false;
}
if (conn.resp != 1) {
setverdict(fail, "Unexpected value for cpars.mgw_conn_*.resp, expect -1, 0 or 1");
mtc.stop;
}
var SDP_Message sdp := valueof(ts_SDP(conn.mgw_rtp_ip, conn.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
conn.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
if (f_mgcp_contains_par(mgcp_msg, "X-OSMUX")) {
if (not cpars.use_osmux) {
setverdict(fail, "MSC sent X-Osmux parameter in MGCP, but not expecting any Osmux");
mtc.stop;
}
cpars.got_osmux_count := cpars.got_osmux_count + 1;
/* we expect MSC to use wildcard here, i.e. osmux_cid == -1 */
osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
log("f_handle_crcx(): got Osmux CID: ", osmux_cid);
if (osmux_cid != -1) {
setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != -1");
mtc.stop;
}
osmux_cid := 0;
mgcp_resp := ts_CRCX_ACK_osmux(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, osmux_cid, sdp);
} else {
mgcp_resp := ts_CRCX_ACK(mgcp_cmd.line.trans_id, conn.mgcp_connection_id, sdp);
}
f_mgcp_par_append(mgcp_resp.params, ts_MgcpParSpecEP(cpars.mgcp_ep));
MGCP.send(mgcp_resp);
return true;
}
altstep as_optional_mgcp_crcx(CallParameters cpars) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
[] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
log("as_optional_mgcp_crcx: rx CRCX");
f_handle_crcx(cpars, mgcp_cmd);
/* Without this 'repeat', the as_optional_mgcp_crcx() exits currently waiting interleaves as soon as an
* CRCX is handled. */
repeat;
}
}
private altstep as_optional_mgcp_mdcx(HostName mgw_rtp_ip, PortNumber mgw_rtp_port) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("as_optional_mgcp_mdcx: rx MDCX");
log(mgcp_cmd);
var charstring conn_id;
var charstring rtp_payload_type;
f_mgcp_find_param_entry(mgcp_cmd.params, "I", conn_id);
rtp_payload_type := mgcp_cmd.sdp.media_list[0].media_field.fmts[0];
var SDP_Message sdp := valueof(ts_SDP(mgw_rtp_ip, mgw_rtp_ip,
mgcp_cmd.sdp.origin.session_id, "42",
mgw_rtp_port,
{ rtp_payload_type },
{ valueof(ts_SDP_ptime(20)) }));
MGCP.send(ts_MDCX_ACK(mgcp_cmd.line.trans_id, str2hex(conn_id), sdp));
/* Without this 'repeat', currently active other interleave and alt series exit as soon as an MDCX is
* handled. */
repeat;
}
}
private altstep as_optional_mgcp_dlcx(CallParameters cpars) runs on BSC_ConnHdlr {
var MgcpCommand mgcp_cmd;
var boolean respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx));
[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
log("as_optional_mgcp_dlcx: rx MGCP DLCX");
if (respond_to_dlcx) {
MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
}
/* Without this 'repeat', currently active other interleave and alt series exit as soon as a
* DLCX is handled. */
repeat;
}
}
function f_mo_call_establish(inout CallParameters cpars)
runs on BSC_ConnHdlr {
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
var template MgcpResponse mgcp_resp;
var boolean respond_to_dlcx;
var PDU_BSSAP bssap;
var RANAP_PDU ranap;
var MgcpOsmuxCID osmux_cid;
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
cpars.mo_call := true;
if (cpars.emergency) {
f_establish_fully(EST_TYPE_EMERG_CALL);
} else {
f_establish_fully(EST_TYPE_MO_CALL);
}
/* Create MNCC and MGCP expect */
f_create_mncc_expect(hex2str(cpars.called_party));
f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
if (cpars.emergency) {
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_EMERG_SETUP(cpars.transaction_id)));
} else {
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_SETUP(cpars.transaction_id, cpars.called_party)));
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (cpars.stop_after_cc_setup) {
return;
}
var template BSSMAP_IE_AoIP_TransportLayerAddress tla_ass :=
f_tr_BSSMAP_IE_AoIP_TLA(cpars.mgw_conn_1.mgw_rtp_ip, ?);
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
var boolean got_mncc_setup_compl_ind := false;
var boolean got_cc_connect := false;
interleave {
[] MNCC.receive(tr_MNCC_SETUP_ind(?, tr_MNCC_number(hex2str(cpars.called_party)))) -> value mncc {
log("f_mo_call_establish 1: rx MNCC SETUP ind");
cpars.mncc_callref := mncc.u.signal.callref;
MNCC.send(ts_MNCC_RTP_CREATE(cpars.mncc_callref));
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
/* First MGCP CRCX */
[] MGCP.receive(tr_CRCX) -> value mgcp_cmd {
log("f_mo_call_establish 2: rx 1st CRCX");
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (not f_handle_crcx(cpars, mgcp_cmd)) {
break;
}
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
/* Second MGCP CRCX */
[] MGCP.receive(tr_CRCX(cpars.mgcp_ep)) -> value mgcp_cmd {
log("f_mo_call_establish 6: rx 2nd CRCX");
if (not f_handle_crcx(cpars, mgcp_cmd)) {
break;
}
}
[] MNCC.receive(tr_MNCC_RTP_CREATE(cpars.mncc_callref)) {
log("f_mo_call_establish 3: rx RTP CREATE");
/* Call Proceeding */
MNCC.send(ts_MNCC_CALL_PROC_req(cpars.mncc_callref, cpars.mncc_bearer_cap));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CALL_PROC(cpars.transaction_id)));
/* Alerting */
MNCC.send(ts_MNCC_ALERT_req(cpars.mncc_callref));
}
//[g_pars.ran_is_geran] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit, tla_ass)) -> value bssap
[] BSSAP.receive(tr_BSSMAP_AssignmentReq(omit)) -> value bssap {
log("f_mo_call_establish 4: rx Assignment Request");
var BSSMAP_IE_AoIP_TransportLayerAddress tla;
var BSSMAP_IE_SpeechCodec codec;
var BSSMAP_IE_Osmo_OsmuxCID osmuxCID;
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (not match(bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer, tla_ass)) {
log("Expected:", tla_ass);
log("Got:", bssap.pdu.bssmap.assignmentRequest.aoIPTransportLayer);
setverdict(fail, "MSC sent Assignment Request with unexpected AoIP Transport Layer IE");
mtc.stop;
}
tla := valueof(f_ts_BSSMAP_IE_AoIP_TLA(cpars.bss_rtp_ip, cpars.bss_rtp_port));
codec := valueof(ts_BSSMAP_IE_SpeechCodec({ts_CodecFR}));
if (cpars.use_osmux) {
if (not ispresent(bssap.pdu.bssmap.assignmentRequest.osmuxCID)) {
setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE");
mtc.stop;
}
osmuxCID := valueof(ts_OsmuxCID(0));
if (cpars.use_osmux and not match(bssap.pdu.bssmap.assignmentRequest.osmuxCID, osmuxCID)) {
setverdict(fail, "MSC sent AssignReq without expected OsmuxCID IE");
mtc.stop;
}
bssap := valueof(ts_BSSMAP_AssignmentComplete(omit, tla, codec, osmuxCID));
} else {
bssap := valueof(ts_BSSMAP_AssignmentComplete(omit, tla, codec));
}
BSSAP.send(bssap);
}
[] BSSAP.receive(tr_RANAP_RabAssReq(*)) -> value ranap {
log("f_mo_call_establish 4.iu: rx RANAP RAB Assignment Request");
var RAB_SetupOrModifiedList l := {
{
{
id := id_RAB_SetupOrModifiedItem,
criticality := ignore,
value_ := {
rAB_SetupOrModifiedItem := {
rAB_ID := int2bit(23, 8),
transportLayerAddress := hex2bit( '350001c0a8021500000000000000000000000000'H),
iuTransportAssociation := {
bindingID := '040c0000'O
},
dl_dataVolumes := omit,
iE_Extensions := omit
}
}
}
}
};
BSSAP.send(ts_RANAP_RabAssResp(l));
}
/* MDCX setting up the RAN side remote RTP address received from Assignment Complete */
[] MGCP.receive(tr_MDCX) -> value mgcp_cmd {
log("f_mo_call_establish 5: rx MDCX for the RAN side");
var SDP_Message sdp := valueof(ts_SDP(cpars.mgw_conn_1.mgw_rtp_ip, cpars.mgw_conn_1.mgw_rtp_ip,
hex2str(cpars.mgcp_call_id), "42",
cpars.mgw_conn_1.mgw_rtp_port,
{ int2str(cpars.rtp_payload_type) },
{ valueof(ts_SDP_rtpmap(cpars.rtp_payload_type,
cpars.rtp_sdp_format)),
valueof(ts_SDP_ptime(20)) }));
if (cpars.use_osmux) {
osmux_cid := f_MgcpCmd_extract_osmux_cid(mgcp_cmd);
if (osmux_cid != 0) { /* we expect MSC to use specific CID here */
setverdict(fail, "MSC using unexpected CID " & int2str(osmux_cid) & " != 0");
mtc.stop;
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
mgcp_resp := ts_MDCX_ACK_osmux(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, osmux_cid, sdp);
} else {
mgcp_resp := ts_MDCX_ACK(mgcp_cmd.line.trans_id, cpars.mgw_conn_1.mgcp_connection_id, sdp);
}
MGCP.send(mgcp_resp);
}
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_ALERTING(cpars.transaction_id))) {
log("f_mo_call_establish 7: rx CC Alerting");
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
if (cpars.ran_clear_when_alerting) {
if (g_pars.ran_is_geran) {
BSSAP.send(ts_BSSMAP_ClearRequest(0));
} else {
BSSAP.send(ts_RANAP_IuReleaseRequest(ts_RanapCause_om_intervention));
}
break;
}
cpars.mncc_callref := mncc.u.signal.callref;
/* Call Proceeding */
var octetstring ip;
var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
if (is_ipv6) {
ip := f_inet6_addr(cpars.mncc_rtp_ip);
} else {
ip := f_inet_addr(cpars.mncc_rtp_ip);
}
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
is_ipv6, ip,
cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
MNCC.send(ts_MNCC_SETUP_rsp(cpars.mncc_callref));
}
[] MNCC.receive(tr_MNCC_SETUP_COMPL_ind(?)) -> value mncc {
log("f_mo_call_establish 8: rx MNCC SETUP COMPLETE ind");
got_mncc_setup_compl_ind := true;
if (not cpars.expect_release and got_cc_connect) {
break;
}
}
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_CONNECT(cpars.transaction_id))) {
log("f_mo_call_establish 10: rx CC CONNECT");
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CONNECT_ACK(cpars.transaction_id)));
got_cc_connect := true;
if (not cpars.expect_release and got_mncc_setup_compl_ind) {
break;
}
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id))) {
log("f_mo_call_establish 11: rx CC RELEASE");
if (not cpars.expect_release) {
setverdict(fail, "Got unexpected CC Release");
mtc.stop;
}
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
f_expect_clear();
break;
}
}
f_sleep(0.5);
deactivate(mdcx);
if (cpars.use_osmux == (cpars.got_osmux_count != 0)) {
log("Osmux ok: use_osmux = ", cpars.use_osmux, " got_osmux_count = ", cpars.got_osmux_count);
} else {
setverdict(fail, "Osmux failure: use_osmux = ", cpars.use_osmux, " got_osmux_count = ", cpars.got_osmux_count);
mtc.stop;
}
log("f_mo_call_establish DONE");
setverdict(pass);
}
function f_call_hangup(inout CallParameters cpars, boolean release_by_ms, boolean is_csfb := false)
runs on BSC_ConnHdlr {
var MobileIdentityLV mi;
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
var boolean respond_to_dlcx;
var boolean dlcx_contained_ci := false;
var template PDU_BSSAP t_clear := tr_BSSMAP_ClearCommand;
if (is_csfb) {
t_clear := tr_BSSMAP_ClearCommandCSFB;
}
log("f_call_hangup 0: tx MNCC_DISC_REQ");
MNCC.send(ts_MNCC_DISC_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
log("f_call_hangup 1: rx DTAP CC DISC");
if (release_by_ms) {
var BIT1 tid_remote := '1'B;
if (cpars.mo_call) {
tid_remote := '0'B;
}
/* B-side (MS) Release of call */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_RELEASE(cpars.transaction_id, tid_remote, '0000000'B)));
MNCC.receive(tr_MNCC_REL_ind(cpars.mncc_callref));
log("f_call_hangup 2: rx MNCC REL ind");
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_REL_COMPL(cpars.transaction_id)));
log("f_call_hangup 3: rx DTAP CC REL COMPL");
} else {
/* A-side (PLMN) Release of call */
MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(42))));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
log("f_call_hangup 4: rx DTAP CC RELEASE");
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
}
respond_to_dlcx := not (isbound(cpars.mgw_drop_dlcx) and valueof(cpars.mgw_drop_dlcx));
msc: overhaul voice call testing * Semantic: We don't really know which side the MSC first creates a CRCX for. Instead of assuming that the RAN side is always CRCX'd first, simply handle a "first" and a "second" CRCX, not making any assumptions which is for which side. Notably, there still are quite a few places assuming which CRCX corresponds to the RAN/CN side, but the changes are sufficient to still pass the tests when osmo-msc swaps the CRCX order; sometimes for slightly obscure reasons, for example because it doesn't matter that the wrong port number is returned during a subsequent MDCX... Cleaning up the rest is still todo for later. Remove code dup from call establishing code, particularly for MGCP. Use f_mo_call_establish() and f_mt_call() where ever possible, to make all of the call establishing tests handle upcoming changes in osmo-msc's order of messages, without re-implementing the changes for each test individually. The X-Osmux parameter was so far expected to appear in the first CRCX received, assuming that this first CRCX is for the RAN. Instead, detect whether X-Osmux is contained in a CRCX, and reply with an Osmux CID if so, regardless of it being the first or second CRCX. Count the number of X-Osmux parameters received in CRCX messages, and compare after call setup to verify X-Osmux presence. Since f_mo_call_establish() can't handle RANAP assignment, a few Iu tests that worked with the older code dup will break by this patch. This is fixed by a subsequent patch, see I0ead36333ab665147b8d222070ea5cf8afc555ec. * Details, per patch chunk: Change ts_BSSMAP_IE_AoIP_TLA4 to a non-value template, so that we can use a wildcard for the assigned port number from MGCP (depending on RAN or CN CRCX first, the RAN port number can be one or the other). In CallParameters, move MGCP handling instructions into a separate record "CrcxResponse", and have two of them for handling the first and the second CRCX, replacing mgw_rtp_{ip,port}_{bss,mss} and mgcp_connection_id_{bss,mss}. In CallParameters, add some flags for early-exiting call establishment with a particular desired behavior, for specialized tests. In CallParameters, use common default values and don't repeat them in each and every call establishing test. Set cpars.mo_call := {true,false} implicitly when f_{mo,mt}_call_establish() are invoked. Remove CRCX comments implying RAN or CN side, instead just talk of the "first" and the "second" CRCX. Implement one common f_handle_crcx() function, which is used by f_mo_call_establish(), f_mt_call_complete(), as_optional_mgcp_crcx(), and implicitly uses the first/second CRCX handling. For Assigment, use a wildcard RTP port so that we don't have to assume which CRCX was for the RAN side. In f_mo_call_establish(), insert special case conditions to make it enact errors at specific times, for individual tests. That saves re-implementing the entire call establishment (code dup). For error cases, add expectation of a CC Release message in the call establishment. This should not apply for normal successful operation, but because interleave does not support conditionals, add flags got_mncc_setup_compl_ind and got_cc_connect to break the interleave when establishing is complete, so that the CC Release is skipped. A CC Release always breaks the interleave, at whatever time it arrives. Tests adopting f_{mo,mt}_call instead of code dup: f_tc_mo_setup_and_nothing() f_tc_mo_crcx_ran_timeout() f_tc_mo_crcx_ran_reject() f_tc_mo_release_timeout() f_tc_mo_cc_bssmap_clear() Change-Id: I8b82476f55a98f7a94d5c4f1cd80eac427b2d20f
2019-10-15 14:54:37 +00:00
var default mdcx := activate(as_optional_mgcp_mdcx(cpars.mgw_conn_2.mgw_rtp_ip, cpars.mgw_conn_2.mgw_rtp_port));
var default dlcx := activate(as_optional_mgcp_dlcx(cpars));
/* clearing of radio channel */
alt {
[g_pars.ran_is_geran] BSSAP.receive(t_clear) {
log("f_call_hangup 5: rx BSSAP Clear Command");
BSSAP.send(ts_BSSMAP_ClearComplete);
BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
log("f_call_hangup 6: rx SCCP DISC");
setverdict(pass);
}
[not g_pars.ran_is_geran] BSSAP.receive(tr_RANAP_IuReleaseCommand(?)) {
log("f_call_hangup 5.iu: rx Iu Release Command");
BSSAP.send(ts_RANAP_IuReleaseComplete);
BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
log("f_call_hangup 6.iu: rx SCCP DISC");
setverdict(pass);
}
}
f_sleep(1.0);
f_create_mgcp_delete_ep(cpars.mgcp_ep);
log("f_call_hangup 9: done");
deactivate(mdcx);
deactivate(dlcx);
}
function f_mt_call(inout CallParameters cpars)
runs on BSC_ConnHdlr {
f_mt_call_establish(cpars);
log("Hold the call for some time");
f_sleep(3.0);
log("Hangup");
f_call_hangup(cpars, true);
setverdict(pass);
}
function f_mo_call(inout CallParameters cpars)
runs on BSC_ConnHdlr {
f_mo_call_establish(cpars);
log("Hold the call for some time");
f_sleep(3.0);
log("Hangup");
f_call_hangup(cpars, false);
setverdict(pass);
}
function f_mo_seq_dtmf_dup(inout CallParameters cpars)
runs on BSC_ConnHdlr {
timer T := 1.0;
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
var template PDU_ML3_MS_NW dtmf_dtap;
f_mo_call_establish(cpars);
/* Send DTMF: send the exact same DTAP message twice, the dup should be filtered out by
* 3GPP TS 24.007 11.2.3.2 Message Type Octet / Duplicate Detection. */
/* Find out the next NSD that will be used, from RAN emulation. */
var N_Sd_Array last_n_sd := f_bssmap_last_n_sd();
var uint2_t next_n_sd := f_next_n_sd(last_n_sd, 0 /* cc is index 0 */);
/* Compose DTAP with this correct NSD */
dtmf_dtap := ts_ML3_MO_CC_START_DTMF(cpars.transaction_id, "2");
/* Here, pass skip_seq_patching == false so that the RAN Emulation NSD increments after this message. */
BSSAP.send(ts_PDU_DTAP_MO(dtmf_dtap, '00'O, false));
T.start;
alt {
[] MNCC.receive(tr_MNCC_START_DTMF_ind(cpars.mncc_callref, "2")) {
log("f_mo_seq_dtmf_dup() 1: got first START_DTMF_ind");
}
[] T.timeout {
setverdict(fail, "Timeout waiting for START_DTMF_ind");
mtc.stop;
}
}
/* Send the exact same DTAP with above NSD, which is now incorrect (has not incremented), so that this message
* will get filtered by the duplicate detection. Write NSD into DTAP and pass skip_seq_patching == true. */
dtmf_dtap.msgs.cc.startDTMF.nsd := int2bit(next_n_sd, 2);
BSSAP.send(ts_PDU_DTAP_MO(dtmf_dtap, '00'O, true));
T.start;
alt {
[] MNCC.receive(tr_MNCC_START_DTMF_ind(cpars.mncc_callref, "2")) {
setverdict(fail, "f_mo_seq_dtmf_dup() 2: Received duplicate START_DTMF_ind");
mtc.stop;
}
[] T.timeout { }
}
/* Here the NSD should be correct again and we see a DTMF. */
dtmf_dtap := ts_ML3_MO_CC_START_DTMF(cpars.transaction_id, "3");
BSSAP.send(ts_PDU_DTAP_MO(dtmf_dtap, '00'O, false));
alt {
[] MNCC.receive(tr_MNCC_START_DTMF_ind(cpars.mncc_callref, "3")) {
log("f_mo_seq_dtmf_dup() 3: got second START_DTMF_ind");
}
[] T.timeout {
setverdict(fail, "Timeout waiting for final START_DTMF_ind");
mtc.stop;
}
}
f_call_hangup(cpars, true);
setverdict(pass);
}
/* expect a clear command */
altstep as_clear_cmd_compl_disc(float t := 5.0) runs on BSC_ConnHdlr {
var PDU_BSSAP bssap;
[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
BSSAP.send(ts_BSSMAP_ClearComplete);
alt {
[] BSSAP.receive(RAN_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
setverdict(pass);
}
[] BSSAP.receive {
setverdict(fail, "Unexpected BSSMAP while waiting for SCCP Release");
mtc.stop;
}
}
}
[] BSSAP.receive(tr_BSSAP_BSSMAP) -> value bssap {
setverdict(fail, "Unexpected BSSMAP while waiting for ClearCommand", bssap);
mtc.stop;
}
}
function f_expect_clear(float t := 5.0, boolean verify_vlr_cell_id := true) runs on BSC_ConnHdlr {
timer T := t;
T.start;
alt {
[g_pars.ran_is_geran] as_clear_cmd_compl_disc(t) { }
[not g_pars.ran_is_geran] as_iu_release_compl_disc(t) { }
[] T.timeout {
setverdict(fail, "Timeout waiting for ClearCommand/Release");
mtc.stop;
}
}
if (verify_vlr_cell_id) {
/* Now the conn is gone, but the VLR reflects the cell ID */
f_verify_vty_lac_ci();
}
}
function f_create_bssmap_exp_handoverRequest(integer targetPointCode) runs on BSC_ConnHdlr {
BSSAP_PROC.call(RAN_register_handoverRequest:{targetPointCode, self}) {
[] BSSAP_PROC.getreply(RAN_register_handoverRequest:{?, ?}) {};
}
}
function f_bssmap_last_n_sd() runs on BSC_ConnHdlr return N_Sd_Array {
var N_Sd_Array last_n_sd;
BSSAP_PROC.call(RAN_last_n_sd:{self, -}) {
[] BSSAP_PROC.getreply(RAN_last_n_sd:{self, ?}) -> param(last_n_sd) {
return last_n_sd;
};
}
}
function f_bssmap_continue_after_n_sd(N_Sd_Array last_n_sd) runs on BSC_ConnHdlr {
BSSAP_PROC.call(RAN_continue_after_n_sd:{last_n_sd, self}) {
[] BSSAP_PROC.getreply(RAN_continue_after_n_sd:{last_n_sd, self});
}
}
type record SmsParametersTp {
OCT1 msg_ref,
TP_DA da,
OCT1 pid,
OCT1 dcs,
integer udl,
octetstring ud
}
type record SmsParametersRp {
OCT1 msg_ref,
RP_NumberingPlan_and_NumberDigits smsc_addr optional
}
type record SmsParameters {
SmsParametersTp tp,
SmsParametersRp rp,
uint3_t tid,
OCT1 dlci,
uint7_t exp_rp_err optional
}
template (value) TP_DA ts_TP_DA(BIT4 npl, BIT3 ton, hexstring addr) := {
tP_DA_NoPad := {
tP_LengthIndicator := 0, /* overwritten */
tP_NumberingPlanID := npl,
tP_TypeOfNumber := ton,
tp_Spare := '0'B,
tP_DAValue := addr
}
}
template RP_NumberingPlan_and_NumberDigits t_RP_Addr(template hexstring addr,
template BIT4 npi := '0001'B,
template BIT3 ton := '001'B,
template BIT1 ext := '1'B) := {
rP_NumberingPlanIdentification := npi,
rP_TypeOfNumber := ton,
rP_Ext := ext,
rP_NumberDigits := addr
}
template (value) SmsParameters t_SmsPars(hexstring tp_daddr := '12345'H) := {
tp := {
msg_ref := '23'O,
da := ts_TP_DA('0000'B, '000'B, tp_daddr),
pid := '00'O,
dcs := '00'O,
udl := 0,
ud := ''O
},
rp := {
msg_ref := '42'O,
/* We don't really need to have both SM-RP-DA/OA here, because only one IE
* is included in MO/MT SMS, and in the most cases it's the SMSC address.
* NOTE: this address is currently hard-coded by OsmoMSC. */
smsc_addr := t_RP_Addr('447785016005'H)
},
tid := 0,
dlci := '03'O,
exp_rp_err := omit
}
private altstep as_other_sms() runs on BSC_ConnHdlr {
[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_SMS(?, ?, ?), ?)) {
setverdict(fail, "Unexpected SMS related PDU from MSC");
mtc.stop;
}
}
/* Submit a MO RP-SMMA over an already existing DTAP connection */
function f_mo_smma(inout SmsParameters spars)
runs on BSC_ConnHdlr {
var template (value) RPDU_MS_SGSN rp_mo;
var template (value) PDU_ML3_MS_NW l3_mo;
var default d := activate(as_other_sms());
/* just in case this is routed to SMPP.. */
f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
rp_mo := ts_RP_SMMA_MO(spars.rp.msg_ref);
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
/* receive CP-ACK for CP-DATA above */
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT), spars.dlci));
deactivate(d);
setverdict(pass);
}
/* Submit a MO-SMS over an already existing DTAP connection */
function f_mo_sms_submit(inout SmsParameters spars)
runs on BSC_ConnHdlr {
var template (value) TPDU_RP_DATA_MS_SGSN tp_mo;
var template (value) RPDU_MS_SGSN rp_mo;
var template (value) PDU_ML3_MS_NW l3_mo;
var default d := activate(as_other_sms());
/* just in case this is routed to SMPP.. */
f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
tp_mo := ts_SMS_SUBMIT(spars.tp.msg_ref, spars.tp.da, spars.tp.pid, spars.tp.dcs,
spars.tp.udl, spars.tp.ud);
rp_mo := ts_RP_DATA_MO(spars.rp.msg_ref, omit, spars.rp.smsc_addr, tp_mo);
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_DATA_MO(rp_mo));
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
/* receive CP-ACK for CP-DATA above */
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_ACK_MT), spars.dlci));
deactivate(d);
setverdict(pass);
}
/* Wait RP-ACK for MO-SMS on an already existing DTAP connection */
function f_mo_sms_wait_rp_ack(inout SmsParameters spars)
runs on BSC_ConnHdlr {
var template (value) PDU_ML3_MS_NW l3_mo;
var template TPDU_RP_DATA_SGSN_MS tp_mt;
var template RPDU_SGSN_MS rp_mt;
var template PDU_ML3_NW_MS l3_mt;
var default d := activate(as_other_sms());
/* just in case this is routed to SMPP.. */
f_create_smpp_expect(hex2str(spars.tp.da.tP_DA_NoPad.tP_DAValue));
if (ispresent(spars.exp_rp_err)) {
/* expect an RP-ERROR message from MSC with given cause */
rp_mt := tr_RP_ERROR_MT(spars.rp.msg_ref, spars.exp_rp_err);
l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
BSSAP.receive(tr_PDU_DTAP_MT(l3_mt, spars.dlci));
/* send CP-ACK for CP-DATA just received */
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
} else {
/* expect RP-ACK for RP-DATA */
rp_mt := tr_RP_ACK_MT(spars.rp.msg_ref);
l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_REPL, tr_CP_DATA_MT(rp_mt));
BSSAP.receive(tr_PDU_DTAP_MT(l3_mt, spars.dlci));
/* send CP-ACO for CP-DATA just received */
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_ORIG, ts_CP_ACK_MO);
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
}
deactivate(d);
setverdict(pass);
}
/* Submit a MO-SMS, and wait for RP-ACK on an existing
* (and authenticated, ...) DTAP connection */
function f_mo_sms(inout SmsParameters spars)
runs on BSC_ConnHdlr {
f_mo_sms_submit(spars);
f_mo_sms_wait_rp_ack(spars);
}
function f_mt_sms_deliver_pdu(in SmsParameters spars)
runs on BSC_ConnHdlr
return template PDU_DTAP_MT {
var template TPDU_RP_DATA_SGSN_MS tp_mt := tr_SMS_DELIVER(?, spars.tp.ud, spars.tp.pid, spars.tp.dcs, ?);
var template RPDU_SGSN_MS rp_mt := tr_RP_DATA_MT(?, spars.rp.smsc_addr, omit, tp_mt);
var template PDU_ML3_NW_MS l3_mt := tr_ML3_MT_SMS(?, c_TIF_ORIG, tr_CP_DATA_MT(rp_mt));
return tr_PDU_DTAP_MT(l3_mt, spars.dlci);
}
/* Wait for MT SMS on an already existing DTAP connection */
function f_mt_sms_expect(inout SmsParameters spars)
runs on BSC_ConnHdlr {
var template (value) PDU_ML3_MS_NW l3_mo;
var PDU_DTAP_MT dtap_mt;
var default d := activate(as_other_sms());
/* Expect CP-DATA(RP-DATA(SMS-DELIVER)) */
BSSAP.receive(f_mt_sms_deliver_pdu(spars)) -> value dtap_mt;
/* Extract relevant identifiers */
spars.tid := bit2int(dtap_mt.dtap.tiOrSkip.transactionId.tio);
spars.rp.msg_ref := dtap_mt.dtap.msgs.sms.cP_DATA.cP_User_Data.cP_RPDU.rP_DATA_SGSN_MS.rP_MessageReference;
/* send CP-ACK for CP-DATA just received */
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_ACK_MO);
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
deactivate(d);
setverdict(pass);
}
/* Send RP-ACK for MT-SMS over an already existing DTAP connection */
function f_mt_sms_send_rp_ack(inout SmsParameters spars)
runs on BSC_ConnHdlr {
var template (value) RPDU_MS_SGSN rp_mo;
var template (value) PDU_ML3_MS_NW l3_mo;
var template PDU_ML3_NW_MS l3_mt;
var default d := activate(as_other_sms());
/* send RP-ACK for RP-DATA */
rp_mo := ts_RP_ACK_MO(spars.rp.msg_ref);
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
/* expect CP-ACK for CP-DATA(RP-ACK) just sent */
l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
BSSAP.receive(tr_PDU_DTAP_MT(l3_mt, spars.dlci));
deactivate(d);
setverdict(pass);
}
/* Send RP-ERROR for MT-SMS over an already existing DTAP connection */
function f_mt_sms_send_rp_error(inout SmsParameters spars, uint7_t cause)
runs on BSC_ConnHdlr {
var template (value) RPDU_MS_SGSN rp_mo;
var template (value) PDU_ML3_MS_NW l3_mo;
var template PDU_ML3_NW_MS l3_mt;
var default d := activate(as_other_sms());
/* send RP-ACK for RP-DATA */
rp_mo := ts_RP_ERROR_MO(spars.rp.msg_ref, cause);
l3_mo := ts_ML3_MO_SMS(spars.tid, c_TIF_REPL, ts_CP_DATA_MO(rp_mo));
BSSAP.send(ts_PDU_DTAP_MO(l3_mo, spars.dlci, true));
/* expect CP-ACK for CP-DATA(RP-ERROR) just sent */
l3_mt := tr_ML3_MT_SMS(spars.tid, c_TIF_ORIG, tr_CP_ACK_MT);
BSSAP.receive(tr_PDU_DTAP_MT(l3_mt, spars.dlci));
deactivate(d);
setverdict(pass);
}
/* Wait for a MT-SMS and send RP-ACK over an already existing
* (and authenticated, ...) DTAP connection */
function f_mt_sms(inout SmsParameters spars)
runs on BSC_ConnHdlr {
f_mt_sms_expect(spars);
f_mt_sms_send_rp_ack(spars);
}
}