pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/41083?usp=email )
Change subject: SGsAP_Emulation: Introduce proper support for server-mode ......................................................................
SGsAP_Emulation: Introduce proper support for server-mode
Prior to this commit, only initial (not really useful) SCTP server-mode support existed in SGsAP_Emulation. This is basically because MSC_Tests uses the SCTP client-mode, and MME_Tests_SGsAP were not yet in a fully working state.
In server-mode, we have a conn_id for the listening socket and a conn_id for the accepted socket; track them properly. Moreover, in server node we definetly need some sort of event to wait for the client to connect; introduce it. Based on existing work in Iuh_Emulation.
Change-Id: Iccf4ac96c56e947529f0ffc06428e2325a115d50 --- M library/SGsAP_Emulation.ttcn M mme/MME_Tests.ttcn M msc/MSC_Tests.ttcn 3 files changed, 111 insertions(+), 11 deletions(-)
Approvals: fixeria: Looks good to me, approved laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve
diff --git a/library/SGsAP_Emulation.ttcn b/library/SGsAP_Emulation.ttcn index bb125a5..da5a311 100644 --- a/library/SGsAP_Emulation.ttcn +++ b/library/SGsAP_Emulation.ttcn @@ -34,6 +34,7 @@ import from SCTP_Templates all; import from Osmocom_Types all; import from IPL4asp_Types all; +import from Misc_Helpers all; import from DNS_Helpers all; import from MobileL3_Types all;
@@ -48,9 +49,20 @@ inout PDU_SGsAP, PDU_ML3_MS_NW, PDU_ML3_NW_MS; } with { extension "internal" };
+type enumerated SGsAPEM_EventUpDown { + SGsAPEM_EVENT_DOWN, + SGsAPEM_EVENT_UP +} + +/* an event indicating us whether or not a connection is physically up or down, + * and whether we have received an ID_ACK */ +type union SGsAPEM_Event { + SGsAPEM_EventUpDown up_down +} + /* global test port e.g. for non-imsi/conn specific messages */ type port SGsAP_PT message { - inout PDU_SGsAP; + inout PDU_SGsAP, SGsAPEM_Event; } with { extension "internal" };
@@ -76,8 +88,10 @@ /* test port for unit data messages */ port SGsAP_PT SGsAP_UNIT;
+ var SGsAP_conn_parameters g_pars; var charstring g_sgsap_id; - var integer g_sgsap_conn_id := -1; + var integer g_self_conn_id := -1; + var IPL4asp_Types.ConnectionId g_last_conn_id := -1; /* server only */ }
type function SGsAPCreateCallback(PDU_SGsAP msg, hexstring imsi, charstring id) @@ -101,7 +115,7 @@ function tr_SGsAP_RecvFrom_R(template PDU_SGsAP msg) runs on SGsAP_Emulation_CT return template SGsAP_RecvFrom { var template SGsAP_RecvFrom mrf := { - connId := g_sgsap_conn_id, + connId := ?, remName := ?, remPort := ?, locName := ?, @@ -246,13 +260,35 @@ return omit; }
+private function emu_is_server() runs on SGsAP_Emulation_CT return boolean { + return g_pars.remote_sctp_port == -1; +} + +/* Resolve TCP/IP connection identifier depending on server/client mode */ +private function f_sgsap_conn_id() +runs on SGsAP_Emulation_CT return IPL4asp_Types.ConnectionId { + var IPL4asp_Types.ConnectionId conn_id; + + if (not emu_is_server()) { + conn_id := g_self_conn_id; + } else { + conn_id := g_last_conn_id; + } + + if (conn_id == -1) { /* Just to be sure */ + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, "Connection is not established"); + } + + return conn_id; +} + private function f_sgsap_xceive(template (value) PDU_SGsAP tx, template PDU_SGsAP rx_t := ?) runs on SGsAP_Emulation_CT return PDU_SGsAP { timer T := 10.0; var SGsAP_RecvFrom mrf;
- SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, tx)); + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), tx)); alt { [] SGsAP.receive(tr_SGsAP_RecvFrom_R(rx_t)) -> value mrf { } [] SGsAP.receive(tr_SctpAssocChange) { repeat; } @@ -265,8 +301,15 @@ return mrf.msg; }
+private function f_send_SGsAPEM_Event(template (value) SGsAPEM_Event evt) runs on SGsAP_Emulation_CT { + if (SGsAP_UNIT.checkstate("Connected")) { + SGsAP_UNIT.send(evt); + } +} + function main(SGsAPOps ops, SGsAP_conn_parameters p, charstring id) runs on SGsAP_Emulation_CT { var Result res; + g_pars := p; g_sgsap_id := id; f_imsi_table_init(); f_expect_table_init(); @@ -281,10 +324,14 @@ { sctp := valueof(ts_SctpTuple) }); } if (not ispresent(res.connId)) { - setverdict(fail, "Could not connect SGsAP socket, check your configuration"); - mtc.stop; + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, "Could not connect SGsAP socket, check your configuration"); } - g_sgsap_conn_id := res.connId; + g_self_conn_id := res.connId; + + /* notify user about SCTP establishment */ + if (p.remote_sctp_port != -1) { + f_send_SGsAPEM_Event(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_UP}); + }
while (true) { var SGsAP_ConnHdlr vc_conn; @@ -295,30 +342,41 @@ var SGsAP_RecvFrom mrf; var PDU_SGsAP msg; var charstring vlr_name, mme_name; + var ASP_Event asp_evt;
alt { + /* SGsAP UNITDATA from client */ + [] SGsAP_UNIT.receive(PDU_SGsAP:?) -> value msg sender vc_conn { + /* Pass message through */ + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), msg)); + } + /* SGsAP from client */ [] SGsAP_CLIENT.receive(PDU_SGsAP:?) -> value msg sender vc_conn { /* Pass message through */ /* TODO: check which ConnectionID client has allocated + store in table? */ - SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg)); + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), msg)); } /* DTAP/MobileL3 from client (emulated MS): wrap in SGsAP-UL-UD and send */ [] SGsAP_CLIENT.receive(PDU_ML3_MS_NW:?) -> value l3_mo sender vc_conn { var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3_mo); imsi := f_imsi_by_comp(vc_conn); msg := valueof(ts_SGsAP_UL_UD(imsi, l3_enc)); - SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg)); + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), msg)); } [] SGsAP_CLIENT.receive(PDU_ML3_NW_MS:?) -> value l3_mt sender vc_conn { var octetstring l3_enc := enc_PDU_ML3_NW_MS(l3_mt); imsi := f_imsi_by_comp(vc_conn); msg := valueof(ts_SGsAP_DL_UD(imsi, l3_enc)); - SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, msg)); + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), msg)); }
/* DTAP/MobileL3 from MSC/VLR to MS wrapped in SGsAP-DL-UD: Extract, decode, forward */ [] SGsAP.receive(tr_SGsAP_RecvFrom_R(tr_SGsAP_DL_UD(?,?))) -> value mrf { + if (not match(mrf.connId, f_sgsap_conn_id())) { + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, + log2str("Received message from unexpected conn_id!", mrf)); + } var octetstring l3_enc := mrf.msg.sGsAP_DOWNLINK_UNITDATA.nAS_MessageContainer.nAS_MessageContainer; imsi := mrf.msg.sGsAP_DOWNLINK_UNITDATA.iMSI.iMSI.digits; vc_conn := f_comp_by_imsi(imsi); @@ -326,6 +384,10 @@ SGsAP_CLIENT.send(l3_mt) to vc_conn; } [] SGsAP.receive(tr_SGsAP_RecvFrom_R(tr_SGsAP_UL_UD(?,?))) -> value mrf { + if (not match(mrf.connId, f_sgsap_conn_id())) { + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, + log2str("Received message from unexpected conn_id!", mrf)); + } var octetstring l3_enc := mrf.msg.sGsAP_UPLINK_UNITDATA.nAS_MessageContainer.nAS_MessageContainer; imsi := mrf.msg.sGsAP_UPLINK_UNITDATA.iMSI.iMSI.digits; l3_mo := dec_PDU_ML3_MS_NW(l3_enc); @@ -336,6 +398,10 @@
/* any other SGsAP from MSC/VLR */ [] SGsAP.receive(tr_SGsAP_RecvFrom_R(?)) -> value mrf { + if (not match(mrf.connId, f_sgsap_conn_id())) { + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, + log2str("Received message from unexpected conn_id!", mrf)); + } imsi_t := f_SGsAP_get_imsi(mrf.msg); if (isvalue(imsi_t)) { imsi := valueof(imsi_t.iMSI.digits); @@ -351,12 +417,39 @@ /* message contained no IMSI; is not IMSI-oriented */ var template PDU_SGsAP resp := ops.unitdata_cb.apply(mrf.msg); if (isvalue(resp)) { - SGsAP.send(t_SGsAP_Send(g_sgsap_conn_id, valueof(resp))); + SGsAP.send(t_SGsAP_Send(f_sgsap_conn_id(), valueof(resp))); } } } [] SGsAP.receive(tr_SctpAssocChange) { } [] SGsAP.receive(tr_SctpPeerAddrChange) { } + [] SGsAP.receive(tr_SctpShutDownEvent) { + log("SGsAP: SCTP shutdown"); + g_self_conn_id := -1; + f_send_SGsAPEM_Event(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_DOWN}); /* TODO: send asp_evt.sctpShutDownEvent.clientId */ + if (not emu_is_server()) { + self.stop; + } + } + /* server only */ + [] SGsAP.receive(ASP_Event:{connOpened:=?}) -> value asp_evt { + if (not emu_is_server()) { + Misc_Helpers.f_shutdown(__FILE__, __LINE__, fail, + log2str("Unexpected event receiver in client mode", asp_evt)); + } + g_last_conn_id := asp_evt.connOpened.connId; + log("Established a new SGsAP connection (conn_id=", g_last_conn_id, ")"); + + f_send_SGsAPEM_Event(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_UP}); /* TODO: send g_last_conn_id */ + } + [] SGsAP.receive(ASP_Event:{connClosed:=?}) -> value asp_evt { + log("SGsAP: Closed"); + g_self_conn_id := -1; + f_send_SGsAPEM_Event(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_DOWN}); /* TODO: send asp_evt.connClosed.connId */ + if (not emu_is_server()) { + self.stop; + } + } [] SGsAP_PROC.getcall(SGsAPEM_register:{?,?}) -> param(imsi, vc_conn) { f_create_expect(imsi, vc_conn); SGsAP_PROC.reply(SGsAPEM_register:{imsi, vc_conn}) to vc_conn; diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn index 2847bcc..885b727 100644 --- a/mme/MME_Tests.ttcn +++ b/mme/MME_Tests.ttcn @@ -154,6 +154,8 @@ connect(vc_SGsAP:SGsAP_PROC, self:SGsAP_PROC); connect(vc_SGsAP:SGsAP_UNIT, self:SGsAP_UNIT); vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id)); + + SGsAP_UNIT.receive(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_UP}); }
/* send incoming unit data messages (like reset) to global S1AP_UNIT port */ diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn index 47b2c5e..ceddc11 100644 --- a/msc/MSC_Tests.ttcn +++ b/msc/MSC_Tests.ttcn @@ -106,7 +106,9 @@ var GSUP_Emulation_CT vc_GSUP; var IPA_Emulation_CT vc_GSUP_IPA; var SMPP_Emulation_CT vc_SMPP; + var SGsAP_Emulation_CT vc_SGsAP; + port SGsAP_PT SGsAP_UNIT;
/* only to get events from IPA underneath GSUP */ port IPA_CTRL_PT GSUP_IPA_EVENT; @@ -284,7 +286,10 @@
vc_SGsAP := SGsAP_Emulation_CT.create(id); map(vc_SGsAP:SGsAP, system:SGsAP_CODEC_PT); + connect(vc_SGsAP:SGsAP_UNIT, self:SGsAP_UNIT); vc_SGsAP.start(SGsAP_Emulation.main(ops, pars, id)); + + SGsAP_UNIT.receive(SGsAPEM_Event:{up_down:=SGsAPEM_EVENT_UP}); }