Vadim Yanitskiy | 95cd935 | 2024-05-31 18:29:17 +0700 | [diff] [blame] | 1 | /* OsmoS1GW (S1AP Gateway) test suite in TTCN-3 |
| 2 | * |
| 3 | * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> |
| 4 | * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> |
| 5 | * |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * Released under the terms of GNU General Public License, Version 2 or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 12 | */ |
| 13 | |
| 14 | module S1GW_Tests { |
| 15 | |
| 16 | import from General_Types all; |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 17 | import from Osmocom_Types all; |
Vadim Yanitskiy | 95cd935 | 2024-05-31 18:29:17 +0700 | [diff] [blame] | 18 | import from Native_Functions all; |
| 19 | import from IPL4asp_Types all; |
| 20 | import from Misc_Helpers all; |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 21 | |
| 22 | import from S1AP_CodecPort all; |
| 23 | import from S1AP_CodecPort_CtrlFunct all; |
Vadim Yanitskiy | 95cd935 | 2024-05-31 18:29:17 +0700 | [diff] [blame] | 24 | import from S1AP_Types all; |
| 25 | import from S1AP_Templates all; |
| 26 | import from S1AP_PDU_Descriptions all; |
| 27 | import from S1AP_IEs all; |
| 28 | import from S1AP_PDU_Contents all; |
| 29 | import from S1AP_Constants all; |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 30 | |
| 31 | import from S1AP_Server all; |
| 32 | |
| 33 | modulepar { |
| 34 | charstring mp_s1gw_ip := "127.0.1.1"; |
| 35 | charstring mp_mme_bind_ip := "127.0.2.10"; |
| 36 | } |
| 37 | |
| 38 | private type record of ConnHdlr ConnHdlrList; |
| 39 | |
| 40 | type component ConnHdlr extends S1APSRV_ConnHdlr { |
| 41 | port S1AP_CODEC_PT S1AP_ENB; |
| 42 | var ConnectionId g_s1ap_conn_id := -1; |
| 43 | }; |
| 44 | |
| 45 | type component test_CT { |
Vadim Yanitskiy | 9ce73fe | 2024-06-12 05:08:36 +0700 | [diff] [blame^] | 46 | timer g_Tguard; |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 47 | var S1AP_Server_CT vc_S1APSRV; |
| 48 | }; |
| 49 | |
Vadim Yanitskiy | 9ce73fe | 2024-06-12 05:08:36 +0700 | [diff] [blame^] | 50 | private altstep as_Tguard() runs on test_CT { |
| 51 | [] g_Tguard.timeout { |
| 52 | Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Tguard timeout"); |
| 53 | } |
| 54 | } |
| 55 | |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 56 | template Global_ENB_ID |
| 57 | ts_Global_ENB_ID(integer enb_id := 0, |
| 58 | OCT3 plmn_id := '00f110'O) := { |
| 59 | pLMNidentity := plmn_id, |
| 60 | eNB_ID := { |
| 61 | macroENB_ID := int2bit(enb_id, 20) |
| 62 | }, |
| 63 | iE_Extensions := omit |
| 64 | } |
| 65 | |
Vadim Yanitskiy | 9ce73fe | 2024-06-12 05:08:36 +0700 | [diff] [blame^] | 66 | function f_init(float Tval := 20.0) runs on test_CT { |
| 67 | g_Tguard.start(Tval); |
| 68 | activate(as_Tguard()); |
| 69 | } |
| 70 | |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 71 | function f_init_s1ap_srv() runs on test_CT { |
| 72 | var S1APSRV_ConnParams cpars := { |
| 73 | local_ip := mp_mme_bind_ip, |
| 74 | local_port := 36412 |
| 75 | }; |
| 76 | |
| 77 | vc_S1APSRV := S1AP_Server_CT.create("S1APSRV-" & testcasename()); |
| 78 | vc_S1APSRV.start(S1AP_Server.main(cpars)); |
| 79 | } |
| 80 | |
| 81 | type union ConnHdlrPars { |
| 82 | integer seed |
| 83 | }; |
| 84 | |
| 85 | type function void_fn(ConnHdlrPars pars) runs on ConnHdlr; |
| 86 | |
| 87 | function f_ConnHdlr_spawn(void_fn fn, ConnHdlrPars pars) |
| 88 | runs on test_CT return ConnHdlr { |
| 89 | var ConnHdlr vc_conn; |
| 90 | |
| 91 | vc_conn := ConnHdlr.create("ConnHdlr-" & testcasename()); |
| 92 | connect(vc_conn:S1AP_CONN, vc_S1APSRV:S1AP_CLIENT); |
| 93 | connect(vc_conn:S1AP_PROC, vc_S1APSRV:S1AP_PROC); |
| 94 | vc_conn.start(derefers(fn)(pars)); |
| 95 | |
| 96 | return vc_conn; |
| 97 | } |
| 98 | |
| 99 | function f_ConnHdlr_connect() runs on ConnHdlr { |
| 100 | var Result res; |
| 101 | |
| 102 | map(self:S1AP_ENB, system:S1AP_CODEC_PT); |
| 103 | res := S1AP_CodecPort_CtrlFunct.f_IPL4_connect(S1AP_ENB, |
| 104 | mp_s1gw_ip, 36412, |
| 105 | "0.0.0.0", 0, -1, |
| 106 | { sctp := valueof(ts_SCTP) }); |
| 107 | if (not ispresent(res.connId)) { |
| 108 | setverdict(fail, "Could not create an S1AP socket, check your configuration"); |
| 109 | mtc.stop; |
| 110 | } |
| 111 | g_s1ap_conn_id := res.connId; |
| 112 | |
| 113 | log("eNB connection established"); |
| 114 | } |
| 115 | |
| 116 | function f_ConnHdlr_disconnect() runs on ConnHdlr { |
| 117 | var Result res; |
| 118 | |
| 119 | S1AP_CodecPort_CtrlFunct.f_IPL4_close(S1AP_ENB, g_s1ap_conn_id, |
| 120 | { sctp := valueof(ts_SCTP) }); |
| 121 | g_s1ap_conn_id := -1; |
| 122 | unmap(self:S1AP_ENB, system:S1AP_CODEC_PT); |
| 123 | |
| 124 | S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_DOWN); |
| 125 | |
| 126 | log("eNB connection closed"); |
| 127 | } |
| 128 | |
| 129 | function f_ConnHdlr_setup(Global_ENB_ID genb_id) runs on ConnHdlr { |
| 130 | var S1AP_PDU pdu; |
| 131 | timer T; |
| 132 | |
| 133 | var SupportedTAs supported_tas_dummy := { |
| 134 | { |
| 135 | tAC := '0000'O, |
| 136 | broadcastPLMNs := { '00f000'O }, |
| 137 | iE_Extensions := omit |
| 138 | } |
| 139 | }; |
| 140 | |
| 141 | S1AP_ENB.send(t_S1AP_Send(g_s1ap_conn_id, |
| 142 | ts_S1AP_SetupReq(genb_id, |
| 143 | supported_tas_dummy, |
| 144 | v32))); |
| 145 | T.start(1.0); |
| 146 | alt { |
| 147 | [] S1AP_CONN.receive(S1APSRV_Event:S1APSRV_EVENT_CONN_UP) { repeat; } |
| 148 | [] S1AP_CONN.receive(tr_S1AP_SetupReq) { |
| 149 | setverdict(pass); |
| 150 | T.stop; |
| 151 | } |
| 152 | [] S1AP_CONN.receive(S1AP_PDU:?) -> value pdu { |
| 153 | setverdict(fail, "Rx unexpected S1AP PDU: ", pdu); |
| 154 | T.stop; |
| 155 | } |
| 156 | [] T.timeout { |
| 157 | setverdict(fail, "Timeout waiting for S1AP SetupReq"); |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | |
| 163 | function f_TC_setup(ConnHdlrPars pars) runs on ConnHdlr { |
| 164 | var Global_ENB_ID genb_id := valueof(ts_Global_ENB_ID(pars.seed)); |
| 165 | |
| 166 | f_ConnHdlr_register(genb_id); |
| 167 | |
| 168 | f_ConnHdlr_connect(); |
| 169 | f_ConnHdlr_setup(genb_id); |
| 170 | f_sleep(0.5); /* keep the connection idle for some time */ |
| 171 | f_ConnHdlr_disconnect(); |
| 172 | |
| 173 | f_ConnHdlr_unregister(genb_id); |
| 174 | } |
| 175 | testcase TC_setup() runs on test_CT { |
| 176 | var ConnHdlrPars pars := { seed := 0 }; |
| 177 | var ConnHdlr vc_conn; |
| 178 | |
Vadim Yanitskiy | 9ce73fe | 2024-06-12 05:08:36 +0700 | [diff] [blame^] | 179 | f_init(); |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 180 | f_init_s1ap_srv(); |
| 181 | |
| 182 | vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars); |
| 183 | vc_conn.done; |
| 184 | } |
| 185 | testcase TC_setup_multi() runs on test_CT { |
| 186 | var ConnHdlrList vc_conns := { }; |
| 187 | |
Vadim Yanitskiy | 9ce73fe | 2024-06-12 05:08:36 +0700 | [diff] [blame^] | 188 | f_init(); |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 189 | f_init_s1ap_srv(); |
| 190 | |
| 191 | for (var integer i := 0; i < 42; i := i + 1) { |
| 192 | var ConnHdlrPars pars := { seed := i }; |
| 193 | var ConnHdlr vc_conn := f_ConnHdlr_spawn(refers(f_TC_setup), pars); |
| 194 | vc_conns := vc_conns & { vc_conn }; |
| 195 | } |
| 196 | |
| 197 | for (var integer i := 0; i < 42; i := i + 1) { |
| 198 | vc_conns[i].done; |
| 199 | } |
| 200 | } |
Vadim Yanitskiy | 95cd935 | 2024-05-31 18:29:17 +0700 | [diff] [blame] | 201 | |
| 202 | control { |
Vadim Yanitskiy | ced53d3 | 2024-06-11 03:19:06 +0700 | [diff] [blame] | 203 | execute( TC_setup() ); |
| 204 | execute( TC_setup_multi() ); |
Vadim Yanitskiy | 95cd935 | 2024-05-31 18:29:17 +0700 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | } |