<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/15196">View Change</a></p><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;">git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/96/15196/1</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: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>