<p>laforge <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15196">View Change</a></p><div style="white-space:pre-wrap">Approvals:
laforge: Looks good to me, approved
pespin: Looks good to me, but someone else must approve
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">library: Add S1AP CodecPort/Emulation<br><br>Change-Id: I9bfba3ab2a3830e590b203c44c03b9c9383fff99<br>---<br>A library/S1AP_CodecPort.ttcn<br>A library/S1AP_CodecPort_CtrlFunct.ttcn<br>A library/S1AP_CodecPort_CtrlFunctDef.cc<br>A library/S1AP_Emulation.ttcn<br>M mme/gen_links.sh<br>M mme/regen_makefile.sh<br>6 files changed, 871 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/library/S1AP_CodecPort.ttcn b/library/S1AP_CodecPort.ttcn</span><br><span>new file mode 100644</span><br><span>index 0000000..59cef18</span><br><span>--- /dev/null</span><br><span>+++ b/library/S1AP_CodecPort.ttcn</span><br><span>@@ -0,0 +1,82 @@</span><br><span style="color: hsl(120, 100%, 40%);">+module S1AP_CodecPort {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Simple S1AP Codec Port, translating between raw SCTP primitives with</span><br><span style="color: hsl(120, 100%, 40%);">+ * octetstring payload towards the IPL4asp provider, and S1AP primitives</span><br><span style="color: hsl(120, 100%, 40%);">+ * which carry the decoded S1AP data types as payload.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Released under the terms of GNU General Public License, Version 2 or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0-or-later</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ import from IPL4asp_PortType all;</span><br><span style="color: hsl(120, 100%, 40%);">+ import from IPL4asp_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+ import from S1AP_PDU_Descriptions all;</span><br><span style="color: hsl(120, 100%, 40%);">+ import from S1AP_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ type record S1AP_RecvFrom {</span><br><span style="color: hsl(120, 100%, 40%);">+ ConnectionId connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ HostName remName,</span><br><span style="color: hsl(120, 100%, 40%);">+ PortNumber remPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ HostName locName,</span><br><span style="color: hsl(120, 100%, 40%);">+ PortNumber locPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_PDU msg</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ template S1AP_RecvFrom t_S1AP_RecvFrom(template S1AP_PDU msg) := {</span><br><span style="color: hsl(120, 100%, 40%);">+ connId := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ remName := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ remPort := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ locName := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ locPort := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ msg := msg</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ type record S1AP_Send {</span><br><span style="color: hsl(120, 100%, 40%);">+ ConnectionId connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_PDU msg</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ template S1AP_Send t_S1AP_Send(template ConnectionId connId, template S1AP_PDU msg) := {</span><br><span style="color: hsl(120, 100%, 40%);">+ connId := connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ msg := msg</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ private function IPL4_to_S1AP_RecvFrom(in ASP_RecvFrom pin, out S1AP_RecvFrom pout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.connId := pin.connId;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.remName := pin.remName;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.remPort := pin.remPort;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.locName := pin.locName;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.locPort := pin.locPort;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.msg := dec_S1AP_PDU(pin.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ } with { extension "prototype(fast)" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ private function S1AP_to_IPL4_Send(in S1AP_Send pin, out ASP_Send pout) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.connId := pin.connId;</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.proto := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sctp := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sinfo_stream := omit,</span><br><span style="color: hsl(120, 100%, 40%);">+ sinfo_ppid := 18,</span><br><span style="color: hsl(120, 100%, 40%);">+ remSocks := omit,</span><br><span style="color: hsl(120, 100%, 40%);">+ assocId := omit</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ pout.msg := enc_S1AP_PDU(pin.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ } with { extension "prototype(fast)" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ type port S1AP_CODEC_PT message {</span><br><span style="color: hsl(120, 100%, 40%);">+ out S1AP_Send;</span><br><span style="color: hsl(120, 100%, 40%);">+ in S1AP_RecvFrom,</span><br><span style="color: hsl(120, 100%, 40%);">+ ASP_ConnId_ReadyToRelease,</span><br><span style="color: hsl(120, 100%, 40%);">+ ASP_Event;</span><br><span style="color: hsl(120, 100%, 40%);">+ } with { extension "user IPL4asp_PT</span><br><span style="color: hsl(120, 100%, 40%);">+ out(S1AP_Send -> ASP_Send:function(S1AP_to_IPL4_Send))</span><br><span style="color: hsl(120, 100%, 40%);">+ in(ASP_RecvFrom -> S1AP_RecvFrom: function(IPL4_to_S1AP_RecvFrom);</span><br><span style="color: hsl(120, 100%, 40%);">+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;</span><br><span style="color: hsl(120, 100%, 40%);">+ ASP_Event -> ASP_Event: simple)"</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/library/S1AP_CodecPort_CtrlFunct.ttcn b/library/S1AP_CodecPort_CtrlFunct.ttcn</span><br><span>new file mode 100644</span><br><span>index 0000000..0399199</span><br><span>--- /dev/null</span><br><span>+++ b/library/S1AP_CodecPort_CtrlFunct.ttcn</span><br><span>@@ -0,0 +1,44 @@</span><br><span style="color: hsl(120, 100%, 40%);">+module S1AP_CodecPort_CtrlFunct {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ import from S1AP_CodecPort all;</span><br><span style="color: hsl(120, 100%, 40%);">+ import from IPL4asp_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ external function f_IPL4_listen(</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_CODEC_PT portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ in HostName locName,</span><br><span style="color: hsl(120, 100%, 40%);">+ in PortNumber locPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ProtoTuple proto,</span><br><span style="color: hsl(120, 100%, 40%);">+ in OptionList options := {}</span><br><span style="color: hsl(120, 100%, 40%);">+ ) return Result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ external function f_IPL4_connect(</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_CODEC_PT portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ in HostName remName,</span><br><span style="color: hsl(120, 100%, 40%);">+ in PortNumber remPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ in HostName locName,</span><br><span style="color: hsl(120, 100%, 40%);">+ in PortNumber locPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ConnectionId connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ProtoTuple proto,</span><br><span style="color: hsl(120, 100%, 40%);">+ in OptionList options := {}</span><br><span style="color: hsl(120, 100%, 40%);">+ ) return Result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ external function f_IPL4_close(</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_CODEC_PT portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ConnectionId id,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ProtoTuple proto := { unspecified := {} }</span><br><span style="color: hsl(120, 100%, 40%);">+ ) return Result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ external function f_IPL4_setUserData(</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_CODEC_PT portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ConnectionId id,</span><br><span style="color: hsl(120, 100%, 40%);">+ in UserData userData</span><br><span style="color: hsl(120, 100%, 40%);">+ ) return Result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ external function f_IPL4_getUserData(</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_CODEC_PT portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ in ConnectionId id,</span><br><span style="color: hsl(120, 100%, 40%);">+ out UserData userData</span><br><span style="color: hsl(120, 100%, 40%);">+ ) return Result;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/library/S1AP_CodecPort_CtrlFunctDef.cc b/library/S1AP_CodecPort_CtrlFunctDef.cc</span><br><span>new file mode 100644</span><br><span>index 0000000..dc73046</span><br><span>--- /dev/null</span><br><span>+++ b/library/S1AP_CodecPort_CtrlFunctDef.cc</span><br><span>@@ -0,0 +1,56 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include "IPL4asp_PortType.hh"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "S1AP_CodecPort.hh"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "IPL4asp_PT.hh"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+namespace S1AP__CodecPort__CtrlFunct {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::Result f__IPL4__listen(</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP__CodecPort::S1AP__CODEC__PT& portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::HostName& locName,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::PortNumber& locPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ProtoTuple& proto,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::OptionList& options)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::Result f__IPL4__connect(</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP__CodecPort::S1AP__CODEC__PT& portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::HostName& remName,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::PortNumber& remPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::HostName& locName,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::PortNumber& locPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ConnectionId& connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ProtoTuple& proto,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::OptionList& options)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,</span><br><span style="color: hsl(120, 100%, 40%);">+ locName, locPort, connId, proto, options);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::Result f__IPL4__close(</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP__CodecPort::S1AP__CODEC__PT& portRef, </span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ConnectionId& connId, </span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ProtoTuple& proto)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ return f__IPL4__PROVIDER__close(portRef, connId, proto);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::Result f__IPL4__setUserData(</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP__CodecPort::S1AP__CODEC__PT& portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ConnectionId& connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::UserData& userData)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::Result f__IPL4__getUserData(</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP__CodecPort::S1AP__CODEC__PT& portRef,</span><br><span style="color: hsl(120, 100%, 40%);">+ const IPL4asp__Types::ConnectionId& connId,</span><br><span style="color: hsl(120, 100%, 40%);">+ IPL4asp__Types::UserData& userData)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/library/S1AP_Emulation.ttcn b/library/S1AP_Emulation.ttcn</span><br><span>new file mode 100644</span><br><span>index 0000000..d09b499</span><br><span>--- /dev/null</span><br><span>+++ b/library/S1AP_Emulation.ttcn</span><br><span>@@ -0,0 +1,681 @@</span><br><span style="color: hsl(120, 100%, 40%);">+module S1AP_Emulation {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* S1AP Emulation, runs on top of S1AP_CodecPort. It multiplexes/demultiplexes</span><br><span style="color: hsl(120, 100%, 40%);">+ * the individual IMSIs/subscribers, so there can be separate TTCN-3 components handling</span><br><span style="color: hsl(120, 100%, 40%);">+ * each of them.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The S1AP_Emulation.main() function processes S1AP primitives from the S1AP</span><br><span style="color: hsl(120, 100%, 40%);">+ * socket via the S1AP_CodecPort, and dispatches them to the per-IMSI components.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * For each new IMSI, the S1apOps.create_cb() is called. It can create</span><br><span style="color: hsl(120, 100%, 40%);">+ * or resolve a TTCN-3 component, and returns a component reference to which that IMSI</span><br><span style="color: hsl(120, 100%, 40%);">+ * is routed/dispatched.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * If a pre-existing component wants to register to handle a future inbound IMSI, it can</span><br><span style="color: hsl(120, 100%, 40%);">+ * do so by registering an "expect" with the expected IMSI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Inbound non-UE related S1AP messages (such as RESET, SETUP, OVERLOAD) are dispatched to</span><br><span style="color: hsl(120, 100%, 40%);">+ * the S1apOps.unitdata_cb() callback, which is registered with an argument to the</span><br><span style="color: hsl(120, 100%, 40%);">+ * main() function below.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * All rights reserved.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Released under the terms of GNU General Public License, Version 2 or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0-or-later</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_CodecPort all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_CodecPort_CtrlFunct all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_Constants all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_PDU_Contents all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_PDU_Descriptions all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_IEs all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from S1AP_Templates all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from NAS_EPS_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from NAS_Templates all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from LTE_CryptoFunctions all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import from General_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from Osmocom_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from IPL4asp_Types all;</span><br><span style="color: hsl(120, 100%, 40%);">+import from DNS_Helpers all;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type component S1AP_ConnHdlr {</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1AP_Conn_PT S1AP;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* procedure based port to register for incoming connections */</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1APEM_PROC_PT S1AP_PROC;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* port between individual per-connection components and this dispatcher */</span><br><span style="color: hsl(120, 100%, 40%);">+type port S1AP_Conn_PT message {</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_PDU, PDU_NAS_EPS, S1APEM_Config;</span><br><span style="color: hsl(120, 100%, 40%);">+} with { extension "internal" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type record NAS_Keys {</span><br><span style="color: hsl(120, 100%, 40%);">+ octetstring k_nas_int,</span><br><span style="color: hsl(120, 100%, 40%);">+ octetstring k_nas_enc</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+type union S1APEM_Config {</span><br><span style="color: hsl(120, 100%, 40%);">+ NAS_Keys set_nas_keys</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type enumerated S1APEM_EventUpDown {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1APEM_EVENT_DOWN,</span><br><span style="color: hsl(120, 100%, 40%);">+ S1APEM_EVENT_UP</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* an event indicating us whether or not a connection is physically up or down,</span><br><span style="color: hsl(120, 100%, 40%);">+ * and whether we have received an ID_ACK */</span><br><span style="color: hsl(120, 100%, 40%);">+type union S1APEM_Event {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1APEM_EventUpDown up_down</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* global test port e.g. for non-imsi/conn specific messages */</span><br><span style="color: hsl(120, 100%, 40%);">+type port S1AP_PT message {</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1AP_PDU, S1APEM_Event;</span><br><span style="color: hsl(120, 100%, 40%);">+} with { extension "internal" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* represents a single S1AP Association */</span><br><span style="color: hsl(120, 100%, 40%);">+type record AssociationData {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_ConnHdlr comp_ref, /* component handling this UE connection */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint24_t enb_ue_s1ap_id optional, /* eNB side S1AP ID */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t mme_ue_s1ap_id optional, /* MME side S1AP ID */</span><br><span style="color: hsl(120, 100%, 40%);">+ EUTRAN_CGI cgi optional,</span><br><span style="color: hsl(120, 100%, 40%);">+ TAI tai optional,</span><br><span style="color: hsl(120, 100%, 40%);">+ NAS_UE_State nus</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ //hexstring imsi optional</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type component S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Port facing to the UDP SUT */</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1AP_CODEC_PT S1AP;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* All S1AP_ConnHdlr S1AP ports connect here</span><br><span style="color: hsl(120, 100%, 40%);">+ * S1AP_Emulation_CT.main needs to figure out what messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * to send where with CLIENT.send() to vc_conn */</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1AP_Conn_PT S1AP_CLIENT;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* currently tracked connections */</span><br><span style="color: hsl(120, 100%, 40%);">+ var AssociationData S1apAssociationTable[16];</span><br><span style="color: hsl(120, 100%, 40%);">+ /* pending expected CRCX */</span><br><span style="color: hsl(120, 100%, 40%);">+ var ExpectData S1apExpectTable[8];</span><br><span style="color: hsl(120, 100%, 40%);">+ /* procedure based port to register for incoming connections */</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1APEM_PROC_PT S1AP_PROC;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* test port for unit data messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ port S1AP_PT S1AP_UNIT;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_conn_parameters g_pars;</span><br><span style="color: hsl(120, 100%, 40%);">+ var charstring g_s1ap_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer g_s1ap_conn_id := -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type function S1APCreateCallback(S1AP_PDU msg, template (omit) MME_UE_S1AP_ID mme_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ template (omit) ENB_UE_S1AP_ID enb_id, charstring id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return S1AP_ConnHdlr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type function S1APUnitdataCallback(S1AP_PDU msg)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return template S1AP_PDU;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type record S1APOps {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1APCreateCallback create_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ S1APUnitdataCallback unitdata_cb</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type record S1AP_conn_parameters {</span><br><span style="color: hsl(120, 100%, 40%);">+ HostName remote_ip,</span><br><span style="color: hsl(120, 100%, 40%);">+ PortNumber remote_sctp_port,</span><br><span style="color: hsl(120, 100%, 40%);">+ HostName local_ip,</span><br><span style="color: hsl(120, 100%, 40%);">+ PortNumber local_sctp_port,</span><br><span style="color: hsl(120, 100%, 40%);">+ NAS_Role role</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function tr_S1AP_RecvFrom_R(template S1AP_PDU msg)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return template S1AP_RecvFrom {</span><br><span style="color: hsl(120, 100%, 40%);">+ var template S1AP_RecvFrom mrf := {</span><br><span style="color: hsl(120, 100%, 40%);">+ connId := g_s1ap_conn_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ remName := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ remPort := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ locName := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ locPort := ?,</span><br><span style="color: hsl(120, 100%, 40%);">+ msg := msg</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return mrf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_s1ap_ids_known(template (omit) MME_UE_S1AP_ID mme_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ template (omit) ENB_UE_S1AP_ID enb_id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return boolean {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ log("f_s1ap_ids_known(",mme_id,", ",enb_id,")");</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ log("tbl[",i,"]: mme=", S1apAssociationTable[i].mme_ue_s1ap_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ ", enb=", S1apAssociationTable[i].enb_ue_s1ap_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* skip empty records */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (S1apAssociationTable[i].mme_ue_s1ap_id == omit and</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].enb_ue_s1ap_id == omit) {</span><br><span style="color: hsl(120, 100%, 40%);">+ log("skipping empty ", i);</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (S1apAssociationTable[i].mme_ue_s1ap_id == omit) {</span><br><span style="color: hsl(120, 100%, 40%);">+ log("entry ", i, " has no MME ID yet (enb=", S1apAssociationTable[i].enb_ue_s1ap_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Table doesn't yet know the MME side ID, let's look-up only</span><br><span style="color: hsl(120, 100%, 40%);">+ * based on the eNB side ID */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match(S1apAssociationTable[i].enb_ue_s1ap_id, enb_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* update table with MME side ID */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id := valueof(mme_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (match(S1apAssociationTable[i].enb_ue_s1ap_id, enb_id) and</span><br><span style="color: hsl(120, 100%, 40%);">+ match(S1apAssociationTable[i].mme_ue_s1ap_id, mme_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_comp_known(S1AP_ConnHdlr client)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return boolean {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (S1apAssociationTable[i].comp_ref == client) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_assoc_id_by_s1ap_ids(template (omit) MME_UE_S1AP_ID mme_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ template (omit) ENB_UE_S1AP_ID enb_id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return integer {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match(S1apAssociationTable[i].enb_ue_s1ap_id, enb_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (istemplatekind(mme_id, "omit")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match(S1apAssociationTable[i].mme_ue_s1ap_id, mme_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "S1AP Association Table not found by ENB-ID=", enb_id, " MME-ID=", mme_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_assoc_id_by_comp(S1AP_ConnHdlr client)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return integer {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (S1apAssociationTable[i].comp_ref == client) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "S1AP Association Table not found by component ", client);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_assoc_by_comp(S1AP_ConnHdlr client)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return AssociationData {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i := f_assoc_id_by_comp(client);</span><br><span style="color: hsl(120, 100%, 40%);">+ return S1apAssociationTable[i];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_s1ap_id_table_add(S1AP_ConnHdlr comp_ref,</span><br><span style="color: hsl(120, 100%, 40%);">+ template (omit) MME_UE_S1AP_ID mme_id, ENB_UE_S1AP_ID enb_id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return integer {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (not isvalue(S1apAssociationTable[i].enb_ue_s1ap_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].enb_ue_s1ap_id := enb_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (istemplatekind(mme_id, "omit")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id := valueof(mme_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].comp_ref := comp_ref;</span><br><span style="color: hsl(120, 100%, 40%);">+ return i;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ testcase.stop("S1AP Association Table full!");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_s1ap_id_table_del(S1AP_ConnHdlr comp_ref, ENB_UE_S1AP_ID enb_id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (S1apAssociationTable[i].comp_ref == comp_ref and</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id == enb_id) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].enb_ue_s1ap_id := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].comp_ref := null;</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "S1AP Association Table: Couldn't find to-be-deleted entry!");</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_s1ap_id_table_init()</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (var integer i := 0; i < sizeof(S1apAssociationTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].mme_ue_s1ap_id := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].enb_ue_s1ap_id := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].cgi := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].tai := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[i].nus := valueof(t_NAS_UE_State(g_pars.role));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private template (value) SctpTuple ts_SCTP(template (omit) integer ppid := 18) := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sinfo_stream := omit,</span><br><span style="color: hsl(120, 100%, 40%);">+ sinfo_ppid := ppid,</span><br><span style="color: hsl(120, 100%, 40%);">+ remSocks := omit,</span><br><span style="color: hsl(120, 100%, 40%);">+ assocId := omit</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private template PortEvent tr_SctpAssocChange := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sctpEvent := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sctpAssocChange := ?</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+private template PortEvent tr_SctpPeerAddrChange := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sctpEvent := {</span><br><span style="color: hsl(120, 100%, 40%);">+ sctpPeerAddrChange := ?</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_s1ap_xceive(template (value) S1AP_PDU tx,</span><br><span style="color: hsl(120, 100%, 40%);">+ template S1AP_PDU rx_t := ?)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return S1AP_PDU {</span><br><span style="color: hsl(120, 100%, 40%);">+ timer T := 10.0;</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_RecvFrom mrf;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id, tx));</span><br><span style="color: hsl(120, 100%, 40%);">+ alt {</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_S1AP_RecvFrom_R(rx_t)) -> value mrf { }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_SctpAssocChange) { repeat; }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_SctpPeerAddrChange) { repeat; }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] T.timeout {</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "Timeout waiting for ", rx_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return mrf.msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_nas_try_decaps(PDU_NAS_EPS nas) return PDU_NAS_EPS</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ var PDU_NAS_EPS_SecurityProtectedNASMessage secp_nas;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (not match(nas, tr_NAS_EMM_SecurityProtected)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return nas;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ secp_nas := nas.ePS_messages.ePS_MobilityManagement.pDU_NAS_EPS_SecurityProtectedNASMessage;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (secp_nas.securityHeaderType) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case ('0011'B) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var octetstring knas_int := '530ce32318f26264eab26bc116870b86'O;</span><br><span style="color: hsl(120, 100%, 40%);">+ var octetstring data_with_seq := int2oct(secp_nas.sequenceNumber, 1) & secp_nas.nAS_Message;</span><br><span style="color: hsl(120, 100%, 40%);">+ var OCT4 exp_mac := f_snow_3g_f9(knas_int, secp_nas.sequenceNumber, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ is_downlink:=true, data:=data_with_seq);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (exp_mac != secp_nas.messageAuthenticationCode) {</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "Received NAS MAC ", secp_nas.messageAuthenticationCode,</span><br><span style="color: hsl(120, 100%, 40%);">+ " doesn't match expected MAC ", exp_mac, ": ", nas);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return dec_PDU_NAS_EPS(secp_nas.nAS_Message);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case else {</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "Implement SecHdrType for ", secp_nas);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+*/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function main(S1APOps ops, S1AP_conn_parameters p, charstring id) runs on S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ var Result res;</span><br><span style="color: hsl(120, 100%, 40%);">+ g_pars := p;</span><br><span style="color: hsl(120, 100%, 40%);">+ g_s1ap_id := id;</span><br><span style="color: hsl(120, 100%, 40%);">+ f_s1ap_id_table_init();</span><br><span style="color: hsl(120, 100%, 40%);">+ f_expect_table_init();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ map(self:S1AP, system:S1AP_CODEC_PT);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p.remote_sctp_port == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ res := S1AP_CodecPort_CtrlFunct.f_IPL4_listen(S1AP, p.local_ip, p.local_sctp_port, { sctp := valueof(ts_SCTP) });</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ res := S1AP_CodecPort_CtrlFunct.f_IPL4_connect(S1AP, p.remote_ip, p.remote_sctp_port,</span><br><span style="color: hsl(120, 100%, 40%);">+ p.local_ip, p.local_sctp_port, -1, { sctp := valueof(ts_SCTP) });</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (not ispresent(res.connId)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "Could not connect S1AP socket, check your configuration");</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ g_s1ap_conn_id := res.connId;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* notify user about SCTP establishment */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p.remote_sctp_port != -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_UNIT.send(S1APEM_Event:{up_down:=S1APEM_EVENT_UP})</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while (true) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_ConnHdlr vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ var PDU_NAS_EPS nas;</span><br><span style="color: hsl(120, 100%, 40%);">+ var hexstring imsi;</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_RecvFrom mrf;</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_PDU msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1APEM_Config s1cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ var charstring vlr_name, mme_name;</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer ai;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ alt {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Configuration primitive from client */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_CLIENT.receive(S1APEM_Config:{set_nas_keys:=?}) -> value s1cfg sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[assoc_id].nus.k_nas_int := s1cfg.set_nas_keys.k_nas_int;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[assoc_id].nus.k_nas_enc := s1cfg.set_nas_keys.k_nas_enc;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* S1AP from client: InitialUE */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_CLIENT.receive(tr_S1AP_InitialUE) -> value msg sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* create a table entry about this connection */</span><br><span style="color: hsl(120, 100%, 40%);">+ ai := f_s1ap_id_table_add(vc_conn, omit, valueof(f_S1AP_get_ENB_UE_S1AP_ID(msg)));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Store CGI + TAI so we can use it for generating UlNasTransport from NAS */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[ai].tai := msg.initiatingMessage.value_.InitialUEMessage.protocolIEs[2].value_.TAI;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apAssociationTable[ai].cgi := msg.initiatingMessage.value_.InitialUEMessage.protocolIEs[3].value_.EUTRAN_CGI;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Pass message through */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id, msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* NAS from client: Wrap in S1AP Uplink NAS Transport */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_CLIENT.receive(PDU_NAS_EPS:?) -> value nas sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer assoc_id := f_assoc_id_by_comp(vc_conn);</span><br><span style="color: hsl(120, 100%, 40%);">+ var AssociationData ad := S1apAssociationTable[assoc_id];</span><br><span style="color: hsl(120, 100%, 40%);">+ nas := f_nas_encaps(S1apAssociationTable[assoc_id].nus, nas, new_ctx := false);</span><br><span style="color: hsl(120, 100%, 40%);">+ var octetstring nas_enc := enc_PDU_NAS_EPS(nas);</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ ts_S1AP_UlNasTransport(ad.mme_ue_s1ap_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ ad.enb_ue_s1ap_id,</span><br><span style="color: hsl(120, 100%, 40%);">+ nas_enc, ad.cgi, ad.tai)));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* S1AP from client: pass on transparently */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_CLIENT.receive(S1AP_PDU:?) -> value msg sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Pass message through */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: validate S1AP_IDs ? */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id, msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* non-UE related S1AP: pass through unmodified/unverified */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_UNIT.receive(S1AP_PDU:?) -> value msg sender vc_conn {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Pass message through */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id, msg));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* S1AP received from peer (MME) */</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_S1AP_RecvFrom_R(?)) -> value mrf {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match(mrf.msg, tr_S1AP_nonUErelated)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* non-UE-related S1AP message */</span><br><span style="color: hsl(120, 100%, 40%);">+ var template S1AP_PDU resp := ops.unitdata_cb.apply(mrf.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (isvalue(resp)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP.send(t_S1AP_Send(g_s1ap_conn_id, valueof(resp)));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (match(mrf.msg, tr_S1AP_UeContextReleaseCmd)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: special handling, as it contains multiple eNB or MME IDs */</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "implement UeContextReleaseCmd handling");</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Ue-related S1AP message */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* obtain MME + ENB UE S1AP ID */</span><br><span style="color: hsl(120, 100%, 40%);">+ var template (omit) MME_UE_S1AP_ID mme_ue_id := f_S1AP_get_MME_UE_S1AP_ID(mrf.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ var template (omit) ENB_UE_S1AP_ID enb_ue_id := f_S1AP_get_ENB_UE_S1AP_ID(mrf.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* check if those IDs are known in our table */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (f_s1ap_ids_known(mme_ue_id, enb_ue_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* if yes, dispatch to the ConnHdlr for this Ue-Connection */</span><br><span style="color: hsl(120, 100%, 40%);">+ var template (omit) octetstring nas_enc;</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer assoc_id := f_assoc_id_by_s1ap_ids(mme_ue_id, enb_ue_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ vc_conn := S1apAssociationTable[assoc_id].comp_ref;</span><br><span style="color: hsl(120, 100%, 40%);">+ nas_enc := f_S1AP_get_NAS_PDU(mrf.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (isvalue(nas_enc)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ nas := dec_PDU_NAS_EPS(valueof(nas_enc));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (match(nas, tr_NAS_EMM_SecurityProtected)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ nas := f_nas_try_decaps(S1apAssociationTable[assoc_id].nus, nas);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send decoded NAS */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_CLIENT.send(nas) to vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* send raw S1AP */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_CLIENT.send(mrf.msg) to vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* if not, call create_cb so it can create new ConnHdlr */</span><br><span style="color: hsl(120, 100%, 40%);">+ vc_conn := ops.create_cb.apply(mrf.msg, mme_ue_id, enb_ue_id, id);</span><br><span style="color: hsl(120, 100%, 40%);">+ f_s1ap_id_table_add(vc_conn, mme_ue_id, valueof(enb_ue_id));</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_CLIENT.send(mrf.msg) to vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_SctpAssocChange) { }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP.receive(tr_SctpPeerAddrChange) { }</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_PROC.getcall(S1APEM_register:{?,?}) -> param(imsi, vc_conn) {</span><br><span style="color: hsl(120, 100%, 40%);">+ f_create_expect(imsi, vc_conn);</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_PROC.reply(S1APEM_register:{imsi, vc_conn}) to vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* "Expect" Handling */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type record ExpectData {</span><br><span style="color: hsl(120, 100%, 40%);">+ hexstring imsi optional,</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_ConnHdlr vc_conn</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+signature S1APEM_register(in hexstring imsi, in S1AP_ConnHdlr hdlr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+type port S1APEM_PROC_PT procedure {</span><br><span style="color: hsl(120, 100%, 40%);">+ inout S1APEM_register;</span><br><span style="color: hsl(120, 100%, 40%);">+} with { extension "internal" };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Function that can be used as create_cb and will usse the expect table */</span><br><span style="color: hsl(120, 100%, 40%);">+function ExpectedCreateCallback(S1AP_PDU msg, hexstring imsi, charstring id)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return S1AP_ConnHdlr {</span><br><span style="color: hsl(120, 100%, 40%);">+ var S1AP_ConnHdlr ret := null;</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (not ispresent(S1apExpectTable[i].imsi)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (imsi == S1apExpectTable[i].imsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ret := S1apExpectTable[i].vc_conn;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Release this entry */</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apExpectTable[i].imsi := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apExpectTable[i].vc_conn := null;</span><br><span style="color: hsl(120, 100%, 40%);">+ log("Found Expect[", i, "] for ", msg, " handled at ", ret);</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "Couldn't find Expect for ", msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_create_expect(hexstring imsi, S1AP_ConnHdlr hdlr)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Check an entry like this is not already presnt */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (imsi == S1apExpectTable[i].imsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ setverdict(fail, "IMSI already present", imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+ mtc.stop;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apExpectTable); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (not ispresent(S1apExpectTable[i].imsi)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apExpectTable[i].imsi := imsi;</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apExpectTable[i].vc_conn := hdlr;</span><br><span style="color: hsl(120, 100%, 40%);">+ log("Created Expect[", i, "] for ", imsi, " to be handled at ", hdlr);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ testcase.stop("No space left in S1apExpectTable")</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* client/conn_hdlr side function to use procedure port to create expect in emulation */</span><br><span style="color: hsl(120, 100%, 40%);">+function f_create_s1ap_expect(hexstring imsi) runs on S1AP_ConnHdlr {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1AP_PROC.call(S1APEM_register:{imsi, self}) {</span><br><span style="color: hsl(120, 100%, 40%);">+ [] S1AP_PROC.getreply(S1APEM_register:{?,?}) {};</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+private function f_expect_table_init()</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT {</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < sizeof(S1apExpectTable); i := i + 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ S1apExpectTable[i].imsi := omit;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function DummyUnitdataCallback(S1AP_PDU msg)</span><br><span style="color: hsl(120, 100%, 40%);">+runs on S1AP_Emulation_CT return template S1AP_PDU {</span><br><span style="color: hsl(120, 100%, 40%);">+ log("Ignoring S1AP ", msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ return omit;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function f_S1AP_get_ENB_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) ENB_UE_S1AP_ID</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ischosen(s1ap.initiatingMessage)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var InitiatingMessage im := s1ap.initiatingMessage;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_InitialUE) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.InitialUEMessage.protocolIEs[0].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_DlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.DownlinkNASTransport.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.UplinkNASTransport.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_IntialCtxSetupReq) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.initialContextSetupRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UeContextReleaseReq) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.UEContextReleaseRequest.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* UeContextReleaseCmd needs special handling; it can contain any number of MME/UE IDs */</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_ConnEstInd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.ConnectionEstablishmentIndication.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ischosen(s1ap.successfulOutcome)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var SuccessfulOutcome so := s1ap.successfulOutcome;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_InitialCtxSetupResp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return so.value_.initialContextSetupResponse.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UeContextReleaseCompl) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return so.value_.UEContextReleaseComplete.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ischosen(s1ap.unsuccessfulOutcome)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var UnsuccessfulOutcome uo := s1ap.unsuccessfulOutcome;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_InitialCtxSetupFail) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return uo.value_.initialContextSetupFailure.protocolIEs[1].value_.ENB_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return omit;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function f_S1AP_get_MME_UE_S1AP_ID(S1AP_PDU s1ap) return template (omit) MME_UE_S1AP_ID</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ischosen(s1ap.initiatingMessage)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var InitiatingMessage im := s1ap.initiatingMessage;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_DlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.DownlinkNASTransport.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.UplinkNASTransport.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_IntialCtxSetupReq) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.initialContextSetupRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UeContextReleaseReq) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.UEContextReleaseRequest.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* UeContextReleaseCmd needs special handling; it can contain any number of MME/UE IDs */</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_ConnEstInd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return im.value_.ConnectionEstablishmentIndication.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ischosen(s1ap.successfulOutcome)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var SuccessfulOutcome so := s1ap.successfulOutcome;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_InitialCtxSetupResp) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return so.value_.initialContextSetupResponse.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UeContextReleaseCompl) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return so.value_.UEContextReleaseComplete.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (ischosen(s1ap.unsuccessfulOutcome)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var UnsuccessfulOutcome uo := s1ap.unsuccessfulOutcome;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_InitialCtxSetupFail) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return uo.value_.initialContextSetupFailure.protocolIEs[0].value_.MME_UE_S1AP_ID;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return omit;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+function f_S1AP_get_NAS_PDU(S1AP_PDU s1ap) return template (omit) NAS_PDU</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ var integer i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ischosen(s1ap.initiatingMessage)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var InitiatingMessage im := s1ap.initiatingMessage;</span><br><span style="color: hsl(120, 100%, 40%);">+ select (s1ap) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_DlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var DownlinkNASTransport msg := im.value_.DownlinkNASTransport;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg.protocolIEs[i].id == id_NAS_PDU) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return msg.protocolIEs[i].value_.NAS_PDU;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ case (tr_S1AP_UlNasTransport) {</span><br><span style="color: hsl(120, 100%, 40%);">+ var UplinkNASTransport msg := im.value_.UplinkNASTransport;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg.protocolIEs[i].id == id_NAS_PDU) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return msg.protocolIEs[i].value_.NAS_PDU;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return omit;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/mme/gen_links.sh b/mme/gen_links.sh</span><br><span>index 2a98c70..1f2d85b 100755</span><br><span>--- a/mme/gen_links.sh</span><br><span>+++ b/mme/gen_links.sh</span><br><span>@@ -31,10 +31,17 @@</span><br><span> FILES="SGsAP_Types.ttcn"</span><br><span> gen_links $DIR $FILES</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DIR=../library/s1ap</span><br><span style="color: hsl(120, 100%, 40%);">+FILES="S1AP_CommonDataTypes.asn S1AP_Constants.asn S1AP_Containers.asn S1AP_IEs.asn S1AP_PDU_Contents.asn</span><br><span style="color: hsl(120, 100%, 40%);">+S1AP_PDU_Descriptions.asn "</span><br><span style="color: hsl(120, 100%, 40%);">+FILES+="S1AP_EncDec.cc S1AP_Types.ttcn "</span><br><span style="color: hsl(120, 100%, 40%);">+gen_links $DIR $FILES</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> DIR=../library</span><br><span> FILES="Misc_Helpers.ttcn General_Types.ttcn GSM_Types.ttcn Osmocom_Types.ttcn Native_Functions.ttcn Native_FunctionDefs.cc "</span><br><span> FILES+="SGsAP_Templates.ttcn SGsAP_CodecPort.ttcn SGsAP_CodecPort_CtrlFunct.ttcn SGsAP_CodecPort_CtrlFunctDef.cc SGsAP_Emulation.ttcn DNS_Helpers.ttcn "</span><br><span> FILES+="L3_Templates.ttcn "</span><br><span style="color: hsl(120, 100%, 40%);">+FILES+="S1AP_CodecPort.ttcn "</span><br><span> gen_links $DIR $FILES</span><br><span> </span><br><span> ignore_pp_results</span><br><span>diff --git a/mme/regen_makefile.sh b/mme/regen_makefile.sh</span><br><span>index 4d6d7c6..ee73658 100755</span><br><span>--- a/mme/regen_makefile.sh</span><br><span>+++ b/mme/regen_makefile.sh</span><br><span>@@ -1,6 +1,6 @@</span><br><span> #!/bin/sh</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc TCCConversion.cc TCCEncoding.cc TCCInterface.cc TELNETasp_PT.cc "</span><br><span style="color: hsl(120, 100%, 40%);">+FILES="*.ttcn *.asn IPL4asp_PT.cc IPL4asp_discovery.cc Native_FunctionDefs.cc SGsAP_CodecPort_CtrlFunctDef.cc TCCConversion.cc TCCEncoding.cc TCCInterface.cc TELNETasp_PT.cc S1AP_EncDec.cc "</span><br><span> </span><br><span> export CPPFLAGS_TTCN3=""</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15196">change 15196</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15196"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-ttcn3-hacks </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I9bfba3ab2a3830e590b203c44c03b9c9383fff99 </div>
<div style="display:none"> Gerrit-Change-Number: 15196 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>