neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/28231 )
Change subject: hnbgw: test SCCP CR without payload ......................................................................
hnbgw: test SCCP CR without payload
Various tweaks are required to allow RAN_Emulation to handle, and also to expect, an SCCP CR that has no payload data.
Related: SYS#5968 Related: If0c5c0a76e5230bf22871f527dcb2dbdf34d7328 (osmo-hnbgw) Change-Id: I827e081eaacfb8e76684ed1560603e6c8f896c38 --- M hnbgw/HNBGW_Tests.ttcn M library/RAN_Emulation.ttcnpp 2 files changed, 108 insertions(+), 19 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve neels: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified
diff --git a/hnbgw/HNBGW_Tests.ttcn b/hnbgw/HNBGW_Tests.ttcn index b2c491e..1b1d709 100644 --- a/hnbgw/HNBGW_Tests.ttcn +++ b/hnbgw/HNBGW_Tests.ttcn @@ -167,7 +167,8 @@ hexstring imsi, boolean ps_domain, MgcpParameters mgcp_pars optional, - HnbConfig hnb optional + HnbConfig hnb optional, + boolean separate_sccp_cr }
/* We extend: @@ -498,12 +499,21 @@ }
/* create an expect on the Iu side for the random NAS portion */ - var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx)); - f_ran_register_exp(valueof(nas)); + if (g_pars.separate_sccp_cr) { + f_ran_register_sccp_cr_without_payload(); + } else { + var template (omit) octetstring nas := f_ranap_extract_l3(valueof(tx)); + f_ran_register_exp(valueof(nas)); + }
/* send it via Iuh (creating a RUA connection) */ RUA.send(RUA_Conn_Req:{g_pars.ps_domain, tx});
+ if (g_pars.separate_sccp_cr) { + /* Acknowledge the empty SCCP CR. RAN_Emulation does the confirmation, no need to respond. */ + BSSAP.receive(tr_RANAP_Conn_Req()); + } + /* expect to receive it on the Iu side */ T.start; alt { @@ -634,11 +644,13 @@ ***********************************************************************/
private template (value) TestHdlrParams -t_pars(integer imsi_suffix, boolean ps_domain := false,integer hnb_idx := 0) := { +t_pars(integer imsi_suffix, boolean ps_domain := false, integer hnb_idx := 0, + boolean separate_sccp_cr := false) := { hnb_idx := hnb_idx, imsi := f_gen_imsi(imsi_suffix), ps_domain := ps_domain, - hnb := omit /* filled in later */ + hnb := omit, /* filled in later */ + separate_sccp_cr := separate_sccp_cr }
/* Create an Iuh connection; send InitialUE; expect it to appear on new SCCP conenction */ @@ -666,6 +678,43 @@ vc_conn.done; }
+private function f_vty_set_sccp_cr_max_payload_len(TELNETasp_PT pt, integer val := 999999) +{ + f_vty_enter_config(pt); + f_vty_transceive(pt, "hnbgw"); + f_vty_transceive(pt, "sccp cr max-payload-len " & int2str(val)); + f_vty_transceive(pt, "end"); +} + +testcase TC_ranap_cs_initial_ue_empty_cr() runs on test_CT { + var ConnHdlr vc_conn; + + f_init(); + f_start_hnbs(); + + f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0); + + vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(1, separate_sccp_cr := true)); + vc_conn.done; + + /* reset */ + f_vty_set_sccp_cr_max_payload_len(HNBGWVTY); +} +testcase TC_ranap_ps_initial_ue_empty_cr() runs on test_CT { + var ConnHdlr vc_conn; + + f_init(); + f_start_hnbs(); + + f_vty_set_sccp_cr_max_payload_len(HNBGWVTY, 0); + + vc_conn := f_start_handler_with_pars(refers(f_tc_initial_ue), t_pars(2, true, separate_sccp_cr := true)); + vc_conn.done; + + /* reset */ + f_vty_set_sccp_cr_max_payload_len(HNBGWVTY); +} + /* Reply to a received CRCX with an OK (or the reply configured in cpars), using the given parameters. * Return true when an OK reply was sent, false otherwise. * Count occurrence of Osmux, include Osmux parameters in the reply if necessary. */ @@ -1104,6 +1153,8 @@ execute(TC_hnb_register()); execute(TC_ranap_cs_initial_ue()); execute(TC_ranap_ps_initial_ue()); + execute(TC_ranap_cs_initial_ue_empty_cr()); + execute(TC_ranap_ps_initial_ue_empty_cr()); execute(TC_ranap_cs_bidir()); execute(TC_ranap_ps_bidir()); execute(TC_rab_assignment()); diff --git a/library/RAN_Emulation.ttcnpp b/library/RAN_Emulation.ttcnpp index 3198ee1..543df2b 100644 --- a/library/RAN_Emulation.ttcnpp +++ b/library/RAN_Emulation.ttcnpp @@ -555,9 +555,18 @@ type record RANAP_Conn_Req { SCCP_PAR_Address addr_peer, SCCP_PAR_Address addr_own, - RANAP_PDU ranap + RANAP_PDU ranap optional } -template (value) RANAP_Conn_Req ts_RANAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, RANAP_PDU ranap) := { +template (value) RANAP_Conn_Req ts_RANAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, + template (omit) RANAP_PDU ranap) := { + addr_peer := peer, + addr_own := own, + ranap := ranap +}; + +template RANAP_Conn_Req tr_RANAP_Conn_Req(template SCCP_PAR_Address peer := ?, + template SCCP_PAR_Address own := ?, + template (omit) RANAP_PDU ranap := omit) := { addr_peer := peer, addr_own := own, ranap := ranap @@ -973,7 +982,12 @@ /* store mapping between client components and SCCP connectionId */ f_conn_table_add(vc_conn, rconn_ind.connectionId); /* handle user payload */ - f_handle_userData_RANAP(vc_conn, rconn_ind.userData); + if (ispresent(rconn_ind.userData)) { + f_handle_userData_RANAP(vc_conn, rconn_ind.userData); + } else { + /* Notify client that we received an SCCP CR without user data */ + CLIENT.send(ts_RANAP_Conn_Req(rconn_ind.callingAddress, rconn_ind.calledAddress, omit)); + } /* confirm connection establishment */ RANAP.send(ts_RANAP_CONNECT_res(rconn_ind.connectionId, omit)); } @@ -1250,6 +1264,11 @@ PROC.reply(RAN_register_handoverRequest:{targetPointCode, vc_hdlr}) to vc_hdlr; }
+ [] PROC.getcall(RAN_register_sccp_cr_without_payload:{?}) -> param(vc_hdlr) { + f_create_expect(omit, vc_hdlr); + PROC.reply(RAN_register_sccp_cr_without_payload:{vc_hdlr}) to vc_hdlr; + } + [] PROC.getcall(RAN_register_imsi:{?,?,?}) -> param(imsi, tmsi, vc_hdlr) { f_create_imsi(imsi, tmsi, vc_hdlr); PROC.reply(RAN_register_imsi:{imsi, tmsi, vc_hdlr}) to vc_hdlr; @@ -1280,6 +1299,7 @@ /* L3 payload based on which we can match it */ octetstring l3_payload optional, integer handoverRequestPointCode optional, + boolean sccp_cr_without_payload, /* component reference for this connection */ RAN_ConnHdlr vc_conn } @@ -1287,6 +1307,7 @@ /* procedure based port to register for incoming connections */ signature RAN_register(in octetstring l3, in RAN_ConnHdlr hdlr); signature RAN_register_handoverRequest(in integer targetPointCode, in RAN_ConnHdlr hdlr); +signature RAN_register_sccp_cr_without_payload(in RAN_ConnHdlr hdlr);
/* procedure based port to register for incoming IMSI/TMSI */ signature RAN_register_imsi(in hexstring imsi, in OCT4 tmsi, in RAN_ConnHdlr hdlr); @@ -1299,7 +1320,8 @@ signature RAN_continue_after_n_sd(N_Sd_Array last_n_sd, in RAN_ConnHdlr hdlr);
type port RAN_PROC_PT procedure { - inout RAN_register, RAN_register_imsi, RAN_unregister_imsi, RAN_register_handoverRequest, RAN_last_n_sd, RAN_continue_after_n_sd; + inout RAN_register, RAN_register_imsi, RAN_unregister_imsi, RAN_register_handoverRequest, + RAN_register_sccp_cr_without_payload, RAN_last_n_sd, RAN_continue_after_n_sd; } with { extension "internal" };
#ifdef RAN_EMULATION_BSSAP @@ -1360,25 +1382,31 @@ runs on RAN_Emulation_CT return RAN_ConnHdlr { var RAN_ConnHdlr ret := null; var template (omit) octetstring l3_info; + var boolean rx_sccp_cr_without_payload; var integer i;
- l3_info := f_ranap_extract_l3(conn_ind.userData); - if (istemplatekind(l3_info, "omit")) { - setverdict(fail, "N-CONNECT.ind without NAS payload"); - mtc.stop; - return ret; + if (ispresent(conn_ind.userData)) { + l3_info := f_ranap_extract_l3(conn_ind.userData); + rx_sccp_cr_without_payload := false; + if (istemplatekind(l3_info, "omit") and not rx_sccp_cr_without_payload) { + setverdict(fail, "N-CONNECT.ind without NAS payload"); + mtc.stop; + return ret; + } + } else { + l3_info := omit; + rx_sccp_cr_without_payload := true; }
for (i := 0; i < sizeof(ExpectTable); i:= i+1) { - if (not ispresent(ExpectTable[i].l3_payload)) { - continue; - } - if (valueof(l3_info) == ExpectTable[i].l3_payload) { + if ((rx_sccp_cr_without_payload and ExpectTable[i].sccp_cr_without_payload) + or (ispresent(ExpectTable[i].l3_payload) and valueof(l3_info) == ExpectTable[i].l3_payload)) { ret := ExpectTable[i].vc_conn; /* release this entry to be used again */ + ExpectTable[i].sccp_cr_without_payload := false; ExpectTable[i].l3_payload := omit; ExpectTable[i].vc_conn := null; - log("Found Expect[", i, "] for ", l3_info, " handled at ", ret); + log("Found Expect[", i, "] for l3=", l3_info, " handled at ", ret); /* return the component reference */ return ret; } @@ -1396,9 +1424,12 @@ log("f_create_expect(l3 := ", l3, ", handoverRequest := ", handoverRequestPointCode); for (i := 0; i < sizeof(ExpectTable); i := i+1) { if (not ispresent(ExpectTable[i].l3_payload) + and not ExpectTable[i].sccp_cr_without_payload and not ispresent(ExpectTable[i].handoverRequestPointCode)) { if (ispresent(l3)) { ExpectTable[i].l3_payload := valueof(l3); + } else { + ExpectTable[i].sccp_cr_without_payload := true; } if (ispresent(handoverRequestPointCode)) { ExpectTable[i].handoverRequestPointCode := valueof(handoverRequestPointCode); @@ -1448,6 +1479,7 @@ for (var integer i := 0; i < sizeof(ExpectTable); i := i+1) { ExpectTable[i].l3_payload := omit; ExpectTable[i].handoverRequestPointCode := omit; + ExpectTable[i].sccp_cr_without_payload := false; } }
@@ -1484,6 +1516,12 @@ } }
+function f_ran_register_sccp_cr_without_payload() runs on RAN_ConnHdlr { + BSSAP_PROC.call(RAN_register_sccp_cr_without_payload:{self}) { + [] BSSAP_PROC.getreply(RAN_register_sccp_cr_without_payload:{?}) {}; + } +} + #ifdef RAN_EMULATION_RANAP /* expect a IuReleaseCommand; Confirm that; expect SCCP-level N-DISCONNET.ind */ altstep as_iu_release_compl_disc(float t := 5.0) runs on RAN_ConnHdlr {