fixeria has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/41125?usp=email )


Change subject: s1gw: implement the REST interface client
......................................................................

s1gw: implement the REST interface client

OsmoS1GW implements a custom (non-standard) REST interface, primarily
intended for state introspection.  The interface is specified using
OpenAPI, with the specification available in osmo-s1gw.git.

Change-Id: Ic6e8b46b7de4fb72139b017fc9a9c83f92fc1541
Related: SYS#7066
---
M s1gw/S1GW_ConnHdlr.ttcn
A s1gw/S1GW_REST_Functions.ttcn
A s1gw/S1GW_REST_Types.ttcn
M s1gw/S1GW_Tests.cfg
M s1gw/S1GW_Tests.default
M s1gw/S1GW_Tests.ttcn
M s1gw/gen_links.sh
M s1gw/regen_makefile.sh
8 files changed, 290 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks 
refs/changes/25/41125/1

diff --git a/s1gw/S1GW_ConnHdlr.ttcn b/s1gw/S1GW_ConnHdlr.ttcn
index 4e47544..15942cb 100644
--- a/s1gw/S1GW_ConnHdlr.ttcn
+++ b/s1gw/S1GW_ConnHdlr.ttcn
@@ -36,12 +36,15 @@

 import from SCTP_Templates all;

+import from HTTP_Adapter all;
+import from HTTPmsg_Types all;
+
 import from StatsD_Types all;
 import from StatsD_Checker all;

 import from S1AP_Server all;

