ipa: Pull everything together: L3->BSSAP->SCCP->IPA
diff --git a/library/BSSMAP_Templates.ttcn b/library/BSSMAP_Templates.ttcn
new file mode 100644
index 0000000..aea1e01
--- /dev/null
+++ b/library/BSSMAP_Templates.ttcn
@@ -0,0 +1,170 @@
+module BSSMAP_Templates {
+
+import from General_Types all;
+import from Osmocom_Types all;
+import from BSSAP_Types all;
+
+type integer BssmapCause;
+
+template PDU_BSSAP ts_BSSAP_BSSMAP := {
+ discriminator := '0'B,
+ spare := '0000000'B,
+ dlci := omit,
+ lengthIndicator := 0, /* overwritten by codec */
+ pdu := ?
+}
+
+template PDU_BSSAP tr_BSSAP_BSSMAP := {
+ discriminator := '0'B,
+ spare := '0000000'B,
+ dlci := omit,
+ lengthIndicator := ?,
+ pdu := {
+ bssmap := ?
+ }
+}
+
+template (value) BSSMAP_IE_Cause ts_BSSMAP_IE_Cause(BssmapCause val) := {
+ elementIdentifier := '04'O,
+ lengthIndicator := 0,
+ causeValue := int2bit(val, 7),
+ extensionCauseValue := '0'B,
+ spare1 := omit
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_Reset(BssmapCause cause) modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ reset := {
+ messageType := '30'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ a_InterfaceSelectorForReset := omit
+ }
+ }
+ }
+}
+
+template (value) PDU_BSSAP ts_BSSMAP_ResetAck modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ resetAck := {
+ messageType := '31'O,
+ a_InterfaceSelectorForReset := omit
+ }
+ }
+ }
+}
+
+template PDU_BSSAP tr_BSSMAP_ResetAck modifies tr_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ resetAck := {
+ messageType := '31'O,
+ a_InterfaceSelectorForReset := *
+ }
+ }
+ }
+}
+
+template BSSMAP_IE_CellIdentifier ts_BSSMAP_IE_CellID := {
+ elementIdentifier := '05'O,
+ lengthIndicator := 0,
+ cellIdentifierDiscriminator := '0000'B,
+ spare1_4 := '0000'B,
+ cellIdentification := ?
+}
+
+type uint16_t BssmapLAC;
+type uint16_t BssmapCI;
+
+/*
+template BSSMAP_IE_CellIdentifier ts_CellId_CGI(mcc, mnc, lac, ci)
+modifies ts_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_LAC_CGI := {
+ mnc_mcc := FIXME,
+ lac := int2oct(lac, 2),
+ ci := int2oct(ci, 2)
+ }
+ }
+}
+*/
+
+template BSSMAP_IE_CellIdentifier ts_CellID_LAC_CI(BssmapLAC lac, BssmapCI ci)
+modifies ts_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_LAC_CI := {
+ lac := int2oct(lac, 2),
+ ci := int2oct(ci, 2)
+ }
+ }
+}
+
+template BSSMAP_IE_CellIdentifier ts_CellId_CI(BssmapCI ci)
+modifies ts_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_CI := int2oct(ci, 2)
+ }
+}
+
+template BSSMAP_IE_CellIdentifier ts_CellId_none
+modifies ts_BSSMAP_IE_CellID := {
+ cellIdentification := {
+ cI_noCell := ''O
+ }
+}
+
+
+template BSSMAP_IE_Layer3Information ts_BSSMAP_IE_L3Info(octetstring l3info) := {
+ elementIdentifier := '17'O,
+ lengthIndicator := 0,
+ layer3info := l3info
+}
+
+template PDU_BSSAP ts_BSSMAP_ComplL3(BSSMAP_IE_CellIdentifier cell_id, octetstring l3_info)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ completeLayer3Information := {
+ messageType := '57'O,
+ cellIdentifier := cell_id,
+ layer3Information := ts_BSSMAP_IE_L3Info(l3_info),
+ chosenChannel := omit,
+ lSAIdentifier := omit,
+ aPDU := omit,
+ codecList := omit,
+ redirectAttemptFlag := omit,
+ sendSequenceNumber := omit,
+ iMSI := omit
+ }
+ }
+ }
+}
+
+template PDU_BSSAP ts_BSSMAP_HandoReq(BssmapCause cause, BSSMAP_IE_CellIdentifierList cid_list)
+modifies ts_BSSAP_BSSMAP := {
+ pdu := {
+ bssmap := {
+ handoverRequired := {
+ messageType := '11'O,
+ cause := ts_BSSMAP_IE_Cause(cause),
+ responseRequest := omit,
+ cellIdentifierList := 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
+ }
+ }
+ }
+}
+
+
+}
diff --git a/library/IPA_CodecPort.ttcn b/library/IPA_CodecPort.ttcn
index 70d3ccb..ad94a92 100644
--- a/library/IPA_CodecPort.ttcn
+++ b/library/IPA_CodecPort.ttcn
@@ -16,6 +16,19 @@
octetstring msg
}
+
+ /* 'stream' contains the octets received so far, we must return the total length */
+ function f_IPA_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
+ var integer stream_len := lengthof(stream);
+ var integer len;
+ if (stream_len < 2) {
+ /* insufficient length to determine the length */
+ return -1;
+ }
+ len := 3 + oct2int(substr(stream, 0, 2));
+ return len;
+ }
+
private function IPL4_to_IPA_RecvFrom(in ASP_RecvFrom pin, out IPA_RecvFrom pout) {
var PDU_IPA ipa := dec_PDU_IPA(pin.msg);
pout.connId := pin.connId;
diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn
index 31f5c27..4d21bb4 100644
--- a/library/IPA_Emulation.ttcn
+++ b/library/IPA_Emulation.ttcn
@@ -12,11 +12,22 @@
}
*/
+type record ASP_IPA_Unitdata {
+ IpaStreamId streamId,
+ octetstring payload
+}
+
+type port IPA_SP_PT message {
+ inout ASP_IPA_Unitdata;
+} with { extension "internal" }
+
type component IPA_Emulation_CT {
/* down-facing port to IPA codec port */
port IPA_CODEC_PT IPA_PORT;
/* up-facing port to SCCP */
port MTP3asp_SP_PT MTP3_SP_PORT;
+ /* up-facing port for other streams */
+ port IPA_SP_PT IPA_SP_PORT;
var boolean g_initialized := false;
var ConnectionId g_ipa_conn_id := -1;
@@ -114,9 +125,26 @@
}
}
+private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
+ var ASP_IPA_Unitdata ret := {
+ streamId := ipa_rx.streamId,
+ payload := ipa_rx.msg
+ }
+ return ret;
+}
+
+private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
+ var IPA_Send ret := {
+ connId := connId,
+ streamId := ipa_tx.streamId,
+ msg := ipa_tx.payload
+ }
+ return ret;
+}
function ScanEvents() runs on IPA_Emulation_CT {
var IPA_RecvFrom ipa_rx;
+ var ASP_IPA_Unitdata ipa_ud;
var ASP_MTP3_TRANSFERreq mtp_req;
f_connect("127.0.0.1", 5000, "127.0.0.1", 49999);
@@ -137,7 +165,7 @@
MTP3_SP_PORT.send(mtp);
}
case else {
- log("Unknown/unsupported IPA Stream ID", ipa_rx);
+ IPA_SP_PORT.send(f_to_asp(ipa_rx));
}
}
}
@@ -151,6 +179,13 @@
}
IPA_PORT.send(ipa_tx);
}
+
+ /* Received MISC (RSL/OML/CTRL/MGCP) -> down into IPA */
+ [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
+ IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
+ }
+
+
}
}
}
diff --git a/library/L3_Templates.ttcn b/library/L3_Templates.ttcn
new file mode 100644
index 0000000..8f60b5c
--- /dev/null
+++ b/library/L3_Templates.ttcn
@@ -0,0 +1,112 @@
+module L3_Templates {
+
+import from General_Types all;
+import from MobileL3_Types all;
+import from MobileL3_CommonIE_Types all;
+import from MobileL3_MM_Types all;
+import from MobileL3_RRM_Types all;
+
+type enumerated CmServiceType {
+ CM_TYPE_MO_CALL ('0001'B),
+ CM_TYPE_EMERG_CALL ('0010'B),
+ CM_TYPE_MO_SMS ('0100'B),
+ CM_TYPE_SS_ACT ('1000'B)
+}
+
+
+/* send template fro Mobile Identity (TMSI) */
+template MobileIdentityLV ts_MI_TMSI_LV(OCT4 tmsi) := {
+ lengthIndicator := 0, /* overwritten */
+ mobileIdentityV := {
+ typeOfIdentity := '000'B, /* overwritten */
+ oddEvenInd_identity := {
+ tmsi_ptmsi := {
+ oddevenIndicator := '0'B,
+ fillerDigit := '1111'B,
+ octets := tmsi
+ }
+ }
+ }
+}
+
+private function f_enc_IMSI_L3(hexstring digits) return IMSI_L3 {
+ var IMSI_L3 l3;
+ var integer len := lengthof(digits);
+ if (len rem 2 == 1) { /* modulo remainder */
+ l3.oddevenIndicator := '0'B;
+ l3.fillerDigit := '1111'B;
+ } else {
+ l3.oddevenIndicator := '1'B;
+ l3.fillerDigit := omit;
+ }
+ l3.digits := digits;
+ return l3;
+}
+
+/* send template fro Mobile Identity (IMSI) */
+template (value) MobileIdentityLV ts_MI_IMSI_LV(hexstring imsi_digits) := {
+ lengthIndicator := 0, /* overwritten */
+ mobileIdentityV := {
+ typeOfIdentity := '000'B, /* overwritten */
+ oddEvenInd_identity := {
+ imsi := f_enc_IMSI_L3(imsi_digits)
+ }
+ }
+}
+
+/* Send template for Classmark 2 */
+template (value) MobileStationClassmark2_LV ts_CM2 := {
+ lengthIndicator := 0,
+ rf_PowerCapability := '000'B,
+ a5_1 := '0'B,
+ esind := '1'B,
+ revisionLevel := '10'B,
+ spare1_1 := '0'B,
+ mobileStationClassmark2_oct4 := omit,
+ mobileStationClassmark2_oct5 := omit
+};
+
+/* Send template for CM SERVICE REQUEST */
+template (value) PDU_ML3_MS_NW ts_CM_SERV_REQ(BIT4 serv_type, MobileIdentityLV mi_lv) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ mm := {
+ cMServiceRequest := {
+ messageType := '000000'B, /* overwritten */
+ nsd := '00'B,
+ cm_ServiceType := serv_type,
+ cipheringKeySequenceNumber := { '000'B, '0'B },
+ mobileStationClassmark2 := ts_CM2,
+ mobileIdentity := mi_lv,
+ priorityLevel := omit,
+ additionalUpdateParameterTV := omit,
+ deviceProperties := omit
+ }
+ }
+ }
+}
+
+/* Send template for PAGING RESPONSE */
+template (value) PDU_ML3_MS_NW ts_PAG_RESP(MobileIdentityLV mi_lv) := {
+ discriminator := '0000'B, /* overwritten */
+ tiOrSkip := {
+ skipIndicator := '0000'B
+ },
+ msgs := {
+ rrm := {
+ pagingResponse := {
+ messageType := '00000000'B, /* overwritten */
+ cipheringKeySequenceNumber := { '000'B, '0'B },
+ spare1_4 := '0000'B,
+ mobileStationClassmark := ts_CM2,
+ mobileIdentity := mi_lv,
+ additionalUpdateParameters := omit
+ }
+ }
+ }
+}
+
+}