msc: add inter-BSC and inter-MSC Handover tests
Change-Id: I7d76c982ad4e198534fa488609c41e8892b268ab
diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
index 4df39d4..b7230cd 100644
--- a/library/BSSMAP_Templates.ttcn
+++ b/library/BSSMAP_Templates.ttcn
@@ -307,7 +307,7 @@
}
}
-template BSSMAP_IE_CellIdentifierList ts_BSSMAP_IE_CidList(BSSMAP_FIELD_CellIdentificationList cid_list) := {
+template BSSMAP_IE_CellIdentifierList ts_BSSMAP_IE_CidList(template BSSMAP_FIELD_CellIdentificationList cid_list) := {
elementIdentifier := '1A'O,
lengthIndicator := 0, /* overwritten */
cellIdentifierDiscriminator := '0000'B, /* overwritten */
@@ -315,31 +315,6 @@
cellIdentificationList := cid_list
}
-template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_FIELD_CellIdentificationList cid_list)
-modifies ts_BSSAP_BSSMAP := {
- pdu := {
- bssmap := {
- handoverRequired := {
- messageType := '11'O,
- cause := ts_BSSMAP_IE_Cause(cause),
- responseRequest := omit,
- cellIdentifierList := ts_BSSMAP_IE_CidList(cid_list),
- circuitPoolList := omit,
- currentChannelType1 := omit,
- speechVersion := omit,
- queueingIndicator := omit,
- oldToNewBSSInfo := omit,
- sourceToTargetRNCTransparentInfo := omit,
- sourceToTargetRNCTransparentInfoCDMA := omit,
- gERANClassmark := omit,
- talkerPriority := omit,
- speechCodec := omit,
- cSG_Identifier := omit
- }
- }
- }
-}
-
const OCT1 ChRate_ANY := '00'O;
const OCT1 ChRate_TCHF := '08'O;
const OCT1 ChRate_TCHH := '09'O;
@@ -703,6 +678,33 @@
}
}
+template PDU_BSSAP ts_BSSMAP_HandoverRequired(BssmapCause cause,
+ template BSSMAP_FIELD_CellIdentificationList cid_list)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverRequired := {
+ messageType := '11'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ responseRequest := omit,
+ cellIdentifierList := ts_BSSMAP_IE_CidList(cid_list),
+ circuitPoolList := omit,
+ currentChannelType1 := omit,
+ speechVersion := omit,
+ queueingIndicator := omit,
+ oldToNewBSSInfo := omit,
+ sourceToTargetRNCTransparentInfo := omit,
+ sourceToTargetRNCTransparentInfoCDMA := omit,
+ gERANClassmark := omit,
+ talkerPriority := omit,
+ speechCodec := omit,
+ cSG_Identifier := omit
+ }
+ }
+ }
+}
+
+
template PDU_BSSAP tr_BSSMAP_HandoverRequired modifies tr_BSSAP_BSSMAP := {
pdu := {
bssmap := {
@@ -713,6 +715,38 @@
}
}
+template PDU_BSSAP tr_BSSMAP_HandoverRequiredReject modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverRequiredReject := {
+ messageType := '1A'O
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_HandoverCommand
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverCommand := {
+ messageType := '13'O
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_HandoverSucceeded
+modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverSucceeded := {
+ messageType := '15'O
+ }
+ }
+ }
+}
+
template (value) PDU_BSSAP ts_BSSMAP_HandoverCommand(octetstring layer3info)
modifies ts_BSSAP_BSSMAP := {
pdu := {
@@ -751,6 +785,16 @@
}
}
+template PDU_BSSAP tr_BSSMAP_HandoverRequest modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverRequest := {
+ messageType := '10'O
+ }
+ }
+ }
+}
+
template PDU_BSSAP ts_BSSMAP_HandoverRequest(
template BSSMAP_IE_CircuitIdentityCode cic := omit,
template BSSMAP_IE_AoIP_TransportLayerAddress aoip_tla := omit,
@@ -826,6 +870,41 @@
}
}
+template PDU_BSSAP ts_BSSMAP_HandoverRequestAcknowledge(
+ template octetstring layer3info,
+ template LIN1 layer3infoLength,
+ template BSSMAP_IE_AoIP_TransportLayerAddress aoIPTransportLayer := omit,
+ template BSSMAP_IE_SpeechCodec speechCodec := omit,
+ template BSSMAP_IE_ChosenChannel chosenChannel := omit,
+ template BSSMAP_IE_ChosenEncryptionAlgorithm chosenEncryptionAlgorithm := omit)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverRequestAck := {
+ messageType := '12'O,
+ layer3Information := {
+ elementIdentifier := '17'O,
+ lengthIndicator := layer3infoLength,
+ layer3info := layer3info
+ },
+ chosenChannel := chosenChannel,
+ chosenEncryptionAlgorithm := chosenEncryptionAlgorithm,
+ circuitPool := omit,
+ speechVersion := omit,
+ circuitIdentityCode := omit,
+ lSAIdentifier := omit,
+ newBSSToOldBSSInfo := omit,
+ interSystemInformation := omit,
+ talkerPriority := omit,
+ aoIPTransportLayer := aoIPTransportLayer,
+ codecList := omit,
+ speechCodec := speechCodec,
+ lCLS_bSS_Status := omit
+ }
+ }
+ }
+}
+
template PDU_BSSAP tr_BSSMAP_HandoverDetect
modifies tr_BSSAP_BSSMAP := {
pdu := {
@@ -838,6 +917,18 @@
}
}
+template PDU_BSSAP ts_BSSMAP_HandoverDetect
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverDetect := {
+ messageType := '1B'O,
+ talkerPriority := omit
+ }
+ }
+ }
+}
+
template PDU_BSSAP tr_BSSMAP_HandoverComplete
modifies tr_BSSAP_BSSMAP := {
pdu := {
@@ -856,6 +947,24 @@
}
}
+template PDU_BSSAP ts_BSSMAP_HandoverComplete
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverComplete := {
+ messageType := '14'O,
+ rR_Cause := omit,
+ talkerPriority := omit,
+ speechCodec := omit,
+ codecList := omit,
+ chosenEncryptionAlgorithm := omit,
+ chosenChannel := omit,
+ lCLS_BSS_Status := omit
+ }
+ }
+ }
+}
+
template PDU_BSSAP tr_BSSMAP_HandoverPerformed
modifies tr_BSSAP_BSSMAP := {
pdu := {
@@ -975,7 +1084,7 @@
messageType := '52'O,
iMSI := ts_BSSMAP_Imsi(imsi_digits),
tMSI := f_tmsi_or_omit(tmsi),
- cellIdentifierList := ts_BSSMAP_IE_CidList(valueof(cid_list)),
+ cellIdentifierList := ts_BSSMAP_IE_CidList(cid_list),
channelNeeded := chneed,
eMLPP_Priority := omit,
pagingInformation := omit /* only VGCS/VBS flag */
diff --git a/library/GSUP_Types.ttcn b/library/GSUP_Types.ttcn
index c024d37..73f4562 100644
--- a/library/GSUP_Types.ttcn
+++ b/library/GSUP_Types.ttcn
@@ -55,7 +55,16 @@
OSMO_GSUP_SM_ALERT_RSN_IE ('46'O),
OSMO_GSUP_IMEI_IE ('50'O),
- OSMO_GSUP_IMEI_RESULT_IE ('51'O)
+ OSMO_GSUP_IMEI_RESULT_IE ('51'O),
+
+ OSMO_GSUP_MESSAGE_CLASS_IE ('0a'O),
+
+ OSMO_GSUP_SOURCE_NAME_IE ('60'O),
+ OSMO_GSUP_DESTINATION_NAME_IE ('61'O),
+ OSMO_GSUP_AN_APDU_IE ('62'O),
+ OSMO_GSUP_CAUSE_RR_IE ('63'O),
+ OSMO_GSUP_CAUSE_BSSAP_IE ('64'O),
+ OSMO_GSUP_CAUSE_SM_IE ('65'O)
} with { variant "FIELDLENGTH(8)" };
type enumerated GSUP_MessageType {
@@ -103,7 +112,27 @@
OSMO_GSUP_MSGT_CHECK_IMEI_REQUEST ('00110000'B),
OSMO_GSUP_MSGT_CHECK_IMEI_ERROR ('00110001'B),
- OSMO_GSUP_MSGT_CHECK_IMEI_RESULT ('00110010'B)
+ OSMO_GSUP_MSGT_CHECK_IMEI_RESULT ('00110010'B),
+
+ OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST ('00110100'B),
+ OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR ('00110101'B),
+ OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT ('00110110'B),
+
+ OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST ('00111000'B),
+ OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_ERROR ('00111001'B),
+ OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT ('00111010'B),
+
+ OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST ('00111100'B),
+ OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_ERROR ('00111101'B),
+ OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT ('00111110'B),
+
+ OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST ('01000000'B),
+ OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST ('01000100'B),
+
+ OSMO_GSUP_MSGT_E_CLOSE ('01000111'B),
+ OSMO_GSUP_MSGT_E_ABORT ('01001011'B),
+
+ OSMO_GSUP_MSGT_E_ROUTING_ERROR ('01001110'B)
} with { variant "FIELDLENGTH(8)" };
type enumerated GSUP_CancelType {
@@ -128,6 +157,14 @@
OSMO_GSUP_SESSION_STATE_END (3)
} with { variant "FIELDLENGTH(8)" };
+type enumerated GSUP_Message_Class {
+ OSMO_GSUP_MESSAGE_CLASS_UNSET (0),
+ OSMO_GSUP_MESSAGE_CLASS_SUBSCRIBER_MANAGEMENT (1),
+ OSMO_GSUP_MESSAGE_CLASS_SMS (2),
+ OSMO_GSUP_MESSAGE_CLASS_USSD (3),
+ OSMO_GSUP_MESSAGE_CLASS_INTER_MSC (4)
+} with { variant "FIELDLENGTH(8)" };
+
type record GSUP_MSISDN {
uint8_t len,
hexstring digits optional
@@ -138,6 +175,16 @@
hexstring digits optional
} with { variant (len) "LENGTHTO(digits)" };
+type enumerated GSUP_AN_PROTO {
+ OSMO_GSUP_AN_PROTO_48006 (1),
+ OSMO_GSUP_AN_PROTO_25413 (2)
+} with { variant "FIELDLENGTH(8)" };
+
+type record GSUP_AN_APDU {
+ GSUP_AN_PROTO proto,
+ octetstring pdu
+};
+
type record GSUP_IE {
GSUP_IEI tag,
uint8_t len,
@@ -175,6 +222,13 @@
sm_alert_rsn, tag = OSMO_GSUP_SM_ALERT_RSN_IE;
imei, tag = OSMO_GSUP_IMEI_IE;
imei_result, tag = OSMO_GSUP_IMEI_RESULT_IE;
+ message_class, tag = OSMO_GSUP_MESSAGE_CLASS_IE;
+ source_name, tag = OSMO_GSUP_SOURCE_NAME_IE;
+ destination_name, tag = OSMO_GSUP_DESTINATION_NAME_IE;
+ an_apdu, tag = OSMO_GSUP_AN_APDU_IE;
+ cause_rr, tag = OSMO_GSUP_CAUSE_RR_IE;
+ cause_bssap, tag = OSMO_GSUP_CAUSE_BSSAP_IE;
+ cause_sm, tag = OSMO_GSUP_CAUSE_SM_IE;
)"
};
@@ -219,7 +273,18 @@
GSUP_SM_ALERT_RSN_Type sm_alert_rsn,
GSUP_IMEI imei,
- GSUP_IMEIResult imei_result
+ GSUP_IMEIResult imei_result,
+
+ GSUP_Message_Class message_class,
+
+ octetstring source_name,
+ octetstring destination_name,
+
+ GSUP_AN_APDU an_apdu,
+
+ OCT1 cause_rr,
+ OCT1 cause_bssap,
+ OCT1 cause_sm
};
type record GSUP_PDU {
@@ -930,6 +995,70 @@
}
}
+template GSUP_IE tr_GSUP_IE_Message_Class(template GSUP_Message_Class val) := {
+ tag := OSMO_GSUP_MESSAGE_CLASS_IE,
+ len := ?,
+ val := {
+ message_class := val
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Message_Class(GSUP_Message_Class val) := {
+ tag := OSMO_GSUP_MESSAGE_CLASS_IE,
+ len := 0, /* overwritten */
+ val := {
+ message_class := val
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Source_Name(template octetstring name) := {
+ tag := OSMO_GSUP_SOURCE_NAME_IE,
+ len := ?,
+ val := {
+ source_name := name
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Source_Name(octetstring name) := {
+ tag := OSMO_GSUP_SOURCE_NAME_IE,
+ len := 0, /* overwritten */
+ val := {
+ source_name := name
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_Destination_Name(template octetstring name) := {
+ tag := OSMO_GSUP_DESTINATION_NAME_IE,
+ len := ?,
+ val := {
+ destination_name := name
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_Destination_Name(octetstring name) := {
+ tag := OSMO_GSUP_DESTINATION_NAME_IE,
+ len := 0, /* overwritten */
+ val := {
+ destination_name := name
+ }
+}
+
+template GSUP_IE tr_GSUP_IE_AN_APDU(template GSUP_AN_APDU an_apdu) := {
+ tag := OSMO_GSUP_AN_APDU_IE,
+ len := ?,
+ val := {
+ an_apdu := an_apdu
+ }
+}
+
+template (value) GSUP_IE ts_GSUP_IE_AN_APDU(GSUP_AN_APDU an_apdu) := {
+ tag := OSMO_GSUP_AN_APDU_IE,
+ len := 0, /* overwritten */
+ val := {
+ an_apdu := an_apdu
+ }
+}
+
private function f_gen_ts_ss_ies(
hexstring imsi,
OCT4 sid,
@@ -962,14 +1091,20 @@
tr_GSUP_IE_SessionId(sid),
tr_GSUP_IE_SessionState(state)
};
+ var integer last_idx := 3;
/* Optional SS payload */
if (istemplatekind(ss, "*")) {
ies[3] := *;
+ last_idx := last_idx + 1;
} else if (not istemplatekind(ss, "omit")) {
ies[3] := tr_GSUP_IE_SSInfo(ss);
+ last_idx := last_idx + 1;
}
+ ies[last_idx] := tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_USSD);
+ last_idx := last_idx + 1;
+
return ies;
}
@@ -1036,7 +1171,8 @@
tr_GSUP_IE_IMSI(imsi),
tr_GSUP_IE_Cause(cause),
tr_GSUP_IE_SessionId(sid),
- tr_GSUP_IE_SessionState(state)
+ tr_GSUP_IE_SessionState(state),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1069,7 +1205,8 @@
tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
tr_GSUP_IE_SM_RP_DA(sm_rp_da),
tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
- tr_GSUP_IE_SM_RP_UI(sm_rp_ui)
+ tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1090,7 +1227,8 @@
OSMO_GSUP_MSGT_MO_FORWARD_SM_RESULT,
{
tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr)
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1115,7 +1253,8 @@
{
tr_GSUP_IE_IMSI(imsi),
tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1162,7 +1301,8 @@
tr_GSUP_IE_SM_RP_DA(sm_rp_da),
tr_GSUP_IE_SM_RP_OA(sm_rp_oa),
tr_GSUP_IE_SM_RP_UI(sm_rp_ui),
- tr_GSUP_IE_SM_RP_MMS(sm_rp_mms)
+ tr_GSUP_IE_SM_RP_MMS(sm_rp_mms),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1183,7 +1323,8 @@
OSMO_GSUP_MSGT_MT_FORWARD_SM_RESULT,
{
tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr)
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1208,7 +1349,8 @@
{
tr_GSUP_IE_IMSI(imsi),
tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1233,7 +1375,8 @@
{
tr_GSUP_IE_IMSI(imsi),
tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn)
+ tr_GSUP_IE_SM_ALERT_RSN(sm_alert_rsn),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1254,7 +1397,8 @@
OSMO_GSUP_MSGT_READY_FOR_SM_RESULT,
{
tr_GSUP_IE_IMSI(imsi),
- tr_GSUP_IE_SM_RP_MR(sm_rp_mr)
+ tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1279,7 +1423,8 @@
{
tr_GSUP_IE_IMSI(imsi),
tr_GSUP_IE_SM_RP_MR(sm_rp_mr),
- tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause)
+ tr_GSUP_IE_SM_RP_CAUSE(sm_rp_cause),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_SMS)
}
);
@@ -1293,5 +1438,79 @@
return false;
}
+template GSUP_AN_APDU t_GSUP_AN_APDU(
+ template GSUP_AN_PROTO an_proto := ?,
+ template octetstring pdu := ?
+) := {
+ proto := an_proto,
+ pdu := pdu
+};
+
+template GSUP_PDU tr_GSUP_E_AN_APDU(
+ template GSUP_MessageType msgt,
+ template hexstring imsi := ?,
+ template octetstring source_name := ?,
+ template octetstring destination_name := ?,
+ template GSUP_AN_APDU an_apdu := ?
+) := tr_GSUP(
+ msgt,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
+ tr_GSUP_IE_Source_Name(source_name),
+ tr_GSUP_IE_Destination_Name(destination_name),
+ tr_GSUP_IE_AN_APDU(an_apdu)
+ }
+);
+
+template GSUP_PDU tr_GSUP_E_NO_PDU(
+ template GSUP_MessageType msgt,
+ template hexstring imsi := ?,
+ template octetstring source_name := ?,
+ template octetstring destination_name := ?
+) := tr_GSUP(
+ msgt,
+ {
+ tr_GSUP_IE_IMSI(imsi),
+ tr_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC),
+ tr_GSUP_IE_Source_Name(source_name),
+ tr_GSUP_IE_Destination_Name(destination_name)
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_E_AN_APDU(
+ GSUP_MessageType msgt,
+ hexstring imsi,
+ octetstring source_name,
+ octetstring destination_name,
+ GSUP_AN_APDU an_apdu
+) := ts_GSUP(
+ msgt,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
+ valueof(ts_GSUP_IE_Source_Name(source_name)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name)),
+ valueof(ts_GSUP_IE_AN_APDU(an_apdu))
+ }
+);
+
+template (value) GSUP_PDU ts_GSUP_E_PrepareHandoverResult(
+ hexstring imsi,
+ hexstring msisdn,
+ octetstring source_name,
+ octetstring destination_name,
+ GSUP_AN_APDU an_apdu
+) := ts_GSUP(
+ OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT,
+ {
+ valueof(ts_GSUP_IE_IMSI(imsi)),
+ valueof(ts_GSUP_IE_MSISDN(msisdn)),
+ valueof(ts_GSUP_IE_Message_Class(OSMO_GSUP_MESSAGE_CLASS_INTER_MSC)),
+ valueof(ts_GSUP_IE_Source_Name(source_name)),
+ valueof(ts_GSUP_IE_Destination_Name(destination_name)),
+ valueof(ts_GSUP_IE_AN_APDU(an_apdu))
+ }
+);
} with { encode "RAW"; variant "FIELDORDER(msb)" }
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
index 4d71f27..cf6d64c 100644
--- a/library/L3_Templates.ttcn
+++ b/library/L3_Templates.ttcn
@@ -582,6 +582,59 @@
}
}
+template PDU_ML3_NW_MS tr_RR_HandoverCommand := {
+ discriminator := '0110'B,
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ handoverCommand := {
+ messageType := '00101011'B,
+ cellDescription := ?,
+ channelDescription2 := ?,
+ handoverReference := ?,
+ powerCommandAndAccesstype := ?,
+ synchronizationIndication := *,
+ frequencyShortListAfterTime := *,
+ frequencyListAfterTime := *,
+ cellChannelDescription := *,
+ multislotAllocation := *,
+ modeOfChannelSet1 := *,
+ modeOfChannelSet2 := *,
+ modeOfChannelSet3 := *,
+ modeOfChannelSet4 := *,
+ modeOfChannelSet5 := *,
+ modeOfChannelSet6 := *,
+ modeOfChannelSet7 := *,
+ modeOfChannelSet8 := *,
+ descrOf2ndCh_at := *,
+ modeOf2ndChannel := *,
+ frequencyChannelSequence_at := *,
+ mobileAllocation_at := *,
+ startingTime := *,
+ timeDifference := *,
+ timingAdvance := *,
+ frequencyShortListBeforeTime := *,
+ frequencyListBeforeTime := *,
+ descrOf1stCh_bt := *,
+ descrOf2ndCh_bt := *,
+ frequencyChannelSequence_bt := *,
+ mobileAllocation_bt := *,
+ cipherModeSetting := *,
+ vGCS_TargetModeIndication := *,
+ multiRateConfiguration := *,
+ dynamicARFCN_Mapping := *,
+ vGCS_Ciphering_Parameters := *,
+ dedicatedServiceInformation := *,
+ pLMNIndex := *,
+ extendedTSCSet_afterTime := *,
+ extendedTSCSet_beforeTime := *
+ }
+ }
+ }
+}
+
function ts_CM3_TLV(template (omit) OCTN cm3) return template MobileStationClassmark3_TLV {
if (not isvalue(cm3)) {
return omit;
diff --git a/library/RAN_Emulation.ttcnpp b/library/RAN_Emulation.ttcnpp
index d6d74e2..843cc9e 100644
--- a/library/RAN_Emulation.ttcnpp
+++ b/library/RAN_Emulation.ttcnpp
@@ -133,6 +133,7 @@
RAN_Conn_Prim;
} with { extension "internal" };
+type uint2_t N_Sd_Array[4];
/* represents a single BSSAP connection over SCCP */
type record ConnectionData {
@@ -146,7 +147,7 @@
/* CIC that has been used for voice of this channel (BSC side) */
integer cic optional,
/* array of N(SD) values for MO DTAP messages, indexed by discriminator */
- uint2_t n_sd[4]
+ N_Sd_Array n_sd
}
type record ImsiMapping {
@@ -671,30 +672,53 @@
return false;
}
-/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
-function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+function f_next_n_sd(inout N_Sd_Array n_sd, in integer n_sd_idx) return uint2_t {
var uint2_t seq_nr;
- if (ischosen(dtap.msgs.cc) or ischosen(dtap.msgs.mm) or ischosen(dtap.msgs.ss)) {
- seq_nr := cd.n_sd[0];
- cd.n_sd[0] := (cd.n_sd[0] + 1) mod 4;
- } else if (ischosen(dtap.msgs.gcc)) {
- seq_nr := cd.n_sd[1];
- cd.n_sd[1] := (cd.n_sd[1] + 1) mod 2;
- } else if (ischosen(dtap.msgs.bcc)) {
- seq_nr := cd.n_sd[2];
- cd.n_sd[2] := (cd.n_sd[2] + 1) mod 2;
- } else if (ischosen(dtap.msgs.loc)) {
- seq_nr := cd.n_sd[3];
- cd.n_sd[3] := (cd.n_sd[3] + 1) mod 2;
+ if (n_sd_idx == 0) {
+ seq_nr := n_sd[0];
+ n_sd[0] := (n_sd[0] + 1) mod 4;
+ } else if (n_sd_idx >= 1 and n_sd_idx <= 3) {
+ seq_nr := n_sd[n_sd_idx];
+ n_sd[n_sd_idx] := (n_sd[n_sd_idx] + 1) mod 2;
} else {
/* no sequence number to patch */
- return;
+ seq_nr := 0;
}
+ return seq_nr;
+}
+
+/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
+function f_ML3_patch_seq_nr(in uint2_t seq_nr, inout octetstring enc_l3) {
log("patching N(SD)=", seq_nr, " into dtap ", enc_l3);
enc_l3[1] := (enc_l3[1] and4b '3f'O) or4b bit2oct(int2bit(seq_nr, 8) << 6);
log("patched enc_l3: ", enc_l3);
}
+function f_ML3_n_sd_idx(in PDU_ML3_MS_NW dtap) return integer {
+ var uint2_t seq_nr;
+ if (ischosen(dtap.msgs.cc) or ischosen(dtap.msgs.mm) or ischosen(dtap.msgs.ss)) {
+ return 0;
+ } else if (ischosen(dtap.msgs.gcc)) {
+ return 1;
+ } else if (ischosen(dtap.msgs.bcc)) {
+ return 2;
+ } else if (ischosen(dtap.msgs.loc)) {
+ return 3;
+ }
+ /* no sequence number to patch */
+ return -1;
+}
+
+/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
+function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+ var integer n_sd_idx := f_ML3_n_sd_idx(dtap);
+ if (n_sd_idx < 0) {
+ return;
+ }
+ var uint2_t seq_nr := f_next_n_sd(cd.n_sd, n_sd_idx);
+ f_ML3_patch_seq_nr(seq_nr, enc_l3);
+}
+
private altstep as_reset_ack() runs on RAN_Emulation_CT {
#ifdef RAN_EMULATION_BSSAP
var BSSAP_N_UNITDATA_ind ud_ind;
@@ -732,6 +756,8 @@
var BSSAP_Conn_Req creq;
var PDU_BSSAP bssap;
var RAN_ConnHdlr vc_conn;
+ var integer targetPointCode;
+ var N_Sd_Array last_n_sd;
/* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
[] BSSAP.receive(BSSAP_N_UNITDATA_ind:?) -> value ud_ind {
@@ -823,7 +849,18 @@
ConnectionTable[idx].n_sd[0] := 1;
log("patch: N(SD) for ConnIdx ", idx, " set to 1");
}
+ }
+ [] PROC.getcall(RAN_last_n_sd:{?,-}) -> param(vc_conn) {
+ var integer idx := f_idx_by_comp(vc_conn);
+ last_n_sd := ConnectionTable[idx].n_sd;
+ PROC.reply(RAN_last_n_sd:{vc_conn, last_n_sd}) to vc_conn;
+ }
+
+ [] PROC.getcall(RAN_continue_after_n_sd:{?,?}) -> param(last_n_sd, vc_conn) {
+ var integer idx := f_idx_by_comp(vc_conn);
+ ConnectionTable[idx].n_sd := last_n_sd;
+ PROC.reply(RAN_continue_after_n_sd:{last_n_sd, vc_conn}) to vc_conn;
}
#else
[false] CLIENT.receive {}
@@ -1045,6 +1082,7 @@
var octetstring l3_info;
var hexstring imsi;
var OCT4 tmsi;
+ var integer targetPointCode;
alt {
[g_ran_ops.protocol == RAN_PROTOCOL_BSSAP] as_main_bssap();
@@ -1075,6 +1113,11 @@
PROC.reply(RAN_register:{l3_info, vc_hdlr}) to vc_hdlr;
}
+ [] PROC.getcall(RAN_register_handoverRequest:{?,?}) -> param(targetPointCode, vc_hdlr) {
+ f_create_expect(omit, vc_hdlr, targetPointCode);
+ PROC.reply(RAN_register_handoverRequest:{targetPointCode, vc_hdlr}) to vc_hdlr;
+ }
+
[] PROC.getcall(RAN_register_imsi:{?,?,?}) -> param(imsi, tmsi, vc_hdlr) {
f_create_imsi(imsi, tmsi, vc_hdlr);
PROC.reply(RAN_register_imsi:{imsi, tmsi, vc_hdlr}) to vc_hdlr;
@@ -1101,18 +1144,26 @@
type record ExpectData {
/* L3 payload based on which we can match it */
octetstring l3_payload optional,
+ integer handoverRequestPointCode optional,
/* component reference for this connection */
RAN_ConnHdlr vc_conn
}
/* procedure based port to register for incoming connections */
signature RAN_register(in octetstring l3, in RAN_ConnHdlr hdlr);
+signature RAN_register_handoverRequest(in integer targetPointCode, in RAN_ConnHdlr hdlr);
/* procedure based port to register for incoming IMSI/TMSI */
signature RAN_register_imsi(in hexstring imsi, in OCT4 tmsi, in RAN_ConnHdlr hdlr);
+/* If DTAP happens across other channels (e.g. GSUP), provide manual advancing of the n_sd sequence number */
+signature RAN_last_n_sd(in RAN_ConnHdlr hdlr, out N_Sd_Array last_n_sd);
+
+/* Update conn's n_sd sequence nr after the connection was taken over from elsewhere */
+signature RAN_continue_after_n_sd(N_Sd_Array last_n_sd, in RAN_ConnHdlr hdlr);
+
type port RAN_PROC_PT procedure {
- inout RAN_register, RAN_register_imsi;
+ inout RAN_register, RAN_register_imsi, RAN_register_handoverRequest, RAN_last_n_sd, RAN_continue_after_n_sd;
} with { extension "internal" };
#ifdef RAN_EMULATION_BSSAP
@@ -1121,16 +1172,35 @@
runs on RAN_Emulation_CT return RAN_ConnHdlr {
var RAN_ConnHdlr ret := null;
var octetstring l3_info;
+ var boolean handoverRequest := false;
+ var integer handoverRequestPointCode;
var integer i;
- if (not ischosen(conn_ind.userData.pdu.bssmap.completeLayer3Information)) {
- setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3");
+ if (ischosen(conn_ind.userData.pdu.bssmap.completeLayer3Information)) {
+ l3_info := conn_ind.userData.pdu.bssmap.completeLayer3Information.layer3Information.layer3info;
+ log("ExpectedCreateCallback completeLayer3Information");
+ } else if (ischosen(conn_ind.userData.pdu.bssmap.handoverRequest)) {
+ handoverRequest := true;
+ handoverRequestPointCode := bit2int(conn_ind.calledAddress.signPointCode);
+ log("ExpectedCreateCallback handoverRequest ", handoverRequestPointCode);
+ } else {
+ setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3 nor a Handover Request");
mtc.stop;
return ret;
}
- l3_info := conn_ind.userData.pdu.bssmap.completeLayer3Information.layer3Information.layer3info;
for (i := 0; i < sizeof(ExpectTable); i:= i+1) {
+ if (handoverRequest) {
+ log("ExpectTable[", i, "].handoverRequestPointCode = ", ExpectTable[i].handoverRequestPointCode,
+ " ==? ", handoverRequestPointCode);
+ if (ExpectTable[i].handoverRequestPointCode == handoverRequestPointCode) {
+ ret := ExpectTable[i].vc_conn;
+ log("Found Expect[", i, "] for handoverRequest handled at ", ret);
+ return ret;
+ } else {
+ continue;
+ }
+ }
if (not ispresent(ExpectTable[i].l3_payload)) {
continue;
}
@@ -1185,14 +1255,26 @@
}
#endif
-private function f_create_expect(octetstring l3, RAN_ConnHdlr hdlr)
+private function f_create_expect(template octetstring l3, RAN_ConnHdlr hdlr,
+ template integer handoverRequestPointCode := omit)
runs on RAN_Emulation_CT {
var integer i;
+ log("f_create_expect(l3 := ", l3, ", handoverRequest := ", handoverRequestPointCode);
for (i := 0; i < sizeof(ExpectTable); i := i+1) {
- if (not ispresent(ExpectTable[i].l3_payload)) {
- ExpectTable[i].l3_payload := l3;
+ if (not ispresent(ExpectTable[i].l3_payload)
+ and not ispresent(ExpectTable[i].handoverRequestPointCode)) {
+ if (ispresent(l3)) {
+ ExpectTable[i].l3_payload := valueof(l3);
+ }
+ if (ispresent(handoverRequestPointCode)) {
+ ExpectTable[i].handoverRequestPointCode := valueof(handoverRequestPointCode);
+ }
ExpectTable[i].vc_conn := hdlr;
- log("Created Expect[", i, "] for ", l3, " to be handled at ", hdlr);
+ if (ispresent(handoverRequestPointCode)) {
+ log("Created Expect[", i, "] for handoverRequest to be handled at ", hdlr);
+ } else {
+ log("Created Expect[", i, "] for ", l3, " to be handled at ", hdlr);
+ }
return;
}
}
@@ -1218,6 +1300,7 @@
runs on RAN_Emulation_CT {
for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) {
ExpectTable[i].l3_payload := omit;
+ ExpectTable[i].handoverRequestPointCode := omit;
}
}