ipa: Further progress on the bsc-nat test suite
This commit is contained in:
parent
19ad52b3b9
commit
c82eef458d
|
@ -43,9 +43,12 @@ function main(charstring remote_ip, PortNumber remote_port,
|
||||||
/* connect MTP3 service provider (IPA) to lower side of SCCP */
|
/* connect MTP3 service provider (IPA) to lower side of SCCP */
|
||||||
connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT);
|
connect(vc_IPA:MTP3_SP_PORT, vc_SCCP:MTP3_SCCP_PORT);
|
||||||
|
|
||||||
/* connect BSSNAP dispatcher to upper side of SCCP */
|
/* connect BSSMAP dispatcher to upper side of SCCP */
|
||||||
connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT);
|
connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT);
|
||||||
|
|
||||||
|
/* connect BSSMAP dispatcher to IPA_Emulation MGCP */
|
||||||
|
connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT);
|
||||||
|
|
||||||
vc_IPA.start(IPA_Emulation.main_client(remote_ip, remote_port, local_ip, local_port));
|
vc_IPA.start(IPA_Emulation.main_client(remote_ip, remote_port, local_ip, local_port));
|
||||||
vc_SCCP.start(SCCPStart(sccp_pars));
|
vc_SCCP.start(SCCPStart(sccp_pars));
|
||||||
vc_BSSMAP.start(BSSMAP_Emulation.main(BSC_MS_BssmapOps));
|
vc_BSSMAP.start(BSSMAP_Emulation.main(BSC_MS_BssmapOps));
|
||||||
|
|
|
@ -7,6 +7,10 @@ import from BSSAP_Types all;
|
||||||
import from BSSMAP_Emulation all;
|
import from BSSMAP_Emulation all;
|
||||||
import from BSSMAP_Templates all;
|
import from BSSMAP_Templates all;
|
||||||
|
|
||||||
|
import from MGCP_Types all;
|
||||||
|
import from MGCP_Templates all;
|
||||||
|
import from SDP_Types all;
|
||||||
|
|
||||||
/* this component represents a single subscriber connection at the MSC.
|
/* this component represents a single subscriber connection at the MSC.
|
||||||
* There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components.
|
* There is a 1:1 mapping between SCCP connections and BSSAP_ConnHdlr components.
|
||||||
* We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */
|
* We inherit all component variables, ports, functions, ... from BSSAP_ConnHdlr */
|
||||||
|
@ -15,6 +19,11 @@ type component MSC_ConnHdlr extends BSSAP_ConnHdlr {
|
||||||
var uint5_t g_e1_timeslot;
|
var uint5_t g_e1_timeslot;
|
||||||
/* SCCP Connecction Identifier for the underlying SCCP connection */
|
/* SCCP Connecction Identifier for the underlying SCCP connection */
|
||||||
var integer g_sccp_conn_id;
|
var integer g_sccp_conn_id;
|
||||||
|
|
||||||
|
var MSC_State g_state := MSC_STATE_NONE;
|
||||||
|
var MgcpEndpoint g_ep_name;
|
||||||
|
var MgcpCallId g_call_id;
|
||||||
|
var MgcpConnectionId g_mgcp_conn_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback function from general BSSMAP_Emulation whenever a new incoming
|
/* Callback function from general BSSMAP_Emulation whenever a new incoming
|
||||||
|
@ -49,30 +58,98 @@ const BssmapOps MSC_BssmapOps := {
|
||||||
unitdata_cb := refers(UnitdataCallback)
|
unitdata_cb := refers(UnitdataCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type enumerated MSC_State {
|
||||||
|
MSC_STATE_NONE,
|
||||||
|
MSC_STATE_WAIT_ASS_COMPL,
|
||||||
|
MSC_STATE_WAIT_CRCX_ACK,
|
||||||
|
MSC_STATE_WAIT_MDCX_ACK,
|
||||||
|
MSC_STATE_WAIT_CLEAR_COMPL,
|
||||||
|
MSC_STATE_WAIT_DLCX_ACK
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_mgcp_alloc_tid() return MgcpTransId {
|
||||||
|
return int2str(float2int(rnd()*2147483647.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_mgcp_alloc_call_id() return MgcpCallId {
|
||||||
|
return int2hex(float2int(rnd()*2147483647.0), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
function extract_conn_id(MgcpResponse resp) return MgcpConnectionId {
|
||||||
|
var integer i;
|
||||||
|
for (i := 0; i < lengthof(resp.params); i := i + 1) {
|
||||||
|
var MgcpParameter par := resp.params[i];
|
||||||
|
if (par.code == "I") {
|
||||||
|
return str2hex(par.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setverdict(fail);
|
||||||
|
return '00000000'H;
|
||||||
|
}
|
||||||
|
|
||||||
/* main function processing various incoming events */
|
/* main function processing various incoming events */
|
||||||
function main(integer connection_id, integer timeslot) runs on MSC_ConnHdlr {
|
function main(integer connection_id, integer timeslot) runs on MSC_ConnHdlr {
|
||||||
g_sccp_conn_id := connection_id;
|
var MgcpResponse mgcp_rsp;
|
||||||
|
|
||||||
g_e1_timeslot := 1; /* FIXME */
|
g_e1_timeslot := 1; /* FIXME */
|
||||||
|
|
||||||
|
g_sccp_conn_id := connection_id;
|
||||||
|
g_call_id := f_mgcp_alloc_call_id();
|
||||||
|
g_ep_name := hex2str(int2hex(g_e1_timeslot, 1)) & "@mgw";
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
var PDU_BSSAP bssap;
|
var PDU_BSSAP bssap;
|
||||||
alt {
|
alt {
|
||||||
/* new SCCP-level connection indication from BSC */
|
/* new SCCP-level connection indication from BSC */
|
||||||
[] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap {
|
[g_state == MSC_STATE_NONE] BSSAP.receive(tr_BSSMAP_ComplL3) -> value bssap {
|
||||||
/* respond with ASSIGNMENT CMD */
|
/* respond with ASSIGNMENT CMD */
|
||||||
|
g_state := MSC_STATE_WAIT_ASS_COMPL;
|
||||||
BSSAP.send(ts_BSSMAP_AssignmentReq(0, g_e1_timeslot));
|
BSSAP.send(ts_BSSMAP_AssignmentReq(0, g_e1_timeslot));
|
||||||
/* FIXME: Send MGCP */
|
}
|
||||||
|
[g_state == MSC_STATE_WAIT_ASS_COMPL] BSSAP.receive(tr_BSSMAP_AssignmentComplete) {
|
||||||
|
/* FIXME: Send MGCP CRCX */
|
||||||
|
g_state := MSC_STATE_WAIT_CRCX_ACK;
|
||||||
|
var MgcpTransId trans_id := f_mgcp_alloc_tid();
|
||||||
|
//template SDP_Message sdp := omit;
|
||||||
|
BSSAP.send(ts_CRCX(trans_id, g_ep_name, "recvonly", g_call_id)); //, sdp));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
[] BSSAP.receive(tr_BSSMAP_AssignmentCompl) {
|
|
||||||
}
|
|
||||||
[] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
|
[] BSSAP.receive(tr_BSSMAP_AssignmentFail) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* receive CRCX ACK: transmit MDCX */
|
||||||
|
[g_state == MSC_STATE_WAIT_CRCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp {
|
||||||
|
/* extract connection ID */
|
||||||
|
g_mgcp_conn_id := extract_conn_id(mgcp_rsp);
|
||||||
|
g_state := MSC_STATE_WAIT_MDCX_ACK;
|
||||||
|
var MgcpTransId trans_id := f_mgcp_alloc_tid();
|
||||||
|
BSSAP.send(ts_MDCX(trans_id, g_ep_name, "sendrecv", g_call_id, g_mgcp_conn_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* receive MDCX ACK: wait + transmit CLEAR COMMAND */
|
||||||
|
[g_state == MSC_STATE_WAIT_MDCX_ACK] BSSAP.receive(tr_CRCX_ACK) -> value mgcp_rsp {
|
||||||
|
g_state := MSC_STATE_WAIT_CLEAR_COMPL
|
||||||
|
BSSAP.send(ts_BSSMAP_ClearCommand(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */
|
||||||
|
[g_state == MSC_STATE_WAIT_CLEAR_COMPL] BSSAP.receive(ts_BSSMAP_ClearComplete) {
|
||||||
|
/* send DLCX */
|
||||||
|
g_state := MSC_STATE_WAIT_DLCX_ACK;
|
||||||
|
var MgcpTransId trans_id := f_mgcp_alloc_tid();
|
||||||
|
BSSAP.send(ts_DLCX(trans_id, g_ep_name, g_call_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[g_state == MSC_STATE_WAIT_DLCX_ACK] BSSAP.receive(tr_DLCX_ACK) {
|
||||||
|
setverdict(pass);
|
||||||
|
self.stop;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: CLEAR REQUEST from BSS */
|
/* TODO: CLEAR REQUEST from BSS */
|
||||||
/* TODO: CLEAR COMPLETE from BSS (response to CLEAR COMMAND) */
|
|
||||||
|
|
||||||
[] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
|
[] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
|
||||||
|
setverdict(fail);
|
||||||
self.stop;
|
self.stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ function main(charstring local_ip, PortNumber local_port,
|
||||||
/* connect BSSNAP dispatcher to upper side of SCCP */
|
/* connect BSSNAP dispatcher to upper side of SCCP */
|
||||||
connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT);
|
connect(vc_BSSMAP:SCCP, vc_SCCP:SCCP_SP_PORT);
|
||||||
|
|
||||||
|
/* connect BSSMAP dispatcher to IPA_Emulation MGCP */
|
||||||
|
connect(vc_BSSMAP:MGCP, vc_IPA:IPA_MGCP_PORT);
|
||||||
|
|
||||||
vc_IPA.start(IPA_Emulation.main_server(local_ip, local_port));
|
vc_IPA.start(IPA_Emulation.main_server(local_ip, local_port));
|
||||||
vc_SCCP.start(SCCPStart(sccp_pars));
|
vc_SCCP.start(SCCPStart(sccp_pars));
|
||||||
vc_BSSMAP.start(BSSMAP_Emulation.main(MSC_BssmapOps));
|
vc_BSSMAP.start(BSSMAP_Emulation.main(MSC_BssmapOps));
|
||||||
|
|
|
@ -16,7 +16,7 @@ gen_links() {
|
||||||
#gen_links $DIR $FILES
|
#gen_links $DIR $FILES
|
||||||
|
|
||||||
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
||||||
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h"
|
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h SDP_EncDec.cc"
|
||||||
gen_links $DIR $FILES
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
||||||
|
@ -35,7 +35,7 @@ gen_links $DIR $FILES
|
||||||
DIR=../SCCP_CNL113341/src
|
DIR=../SCCP_CNL113341/src
|
||||||
FILES="SCCP_Emulation.ttcn SCCP_EncDec.cc SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
|
FILES="SCCP_Emulation.ttcn SCCP_EncDec.cc SCCP_Mapping.ttcnpp SCCP_Types.ttcn SCCPasp_Types.ttcn"
|
||||||
gen_links $DIR $FILES
|
gen_links $DIR $FILES
|
||||||
ln -s SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn
|
ln -sf SCCP_Mapping.ttcnpp SCCP_Mapping.ttcn
|
||||||
|
|
||||||
DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src
|
DIR=$BASEDIR/titan.ProtocolModules.BSSMAP_v11.2.0/src
|
||||||
FILES="BSSAP_Types.ttcn"
|
FILES="BSSAP_Types.ttcn"
|
||||||
|
@ -45,7 +45,15 @@ DIR=$BASEDIR/titan.ProtocolModules.MobileL3_v13.4.0/src
|
||||||
FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
|
FILES="MobileL3_CC_Types.ttcn MobileL3_CommonIE_Types.ttcn MobileL3_GMM_SM_Types.ttcn MobileL3_MM_Types.ttcn MobileL3_RRM_Types.ttcn MobileL3_SMS_Types.ttcn MobileL3_SS_Types.ttcn MobileL3_Types.ttcn"
|
||||||
gen_links $DIR $FILES
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.ProtocolModules.SDP/src
|
||||||
|
FILES="SDP_EncDec.cc SDP_Types.ttcn SDP_parse_.tab.c SDP_parse_.tab.h SDP_parse_parser.h SDP_parser.l
|
||||||
|
SDP_parser.y lex.SDP_parse_.c"
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
|
DIR=$BASEDIR/titan.ProtocolModules.RTP/src
|
||||||
|
FILES="RTP_EncDec.cc RTP_Types.ttcn"
|
||||||
|
gen_links $DIR $FILES
|
||||||
|
|
||||||
DIR=../library
|
DIR=../library
|
||||||
FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn"
|
FILES="General_Types.ttcn Osmocom_Types.ttcn IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcn L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn"
|
||||||
gen_links $DIR $FILES
|
gen_links $DIR $FILES
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
MAIN=IPA_Test.ttcn
|
MAIN=IPA_Test.ttcn
|
||||||
|
|
||||||
FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc"
|
FILES="*.ttcn SCCP_EncDec.cc IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc RTP_EncDec.cc SDP_EncDec *.c"
|
||||||
|
|
||||||
ttcn3_makefilegen -l -f $MAIN $FILES
|
ttcn3_makefilegen -l -f $MAIN $FILES
|
||||||
sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
|
sed -i -e 's/# TTCN3_DIR = /TTCN3_DIR = \/usr/' Makefile
|
||||||
|
|
|
@ -4,7 +4,9 @@ import from SCCP_Emulation all;
|
||||||
import from SCCPasp_Types all;
|
import from SCCPasp_Types all;
|
||||||
import from BSSAP_Types all;
|
import from BSSAP_Types all;
|
||||||
import from BSSMAP_Templates all;
|
import from BSSMAP_Templates all;
|
||||||
//import from MSC_ConnectionHandler all;
|
import from MGCP_Types all;
|
||||||
|
import from MGCP_Templates all;
|
||||||
|
import from IPA_Emulation all;
|
||||||
|
|
||||||
/* General "base class" component definition, of which specific implementations
|
/* General "base class" component definition, of which specific implementations
|
||||||
* derive themselves by means of the "extends" feature */
|
* derive themselves by means of the "extends" feature */
|
||||||
|
@ -29,7 +31,7 @@ type record BSSAP_Conn_Req {
|
||||||
|
|
||||||
/* port between individual per-connection components and this dispatcher */
|
/* port between individual per-connection components and this dispatcher */
|
||||||
type port BSSAP_Conn_PT message {
|
type port BSSAP_Conn_PT message {
|
||||||
inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req;
|
inout PDU_BSSAP, BSSAP_Conn_Prim, BSSAP_Conn_Req, MgcpCommand, MgcpResponse;
|
||||||
} with { extension "internal" };
|
} with { extension "internal" };
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +39,11 @@ type port BSSAP_Conn_PT message {
|
||||||
type record ConnectionData {
|
type record ConnectionData {
|
||||||
/* reference to the instance of the per-connection component */
|
/* reference to the instance of the per-connection component */
|
||||||
BSSAP_ConnHdlr comp_ref,
|
BSSAP_ConnHdlr comp_ref,
|
||||||
integer sccp_conn_id
|
integer sccp_conn_id,
|
||||||
|
/* most recent MGCP transaction ID (Used on MSC side) */
|
||||||
|
MgcpTransId mgcp_trans_id optional,
|
||||||
|
/* CIC that has been used for voice of this channel (BSC side) */
|
||||||
|
integer cic optional
|
||||||
}
|
}
|
||||||
|
|
||||||
type component BSSMAP_Emulation_CT {
|
type component BSSMAP_Emulation_CT {
|
||||||
|
@ -45,6 +51,8 @@ type component BSSMAP_Emulation_CT {
|
||||||
port SCCPasp_PT SCCP;
|
port SCCPasp_PT SCCP;
|
||||||
/* BSSAP port to the per-connection clients */
|
/* BSSAP port to the per-connection clients */
|
||||||
port BSSAP_Conn_PT CLIENT;
|
port BSSAP_Conn_PT CLIENT;
|
||||||
|
/* MGCP port */
|
||||||
|
port IPA_MGCP_PT MGCP;
|
||||||
|
|
||||||
/* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
|
/* use 16 as this is also the number of SCCP connections that SCCP_Emulation can handle */
|
||||||
var ConnectionData ConnectionTable[16];
|
var ConnectionData ConnectionTable[16];
|
||||||
|
@ -85,6 +93,56 @@ runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr {
|
||||||
self.stop;
|
self.stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* resolve component reference by CIC */
|
||||||
|
private function f_comp_by_mgcp_tid(MgcpTransId tid)
|
||||||
|
runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr {
|
||||||
|
var integer i;
|
||||||
|
for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
||||||
|
if (ConnectionTable[i].mgcp_trans_id == tid) {
|
||||||
|
return ConnectionTable[i].comp_ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("BSSMAP Connection table not found by MGCP Transaction ID ", tid);
|
||||||
|
self.stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_comp_store_mgcp_tid(BSSAP_ConnHdlr client, MgcpTransId tid)
|
||||||
|
runs on BSSMAP_Emulation_CT {
|
||||||
|
var integer i;
|
||||||
|
for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
||||||
|
if (ConnectionTable[i].comp_ref == client) {
|
||||||
|
ConnectionTable[i].mgcp_trans_id := tid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("BSSMAP Connection table not found by component ", client);
|
||||||
|
self.stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_comp_by_cic(integer cic)
|
||||||
|
runs on BSSMAP_Emulation_CT return BSSAP_ConnHdlr {
|
||||||
|
var integer i;
|
||||||
|
for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
||||||
|
if (ConnectionTable[i].cic == cic) {
|
||||||
|
return ConnectionTable[i].comp_ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("BSSMAP Connection table not found by CIC ", cic);
|
||||||
|
self.stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function f_comp_store_cic(BSSAP_ConnHdlr client, integer cic)
|
||||||
|
runs on BSSMAP_Emulation_CT {
|
||||||
|
var integer i;
|
||||||
|
for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
||||||
|
if (ConnectionTable[i].comp_ref == client) {
|
||||||
|
ConnectionTable[i].cic := cic;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("BSSMAP Connection table not found by component ", client);
|
||||||
|
}
|
||||||
|
|
||||||
/* resolve connection ID by component reference */
|
/* resolve connection ID by component reference */
|
||||||
private function f_conn_id_by_comp(BSSAP_ConnHdlr client)
|
private function f_conn_id_by_comp(BSSAP_ConnHdlr client)
|
||||||
runs on BSSMAP_Emulation_CT return integer {
|
runs on BSSMAP_Emulation_CT return integer {
|
||||||
|
@ -113,6 +171,8 @@ runs on BSSMAP_Emulation_CT {
|
||||||
for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
for (var integer i := 0; i < sizeof(ConnectionTable); i := i+1) {
|
||||||
ConnectionTable[i].comp_ref := null;
|
ConnectionTable[i].comp_ref := null;
|
||||||
ConnectionTable[i].sccp_conn_id := -1;
|
ConnectionTable[i].sccp_conn_id := -1;
|
||||||
|
ConnectionTable[i].mgcp_trans_id := omit;
|
||||||
|
ConnectionTable[i].cic := omit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +238,8 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT {
|
||||||
var BSSAP_Conn_Req creq;
|
var BSSAP_Conn_Req creq;
|
||||||
var BSSAP_ConnHdlr vc_conn;
|
var BSSAP_ConnHdlr vc_conn;
|
||||||
var PDU_BSSAP bssap;
|
var PDU_BSSAP bssap;
|
||||||
|
var MgcpCommand mgcp_req;
|
||||||
|
var MgcpResponse mgcp_resp;
|
||||||
|
|
||||||
alt {
|
alt {
|
||||||
/* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
|
/* SCCP -> Client: UNIT-DATA (connectionless SCCP) from a BSC */
|
||||||
|
@ -266,14 +328,62 @@ function main(BssmapOps ops) runs on BSSMAP_Emulation_CT {
|
||||||
|
|
||||||
[] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn {
|
[] CLIENT.receive(PDU_BSSAP:?) -> value bssap sender vc_conn {
|
||||||
var integer conn_id := f_conn_id_by_comp(vc_conn);
|
var integer conn_id := f_conn_id_by_comp(vc_conn);
|
||||||
|
/* MSC Side: If this is an assignment command, store CIC */
|
||||||
|
if (ischosen(bssap.pdu.bssmap.assignmentRequest) and
|
||||||
|
ispresent(bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode)) {
|
||||||
|
var BSSMAP_IE_CircuitIdentityCode cic_ie :=
|
||||||
|
bssap.pdu.bssmap.assignmentRequest.circuitIdentityCode;
|
||||||
|
var integer cic := (oct2int(cic_ie.cicHigh) * 256) + oct2int(cic_ie.cicLow);
|
||||||
|
f_comp_store_cic(vc_conn, cic);
|
||||||
|
}
|
||||||
/* encode + send it to dispatcher */
|
/* encode + send it to dispatcher */
|
||||||
var octetstring userdata := enc_PDU_BSSAP(bssap);
|
var octetstring userdata := enc_PDU_BSSAP(bssap);
|
||||||
SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit));
|
SCCP.send(t_ASP_N_DATA_req(userdata, conn_id, omit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handling of MGCP in IPA SCCPLite case. This predates 3GPP AoIP
|
||||||
|
* and uses a MGCP session in parallel to BSSAP. BSSAP uses CIC
|
||||||
|
* as usual, and MGCP uses "CIC@mgw" endpoint naming, where CIC
|
||||||
|
* is printed as hex string, e.g. a@mgw for CIC 10 */
|
||||||
|
|
||||||
|
/* CLIENT -> MGCP */
|
||||||
|
[] CLIENT.receive(MgcpCommand:?) -> value mgcp_req sender vc_conn {
|
||||||
|
/* MGCP request from Handler (we're MSC) */
|
||||||
|
/* store the transaction ID we've seen */
|
||||||
|
f_comp_store_mgcp_tid(vc_conn, mgcp_req.line.trans_id);
|
||||||
|
/* simply forward any MGCP from the client to the port */
|
||||||
|
MGCP.send(mgcp_req);
|
||||||
|
}
|
||||||
|
[] CLIENT.receive(MgcpResponse:?) -> value mgcp_resp sender vc_conn {
|
||||||
|
/* MGCP response from Handler (we're BSC/MGW) */
|
||||||
|
/* simply forward any MGCP from the client to the port */
|
||||||
|
MGCP.send(mgcp_resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MGCP -> CLIENT */
|
||||||
|
[] MGCP.receive(MgcpCommand:?) -> value mgcp_req {
|
||||||
|
/* MGCP request from network side (we're BSC/MGW) */
|
||||||
|
/* Extract CIC from local part of endpoint name */
|
||||||
|
var integer cic := f_mgcp_ep_extract_cic(mgcp_req.line.ep);
|
||||||
|
/* Resolve the vc_conn by the CIC */
|
||||||
|
vc_conn := f_comp_by_cic(cic);
|
||||||
|
CLIENT.send(mgcp_req) to vc_conn;
|
||||||
|
}
|
||||||
|
[] MGCP.receive(MgcpResponse:?) -> value mgcp_resp {
|
||||||
|
/* MGCP response from network side (we're MSC) */
|
||||||
|
/* Resolve the vc_conn by the transaction ID */
|
||||||
|
vc_conn := f_comp_by_mgcp_tid(mgcp_resp.line.trans_id);
|
||||||
|
CLIENT.send(mgcp_resp) to vc_conn;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function f_mgcp_ep_extract_cic(charstring inp) return integer {
|
||||||
|
var charstring local_part := regexp(inp, "(.*)@(.*)", 0);
|
||||||
|
return hex2int(str2hex(local_part));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,13 @@ module IPA_CodecPort {
|
||||||
octetstring msg
|
octetstring msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template IPA_Send t_IPA_Send(ConnectionId conn_id, IpaStreamId stream_id,
|
||||||
|
octetstring msg, template IpaExtStreamId stream_id_ext := omit) := {
|
||||||
|
connId := conn_id,
|
||||||
|
streamId := stream_id,
|
||||||
|
streamIdExt := stream_id_ext,
|
||||||
|
msg := msg
|
||||||
|
}
|
||||||
|
|
||||||
/* 'stream' contains the octets received so far, we must return the total length */
|
/* 'stream' contains the octets received so far, we must return the total length */
|
||||||
function f_IPA_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
|
function f_IPA_getMsgLen(in octetstring stream, inout ro_integer args) return integer {
|
||||||
|
|
|
@ -7,6 +7,8 @@ import from IPL4asp_Types all;
|
||||||
import from MTP3asp_Types all;
|
import from MTP3asp_Types all;
|
||||||
import from MTP3asp_PortType all;
|
import from MTP3asp_PortType all;
|
||||||
|
|
||||||
|
import from MGCP_Types all;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
modulepar {
|
modulepar {
|
||||||
}
|
}
|
||||||
|
@ -19,7 +21,7 @@ type enumerated IpaMode {
|
||||||
|
|
||||||
type record ASP_IPA_Unitdata {
|
type record ASP_IPA_Unitdata {
|
||||||
IpaStreamId streamId,
|
IpaStreamId streamId,
|
||||||
IpaStreamIdExt streamIdExt optional,
|
IpaExtStreamId streamIdExt optional,
|
||||||
octetstring payload
|
octetstring payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,16 +29,24 @@ type port IPA_SP_PT message {
|
||||||
inout ASP_IPA_Unitdata;
|
inout ASP_IPA_Unitdata;
|
||||||
} with { extension "internal" }
|
} with { extension "internal" }
|
||||||
|
|
||||||
|
type port IPA_MGCP_PT message {
|
||||||
|
inout MgcpCommand, MgcpResponse;
|
||||||
|
} with { extension "internal" }
|
||||||
|
|
||||||
type component IPA_Emulation_CT {
|
type component IPA_Emulation_CT {
|
||||||
/* down-facing port to IPA codec port */
|
/* down-facing port to IPA codec port */
|
||||||
port IPA_CODEC_PT IPA_PORT;
|
port IPA_CODEC_PT IPA_PORT;
|
||||||
/* up-facing port to SCCP */
|
/* up-facing port to SCCP */
|
||||||
port MTP3asp_SP_PT MTP3_SP_PORT;
|
port MTP3asp_SP_PT MTP3_SP_PORT;
|
||||||
|
/* up-facing port for MGCP */
|
||||||
|
port IPA_MGCP_PT IPA_MGCP_PORT;
|
||||||
/* up-facing port for other streams */
|
/* up-facing port for other streams */
|
||||||
port IPA_SP_PT IPA_SP_PORT;
|
port IPA_SP_PT IPA_SP_PORT;
|
||||||
|
|
||||||
var boolean g_initialized := false;
|
var boolean g_initialized := false;
|
||||||
var ConnectionId g_ipa_conn_id := -1;
|
var ConnectionId g_ipa_conn_id := -1;
|
||||||
|
/* Are we a BSC/MGW (truel) or MSC (false) */
|
||||||
|
var boolean g_is_bsc_mgw;
|
||||||
|
|
||||||
var IpaMode g_mode;
|
var IpaMode g_mode;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +57,7 @@ function f_connect(charstring remote_host, PortNumber remote_port,
|
||||||
res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
|
res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
|
||||||
local_host, local_port, 0, { tcp:={} });
|
local_host, local_port, 0, { tcp:={} });
|
||||||
g_ipa_conn_id := res.connId;
|
g_ipa_conn_id := res.connId;
|
||||||
|
g_is_bsc_mgw := true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
|
function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
|
||||||
|
@ -54,6 +65,7 @@ function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulat
|
||||||
res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
|
res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
|
||||||
local_host, local_port, { tcp:={} });
|
local_host, local_port, { tcp:={} });
|
||||||
g_ipa_conn_id := res.connId;
|
g_ipa_conn_id := res.connId;
|
||||||
|
g_is_bsc_mgw := false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
|
template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
|
||||||
|
@ -103,12 +115,7 @@ private function f_ccm_make_id_resp(PDU_IPA_CCM get) return PDU_IPA_CCM {
|
||||||
|
|
||||||
/* transmit IPA CCM message */
|
/* transmit IPA CCM message */
|
||||||
private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
|
private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
|
||||||
var IPA_Send ipa_tx := {
|
var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm)));
|
||||||
connId := g_ipa_conn_id,
|
|
||||||
streamId := IPAC_PROTO_CCM,
|
|
||||||
streamIdExt := omit,
|
|
||||||
msg := enc_PDU_IPA_CCM(ccm)
|
|
||||||
}
|
|
||||||
log("CCM Tx:", ccm);
|
log("CCM Tx:", ccm);
|
||||||
IPA_PORT.send(ipa_tx);
|
IPA_PORT.send(ipa_tx);
|
||||||
}
|
}
|
||||||
|
@ -160,12 +167,8 @@ private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
|
private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
|
||||||
var IPA_Send ret := {
|
var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
|
||||||
connId := connId,
|
ipa_tx.streamIdExt));
|
||||||
streamId := ipa_tx.streamId,
|
|
||||||
streamIdExt := ipa_tx.streamIdExt,
|
|
||||||
msg := ipa_tx.payload
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,11 +185,24 @@ function main_server(charstring local_host, PortNumber local_port) runs on IPA_E
|
||||||
ScanEvents();
|
ScanEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
|
||||||
|
var charstring msg_ch := oct2char(msg);
|
||||||
|
if (g_is_bsc_mgw) {
|
||||||
|
log("============");
|
||||||
|
log(msg_ch);
|
||||||
|
IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
|
||||||
|
} else {
|
||||||
|
IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function ScanEvents() runs on IPA_Emulation_CT {
|
private function ScanEvents() runs on IPA_Emulation_CT {
|
||||||
var IPA_RecvFrom ipa_rx;
|
var IPA_RecvFrom ipa_rx;
|
||||||
var ASP_IPA_Unitdata ipa_ud;
|
var ASP_IPA_Unitdata ipa_ud;
|
||||||
var ASP_MTP3_TRANSFERreq mtp_req;
|
var ASP_MTP3_TRANSFERreq mtp_req;
|
||||||
var ASP_Event asp_evt;
|
var ASP_Event asp_evt;
|
||||||
|
var MgcpCommand mgcp_cmd;
|
||||||
|
var MgcpResponse mgcp_rsp;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
alt {
|
alt {
|
||||||
|
@ -197,13 +213,21 @@ private function ScanEvents() runs on IPA_Emulation_CT {
|
||||||
var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
|
var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
|
||||||
log("CCM Rx:", ccm);
|
log("CCM Rx:", ccm);
|
||||||
f_ccm_rx(ccm);
|
f_ccm_rx(ccm);
|
||||||
}
|
} case (IPAC_PROTO_SCCP) {
|
||||||
case (IPAC_PROTO_SCCP) {
|
|
||||||
var ASP_MTP3_TRANSFERind mtp;
|
var ASP_MTP3_TRANSFERind mtp;
|
||||||
mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
|
mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
|
||||||
MTP3_SP_PORT.send(mtp);
|
MTP3_SP_PORT.send(mtp);
|
||||||
|
} case (IPAC_PROTO_MGCP_OLD) {
|
||||||
|
f_mgcp_to_user(ipa_rx.msg);
|
||||||
|
} case (IPAC_PROTO_OSMO) {
|
||||||
|
select (ipa_rx.streamIdExt) {
|
||||||
|
case (IPAC_PROTO_EXT_MGCP) {
|
||||||
|
f_mgcp_to_user(ipa_rx.msg);
|
||||||
|
} case else {
|
||||||
|
IPA_SP_PORT.send(f_to_asp(ipa_rx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case else {
|
} case else {
|
||||||
IPA_SP_PORT.send(f_to_asp(ipa_rx));
|
IPA_SP_PORT.send(f_to_asp(ipa_rx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,15 +250,31 @@ private function ScanEvents() runs on IPA_Emulation_CT {
|
||||||
|
|
||||||
/* Received SCCP -> down into IPA */
|
/* Received SCCP -> down into IPA */
|
||||||
[] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
|
[] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
|
||||||
var IPA_Send ipa_tx := {
|
var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_SCCP,
|
||||||
connId := g_ipa_conn_id,
|
mtp_req.data));
|
||||||
streamId := IPAC_PROTO_SCCP,
|
|
||||||
msg := mtp_req.data
|
|
||||||
}
|
|
||||||
IPA_PORT.send(ipa_tx);
|
IPA_PORT.send(ipa_tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Received MISC (RSL/OML/CTRL/MGCP) -> down into IPA */
|
/* Received MGCP -> down into IPA */
|
||||||
|
[] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
|
||||||
|
ipa_ud := {
|
||||||
|
streamId := IPAC_PROTO_OSMO,
|
||||||
|
streamIdExt := IPAC_PROTO_EXT_MGCP,
|
||||||
|
payload := char2oct(enc_MgcpCommand(mgcp_cmd))
|
||||||
|
}
|
||||||
|
IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
|
||||||
|
}
|
||||||
|
[] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
|
||||||
|
ipa_ud := {
|
||||||
|
streamId := IPAC_PROTO_OSMO,
|
||||||
|
streamIdExt := IPAC_PROTO_EXT_MGCP,
|
||||||
|
payload := char2oct(enc_MgcpResponse(mgcp_rsp))
|
||||||
|
}
|
||||||
|
IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Received MISC (RSL/OML/CTRL) -> down into IPA */
|
||||||
[] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
|
[] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
|
||||||
IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
|
IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,16 @@ module MGCP_Templates {
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template MgcpResponse tr_DLCX_ACK := {
|
||||||
|
line := {
|
||||||
|
code := "200",
|
||||||
|
trans_id := ?,
|
||||||
|
string := "OK"
|
||||||
|
},
|
||||||
|
params:= *,
|
||||||
|
sdp := *
|
||||||
|
}
|
||||||
|
|
||||||
/* SDP Templates */
|
/* SDP Templates */
|
||||||
template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
|
template SDP_Origin ts_SDP_origin(charstring addr, charstring session_id,
|
||||||
charstring session_version := "1",
|
charstring session_version := "1",
|
||||||
|
|
Loading…
Reference in New Issue