-type component ConnHdlr extends MutexCT, S1APSRV_ConnHdlr, PFCP_ConnHdlr, 
StatsD_ConnHdlr {
+type component ConnHdlr extends MutexCT, S1APSRV_ConnHdlr, PFCP_ConnHdlr, 
StatsD_ConnHdlr, http_CT {
        var ConnHdlrPars g_pars;
        port S1AP_CODEC_PT S1AP_ENB;
        var ConnectionId g_s1ap_conn_id := -1;
diff --git a/s1gw/S1GW_REST_Functions.ttcn b/s1gw/S1GW_REST_Functions.ttcn
new file mode 100644
index 0000000..fb8731b
--- /dev/null
+++ b/s1gw/S1GW_REST_Functions.ttcn
@@ -0,0 +1,94 @@
+/* REST interface API for OsmoS1GW
+ *
+ * (C) 2025 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanits...@sysmocom.de>
+ *
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module S1GW_REST_Functions {
+
+import from HTTP_Adapter all;
+import from HTTPmsg_Types all;
+import from S1GW_REST_Types all;
+
+/* Get a list of metrics */
+function f_REST_MetricsList(charstring metric_type := "all",
+                           charstring path := "")
+runs on http_CT return MetricsList {
+       var HTTPMessage rsp := f_http_transact("/metrics-list?type=" & 
metric_type & "&path=" & path);
+       return dec_MetricsList(char2oct(rsp.response.body));
+}
+
+/* Get the PFCP association state */
+function f_REST_PfcpAssocState()
+runs on http_CT return PfcpAssocInfo {
+       var HTTPMessage rsp := f_http_transact("/pfcp/assoc", method := "GET");
+       return dec_PfcpAssocInfo(char2oct(rsp.response.body));
+}
+
+/* Initiate the PFCP Association Setup procedure */
+function f_REST_PfcpAssocSetup()
+runs on http_CT return OperationResult {
+       var HTTPMessage rsp := f_http_transact("/pfcp/assoc", method := "POST");
+       return dec_OperationResult(char2oct(rsp.response.body));
+}
+
+/* Initiate the PFCP Association Release procedure */
+function f_REST_PfcpAssocRelease()
+runs on http_CT return OperationResult {
+       var HTTPMessage rsp := f_http_transact("/pfcp/assoc", method := 
"DELETE");
+       return dec_OperationResult(char2oct(rsp.response.body));
+}
+
+/* Send a PFCP Heartbeat Request to the peer */
+function f_REST_PfcpHeartbeat()
+runs on http_CT return OperationResult {
+       var HTTPMessage rsp := f_http_transact("/pfcp/heartbeat", method := 
"POST");
+       return dec_OperationResult(char2oct(rsp.response.body));
+}
+
+/* Get a list of eNB connections */
+function f_REST_EnbList()
+runs on http_CT return EnbList {
+       var HTTPMessage rsp := f_http_transact("/enb-list", method := "GET");
+       return dec_EnbList(char2oct(rsp.response.body));
+}
+
+/* Get information about a specific eNB */
+function f_REST_EnbInfo(ParamEnbId enb_id)
+runs on http_CT return EnbItem {
+       var charstring p_enb_id := enc_ParamEnbId(enb_id);
+       var HTTPMessage rsp := f_http_transact("/enb/" & p_enb_id, method := 
"GET");
+       return dec_EnbItem(char2oct(rsp.response.body));
+}
+
+/* Get E-RAB list for a specific eNB */
+function f_REST_EnbErabList(ParamEnbId enb_id)
+runs on http_CT return ErabList {
+       var charstring p_enb_id := enc_ParamEnbId(enb_id);
+       var HTTPMessage rsp := f_http_transact("/enb/" & p_enb_id & 
"/erab-list", method := "GET");
+       return dec_ErabList(char2oct(rsp.response.body));
+}
+
+/* Get E-RAB list for all eNBs */
+function f_REST_ErabList()
+runs on http_CT return ErabList {
+       var HTTPMessage rsp := f_http_transact("/erab-list", method := "GET");
+       return dec_ErabList(char2oct(rsp.response.body));
+}
+
+/* Get information about a specific E-RAB */
+function f_REST_ErabInfo(ParamErabId erab_id)
+runs on http_CT return ErabItem {
+       var charstring p_erab_id := enc_ParamErabId(erab_id);
+       var HTTPMessage rsp := f_http_transact("/erab/" & p_erab_id, method := 
"GET");
+       return dec_ErabItem(char2oct(rsp.response.body));
+}
+
+}
diff --git a/s1gw/S1GW_REST_Types.ttcn b/s1gw/S1GW_REST_Types.ttcn
new file mode 100644
index 0000000..8ddbc20
--- /dev/null
+++ b/s1gw/S1GW_REST_Types.ttcn
@@ -0,0 +1,135 @@
+/* REST interface definitions for OsmoS1GW
+ *
+ * (C) 2025 by sysmocom - s.f.m.c. GmbH <i...@sysmocom.de>
+ * Author: Vadim Yanitskiy <vyanits...@sysmocom.de>
+ *
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module S1GW_REST_Types {
+
+type charstring GlobalEnbId (pattern "[0-9]#3-[0-9]#(2,3)-[0-9]+");
+type charstring Pid (pattern "<[0-9]+.[0-9]+.[0-9]+>");
+
+type integer EnbHandle (0..infinity);
+type integer SEID (0..18446744073709551615);
+type integer TEID (0..4294967295);
+type integer Port (0..65535);
+
+type union ParamEnbId {
+       charstring handle (pattern "handle:[0-9]+"),
+       charstring pid (pattern "pid:[0-9]+.[0-9]+.[0-9]+"),
+       charstring genbid (pattern "genbid:[0-9]#3-[0-9]#(2,3)-[0-9]+"),
+       charstring sctp_aid (pattern "(enb|mme)-sctp-aid:[0-9]+"),
+       charstring enb_conn (pattern "enb-conn:[0-9:.]+-[0-9]+")
+} with { encode "TEXT" };
+
+type union ParamErabId {
+       charstring pid (pattern "pid:[0-9]+.[0-9]+.[0-9]+")
+} with { encode "TEXT" };
+
+type set OperationResult {
+       boolean success,
+       charstring msg optional
+} with {
+       variant(msg) "JSON:name as message";
+};
+
+type set of MetricsItem MetricsList;
+type set MetricsItem {
+       MetricType metric_type,
+       charstring metric_name,
+       integer metric_value
+} with {
+       variant(metric_type) "JSON:name as type";
+       variant(metric_name) "JSON:name as name";
+       variant(metric_value) "JSON:name as value";
+};
+
+type enumerated MetricType {
+       counter,
+       gauge
+};
+
+type set PfcpAssocInfo {
+       PfcpAssocState state,           /* Current association state */
+       charstring laddr,               /* Local (bind) IP address */
+       charstring raddr,               /* Remote (connect) IP address */
+       integer lrts optional,          /* Local Recovery TimeStamp */
+       integer rrts optional           /* Remote Recovery TimeStamp */
+};
+
+type enumerated PfcpAssocState {
+       connecting,
+       connected
+};
+
+type set of EnbItem EnbList;
+type set EnbItem {
+       EnbHandle handle,               /* Unique number in the eNB registry */
+       Pid pid,                        /* Process ID */
+       EnbState state,                 /* Connection state */
+       integer uptime,                 /* Uptime (in seconds) */
+       integer erab_count,             /* Total number of E-RABs */
+       GlobalEnbId genb_id optional,   /* Global-eNB-ID (e.g. "001-01-1337") */
+       charstring enb_saddr optional,  /* Source (remote) address of the eNB */
+       charstring mme_daddr optional,  /* Destination (remote) address of the 
MME */
+       Port enb_sport optional,        /* Source (remote) port of the eNB-S1GW 
connection */
+       Port mme_sport optional,        /* Source (local) port of the S1GW-MME 
connection */
+       Port mme_dport optional,        /* Destination (remote) port of the 
S1GW-MME connection */
+       integer enb_sctp_aid optional,  /* SCTP association identifier of the 
eNB-S1GW connection */
+       integer mme_sctp_aid optional   /* SCTP association identifier of the 
eNB-S1GW connection */
+};
+
+type enumerated EnbState {
+       connecting,
+       connected,
+       s1setup
+};
+
+type set of ErabItem ErabList;
+type set ErabItem {
+       integer mme_ue_id,              /* MME-UE-S1AP-ID */
+       integer erab_id,                /* E-RAB-ID */
+       charstring state,               /* E-RAB FSM state */
+       Pid pid,                        /* E-RAB FSM process ID */
+       SEID pfcp_lseid optional,       /* PFCP SEID (local) */
+       SEID pfcp_rseid optional,       /* PFCP SEID (remote) */
+       FTEID f_teid_u2c optional,      /* GTP-U F-TEID for UPF -> Core */
+       FTEID f_teid_c2u optional,      /* GTP-U F-TEID for UPF <- Core */
+       FTEID f_teid_a2u optional,      /* GTP-U F-TEID for UPF <- Access */
+       FTEID f_teid_u2a optional       /* GTP-U F-TEID for UPF -> Access */
+
+};
+
+type set FTEID {
+       TEID teid,                      /* GTP-U TEID */
+       charstring tla                  /* GTP-U TLA (Transport Layer Address) 
*/
+};
+
+external function enc_ParamEnbId(in ParamEnbId enb_id) return charstring
+       with { extension "prototype(convert) encode(TEXT)" }
+external function enc_ParamErabId(in ParamErabId erab_id) return charstring
+       with { extension "prototype(convert) encode(TEXT)" }
+
+external function dec_OperationResult(in octetstring data) return 
OperationResult
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_MetricsList(in octetstring data) return MetricsList
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_PfcpAssocInfo(in octetstring data) return PfcpAssocInfo
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_EnbList(in octetstring data) return EnbList
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_EnbItem(in octetstring data) return EnbItem
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_ErabList(in octetstring data) return ErabList
+       with { extension "prototype(convert) decode(JSON)" }
+external function dec_ErabItem(in octetstring data) return ErabItem
+       with { extension "prototype(convert) decode(JSON)" }
+
+} with { encode "JSON" }
diff --git a/s1gw/S1GW_Tests.cfg b/s1gw/S1GW_Tests.cfg
index 54e7992..94c7591 100644
--- a/s1gw/S1GW_Tests.cfg
+++ b/s1gw/S1GW_Tests.cfg
@@ -19,6 +19,9 @@
 S1GW_Tests.mp_upf_bind_ip := "127.0.3.10";
 S1GW_Tests.mp_local_statsd_ip := "127.0.4.10";
 S1GW_Tests.mp_local_statsd_port := 8125;
