WIP: msc: First test case for mobile terminated call testing

We start the call from the MNCC side, match on the paging and then
pick it up from there.

It currently fails as the MNCC_Emulation cannot yet handle "ConnHdlr
originated" MNCC calls yet.

Change-Id: I28c465187fd8b1dcfd687180b373a47bb9ac6734
This commit is contained in:
Harald Welte 2018-01-27 00:49:18 +01:00
parent 3f95be8fff
commit 812f7a45e3
5 changed files with 259 additions and 7 deletions

View File

@ -435,6 +435,22 @@ template (value) CalledPartyBCD_Number ts_Called(hexstring digits) := {
digits := digits
}
template CalledPartyBCD_Number tr_Called(template hexstring digits) := {
elementIdentifier := '5E'O,
lengthIndicator := ?,
numberingPlanIdentification := ?,
typeOfNumber := ?,
ext1 := ?,
digits := digits
}
template CallingPartyBCD_Number tr_Calling(template hexstring digits) := {
elementIdentifier := '5C'O,
lengthIndicator := ?,
oct3 := ?,
digits := digits
}
type integer SpeechVer;
template (value) Speech_AuxiliarySpeech ts_SpeechAux(SpeechVer ver, BIT1 suffix) := {
@ -756,5 +772,79 @@ template (value) PDU_ML3_MS_NW ts_ML3_MT_MM_AUTH_RESP_3G(OCT4 sres, octetstring
}
}
template PDU_ML3_MS_NW ts_ML3_MO_CC_CALL_CONF(integer tid,
template BearerCapability_TLV bcap := omit) := {
discriminator := '0011'B,
tiOrSkip := {
transactionId := {
tio := int2bit(tid, 3),
tiFlag := '1'B, /* response from destination */
tIExtension := omit
}
},
msgs := {
cc := {
callConfirmed := {
messageType := '001000'B,
nsd := '00'B,
repeatIndicator := omit,
bearerCapability1 := bcap,
bearerCapability2 := omit,
cause := omit,
cC_Capabilities := omit,
streamIdentifier := omit,
supportedCodecs := omit
}
}
}
}
template PDU_ML3_NW_MS tr_ML3_MT_CC_SETUP(integer tid, template hexstring called := *,
template hexstring calling := *,
template BearerCapability_TLV bcap := *) := {
discriminator := '0011'B,
tiOrSkip := {
transactionId := {
tio := int2bit(tid, 3),
tiFlag := '0'B, /* from originator */
tIExtension := omit
}
},
msgs := {
cc := {
setup_NW_MS := {
messageType := '000101'B,
nsd := '00'B,
bcRepeatIndicator := *,
bearerCapability1 := bcap,
bearerCapability2 := *,
facility := *,
progressIndicator := *,
signal := *,
callingPartyBCD_Number := tr_Calling(calling) ifpresent,
callingPartySubAddress := *,
calledPartyBCD_Number := tr_Called(called) ifpresent,
calledPartySubAddress := *,
redirectingPartyBCDNumber := *,
redirectingPartySubaddress := *,
llc_RepeatIndicator := *,
lowLayerCompatibility1 := *,
lowLayerCompatibility2 := *,
hlc_RepeatIndicator := *,
highLayerCompatibility1 := *,
highLayerCompatibility2 := *,
user_user := *,
priority := *,
alert := *,
networkCCCapabilities := *,
causeofNoCli := *,
backupBearerCapacity := *
}
}
}
}
}

View File

