cbc: Support mme/bsc sctp/tcp server mode

Related: OS#4945
Change-Id: I9fa4ddfa18ac85644f219874e6b2166e1795e3a9
This commit is contained in:
Pau Espin 2022-08-01 17:55:22 +02:00
parent 7e45128ec0
commit db247f8318
6 changed files with 166 additions and 10 deletions

View File

@ -25,15 +25,23 @@ import from CBS_Message all;
type function void_fn() runs on BSC_ConnHdlr;
/* Coordinate with test_CT: */
type port BSC_ConnHdlr_Coord_PT message {
inout charstring;
} with { extension "internal" };
/* this component represents a single subscriber connection */
type component BSC_ConnHdlr extends CBSP_Adapter_CT {
var BSC_ConnHdlrPars g_pars;
port BSC_ConnHdlr_Coord_PT COORD;
}
type record BSC_ConnHdlrPars {
charstring bsc_host,
integer bsc_cbsp_port,
charstring cbc_host,
integer cbc_cbsp_port,
boolean tcp_is_client,
void_fn start_fn,
CBS_Message exp_cbs_msg optional,
BSSMAP_FIELD_CellIdentificationList cell_list_success optional
@ -41,7 +49,13 @@ type record BSC_ConnHdlrPars {
function f_BSC_ConnHdlr_main(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
g_pars := pars;
CBSP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_cbsp_port, "", g_pars.bsc_cbsp_port);
if (g_pars.tcp_is_client) {
CBSP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_cbsp_port,
g_pars.bsc_host, g_pars.bsc_cbsp_port);
} else {
CBSP_Adapter.f_bind(g_pars.bsc_host, g_pars.bsc_cbsp_port);
CBSP_Adapter.f_wait_client_connect();
}
var BSSMAP_FIELD_CellIdentificationList cell_list := {
cIl_allInBSS := ''O
@ -51,6 +65,7 @@ function f_BSC_ConnHdlr_main(charstring id, BSC_ConnHdlrPars pars) runs on BSC_C
f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST));
f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_EMERG, CBSP_RI_DATA_LOST));
as_cbsp_reset(0);
COORD.send(COORD_MSG_CONNECTED);
g_pars.start_fn.apply();
}

View File

