laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/36620?usp=email )
Change subject: RUA_Emulation: Support decode of L3/DTAP inside RANAP ...................................................................... RUA_Emulation: Support decode of L3/DTAP inside RANAP ... similar to what we support in the RAN_Emulation module. Change-Id: Id934e73ace7d0a0eb7242a8fa926b7eabe0c7770 --- M hnbgw/HNBGW_Tests.ttcn M library/RAN_Emulation.ttcnpp M library/rua/RUA_Emulation.ttcn 3 files changed, 127 insertions(+), 12 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/20/36620/1 diff --git a/hnbgw/HNBGW_Tests.ttcn b/hnbgw/HNBGW_Tests.ttcn index 3369e37..a53187a 100644 --- a/hnbgw/HNBGW_Tests.ttcn +++ b/hnbgw/HNBGW_Tests.ttcn @@ -499,7 +499,9 @@ /* RUA/RANAP emulation on top of lower-layer Iuh */ var RuaOps rua_ops := { create_cb := refers(IuhRanapCreateCallback), - unitdata_cb := refers(IuhRanapUnitdataCallback) + unitdata_cb := refers(IuhRanapUnitdataCallback), + decode_dtap := false, + role_ms := true }; for (var integer i := 0; i < g_num_hnbs; i := i+1) { g_hnb_cfg[i] := { diff --git a/library/RAN_Emulation.ttcnpp b/library/RAN_Emulation.ttcnpp index fbe921d..25c6a49 100644 --- a/library/RAN_Emulation.ttcnpp +++ b/library/RAN_Emulation.ttcnpp @@ -62,6 +62,8 @@ import from RANAP_Templates all; #endif +friend module RUA_Emulation; + /* General "base class" component definition, of which specific implementations * derive themselves by means of the "extends" feature */ type component RAN_ConnHdlr { @@ -580,7 +582,7 @@ ranap := ranap }; -private function fake_dlci_from_sapi(template (omit) SAPI sapi) return template (omit) OCT1 +friend function fake_dlci_from_sapi(template (omit) SAPI sapi) return template (omit) OCT1 { if (istemplatekind(sapi, "omit")) { return omit; diff --git a/library/rua/RUA_Emulation.ttcn b/library/rua/RUA_Emulation.ttcn index a9c445e..4560ad2 100644 --- a/library/rua/RUA_Emulation.ttcn +++ b/library/rua/RUA_Emulation.ttcn @@ -17,7 +17,7 @@ * If a pre-existing component wants to register to handle future inbound connection, * it can do so by registering an "expect" with the expected RANAP payload. - * (C) 2022 by Harald Welte <lafo...@gnumonks.org> + * (C) 2022-2024 by Harald Welte <lafo...@gnumonks.org> * All rights reserved. * * Released under the terms of GNU General Public License, Version 2 or @@ -26,8 +26,10 @@ import from General_Types all; import from Osmocom_Types all; +import from MobileL3_Types all; import from Iuh_Emulation all; +import from RAN_Emulation all; // for PDU_DTAP_MO / PDU_DTAP_MT import from RUA_Templates all; //import from RUA_Constants all; @@ -54,6 +56,8 @@ /* port between individual per-connection components and this dispatcher */ type port RUA_Conn_PT message { inout RANAP_PDU, + PDU_DTAP_MO, PDU_DTAP_MT, + PDU_DTAP_PS_MO, PDU_DTAP_PS_MT, RUA_Conn_Req, RUA_Disc_Req, RUA_Disc_Ind; @@ -113,9 +117,9 @@ type record RuaOps { RanapCreateCallback create_cb optional, - RanapUnitdataCallback unitdata_cb optional - //boolean deode_dtap - //boolean role_ms + RanapUnitdataCallback unitdata_cb optional, + boolean decode_dtap, + boolean role_ms }; private function f_context_id_known(ContextId context_id) @@ -240,10 +244,56 @@ return g_rua_ops.unitdata_cb.apply(ranap); } -private function f_handle_userData_RANAP(RUA_ConnHdlr client, RANAP_PDU ranap) +private function f_handle_userData_RANAP(RUA_ConnHdlr client, RUA_IEs.CN_DomainIndicator domain_ind, RANAP_PDU ranap) runs on RUA_Emulation_CT { - /* TODO: L3 decoding, if requested */ - CLIENT.send(ranap) to client; + var template (omit) octetstring l3 := f_ranap_extract_l3(ranap); + if (istemplatekind(l3, "omit") or not g_rua_ops.decode_dtap) { + CLIENT.send(ranap) to client; + } else { + var template (omit) SAPI sapi := f_ranap_extract_sapi(ranap); + var template (omit) OCT1 dlci := fake_dlci_from_sapi(sapi); + if (g_rua_ops.role_ms) { + if (domain_ind == ps_domain) { + var PDU_DTAP_PS_MT mt := { + dlci := omit, + dtap := dec_PDU_L3_SGSN_MS(valueof(l3)) + }; + if (isvalue(dlci)) { + mt.dlci := valueof(dlci); + } + CLIENT.send(mt) to client; + } else { + var PDU_DTAP_MT mt := { + dlci := omit, + dtap := dec_PDU_ML3_NW_MS(valueof(l3)) + }; + if (isvalue(dlci)) { + mt.dlci := valueof(dlci); + } + CLIENT.send(mt) to client; + } + } else { + if (domain_ind == ps_domain) { + var PDU_DTAP_PS_MO mo := { + dlci := omit, + dtap := dec_PDU_L3_MS_SGSN(valueof(l3)) + }; + if (isvalue(dlci)) { + mo.dlci := valueof(dlci); + } + CLIENT.send(mo) to client; + } else { + var PDU_DTAP_MO mo := { + dlci := omit, + dtap := dec_PDU_ML3_MS_NW(valueof(l3)) + }; + if (isvalue(dlci)) { + mo.dlci := valueof(dlci); + } + CLIENT.send(mo) to client; + } + } + } } @@ -289,26 +339,28 @@ f_conn_table_add(vc_conn, domain_ind, context_id); /* TODO: notify user about incoming connection? */ /* handle user payload */ - f_handle_userData_RANAP(vc_conn, ranap); + f_handle_userData_RANAP(vc_conn, domain_ind, ranap); } /* RUA -> Client: connection-oriented data in existing connection */ [] RUA.receive(tr_RUA_DirectTransfer) -> value rua { + domain_ind := rua.initiatingMessage.value_.directTransfer.protocolIEs[0].value_.cN_DomainIndicator; context_id := rua.initiatingMessage.value_.directTransfer.protocolIEs[1].value_.context_ID; vc_conn := f_comp_by_context_id(context_id); ranap_enc := rua.initiatingMessage.value_.directTransfer.protocolIEs[2].value_.rANAP_Message; - f_handle_userData_RANAP(vc_conn, dec_RANAP_PDU(ranap_enc)); + f_handle_userData_RANAP(vc_conn, domain_ind, dec_RANAP_PDU(ranap_enc)); } /* RUA -> Client: disconnect of an existing connection */ [] RUA.receive(tr_RUA_Disconnect_opt_ranap) -> value rua { + domain_ind := rua.initiatingMessage.value_.disconnect_.protocolIEs[0].value_.cN_DomainIndicator; cause := rua.initiatingMessage.value_.disconnect_.protocolIEs[2].value_.cause; context_id := rua.initiatingMessage.value_.disconnect_.protocolIEs[1].value_.context_ID; vc_conn := f_comp_by_context_id(context_id); /* send contained RANAP message to user */ if (lengthof(rua.initiatingMessage.value_.disconnect_.protocolIEs) > 3) { ranap_enc := rua.initiatingMessage.value_.disconnect_.protocolIEs[3].value_.rANAP_Message; - f_handle_userData_RANAP(vc_conn, dec_RANAP_PDU(ranap_enc)); + f_handle_userData_RANAP(vc_conn, domain_ind, dec_RANAP_PDU(ranap_enc)); } /* notify user of disconnect */ if (CLIENT.checkstate("Connected")) { @@ -380,6 +432,20 @@ } } +private function f_xmit_raw_l3(RUA_IEs.CN_DomainIndicator domain_ind, integer context_id, OCT1 dlci, octetstring l3_enc) runs on RUA_Emulation_CT +{ + var template (omit) RANAP_IEs.SAPI sapi := omit; + var RANAP_PDU ranap; + + if (dlci and4b '07'O == '03'O) { + sapi := sapi_3; + } + + ranap := valueof(ts_RANAP_DirectTransfer(l3_enc, sapi := sapi)); + RUA.send(ts_RUA_DirectTransfer(domain_ind, int2bit(context_id, 24), enc_RANAP_PDU(ranap))); +} + + function main(RuaOps ops, charstring id) runs on RUA_Emulation_CT { g_rua_id := id; g_rua_ops := ops; @@ -387,9 +453,43 @@ //f_expect_table_init(); while (true) { + var RUA_ConnHdlr vc_conn; + var PDU_DTAP_MO dtap_mo; + var PDU_DTAP_MT dtap_mt; + var PDU_DTAP_PS_MO dtap_mo_ps; + var PDU_DTAP_PS_MT dtap_mt_ps; + alt { [] as_main_rua(); + [g_rua_ops.role_ms] CLIENT.receive(PDU_DTAP_MO:?) -> value dtap_mo sender vc_conn { + var integer idx := f_idx_by_comp(vc_conn); + /* convert from decoded DTAP to encoded DTAP */ + var octetstring l3_enc := enc_PDU_ML3_MS_NW(dtap_mo.dtap); + /* TODO: patch correct L3 send sequence number N(SD) into l3_enc */ + f_xmit_raw_l3(ConnectionTable[idx].domain, ConnectionTable[idx].context_id, dtap_mo.dlci, l3_enc); + } + + [not g_rua_ops.role_ms] CLIENT.receive(PDU_DTAP_MT:?) -> value dtap_mt sender vc_conn { + var integer idx := f_idx_by_comp(vc_conn); + /* convert from decoded DTAP to encoded DTAP */ + var octetstring l3_enc := enc_PDU_ML3_NW_MS(dtap_mt.dtap); + f_xmit_raw_l3(ConnectionTable[idx].domain, ConnectionTable[idx].context_id, dtap_mo.dlci, l3_enc); + } + + [g_rua_ops.role_ms] CLIENT.receive(PDU_DTAP_PS_MO:?) -> value dtap_mo_ps sender vc_conn { + var integer idx := f_idx_by_comp(vc_conn); + var octetstring l3_enc := enc_PDU_L3_MS_SGSN(dtap_mo_ps.dtap); + /* TODO: patch correct L3 send sequence number N(SD) into l3_enc */ + f_xmit_raw_l3(ConnectionTable[idx].domain, ConnectionTable[idx].context_id, dtap_mo_ps.dlci, l3_enc); + } + + [not g_rua_ops.role_ms] CLIENT.receive(PDU_DTAP_PS_MT:?) -> value dtap_mt_ps sender vc_conn { + var integer idx := f_idx_by_comp(vc_conn); + var octetstring l3_enc := enc_PDU_L3_SGSN_MS(dtap_mt_ps.dtap); + f_xmit_raw_l3(ConnectionTable[idx].domain, ConnectionTable[idx].context_id, dtap_mt_ps.dlci, l3_enc); + } + /* [] PROC.getcall(RUA_Register:{?,?}) -> param(l3_info, vc_hdlr) { f_create_expect(l3_info, vc_hdlr); -- To view, visit https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/36620?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-ttcn3-hacks Gerrit-Branch: master Gerrit-Change-Id: Id934e73ace7d0a0eb7242a8fa926b7eabe0c7770 Gerrit-Change-Number: 36620 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <lafo...@osmocom.org> Gerrit-MessageType: newchange