Expand IPA emulaitpn code + example to include CCM and SCCP binding
diff --git a/library/IPA_Emulation.ttcn b/library/IPA_Emulation.ttcn
new file mode 100644
index 0000000..31f5c27
--- /dev/null
+++ b/library/IPA_Emulation.ttcn
@@ -0,0 +1,158 @@
+module IPA_Emulation {
+
+import from IPA_Types all;
+import from IPA_CodecPort all;
+import from IPA_CodecPort_CtrlFunct all;
+import from IPL4asp_Types all;
+import from MTP3asp_Types all;
+import from MTP3asp_PortType all;
+
+/*
+modulepar {
+}
+*/
+
+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;
+
+ var boolean g_initialized := false;
+ var ConnectionId g_ipa_conn_id := -1;
+}
+
+function f_connect(charstring remote_host, PortNumber remote_port,
+ charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
+ var Result res;
+ res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
+ local_host, local_port, 0, { tcp:={} });
+ g_ipa_conn_id := res.connId;
+}
+
+template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
+ sio := { '10'B, '00'B, '0011'B },
+ opc := opc,
+ dpc := 0,
+ sls := 0,
+ data := data
+}
+
+
+private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
+ len := 0, /* overwritten by codec */
+ tag := tag,
+ data := payload
+}
+
+/* build IPA CCM ID RESP response from IPA CCM GET */
+private function f_ccm_make_id_resp(PDU_IPA_CCM get) return PDU_IPA_CCM {
+ var integer i;
+ var PDU_IPA_CCM resp := {
+ msg_type := IPAC_MSGT_ID_RESP,
+ u := {
+ resp := {}
+ }
+ }
+
+ for (i := 0; i < sizeof(get.u.get); i := i + 1) {
+ var IpaCcmIdTag tag := get.u.get[i].tag;
+ var charstring foo;
+ select (tag) {
+ case (IPAC_IDTAG_UNIT) {
+ foo := "0/1/2";
+ }
+ case (IPAC_IDTAG_UNITNAME) {
+ foo := "mahlzeit";
+ }
+ case else {
+ foo := "foo";
+ }
+ }
+ resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
+ }
+
+ return resp;
+}
+
+/* transmit IPA CCM message */
+private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
+ var IPA_Send ipa_tx := {
+ connId := g_ipa_conn_id,
+ streamId := IPAC_PROTO_CCM,
+ msg := enc_PDU_IPA_CCM(ccm)
+ }
+ log("CCM Tx:", ccm);
+ IPA_PORT.send(ipa_tx);
+}
+
+template PDU_IPA_CCM ts_IPA_PONG := {
+ msg_type := IPAC_MSGT_PONG,
+ u := omit
+}
+
+template PDU_IPA_CCM ts_IPA_ACK := {
+ msg_type := IPAC_MSGT_ID_ACK,
+ u := omit
+}
+
+/* receive IPA CCM message */
+private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
+ select (ccm.msg_type) {
+ case (IPAC_MSGT_PING) {
+ f_ccm_tx(valueof(ts_IPA_PONG));
+ }
+ case (IPAC_MSGT_ID_ACK) {
+ f_ccm_tx(valueof(ts_IPA_ACK));
+ }
+ case (IPAC_MSGT_ID_GET) {
+ f_ccm_tx(f_ccm_make_id_resp(ccm));
+ }
+ case else {
+ log("Unknown/unsupported IPA CCM message type", ccm);
+ }
+ }
+}
+
+
+function ScanEvents() runs on IPA_Emulation_CT {
+ var IPA_RecvFrom ipa_rx;
+ var ASP_MTP3_TRANSFERreq mtp_req;
+
+ f_connect("127.0.0.1", 5000, "127.0.0.1", 49999);
+
+ while (true) {
+ alt {
+ /* Received IPA -> up into SCCP stack */
+ [] IPA_PORT.receive(IPA_RecvFrom: ?) -> value ipa_rx {
+ select (ipa_rx.streamId) {
+ case (IPAC_PROTO_CCM) {
+ var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
+ log("CCM Rx:", ccm);
+ f_ccm_rx(ccm);
+ }
+ case (IPAC_PROTO_SCCP) {
+ var ASP_MTP3_TRANSFERind mtp;
+ mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
+ MTP3_SP_PORT.send(mtp);
+ }
+ case else {
+ log("Unknown/unsupported IPA Stream ID", ipa_rx);
+ }
+ }
+ }
+
+ /* Received SCCP -> down into IPA */
+ [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
+ var IPA_Send ipa_tx := {
+ connId := g_ipa_conn_id,
+ streamId := IPAC_PROTO_SCCP,
+ msg := mtp_req.data
+ }
+ IPA_PORT.send(ipa_tx);
+ }
+ }
+ }
+}
+
+}
diff --git a/library/IPA_Types.ttcn b/library/IPA_Types.ttcn
index ceb31ce..1636f44 100644
--- a/library/IPA_Types.ttcn
+++ b/library/IPA_Types.ttcn
@@ -4,7 +4,24 @@
import from Osmocom_Types all;
-type uint8_t IpaStreamId;
+type enumerated IpaStreamId {
+ IPAC_PROTO_RSL (0),
+ IPAC_PROTO_OSMO (238),
+ IPAC_PROTO_MGCP_OLD (252),
+ IPAC_PROTO_SCCP (253),
+ IPAC_PROTO_CCM (254),
+ IPAC_PROTO_OML (255)
+} with { variant "FIELDLENGTH(8)" }
+
+type enumerated IpaExtStreamId {
+ IPAC_PROTO_EXT_CTRL ('00'H),
+ IPAC_PROTO_EXT_MGCP ('01'H),
+ IPAC_PROTO_EXT_LAC ('02'H),
+ IPAC_PROTO_EXT_SMSC ('03'H),
+ IPAC_PROTO_EXT_ORC ('04'H),
+ IPAC_PROTO_EXT_GSUP ('05'H),
+ IPAC_PROTO_EXT_OAP ('06'H)
+} with { variant "FIELDLENGTH(8)" }
external function enc_PDU_IPA(in PDU_IPA pdu) return octetstring
with { extension "prototype(convert)"
@@ -22,10 +39,67 @@
IpaStreamId streamId,
octetstring payloadData
} with {
- variant (lengthInd) "LENGTHTO(lengthInd,streamId,payloadData)";
+ variant (lengthInd) "LENGTHTO(payloadData)";
variant (lengthInd) "FIELDLENGTH(16)";
variant (lengthInd) "BYTEORDER(last)";
- encode "RAW";
}
+
+type enumerated IpaCcmMsgtype {
+ IPAC_MSGT_PING ('00'H),
+ IPAC_MSGT_PONG ('01'H),
+ IPAC_MSGT_ID_GET ('04'H),
+ IPAC_MSGT_ID_RESP ('05'H),
+ IPAC_MSGT_ID_ACK ('06'H)
+} with { variant "FIELDLENGTH(8)" }
+
+type enumerated IpaCcmIdTag {
+ IPAC_IDTAG_SERNR ('00'H),
+ IPAC_IDTAG_UNITNAME ('01'H),
+ IPAC_IDTAG_LOCATION1 ('02'H),
+ IPAC_IDTAG_LOCATION2 ('03'H),
+ IPAC_IDTAG_EQUIPVERS ('04'H),
+ IPAC_IDTAG_SWVERSION ('05'H),
+ IPAC_IDTAG_IPADDR ('06'H),
+ IPAC_IDTAG_MACADDR ('07'H),
+ IPAC_IDTAG_UNIT ('08'H)
+} with { variant "FIELDLENGTH(8)" }
+
+
+type record IpaCcmGetPart {
+ uint8_t one,
+ IpaCcmIdTag tag
}
+type set of IpaCcmGetPart IpaCcmIdGet;
+
+type record IpaCcmRespPart {
+ uint16_t len,
+ IpaCcmIdTag tag,
+ charstring data
+} with { variant (len) "LENGTHTO(data,tag)" }
+type set of IpaCcmRespPart IpaCcmIdResp;
+
+type union IpaCcmUnion {
+ IpaCcmIdGet get,
+ IpaCcmIdResp resp,
+ octetstring other
+}
+
+type record PDU_IPA_CCM {
+ IpaCcmMsgtype msg_type,
+ IpaCcmUnion u optional
+} with { variant "" };
+
+
+external function enc_PDU_IPA_CCM(in PDU_IPA_CCM pdu) return octetstring
+with { extension "prototype(convert)"
+ extension "encode(RAW)"
+ }
+
+external function dec_PDU_IPA_CCM(in octetstring stream) return PDU_IPA_CCM
+with { extension "prototype(convert)"
+ extension "decode(RAW)"
+ }
+
+
+} with { encode "RAW" }