aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-11-24 17:00:03 +0100
committerlaforge <laforge@osmocom.org>2021-12-15 14:23:23 +0000
commita6bbb8c45d00471e09d8890f6a402280ad7d600f (patch)
treeaeac6a3afa0048d6831195d7263a8b2da9bf11c2
parent3f7a6dc2976971f96faae0ab6b0e907912b4e49f (diff)
hnodeb: Add initial infra to emulate HNB LL socket iface
-rw-r--r--hnodeb/HNBGW_ConnectionHandler.ttcn92
-rw-r--r--hnodeb/HNB_Tests.default1
-rw-r--r--hnodeb/HNB_Tests.ttcn129
-rwxr-xr-xhnodeb/gen_links.sh7
-rwxr-xr-xhnodeb/regen_makefile.sh1
-rw-r--r--library/HNBLLIF_CodecPort.ttcn95
-rw-r--r--library/HNBLLIF_Templates.ttcn251
-rw-r--r--library/HNBLLIF_Types.ttcn275
-rw-r--r--library/Iuh_CodecPort.ttcn6
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;