MSC_ConnectionHandler: check channel mode in f_establish_fully

The helper function f_establish_fully() checks the channel type
for compatibility. If the channel type is compatible with the
desired mode a channel mode modification could be necessary if
the current channel mode is different from the desired channel
mode. However, this is not checked at the momemend. We just
blindly expect a MODE MODIFY message from the BSC and ignore
the cases where the current channel mode and the desired channel
mode already matches up. This is the case if only a signalling
channel is requested with f_establish_fully for example.

- Check if the channel mode of the current channel and the
  desired channel mode match up.

- Make sure that the MODE MODIFY from the BSC is only
  expected when the channel modes are different.

Note: The function f_channel_needs_modify() that is used
to determine if a channel modification is needed or not
does not cover all cases yet. (see fixme note)

Change-Id: I9004f299220b01ecea6b2316ba3f913c316947dc
Closes: OS#2762
Related: OS#2936
This commit is contained in:
Philipp Maier 2018-05-18 11:12:50 +02:00
parent d879e2ff9a
commit 8ef527e75c
1 changed files with 51 additions and 4 deletions

View File

@ -674,6 +674,41 @@ return boolean {
return false;
}
/* Determine if the channel mode specified within rsl_chan_nr requires a
* MODE MODIFY in to match the channel mode specified by given BSSMAP
* ChannelType */
function f_channel_needs_modify(BSSMAP_IE_ChannelType bssmap, RslChannelNr rsl_chan_nr)
return boolean {
/* FIXME: This tests the rsl_chan_nr to determine if we are on a
* signalling channel or not. Unfortunately this may lead to false
* results if we are on a TCH. The problem is that a TCH may be also
* used in signalling mode, but this function assumes that only SDCCH4
* and SDCCH8 are used as signalling channels at all. */
var boolean current_signalling := false;
var boolean desired_signalling := false;
select (rsl_chan_nr) {
case (t_RslChanNr_SDCCH4(?, ?)) { current_signalling := true; }
case (t_RslChanNr_SDCCH8(?, ?)) { current_signalling := true; }
}
if (bssmap.speechOrDataIndicator == '0011'B) {
desired_signalling := true;
}
if (current_signalling == desired_signalling) {
/* The desired channel mode is equal to the one we currently
* have, there is no mode modification needed or expected */
return false;
} else {
/* The desired channel mode and the current channel mode do
* not match. A mode modification is required */
return true;
}
}
/* establish a channel fully, expecting an assignment matching 'exp' */
function f_establish_fully(template (omit) PDU_BSSAP ass_tpl, template PDU_BSSAP exp_ass_cpl)
runs on MSC_ConnHdlr {
@ -698,6 +733,7 @@ runs on MSC_ConnHdlr {
timer T := 10.0;
var boolean exp_compl := ischosen(exp_ass_cpl.pdu.bssmap.assignmentComplete);
var boolean exp_fail := ischosen(exp_ass_cpl.pdu.bssmap.assignmentFailure);
var boolean exp_modify;
var ExpectCriteria mgcpcrit := {
connid := omit,
endpoint := omit,
@ -707,10 +743,22 @@ runs on MSC_ConnHdlr {
/* if the channel type is SIGNAL, we're not handling a voice call */
if (ass_cmd.pdu.bssmap.assignmentRequest.channelType.speechOrDataIndicator != '0011'B) {
st.voice_call := true;
exp_modify := true;
}
/* determine if the current channel can support the given service or not */
if (not f_channel_compatible(ass_cmd.pdu.bssmap.assignmentRequest.channelType, g_chan_nr)) {
st.is_assignment := true;
/* We decided to assign a new channel, so we do not expect
* any mode modify messages on RSL */
exp_modify := false;
} else {
/* We will continue working with the currently assigned
* channel, we must now check if the mode of the current
* channel is compatible. If not we expect the BSC to modify
* the mode */
exp_modify := f_channel_needs_modify(ass_cmd.pdu.bssmap.assignmentRequest.channelType, g_chan_nr);
}
f_create_mgcp_expect(mgcpcrit);
@ -722,21 +770,20 @@ runs on MSC_ConnHdlr {
[st.is_assignment] as_assignment(st);
/* modify related bits */
[not st.is_assignment] as_modify(st);
[not st.is_assignment and exp_modify] as_modify(st);
/* voice call related bits (IPA CRCX/MDCX + MGCP) */
[st.voice_call] as_Media();
/* if we receive exactly what we expected, always return + pass */
[st.is_assignment and st.assignment_done or
(not st.is_assignment and st.modify_done)] BSSAP.receive(exp_ass_cpl) -> value bssap {
[st.is_assignment and st.assignment_done or (not st.is_assignment and (st.modify_done or not exp_modify))] BSSAP.receive(exp_ass_cpl) -> value bssap {
setverdict(pass);
}
[exp_fail] BSSAP.receive(exp_ass_cpl) -> value bssap {
setverdict(pass);
}
[(st.is_assignment and st.assignment_done or
(not st.is_assignment and st.modify_done)) and
(not st.is_assignment and (st.modify_done or not exp_modify))) and
exp_compl] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
setverdict(fail, "Received non-matching ASSIGNMENT COMPLETE");
}