@ -280,6 +280,14 @@ function main(MnccOps ops, charstring id, charstring sock) runs on MNCC_Emulatio
f_call_table_del(call_id);
}
/* Client -> MNCC Socket: SETUP.req: forward + add call table entry */
[] MNCC_CLIENT.receive(MNCC_PDU:{msg_type := MNCC_SETUP_REQ, u:=?}) -> value mncc sender vc_conn {
/* add to call table */
f_call_table_add(vc_conn, f_mncc_get_call_id(mncc));
/* forward to MNCC socket */
MNCC.send(t_SD_MNCC(g_mncc_ud_id, mncc));
}
/* Client -> MNCC Socket: Normal message */
[] MNCC_CLIENT.receive(MNCC_PDU:?) -> value mncc sender vc_conn {
/* forward to MNCC socket */

View File

@ -665,10 +665,10 @@ template MNCC_PDU ts_MNCC_REJ_ind(uint32_t call_id, template MNCC_cause cause :=
}
}
/* MT: MSC <- MNCC: CALL_CONF.req; send CALL CONFIRMED to MS */
template MNCC_PDU ts_MNCC_CALL_CONF_req(uint32_t call_id, template MNCC_bearer_cap bcap := omit,
template MNCC_cause cause := omit,
template MNCC_cccap cccap := omit) := {
/* MT: MSC -> MNCC: CALL_CONF.req; send CALL CONFIRMED to MS */
template MNCC_PDU tr_MNCC_CALL_CONF_ind(template uint32_t call_id, template MNCC_bearer_cap bcap := *,
template MNCC_cause cause := *,
template MNCC_cccap cccap := *) := {
msg_type := MNCC_CALL_CONF_IND,
u := {
signal := { /* See 24.008 9.3.2 */
@ -691,9 +691,9 @@ template MNCC_PDU ts_MNCC_CALL_CONF_req(uint32_t call_id, template MNCC_bearer_c
more := 0,
notify := 0,
emergency := omit,
imsi := "",
lchan_type := 0,
lchan_mode := 0
imsi := ?,
lchan_type := ?,
lchan_mode := ?
}
}
}

View File

@ -132,6 +132,19 @@ runs on BSC_ConnHdlr {
}
}
/* helper function to fully establish a dedicated channel */
function f_establish_fully_pag(MobileIdentityLV mi, boolean expect_auth, boolean expect_ciph)
runs on BSC_ConnHdlr {
var PDU_ML3_MS_NW l3_info := valueof(ts_PAG_RESP(mi));
var PDU_DTAP_MT dtap_mt;
/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
f_bssap_compl_l3(l3_info);
f_mm_common(expect_auth, expect_ciph);
}
/* build a PDU_ML3_MS_NW containing a Location Update by IMSI */
function f_build_lu_imsi(hexstring imsi) return PDU_ML3_MS_NW
{

View File

@ -1311,6 +1311,147 @@ testcase TC_mo_crcx_ran_reject() runs on MTC_CT {
}
/* helper function to start a MT call: MNCC SETUP; Paging; DChan est.; DTAP SETUP */
private function f_mt_call_start(inout CallParameters cpars) runs on BSC_ConnHdlr {
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
var OCT4 tmsi;
f_perform_lu(false, true, true, false);
if (isvalue(g_pars.tmsi)) {
tmsi := g_pars.tmsi;
} else {
tmsi := 'FFFFFFFF'O;
}
f_bssmap_register_imsi(g_pars.imsi, tmsi);
/* Allocate call reference and send SETUP via MNCC to MSC */
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)));
/* MSC->BSC: expect PAGING from MSC */
BSSAP.receive(tr_BSSMAP_Paging(g_pars.imsi));
/* MS -> MSC: PAGING RESPONSE */
f_establish_fully_pag(valueof(ts_MI_IMSI_LV(g_pars.imsi)), false, false);
f_create_mgcp_expect(ExpectCriteria:{omit,omit,omit});
/* MSC->MS: SETUP */
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_SETUP(cpars.transaction_id, *, cpars.called_party)));
}
/* Test MT Call */
private function f_tc_mt_crcx_ran_reject(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
g_pars := pars;
var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
f_mt_call_start(cpars);
/* MS->MSC: CALL CONFIRMED */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
MGCP.receive(tr_CRCX) -> value mgcp_cmd;
cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
cpars.mgcp_ep := mgcp_cmd.line.ep;
/* Respond to CRCX with error */
var MgcpResponse mgcp_rsp := {
line := {
code := "542",
trans_id := mgcp_cmd.line.trans_id,
string := "FORCED_FAIL"
},
params := omit,
sdp := omit
}
MGCP.send(mgcp_rsp);
timer T := 30.0;
T.start;
alt {
[] T.timeout { setverdict(fail, "Timeout waiting for channel release"); self.stop; }
[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
BSSAP.send(ts_BSSMAP_ClearComplete);
BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
setverdict(pass);
}
[] BSSAP.receive { repeat; }
[] MNCC.receive { repeat; }
[] GSUP.receive { repeat; }
[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
f_create_mgcp_delete_ep(cpars.mgcp_ep);
repeat;
}
[] MGCP.receive { repeat; }
}
}
testcase TC_mt_crcx_ran_reject() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_tc_mt_crcx_ran_reject), testcasename(), 29);
vc_conn.done;
}
/* Test MT Call T310 timer */
private function f_tc_mt_t310(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
g_pars := pars;
var CallParameters cpars := valueof(t_CallParams('123456'H, 0));
var MNCC_PDU mncc;
var MgcpCommand mgcp_cmd;
f_mt_call_start(cpars);
/* MS->MSC: CALL CONFIRMED */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_CALL_CONF(cpars.transaction_id)));
MNCC.receive(tr_MNCC_CALL_CONF_ind(cpars.mncc_callref));
MGCP.receive(tr_CRCX) -> value mgcp_cmd;
cpars.mgcp_call_id := f_MgcpCmd_extract_call_id(mgcp_cmd);
cpars.mgcp_ep := mgcp_cmd.line.ep;
/* FIXME: Respond to CRCX */
/* old libosmocore T310 default timeout is 180s. so let's wait 190 */
timer T := 190.0;
T.start;
alt {
[] T.timeout { setverdict(fail, "Timeout waiting for T310"); self.stop; }
[] MNCC.receive(tr_MNCC_DISC_ind(cpars.mncc_callref)) {
MNCC.send(ts_MNCC_REL_req(cpars.mncc_callref, valueof(ts_MNCC_cause(23))));
}
}
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_DISC(cpars.transaction_id)));
BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_CC_RELEASE(cpars.transaction_id)));
/* FIXME: We're sending this with TIflag 0: allocated by sender, which is wrong */
BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_CC_REL_COMPL(cpars.transaction_id)));
alt {
[] BSSAP.receive(tr_BSSMAP_ClearCommand) {
BSSAP.send(ts_BSSMAP_ClearComplete);
BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
setverdict(pass);
}
[] MGCP.receive(tr_DLCX(?)) -> value mgcp_cmd {
MGCP.send(ts_DLCX_ACK2(mgcp_cmd.line.trans_id));
f_create_mgcp_delete_ep(cpars.mgcp_ep);
repeat;
}
}
}
testcase TC_mt_t310() runs on MTC_CT {
var BSC_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_tc_mt_t310), testcasename(), 30);
vc_conn.done;
}
/* TODO: