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>