2017-07-23 15:26:17 +00:00
|
|
|
module BSSGP_Emulation {
|
|
|
|
|
2019-05-27 09:54:11 +00:00
|
|
|
/* BSSGP Emulation in TTCN-3
|
2021-01-17 12:46:57 +00:00
|
|
|
* (C) 2018-2021 Harald Welte <laforge@gnumonks.org>
|
2019-05-27 09:54:11 +00:00
|
|
|
* 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
|
2020-10-04 20:52:56 +00:00
|
|
|
*
|
|
|
|
* This code implements BSSGP asa hierarchy of components:
|
|
|
|
* - the main BSSGP_CT which runs on top of a NSE (NS Entity).
|
|
|
|
* - demultiplex based on BVCI. BVCI=0 is handled to a user port
|
|
|
|
* - a per-BVC BSSGP_BVC_CT which runs on top of BSSGP_CT, it handles
|
|
|
|
* one PTP BVCI (i.e. one cell)
|
|
|
|
* - demultiplex based on TLLI
|
|
|
|
* - a per-TLLI BSSGP_Client_CT which runs on top of BSSGP_BVC_CT
|
2019-05-27 09:54:11 +00:00
|
|
|
*/
|
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
import from General_Types all;
|
|
|
|
import from Osmocom_Types all;
|
2018-02-15 16:45:29 +00:00
|
|
|
import from NS_Types all;
|
|
|
|
import from NS_Emulation all;
|
|
|
|
import from BSSGP_Types all;
|
|
|
|
import from Osmocom_Gb_Types all;
|
|
|
|
import from IPL4asp_Types all;
|
2021-02-05 11:07:04 +00:00
|
|
|
import from Misc_Helpers all;
|
2018-02-15 16:45:29 +00:00
|
|
|
|
2020-09-12 18:51:05 +00:00
|
|
|
#ifdef BSSGP_EM_L3
|
2018-02-15 19:39:13 +00:00
|
|
|
import from MobileL3_GMM_SM_Types all;
|
|
|
|
import from MobileL3_Types all;
|
2020-09-12 18:51:05 +00:00
|
|
|
#endif
|
2018-02-15 19:39:13 +00:00
|
|
|
|
|
|
|
import from LLC_Types all;
|
|
|
|
import from LLC_Templates all;
|
|
|
|
|
2018-02-18 18:03:36 +00:00
|
|
|
import from SNDCP_Types all;
|
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
/***********************************************************************
|
2020-10-04 20:52:56 +00:00
|
|
|
* Communication between Client Components and per-BVC component
|
2018-02-15 19:39:13 +00:00
|
|
|
***********************************************************************/
|
|
|
|
|
2018-02-15 16:45:29 +00:00
|
|
|
type record BssgpStatusIndication {
|
2020-10-04 20:52:56 +00:00
|
|
|
Nsei nsei optional,
|
2018-02-15 16:45:29 +00:00
|
|
|
BssgpBvci bvci,
|
|
|
|
BvcState state
|
2020-10-04 20:52:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
type record BssgpResetIndication {
|
|
|
|
BssgpBvci bvci
|
|
|
|
};
|
|
|
|
|
|
|
|
template (value) BssgpStatusIndication
|
|
|
|
ts_BssgpStsInd(template (omit) Nsei nsei, template (value) BssgpBvci bvci,
|
|
|
|
template (value) BvcState state) := {
|
|
|
|
nsei := nsei,
|
|
|
|
bvci := bvci,
|
|
|
|
state := state
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
template (present) BssgpStatusIndication
|
|
|
|
tr_BssgpStsInd(template Nsei nsei, template (present) BssgpBvci bvci,
|
|
|
|
template (present) BvcState state) := {
|
2018-02-15 16:45:29 +00:00
|
|
|
nsei := nsei,
|
|
|
|
bvci := bvci,
|
|
|
|
state := state
|
|
|
|
}
|
|
|
|
|
|
|
|
type enumerated BvcState {
|
2020-10-04 20:52:56 +00:00
|
|
|
/* SGSN role: waiting to be reset by the peer */
|
|
|
|
BVC_S_WAIT_RESET,
|
|
|
|
/* PCU role: waiting for NS_ALIVE_UNBLOCKED */
|
|
|
|
BVC_S_WAIT_NS_ALIVE_UNBLOCKED,
|
|
|
|
/* BVC-BLOCKED state */
|
2018-02-15 16:45:29 +00:00
|
|
|
BVC_S_BLOCKED,
|
2020-10-04 20:52:56 +00:00
|
|
|
/* BVC-UNBLOCKED state */
|
2018-02-15 16:45:29 +00:00
|
|
|
BVC_S_UNBLOCKED
|
|
|
|
};
|
|
|
|
|
|
|
|
/* port from our (internal) point of view */
|
|
|
|
type port BSSGP_SP_PT message {
|
2018-02-15 19:39:13 +00:00
|
|
|
in PDU_BSSGP,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_LLC
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
,
|
2018-02-15 19:39:13 +00:00
|
|
|
PDU_L3_MS_SGSN,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_L3_SGSN_MS
|
|
|
|
#endif
|
|
|
|
;
|
2019-05-02 23:29:29 +00:00
|
|
|
out PDU_BSSGP,
|
|
|
|
PDU_LLC,
|
|
|
|
PDU_SN,
|
2018-02-15 16:45:29 +00:00
|
|
|
NsStatusIndication,
|
|
|
|
BssgpStatusIndication,
|
2020-09-12 18:51:05 +00:00
|
|
|
ASP_Event
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
,
|
2018-02-15 19:39:13 +00:00
|
|
|
PDU_L3_MS_SGSN,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_L3_SGSN_MS
|
|
|
|
#endif
|
|
|
|
;
|
2018-02-15 16:45:29 +00:00
|
|
|
} with { extension "internal" };
|
|
|
|
|
|
|
|
/* port from the user point of view */
|
|
|
|
type port BSSGP_PT message {
|
|
|
|
in ASP_Event,
|
|
|
|
NsStatusIndication,
|
|
|
|
BssgpStatusIndication,
|
2019-05-02 23:29:29 +00:00
|
|
|
PDU_BSSGP,
|
|
|
|
PDU_LLC,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_SN
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
,
|
2018-02-15 19:39:13 +00:00
|
|
|
PDU_L3_MS_SGSN,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_L3_SGSN_MS
|
|
|
|
#endif
|
|
|
|
;
|
2018-02-15 19:39:13 +00:00
|
|
|
out PDU_BSSGP,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_LLC
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
,
|
2018-02-15 19:39:13 +00:00
|
|
|
PDU_L3_SGSN_MS,
|
2020-09-12 18:51:05 +00:00
|
|
|
PDU_L3_MS_SGSN
|
|
|
|
#endif
|
|
|
|
;
|
2018-02-15 16:45:29 +00:00
|
|
|
} with { extension "internal" };
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
signature BSSGP_register_client(hexstring imsi, OCT4 tlli);
|
2018-02-15 19:39:13 +00:00
|
|
|
signature BSSGP_unregister_client(hexstring imsi);
|
2018-02-17 09:11:19 +00:00
|
|
|
signature BSSGP_llgmm_assign(OCT4 tlli_old, OCT4 tlli);
|
2018-02-15 19:39:13 +00:00
|
|
|
|
|
|
|
type port BSSGP_PROC_PT procedure {
|
2018-02-17 09:11:19 +00:00
|
|
|
inout BSSGP_register_client, BSSGP_unregister_client, BSSGP_llgmm_assign;
|
2018-02-15 19:39:13 +00:00
|
|
|
} with { extension "internal" };
|
|
|
|
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* Client Component for a single MS/TLLI
|
2020-10-04 20:52:56 +00:00
|
|
|
***********************************************************************
|
|
|
|
* This is what most users will want to derive their test cases from. It
|
|
|
|
* provides a set of three different ports (PTP, signaling, procedure)
|
|
|
|
* for (currently up to 3) different Cells. Those ports are all connected
|
|
|
|
* to one or multiple different per-BVC compoennts, depending on whether
|
|
|
|
* they share the same BSS or not.
|
2018-02-15 19:39:13 +00:00
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
type component BSSGP_Client_CT {
|
2020-10-04 20:52:56 +00:00
|
|
|
/* one port array for each client; allows talking to up to 3 BVC/Cell (handover, ...) */
|
|
|
|
port BSSGP_PT BSSGP[3]; /* PTP-BVC */
|
|
|
|
port BSSGP_PT BSSGP_SIG[3]; /* Signaling BVC */
|
2020-12-10 22:41:14 +00:00
|
|
|
port BSSGP_PT BSSGP_GLOBAL[3]; /* Signaling BVC */
|
2020-10-04 20:52:56 +00:00
|
|
|
port BSSGP_PROC_PT BSSGP_PROC[3]; /* registration / deregistration */
|
2018-02-15 19:39:13 +00:00
|
|
|
};
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
function f_bssgp_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT := BSSGP_PROC[0])
|
|
|
|
runs on BSSGP_Client_CT {
|
|
|
|
PT.call(BSSGP_register_client:{imsi, tlli}) {
|
|
|
|
[] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function f_bssgp_client_unregister(hexstring imsi, BSSGP_PROC_PT PT := BSSGP_PROC[0])
|
|
|
|
runs on BSSGP_Client_CT {
|
|
|
|
PT.call(BSSGP_unregister_client:{imsi}) {
|
|
|
|
[] PT.getreply(BSSGP_unregister_client:{imsi}) {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
|
|
|
|
function f_bssgp_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_PROC_PT PT := BSSGP_PROC[0])
|
|
|
|
runs on BSSGP_Client_CT {
|
|
|
|
PT.call(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {
|
|
|
|
[] PT.getreply(BSSGP_llgmm_assign:{tlli_old, tlli_new}) {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* Main Component
|
2020-10-04 20:52:56 +00:00
|
|
|
***********************************************************************
|
|
|
|
* This component exists once, and it runs on to of the NS_Emulation.
|
|
|
|
* It handles the BVC-RESET for the signaling BVCI, and dispatches messages
|
|
|
|
* to the per-BVC components running above it. Messages are routed by:
|
|
|
|
* - PTP BVCI in NS header (if non-0)
|
|
|
|
* - BVCI IE in messages on BVCI=0 in NS header
|
|
|
|
* Messages for which no unique BVC can be identified (like paging without
|
|
|
|
* a BVCI IE set) are broadcast to all BVC components.
|
|
|
|
* We also broadcast state changes (BssgpStatusIndication) and reset events
|
|
|
|
* (BssgpResetIndication) of the signaling BVC to all per-BVC components.
|
2018-02-15 19:39:13 +00:00
|
|
|
***********************************************************************/
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
function BssgpStart(BssgpConfig cfg, charstring id) runs on BSSGP_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
g_cfg := cfg;
|
2018-02-15 16:45:29 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* create the per-BVC components based on the configuration */
|
|
|
|
for (var integer i := 0; i < lengthof(g_cfg.bvc); i := i+1) {
|
|
|
|
var BssgpBvcConfig bvc_cfg := g_cfg.bvc[i];
|
|
|
|
var charstring bvc_id := id & "-BVCI" & int2str(bvc_cfg.bvci);
|
|
|
|
/* create, connect and start the BVC component */
|
|
|
|
var BSSGP_BVC_CT bvc_ct := BSSGP_BVC_CT.create(bvc_id);
|
|
|
|
connect(bvc_ct:BVC, self:BVC);
|
2020-11-24 22:12:31 +00:00
|
|
|
bvc_ct.start(f_bssgp_bvc_main(bvc_cfg, g_cfg.sgsn_role, g_cfg.nsei, bvc_id));
|
2020-10-04 20:52:56 +00:00
|
|
|
/* populate the BVC state table */
|
|
|
|
BvcTable[i] := {
|
|
|
|
bvci := bvc_cfg.bvci,
|
|
|
|
cell_id := bvc_cfg.cell_id,
|
|
|
|
comp_ref := bvc_ct
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_cfg.sgsn_role) {
|
|
|
|
/* The SGSN side waits for an inbound BVC-RESET on the signaling BVC */
|
|
|
|
f_sign_change_state(BVC_S_WAIT_RESET);
|
|
|
|
} else {
|
|
|
|
/* The BSS/PCU side waits for an inbound NsStatusIndication to Tx BVC-RESET */
|
|
|
|
f_sign_change_state(BVC_S_WAIT_NS_ALIVE_UNBLOCKED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* main loop */
|
|
|
|
f_bssgp_ScanEvents();
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* master component, exists once per BSSGP instance (NSE) */
|
2018-02-15 16:45:29 +00:00
|
|
|
type component BSSGP_CT {
|
2018-05-03 17:14:28 +00:00
|
|
|
/* UDP ports towards the bottom (IUT) */
|
2018-02-15 16:45:29 +00:00
|
|
|
port NS_PT BSCP;
|
2020-10-04 20:52:56 +00:00
|
|
|
|
|
|
|
/* control by the user */
|
|
|
|
port BSSGP_CT_PROC_PT PROC;
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-11-24 17:15:02 +00:00
|
|
|
/* global port for procedures without any relation to a BVC
|
|
|
|
* (currently only) SUSPEND/RESUME */
|
|
|
|
port BSSGP_SP_PT GLOBAL;
|
|
|
|
|
2020-12-02 20:30:44 +00:00
|
|
|
/* RAN INFORMATION MGMT */
|
|
|
|
port BSSGP_SP_PT RIM;
|
|
|
|
|
2020-11-27 17:58:46 +00:00
|
|
|
/* port to a management instance */
|
|
|
|
port BSSGP_BVC_MGMT_SP_PT MGMT;
|
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
var BssgpConfig g_cfg;
|
2018-02-15 16:45:29 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Signaling BVC (BVCI=0) */
|
|
|
|
var BvcState g_sign_bvc_state := BVC_S_WAIT_RESET;
|
2018-02-15 16:45:29 +00:00
|
|
|
timer g_T2 := 60.0;
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* port to per-BVC components */
|
|
|
|
port BSSGP_BVC_SP_PT BVC;
|
|
|
|
/* per-BVC state table */
|
2021-02-03 16:47:18 +00:00
|
|
|
var BvcEntity BvcTable[64];
|
2020-10-04 20:52:56 +00:00
|
|
|
};
|
2018-07-31 12:19:36 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* one element in the per-BVC state table */
|
|
|
|
type record BvcEntity {
|
|
|
|
/* PTP BVCI of this BVC/Cell */
|
|
|
|
BssgpBvci bvci,
|
|
|
|
/* Cell Identity of this cell */
|
2018-02-15 19:39:13 +00:00
|
|
|
BssgpCellId cell_id,
|
2020-10-04 20:52:56 +00:00
|
|
|
/* reference to the per-BVC/cell component */
|
|
|
|
BSSGP_BVC_CT comp_ref
|
2018-02-15 19:39:13 +00:00
|
|
|
};
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* find the per-BVC component for a given BVCI */
|
|
|
|
private function f_comp_for_bvci(BssgpBvci bvci) runs on BSSGP_CT return BSSGP_BVC_CT {
|
|
|
|
var integer i;
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
for (i := 0; i < lengthof(BvcTable); i := i+1) {
|
|
|
|
if (BvcTable[i].bvci == bvci) {
|
|
|
|
return BvcTable[i].comp_ref;
|
|
|
|
}
|
2018-07-31 13:37:14 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
return null;
|
2018-07-31 13:37:14 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* We are in BVC_S_WAIT_RSET state (only happens in SGSN role) */
|
|
|
|
altstep as_sig_wait_reset() runs on BSSGP_CT {
|
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
|
|
|
|
/* Respond to RESET for signalling BVCI 0 */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
|
|
|
|
log("Rx BVC-RESET for Signaling BVCI=0");
|
|
|
|
f_sign_change_state(BVC_S_UNBLOCKED);
|
2020-11-27 17:58:46 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{0});
|
|
|
|
}
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
|
|
|
|
2020-12-09 10:57:41 +00:00
|
|
|
private template PDU_BSSGP tr_GLOBAL_SIG := (
|
2020-11-24 17:15:02 +00:00
|
|
|
{pDU_BSSGP_SUSPEND:=?}, {pDU_BSSGP_SUSPEND_ACK:=?}, {pDU_BSSGP_SUSPEND_NACK:=?},
|
2020-11-27 21:37:23 +00:00
|
|
|
{pDU_BSSGP_RESUME:=?}, {pDU_BSSGP_RESUME_ACK:=?}, {pDU_BSSGP_RESUME_NACK:=?},
|
2021-01-17 12:46:57 +00:00
|
|
|
{pDU_BSSGP_SGSN_INVOKE_TRACE:=?}, {pDU_BSSGP_OVERLOAD:=?}, {pDU_BSSGP_STATUS:=?}
|
2020-11-24 17:15:02 +00:00
|
|
|
);
|
|
|
|
|
2020-12-02 20:30:44 +00:00
|
|
|
/* BSSGP messages that should arrive on the RIM port */
|
|
|
|
private template PDU_BSSGP tr_RIM := (
|
|
|
|
{pDU_BSSGP_RAN_INFORMATION:=?}, {pDU_BSSGP_RAN_INFORMATION_REQUEST:=?},
|
|
|
|
{pDU_BSSGP_RAN_INFORMATION_ACK:=?}, {pDU_BSSGP_RAN_INFORMATION_ERROR:=?},
|
|
|
|
{pDU_BSSGP_RAN_INFORMATION_APPLICATION_ERROR:=?}
|
|
|
|
);
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* We are in BVC_S_UNBLOCKED state */
|
|
|
|
altstep as_sig_unblocked() runs on BSSGP_CT {
|
|
|
|
var BSSGP_BVC_CT bvc_comp_ref;
|
|
|
|
var BSSGP_Client_CT vc_conn;
|
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
var NsUnitdataRequest udr;
|
2020-11-24 17:15:02 +00:00
|
|
|
var PDU_BSSGP bssgp;
|
2020-10-04 20:52:56 +00:00
|
|
|
|
|
|
|
/* Messages PTP BVCI in BVCI field of NS: dispatch by that */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(?, (2..65535))) -> value udi {
|
|
|
|
bvc_comp_ref := f_comp_for_bvci(valueof(udi.bvci));
|
|
|
|
if (isbound(bvc_comp_ref) and bvc_comp_ref != null) {
|
|
|
|
/* dispatch to BVC component */
|
|
|
|
BVC.send(udi) to bvc_comp_ref;
|
|
|
|
} else {
|
|
|
|
setverdict(fail, "Rx BSSGP for unknown PTP BVCI ", udi.bvci, ": ", udi.bssgp);
|
2020-11-11 17:55:09 +00:00
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), udi.bvci, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Messages with BVCI = 0 (Signaling) in BVCI field of NS */
|
2020-12-09 10:57:41 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_GLOBAL_SIG, 0)) -> value udi {
|
2021-09-24 11:17:20 +00:00
|
|
|
if (GLOBAL.checkstate("Connected")) {
|
|
|
|
GLOBAL.send(udi.bssgp);
|
|
|
|
}
|
2020-11-24 17:15:02 +00:00
|
|
|
}
|
2020-12-02 20:30:44 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_RIM, 0)) -> value udi {
|
|
|
|
if (RIM.checkstate("Connected")) {
|
|
|
|
RIM.send(udi.bssgp);
|
|
|
|
}
|
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2021-11-26 10:41:50 +00:00
|
|
|
/* Broadcast FLUSH_LL_ACK no matter the BVCI */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BSSGP_FLUSH_LL_ACK(?, ?, ?), 0)) -> value udi {
|
|
|
|
log("Rx FLUSH_LL_ACK: broadcasting");
|
|
|
|
for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(udi) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Route based on PTP BVCI in payload/IE of signaling PDU */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(?, 0)) -> value udi {
|
|
|
|
var template (omit) BssgpBvci ptp_bvci := f_BSSGP_BVCI_get(udi.bssgp);
|
|
|
|
if (istemplatekind(ptp_bvci, "omit")) {
|
|
|
|
log("Rx on SIG BVCI without PTP BVCI: broadcasting");
|
|
|
|
for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(udi) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bvc_comp_ref := f_comp_for_bvci(valueof(ptp_bvci));
|
|
|
|
if (isbound(bvc_comp_ref) and bvc_comp_ref != null) {
|
|
|
|
/* dispatch to BVC component */
|
|
|
|
BVC.send(udi) to bvc_comp_ref;
|
|
|
|
} else {
|
|
|
|
setverdict(fail, "Rx SIG BSSGP for unknown PTP BVCI ", ptp_bvci, ": ", udi.bssgp);
|
2020-11-11 17:55:09 +00:00
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
|
2021-02-05 11:08:04 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle PS-PAGING on SIGN BVCI with no conditional BVCI IE */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(PDU_BSSGP:{pDU_BSSGP_PAGING_PS:=?}, 0)) -> value udi {
|
|
|
|
/* FIXME: use LA, RA or BSS Area to dispatch instead of broadcast */
|
|
|
|
for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(udi) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Handle CS-PAGING on SIGN BVCI with no conditional BVCI IE */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(PDU_BSSGP:{pDU_BSSGP_PAGING_CS:=?}, 0)) -> value udi {
|
|
|
|
/* FIXME: use LA, RA or BSS Area to dispatch instead of broadcast */
|
|
|
|
for (var integer i := 0; i < lengthof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(udi) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* per-BVC component sends us something; forward to NS without any validation */
|
|
|
|
[] BVC.receive(NsUnitdataRequest:?) -> value udr {
|
|
|
|
/* patch in the NSEI, as the per-BVC components have no idea about it */
|
|
|
|
udr.nsei := g_cfg.nsei;
|
|
|
|
BSCP.send(udr);
|
|
|
|
}
|
2020-11-24 17:15:02 +00:00
|
|
|
|
2020-12-09 10:57:41 +00:00
|
|
|
[] GLOBAL.receive(tr_GLOBAL_SIG) -> value bssgp {
|
2020-11-24 17:15:02 +00:00
|
|
|
BSCP.send(f_BnsUdReq(bssgp, 0, 0));
|
|
|
|
}
|
2020-12-02 20:30:44 +00:00
|
|
|
|
|
|
|
[] RIM.receive(tr_RIM) -> value bssgp {
|
|
|
|
BSCP.send(f_BnsUdReq(bssgp, 0, 0));
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We are in BVC_S_WAIT_NS_ALIVE_UNBLOCKED (only happens in BSS role) */
|
|
|
|
altstep as_sig_wait_ns_alive_unblocked() runs on BSSGP_CT {
|
|
|
|
var NsStatusIndication nsi;
|
2020-11-10 20:03:29 +00:00
|
|
|
[] BSCP.receive(NsStatusIndication:{g_cfg.nsei,?, complement (NSVC_S_ALIVE_UNBLOCKED), NSVC_S_ALIVE_UNBLOCKED, true}) -> value nsi {
|
2020-10-04 20:52:56 +00:00
|
|
|
/* if we just became NS-unblocked, send a BCC-RESET */
|
|
|
|
if (g_cfg.sgsn_role == false) {
|
2020-11-11 17:55:09 +00:00
|
|
|
BSCP.send(f_BnsUdReq(ts_BVC_RESET(BSSGP_CAUSE_OM_INTERVENTION, 0, omit), 0, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
g_T2.start;
|
|
|
|
/* The BVC_RESET_ACK is handled in the as_sig_allstate() below */
|
|
|
|
}
|
|
|
|
/* Idea: We could send BVC-UNBLOCK here like some SGSN do */
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-27 18:04:46 +00:00
|
|
|
/* handling of events irrespective of BVC state (before state-specific handling) */
|
|
|
|
altstep as_sig_allstate_pre() runs on BSSGP_CT {
|
2020-10-04 20:52:56 +00:00
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
|
|
|
|
/* Respond to RESET for signalling BVCI 0 */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
|
|
|
|
log("Rx BVC-RESET for Signaling BVCI=0");
|
2020-11-27 17:58:46 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{0});
|
|
|
|
}
|
2020-11-11 17:55:09 +00:00
|
|
|
BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* any BLOCK or UNBLOCK for the SIGNALING BVCI are illegal */
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(0, ?), 0)) -> value udi {
|
2020-10-04 20:52:56 +00:00
|
|
|
setverdict(fail, "Rx BVC-BLOCK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK(0), 0)) -> value udi {
|
2020-10-04 20:52:56 +00:00
|
|
|
setverdict(fail, "Rx BVC-UNBLOCK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK_ACK(0), 0)) -> value udi {
|
2020-10-04 20:52:56 +00:00
|
|
|
setverdict(fail, "Rx BVC-BLOCK-ACK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK_ACK(0), 0)) -> value udi {
|
2020-10-04 20:52:56 +00:00
|
|
|
setverdict(fail, "Rx BVC-UNBLOCK-ACK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BVC-RESET-ACK for BVCI=0 while T2 is running: Answer to a BVC-RESET we sent earlier */
|
|
|
|
[g_T2.running] BSCP.receive(f_BnsUdInd(tr_BVC_RESET_ACK(0, omit), 0)) -> value udi {
|
|
|
|
log("BVCI(0) Rx BVC-RESET-ACK");
|
|
|
|
g_T2.stop;
|
|
|
|
f_sign_change_state(BVC_S_UNBLOCKED);
|
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[] g_T2.timeout {
|
|
|
|
setverdict(fail, "Timeout waiting for BVC-RESET-ACK on BVCI=0");
|
2020-11-11 17:55:09 +00:00
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(udi.bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
g_T2.start;
|
|
|
|
}
|
2020-11-27 18:04:46 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2020-11-27 18:04:46 +00:00
|
|
|
/* handling of events irrespective of BVC state (after state-specific handling) */
|
|
|
|
altstep as_sig_allstate_post() runs on BSSGP_CT {
|
|
|
|
var BSSGP_Client_CT vc_conn;
|
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
var NsStatusIndication nsi;
|
|
|
|
var ASP_Event evt;
|
|
|
|
var BSSGP_BVC_CT bvc_comp_ref;
|
|
|
|
var BssgpBvci bvci;
|
|
|
|
var BssgpResetRequest brr;
|
|
|
|
|
|
|
|
/* Respond to RESET for signalling BVCI 0 */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, 0, omit), 0)) -> value udi {
|
|
|
|
log("Rx BVC-RESET for Signaling BVCI=0");
|
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{0});
|
|
|
|
}
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BVC_RESET_ACK(0, omit), 0, 0));
|
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(BssgpResetIndication:{0}) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* any BLOCK or UNBLOCK for the SIGNALING BVCI are illegal */
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(0, ?), 0)) -> value udi {
|
2020-11-27 18:04:46 +00:00
|
|
|
setverdict(fail, "Rx BVC-BLOCK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK(0), 0)) -> value udi {
|
2020-11-27 18:04:46 +00:00
|
|
|
setverdict(fail, "Rx BVC-UNBLOCK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK_ACK(0), 0)) -> value udi {
|
2020-11-27 18:04:46 +00:00
|
|
|
setverdict(fail, "Rx BVC-BLOCK-ACK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_UNBLOCK_ACK(0), 0)) -> value udi {
|
2020-11-27 18:04:46 +00:00
|
|
|
setverdict(fail, "Rx BVC-UNBLOCK-ACK illegal for BVCI=0: ", udi);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Respond to BLOCK for wrong BVCI */
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_BLOCK(?, ?), 0)) -> value udi {
|
2020-11-27 18:04:46 +00:00
|
|
|
setverdict(fail, "Rx BVC-BLOCK for unknown BVCI");
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Respond to RESET with wrong BVCI */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(tr_BVC_RESET(?, ?, ?), 0)) -> value udi {
|
|
|
|
var BssgpBvci ptp_bvci := oct2int(udi.bssgp.pDU_BSSGP_BVC_RESET.bVCI.unstructured_value);
|
|
|
|
setverdict(fail, "Rx BVC-RESET for unknown BVCI ", ptp_bvci);
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(ptp_bvci, BSSGP_CAUSE_BVCI_UNKNOWN, udi.bssgp), 0, 0));
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Forwarding of ASP_Event to per-BVC components */
|
|
|
|
[] BSCP.receive(ASP_Event:?) -> value evt {
|
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(evt) to BvcTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Keep NS Status Indicaitons to us; no need to inform per-BVC components [for now?] */
|
2020-11-10 20:03:29 +00:00
|
|
|
[] BSCP.receive(tr_NsStsInd(g_cfg.nsei)) -> value nsi { }
|
2020-11-10 18:15:30 +00:00
|
|
|
/* We should never see any different NSEI: There's one BSSGP_CT per NSE */
|
2020-11-10 20:03:29 +00:00
|
|
|
[] BSCP.receive(tr_NsStsInd(?)) -> value nsi {
|
2020-11-10 18:15:30 +00:00
|
|
|
setverdict(fail, "Rx NsStatusInd for wrong NSEI ", nsi);
|
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
|
|
|
/* Procedure port request to resolve the per-BVC component for a given ptp BVCI */
|
|
|
|
[] PROC.getcall(BSSGP_get_bvci_ct:{?}) -> param(bvci) sender vc_conn {
|
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (BvcTable[i].bvci == bvci) {
|
|
|
|
PROC.reply(BSSGP_get_bvci_ct:{bvci} value BvcTable[i].comp_ref) to vc_conn;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-27 18:04:46 +00:00
|
|
|
|
|
|
|
/* default case of handling unknown PDUs */
|
|
|
|
[] BSCP.receive(f_BnsUdInd(?, ?)) -> value udi {
|
|
|
|
setverdict(fail, "Rx Unexpected BSSGP PDU ", udi.bssgp," in state ", g_sign_bvc_state);
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BSSGP_STATUS(0, BSSGP_CAUSE_PDU_NOT_COMPATIBLE_WITH_PROTOCOL_STATE, udi.bssgp), 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
[] MGMT.receive(BssgpResetRequest:?) -> value brr {
|
|
|
|
BSCP.send(f_BnsUdReq(ts_BVC_RESET(brr.cause, 0, omit), 0, 0));
|
|
|
|
g_T2.start;
|
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* send the highest decoded layer of the message through given port */
|
|
|
|
private function f_send_bssgp_dec(BssgpDecoded dec, BSSGP_Client_CT vc_conn, BSSGP_SP_PT pt) {
|
2020-09-12 18:51:05 +00:00
|
|
|
#ifdef BSSGP_EM_L3
|
2020-10-04 20:52:56 +00:00
|
|
|
if (ispresent(dec.l3_mt)) {
|
|
|
|
pt.send(dec.l3_mt) to vc_conn;
|
|
|
|
} else if (ispresent(dec.l3_mo)) {
|
|
|
|
pt.send(dec.l3_mo) to vc_conn;
|
|
|
|
} else
|
2020-09-12 18:51:05 +00:00
|
|
|
#endif
|
2020-10-04 20:52:56 +00:00
|
|
|
if (ispresent(dec.sndcp)) {
|
|
|
|
pt.send(dec.sndcp) to vc_conn;
|
|
|
|
} else if (ispresent(dec.llc)) {
|
|
|
|
pt.send(dec.llc) to vc_conn;
|
|
|
|
} else {
|
|
|
|
pt.send(dec.bssgp) to vc_conn;
|
|
|
|
}
|
|
|
|
}
|
BSSGP_Emulation: add BssgpDecodeDepth
Make the decoding level (BSSGP, LLC, SNDCP, L3) configurable, so the
existing PCU tests, that expect messages only decoded to the BSSGP
level, can pass again. Move the SNDCP decoding in f_dec_bssgp above the
L3 decoding, so f_dec_bssgp goes through the layers in the reverse order
of f_send_bssgp_dec.
I have verified, that all testsuites using the BSSGP Emulation (SGSN,
PCU, PCU-SNS) are still working with this patch.
Related: OS#4180
Fixes: 955aa94504510139a12d223071cf49ef90788a3d ("BSSGP_Emulation: Abandon "BssgpDecoded" intermediate structure")
Change-Id: I8f76385528c1de98c557cee451c0e0dfd182b605
2019-09-02 06:36:36 +00:00
|
|
|
|
2018-02-15 16:45:29 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
function f_llc_get_n_u_tx(inout LLC_Entity llc) return uint9_t {
|
|
|
|
var uint9_t ret := llc.n_u_tx_next;
|
|
|
|
llc.n_u_tx_next := llc.n_u_tx_next + 1;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
function f_llc_sapi_by_l3_mo(PDU_L3_MS_SGSN l3_mo) return BIT4 {
|
|
|
|
if (ischosen(l3_mo.msgs.gprs_mm)) {
|
|
|
|
return c_LLC_SAPI_LLGMM;
|
|
|
|
} else if (ischosen(l3_mo.msgs.gprs_sm)) {
|
|
|
|
return c_LLC_SAPI_LLGMM;
|
|
|
|
} else if (ischosen(l3_mo.msgs.sms)) {
|
|
|
|
return c_LLC_SAPI_LLSMS;
|
|
|
|
}
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No LLC SAPI for ", l3_mo));
|
|
|
|
return '0000'B;
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private function f_llc_sapi_by_l3_mt(PDU_L3_SGSN_MS l3_mt) return BIT4 {
|
|
|
|
if (ischosen(l3_mt.msgs.gprs_mm)) {
|
|
|
|
return c_LLC_SAPI_LLGMM;
|
|
|
|
} else if (ischosen(l3_mt.msgs.gprs_sm)) {
|
|
|
|
return c_LLC_SAPI_LLGMM;
|
|
|
|
} else if (ischosen(l3_mt.msgs.sms)) {
|
|
|
|
return c_LLC_SAPI_LLSMS;
|
|
|
|
}
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("No LLC SAPI for ", l3_mt));
|
|
|
|
return '0000'B;
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* main loop of BSSGP_CT */
|
|
|
|
private function f_bssgp_ScanEvents() runs on BSSGP_CT {
|
|
|
|
while (true) {
|
|
|
|
alt {
|
|
|
|
[g_sign_bvc_state == BVC_S_WAIT_RESET] as_sig_wait_reset();
|
2020-11-27 18:04:46 +00:00
|
|
|
[] as_sig_allstate_pre();
|
2020-10-04 20:52:56 +00:00
|
|
|
[g_sign_bvc_state == BVC_S_WAIT_NS_ALIVE_UNBLOCKED] as_sig_wait_ns_alive_unblocked();
|
|
|
|
[g_sign_bvc_state == BVC_S_UNBLOCKED] as_sig_unblocked();
|
2020-11-27 18:04:46 +00:00
|
|
|
[g_sign_bvc_state == BVC_S_WAIT_RESET] as_sig_wait_reset();
|
|
|
|
[] as_sig_allstate_post();
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
} /* while */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generate a send template. Cannot be a real template as we want to use g_cfg.nsei */
|
2020-11-11 17:55:09 +00:00
|
|
|
private function f_BnsUdReq(template PDU_BSSGP pdu, BssgpBvci bvci, integer lsp)
|
2018-02-15 19:39:13 +00:00
|
|
|
runs on BSSGP_CT return NsUnitdataRequest {
|
2018-02-15 16:45:29 +00:00
|
|
|
var NsUnitdataRequest udr := {
|
2017-07-23 15:26:17 +00:00
|
|
|
bvci := bvci,
|
2018-02-15 19:39:13 +00:00
|
|
|
nsei := g_cfg.nsei,
|
2020-11-11 17:55:09 +00:00
|
|
|
lsp := lsp,
|
2018-02-15 16:45:29 +00:00
|
|
|
/* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
|
|
|
|
* unbound integer value." when trying to send the reocrd rather than the octetstring */
|
|
|
|
//sdu := omit,
|
|
|
|
//bssgp := valueof(pdu)
|
|
|
|
sdu := enc_PDU_BSSGP(valueof(pdu)),
|
|
|
|
bssgp := omit
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
return udr;
|
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* generate a receive template. Cannot be a real template as we want to use g_cfg.nsei */
|
|
|
|
private function f_BnsUdInd(template PDU_BSSGP pdu, template BssgpBvci bvci)
|
|
|
|
runs on BSSGP_CT return template (present) NsUnitdataIndication {
|
|
|
|
var template (present) NsUnitdataIndication udi := {
|
2018-02-15 16:45:29 +00:00
|
|
|
bvci := bvci,
|
2018-02-15 19:39:13 +00:00
|
|
|
nsei := g_cfg.nsei,
|
2020-11-17 18:57:40 +00:00
|
|
|
nsvci := ?,
|
2018-02-15 16:45:29 +00:00
|
|
|
sdu := *,
|
|
|
|
bssgp := pdu
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
return udi;
|
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* change state of signaling BVCI; notify per-BVC components */
|
|
|
|
private function f_sign_change_state(BvcState new_state) runs on BSSGP_CT {
|
|
|
|
if (new_state == g_sign_bvc_state) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
log("BVCI(0) State Transition: ", g_sign_bvc_state, " -> ", new_state);
|
|
|
|
g_sign_bvc_state := new_state;
|
|
|
|
for (var integer i := 0; i < sizeof(BvcTable); i := i+1) {
|
|
|
|
if (isbound(BvcTable[i].comp_ref) and BvcTable[i].comp_ref != null) {
|
|
|
|
BVC.send(ts_BssgpStsInd(g_cfg.nsei, 0, g_sign_bvc_state)) to BvcTable[i].comp_ref;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* User wants to get per-BVC component reference from BSSGP_CT */
|
|
|
|
signature BSSGP_get_bvci_ct(BssgpBvci bvci) return BSSGP_BVC_CT;
|
2020-09-14 14:07:26 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
type port BSSGP_CT_PROC_PT procedure {
|
|
|
|
inout BSSGP_get_bvci_ct
|
|
|
|
} with { extension "internal" };
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* convenience wrapper function for user */
|
|
|
|
function f_bssgp_get_bvci_ct(BssgpBvci bvci, BSSGP_CT_PROC_PT PT) return BSSGP_BVC_CT {
|
|
|
|
var BSSGP_BVC_CT res;
|
|
|
|
PT.call(BSSGP_get_bvci_ct:{bvci}) {
|
|
|
|
[] PT.getreply(BSSGP_get_bvci_ct:{bvci})-> value res {
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* per-BVC (Cell) Component
|
|
|
|
***********************************************************************
|
|
|
|
* Any number of these components runs on top of the BSSGP_CT, each
|
|
|
|
* representing one PTP BVC within this NSE. Users (test cases) can
|
|
|
|
* register with TLLI and/or IMSI via the procedure port.
|
|
|
|
***********************************************************************/
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* per-BVC component. Exists once per cell within a BSSGP_CT */
|
|
|
|
type component BSSGP_BVC_CT {
|
|
|
|
/* port towards the underlying BSSGP_CT */
|
|
|
|
port BSSGP_BVC_PT BVC;
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-11-15 21:37:45 +00:00
|
|
|
/* port to a management instance */
|
|
|
|
port BSSGP_BVC_MGMT_SP_PT MGMT;
|
|
|
|
|
2020-12-09 10:58:23 +00:00
|
|
|
/* per-BVC global port for e.g. BVC Flow Control */
|
|
|
|
port BSSGP_SP_PT GLOBAL;
|
|
|
|
|
|
|
|
/* BSSGP-User SAP towards the user (per-TLLI, Client) */
|
2020-10-04 20:52:56 +00:00
|
|
|
port BSSGP_SP_PT BSSGP_SP;
|
|
|
|
port BSSGP_SP_PT BSSGP_SP_SIG;
|
|
|
|
port BSSGP_PROC_PT BSSGP_PROC;
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
var BssgpBvcConfig g_cfg;
|
|
|
|
var boolean g_sgsn_role;
|
2020-11-24 22:12:31 +00:00
|
|
|
var Nsei g_nsei;
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2020-11-11 17:55:09 +00:00
|
|
|
/* default Link Selector Parameter for this BVC (for traffic unrelated to a TLLI) */
|
|
|
|
var integer g_bvc_lsp;
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
var BvcState g_ptp_bvc_state := BVC_S_BLOCKED;
|
|
|
|
timer g_T1 := 15.0;
|
|
|
|
timer g_T2 := 60.0;
|
|
|
|
var boolean g_t1_waits_for_block_ack := false;
|
2020-11-15 21:37:45 +00:00
|
|
|
/* for re-transmissions */
|
|
|
|
var BssgpCause g_last_block_cause;
|
|
|
|
var BssgpCause g_last_reset_cause;
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2021-02-03 16:47:18 +00:00
|
|
|
var ClientEntity ClientTable[64];
|
2020-10-04 20:52:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* port between global BSSGP_CT and per-BVC BSSGP_BVC_CT */
|
|
|
|
type port BSSGP_BVC_SP_PT message {
|
|
|
|
in NsUnitdataRequest;
|
|
|
|
out ASP_Event,
|
|
|
|
BssgpStatusIndication,
|
|
|
|
BssgpResetIndication,
|
|
|
|
NsUnitdataIndication;
|
|
|
|
} with { extension "internal" };
|
|
|
|
type port BSSGP_BVC_PT message {
|
|
|
|
in ASP_Event,
|
|
|
|
BssgpStatusIndication,
|
|
|
|
BssgpResetIndication,
|
|
|
|
NsUnitdataIndication;
|
|
|
|
out NsUnitdataRequest;
|
|
|
|
} with { extension "internal" };
|
|
|
|
|
2020-11-15 21:37:45 +00:00
|
|
|
/* port between BSSGP_BVC_CT and a management instance */
|
|
|
|
type port BSSGP_BVC_MGMT_SP_PT message {
|
|
|
|
in BssgpResetRequest,
|
|
|
|
BssgpBlockRequest,
|
|
|
|
BssgpUnblockRequest;
|
|
|
|
out BssgpStatusIndication,
|
|
|
|
BssgpResetIndication;
|
|
|
|
} with { extension "internal" };
|
|
|
|
type port BSSGP_BVC_MGMT_PT message {
|
|
|
|
in BssgpStatusIndication,
|
|
|
|
BssgpResetIndication;
|
|
|
|
out BssgpResetRequest,
|
|
|
|
BssgpBlockRequest,
|
|
|
|
BssgpUnblockRequest;
|
|
|
|
} with { extension "internal" };
|
|
|
|
|
|
|
|
type record BssgpResetRequest {
|
|
|
|
BssgpCause cause
|
|
|
|
};
|
|
|
|
type record BssgpBlockRequest {
|
|
|
|
BssgpCause cause
|
|
|
|
};
|
|
|
|
type record BssgpUnblockRequest {
|
|
|
|
};
|
2020-10-04 20:52:56 +00:00
|
|
|
|
|
|
|
/* one element in the per-TLLI state table */
|
|
|
|
type record ClientEntity {
|
|
|
|
OCT4 tlli,
|
|
|
|
OCT4 tlli_old optional,
|
|
|
|
hexstring imsi,
|
|
|
|
BSSGP_Client_CT comp_ref,
|
|
|
|
/* LLC entities, one for each SAPI */
|
|
|
|
LLC_Entity llc[16]
|
|
|
|
};
|
|
|
|
type record LLC_Entity {
|
|
|
|
boolean sgsn_role,
|
|
|
|
/* N(U) on transmit side for next PDU */
|
|
|
|
uint9_t n_u_tx_next,
|
|
|
|
/* N(U) on receive side, last PDU */
|
|
|
|
uint9_t n_u_rx_last optional
|
|
|
|
};
|
|
|
|
type record length(16) of LLC_Entity LLC_Entities;
|
|
|
|
|
2021-01-17 12:46:57 +00:00
|
|
|
private template PDU_BSSGP tr_GLOBAL_PTP := (
|
|
|
|
{pDU_BSSGP_STATUS:=?}
|
|
|
|
);
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
function f_llc_create(boolean sgsn_role := false) return LLC_Entities {
|
|
|
|
var LLC_Entities llc;
|
|
|
|
for (var integer i := 0; i < 16; i := i+1) {
|
|
|
|
llc[i] := valueof(t_LLC_init(sgsn_role));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
return llc;
|
|
|
|
}
|
|
|
|
|
|
|
|
private template LLC_Entity t_LLC_init(boolean sgsn_role := false) := {
|
|
|
|
sgsn_role := sgsn_role,
|
|
|
|
n_u_tx_next := 0,
|
|
|
|
n_u_rx_last := -
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* configuration of BSSGP_CT */
|
|
|
|
type record BssgpConfig {
|
|
|
|
Nsvci nsei,
|
|
|
|
boolean sgsn_role,
|
|
|
|
BssgpBvcConfigs bvc
|
|
|
|
};
|
|
|
|
/* Configuration of one BVC (Cell) BSSGP_BVC_CT */
|
|
|
|
type record BssgpBvcConfig {
|
|
|
|
BssgpBvci bvci,
|
|
|
|
BssgpCellId cell_id,
|
2020-11-12 18:48:31 +00:00
|
|
|
BssgpDecodeDepth depth,
|
|
|
|
BssgpCreateCallback create_cb
|
2020-10-04 20:52:56 +00:00
|
|
|
};
|
|
|
|
type record of BssgpBvcConfig BssgpBvcConfigs;
|
|
|
|
type enumerated BssgpDecodeDepth {
|
|
|
|
BSSGP_DECODE_DEPTH_BSSGP,
|
|
|
|
BSSGP_DECODE_DEPTH_LLC,
|
|
|
|
BSSGP_DECODE_DEPTH_SNDCP
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
,
|
|
|
|
BSSGP_DECODE_DEPTH_L3
|
|
|
|
#endif
|
|
|
|
};
|
2020-11-12 18:48:31 +00:00
|
|
|
/* call-back function type: Called for inbound BSSGP for unknown TLLIs; could create BSSGP_ClienT_CT */
|
|
|
|
type function BssgpCreateCallback(BssgpBvci bvci, BssgpCellId cell_id, OCT4 tlli, BssgpDecoded dec) runs on BSSGP_BVC_CT;
|
|
|
|
|
|
|
|
/* Default Create Callback function: Fail and terminate */
|
|
|
|
function DefaultCreateCallback(BssgpBvci bvci, BssgpCellId cell_id, OCT4 tlli, BssgpDecoded dec) runs on BSSGP_BVC_CT {
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Component for TLLI ", tlli));
|
2020-11-12 18:48:31 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
/*
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_init() runs on BSSGP_BVC_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ImsiTable); i := i+1) {
|
|
|
|
ImsiTable[i] := -;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i := 0; i < sizeof(TlliTable); i := i+1) {
|
|
|
|
TlliTable[i] := -;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_client_add(hexstring imsi, OCT4 tlli, BSSGP_Client_CT vc_conn)
|
|
|
|
runs on BSSGP_BVC_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (not isvalue(ClientTable[i].comp_ref)) {
|
|
|
|
log("Adding Client=", vc_conn, ", IMSI=", imsi, ", TLLI=", tlli, ", index=", i);
|
2018-02-15 19:39:13 +00:00
|
|
|
ClientTable[i] := {
|
|
|
|
tlli := tlli,
|
|
|
|
tlli_old := omit,
|
|
|
|
imsi := imsi,
|
|
|
|
comp_ref := vc_conn,
|
|
|
|
llc := -
|
|
|
|
};
|
|
|
|
for (var integer j := 0; j < sizeof(ClientTable[i].llc); j := j+1) {
|
2020-10-04 20:52:56 +00:00
|
|
|
ClientTable[i].llc[j] := valueof(t_LLC_init(g_sgsn_role));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2018-07-05 15:35:03 +00:00
|
|
|
testcase.stop("Client Table full");
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_client_del(hexstring imsi, BSSGP_Client_CT vc_conn) runs on BSSGP_BVC_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (isvalue(ClientTable[i].imsi) and ClientTable[i].imsi == imsi) {
|
2018-02-15 19:39:13 +00:00
|
|
|
if (ClientTable[i].comp_ref != vc_conn) {
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
|
|
|
|
log2str("Cannot unregister index=", i, " IMSI ",
|
|
|
|
imsi, " registred to ", ClientTable[i].comp_ref,
|
|
|
|
" from ", vc_conn));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
log("Removing Client IMSI=", imsi, ", index=", i);
|
2018-06-12 16:10:30 +00:00
|
|
|
ClientTable[i] := {
|
|
|
|
tlli := -,
|
|
|
|
tlli_old := omit,
|
|
|
|
imsi := ''H,
|
|
|
|
comp_ref := null,
|
|
|
|
llc := - };
|
2018-02-15 19:39:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 13:55:34 +00:00
|
|
|
log("Warning: Could not find client for IMSI ", imsi);
|
|
|
|
return;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2018-02-17 09:11:19 +00:00
|
|
|
/* TS 44.064 7.2.1.1 LLGMM-ASSIGN */
|
|
|
|
private function f_tbl_client_llgmm_assign(OCT4 tlli_old, OCT4 tlli_new, BSSGP_Client_CT vc_conn)
|
2020-10-04 20:52:56 +00:00
|
|
|
runs on BSSGP_BVC_CT {
|
2018-02-17 09:11:19 +00:00
|
|
|
var integer i := f_tbl_idx_by_comp(vc_conn);
|
|
|
|
|
|
|
|
if (tlli_old == 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
|
|
|
|
/* TLLI assignment */
|
|
|
|
ClientTable[i].tlli := tlli_new;
|
|
|
|
ClientTable[i].tlli_old := omit;
|
|
|
|
} else if (tlli_old != 'FFFFFFFF'O and tlli_new != 'FFFFFFFF'O) {
|
|
|
|
/* TLLI change: both active */
|
|
|
|
ClientTable[i].tlli := tlli_new;
|
|
|
|
ClientTable[i].tlli_old := tlli_old;
|
|
|
|
} else if (tlli_old != 'FFFFFFFF'O and tlli_new == 'FFFFFFFF'O) {
|
|
|
|
/* TLLI unassignment: old shall be unassigned; new stays */
|
|
|
|
ClientTable[i].tlli_old := omit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_comp_by_imsi(hexstring imsi) runs on BSSGP_BVC_CT return BSSGP_Client_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (isvalue(ClientTable[i].imsi) and isvalue(ClientTable[i].comp_ref)
|
2018-02-15 19:39:13 +00:00
|
|
|
and ClientTable[i].imsi == imsi) {
|
|
|
|
return ClientTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Component for IMSI ", imsi));
|
|
|
|
return ClientTable[0].comp_ref;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_comp_by_tlli(OCT4 tlli) runs on BSSGP_BVC_CT return BSSGP_Client_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (isvalue(ClientTable[i].comp_ref) and
|
|
|
|
(isvalue(ClientTable[i].tlli) and (ClientTable[i].tlli == tlli or
|
|
|
|
isvalue(ClientTable[i].tlli_old) and ClientTable[i].tlli_old == tlli) )) {
|
2018-02-15 19:39:13 +00:00
|
|
|
return ClientTable[i].comp_ref;
|
|
|
|
}
|
|
|
|
}
|
2020-11-12 18:48:31 +00:00
|
|
|
return null;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_idx_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_BVC_CT return integer {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (isvalue(ClientTable[i].comp_ref) and ClientTable[i].comp_ref == comp_ref) {
|
2018-02-15 19:39:13 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find Client for Component ", comp_ref));
|
|
|
|
return 1;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_tbl_tlli_by_comp(BSSGP_Client_CT comp_ref) runs on BSSGP_BVC_CT return OCT4 {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer i;
|
|
|
|
for (i := 0; i < sizeof(ClientTable); i := i+1) {
|
2018-02-18 13:06:12 +00:00
|
|
|
if (isvalue(ClientTable[i].tlli) and isvalue(ClientTable[i].comp_ref)
|
2018-02-15 19:39:13 +00:00
|
|
|
and ClientTable[i].comp_ref == comp_ref) {
|
|
|
|
return ClientTable[i].tlli;
|
|
|
|
}
|
|
|
|
}
|
2021-02-05 11:07:04 +00:00
|
|
|
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Couldn't find TLLI for Component ", comp_ref));
|
|
|
|
return '00000000'O;
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* PDU_BSSGP enhanced with LLC and possibly L3 decoded payloads */
|
|
|
|
type record BssgpDecoded {
|
|
|
|
PDU_BSSGP bssgp,
|
|
|
|
PDU_LLC llc optional,
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
PDU_L3_MS_SGSN l3_mo optional,
|
|
|
|
PDU_L3_SGSN_MS l3_mt optional,
|
|
|
|
#endif
|
|
|
|
PDU_SN sndcp optional
|
2020-09-14 14:07:26 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Decode a PDU_BSSGP into a BssgpDecoded (i.e. with LLC/L3 decoded, as applicable) */
|
|
|
|
private function f_dec_bssgp(PDU_BSSGP bssgp) runs on BSSGP_BVC_CT return BssgpDecoded {
|
|
|
|
var BssgpDecoded dec := {
|
|
|
|
bssgp := bssgp,
|
|
|
|
llc := omit,
|
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
l3_mo := omit,
|
|
|
|
l3_mt := omit,
|
|
|
|
#endif
|
|
|
|
sndcp := omit
|
|
|
|
};
|
2020-10-09 09:41:06 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Decode LLC, if it is a PDU that contains LLC */
|
|
|
|
if (g_cfg.depth >= BSSGP_DECODE_DEPTH_LLC) {
|
|
|
|
if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
|
|
|
|
dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_DL_UNITDATA.lLC_PDU.lLC_PDU);
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
|
|
|
|
dec.llc := dec_PDU_LLC(bssgp.pDU_BSSGP_UL_UNITDATA.lLC_PDU.lLC_PDU);
|
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Decode SNDCP, if it is a LLC PDU containing user plane data */
|
|
|
|
if (g_cfg.depth >= BSSGP_DECODE_DEPTH_SNDCP) {
|
|
|
|
if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_USER)) {
|
|
|
|
dec.sndcp := dec_PDU_SN(dec.llc.pDU_LLC_UI.information_field_UI);
|
|
|
|
}
|
2017-07-23 17:52:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
#ifdef BSSGP_EM_L3
|
|
|
|
/* Decode L3, if it is a LLC PDU containing L3 */
|
|
|
|
if (g_cfg.depth >= BSSGP_DECODE_DEPTH_L3) {
|
|
|
|
if (isvalue(dec.llc) and match(dec.llc, tr_LLC_UI_L3)) {
|
|
|
|
if (g_sgsn_role) {
|
|
|
|
dec.l3_mo := dec_PDU_L3_MS_SGSN(dec.llc.pDU_LLC_UI.information_field_UI);
|
|
|
|
} else {
|
|
|
|
dec.l3_mt := dec_PDU_L3_SGSN_MS(dec.llc.pDU_LLC_UI.information_field_UI);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
#endif
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
return dec;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function f_ptp_sendUnblock() runs on BSSGP_BVC_CT {
|
2021-02-05 12:05:06 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK(g_cfg.bvci), 0, g_bvc_lsp));
|
2020-10-04 20:52:56 +00:00
|
|
|
g_t1_waits_for_block_ack := false;
|
|
|
|
g_T1.start;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function f_ptp_sendBlock(BssgpCause cause) runs on BSSGP_BVC_CT {
|
2021-02-05 12:05:06 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_BLOCK(g_cfg.bvci, cause), 0, g_bvc_lsp));
|
2020-10-04 20:52:56 +00:00
|
|
|
g_t1_waits_for_block_ack := true;
|
|
|
|
g_T1.start;
|
2020-11-15 21:37:45 +00:00
|
|
|
g_last_block_cause := cause;
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
2018-02-17 09:11:19 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
private function f_ptp_sendStatus(BssgpCause cause, PDU_BSSGP pdu) runs on BSSGP_BVC_CT {
|
|
|
|
/* FIXME: Make sure correct Signaling or PTP BVCI is used! */
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_STATUS(g_cfg.bvci, cause, pdu), g_cfg.bvci, g_bvc_lsp));
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-11-15 21:37:45 +00:00
|
|
|
private function f_ptp_sendReset(BssgpCause cause := BSSGP_CAUSE_OM_INTERVENTION) runs on BSSGP_BVC_CT {
|
2020-10-04 20:52:56 +00:00
|
|
|
var PDU_BSSGP pdu;
|
|
|
|
|
|
|
|
/* The Cell Identifier IE is mandatory in the BVC-RESET PDU sent from BSS to
|
|
|
|
* SGSN in order to reset a BVC corresponding to a PTP functional entity. The
|
|
|
|
* Cell Identifier IE shall not be used in any other BVC-RESET PDU. */
|
|
|
|
if (g_sgsn_role) {
|
2020-11-15 21:37:45 +00:00
|
|
|
pdu := valueof(ts_BVC_RESET(cause, g_cfg.bvci, omit));
|
2020-10-04 20:52:56 +00:00
|
|
|
} else {
|
2020-11-15 21:37:45 +00:00
|
|
|
pdu := valueof(ts_BVC_RESET(cause, g_cfg.bvci, g_cfg.cell_id));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
|
|
|
/* BVC-RESET is always sent via the SIGNALLING BVCI, see Table 5.4.1 */
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(pdu, 0, g_bvc_lsp));
|
2020-10-04 20:52:56 +00:00
|
|
|
g_T2.start;
|
|
|
|
//f_change_state(BVC_S_WAIT_RESET);
|
2020-11-15 21:37:45 +00:00
|
|
|
g_last_reset_cause := cause;
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* PTP-BVC is in BVC_S_BLOCKED state */
|
|
|
|
private altstep as_ptp_blocked() runs on BSSGP_BVC_CT {
|
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
|
2021-02-05 12:05:06 +00:00
|
|
|
[g_T1.running and not g_t1_waits_for_block_ack] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK_ACK(g_cfg.bvci), 0)) {
|
2018-02-15 19:39:13 +00:00
|
|
|
g_T1.stop;
|
2020-10-04 20:52:56 +00:00
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
|
2020-11-24 22:13:01 +00:00
|
|
|
/* Inbound BVC-UNBLOCK from peer */
|
2021-02-05 12:05:06 +00:00
|
|
|
[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK(g_cfg.bvci), 0)) {
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
|
2020-11-24 22:13:01 +00:00
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* RESET-ACK before T2 timeout: reset successful. In SGSN role, CellID must be present */
|
|
|
|
[g_T2.running and g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
|
|
|
|
g_T2.stop;
|
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
|
|
|
}
|
|
|
|
/* RESET-ACK before T2 timeout: reset successful. In BSS role, CellID must be absent */
|
|
|
|
[g_T2.running and not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET_ACK(g_cfg.bvci, omit), 0)) -> value udi {
|
|
|
|
g_T2.stop;
|
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-25 16:11:08 +00:00
|
|
|
[] as_ptp_handle_inbound_reset();
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
[] g_T2.timeout {
|
|
|
|
/* BVC-RESET-ACK PDU was not received within T2: retransmit */
|
2020-11-15 21:37:45 +00:00
|
|
|
f_ptp_sendReset(g_last_reset_cause);
|
2019-05-02 23:29:29 +00:00
|
|
|
}
|
2020-11-15 21:37:45 +00:00
|
|
|
|
|
|
|
[] MGMT.receive(BssgpUnblockRequest:?) {
|
|
|
|
f_ptp_sendUnblock();
|
|
|
|
}
|
2019-05-02 23:29:29 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* PTP-BVC is in UNBLOCKED state */
|
|
|
|
private altstep as_ptp_unblocked() runs on BSSGP_BVC_CT {
|
2018-02-15 16:45:29 +00:00
|
|
|
var NsUnitdataIndication udi;
|
2020-10-04 20:52:56 +00:00
|
|
|
var NsStatusIndication nsi;
|
2020-11-15 21:37:45 +00:00
|
|
|
var BssgpBlockRequest bbr;
|
2020-10-04 20:52:56 +00:00
|
|
|
var BSSGP_Client_CT vc_conn;
|
|
|
|
var ASP_Event evt;
|
2018-02-15 16:45:29 +00:00
|
|
|
var PDU_BSSGP bs_pdu;
|
2018-02-18 18:42:17 +00:00
|
|
|
var PDU_LLC llc;
|
2020-09-12 18:51:05 +00:00
|
|
|
#ifdef BSSGP_EM_L3
|
2018-02-15 19:39:13 +00:00
|
|
|
var PDU_L3_MS_SGSN l3_mo;
|
|
|
|
var PDU_L3_SGSN_MS l3_mt;
|
2020-09-12 18:51:05 +00:00
|
|
|
#endif
|
2018-02-15 19:39:13 +00:00
|
|
|
|
|
|
|
/* bogus unblock, just respond with ACK */
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_UNBLOCK(g_cfg.bvci), 0)) -> value udi {
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_UNBLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
/* Respond to BLOCK with BLOCK-ACK + change state */
|
2021-02-05 12:05:06 +00:00
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_BLOCK(g_cfg.bvci, ?), 0)) -> value udi {
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_BLOCK_ACK(g_cfg.bvci), 0, g_bvc_lsp));
|
2018-02-15 19:39:13 +00:00
|
|
|
g_T1.stop;
|
2020-10-04 20:52:56 +00:00
|
|
|
f_ptp_change_state(BVC_S_BLOCKED);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
/* BLOCK-ACK before T1 timeout: mark as blocked */
|
2021-02-05 12:05:06 +00:00
|
|
|
[g_T1.running and g_t1_waits_for_block_ack] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_BLOCK_ACK(g_cfg.bvci), 0)) -> value udi {
|
2018-02-15 19:39:13 +00:00
|
|
|
g_T1.stop;
|
2020-10-04 20:52:56 +00:00
|
|
|
f_ptp_change_state(BVC_S_BLOCKED);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Re-transmit BLOCK / UNBLOCK on T1 timeout */
|
|
|
|
[not g_t1_waits_for_block_ack] g_T1.timeout {
|
|
|
|
f_ptp_sendUnblock();
|
|
|
|
}
|
|
|
|
[g_t1_waits_for_block_ack] g_T1.timeout {
|
2020-11-15 21:37:45 +00:00
|
|
|
f_ptp_sendBlock(g_last_block_cause);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2017-07-23 17:52:33 +00:00
|
|
|
|
2020-11-25 16:11:08 +00:00
|
|
|
[] as_ptp_handle_inbound_reset();
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_FC_BVC, g_cfg.bvci)) -> value udi {
|
2020-12-09 10:58:23 +00:00
|
|
|
if (GLOBAL.checkstate("Connected")) {
|
|
|
|
GLOBAL.send(udi.bssgp);
|
|
|
|
} else {
|
|
|
|
/* simply acknowledge all per-BVC Flow Control Messages */
|
|
|
|
var OCT1 tag := udi.bssgp.pDU_BSSGP_FLOW_CONTROL_BVC.tag.unstructured_Value;
|
2021-02-05 12:05:06 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_FC_BVC_ACK(tag), g_cfg.bvci, g_bvc_lsp));
|
2020-12-09 10:58:23 +00:00
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-12-09 10:58:23 +00:00
|
|
|
|
2021-02-05 12:05:06 +00:00
|
|
|
[not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_FC_BVC_ACK(?), g_cfg.bvci)) -> value udi {
|
2020-12-09 10:58:23 +00:00
|
|
|
if (GLOBAL.checkstate("Connected")) {
|
|
|
|
GLOBAL.send(udi.bssgp);
|
|
|
|
} else {
|
|
|
|
/* ignore any incoming flow control ACK */
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-12-09 10:58:23 +00:00
|
|
|
|
2021-01-17 12:46:57 +00:00
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(tr_GLOBAL_PTP, g_cfg.bvci)) -> value udi {
|
|
|
|
if (GLOBAL.checkstate("Connected")) {
|
|
|
|
GLOBAL.send(udi.bssgp);
|
|
|
|
} else {
|
|
|
|
setverdict(fail, "Received BSSGP STATUS ", udi.bssgp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Any other PTP BSSGP message: If it has TLLI, route to component; otherwise broadcast */
|
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(?, g_cfg.bvci)) -> value udi {
|
2018-02-15 19:39:13 +00:00
|
|
|
var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
|
|
|
|
var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
|
|
|
|
if (isvalue(tlli)) {
|
|
|
|
vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
|
2020-11-12 18:48:31 +00:00
|
|
|
if (vc_conn == null) {
|
|
|
|
g_cfg.create_cb.apply(g_cfg.bvci, g_cfg.cell_id, valueof(tlli), dec);
|
|
|
|
} else {
|
|
|
|
f_send_bssgp_dec(dec, vc_conn, BSSGP_SP);
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
} else {
|
|
|
|
log("No TLLI: Broadcasting ", dec);
|
|
|
|
/* broadcast this message to all components */
|
|
|
|
// TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
|
|
|
|
for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
|
2020-10-04 20:52:56 +00:00
|
|
|
if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
|
|
|
|
f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP);
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2021-11-26 10:41:50 +00:00
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(tr_BSSGP_FLUSH_LL_ACK(?, ?, ?), 0)) -> value udi {
|
|
|
|
var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
|
|
|
|
|
|
|
|
log("Broadcasting FLUSH_LL_ACK ", dec);
|
|
|
|
/* broadcast this message to all components */
|
|
|
|
// TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
|
|
|
|
for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
|
|
|
|
if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
|
|
|
|
f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Any other SIG BSSGP message: If it has TLLI, route to component; otherwise broadcast */
|
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(?, 0)) -> value udi {
|
2019-03-21 20:30:47 +00:00
|
|
|
var BssgpDecoded dec := f_dec_bssgp(udi.bssgp);
|
|
|
|
var template OCT4 tlli := f_bssgp_get_tlli(udi.bssgp);
|
|
|
|
if (isvalue(tlli)) {
|
|
|
|
vc_conn := f_tbl_comp_by_tlli(valueof(tlli));
|
2020-11-12 18:48:31 +00:00
|
|
|
if (vc_conn == null) {
|
|
|
|
g_cfg.create_cb.apply(g_cfg.bvci, g_cfg.cell_id, valueof(tlli), dec);
|
|
|
|
} else {
|
|
|
|
f_send_bssgp_dec(dec, vc_conn, BSSGP_SP_SIG);
|
|
|
|
}
|
2019-03-21 20:30:47 +00:00
|
|
|
} else {
|
|
|
|
log("No TLLI: Broadcasting ", dec);
|
|
|
|
/* broadcast this message to all components */
|
|
|
|
// TITAN DOESN'T DO THIS, *SIGH*: "BSSGP_SP.send(dec) to all component;"
|
|
|
|
for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
|
2020-10-04 20:52:56 +00:00
|
|
|
if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
|
2019-08-30 09:48:00 +00:00
|
|
|
f_send_bssgp_dec(dec, ClientTable[i].comp_ref, BSSGP_SP_SIG);
|
2019-03-21 20:30:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* ConnHdlr sends BSSGP on BVCI=0 port: forward it to BSSGP_CT */
|
2018-05-03 17:14:28 +00:00
|
|
|
[] BSSGP_SP_SIG.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(bs_pdu, 0, g_bvc_lsp));
|
2018-05-03 17:14:28 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* ConnHdlr sends BSSGP on BVCI=PTP port: forward it to BSSGP_CT */
|
|
|
|
[] BSSGP_SP.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci, g_bvc_lsp));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-09-12 18:51:05 +00:00
|
|
|
#ifdef BSSGP_EM_L3
|
2019-05-02 22:50:48 +00:00
|
|
|
/* ConnHdlr sends L3: Encode and send as UL_UD / DL_UD */
|
2020-10-04 20:52:56 +00:00
|
|
|
[g_sgsn_role] BSSGP_SP.receive(PDU_L3_SGSN_MS:?) -> value l3_mt sender vc_conn {
|
2018-02-15 19:39:13 +00:00
|
|
|
var integer idx := f_tbl_idx_by_comp(vc_conn);
|
2020-11-11 17:55:09 +00:00
|
|
|
var OCT4 tlli := ClientTable[idx].tlli;
|
2018-02-15 19:39:13 +00:00
|
|
|
var octetstring l3_enc := enc_PDU_L3_SGSN_MS(l3_mt);
|
|
|
|
var BIT4 sapi := f_llc_sapi_by_l3_mt(l3_mt);
|
|
|
|
var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
|
|
|
|
var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
[not g_sgsn_role] BSSGP_SP.receive(PDU_L3_MS_SGSN:?) -> value l3_mo sender vc_conn {
|
2019-05-02 22:48:46 +00:00
|
|
|
var integer idx := f_tbl_idx_by_comp(vc_conn);
|
2020-11-11 17:55:09 +00:00
|
|
|
var OCT4 tlli := ClientTable[idx].tlli;
|
2019-05-02 22:48:46 +00:00
|
|
|
var octetstring l3_enc := enc_PDU_L3_MS_SGSN(l3_mo);
|
|
|
|
var BIT4 sapi := f_llc_sapi_by_l3_mo(l3_mo);
|
|
|
|
var integer n_u := f_llc_get_n_u_tx(ClientTable[idx].llc[bit2int(sapi)]);
|
|
|
|
var octetstring llc_enc := enc_PDU_LLC(valueof(ts_LLC_UI(l3_enc, sapi, '1'B, n_u)));
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
|
2019-05-02 22:48:46 +00:00
|
|
|
}
|
2020-09-12 18:51:05 +00:00
|
|
|
#endif
|
2018-02-18 18:42:17 +00:00
|
|
|
|
2019-05-02 22:49:25 +00:00
|
|
|
/* ConnHdlr sends raw LLC: Encode and send as UL_UD / DL_UD */
|
2020-10-04 20:52:56 +00:00
|
|
|
[not g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
|
2018-02-18 18:42:17 +00:00
|
|
|
var integer idx := f_tbl_idx_by_comp(vc_conn);
|
2020-11-11 17:55:09 +00:00
|
|
|
var OCT4 tlli := ClientTable[idx].tlli;
|
2018-02-18 18:42:17 +00:00
|
|
|
var octetstring llc_enc := enc_PDU_LLC(llc);
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_UL_UD(tlli, g_cfg.cell_id, llc_enc), g_cfg.bvci, oct2int(tlli)));
|
2018-02-18 18:42:17 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
[g_sgsn_role] BSSGP_SP.receive(PDU_LLC:?) -> value llc sender vc_conn {
|
2019-05-02 22:49:25 +00:00
|
|
|
var integer idx := f_tbl_idx_by_comp(vc_conn);
|
2020-11-11 17:55:09 +00:00
|
|
|
var OCT4 tlli := ClientTable[idx].tlli;
|
2019-05-02 22:49:25 +00:00
|
|
|
var octetstring llc_enc := enc_PDU_LLC(llc);
|
2020-11-11 17:55:09 +00:00
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BSSGP_DL_UD(tlli, llc_enc), g_cfg.bvci, oct2int(tlli)));
|
2019-05-02 22:49:25 +00:00
|
|
|
}
|
2020-11-15 21:37:45 +00:00
|
|
|
|
2020-12-09 10:58:23 +00:00
|
|
|
/* Testcase sends us BSSGP on global port */
|
|
|
|
[] GLOBAL.receive(PDU_BSSGP:?)-> value bs_pdu sender vc_conn {
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(bs_pdu, g_cfg.bvci, g_bvc_lsp));
|
|
|
|
}
|
|
|
|
|
2020-11-15 21:37:45 +00:00
|
|
|
[] MGMT.receive(BssgpBlockRequest:?) -> value bbr {
|
|
|
|
f_ptp_sendBlock(bbr.cause);
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-11-25 16:11:08 +00:00
|
|
|
private altstep as_ptp_handle_inbound_reset() runs on BSSGP_BVC_CT {
|
|
|
|
var NsUnitdataIndication udi;
|
|
|
|
/* we are a SGSN: BSS/PCU-originated RESET must have a cell ID */
|
|
|
|
[g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, g_cfg.cell_id), 0)) -> value udi {
|
|
|
|
log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
|
2020-11-26 19:56:09 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{g_cfg.bvci});
|
|
|
|
}
|
2020-11-25 16:11:08 +00:00
|
|
|
/* Respond to RESET with correct BVCI but without CellID */
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, omit), 0, g_bvc_lsp));
|
|
|
|
/* FIXME: reset all state? What about clients? */
|
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
|
|
|
}
|
|
|
|
/* we are a BSS/PCU: SGSN-originated RESET must not have a cell ID */
|
|
|
|
[not g_sgsn_role] BVC.receive(tr_ptp_BnsUdInd(tr_BVC_RESET(?, g_cfg.bvci, omit), 0)) -> value udi {
|
|
|
|
log("Rx BVC-RESET from BVCI=", g_cfg.bvci);
|
2020-11-26 19:56:09 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{g_cfg.bvci});
|
|
|
|
}
|
2020-11-25 16:11:08 +00:00
|
|
|
/* Respond to RESET with correct BVCI with CellID */
|
|
|
|
BVC.send(ts_ptp_BnsUdReq(ts_BVC_RESET_ACK(g_cfg.bvci, g_cfg.cell_id), 0, g_bvc_lsp));
|
|
|
|
/* FIXME: reset all state? What about clients? */
|
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Events permitted in all states */
|
|
|
|
private altstep as_ptp_allstate() runs on BSSGP_BVC_CT {
|
|
|
|
var NsUnitdataIndication udi;
|
2020-11-15 21:37:45 +00:00
|
|
|
var BssgpResetRequest brr;
|
2020-10-04 20:52:56 +00:00
|
|
|
var BSSGP_Client_CT vc_conn;
|
|
|
|
var OCT4 tlli, tlli_old;
|
|
|
|
var hexstring imsi;
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Signaling BVC was reset */
|
|
|
|
[] BVC.receive(BssgpResetIndication:{0}) {
|
2020-11-15 21:37:45 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
|
|
|
MGMT.send(BssgpResetIndication:{0});
|
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
if (not g_sgsn_role) {
|
|
|
|
f_ptp_change_state(BVC_S_BLOCKED);
|
|
|
|
/* when the BSS side signaling PTP is RESET, all PTP BVC must start the
|
|
|
|
* reset procedure */
|
|
|
|
f_ptp_sendReset();
|
|
|
|
} else {
|
|
|
|
f_ptp_change_state(BVC_S_UNBLOCKED);
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* Ignore those for now */
|
|
|
|
[] BVC.receive(ASP_Event:?) { }
|
|
|
|
[] BVC.receive(BssgpStatusIndication:?) { }
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* catch-all */
|
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(?, 0)) -> value udi {
|
|
|
|
setverdict(fail, "Received unexpected NS (SIG): ", udi);
|
|
|
|
}
|
|
|
|
[] BVC.receive(tr_ptp_BnsUdInd(?, ?)) -> value udi {
|
|
|
|
setverdict(fail, "Received unexpected NS (PTP): ", udi);
|
|
|
|
}
|
|
|
|
[] BVC.receive {
|
|
|
|
setverdict(fail, "Received unexpected message from BSSGP_CT");
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* registration/deregistration of Clients (per-TLLI components) */
|
|
|
|
[] BSSGP_PROC.getcall(BSSGP_register_client:{?,?}) -> param(imsi, tlli) sender vc_conn {
|
|
|
|
f_tbl_client_add(imsi, tlli, vc_conn);
|
|
|
|
BSSGP_PROC.reply(BSSGP_register_client:{imsi, tlli}) to vc_conn;
|
|
|
|
}
|
|
|
|
[] BSSGP_PROC.getcall(BSSGP_unregister_client:{?}) -> param(imsi) sender vc_conn {
|
|
|
|
f_tbl_client_del(imsi, vc_conn);
|
|
|
|
BSSGP_PROC.reply(BSSGP_unregister_client:{imsi}) to vc_conn;
|
|
|
|
}
|
|
|
|
[] BSSGP_PROC.getcall(BSSGP_llgmm_assign:{?,?}) -> param(tlli_old, tlli) sender vc_conn {
|
|
|
|
f_tbl_client_llgmm_assign(tlli_old, tlli, vc_conn);
|
|
|
|
BSSGP_PROC.reply(BSSGP_llgmm_assign:{tlli_old, tlli}) to vc_conn;
|
|
|
|
}
|
2020-11-15 21:37:45 +00:00
|
|
|
|
|
|
|
[] MGMT.receive(BssgpResetRequest:?) -> value brr {
|
2020-11-25 20:57:31 +00:00
|
|
|
f_ptp_change_state(BVC_S_BLOCKED);
|
2020-11-15 21:37:45 +00:00
|
|
|
f_ptp_sendReset(brr.cause);
|
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* main loop for per-BVC component */
|
|
|
|
private function f_bssgp_bvc_ScanEvents() runs on BSSGP_BVC_CT {
|
2018-02-15 19:39:13 +00:00
|
|
|
while (true) {
|
2018-02-15 16:45:29 +00:00
|
|
|
alt {
|
2020-10-04 20:52:56 +00:00
|
|
|
[g_ptp_bvc_state == BVC_S_BLOCKED] as_ptp_blocked();
|
|
|
|
[g_ptp_bvc_state == BVC_S_UNBLOCKED] as_ptp_unblocked();
|
|
|
|
[] as_ptp_allstate();
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2018-02-15 16:45:29 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* main function for per-BVC Component */
|
2020-11-24 22:12:31 +00:00
|
|
|
private function f_bssgp_bvc_main(BssgpBvcConfig cfg, boolean sgsn_role, Nsei nsei, charstring id) runs on BSSGP_BVC_CT {
|
2020-10-04 20:52:56 +00:00
|
|
|
g_cfg := cfg;
|
2020-11-24 22:12:31 +00:00
|
|
|
g_nsei := nsei;
|
2020-11-11 17:55:09 +00:00
|
|
|
g_bvc_lsp := cfg.bvci;
|
2020-10-04 20:52:56 +00:00
|
|
|
g_sgsn_role := sgsn_role;
|
|
|
|
f_bssgp_bvc_ScanEvents();
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2017-07-23 17:52:33 +00:00
|
|
|
|
2020-11-11 17:55:09 +00:00
|
|
|
template (value) NsUnitdataRequest ts_ptp_BnsUdReq(template (value) PDU_BSSGP pdu, template (value) BssgpBvci bvci,
|
|
|
|
template (value) integer lsp) := {
|
2020-10-04 20:52:56 +00:00
|
|
|
bvci := bvci,
|
|
|
|
nsei := 0, // overwritten in BSSGP_CT
|
2020-11-11 17:55:09 +00:00
|
|
|
lsp := lsp,
|
2020-10-04 20:52:56 +00:00
|
|
|
/* for some weird reason we get "Dynamic test case error: Text encoder: Encoding an
|
|
|
|
* unbound integer value." when trying to send the reocrd rather than the octetstring */
|
|
|
|
//sdu := omit,
|
|
|
|
//bssgp := valueof(pdu)
|
|
|
|
sdu := enc_PDU_BSSGP(valueof(pdu)),
|
|
|
|
bssgp := omit
|
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
template (present) NsUnitdataIndication tr_ptp_BnsUdInd(template (present) PDU_BSSGP pdu, template (present) BssgpBvci bvci) := {
|
|
|
|
bvci := bvci,
|
|
|
|
nsei := ?,
|
2020-11-17 18:57:40 +00:00
|
|
|
nsvci := ?,
|
2020-10-04 20:52:56 +00:00
|
|
|
sdu := *,
|
|
|
|
bssgp := pdu
|
|
|
|
}
|
2017-07-23 15:26:17 +00:00
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* change state of PTP BVC; broadcast state change to clients */
|
|
|
|
private function f_ptp_change_state(BvcState new_state) runs on BSSGP_BVC_CT {
|
|
|
|
if (new_state == g_ptp_bvc_state) {
|
|
|
|
return;
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
log("BVCI(", g_cfg.bvci, ") State Transition: ", g_ptp_bvc_state, " -> ", new_state);
|
|
|
|
g_ptp_bvc_state := new_state;
|
2020-11-15 21:37:45 +00:00
|
|
|
if (MGMT.checkstate("Connected")) {
|
2020-11-24 22:12:31 +00:00
|
|
|
MGMT.send(ts_BssgpStsInd(g_nsei, g_cfg.bvci, g_ptp_bvc_state));
|
2020-11-15 21:37:45 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
for (var integer i := 0; i < sizeof(ClientTable); i := i+1) {
|
|
|
|
if (isbound(ClientTable[i].comp_ref) and ClientTable[i].comp_ref != null) {
|
2020-11-24 22:12:31 +00:00
|
|
|
BSSGP_SP.send(ts_BssgpStsInd(g_nsei, g_cfg.bvci, g_ptp_bvc_state)) to ClientTable[i].comp_ref;
|
BSSGP_Emulation: add BssgpDecodeDepth
Make the decoding level (BSSGP, LLC, SNDCP, L3) configurable, so the
existing PCU tests, that expect messages only decoded to the BSSGP
level, can pass again. Move the SNDCP decoding in f_dec_bssgp above the
L3 decoding, so f_dec_bssgp goes through the layers in the reverse order
of f_send_bssgp_dec.
I have verified, that all testsuites using the BSSGP Emulation (SGSN,
PCU, PCU-SNS) are still working with this patch.
Related: OS#4180
Fixes: 955aa94504510139a12d223071cf49ef90788a3d ("BSSGP_Emulation: Abandon "BssgpDecoded" intermediate structure")
Change-Id: I8f76385528c1de98c557cee451c0e0dfd182b605
2019-09-02 06:36:36 +00:00
|
|
|
}
|
2018-02-18 18:03:36 +00:00
|
|
|
}
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
|
|
|
|
2020-10-04 20:52:56 +00:00
|
|
|
/* attempt to extract the TLLI from a BSSGP PDU */
|
|
|
|
function f_bssgp_get_tlli(PDU_BSSGP bssgp) return template OCT4 {
|
|
|
|
if (ischosen(bssgp.pDU_BSSGP_DL_UNITDATA)) {
|
|
|
|
return bssgp.pDU_BSSGP_DL_UNITDATA.tLLI_current;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_UL_UNITDATA)) {
|
|
|
|
return bssgp.pDU_BSSGP_UL_UNITDATA.tLLI;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY)) {
|
|
|
|
return bssgp.pDU_BSSGP_RA_CAPABILITY.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE)) {
|
|
|
|
return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_RA_CAPABILITY_UPDATE_ACK.tLLI.tLLI_Value;
|
2021-01-17 09:58:56 +00:00
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RADIO_STATUS) and
|
|
|
|
ispresent(bssgp.pDU_BSSGP_RADIO_STATUS.tLLI)) {
|
2020-10-04 20:52:56 +00:00
|
|
|
return bssgp.pDU_BSSGP_RADIO_STATUS.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_SUSPEND)) {
|
|
|
|
return bssgp.pDU_BSSGP_SUSPEND.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_ACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_SUSPEND_ACK.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_SUSPEND_NACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_SUSPEND_NACK.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RESUME)) {
|
|
|
|
return bssgp.pDU_BSSGP_RESUME.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RESUME_ACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_RESUME_ACK.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_RESUME_NACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_RESUME_NACK.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL)) {
|
|
|
|
return bssgp.pDU_BSSGP_FLUSH_LL.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_FLUSH_LL_ACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_FLUSH_LL_ACK.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
|
|
|
|
return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_LLC_DISCARDED)) {
|
|
|
|
return bssgp.pDU_BSSGP_LLC_DISCARDED.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_PAGING_CS) and
|
|
|
|
isvalue(bssgp.pDU_BSSGP_PAGING_CS.tLLI)) {
|
|
|
|
return bssgp.pDU_BSSGP_PAGING_CS.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS)) {
|
|
|
|
return bssgp.pDU_BSSGP_FLOW_CONTROL_MS.tLLI.tLLI_Value;
|
|
|
|
} else if (ischosen(bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK)) {
|
|
|
|
return bssgp.pDU_BSSGP_FLOW_CONTROL_MS_ACK.tLLI.tLLI_Value;
|
2018-02-15 19:39:13 +00:00
|
|
|
}
|
2020-10-04 20:52:56 +00:00
|
|
|
/* TODO: Handover, PFC, LCS */
|
|
|
|
return omit;
|
2018-02-15 16:45:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-17 09:11:19 +00:00
|
|
|
|
2018-02-15 19:39:13 +00:00
|
|
|
|
2017-07-23 15:26:17 +00:00
|
|
|
}
|