aboutsummaryrefslogtreecommitdiffstats
path: root/hnodeb/HNBGW_ConnectionHandler.ttcn
diff options
context:
space:
mode:
Diffstat (limited to 'hnodeb/HNBGW_ConnectionHandler.ttcn')
-rw-r--r--hnodeb/HNBGW_ConnectionHandler.ttcn295
1 files changed, 295 insertions, 0 deletions
diff --git a/hnodeb/HNBGW_ConnectionHandler.ttcn b/hnodeb/HNBGW_ConnectionHandler.ttcn
new file mode 100644
index 00000000..a72b5f24
--- /dev/null
+++ b/hnodeb/HNBGW_ConnectionHandler.ttcn
@@ -0,0 +1,295 @@
+module HNBGW_ConnectionHandler {
+
+/* HNBGW Connection Handler of HNB_Tests in TTCN-3
+ * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@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
+ */
+
+import from Misc_Helpers all;
+import from General_Types all;
+import from Osmocom_Types all;
+import from IPL4asp_Types all;
+import from Native_Functions all;
+
+import from SDP_Types all;
+
+import from StatsD_Checker all;
+
+import from TELNETasp_PortType all;
+import from Osmocom_VTY_Functions all;
+
+import from HNBAP_Templates all;
+
+import from Iuh_Emulation all;
+
+import from RTP_Types all;
+import from RTP_Emulation all;
+
+import from HNBLLIF_CodecPort all;
+import from HNBLLIF_Types all;
+import from HNBLLIF_Templates all;
+
+import from GTP_Emulation all;
+import from GTPv1U_Templates all;
+import from GTPv1U_CodecPort all;
+import from GTPU_Types all;
+
+/* this component represents a single Iuh connection at the HNBGW. */
+type component HNBGW_ConnHdlr extends Iuh_ConnHdlr, GTP_ConnHdlr, StatsD_ConnHdlr {
+ port TELNETasp_PT HNBVTY;
+ /* HNBLLIF Interface of HNodeB */
+ port HNBLLIF_CODEC_PT LLSK;
+ var integer g_llsk_conn_id;
+
+ var RTP_Emulation_CT vc_RTPEM;
+ port RTPEM_CTRL_PT RTPEM_CTRL;
+ port RTPEM_DATA_PT RTPEM_DATA;
+
+ var GTP_Emulation_CT vc_GTP;
+
+
+ var TestHdlrParams g_pars;
+
+ var boolean g_vty_initialized := false;
+}
+
+function f_HNBGW_ConnHdlr_init_vty() runs on HNBGW_ConnHdlr {
+ if (not g_vty_initialized) {
+ map(self:HNBVTY, system:HNBVTY);
+ f_vty_set_prompts(HNBVTY);
+ f_vty_transceive(HNBVTY, "enable");
+ g_vty_initialized := true;
+ }
+}
+
+private function f_HNBGW_ConnHdlr_init_iuh(charstring id) runs on HNBGW_ConnHdlr {
+ var Iuh_Emulation_CT vc_Iuh;
+ vc_Iuh := Iuh_Emulation_CT.create(id & "-HNBGW") alive;
+ connect(self:HNBAP, vc_Iuh:HNBAP);
+ connect(self:RUA, vc_Iuh:RUA);
+
+ var Iuh_conn_parameters iuh_pars;
+ iuh_pars.remote_ip := g_pars.hnodeb_addr;
+ iuh_pars.remote_sctp_port := -1;
+ iuh_pars.local_ip := g_pars.hnbgw_addr;
+ iuh_pars.local_sctp_port := g_pars.hnbgw_port;
+ vc_Iuh.start(Iuh_Emulation.main(iuh_pars, id & "-Iuh"));
+}
+
+private function f_HNBGW_ConnHdlr_init_gtp(charstring id) runs on HNBGW_ConnHdlr {
+ id := id & "-GTP";
+
+ var GtpEmulationCfg gtp_cfg := {
+ gtpc_bind_ip := g_pars.hnbgw_addr,
+ gtpc_bind_port := GTP1C_PORT,
+ gtpu_bind_ip := g_pars.hnbgw_addr,
+ gtpu_bind_port := GTP1U_PORT,
+ sgsn_role := false
+ };
+
+ vc_GTP := GTP_Emulation_CT.create(id) alive;
+ connect(self:GTP[0], vc_GTP:CLIENT);
+ connect(self:GTP_PROC[0], vc_GTP:CLIENT_PROC);
+ vc_GTP.start(GTP_Emulation.main(gtp_cfg));
+}
+
+/* initialize all parameters */
+function f_HNBGW_ConnHdlr_init(charstring id, TestHdlrParams pars) runs on HNBGW_ConnHdlr {
+ g_pars := valueof(pars);
+ f_HNBGW_ConnHdlr_init_iuh(id);
+ f_HNBGW_ConnHdlr_init_gtp(id);
+ f_HNBGW_ConnHdlr_init_vty();
+
+ /* Connect to HNB on LLSK and do HELLO ping-pong */
+ f_start_hnbllif(LLSK, id & "-LLSK", g_pars, g_llsk_conn_id);
+}
+
+
+function f_start_hnbllif(HNBLLIF_CODEC_PT pt, charstring id, TestHdlrParams pars,
+ out integer hnbllif_conn_id) {
+ timer T := 2.0;
+ var HNBLLIF_send_data sd;
+ var HNBLLIF_Message last_hello_cnf;
+ if (pars.hnbllif_sk_path == "") {
+ hnbllif_conn_id := -1;
+ return;
+ }
+ hnbllif_conn_id := f_hnbllif_connect(pt, pars.hnbllif_sk_path);
+
+ T.start;
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_CTL, HNBLLIF_Types.mp_hnbllif_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_CTL, HNBLLIF_Types.mp_hnbllif_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=CTL");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_IUH, pars.hnbllif_sapi_iuh_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_IUH, pars.hnbllif_sapi_iuh_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=IUH");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_AUDIO, pars.hnbllif_sapi_audio_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_AUDIO, pars.hnbllif_sapi_audio_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=AUDIO");
+ }
+ }
+ pt.send(t_SD_HNBLLIF(hnbllif_conn_id, ts_HNBLLIF_CTL_HELLO_REQ(HNBLL_IF_SAPI_GTP, pars.hnbllif_sapi_gtp_version)));
+ alt {
+ [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_GTP, pars.hnbllif_sapi_gtp_version);
+ [] T.timeout {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=GTP");
+ }
+ }
+}
+
+type record TestHdlrParams {
+ charstring hnbllif_sk_path, /* "" means don't connect */
+ uint16_t hnbllif_sapi_iuh_version,
+ uint16_t hnbllif_sapi_gtp_version,
+ uint16_t hnbllif_sapi_audio_version,
+ charstring hnbgw_addr,
+ charstring hnodeb_addr,
+ integer hnbgw_port,
+ integer hnbgw_rtp_port,
+ uint16_t rnc_id,
+ charstring hNB_Identity_Info,
+ uint16_t mcc,
+ uint16_t mnc,
+ uint32_t cell_identity,
+ uint16_t lac,
+ uint8_t rac,
+ uint8_t sac
+};
+
+/* Note: Do not use valueof() to get a value of this template, use
+ * f_gen_test_hdlr_pars() instead in order to get a configuration. */
+template (value) TestHdlrParams t_def_TestHdlrPars := {
+ hnbllif_sk_path := HNBLL_SOCK_DEFAULT,
+ hnbllif_sapi_iuh_version := 0,
+ hnbllif_sapi_gtp_version := 0,
+ hnbllif_sapi_audio_version := 1,
+ hnbgw_addr := "127.0.0.1",
+ hnodeb_addr := "127.0.0.1",
+ hnbgw_port := 29169,
+ hnbgw_rtp_port := 9000,
+ rnc_id := 23,
+ hNB_Identity_Info := "OsmoHNodeB",
+ mcc := 1,
+ mnc := 1,
+ cell_identity := 1,
+ lac := 2,
+ rac := 3,
+ sac := 4
+}
+
+template (value) Gtp1uPeer ts_GtpPeerU(charstring ip) := {
+ connId := 1,
+ remName := ip,
+ remPort := GTP1U_PORT
+}
+
+function f_gtpu_send(uint32_t tei, octetstring payload) runs on HNBGW_ConnHdlr {
+ var Gtp1uPeer peer := valueof(ts_GtpPeerU(g_pars.hnodeb_addr));
+ GTP[0].send(ts_GTP1U_GPDU(peer, 0 /*seq*/, int2oct(tei, 4), payload));
+}
+
+/* HNBLLIF socket may at any time receive a new INFO.ind */
+altstep as_hnbllif_hello_cnf(HNBLLIF_CODEC_PT pt, integer hnbllif_conn_id,
+ out HNBLLIF_Message last_hello_cnf,
+ template (present) HNBLLIF_Sapi exp_sapi := ?,
+ template (present) uint16_t exp_version := ?) {
+ var HNBLLIF_send_data sd;
+ [] pt.receive(t_SD_HNBLLIF(hnbllif_conn_id, tr_HNBLLIF_CTL_HELLO_CNF(exp_sapi, exp_version))) -> value sd {
+ last_hello_cnf := sd.data;
+ }
+ [] pt.receive(t_SD_HNBLLIF(hnbllif_conn_id, tr_HNBLLIF_CTL_HELLO_CNF(?))) -> value sd {
+ Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Invalid API_VERSION received");
+ }
+}
+
+function f_llsk_rx(template (present) HNBLLIF_Message exp_tmpl) runs on HNBGW_ConnHdlr
+return template (present) HNBLLIF_send_data {
+ return t_SD_HNBLLIF(g_llsk_conn_id, exp_tmpl);
+}
+
+function f_llsk_tx(template (value) HNBLLIF_Message tx_msg) runs on HNBGW_ConnHdlr
+return template (value) HNBLLIF_send_data {
+ return ts_SD_HNBLLIF(g_llsk_conn_id, tx_msg);
+}
+
+function f_enc_mcc_mnc(uint16_t mcc_uint, uint16_t mnc_uint) return OCT3 {
+ var hexstring mnc;
+ var hexstring mcc := int2hex(mcc_uint, 3);
+
+ if (mnc_uint < 100) {
+ mnc := int2hex(mnc_uint, 2);
+ return hex2oct(mcc[1] & mcc[0] & 'F'H & mcc[2] & mnc[1] & mnc[0]);
+ } else {
+ mnc := int2hex(mnc_uint, 3);
+ return hex2oct(mcc[1] & mcc[0] & mnc[2] & mcc[2] & mnc[1] & mnc[0]);
+ }
+}
+
+function f_handle_hnbap_hnb_register_req()
+runs on HNBGW_ConnHdlr {
+ HNBAP.receive(tr_HNBAP_HNBRegisterRequest(char2oct(g_pars.hNB_Identity_Info),
+ f_enc_mcc_mnc(g_pars.mcc, g_pars.mnc),
+ int2bit(g_pars.cell_identity, 28),
+ int2oct(g_pars.lac, 2),
+ int2oct(g_pars.rac, 1),
+ int2oct(g_pars.sac, 2)
+ ));
+ HNBAP.send(ts_HNBAP_HNBRegisterAccept(g_pars.rnc_id));
+}
+
+/* Initialize and start the RTP emulation component for a ConnHdlr */
+function f_HNBGW_rtpem_activate(inout octetstring payload)
+runs on HNBGW_ConnHdlr {
+ /* Initialize, connect and start the emulation component */
+ var RtpemConfig cfg := c_RtpemDefaultCfg;
+ cfg.iuup_mode := true;
+ cfg.iuup_cfg.active_init := false;
+ cfg.tx_payloads[0].payload_type := 96;
+ cfg.rx_payloads[0].payload_type := 96;
+
+ vc_RTPEM := RTP_Emulation_CT.create(testcasename() & "-RTPEM") alive;
+ map(vc_RTPEM:RTP, system:RTP);
+ map(vc_RTPEM:RTCP, system:RTCP);
+ connect(vc_RTPEM:CTRL, self:RTPEM_CTRL);
+ connect(vc_RTPEM:DATA, self:RTPEM_DATA);
+ vc_RTPEM.start(RTP_Emulation.f_main());
+
+ /* Configure the RTP parameters (TCH/FS). TODO: IuUP */
+ var integer payload_len := 33;
+ var octetstring hdr := 'D0'O;
+
+ /* Pad the payload to conform the expected length */
+ payload := f_pad_oct(hdr & payload, payload_len, '00'O);
+ cfg.tx_payloads[0].fixed_payload := payload;
+ f_rtpem_configure(RTPEM_CTRL, cfg);
+
+ /* Bind the RTP emulation to the configured address */
+ f_rtpem_bind(RTPEM_CTRL, g_pars.hnbgw_addr, g_pars.hnbgw_rtp_port);
+
+ /* Set the given RTP emulation mode */
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_RXONLY);
+}
+
+function f_HNBGW_rtpem_connect(HostName remote_host, PortNumber remote_port)
+runs on HNBGW_ConnHdlr {
+ f_rtpem_connect(RTPEM_CTRL, remote_host, remote_port);
+ /* Set the given RTP emulation mode */
+ f_rtpem_mode(RTPEM_CTRL, RTPEM_MODE_BIDIR);
+}
+
+}