@ -33,18 +33,38 @@ import from ECBE_Components all;
import from BSC_ConnectionHandler all;
import from MME_ConnectionHandler all;
const integer MAX_BSC := 2;
const integer MAX_MME := 2;
type record BSC_modulepar_cfg {
boolean tcp_is_client
};
type record of BSC_modulepar_cfg BSC_modulepar_cfgs;
type record MME_modulepar_cfg {
boolean sctp_is_client
};
type record of MME_modulepar_cfg MME_modulepar_cfgs;
modulepar {
charstring mp_local_host := "127.0.0.2";
charstring mp_cbc_host := "127.0.0.1";
integer mp_cbc_cbsp_port := 48049;
integer mp_cbc_sbcap_port := c_SBC_AP_PORT;
integer mp_cbc_ecbe_port := 12345;
integer mp_local_cbsp_port := 15000;
integer mp_local_sbcap_port := 16000;
/* Must match osmo-cbc.cfg: */
BSC_modulepar_cfgs mp_bsc_cfg := {
{ tcp_is_client := true },
{ tcp_is_client := false }
};
MME_modulepar_cfgs mp_mme_cfg := {
{ sctp_is_client := true },
{ sctp_is_client := false }
};
};
const integer MAX_BSC := 3;
const integer MAX_MME := 3;
type component test_CT extends CBSP_Adapter_CT, http_CT {
timer g_Tguard := 60.0;
var integer g_num_bsc;
@ -53,6 +73,8 @@ type component test_CT extends CBSP_Adapter_CT, http_CT {
var MME_ConnHdlr g_vc_conn_MME[MAX_MME];
var BSC_ConnHdlrPars g_pars_BSC[MAX_BSC];
var MME_ConnHdlrPars g_pars_MME[MAX_MME];
port BSC_ConnHdlr_Coord_PT COORD_BSC[MAX_BSC];
port MME_ConnHdlr_Coord_PT COORD_MME[MAX_BSC];
};
private function f_shutdown_helper() runs on test_CT {
@ -84,12 +106,16 @@ private altstep as_Tguard() runs on test_CT {
private function f_BSC_ConnHdlr_start_fn_void() runs on BSC_ConnHdlr {
log("Default start_fn() function called!");
}
private function f_init_pars_bsc(integer bsc_cbsp_port, charstring cbc_host, integer cbc_cbsp_port)
private function f_init_pars_bsc(charstring bsc_host, integer bsc_cbsp_port,
charstring cbc_host, integer cbc_cbsp_port,
boolean tcp_is_client)
runs on test_CT return BSC_ConnHdlrPars {
var BSC_ConnHdlrPars pars := {
bsc_host := bsc_host,
bsc_cbsp_port := bsc_cbsp_port,
cbc_host := cbc_host,
cbc_cbsp_port := cbc_cbsp_port,
tcp_is_client := tcp_is_client,
start_fn := refers(f_BSC_ConnHdlr_start_fn_void),
exp_cbs_msg := omit,
cell_list_success := omit
@ -101,7 +127,10 @@ private function f_init_bsc(integer idx, charstring id) runs on test_CT return B
var BSC_ConnHdlr vc_conn;
id := id & "-BSC" & int2str(idx);
vc_conn := BSC_ConnHdlr.create(id) alive;
g_pars_BSC[idx] := f_init_pars_bsc(mp_local_cbsp_port + idx, mp_cbc_host, mp_cbc_cbsp_port);
g_pars_BSC[idx] := f_init_pars_bsc(mp_local_host, mp_local_cbsp_port + idx,
mp_cbc_host, mp_cbc_cbsp_port,
mp_bsc_cfg[idx].tcp_is_client);
connect(self:COORD_BSC[idx], vc_conn:COORD);
return vc_conn;
}
@ -118,12 +147,16 @@ private function f_start_bsc(integer idx, charstring id, BSC_ConnHdlrPars pars)
private function f_MME_ConnHdlr_start_fn_void() runs on MME_ConnHdlr {
log("Default start_fn() function called!");
}
private function f_init_pars_mme(integer mme_sbcap_port, charstring cbc_host, integer cbc_sbcap_port)
private function f_init_pars_mme(charstring mme_host, integer mme_sbcap_port,
charstring cbc_host, integer cbc_sbcap_port,
boolean sctp_is_client)
runs on test_CT return MME_ConnHdlrPars {
var MME_ConnHdlrPars pars := {
mme_host := mme_host,
mme_sbcap_port := mme_sbcap_port,
cbc_host := cbc_host,
cbc_sbcap_port := cbc_sbcap_port,
sctp_is_client := sctp_is_client,
start_fn := refers(f_MME_ConnHdlr_start_fn_void),
exp_cbs_msg := omit,
write_replace_warning_ind_cause := omit,
@ -136,7 +169,10 @@ private function f_init_mme(integer idx, charstring id) runs on test_CT return M
var MME_ConnHdlr vc_conn;
id := id & "-MME" & int2str(idx);
vc_conn := MME_ConnHdlr.create(id) alive;
g_pars_MME[idx] := f_init_pars_mme(mp_local_sbcap_port + idx, mp_cbc_host, mp_cbc_sbcap_port);
g_pars_MME[idx] := f_init_pars_mme(mp_local_host, mp_local_sbcap_port + idx,
mp_cbc_host, mp_cbc_sbcap_port,
mp_mme_cfg[idx].sctp_is_client);
connect(self:COORD_MME[idx], vc_conn:COORD);
return vc_conn;
}
@ -172,7 +208,14 @@ function f_start(float t_guard := 60.0) runs on test_CT {
for (var integer i := 0; i < g_num_mme; i := i + 1) {
f_start_mme(i, testcasename(), g_pars_MME[i]);
}
f_sleep(2.0); /* wait all conns connected */
/* Now wait for conns to be ready: */
for (var integer i := 0; i < g_num_bsc; i := i + 1) {
COORD_BSC[i].receive(COORD_MSG_CONNECTED);
}
for (var integer i := 0; i < g_num_mme; i := i + 1) {
COORD_MME[i].receive(COORD_MSG_CONNECTED);
}
}
/* test whether or not we receive a valid KEEP-ALIVE from the CBC */
@ -483,6 +526,56 @@ testcase TC_ecbe_create_delete_bsc_and_mme() runs on test_CT {
f_shutdown_helper();
}
/* Create and delete message with BSC acting as TCP server */
testcase TC_ecbe_create_delete_bsc_server() runs on test_CT {
var template (value) BSSMAP_FIELD_CellIdentificationList cell_list_success;
var template (value) CBS_Message msg := t_CBSmsg(46, 16752);
/* The 2nd BSC is the one configured as server, but we only want to test
* that one, so initialize both but copy over config of the 2nd one to
* the first one, to start only one BSC: */
f_init(num_bsc := 2);
g_num_bsc := 1;
g_pars_BSC[0] := g_pars_BSC[1];
cell_list_success := ts_BSSMAP_CIL_CI({
ts_BSSMAP_CI_CI(50001),
ts_BSSMAP_CI_CI(50002),
ts_BSSMAP_CI_CI(50003)
});
g_pars_BSC[0].start_fn := refers(f_bsc_create_and_delete);
g_pars_BSC[0].exp_cbs_msg := valueof(msg);
g_pars_BSC[0].cell_list_success := valueof(cell_list_success);
f_start();
f_create_and_delete(valueof(msg));
f_shutdown_helper();
}
/* Create and delete message with MME acting as SCTP server */
testcase TC_ecbe_create_delete_mme_server() runs on test_CT {
var template (value) CellId_Broadcast_List bcast_cell_id_li;
var template (value) CBS_Message msg := t_CBSmsg(48, 16752);
/* The 2nd MME is the one configured as server, but we only want to test
* that one, so initialize both but copy over config of the 2nd one to
* the first one, to start only one MME: */
f_init(num_bsc := 0, num_mme := 2);
g_num_mme := 1;
g_pars_MME[0] := g_pars_MME[1];
bcast_cell_id_li := {
ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 1234)),
ts_SBCAP_CellId_Broadcast_List_Item(ts_SBCAP_ECGI(f_enc_mcc_mnc('901'H, '70'H), 5678))
};
g_pars_MME[0].start_fn := refers(f_mme_create_and_delete);
g_pars_MME[0].exp_cbs_msg := valueof(msg);
g_pars_MME[0].write_replace_warning_ind_cause := SBC_AP_Cause_message_accepted;
g_pars_MME[0].bcast_cell_id_list := valueof(bcast_cell_id_li);
f_start();
f_create_and_delete(valueof(msg));
f_shutdown_helper();
}
control {
execute( TC_rx_keepalive() );
execute( TC_rx_keepalive_timeout() );
@ -493,6 +586,8 @@ control {
execute( TC_ecbe_create_delete_lai() );
execute( TC_ecbe_create_delete_mme_indication() );
execute( TC_ecbe_create_delete_bsc_and_mme() );
execute( TC_ecbe_create_delete_bsc_server() );
execute( TC_ecbe_create_delete_mme_server() );
}
}

View File

@ -17,6 +17,10 @@ import from BSSMAP_Templates all;
import from CBSP_Types all;
/* Messages used for coordination between handlers and test_CT: */
const charstring COORD_MSG_CONNECTED := "COORD_MSG_CONNECTED";
type record CBS_Message {
uint16_t msg_id,
uint16_t ser_nr,

View File

@ -25,15 +25,23 @@ import from CBS_Message all;
type function void_fn() runs on MME_ConnHdlr;
/* Coordinate with test_CT: */
type port MME_ConnHdlr_Coord_PT message {
inout charstring;
} with { extension "internal" };
/* this component represents a single subscriber connection */
type component MME_ConnHdlr extends SBC_AP_Adapter_CT {
var MME_ConnHdlrPars g_pars;
port MME_ConnHdlr_Coord_PT COORD;
}
type record MME_ConnHdlrPars {
charstring mme_host,
integer mme_sbcap_port,
charstring cbc_host,
integer cbc_sbcap_port,
boolean sctp_is_client,
void_fn start_fn,
CBS_Message exp_cbs_msg optional,
SBC_AP_Cause write_replace_warning_ind_cause optional,
@ -42,7 +50,14 @@ type record MME_ConnHdlrPars {
function f_MME_ConnHdlr_main(charstring id, MME_ConnHdlrPars pars) runs on MME_ConnHdlr {
g_pars := pars;
SBC_AP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_sbcap_port, "", g_pars.mme_sbcap_port);
if (g_pars.sctp_is_client) {
SBC_AP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_sbcap_port,
g_pars.mme_host, g_pars.mme_sbcap_port);
} else {
SBC_AP_Adapter.f_bind(g_pars.mme_host, g_pars.mme_sbcap_port);
SBC_AP_Adapter.f_wait_client_connect();
}
COORD.send(COORD_MSG_CONNECTED);
g_pars.start_fn.apply();
}

View File

@ -77,6 +77,16 @@ runs on CBSP_Adapter_CT {
f_set_tcp_segmentation(idx);
}
function f_wait_client_connect(integer idx := 0) runs on CBSP_Adapter_CT {
var IPL4asp_Types.PortEvent rx_event;
CBSP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
/* we want to store the client's connId, not the 'bind socket' one */
g_cbsp_conn_id[idx] := rx_event.connOpened.connId;
}
f_set_tcp_segmentation(idx);
}
function f_cbsp_send(template (value) CBSP_PDU pdu, integer idx := 0) runs on CBSP_Adapter_CT {
CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], pdu));
}

View File

@ -77,6 +77,23 @@ runs on SBC_AP_Adapter_CT {
g_SBC_AP_conn_id[idx] := res.connId;
}
function f_wait_client_connect(integer idx := 0) runs on SBC_AP_Adapter_CT {
var IPL4asp_Types.PortEvent rx_event;
SBC_AP[idx].receive(IPL4asp_Types.PortEvent:{connOpened:=?}) -> value rx_event {
log("Connection from ", rx_event.connOpened.remName, ":", rx_event.connOpened.remPort);
/* we want to store the client's connId, not the 'bind socket' one */
g_SBC_AP_conn_id[idx] := rx_event.connOpened.connId;
}
timer Tcommup := 10.0;
Tcommup.start;
alt {
[] SBC_AP[idx].receive(tr_SctpAssocChange_COMM_UP(g_SBC_AP_conn_id[idx])) {}
[] Tcommup.timeout {
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Timeout waiting SCTP_COMM_UP");
}
}
}
function f_SBC_AP_send(template (value) SBC_AP_PDU pdu, integer idx := 0) runs on SBC_AP_Adapter_CT {
SBC_AP[idx].send(ts_SBC_AP_Send(g_SBC_AP_conn_id[idx], pdu));
}