+S1GW_Tests.mp_rest_host := "127.0.0.1";
+S1GW_Tests.mp_rest_port := 8125;
+S1GW_Tests.mp_rest_enable := fase;

 [MAIN_CONTROLLER]

diff --git a/s1gw/S1GW_Tests.default b/s1gw/S1GW_Tests.default
index 8f9cfdc..48169e1 100644
--- a/s1gw/S1GW_Tests.default
+++ b/s1gw/S1GW_Tests.default
@@ -5,6 +5,7 @@
 [TESTPORT_PARAMETERS]
 *.S1AP_ENB.noDelay := "yes" // eNB: turn off Nagle
 *.S1AP.noDelay := "yes" // MME: turn off Nagle
+*.HTTP.use_notification_ASPs := "yes"

 [MODULE_PARAMETERS]

diff --git a/s1gw/S1GW_Tests.ttcn b/s1gw/S1GW_Tests.ttcn
index 296c234..466e377 100644
--- a/s1gw/S1GW_Tests.ttcn
+++ b/s1gw/S1GW_Tests.ttcn
@@ -41,10 +41,16 @@
 import from StatsD_CodecPort_CtrlFunct all;
 import from StatsD_Checker all;

+import from HTTP_Adapter all;
+import from HTTPmsg_Types all;
+
 import from S1AP_Server all;
 import from S1GW_ConnHdlr all;
 import from S1GW_UEMux all;

