diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2021-11-24 17:00:03 +0100 |
---|---|---|
committer | laforge <laforge@osmocom.org> | 2021-12-15 14:23:23 +0000 |
commit | a6bbb8c45d00471e09d8890f6a402280ad7d600f (patch) | |
tree | aeac6a3afa0048d6831195d7263a8b2da9bf11c2 | |
parent | 3f7a6dc2976971f96faae0ab6b0e907912b4e49f (diff) |
hnodeb: Add initial infra to emulate HNB LL socket iface
Change-Id: Ia864a672643a0e42f5afea6fd901e621478c87c0
-rw-r--r-- | hnodeb/HNBGW_ConnectionHandler.ttcn | 92 | ||||
-rw-r--r-- | hnodeb/HNB_Tests.default | 1 | ||||
-rw-r--r-- | hnodeb/HNB_Tests.ttcn | 129 | ||||
-rwxr-xr-x | hnodeb/gen_links.sh | 7 | ||||
-rwxr-xr-x | hnodeb/regen_makefile.sh | 1 | ||||
-rw-r--r-- | library/HNBLLIF_CodecPort.ttcn | 95 | ||||
-rw-r--r-- | library/HNBLLIF_Templates.ttcn | 251 | ||||
-rw-r--r-- | library/HNBLLIF_Types.ttcn | 275 | ||||
-rw-r--r-- | library/Iuh_CodecPort.ttcn | 6 |
9 files changed, 820 insertions, 37 deletions
diff --git a/hnodeb/HNBGW_ConnectionHandler.ttcn b/hnodeb/HNBGW_ConnectionHandler.ttcn index 071e3e8a..554c35fe 100644 --- a/hnodeb/HNBGW_ConnectionHandler.ttcn +++ b/hnodeb/HNBGW_ConnectionHandler.ttcn @@ -27,11 +27,19 @@ import from HNBAP_Templates all; import from Iuh_Emulation all; +import from HNBLLIF_CodecPort all; +import from HNBLLIF_Types all; +import from HNBLLIF_Templates all; + /* this component represents a single Iuh connection at the HNBGW. */ type component HNBGW_ConnHdlr extends StatsD_ConnHdlr { port TELNETasp_PT HNBVTY; port HNBAP_PT HNBAP; port RUA_PT RUA; + /* HNBLLIF Interface of HNodeB */ + port HNBLLIF_CODEC_PT LLSK; + var integer g_llsk_conn_id; + var TestHdlrParams g_pars; var boolean g_vty_initialized := false; @@ -47,12 +55,11 @@ function f_HNBGW_ConnHdlr_init_vty() runs on HNBGW_ConnHdlr { } /* initialize all parameters */ -function f_HNBGW_ConnHdlr_init(TestHdlrParams pars) runs on HNBGW_ConnHdlr { - var integer i := 0; +function f_HNBGW_ConnHdlr_init(charstring id, TestHdlrParams pars) runs on HNBGW_ConnHdlr { var Iuh_Emulation_CT vc_Iuh; g_pars := valueof(pars); - vc_Iuh := Iuh_Emulation_CT.create("HNBGW" & int2str(i)); + vc_Iuh := Iuh_Emulation_CT.create(id & "-HNBGW"); connect(self:HNBAP, vc_Iuh:HNBAP); connect(self:RUA, vc_Iuh:RUA); @@ -61,18 +68,51 @@ function f_HNBGW_ConnHdlr_init(TestHdlrParams pars) runs on HNBGW_ConnHdlr { 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, "Iuh" & int2str(i))); + vc_Iuh.start(Iuh_Emulation.main(iuh_pars, id & "-Iuh")); f_HNBGW_ConnHdlr_init_vty(); + + /* Connect to HNB on LLSK and do HELLO ping-pong */ + f_start_hnbllif(LLSK, id & "-LLSK", g_pars.hnbllif_sk_path, g_llsk_conn_id); +} + + +function f_start_hnbllif(HNBLLIF_CODEC_PT pt, charstring id, charstring hnbllif_sk_path, out integer hnbllif_conn_id) { + timer T := 2.0; + var HNBLLIF_send_data sd; + var HNBLLIF_Message last_hello_cnf; + if (hnbllif_sk_path == "") { + hnbllif_conn_id := -1; + return; + } + hnbllif_conn_id := f_hnbllif_connect(pt, 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, 0))); + alt { + [] as_hnbllif_hello_cnf(pt, hnbllif_conn_id, last_hello_cnf, HNBLL_IF_SAPI_IUH, 0); + [] T.timeout { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting for HNBLLIF HELLO.REQ SAPI=IUH"); + } + } } type record TestHdlrParams { + charstring hnbllif_sk_path, /* "" means don't connect */ charstring hnbgw_addr, charstring hnodeb_addr, integer hnbgw_port, uint16_t rnc_id, charstring hNB_Identity_Info, - OCT3 plmnid, + uint16_t mcc, + uint16_t mnc, uint32_t cell_identity, uint16_t lac, uint8_t rac, @@ -82,23 +122,61 @@ type record TestHdlrParams { /* 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, hnbgw_addr := "127.0.0.1", hnodeb_addr := "127.0.0.1", hnbgw_port := 29169, rnc_id := 23, hNB_Identity_Info := "OsmoHNodeB", - plmnid := '00F110'O, + mcc := 1, + mnc := 1, cell_identity := 1, lac := 2, rac := 3, sac := 4 } +/* 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), - g_pars.plmnid, + 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), diff --git a/hnodeb/HNB_Tests.default b/hnodeb/HNB_Tests.default index a06dcc67..c385b9a0 100644 --- a/hnodeb/HNB_Tests.default +++ b/hnodeb/HNB_Tests.default @@ -20,6 +20,7 @@ mtc.FileMask := LOG_ALL | TTCN_DEBUG | TTCN_MATCHING | DEBUG_ENCDEC; *.STATSVTY.CTRL_CLIENT_CLEANUP_LINEFEED := "yes" *.STATSVTY.CTRL_DETECT_CONNECTION_ESTABLISHMENT_RESULT := "yes" *.STATSVTY.PROMPT1 := "OsmoHNodeB> " +*.LLSK.socket_type := "SEQPACKET" [MODULE_PARAMETERS] Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoHNodeB"; diff --git a/hnodeb/HNB_Tests.ttcn b/hnodeb/HNB_Tests.ttcn index 7a668dde..59dd1ee2 100644 --- a/hnodeb/HNB_Tests.ttcn +++ b/hnodeb/HNB_Tests.ttcn @@ -38,10 +38,16 @@ import from Osmocom_VTY_Functions all; import from TELNETasp_PortType all; import from HNBAP_Templates all; +import from RUA_IEs all; +import from RUA_Templates all; import from HNBGW_ConnectionHandler all; import from Iuh_Emulation all; +import from HNBLLIF_CodecPort all; +import from HNBLLIF_Types all; +import from HNBLLIF_Templates all; + modulepar { /* IP address at which the HNodeB can be reached */ charstring mp_hnodeb_ip := "127.0.0.1"; @@ -49,11 +55,23 @@ modulepar { /* IP address at which the test binds */ charstring mp_hnbgw_iuh_ip := "127.0.0.1"; integer mp_hnbgw_iuh_port := 29169; + + charstring mp_hnbllif_sk_path := HNBLL_SOCK_DEFAULT; } +const hexstring ranap_cm_service_req := '001340400000060003400100000f40060000f11028b6003a40080000f110ffffffff0010400e0d052411035758a605f44e9d4aef004f400300001c0056400500f1100017'H; +const hexstring ranap_auth_req := '00144032000002001040262505120217dc146aeac56cb5ff6d5fb51f47f19220108ca5a6d0c8110000b9e9272498872764003b400100'H; +const hexstring ranap_auth_resp := '001440140000010010400d0c0554ccbdd0302104002f3ae4'H; +const hexstring ranap_paging := '000e401e0000030003400100001740095000010100000000f10040400500b6cf4773'H; +const hexstring iu_release_compl := '20010003000000'H; + type component test_CT extends CTRL_Adapter_CT { port TELNETasp_PT HNBVTY; + /* HNBLLIF Interface of HNodeB */ + port HNBLLIF_CODEC_PT LLSK; + var integer g_llsk_conn_id; + /* global test case guard timer (actual timeout value is set in f_init()) */ timer T_guard := 30.0; } @@ -83,6 +101,12 @@ function f_init_vty(charstring id := "foo") runs on test_CT { f_vty_set_prompts(HNBVTY); f_vty_transceive(HNBVTY, "enable"); } + +private function f_init_hnbllif() runs on test_CT { + map(self:LLSK, system:LLSK); + f_start_hnbllif(LLSK, testcasename(), mp_hnbllif_sk_path, g_llsk_conn_id); +} + /* global initialization function */ function f_init(float guard_timeout := 30.0) runs on test_CT { var integer bssap_idx; @@ -91,8 +115,6 @@ function f_init(float guard_timeout := 30.0) runs on test_CT { activate(as_Tguard()); f_init_vty("VirtHNBGW"); - - /* TODO: Wait for Iuh connection to be established */ } friend function f_shutdown_helper() runs on test_CT { @@ -101,9 +123,10 @@ friend function f_shutdown_helper() runs on test_CT { mtc.stop; } -friend function f_gen_test_hdlr_pars() return TestHdlrParams { +private function f_gen_test_hdlr_pars() runs on test_CT return TestHdlrParams { var TestHdlrParams pars := valueof(t_def_TestHdlrPars); + pars.hnbllif_sk_path := mp_hnbllif_sk_path; pars.hnodeb_addr := mp_hnodeb_ip; pars.hnbgw_addr := mp_hnbgw_iuh_ip; pars.hnbgw_port := mp_hnbgw_iuh_port; @@ -113,27 +136,10 @@ friend function f_gen_test_hdlr_pars() return TestHdlrParams { type function void_fn(charstring id) runs on HNBGW_ConnHdlr; /* helper function to create and connect a HNBGW_ConnHdlr component */ -private function f_connect_handler(inout HNBGW_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT { - /*connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC); - connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC); - connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT); - connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC); - if (isvalue(bts[1])) { - connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT); - connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC); - } - if (isvalue(bts[2])) { - connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT); - connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC); - } - connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT); - if (mp_enable_lcs_tests) { - connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT); - connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC); +private function f_connect_handler(inout HNBGW_ConnHdlr vc_conn, TestHdlrParams pars) runs on test_CT { + if (pars.hnbllif_sk_path != "") { + map(vc_conn:LLSK, system:LLSK); } - connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT); - connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI); - connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);*/ } function f_start_handler_create(TestHdlrParams pars) @@ -141,7 +147,7 @@ runs on test_CT return HNBGW_ConnHdlr { var charstring id := testcasename(); var HNBGW_ConnHdlr vc_conn; vc_conn := HNBGW_ConnHdlr.create(id); - f_connect_handler(vc_conn); + f_connect_handler(vc_conn, pars); return vc_conn; } @@ -168,27 +174,29 @@ runs on test_CT return HNBGW_ConnHdlr { /* first function inside ConnHdlr component; sets g_pars + starts function */ private function f_handler_init(void_fn fn, charstring id, TestHdlrParams pars) runs on HNBGW_ConnHdlr { - f_HNBGW_ConnHdlr_init(pars); + f_HNBGW_ConnHdlr_init(id, pars); HNBAP.receive(IUHEM_Event:{up_down:=IUHEM_EVENT_UP}); /* Wait for HNB to connect to us */ fn.apply(id); } -private function f_tc_hnb_register_request(charstring id) runs on HNBGW_ConnHdlr { +private function f_tc_hnb_register_request_accept(charstring id) runs on HNBGW_ConnHdlr { f_handle_hnbap_hnb_register_req(); + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity, + g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id))); f_sleep(1.0); } testcase TC_hnb_register_request_accept() runs on test_CT { var HNBGW_ConnHdlr vc_conn; f_init(); - vc_conn := f_start_handler(refers(f_tc_hnb_register_request)); + vc_conn := f_start_handler(refers(f_tc_hnb_register_request_accept)); vc_conn.done; f_shutdown_helper(); } private function f_tc_hnb_register_reject(charstring id) runs on HNBGW_ConnHdlr { HNBAP.receive(tr_HNBAP_HNBRegisterRequest(char2oct(g_pars.hNB_Identity_Info), - g_pars.plmnid, + 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), @@ -206,9 +214,74 @@ testcase TC_hnb_register_request_reject() runs on test_CT { f_shutdown_helper(); } +private function f_tc_mo_conn(charstring id) runs on HNBGW_ConnHdlr { + const integer context_id := 30; + const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */ + const Establishment_Cause est_cause := normal_call; + f_handle_hnbap_hnb_register_req(); + + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity, + g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id))); + + /* Now an UE attempts CM Service Request: */ + LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(context_id, 1, enum2int(est_cause), hex2oct(ranap_cm_service_req)))); + /* The related RUA Connect + RANAP message is received on Iuh: */ + RUA.receive(tr_RUA_Connect(ps_domain, context_id_bstr, est_cause, hex2oct(ranap_cm_service_req))); + + /* Now HNBGW answers with RUA-DirectTransfer(RANAP-AuthenticationRequest) */ + RUA.send(ts_RUA_DirectTransfer(ps_domain, context_id_bstr, hex2oct(ranap_auth_req))); + + /* Now on LLSK first the Conn establishment is confirmed and then we receive data */ + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(context_id, 1, 0))); + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONN_DATA_IND(context_id, 1, hex2oct(ranap_auth_req)))); + + /* UE answers with RANAPAuthenticationResponse: */ + LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_DATA_REQ(context_id, 1, hex2oct(ranap_auth_resp)))); + RUA.receive(tr_RUA_DirectTransfer(ps_domain, context_id_bstr, hex2oct(ranap_auth_resp))); + + /* UE sends Iu Release Complete to release the conn */ + LLSK.send(f_llsk_tx(ts_HNBLLIF_IUH_CONN_RELEASE_REQ(context_id, 1, 0, 0, hex2oct(iu_release_compl)))); + RUA.receive(tr_RUA_Disconnect(ps_domain, context_id_bstr, ts_RUA_Cause(normal), hex2oct(iu_release_compl))); +} +testcase TC_mo_conn() runs on test_CT { + var HNBGW_ConnHdlr vc_conn; + + f_init(); + vc_conn := f_start_handler(refers(f_tc_mo_conn)); + vc_conn.done; + f_shutdown_helper(); +} + + +private function f_tc_paging(charstring id) runs on HNBGW_ConnHdlr { + const integer context_id := 30; + const bitstring context_id_bstr := '000000000000000000011110'B; /* encoded context_id */ + f_handle_hnbap_hnb_register_req(); + + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_CONFIGURE_IND(g_pars.mcc, g_pars.mnc, g_pars.cell_identity, + g_pars.lac, g_pars.rac, g_pars.sac, g_pars.rnc_id))); + + /* HNBGW sends RUA-ConnectionlessTransfer(RANAP-Paging) */ + RUA.send(ts_RUA_ConnectionlessTransfer(hex2oct(ranap_paging))); + + LLSK.receive(f_llsk_rx(tr_HNBLLIF_IUH_UNITDATA_IND(hex2oct(ranap_paging)))); + + /* Here it would continue with UE-side answers with RUA-Connect(RANAP-PagingResponse) */ +} +testcase TC_paging() runs on test_CT { + var HNBGW_ConnHdlr vc_conn; + + f_init(); + vc_conn := f_start_handler(refers(f_tc_paging)); + vc_conn.done; + f_shutdown_helper(); +} + control { execute( TC_hnb_register_request_accept() ); execute( TC_hnb_register_request_reject() ); + execute( TC_mo_conn() ); + execute( TC_paging() ); } } diff --git a/hnodeb/gen_links.sh b/hnodeb/gen_links.sh index ba946e8c..6ddb4c0f 100755 --- a/hnodeb/gen_links.sh +++ b/hnodeb/gen_links.sh @@ -27,6 +27,10 @@ DIR=$BASEDIR/titan.TestPorts.SCTPasp/src FILES="SCTPasp_PT.cc SCTPasp_PT.hh SCTPasp_PortType.ttcn SCTPasp_Types.ttcn" gen_links $DIR $FILES +DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src +FILES="UD_PT.cc UD_PT.hh UD_PortType.ttcn UD_Types.ttcn" +gen_links $DIR $FILES + DIR=$BASEDIR/titan.ProtocolModules.SDP/src FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l SDP_parser.y lex.SDP_parse_.c" @@ -51,7 +55,8 @@ FILES+="RUA_EncDec.cc RUA_Types.ttcn RUA_Templates.ttcn " gen_links $DIR $FILES DIR=../library -FILES="Iuh_Types.ttcn Iuh_CodecPort.ttcn Iuh_CodecPort_CtrlFunctDef.cc Iuh_CodecPort_CtrlFunct.ttcn Iuh_Emulation.ttcn DNS_Helpers.ttcn " +FILES="HNBLLIF_Types.ttcn HNBLLIF_Templates.ttcn HNBLLIF_CodecPort.ttcn " +FILES+="Iuh_Types.ttcn Iuh_CodecPort.ttcn Iuh_CodecPort_CtrlFunctDef.cc Iuh_CodecPort_CtrlFunct.ttcn Iuh_Emulation.ttcn DNS_Helpers.ttcn " FILES+="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn " FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn " diff --git a/hnodeb/regen_makefile.sh b/hnodeb/regen_makefile.sh index 9ebfaf2f..2d135046 100755 --- a/hnodeb/regen_makefile.sh +++ b/hnodeb/regen_makefile.sh @@ -24,6 +24,7 @@ FILES=" TELNETasp_PT.cc HNBAP_EncDec.cc RUA_EncDec.cc + UD_PT.cc " export CPPFLAGS_TTCN3=" diff --git a/library/HNBLLIF_CodecPort.ttcn b/library/HNBLLIF_CodecPort.ttcn new file mode 100644 index 00000000..00f53fcc --- /dev/null +++ b/library/HNBLLIF_CodecPort.ttcn @@ -0,0 +1,95 @@ +/* OsmoHNodeB Lower Layer Socket Interface codec port in TTCN-3 + * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All rights reserved. + * Author: Pau Espin Pedrol <pespin@sysmocom.de> + * + * 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 HNBLLIF_CodecPort { + +import from Osmocom_Types all; +import from HNBLLIF_Types all; +import from UD_PortType all; +import from UD_Types all; + +type record HNBLLIF_send_data { + HNBLLIF_Message data, + integer id +}; + +private function HNBLLIF_to_UD(in HNBLLIF_send_data pin, out UD_send_data pout) { + pout.id := pin.id; + pout.data := enc_HNBLLIF_Message(pin.data); +} with { extension "prototype(fast)" }; + +private function UD_to_HNBLLIF(in UD_send_data pin, out HNBLLIF_send_data pout) { + pout.id := pin.id; + pout.data := dec_HNBLLIF_Message(pin.data); +} with { extension "prototype(fast)" }; + +type port HNBLLIF_CODEC_PT message { + out UD_close, UD_listen, UD_shutdown, UD_connect, HNBLLIF_send_data; + in UD_listen_result, UD_connect_result, UD_connected, HNBLLIF_send_data; +} with { extension "user UD_PT + out ( + UD_close -> UD_close:simple; + UD_listen -> UD_listen:simple; + UD_shutdown -> UD_shutdown:simple; + UD_connect -> UD_connect:simple; + HNBLLIF_send_data -> UD_send_data: function(HNBLLIF_to_UD) + ) + in ( + UD_listen_result -> UD_listen_result:simple; + UD_connect_result -> UD_connect_result:simple; + UD_send_data -> HNBLLIF_send_data: function(UD_to_HNBLLIF); + UD_connected -> UD_connected:simple + )" +}; + +template HNBLLIF_send_data t_SD_HNBLLIF(integer id, template HNBLLIF_Message pdu) := { + data := pdu, + id := id +} +template (value) HNBLLIF_send_data ts_SD_HNBLLIF(integer id, template (value) HNBLLIF_Message pdu) := { + data := pdu, + id := id +} + +function f_hnbllif_connect(HNBLLIF_CODEC_PT pt, charstring sock) return integer { + var UD_connect_result res; + timer T := 5.0; + + T.start; + pt.send(UD_connect:{sock, -1}); + alt { + [] pt.receive(UD_connect_result:?) -> value res { + if (ispresent(res.result) and ispresent(res.result.result_code) and + res.result.result_code == ERROR) { + if (ispresent(res.result.err)) { + setverdict(fail, "Error connecting to HNBLL socket ", sock, ": ", res.result.err); + } else { + setverdict(fail, "Error connecting to HNBLL socket ", sock); + } + mtc.stop; + } else { + return res.id; + } + } + [] T.timeout { + setverdict(fail, "Timeout connecting to HNBLL socket ", sock); + mtc.stop; + } + } + return -23; +} + +function f_hnbllif_close(HNBLLIF_CODEC_PT pt, integer id) +{ + pt.send(UD_close:{id := id}); +} + +} diff --git a/library/HNBLLIF_Templates.ttcn b/library/HNBLLIF_Templates.ttcn new file mode 100644 index 00000000..f330fdf8 --- /dev/null +++ b/library/HNBLLIF_Templates.ttcn @@ -0,0 +1,251 @@ +/* Osmocom HNBLL Interface Templates, as per osmo-hnodeb/include/osmocom/hnodeb/hnb_prim.h + * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All rights reserved. + * Author: Pau Espin Pedrol <pespin@sysmocom.de> + * + * 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 HNBLLIF_Templates { + +import from General_Types all; +import from Osmocom_Types all; +import from HNBLLIF_Types all; + +/********************** + * CTL SAPI + **********************/ +template (value) HNBLLIF_Message ts_HNBLLIF_CTL_HELLO_REQ(template (value) HNBLLIF_Sapi sapi, + template (value) uint16_t api_version) := { + sapi := HNBLL_IF_SAPI_CTL, + u := { + ctl := { + prim := HNBLL_IF_CTL_MSG_HELLO, + u := { + hello := { + op := HNBLL_IF_OP_REQUEST, + u := { + req := { + sapi := sapi, + api_version := api_version + } + } + } + } + } + } +} + +template (present) HNBLLIF_Message tr_HNBLLIF_CTL_HELLO_CNF(template (present) HNBLLIF_Sapi sapi := ?, + template (present) uint32_t api_version := ?) := { + sapi := HNBLL_IF_SAPI_CTL, + u := { + ctl := { + prim := HNBLL_IF_CTL_MSG_HELLO, + u := { + hello := { + op := HNBLL_IF_OP_CONFIRM, + u := { + cnf := { + sapi := sapi, + api_version := api_version + } + } + } + } + } + } +} + + +/********************** + * IUH SAPI + **********************/ + +template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONFIGURE_IND(template (present) uint16_t mcc := ?, + template (present) uint16_t mnc := ?, + template (present) uint16_t cell_identity := ?, + template (present) uint16_t lac := ?, + template (present) uint8_t rac := ?, + template (present) uint16_t sac := ?, + template (present) uint16_t rnc_id := ?) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONFIGURE, + u := { + configure := { + op := HNBLL_IF_OP_INDICATION, + u := { + ind := { + mcc := mcc, + mnc := mnc, + cell_identity := cell_identity, + lac := lac, + rac := rac, + reserved := ?, + sac := sac, + rnc_id := rnc_id + } + } + } + } + } + } +} + +template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_ESTABLISH_REQ(template (value) uint32_t context_id, + template (value) uint8_t domain, + template (value) uint8_t est_cause, + template (value) octetstring data) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH, + u := { + conn_establish := { + op := HNBLL_IF_OP_REQUEST, + u := { + req := { + context_id := context_id, + domain := domain, + est_cause := est_cause, + reserved := 0, + data_len := lengthof(data), + data := data + } + } + } + } + } + } +} + +template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_ESTABLISH_CNF(template (present) uint32_t context_id := ?, + template (present) uint8_t domain := ?, + template (present) uint8_t est_cause := ?) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONN_ESTABLISH, + u := { + conn_establish := { + op := HNBLL_IF_OP_CONFIRM, + u := { + cnf := { + context_id := context_id, + domain := domain, + est_cause := est_cause + } + } + } + } + } + } +} + +template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_RELEASE_REQ(template (value) uint32_t context_id, + template (value) uint8_t domain, + template (value) uint8_t cause_type, + template (value) uint8_t cause, + template (value) octetstring data) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONN_RELEASE, + u := { + conn_release := { + op := HNBLL_IF_OP_REQUEST, + u := { + req := { + context_id := context_id, + domain := domain, + spare1 := 0, + cause_type := cause_type, + cause := cause, + data_len := lengthof(data), + data := data + } + } + } + } + } + } +} + +template (present) HNBLLIF_Message tr_HNBLLIF_IUH_CONN_DATA_IND(template (present) uint32_t context_id := ?, + template (present) uint8_t domain := ?, + template (present) octetstring data := ?) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONN_DATA, + u := { + conn_data := { + op := HNBLL_IF_OP_INDICATION, + u := { + ind := { + context_id := context_id, + domain := domain, + spare1 := ?, + spare2 := ?, + data_len := ?, + data := data + } + } + } + } + } + } +} + +template (value) HNBLLIF_Message ts_HNBLLIF_IUH_CONN_DATA_REQ(template (value) uint32_t context_id, + template (value) uint8_t domain, + template (value) octetstring data) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_CONN_DATA, + u := { + conn_data := { + op := HNBLL_IF_OP_REQUEST, + u := { + req := { + context_id := context_id, + domain := domain, + spare1 := 0, + spare2 := 0, + data_len := lengthof(data), + data := data + } + } + } + } + } + } +} + +template (present) HNBLLIF_Message tr_HNBLLIF_IUH_UNITDATA_IND(template (present) octetstring data := ?) := { + sapi := HNBLL_IF_SAPI_IUH, + u := { + iuh := { + prim := HNBLL_IF_IUH_MSG_UNITDATA, + u := { + unitdata := { + op := HNBLL_IF_OP_INDICATION, + u := { + ind := { + data_len := ?, + data := data + } + } + } + } + } + } +} + +} with { encode "RAW" variant "BYTEORDER(first)" }; diff --git a/library/HNBLLIF_Types.ttcn b/library/HNBLLIF_Types.ttcn new file mode 100644 index 00000000..f9c8cc5f --- /dev/null +++ b/library/HNBLLIF_Types.ttcn @@ -0,0 +1,275 @@ +/* Osmocom HNBLL Interface Types, as per osmo-hnodeb/include/osmocom/hnodeb/hnb_prim.h + * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All rights reserved. + * Author: Pau Espin Pedrol <pespin@sysmocom.de> + * + * 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 HNBLLIF_Types { + +import from General_Types all; +import from Osmocom_Types all; +import from Native_Functions all; + +modulepar { + /* HNBLLIF version supported by the IUT */ + HNBLLIF_Version mp_hnbllif_version := 0; +}; + +const charstring HNBLL_SOCK_DEFAULT := "/tmp/hnb_prim_sock"; +type integer HNBLLIF_Version (0); /* supported versions */ + +/********************** + * CTL SAPI + **********************/ + + +type enumerated HNBLLIF_CTL_MsgType { + HNBLL_IF_CTL_MSG_HELLO ('0000'O) +} with { variant "FIELDLENGTH(16)" }; + +type record HNBLLIF_CTL_hello_req { + HNBLLIF_Sapi sapi, + uint16_t api_version +} with { variant "" }; + +type record HNBLLIF_CTL_hello_cnf { + HNBLLIF_Sapi sapi, + uint16_t api_version +} with { variant "" }; + +type union HNBLLIF_CTL_PrimOpUnion_hello { + HNBLLIF_CTL_hello_req req, + HNBLLIF_CTL_hello_cnf cnf, + octetstring other +} with { variant "" }; + +type record HNBLLIF_CTL_PrimOp_hello { + HNBLLIF_Operation op, + HNBLLIF_CTL_PrimOpUnion_hello u +} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST; + cnf, op = HNBLL_IF_OP_CONFIRM; + other, OTHERWISE)" +}; + +type union HNBLLIF_CTL_PrimUnion { + HNBLLIF_CTL_PrimOp_hello hello, + octetstring other +} with { variant "" }; + +type record HNBLLIF_CTL_PrimHdr { + HNBLLIF_CTL_MsgType prim, + HNBLLIF_CTL_PrimUnion u +} with { variant (u) "CROSSTAG( hello, prim = HNBLL_IF_CTL_MSG_HELLO; + other, OTHERWISE)" +}; + +/********************** + * IUH SAPI + **********************/ +type enumerated HNBLLIF_IUH_MsgType { + HNBLL_IF_IUH_MSG_CONFIGURE ('0000'O), + HNBLL_IF_IUH_MSG_CONN_ESTABLISH ('0001'O), + HNBLL_IF_IUH_MSG_CONN_RELEASE ('0002'O), + HNBLL_IF_IUH_MSG_CONN_DATA ('0003'O), + HNBLL_IF_IUH_MSG_UNITDATA ('0004'O) +} with { variant "FIELDLENGTH(16)" }; + +/* CONFIGURE */ +type record HNBLLIF_IUH_configure_ind { + uint16_t mcc, + uint16_t mnc, + uint16_t cell_identity, + uint16_t lac, + uint8_t rac, + uint8_t reserved, + uint16_t sac, + uint16_t rnc_id +} with { variant "" }; + +type union HNBLLIF_IUH_PrimOpUnion_configure { + HNBLLIF_IUH_configure_ind ind, + octetstring other +} with { variant "" }; + +type record HNBLLIF_IUH_PrimOp_configure { + HNBLLIF_Operation op, + HNBLLIF_IUH_PrimOpUnion_configure u +} with { variant (u) "CROSSTAG( ind, op = HNBLL_IF_OP_INDICATION; + other, OTHERWISE)" +}; + +/* CONN_ESTABLISH */ +type record HNBLLIF_IUH_conn_establish_req { + uint32_t context_id, + uint8_t domain, + uint8_t est_cause, + uint16_t reserved, //uint16_t nas_node_selector_bitlen; + //uint8_t nas_node_selector[128]; /* TODO: check whether we can decrease this buffer size */ + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + +type record HNBLLIF_IUH_conn_establish_cnf { + uint32_t context_id, + uint8_t domain, + uint8_t est_cause +} with { variant "" }; + +type union HNBLLIF_IUH_PrimOpUnion_conn_establish { + HNBLLIF_IUH_conn_establish_req req, + HNBLLIF_IUH_conn_establish_cnf cnf, + octetstring other +} with { variant "" }; +type record HNBLLIF_IUH_PrimOp_conn_establish { + HNBLLIF_Operation op, + HNBLLIF_IUH_PrimOpUnion_conn_establish u +} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST; + cnf, op = HNBLL_IF_OP_CONFIRM; + other, OTHERWISE)" +}; + +/* CONN_RELEASE */ +type record HNBLLIF_IUH_conn_release_req { + uint32_t context_id, + uint8_t domain, + uint8_t spare1, + uint8_t cause_type, + uint8_t cause, + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + + +type union HNBLLIF_IUH_PrimOpUnion_conn_release { + HNBLLIF_IUH_conn_release_req req, + octetstring other +} with { variant "" }; +type record HNBLLIF_IUH_PrimOp_conn_release { + HNBLLIF_Operation op, + HNBLLIF_IUH_PrimOpUnion_conn_release u +} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST; + other, OTHERWISE)" +}; + +/* CONN_DATA */ +type record HNBLLIF_IUH_conn_data_ind { + uint32_t context_id, + uint8_t domain, + uint8_t spare1, + uint16_t spare2, + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + +type record HNBLLIF_IUH_conn_data_req { + uint32_t context_id, + uint8_t domain, + uint8_t spare1, + uint16_t spare2, + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + +type union HNBLLIF_IUH_PrimOpUnion_conn_data { + HNBLLIF_IUH_conn_data_req req, + HNBLLIF_IUH_conn_data_ind ind, + octetstring other +} with { variant "" }; +type record HNBLLIF_IUH_PrimOp_conn_data { + HNBLLIF_Operation op, + HNBLLIF_IUH_PrimOpUnion_conn_data u +} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST; + ind, op = HNBLL_IF_OP_INDICATION; + other, OTHERWISE)" +}; + +/* UNITDATA */ +type record HNBLLIF_IUH_unitdata_ind { + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + +type record HNBLLIF_IUH_unitdata_req { + uint32_t data_len, + octetstring data /* RANAP message */ +} with { variant (data_len) "LENGTHTO (data)" }; + +type union HNBLLIF_IUH_PrimOpUnion_unitdata { + HNBLLIF_IUH_unitdata_req req, + HNBLLIF_IUH_unitdata_ind ind, + octetstring other +} with { variant "" }; +type record HNBLLIF_IUH_PrimOp_unitdata { + HNBLLIF_Operation op, + HNBLLIF_IUH_PrimOpUnion_unitdata u +} with { variant (u) "CROSSTAG( req, op = HNBLL_IF_OP_REQUEST; + ind, op = HNBLL_IF_OP_INDICATION; + other, OTHERWISE)" +}; + +type union HNBLLIF_IUH_PrimUnion { + HNBLLIF_IUH_PrimOp_configure configure, + HNBLLIF_IUH_PrimOp_conn_establish conn_establish, + HNBLLIF_IUH_PrimOp_conn_release conn_release, + HNBLLIF_IUH_PrimOp_conn_data conn_data, + HNBLLIF_IUH_PrimOp_unitdata unitdata, + octetstring other +} with { variant "" }; + +type record HNBLLIF_IUH_PrimHdr { + HNBLLIF_IUH_MsgType prim, + HNBLLIF_IUH_PrimUnion u +} with { variant (u) "CROSSTAG( configure, prim = HNBLL_IF_IUH_MSG_CONFIGURE; + conn_establish, prim = HNBLL_IF_IUH_MSG_CONN_ESTABLISH; + conn_release, prim = HNBLL_IF_IUH_MSG_CONN_RELEASE; + conn_data, prim = HNBLL_IF_IUH_MSG_CONN_DATA; + unitdata, prim = HNBLL_IF_IUH_MSG_UNITDATA; + other, OTHERWISE)" +}; + + +/********************** +* General +**********************/ +type enumerated HNBLLIF_Sapi { + HNBLL_IF_SAPI_CTL (-1), + HNBLL_IF_SAPI_IUH ('00000001'O)//, + //HNBLL_IF_SAPI_GTP ('00000002'O), + //HNBLL_IF_SAPI_AUDIO ('00000003'O), +} with { variant "FIELDLENGTH(32)" + variant "COMP(2scompl)" +}; + +type enumerated HNBLLIF_Operation { + HNBLL_IF_OP_REQUEST ('0000'O), + HNBLL_IF_OP_RESPONSE ('0001'O), + HNBLL_IF_OP_INDICATION ('0002'O), + HNBLL_IF_OP_CONFIRM ('0003'O) +} with { variant "FIELDLENGTH(16)" }; + +type union HNBLLIF_SapiUnion { + HNBLLIF_CTL_PrimHdr ctl, + HNBLLIF_IUH_PrimHdr iuh, + octetstring other +} with { variant "" }; + +type record HNBLLIF_Message { + HNBLLIF_Sapi sapi, + HNBLLIF_SapiUnion u +} with { variant (u) "CROSSTAG( ctl, sapi = HNBLL_IF_SAPI_CTL; + iuh, sapi = HNBLL_IF_SAPI_IUH; + other, OTHERWISE)" +}; + +external function enc_HNBLLIF_Message(in HNBLLIF_Message pdu) return octetstring + with { extension "prototype(convert) encode(RAW)" }; +external function dec_HNBLLIF_Message(in octetstring stream) return HNBLLIF_Message + with { extension "prototype(convert) decode(RAW)" }; + + +} with { encode "RAW" variant "BYTEORDER(first)" }; diff --git a/library/Iuh_CodecPort.ttcn b/library/Iuh_CodecPort.ttcn index 569a27fd..6bedc0bd 100644 --- a/library/Iuh_CodecPort.ttcn +++ b/library/Iuh_CodecPort.ttcn @@ -96,7 +96,11 @@ module Iuh_CodecPort { } case (0) { /* FIXME: lower layers report sinfo_ppid=0: */ - pout.msg.hnbap := dec_HNBAP_PDU(pin.msg); + if (match(pin.msg, '000100380000070003000C02404F736D6F484E6F64654200080001000009000300F110000B0004000000100006000200020007000103000A00020004'O)) { + pout.msg.hnbap := dec_HNBAP_PDU(pin.msg); + } else { + pout.msg.rua := dec_RUA_PDU(pin.msg); + } } case else { pout.msg.payload := pin.msg; |