laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/34212 )
Change subject: DIAMETER_Emulation: Support forwarding messages identified by ete_id to a client component ......................................................................
DIAMETER_Emulation: Support forwarding messages identified by ete_id to a client component
This is useful in the scenarios where the client component submits a IMSI-based transaction such as AIR, but its answer (AIA) contains no IMSI (as per what's specified in TS 29.272 5.2.3.1). As a result, the received AIA message would be enqueued in the DIAMETER_UNIT.
With this new feature, the test can create an expect using the End-to-End Identifier of the message it is going to transmit, and receive the answer in the same DIAMETER_CLIENT port the request was transmitted, even if it contains no IMSI.
Related: OS#5757 Change-Id: I25e44146d2c49e308c1fb490b499e70ac6045f2f --- M library/DIAMETER_Emulation.ttcn M mme/MME_Tests.ttcn M pgw/PGW_Tests.ttcn 3 files changed, 130 insertions(+), 15 deletions(-)
Approvals: laforge: Looks good to me, approved fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified
diff --git a/library/DIAMETER_Emulation.ttcn b/library/DIAMETER_Emulation.ttcn index 6eb72ad..e7481ca 100644 --- a/library/DIAMETER_Emulation.ttcn +++ b/library/DIAMETER_Emulation.ttcn @@ -70,6 +70,12 @@ hexstring imsi optional };
+/* represents a single DIAMETER message identified by ete_id field */ +type record ETEIDData { + DIAMETER_ConnHdlr comp_ref, + UINT32 ete_id optional +}; + type component DIAMETER_Emulation_CT { /* Port facing to the UDP SUT */ port DIAMETER_CODEC_PT DIAMETER; @@ -79,6 +85,8 @@ port DIAMETER_Conn_PT DIAMETER_CLIENT; /* currently tracked connections */ var AssociationData DiameterAssocTable[256]; + /* Forward reply messages not containing IMSI to correct client port */ + var ETEIDData DiameterETEIDTable[256]; /* pending expected CRCX */ var ExpectData DiameterExpectTable[256]; /* procedure based port to register for incoming connections */ @@ -202,7 +210,6 @@ mtc.stop; }
- private function f_imsi_table_init() runs on DIAMETER_Emulation_CT { for (var integer i := 0; i < sizeof(DiameterAssocTable); i := i+1) { @@ -211,6 +218,67 @@ } }
+/* End-to-End ID table matching. */ +private function f_ete_id_known(UINT32 ete_id) +runs on DIAMETER_Emulation_CT return boolean { + var integer i; + for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) { + if (DiameterETEIDTable[i].ete_id == ete_id) { + return true; + } + } + return false; +} + +private function f_comp_by_ete_id(UINT32 ete_id) +runs on DIAMETER_Emulation_CT return DIAMETER_ConnHdlr { + var integer i; + for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) { + if (DiameterETEIDTable[i].ete_id == ete_id) { + return DiameterETEIDTable[i].comp_ref; + } + } + setverdict(fail, "DIAMETER ETEID Table not found by ete_id", ete_id); + mtc.stop; +} + +private function f_eteid_table_add(DIAMETER_ConnHdlr comp_ref, UINT32 ete_id) +runs on DIAMETER_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) { + if (not isvalue(DiameterETEIDTable[i].ete_id)) { + DiameterETEIDTable[i].ete_id := ete_id; + DiameterETEIDTable[i].comp_ref := comp_ref; + return; + } + } + testcase.stop("DIAMETER ETEID Table full!"); +} + +private function f_eteid_table_del(DIAMETER_ConnHdlr comp_ref, UINT32 ete_id) +runs on DIAMETER_Emulation_CT { + var integer i; + for (i := 0; i < sizeof(DiameterETEIDTable); i := i+1) { + if (DiameterETEIDTable[i].comp_ref == comp_ref and + DiameterETEIDTable[i].ete_id == ete_id) { + DiameterETEIDTable[i].ete_id := omit; + DiameterETEIDTable[i].comp_ref := null; + return; + } + } + setverdict(fail, "DIAMETER ETEID Table: Couldn't find to-be-deleted entry!"); + mtc.stop; +} + + +private function f_eteid_table_init() +runs on DIAMETER_Emulation_CT { + for (var integer i := 0; i < sizeof(DiameterETEIDTable); i := i+1) { + DiameterETEIDTable[i].comp_ref := null; + DiameterETEIDTable[i].ete_id := omit; + } +} + function f_DIAMETER_get_imsi(PDU_DIAMETER pdu) return template (omit) IMSI { var template (omit) AVP imsi_avp; @@ -280,6 +348,7 @@ var Result res; g_diameter_id := id; f_imsi_table_init(); + f_eteid_table_init(); f_expect_table_init();
map(self:DIAMETER, system:DIAMETER_CODEC_PT); @@ -311,6 +380,7 @@ var DIAMETER_ConnHdlr vc_conn; var template IMSI imsi_t; var hexstring imsi; + var UINT32 ete_id; var DIAMETER_RecvFrom mrf; var PDU_DIAMETER msg; var charstring vlr_name, mme_name; @@ -357,7 +427,13 @@ /* DIAMETER from remote peer (IMSI based routing) */ [not ops.raw] DIAMETER.receive(tr_DIAMETER_RecvFrom_R(?)) -> value mrf { imsi_t := f_DIAMETER_get_imsi(mrf.msg); - if (isvalue(imsi_t)) { + ete_id := mrf.msg.end_to_end_id; + if (f_ete_id_known(ete_id)) { + vc_conn := f_comp_by_ete_id(ete_id); + /* The ete_id is a single-time expect: */ + f_eteid_table_del(vc_conn, ete_id); + DIAMETER_CLIENT.send(mrf.msg) to vc_conn; + } else if (isvalue(imsi_t)) { imsi := valueof(imsi_t); if (f_imsi_known(imsi)) { vc_conn := f_comp_by_imsi(imsi); @@ -377,9 +453,13 @@ } [] DIAMETER.receive(tr_SctpAssocChange) { } [] DIAMETER.receive(tr_SctpPeerAddrChange) { } - [] DIAMETER_PROC.getcall(DIAMETEREM_register:{?,?}) -> param(imsi, vc_conn) { + [] DIAMETER_PROC.getcall(DIAMETEREM_register_imsi:{?,?}) -> param(imsi, vc_conn) { f_create_expect(imsi, vc_conn); - DIAMETER_PROC.reply(DIAMETEREM_register:{imsi, vc_conn}) to vc_conn; + DIAMETER_PROC.reply(DIAMETEREM_register_imsi:{imsi, vc_conn}) to vc_conn; + } + [] DIAMETER_PROC.getcall(DIAMETEREM_register_eteid:{?,?}) -> param(ete_id, vc_conn) { + f_eteid_table_add(vc_conn, ete_id); + DIAMETER_PROC.reply(DIAMETEREM_register_eteid:{ete_id, vc_conn}) to vc_conn; }
} @@ -387,18 +467,29 @@ } }
-/* "Expect" Handling */ +/* "E2E ID Expect" Handling */ +type record ExpectDataE2EID { + UINT32 ete_id optional, + DIAMETER_ConnHdlr vc_conn +} + +signature DIAMETEREM_register_eteid(in UINT32 ete_id, in DIAMETER_ConnHdlr hdlr); + +/* client/conn_hdlr side function to use procedure port to create expect in emulation */ +function f_diameter_expect_eteid(UINT32 ete_id) runs on DIAMETER_ConnHdlr { + DIAMETER_PROC.call(DIAMETEREM_register_eteid:{ete_id, self}) { + [] DIAMETER_PROC.getreply(DIAMETEREM_register_eteid:{?,?}) {}; + } +} + +/* "IMSI Expect" Handling */
type record ExpectData { hexstring imsi optional, DIAMETER_ConnHdlr vc_conn }
-signature DIAMETEREM_register(in hexstring imsi, in DIAMETER_ConnHdlr hdlr); - -type port DIAMETEREM_PROC_PT procedure { - inout DIAMETEREM_register; -} with { extension "internal" }; +signature DIAMETEREM_register_imsi(in hexstring imsi, in DIAMETER_ConnHdlr hdlr);
/* Function that can be used as create_cb and will use the expect table */ function ExpectedCreateCallback(PDU_DIAMETER msg, hexstring imsi, charstring id) @@ -446,9 +537,9 @@ }
/* client/conn_hdlr side function to use procedure port to create expect in emulation */ -function f_diameter_expect(hexstring imsi) runs on DIAMETER_ConnHdlr { - DIAMETER_PROC.call(DIAMETEREM_register:{imsi, self}) { - [] DIAMETER_PROC.getreply(DIAMETEREM_register:{?,?}) {}; +function f_diameter_expect_imsi(hexstring imsi) runs on DIAMETER_ConnHdlr { + DIAMETER_PROC.call(DIAMETEREM_register_imsi:{imsi, self}) { + [] DIAMETER_PROC.getreply(DIAMETEREM_register_imsi:{?,?}) {}; } }
@@ -466,6 +557,10 @@ return omit; }
+type port DIAMETEREM_PROC_PT procedure { + inout DIAMETEREM_register_imsi; + inout DIAMETEREM_register_eteid; +} with { extension "internal" };
function f_diameter_wait_capability(DIAMETER_PT pt) { diff --git a/mme/MME_Tests.ttcn b/mme/MME_Tests.ttcn index 17a4d60..cc75377 100644 --- a/mme/MME_Tests.ttcn +++ b/mme/MME_Tests.ttcn @@ -361,7 +361,7 @@ g_Tguard.start(t_guard); activate(as_Tguard()); if (DIAMETER_PROC.checkstate("Connected")) { - f_diameter_expect(g_pars.ue_pars.imsi); + f_diameter_expect_imsi(g_pars.ue_pars.imsi); } if (SGsAP_PROC.checkstate("Connected")) { /* Route all SGsAP mesages for our IMSIto us */ diff --git a/pgw/PGW_Tests.ttcn b/pgw/PGW_Tests.ttcn index 7bb6910..4730040 100644 --- a/pgw/PGW_Tests.ttcn +++ b/pgw/PGW_Tests.ttcn @@ -72,7 +72,7 @@ var PDU_DIAMETER msg;
if (DIAMETER_PROC.checkstate("Connected")) { - f_diameter_expect(imsi); + f_diameter_expect_imsi(imsi); }
while (true) {