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

Reply via email to