diff options
Diffstat (limited to 'hnodeb/HNBGW_ConnectionHandler.ttcn')
-rw-r--r-- | hnodeb/HNBGW_ConnectionHandler.ttcn | 295 |
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); +} + +} |