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 <laforge(a)gnumonks.org>
+ * (C) 2022-2024 by Harald Welte <laforge(a)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 <laforge(a)osmocom.org>
Gerrit-MessageType: newchange