summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-08-21 12:39:11 +0200
committerHarald Welte <laforge@osmocom.org>2020-08-21 14:17:57 +0200
commit9f1c0944821cbbe3fae3f9405077338111c6fd35 (patch)
tree334f308a661780f150c95e54eb48d0966db6b837
parent638743cec410a198740c9a0f079b6929ec17718e (diff)
bsc: Add Lb interface supportlaforge/lcs
This introduces the Lb interface stack, which allows BSC_Tests.ttcn to emulate a SMLC towards the BSC. In accordance with https://osmocom.org/projects/cellular-infrastructure/wiki/Point_Codes we use 0.23.6 as point code for emulating the SMLC. Change-Id: I854618cc08de1a716784f52542a4df3c7f7ad900
-rw-r--r--bsc/BSC_Tests.ttcn25
-rw-r--r--bsc/MSC_ConnectionHandler.ttcn28
-rwxr-xr-xbsc/gen_links.sh4
-rw-r--r--library/BSSAP_LE_Adapter.ttcn130
-rw-r--r--library/BSSAP_LE_Emulation.ttcn46
-rw-r--r--library/RAN_Emulation.ttcnpp4
6 files changed, 203 insertions, 34 deletions
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index 0e76476..e8e06f7 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -28,6 +28,8 @@ import from IPL4asp_Types all;
import from BSSAP_Types all;
import from RAN_Adapter all;
+import from BSSAP_LE_Adapter all;
+import from BSSAP_LE_CodecPort all;
import from BSSAP_CodecPort all;
import from BSSMAP_Templates all;
import from IPA_Emulation all;
@@ -480,8 +482,10 @@ type component test_CT extends CTRL_Adapter_CT {
var StatsD_Checker_CT vc_STATSD;
var RAN_Adapter g_bssap[NUM_MSC];
+ var BSSAP_LE_Adapter g_bssap_le;
/* for old legacy-tests only */
port BSSAP_CODEC_PT BSSAP;
+ port BSSAP_LE_CODEC_PT BSSAP_LE;
/* are we initialized yet */
var boolean g_initialized := false;
@@ -553,6 +557,17 @@ modulepar {
}
};
+ BSSAP_LE_Configuration mp_bssap_le_cfg := {
+ sccp_service_type := "mtp3_itu",
+ sctp_addr := { 23908, "127.0.0.1", 2905, "127.0.0.1" },
+ own_pc := 6, /* 0.0.6 SMLC emulation */
+ own_ssn := 252, /* SMLC side SSN */
+ peer_pc := 187, /* 0.23.3 osmo-bsc */
+ peer_ssn := 250, /* BSC side SSN */
+ sio := '83'O,
+ rctx := 6
+ };
+
/* Whether to enable osmux tests. Can be dropped completely and enable
unconditionally once new version of osmo-bsc is released (current
version: 1.4.1) */
@@ -928,6 +943,14 @@ function f_init(integer nr_bts := NUM_BTS, boolean handler_mode := false, boolea
}
}
+ if (handler_mode) {
+ f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", SMLC_BssapLeOps);
+ } else {
+ f_bssap_le_adapter_init(g_bssap_le, mp_bssap_le_cfg, "VirtSMLC", omit);
+ connect(self:BSSAP_LE, g_bssap_le.vc_SCCP:SCCP_SP_PORT);
+ }
+ f_bssap_le_adapter_start(g_bssap_le);
+
/* start the test with exactly all enabled MSCs allowed to attach */
f_vty_msc_allow_attach(BSCVTY, allow_attach);
@@ -2767,6 +2790,7 @@ testcase TC_oml_unknown_unit_id() runs on test_CT {
***********************************************************************/
import from RAN_Emulation all;
+import from BSSAP_LE_Emulation all;
import from RSL_Emulation all;
import from MSC_ConnectionHandler all;
@@ -2787,6 +2811,7 @@ private function f_connect_handler(inout MSC_ConnHdlr vc_conn, integer bssap_idx
connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC);
}
connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT);
+ connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT);
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);
diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn
index bf96eff..f02cfb4 100644
--- a/bsc/MSC_ConnectionHandler.ttcn
+++ b/bsc/MSC_ConnectionHandler.ttcn
@@ -19,6 +19,9 @@ import from IPA_Emulation all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from RAN_Emulation all;
+import from BSSAP_LE_Emulation all;
+import from BSSAP_LE_Types all;
+import from BSSMAP_LE_Templates all;
import from BSSMAP_Templates all;
import from IPL4asp_Types all;
@@ -411,7 +414,7 @@ altstep as_Media() runs on MSC_ConnHdlr {
/* this component represents a single subscriber connection at the MSC.
* There is a 1:1 mapping between SCCP connections and RAN_ConnHdlr components.
* We inherit all component variables, ports, functions, ... from RAN_ConnHdlr */
-type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr, StatsD_ConnHdlr {
+type component MSC_ConnHdlr extends RAN_ConnHdlr, RSL_DchanHdlr, MGCP_ConnHdlr, BSSAP_LE_ConnHdlr, StatsD_ConnHdlr {
/* SCCP Connecction Identifier for the underlying SCCP connection */
var integer g_sccp_conn_id;
@@ -470,6 +473,20 @@ runs on RAN_Emulation_CT return template PDU_BSSAP {
return resp;
}
+/* Callback function from general BSSAP_LE_Emulation whenever a connectionless
+ * BSSAP_LE message arrives. Can return a PDU_BSSAP_LE that should be sent in return */
+private function BSSAP_LE_UnitdataCallback(PDU_BSSAP_LE bssap)
+runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
+ var template PDU_BSSAP_LE resp := omit;
+
+ /* answer all RESET with a RESET ACK */
+ if (match(bssap, tr_BSSMAP_LE_Reset)) {
+ resp := ts_BSSMAP_LE_ResetAck;
+ }
+
+ return resp;
+}
+
const RanOps MSC_RanOps := {
create_cb := refers(RAN_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(UnitdataCallback),
@@ -482,6 +499,15 @@ const RanOps MSC_RanOps := {
sccp_addr_peer := omit
}
+const BssapLeOps SMLC_BssapLeOps := {
+ create_cb := refers(BSSAP_LE_Emulation.ExpectedCreateCallback),
+ unitdata_cb := refers(BSSAP_LE_UnitdataCallback),
+ decode_dtap := false,
+ role_ms := false,
+ sccp_addr_local := omit,
+ sccp_addr_peer := omit
+}
+
const MGCPOps MSC_MGCPOps := {
create_cb := refers(MGCP_Emulation.ExpectedCreateCallback),
unitdata_cb := refers(MGCP_Emulation.DummyUnitdataCallback)
diff --git a/bsc/gen_links.sh b/bsc/gen_links.sh
index 02e093d..f316509 100755
--- a/bsc/gen_links.sh
+++ b/bsc/gen_links.sh
@@ -70,7 +70,9 @@ DIR=../library
FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn GSM_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 L3_Templates.ttcn BSSMAP_Templates.ttcn RAN_Emulation.ttcnpp RLCMAC_CSN1_Templates.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn RAN_Adapter.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 SCCP_Templates.ttcn IPA_Testing.ttcn GSM_SystemInformation.ttcn GSM_RestOctets.ttcn "
FILES+="CBSP_Types.ttcn CBSP_Templates.ttcn "
FILES+="CBSP_CodecPort.ttcn CBSP_CodecPort_CtrlFunct.ttcn CBSP_CodecPort_CtrlFunctdef.cc CBSP_Adapter.ttcn "
-FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn"
+FILES+="StatsD_Types.ttcn StatsD_CodecPort.ttcn StatsD_CodecPort_CtrlFunct.ttcn StatsD_CodecPort_CtrlFunctdef.cc StatsD_Checker.ttcn "
+FILES+="BSSAP_LE_CodecPort.ttcn BSSAP_LE_Emulation.ttcn BSSAP_LE_Types.ttcn BSSAP_LE_Adapter.ttcn BSSLAP_Types.ttcn BSSMAP_LE_Templates.ttcn "
+
gen_links $DIR $FILES
ignore_pp_results
diff --git a/library/BSSAP_LE_Adapter.ttcn b/library/BSSAP_LE_Adapter.ttcn
new file mode 100644
index 0000000..dba8841
--- /dev/null
+++ b/library/BSSAP_LE_Adapter.ttcn
@@ -0,0 +1,130 @@
+module BSSAP_LE_Adapter {
+
+/* This module implements a 'dumb' BSSAP_LE adapter. It creates the M3UA and SCCP components and stacks a
+ * BSSAP_LE codec port on top. As a result, it provides the ability to transceive SCCP-User-SAP primitives
+ * with deoded BSSAP_LE payload. Use this if you want to have full control about what you transmit or
+ * receive, without any automatisms in place. Allows you to refuse connections or other abnormal behavior. */
+
+/* (C) 2017-2020 Harald Welte <laforge@gnumonks.org>
+ * contributions by sysmocom - s.f.m.c. GmbH
+ * All rights reserved.
+ *
+ * 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
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from M3UA_Emulation all;
+import from MTP3asp_Types all;
+import from MTP3asp_PortType all;
+
+import from IPA_Emulation all;
+
+import from SCCP_Types all;
+import from SCCPasp_Types all;
+import from SCCP_Emulation all;
+import from SCCP_Templates all;
+
+import from SCTPasp_Types all;
+import from SCTPasp_PortType all;
+
+import from BSSMAP_LE_Templates all;
+import from BSSAP_LE_Emulation all;
+
+type record BSSAP_LE_Adapter {
+ /* component references */
+ M3UA_CT vc_M3UA, /* only in 3GPP AoIP */
+ SCCP_CT vc_SCCP,
+
+ MSC_SCCP_MTP3_parameters sccp_pars,
+ SCCP_PAR_Address sccp_addr_own,
+ SCCP_PAR_Address sccp_addr_peer,
+
+ /* handler mode */
+ BSSAP_LE_Emulation_CT vc_BSSAP_LE
+}
+
+type record BSSAP_LE_Configuration {
+ charstring sccp_service_type,
+ SCTP_Association_Address sctp_addr,
+ integer own_pc,
+ integer own_ssn,
+ integer peer_pc,
+ integer peer_ssn,
+ octetstring sio,
+ integer rctx
+};
+type record of BSSAP_LE_Configuration BSSAP_LE_Configurations;
+
+private function init_pars(inout BSSAP_LE_Adapter ba, in BSSAP_LE_Configuration cfg) {
+ ba.sccp_pars := {
+ sio := {
+ ni := substr(oct2bit(cfg.sio),0,2),
+ prio := substr(oct2bit(cfg.sio),2,2),
+ si := substr(oct2bit(cfg.sio),4,4)
+ },
+ opc := cfg.own_pc,
+ dpc := cfg.peer_pc,
+ sls := 0,
+ sccp_serviceType := cfg.sccp_service_type,
+ ssn := cfg.own_ssn
+ };
+ ba.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(cfg.own_pc, cfg.own_ssn, cfg.sio, cfg.sccp_service_type));
+ ba.sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(cfg.peer_pc, cfg.peer_ssn, cfg.sio, cfg.sccp_service_type));
+}
+
+
+function f_bssap_le_adapter_init(inout BSSAP_LE_Adapter ba, in BSSAP_LE_Configuration cfg, charstring id,
+ template BssapLeOps ops) {
+ init_pars(ba, cfg);
+ ops.sccp_addr_local := ba.sccp_addr_own;
+ ops.sccp_addr_peer := ba.sccp_addr_peer;
+
+ /* create components */
+ ba.vc_SCCP := SCCP_CT.create(id & "-SCCP");
+ if (isvalue(ops)) {
+ ba.vc_BSSAP_LE := BSSAP_LE_Emulation_CT.create(id & "-BSSAP_LE");
+ } else {
+ ba.vc_BSSAP_LE := null;
+ }
+ ba.vc_M3UA := M3UA_CT.create(id & "-M3UA");
+ map(ba.vc_M3UA:SCTP_PORT, system:sctp);
+ /* connect MTP3 service provider (M3UA) to lower side of SCCP */
+ connect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
+ ba.vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr, cfg.rctx));
+
+ if (isvalue(ops)) {
+ timer T := 5.0;
+ T.start;
+ //T.timeout;
+ /* connect BSSNAP component to upper side of SCCP */
+ log("Connecting BSSAP_LE_Emulation to SCCP_SP_PORT");
+ connect(ba.vc_BSSAP_LE:BSSAP_LE, ba.vc_SCCP:SCCP_SP_PORT);
+ log("Starting BSSAP_LE_Emulation");
+ ba.vc_BSSAP_LE.start(BSSAP_LE_Emulation.main(valueof(ops), ""));
+ }
+
+
+}
+
+function f_bssap_le_adapter_start(inout BSSAP_LE_Adapter ba) {
+ ba.vc_SCCP.start(SCCPStart(ba.sccp_pars));
+}
+
+function f_bssap_le_adapter_cleanup(inout BSSAP_LE_Adapter ba) {
+ if (ba.vc_BSSAP_LE != null) {
+ disconnect(ba.vc_BSSAP_LE:BSSAP_LE, ba.vc_SCCP:SCCP_SP_PORT);
+ ba.vc_BSSAP_LE.stop;
+ }
+ unmap(ba.vc_M3UA:SCTP_PORT, system:sctp);
+ disconnect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
+ ba.vc_M3UA.stop;
+ ba.vc_SCCP.stop;
+}
+
+
+}
diff --git a/library/BSSAP_LE_Emulation.ttcn b/library/BSSAP_LE_Emulation.ttcn
index 519d10f..8276e56 100644
--- a/library/BSSAP_LE_Emulation.ttcn
+++ b/library/BSSAP_LE_Emulation.ttcn
@@ -289,7 +289,6 @@ runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE;
/* handle common Unitdata such as Paging */
private function CommonBssmapUnitdataCallback(PDU_BSSAP_LE bssap)
runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
-/*
if (match(bssap, tr_BSSMAP_LE_Paging)) {
var BSSAP_LE_ConnHdlr client := null;
client := f_imsi_table_find(bssap.pdu.bssmap.paging.iMSI.digits,
@@ -304,15 +303,14 @@ runs on BSSAP_LE_Emulation_CT return template PDU_BSSAP_LE {
} else {
log("CommonBssmapUnitdataCallback: Not a paging message");
}
-*/
/* ELSE: handle in user callback */
return g_ran_ops.unitdata_cb.apply(bssap);
}
-function f_bssap_reset(SCCP_PAR_Address peer, SCCP_PAR_Address own) runs on BSSAP_LE_Emulation_CT {
+private function f_bssap_le_reset(SCCP_PAR_Address peer, SCCP_PAR_Address own) runs on BSSAP_LE_Emulation_CT {
timer T := 5.0;
- BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(peer, own, ts_BSSMAP_LE_Reset(0)));
+ BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(peer, own, ts_BSSMAP_LE_Reset(GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE)));
T.start;
alt {
[] BSSAP_LE.receive(tr_BSSAP_LE_UNITDATA_ind(own, peer, tr_BSSMAP_LE_ResetAck)) {
@@ -371,7 +369,7 @@ private altstep as_main_bssap_le() runs on BSSAP_LE_Emulation_CT {
/* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
[] BSSAP_LE.receive(BSSAP_LE_N_UNITDATA_ind:?) -> value ud_ind {
/* Connectionless Procedures like RESET */
- var template PDU_BSSAP resp;
+ var template PDU_BSSAP_LE resp;
resp := CommonBssmapUnitdataCallback(ud_ind.userData);
if (isvalue(resp)) {
BSSAP_LE.send(ts_BSSAP_LE_UNITDATA_req(ud_ind.callingAddress,
@@ -417,7 +415,7 @@ private altstep as_main_bssap_le() runs on BSSAP_LE_Emulation_CT {
f_handle_userData(vc_conn, conn_cfm.userData);
}
}
- [] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn {
+ [] CLIENT.receive(PDU_BSSAP_LE:?) -> value bssap sender vc_conn {
var integer conn_id := f_conn_id_by_comp(vc_conn);
/* send it to dispatcher */
BSSAP_LE.send(ts_BSSAP_LE_DATA_req(conn_id, bssap));
@@ -435,7 +433,7 @@ private altstep as_main_bssap_le() runs on BSSAP_LE_Emulation_CT {
}
/* BSSAP from client -> SCCP */
- [] CLIENT.receive(BSSAP_Conn_Req:?) -> value creq sender vc_conn {
+ [] CLIENT.receive(BSSAP_LE_Conn_Req:?) -> value creq sender vc_conn {
var integer conn_id;
/* send to dispatcher */
@@ -486,6 +484,16 @@ private function f_xmit_raw_l3(integer sccp_conn_id, OCT1 dlci, octetstring l3_e
BSSAP_LE.send(ts_BSSAP_LE_DATA_req(sccp_conn_id, bssap));
}
+/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
+private function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+ var integer n_sd_idx := f_ML3_n_sd_idx(dtap);
+ if (n_sd_idx < 0) {
+ return;
+ }
+ var uint2_t seq_nr := f_next_n_sd(cd.n_sd, n_sd_idx);
+ f_ML3_patch_seq_nr(seq_nr, enc_l3);
+}
+
function main(BssapLeOps ops, charstring id) runs on BSSAP_LE_Emulation_CT {
g_ran_id := id;
@@ -529,9 +537,6 @@ function main(BssapLeOps ops, charstring id) runs on BSSAP_LE_Emulation_CT {
f_xmit_raw_l3(ConnectionTable[idx].sccp_conn_id, dtap_mt.dlci, l3_enc);
}
- [] as_main_mgcp();
- [] as_main_ctrl();
-
[] PROC.getcall(BSSAP_LE_register:{?,?}) -> param(l3_info, vc_hdlr) {
f_create_expect(l3_info, vc_hdlr);
PROC.reply(BSSAP_LE_register:{l3_info, vc_hdlr}) to vc_hdlr;
@@ -587,35 +592,17 @@ function ExpectedCreateCallback(BSSAP_LE_N_CONNECT_ind conn_ind, charstring id)
runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr {
var BSSAP_LE_ConnHdlr ret := null;
var octetstring l3_info;
- var boolean handoverRequest := false;
- var integer handoverRequestPointCode;
var integer i;
if (ischosen(conn_ind.userData.pdu.bssmap.completeLayer3Information)) {
l3_info := conn_ind.userData.pdu.bssmap.completeLayer3Information.layer3Information.layer3info;
log("ExpectedCreateCallback completeLayer3Information");
- } else if (ischosen(conn_ind.userData.pdu.bssmap.handoverRequest)) {
- handoverRequest := true;
- handoverRequestPointCode := bit2int(conn_ind.calledAddress.signPointCode);
- log("ExpectedCreateCallback handoverRequest ", handoverRequestPointCode);
} else {
- setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3 nor a Handover Request");
+ setverdict(fail, "N-CONNECT.ind with L3 != COMPLETE L3");
mtc.stop;
- return ret;
}
for (i := 0; i < sizeof(ExpectTable); i:= i+1) {
- if (handoverRequest) {
- log("ExpectTable[", i, "].handoverRequestPointCode = ", ExpectTable[i].handoverRequestPointCode,
- " ==? ", handoverRequestPointCode);
- if (ExpectTable[i].handoverRequestPointCode == handoverRequestPointCode) {
- ret := ExpectTable[i].vc_conn;
- log("Found Expect[", i, "] for handoverRequest handled at ", ret);
- return ret;
- } else {
- continue;
- }
- }
if (not ispresent(ExpectTable[i].l3_payload)) {
continue;
}
@@ -631,7 +618,6 @@ runs on BSSAP_LE_Emulation_CT return BSSAP_LE_ConnHdlr {
}
setverdict(fail, "Couldn't find Expect for incoming connection ", conn_ind);
mtc.stop;
- return ret;
}
diff --git a/library/RAN_Emulation.ttcnpp b/library/RAN_Emulation.ttcnpp
index c1dc036..f410427 100644
--- a/library/RAN_Emulation.ttcnpp
+++ b/library/RAN_Emulation.ttcnpp
@@ -720,7 +720,7 @@ type record RanOps {
template BIT4 t_ML3_DISC_CC_MM_SS := ('0011'B, '0101'B, '1011'B);
-private function f_L3_is_rr(template octetstring l3) return boolean {
+function f_L3_is_rr(template octetstring l3) return boolean {
if (not isvalue(l3)) {
return false;
}
@@ -773,7 +773,7 @@ function f_ML3_n_sd_idx(in PDU_ML3_MS_NW dtap) return integer {
}
/* patch N(SD) into enc_l3, according to 24.007 11.2.3.2 */
-function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
+private function f_ML3_patch_seq(inout ConnectionData cd, in PDU_ML3_MS_NW dtap, inout octetstring enc_l3) {
var integer n_sd_idx := f_ML3_n_sd_idx(dtap);
if (n_sd_idx < 0) {
return;