osmo-ttcn3-hacks/gbproxy/GBProxy_Tests.ttcn

745 lines
20 KiB
Plaintext
Raw Normal View History

module GBProxy_Tests {
/* Osmocom GBProxy test suite in TTCN-3
* (C) 2020 sysmocom - s.f.m.c. GmbH
* All rights reserved.
*
* Author: Daniel Willmann <dwillmann@sysmocom.de>
* 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 GSM_Types all;
import from Native_Functions all;
import from NS_Types all;
import from NS_Emulation all;
import from BSSGP_Types all;
import from BSSGP_Emulation all;
import from SCCPasp_Types all;
import from Osmocom_Gb_Types all;
import from MobileL3_CommonIE_Types all;
import from MobileL3_GMM_SM_Types all;
import from MobileL3_Types all;
import from L3_Templates all;
import from L3_Common all;
import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;
import from LLC_Types all;
import from LLC_Templates all;
import from GSM_RR_Types all;
/* mcc_mnc is 24.008 10.5.5.15 encoded. 262 42 */
const BcdMccMnc c_mcc_mnc := '262F42'H;
modulepar {
/* IP/port on which we run our internal GSUP/HLR emulation */
NSConfigurations mp_nsconfig_sgsn := {
{
nsei := 101,
role_sgsn := true,
handle_sns := false,
nsvc := {
{
provider := {
ip := {
address_family := AF_INET,
local_udp_port := 7777,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
remote_ip := "127.0.0.1"
}
},
nsvci := 101
}
}
}
};
NSConfigurations mp_nsconfig_pcu := {
{
nsei := 96,
role_sgsn := false,
handle_sns := false,
nsvc := {
{
provider := {
ip := {
address_family := AF_INET,
local_udp_port := 21010,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
remote_ip := "127.0.0.1"
}
},
nsvci := 97
}
}
},
{
nsei := 97,
role_sgsn := false,
handle_sns := false,
nsvc := {
{
provider := {
ip := {
address_family := AF_INET,
local_udp_port := 21011,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
remote_ip := "127.0.0.1"
}
},
nsvci := 98
}
}
},
{
nsei := 98,
role_sgsn := false,
handle_sns := false,
nsvc := {
{
provider := {
ip := {
address_family := AF_INET,
local_udp_port := 21012,
local_ip := "127.0.0.1",
remote_udp_port := 23000,
remote_ip := "127.0.0.1"
}
},
nsvci := 99
}
}
}
};
BssgpConfigs mp_gbconfigs := {
{
nsei := 96,
sgsn_role := false,
bvc := {
{
bvci := 196,
cell_id := {
ra_id := {
lai := {
mcc_mnc := c_mcc_mnc,
lac := 13135
},
rac := 0
},
cell_id := 20960
},
depth := BSSGP_DECODE_DEPTH_BSSGP,
create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
}
}
}, {
nsei := 97,
sgsn_role := false,
bvc := {
{
bvci := 210,
cell_id := {
ra_id := {
lai := {
mcc_mnc := c_mcc_mnc,
lac := 13200
},
rac := 0
},
cell_id := 20961
},
depth := BSSGP_DECODE_DEPTH_BSSGP,
create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
}
}
}, {
nsei := 98,
sgsn_role := false,
bvc := {
{
bvci := 220,
cell_id := {
ra_id := {
lai := {
mcc_mnc := c_mcc_mnc,
lac := 13300
},
rac := 0
},
cell_id := 20962
},
depth := BSSGP_DECODE_DEPTH_BSSGP,
create_cb := refers(BSSGP_Emulation.DefaultCreateCallback)
}
}
}
}
};
type record GbInstance {
NS_CT vc_NS,
BSSGP_CT vc_BSSGP,
BSSGP_BVC_CTs vc_BSSGP_BVC,
BssgpConfig cfg
};
type record of BSSGP_BVC_CT BSSGP_BVC_CTs
const integer NUM_PCU := 3;
type record of GbInstance GbInstances;
type record of BssgpConfig BssgpConfigs;
type record of NSConfiguration NSConfigurations;
type record of BssgpCellId BssgpCellIds;
const integer NUM_SGSN := 1;
type component test_CT {
var GbInstances g_pcu;
var GbInstances g_sgsn;
port BSSGP_CT_PROC_PT PROC;
port BSSGP_BVC_MGMT_PT SGSN_MGMT;
port BSSGP_BVC_MGMT_PT PCU_MGMT;
port TELNETasp_PT GBPVTY;
var boolean g_initialized := false;
var boolean g_use_echo := false;
};
type component BSSGP_ConnHdlr {
port BSSGP_PT PCU[NUM_PCU];
port BSSGP_PT PCU_SIG[NUM_PCU];
port BSSGP_PROC_PT PCU_PROC[NUM_PCU];
port BSSGP_PT SGSN[NUM_SGSN];
port BSSGP_PT SGSN_SIG[NUM_SGSN];
port BSSGP_PROC_PT SGSN_PROC[NUM_SGSN];
var BSSGP_ConnHdlrPars g_pars;
timer g_Tguard;
var LLC_Entities llc;
}
type record SGSN_ConnHdlrNetworkPars {
boolean expect_ptmsi,
boolean expect_auth,
boolean expect_ciph
};
type record BSSGP_ConnHdlrPars {
/* IMEI of the simulated ME */
hexstring imei,
/* IMSI of the simulated MS */
hexstring imsi,
/* MSISDN of the simulated MS (probably unused) */
hexstring msisdn,
/* P-TMSI allocated to the simulated MS */
OCT4 p_tmsi optional,
OCT3 p_tmsi_sig optional,
/* TLLI of the simulated MS */
OCT4 tlli,
OCT4 tlli_old optional,
RoutingAreaIdentificationV ra optional,
GbInstances pcu,
float t_guard
};
private function f_cellid_to_RAI(in BssgpCellId cell_id) return RoutingAreaIdentificationV {
/* mcc_mnc is encoded as of 24.008 10.5.5.15 */
var BcdMccMnc mcc_mnc := cell_id.ra_id.lai.mcc_mnc;
var RoutingAreaIdentificationV ret := {
mccDigit1 := mcc_mnc[0],
mccDigit2 := mcc_mnc[1],
mccDigit3 := mcc_mnc[2],
mncDigit3 := mcc_mnc[3],
mncDigit1 := mcc_mnc[4],
mncDigit2 := mcc_mnc[5],
lac := int2oct(cell_id.ra_id.lai.lac, 16),
rac := int2oct(cell_id.ra_id.rac, 8)
}
return ret;
};
private function f_init_gb_pcu(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
var charstring ns_id := id & "-NS(PCU[" & int2str(offset) & "])";
var charstring bssgp_id := id & "-BSSGP(PCU[" & int2str(offset) & "])";
gb.vc_NS := NS_CT.create(ns_id);
gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
/* connect lower end of BSSGP emulation with NS upper port */
connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
gb.vc_NS.start(NSStart(mp_nsconfig_pcu[offset], ns_id));
gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
connect(self:PROC, gb.vc_BSSGP:PROC);
gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
disconnect(self:PROC, gb.vc_BSSGP:PROC);
connect(self:PCU_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
}
}
private function f_init_gb_sgsn(inout GbInstance gb, charstring id, integer offset) runs on test_CT {
var charstring ns_id := id & "-NS(SGSN[" & int2str(offset) & "])";
var charstring bssgp_id := id & "-BSSGP(SGSN[" & int2str(offset) & "])";
gb.vc_NS := NS_CT.create(ns_id);
gb.vc_BSSGP := BSSGP_CT.create(bssgp_id);
/* connect lower end of BSSGP emulation with NS upper port */
connect(gb.vc_BSSGP:BSCP, gb.vc_NS:NS_SP);
gb.vc_NS.start(NSStart(mp_nsconfig_sgsn[offset], ns_id));
gb.vc_BSSGP.start(BssgpStart(gb.cfg, bssgp_id));
for (var integer i := 0; i < lengthof(gb.cfg.bvc); i := i + 1) {
connect(self:PROC, gb.vc_BSSGP:PROC);
gb.vc_BSSGP_BVC[i] := f_bssgp_get_bvci_ct(gb.cfg.bvc[i].bvci, PROC);
disconnect(self:PROC, gb.vc_BSSGP:PROC);
connect(self:SGSN_MGMT, gb.vc_BSSGP_BVC[i]:MGMT);
}
}
private function f_init_vty() runs on test_CT {
map(self:GBPVTY, system:GBPVTY);
f_vty_set_prompts(GBPVTY);
f_vty_transceive(GBPVTY, "enable");
}
type record of integer ro_integer;
private function ro_integer_contains(ro_integer r, integer x) return boolean {
for (var integer j := 0; j < lengthof(r); j := j+1) {
if (r[j] == x) {
return true;
}
}
return false;
}
function f_init() runs on test_CT {
var ro_integer bvci_unblocked := {};
var BssgpStatusIndication bsi;
var integer i;
if (g_initialized == true) {
return;
}
g_initialized := true;
g_sgsn[0].cfg := {
nsei := mp_nsconfig_sgsn[0].nsei,
sgsn_role := true,
bvc := { }
}
for (i := 0; i < lengthof(mp_gbconfigs); i := i+1) {
g_pcu[i].cfg := mp_gbconfigs[i];
/* concatenate all the PCU-side BVCs for the SGSN side */
g_sgsn[0].cfg.bvc := g_sgsn[0].cfg.bvc & mp_gbconfigs[i].bvc;
}
f_init_vty();
for (i := 0; i < lengthof(mp_nsconfig_sgsn); i := i+1) {
f_init_gb_sgsn(g_sgsn[i], "GbProxy_Test", i);
}
f_sleep(4.0);
for (i := 0; i < lengthof(mp_nsconfig_pcu); i := i+1) {
f_init_gb_pcu(g_pcu[i], "GbProxy_Test", i);
}
/* wait until all BVC are unblocked on both sides */
timer T := 5.0;
T.start;
alt {
[] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
bvci_unblocked := bvci_unblocked & { bsi.bvci };
if (lengthof(bvci_unblocked) != lengthof(g_sgsn[0].cfg.bvc)) {
repeat;
}
}
[] SGSN_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
repeat;
}
[] SGSN_MGMT.receive {
setverdict(fail, "Received unexpected message on SGSN_MGMT");
mtc.stop;
}
[] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, BVC_S_UNBLOCKED}) -> value bsi {
repeat;
}
[] PCU_MGMT.receive(BssgpStatusIndication:{*, ?, ?}) {
repeat;
}
[] PCU_MGMT.receive(BssgpResetIndication:{0}) {
repeat;
}
[] PCU_MGMT.receive {
setverdict(fail, "Received unexpected message on PCU_MGMT");
mtc.stop;
}
[] T.timeout {
setverdict(fail, "Timeout waiting for unblock of all BVCs");
mtc.stop;
}
}
/* iterate over list and check all BVCI */
for (i := 0; i < lengthof(g_sgsn[0].cfg.bvc); i := i+1) {
var BssgpBvci bvci := g_sgsn[0].cfg.bvc[i].bvci;
if (not ro_integer_contains(bvci_unblocked, bvci)) {
setverdict(fail, "BVCI=", bvci, " was not unblocked during start-up");
mtc.stop;
}
}
}
function f_cleanup() runs on test_CT {
self.stop;
}
type function void_fn(charstring id) runs on BSSGP_ConnHdlr;
/* helper function to create, connect and start a BSSGP_ConnHdlr component */
function f_start_handler(void_fn fn, charstring id, GbInstances pcu, GbInstances sgsn, integer imsi_suffix,
float t_guard := 30.0)
runs on test_CT return BSSGP_ConnHdlr {
var BSSGP_ConnHdlr vc_conn;
var BSSGP_ConnHdlrPars pars := {
imei := f_gen_imei(imsi_suffix),
imsi := f_gen_imsi(imsi_suffix),
msisdn := f_gen_msisdn(imsi_suffix),
p_tmsi := omit,
p_tmsi_sig := omit,
tlli := f_gprs_tlli_random(),
tlli_old := omit,
ra := omit,
pcu := g_pcu,
t_guard := t_guard
};
vc_conn := BSSGP_ConnHdlr.create(id);
// PDU side
connect(vc_conn:PCU[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP);
connect(vc_conn:PCU_SIG[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
connect(vc_conn:PCU_PROC[0], pcu[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
connect(vc_conn:PCU[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP);
connect(vc_conn:PCU_SIG[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
connect(vc_conn:PCU_PROC[1], pcu[1].vc_BSSGP_BVC[0]:BSSGP_PROC);
connect(vc_conn:PCU[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP);
connect(vc_conn:PCU_SIG[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
connect(vc_conn:PCU_PROC[2], pcu[2].vc_BSSGP_BVC[0]:BSSGP_PROC);
// SGSN side
connect(vc_conn:SGSN[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP);
connect(vc_conn:SGSN_SIG[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_SP_SIG);
connect(vc_conn:SGSN_PROC[0], sgsn[0].vc_BSSGP_BVC[0]:BSSGP_PROC);
vc_conn.start(f_handler_init(fn, id, pars));
return vc_conn;
}
private altstep as_Tguard() runs on BSSGP_ConnHdlr {
[] g_Tguard.timeout {
setverdict(fail, "Tguard timeout");
mtc.stop;
}
}
/* first function called in every ConnHdlr */
private function f_handler_init(void_fn fn, charstring id, BSSGP_ConnHdlrPars pars)
runs on BSSGP_ConnHdlr {
var integer i;
/* do some common stuff like setting up g_pars */
g_pars := pars;
llc := f_llc_create(false);
/* register for our IMSI + TLLI */
for (i := 0; i < sizeof(SGSN_PROC); i := i+1) {
if (SGSN_PROC[i].checkstate("Connected")) {
f_client_register(g_pars.imsi, g_pars.tlli, SGSN_PROC[i]);
}
}
for (i := 0; i < sizeof(PCU_PROC); i := i+1) {
if (PCU_PROC[i].checkstate("Connected")) {
f_client_register(g_pars.imsi, g_pars.tlli, PCU_PROC[i]);
}
}
g_Tguard.start(pars.t_guard);
activate(as_Tguard());
/* call the user-supplied test case function */
fn.apply(id);
}
private function f_client_register(hexstring imsi, OCT4 tlli, BSSGP_PROC_PT PT)
runs on BSSGP_ConnHdlr {
PT.call(BSSGP_register_client:{imsi, tlli}) {
[] PT.getreply(BSSGP_register_client:{imsi, tlli}) {};
}
}
private function f_client_unregister(hexstring imsi, BSSGP_PROC_PT PT)
runs on BSSGP_ConnHdlr {
PT.call(BSSGP_unregister_client:{imsi}) {
[] PT.getreply(BSSGP_unregister_client:{imsi}) {};
}
}
/* Send 'tx' on PTP-BVCI from PCU; expect 'rx' on SGSN */
friend function f_pcu2sgsn(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
integer pcu_idx := 0, integer sgsn_idx := 0) runs on BSSGP_ConnHdlr {
var PDU_BSSGP rx;
timer T := 1.0;
PCU[pcu_idx].send(tx);
T.start;
alt {
[] SGSN[sgsn_idx].receive(exp_rx) {
setverdict(pass);
}
[] SGSN[sgsn_idx].receive(PDU_BSSGP:?) -> value rx {
setverdict(fail, "Unexpected BSSGP on SGSN side: ", rx);
mtc.stop;
}
[] T.timeout {
setverdict(fail, "Timeout waiting for BSSGP on SGSN side: ", rx);
mtc.stop;
}
}
}
/* Send 'tx' on PTP-BVCI from SGSN; expect 'rx' on PCU */
friend function f_sgsn2pcu(template (value) PDU_BSSGP tx, template (present) PDU_BSSGP exp_rx,
integer sgsn_idx:= 0, integer pcu_idx := 0) runs on BSSGP_ConnHdlr {
var PDU_BSSGP rx;
timer T := 1.0;
SGSN[sgsn_idx].send(tx);
T.start;
alt {
[] PCU[pcu_idx].receive(exp_rx) {
setverdict(pass);
}
[] PCU[pcu_idx].receive(PDU_BSSGP:?) -> value rx {
setverdict(fail, "Unexpected BSSGP on PCU side: ", rx);
mtc.stop;
}
[] T.timeout {
setverdict(fail, "Timeout waiting for BSSGP on PCU side: ", rx);
mtc.stop;
}
}
}
/* TODO:
* Detach without Attach
* SM procedures without attach / RAU
* ATTACH / RAU
** with / without authentication
** with / without P-TMSI allocation
* re-transmissions of LLC frames
* PDP Context activation
** with different GGSN config in SGSN VTY
** with different PDP context type (v4/v6/v46)
** timeout from GGSN
** multiple / secondary PDP context
*/
private function f_TC_BVC_bringup(charstring id) runs on BSSGP_ConnHdlr {
f_sleep(5.0);
setverdict(pass);
}
testcase TC_BVC_bringup() runs on test_CT {
var BSSGP_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_TC_BVC_bringup), testcasename(), g_pcu, g_sgsn, 51);
vc_conn.done;
f_cleanup();
}
friend function f_bssgp_suspend(integer ran_idx := 0) runs on BSSGP_ConnHdlr return OCT1 {
var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
timer T := 5.0;
var PDU_BSSGP rx_pdu;
PCU_SIG[ran_idx].send(ts_BSSGP_SUSPEND(g_pars.tlli, bvcc.cell_id.ra_id));
T.start;
alt {
[] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_ACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
return rx_pdu.pDU_BSSGP_SUSPEND_ACK.suspend_Reference_Number.suspend_Reference_Number_value;
}
[] PCU_SIG[ran_idx].receive(tr_BSSGP_SUSPEND_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) -> value rx_pdu {
setverdict(fail, "SUSPEND-NACK in response to SUSPEND for TLLI ", g_pars.tlli);
mtc.stop;
}
[] T.timeout {
setverdict(fail, "No SUSPEND-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
mtc.stop;
}
}
return '00'O;
}
friend function f_bssgp_resume(OCT1 susp_ref, integer ran_idx := 0) runs on BSSGP_ConnHdlr {
var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
timer T := 5.0;
PCU_SIG[ran_idx].send(ts_BSSGP_RESUME(g_pars.tlli, bvcc.cell_id.ra_id, susp_ref));
T.start;
alt {
[] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_ACK(g_pars.tlli, bvcc.cell_id.ra_id));
[] PCU_SIG[ran_idx].receive(tr_BSSGP_RESUME_NACK(g_pars.tlli, bvcc.cell_id.ra_id, ?)) {
setverdict(fail, "RESUME-NACK in response to RESUME for TLLI ", g_pars.tlli);
mtc.stop;
}
[] T.timeout {
setverdict(fail, "No RESUME-ACK in response to SUSPEND for TLLI ", g_pars.tlli);
mtc.stop;
}
}
}
/* send uplink-unitdata of a variety of different sizes; expect it to show up on SGSN */
private function f_TC_ul_unitdata(charstring id) runs on BSSGP_ConnHdlr {
var integer ran_idx := 0;
var BssgpBvcConfig bvcc := g_pars.pcu[ran_idx].cfg.bvc[0];
var integer i;
for (i := 0; i < 1024; i := i+1) {
var octetstring payload := f_rnd_octstring(i);
var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
/* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_UL_UD(g_pars.tlli, bvcc.cell_id, payload);
f_pcu2sgsn(pdu_tx, pdu_rx);
}
setverdict(pass);
}
testcase TC_ul_unitdata() runs on test_CT
{
var BSSGP_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_TC_ul_unitdata), testcasename(), g_pcu, g_sgsn, 1);
vc_conn.done;
/* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
f_cleanup();
}
/* send downlink-unitdata of a variety of different sizes; expect it to show up on PCU */
private function f_TC_dl_unitdata(charstring id) runs on BSSGP_ConnHdlr {
var integer i;
for (i := 0; i < 1024; i := i+1) {
var octetstring payload := f_rnd_octstring(i);
var template (value) PDU_BSSGP pdu_tx :=
ts_BSSGP_DL_UD(g_pars.tlli, payload, omit, ts_BSSGP_IMSI(g_pars.imsi));
/* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
var template (present) PDU_BSSGP pdu_rx :=
tr_BSSGP_DL_UD(g_pars.tlli, payload, tr_BSSGP_IMSI(g_pars.imsi));
f_sgsn2pcu(pdu_tx, pdu_rx);
}
setverdict(pass);
}
testcase TC_dl_unitdata() runs on test_CT
{
var BSSGP_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_TC_dl_unitdata), testcasename(), g_pcu, g_sgsn, 2);
vc_conn.done;
/* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
f_cleanup();
}
private function f_TC_ra_capability(charstring id) runs on BSSGP_ConnHdlr {
var integer i;
for (i := 0; i < 10; i := i+1) {
var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP(g_pars.tlli, { ts_RaCapRec_BSSGP });
/* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP(g_pars.tlli, { tr_RaCapRec_BSSGP })
f_sgsn2pcu(pdu_tx, pdu_rx);
}
setverdict(pass);
}
testcase TC_ra_capability() runs on test_CT
{
var BSSGP_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_TC_ra_capability), testcasename(), g_pcu, g_sgsn, 3);
vc_conn.done;
/* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
f_cleanup();
}
private function f_TC_ra_capability_upd(charstring id) runs on BSSGP_ConnHdlr {
var integer i;
var OCT1 tag;
for (i := 0; i < 10; i := i+1) {
tag := int2oct(23 + i, 1);
var template (value) PDU_BSSGP pdu_tx := ts_BSSGP_RA_CAP_UPD(g_pars.tlli, tag);
/* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
var template (present) PDU_BSSGP pdu_rx := tr_BSSGP_RA_CAP_UPD(g_pars.tlli, tag)
f_pcu2sgsn(pdu_tx, pdu_rx);
pdu_tx := ts_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O);
/* we cannot use pdu_tx as there are some subtle differences in the length field :/ */
pdu_rx := tr_BSSGP_RA_CAP_UPD_ACK(g_pars.tlli, tag, '42'O)
f_sgsn2pcu(pdu_tx, pdu_rx);
}
setverdict(pass);
}
testcase TC_ra_capability_upd() runs on test_CT
{
var BSSGP_ConnHdlr vc_conn;
f_init();
vc_conn := f_start_handler(refers(f_TC_ra_capability_upd), testcasename(), g_pcu, g_sgsn, 3);
vc_conn.done;
/* TODO: start multiple handlers (UEs) on various cells on same and other NSEs */
f_cleanup();
}
control {
execute( TC_BVC_bringup() );
execute( TC_ul_unitdata() );
execute( TC_dl_unitdata() );
execute( TC_ra_capability() );
execute( TC_ra_capability_upd() );
}
}