+import from S1GW_REST_Types all;
+import from S1GW_REST_Functions all;
+
 modulepar {
        charstring mp_s1gw_enb_ip := "127.0.1.1";       /* eNB facing address 
of the S1GW */
        charstring mp_enb_bind_ip := "127.0.1.10";      /* eNB address to use 
locally when connecting to S1GW */
@@ -60,9 +66,13 @@

        integer mp_multi_enb_num := 42;                 /* number of eNBs in 
_multi TCs */
        integer mp_multi_ue_num := 128;                 /* number of UEs in 
_multi TCs */
+
+       boolean mp_rest_enable := false;                /* whether enable the 
HTTP/REST interface */
+       charstring mp_rest_host := "127.0.0.1";
+       integer mp_rest_port := 8080;
 }

-type component test_CT extends StatsD_Checker_CT {
+type component test_CT extends StatsD_Checker_CT, http_CT {
        timer g_Tguard;
        var MutexDispCT vc_mutex_disp;
        var S1AP_Server_CT vc_S1APSRV;
@@ -93,6 +103,9 @@
                f_init_pfcp();
                f_pfcp_assoc();
        }
+       if (mp_rest_enable) {
+               f_init_rest();
+       }
 }

 function f_init_s1ap_srv() runs on test_CT {
@@ -131,6 +144,16 @@
        }
 }

+function f_init_rest() runs on test_CT {
+       f_http_init(valueof(t_HTTP_Adapter_Params));
+}
+
+template (value) HTTP_Adapter_Params t_HTTP_Adapter_Params := {
+       http_host := mp_rest_host,
+       http_port := mp_rest_port,
+       use_ssl := false
+}
+
 template (value) ConnHdlrPars
 t_ConnHdlrPars(integer idx := 0,
               integer num_erabs := 1,
@@ -193,6 +216,14 @@

        vc_conn := ConnHdlr.create(id) alive;
        f_ConnHdlr_connect(vc_conn);
+
+       if (mp_rest_enable) {
+               /* Init the HTTP client (M2M/REST interface) */
+               vc_conn.start(f_http_init(valueof(t_HTTP_Adapter_Params)));
+               vc_conn.done;
+       }
+
+       /* run the actual testcase logic */
        vc_conn.start(f_ConnHdlr_init(fn, id, pars));

        return vc_conn;
diff --git a/s1gw/gen_links.sh b/s1gw/gen_links.sh
index 6328ab8..58a3e57 100755
--- a/s1gw/gen_links.sh
+++ b/s1gw/gen_links.sh
@@ -21,6 +21,22 @@
 FILES="PFCP_Types.ttcn"
 gen_links $DIR $FILES

+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Abstract_Socket/src
+FILES="Abstract_Socket.cc Abstract_Socket.hh "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.HTTPmsg/src
+FILES="HTTPmsg_MessageLen.ttcn HTTPmsg_MessageLen_Function.cc HTTPmsg_PT.cc 
HTTPmsg_PT.hh HTTPmsg_PortType.ttcn HTTPmsg_Types.ttcn "
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.ProtocolModules.JSON_v07_2006/src
+FILES="JSON_EncDec.cc JSON_Types.ttcn "
+gen_links $DIR $FILES
+
 DIR=../library/s1ap
 FILES="S1AP_CommonDataTypes.asn S1AP_Constants.asn S1AP_Containers.asn 
S1AP_IEs.asn "
 FILES+="S1AP_PDU_Contents.asn S1AP_PDU_Descriptions.asn "
@@ -33,6 +49,7 @@
 FILES+="S1AP_CodecPort.ttcn S1AP_CodecPort_CtrlFunctDef.cc 
S1AP_CodecPort_CtrlFunct.ttcn S1AP_Functions.ttcn "
 FILES+="SCTP_Templates.ttcn "
 FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn 
StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc 
StatsD_Checker.ttcnpp "
+FILES+="HTTP_Adapter.ttcn "
 gen_links $DIR $FILES

 gen_links_finish
diff --git a/s1gw/regen_makefile.sh b/s1gw/regen_makefile.sh
index 3c48af2..cc7e2bb 100755
--- a/s1gw/regen_makefile.sh
+++ b/s1gw/regen_makefile.sh
@@ -6,8 +6,12 @@
        *.asn
        *.ttcn
        *.ttcnpp
+       Abstract_Socket.cc
+       HTTPmsg_MessageLen_Function.cc
+       HTTPmsg_PT.cc
        IPL4asp_PT.cc
        IPL4asp_discovery.cc
+       JSON_EncDec.cc
        Native_FunctionDefs.cc
        PFCP_CodecPort_CtrlFunctDef.cc
        S1AP_CodecPort_CtrlFunctDef.cc

--
To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/41125?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Change-Id: Ic6e8b46b7de4fb72139b017fc9a9c83f92fc1541
Gerrit-Change-Number: 41125
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanits...@sysmocom.de>

Reply via email to