blob: d442d99927aff3b7bdd54ef6cfdc3b84795a13ed [file] [log] [blame]
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001/*
2 * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <errno.h>
23
24#include <assert.h>
25
26#include <osmocom/core/application.h>
27#include <osmocom/core/select.h>
28#include <osmocom/core/talloc.h>
29
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020030#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
Pau Espin Pedrole2490452018-03-17 01:16:54 +010031
Neels Hofmeyr909e9722017-12-07 03:54:01 +010032#include <osmocom/bsc/abis_rsl.h>
33#include <osmocom/bsc/debug.h>
34#include <osmocom/bsc/bsc_subscriber.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020035#include <osmocom/bsc/lchan_select.h>
36#include <osmocom/bsc/lchan_fsm.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010037#include <osmocom/bsc/handover_decision.h>
38#include <osmocom/bsc/system_information.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020039#include <osmocom/bsc/handover.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010040#include <osmocom/bsc/handover_cfg.h>
41#include <osmocom/bsc/handover_decision_2.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010042#include <osmocom/bsc/bss.h>
Neels Hofmeyr81a49632018-07-24 18:10:05 +020043#include <osmocom/bsc/gsm_08_08.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010044#include <osmocom/bsc/osmo_bsc.h>
Harald Welte3561bd42018-01-28 03:04:16 +010045#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020046#include <osmocom/bsc/timeslot_fsm.h>
47#include <osmocom/bsc/lchan_fsm.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020048#include <osmocom/bsc/handover_fsm.h>
49#include <osmocom/bsc/bsc_msc_data.h>
Pau Espin Pedrol388ed582020-07-15 20:53:16 +020050#include <osmocom/bsc/bts.h>
Neels Hofmeyr86ce1052020-09-18 02:49:32 +020051#include <osmocom/bsc/paging.h>
Neels Hofmeyr909e9722017-12-07 03:54:01 +010052
Neels Hofmeyre3416182018-03-05 05:31:14 +010053void *ctx;
54
Neels Hofmeyr909e9722017-12-07 03:54:01 +010055struct gsm_network *bsc_gsmnet;
56
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020057/* override, requires '-Wl,--wrap=osmo_mgcpc_ep_ci_request'.
Harald Welte3561bd42018-01-28 03:04:16 +010058 * Catch modification of an MGCP connection. */
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020059void __real_osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020060 enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
61 struct osmo_fsm_inst *notify,
62 uint32_t event_success, uint32_t event_failure,
63 void *notify_data);
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +020064void __wrap_osmo_mgcpc_ep_ci_request(struct osmo_mgcpc_ep_ci *ci,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020065 enum mgcp_verb verb, const struct mgcp_conn_peer *verb_info,
66 struct osmo_fsm_inst *notify,
67 uint32_t event_success, uint32_t event_failure,
68 void *notify_data)
Harald Welte3561bd42018-01-28 03:04:16 +010069{
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020070 struct mgcp_conn_peer fake_data = {};
71 /* All MGCP shall be successful */
72 if (!notify)
73 return;
74 osmo_fsm_inst_dispatch(notify, event_success, &fake_data);
Harald Welte3561bd42018-01-28 03:04:16 +010075}
76
Neels Hofmeyr909e9722017-12-07 03:54:01 +010077/* measurement report */
78
79uint8_t meas_rep_ba = 0, meas_rep_valid = 1, meas_valid = 1, meas_multi_rep = 0;
80uint8_t meas_dl_rxlev = 0, meas_dl_rxqual = 0;
81uint8_t meas_ul_rxlev = 0, meas_ul_rxqual = 0;
82uint8_t meas_tx_power_ms = 0, meas_tx_power_bs = 0, meas_ta_ms = 0;
83uint8_t meas_dtx_ms = 0, meas_dtx_bs = 0, meas_nr = 0;
84uint8_t meas_num_nc = 0, meas_rxlev_nc[6], meas_bsic_nc[6], meas_bcch_f_nc[6];
85
86static void gen_meas_rep(struct gsm_lchan *lchan)
87{
88 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
89 struct abis_rsl_dchan_hdr *dh;
90 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
91 uint8_t ulm[3], l1i[2], *buf;
92 struct gsm48_hdr *gh;
93 struct gsm48_meas_res *mr;
94
95 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
96 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
97 dh->c.msg_type = RSL_MT_MEAS_RES;
98 dh->ie_chan = RSL_IE_CHAN_NR;
99 dh->chan_nr = chan_nr;
100
101 msgb_tv_put(msg, RSL_IE_MEAS_RES_NR, meas_nr++);
102
103 ulm[0] = meas_ul_rxlev | (meas_dtx_bs << 7);
104 ulm[1] = meas_ul_rxlev;
105 ulm[2] = (meas_ul_rxqual << 3) | meas_ul_rxqual;
106 msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, sizeof(ulm), ulm);
107
108 msgb_tv_put(msg, RSL_IE_BS_POWER, meas_tx_power_bs);
109
110 l1i[0] = 0;
111 l1i[1] = meas_ta_ms;
112 msgb_tv_fixed_put(msg, RSL_IE_L1_INFO, sizeof(l1i), l1i);
113
114 buf = msgb_put(msg, 3);
115 buf[0] = RSL_IE_L3_INFO;
116 buf[1] = (sizeof(*gh) + sizeof(*mr)) >> 8;
117 buf[2] = (sizeof(*gh) + sizeof(*mr)) & 0xff;
118
119 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
120 mr = (struct gsm48_meas_res *) msgb_put(msg, sizeof(*mr));
121
122 gh->proto_discr = GSM48_PDISC_RR;
123 gh->msg_type = GSM48_MT_RR_MEAS_REP;
124
125 /* measurement results */
126 mr->rxlev_full = meas_dl_rxlev;
127 mr->rxlev_sub = meas_dl_rxlev;
128 mr->rxqual_full = meas_dl_rxqual;
129 mr->rxqual_sub = meas_dl_rxqual;
130 mr->dtx_used = meas_dtx_ms;
131 mr->ba_used = meas_rep_ba;
132 mr->meas_valid = !meas_valid; /* 0 = valid */
133 if (meas_rep_valid) {
134 mr->no_nc_n_hi = meas_num_nc >> 2;
135 mr->no_nc_n_lo = meas_num_nc & 3;
136 } else {
137 /* no results for serving cells */
138 mr->no_nc_n_hi = 1;
139 mr->no_nc_n_lo = 3;
140 }
141 mr->rxlev_nc1 = meas_rxlev_nc[0];
142 mr->rxlev_nc2_hi = meas_rxlev_nc[1] >> 1;
143 mr->rxlev_nc2_lo = meas_rxlev_nc[1] & 1;
144 mr->rxlev_nc3_hi = meas_rxlev_nc[2] >> 2;
145 mr->rxlev_nc3_lo = meas_rxlev_nc[2] & 3;
146 mr->rxlev_nc4_hi = meas_rxlev_nc[3] >> 3;
147 mr->rxlev_nc4_lo = meas_rxlev_nc[3] & 7;
148 mr->rxlev_nc5_hi = meas_rxlev_nc[4] >> 4;
149 mr->rxlev_nc5_lo = meas_rxlev_nc[4] & 15;
150 mr->rxlev_nc6_hi = meas_rxlev_nc[5] >> 5;
151 mr->rxlev_nc6_lo = meas_rxlev_nc[5] & 31;
152 mr->bsic_nc1_hi = meas_bsic_nc[0] >> 3;
153 mr->bsic_nc1_lo = meas_bsic_nc[0] & 7;
154 mr->bsic_nc2_hi = meas_bsic_nc[1] >> 4;
155 mr->bsic_nc2_lo = meas_bsic_nc[1] & 15;
156 mr->bsic_nc3_hi = meas_bsic_nc[2] >> 5;
157 mr->bsic_nc3_lo = meas_bsic_nc[2] & 31;
158 mr->bsic_nc4 = meas_bsic_nc[3];
159 mr->bsic_nc5 = meas_bsic_nc[4];
160 mr->bsic_nc6 = meas_bsic_nc[5];
161 mr->bcch_f_nc1 = meas_bcch_f_nc[0];
162 mr->bcch_f_nc2 = meas_bcch_f_nc[1];
163 mr->bcch_f_nc3 = meas_bcch_f_nc[2];
164 mr->bcch_f_nc4 = meas_bcch_f_nc[3];
165 mr->bcch_f_nc5_hi = meas_bcch_f_nc[4] >> 1;
166 mr->bcch_f_nc5_lo = meas_bcch_f_nc[4] & 1;
167 mr->bcch_f_nc6_hi = meas_bcch_f_nc[5] >> 2;
168 mr->bcch_f_nc6_lo = meas_bcch_f_nc[5] & 3;
169
170 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
171 msg->l2h = (unsigned char *)dh;
172 msg->l3h = (unsigned char *)gh;
173
174 abis_rsl_rcvmsg(msg);
175}
176
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100177enum gsm_phys_chan_config pchan_from_str(const char *str)
178{
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100179 enum gsm_phys_chan_config pchan;
180 if (!strcmp(str, "dyn"))
181 return GSM_PCHAN_TCH_F_TCH_H_PDCH;
182 if (!strcmp(str, "c+s4"))
183 return GSM_PCHAN_CCCH_SDCCH4;
184 if (!strcmp(str, "-"))
185 return GSM_PCHAN_NONE;
186 pchan = gsm_pchan_parse(str);
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100187 if (pchan < 0) {
188 fprintf(stderr, "Invalid timeslot pchan type: %s\n", str);
189 exit(1);
190 }
191 return pchan;
192}
193
194const char * const bts_default_ts[] = {
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100195 "c+s4", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H", "TCH/H", "-",
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100196};
197
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100198static struct gsm_bts *create_bts(int num_trx, const char * const *ts_args)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100199{
Neels Hofmeyr2f58de52020-11-12 22:51:11 +0100200 static int arfcn = 870;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100201 struct gsm_bts *bts;
202 struct e1inp_sign_link *rsl_link;
203 int i;
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100204 int trx_i;
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100205 struct gsm_bts_trx *trx;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100206
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100207 fprintf(stderr, "- Creating BTS %d, %d TRX\n", bsc_gsmnet->num_bts, num_trx);
208 for (trx_i = 0; trx_i < num_trx; trx_i++) {
209 for (i = 0; i < 8; i++)
210 fprintf(stderr, "\t%s", ts_args[8*trx_i + i]);
211 fprintf(stderr, "\n");
212 }
213
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +0700214 bts = bsc_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_UNKNOWN, 0x3f);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100215 if (!bts) {
216 printf("No resource for bts1\n");
217 return NULL;
218 }
219
220 bts->location_area_code = 23;
Neels Hofmeyr2f58de52020-11-12 22:51:11 +0100221 bts->c0->arfcn = arfcn++;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100222
223 bts->codec.efr = 1;
224 bts->codec.hr = 1;
225 bts->codec.amr = 1;
226
Neels Hofmeyre3416182018-03-05 05:31:14 +0100227 rsl_link = talloc_zero(ctx, struct e1inp_sign_link);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100228 rsl_link->trx = bts->c0;
229 bts->c0->rsl_link = rsl_link;
230
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100231 for (trx_i = 0; trx_i < num_trx; trx_i++) {
232 while (!(trx = gsm_bts_trx_num(bts, trx_i)))
233 gsm_bts_trx_alloc(bts);
Neels Hofmeyre3eb67c2020-11-12 22:53:59 +0100234
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100235 trx->mo.nm_state.operational = NM_OPSTATE_ENABLED;
236 trx->mo.nm_state.availability = NM_AVSTATE_OK;
237 trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
238 trx->bb_transc.mo.nm_state.operational = NM_OPSTATE_ENABLED;
239 trx->bb_transc.mo.nm_state.availability = NM_AVSTATE_OK;
240 trx->bb_transc.mo.nm_state.administrative = NM_STATE_UNLOCKED;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100241
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100242 /* 4 full rate and 4 half rate channels */
243 for (i = 0; i < 8; i++) {
244 trx->ts[i].pchan_from_config = pchan_from_str(ts_args[trx_i * 8 + i]);
245 if (trx->ts[i].pchan_from_config == GSM_PCHAN_NONE)
246 continue;
247 trx->ts[i].mo.nm_state.operational = NM_OPSTATE_ENABLED;
248 trx->ts[i].mo.nm_state.availability = NM_AVSTATE_OK;
249 trx->ts[i].mo.nm_state.administrative = NM_STATE_UNLOCKED;
250 }
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200251
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100252 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100253 /* make sure ts->lchans[] get initialized */
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +0100254 osmo_fsm_inst_dispatch(trx->ts[i].fi, TS_EV_RSL_READY, 0);
255 osmo_fsm_inst_dispatch(trx->ts[i].fi, TS_EV_OML_READY, 0);
256
257 /* Unused dyn TS start out as used for PDCH */
258 switch (trx->ts[i].pchan_on_init) {
259 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
260 case GSM_PCHAN_TCH_F_PDCH:
261 trx->ts[i].pchan_is = GSM_PCHAN_PDCH;
262 break;
263 default:
264 break;
265 }
Neels Hofmeyrdd7b7102020-11-12 22:54:58 +0100266 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100267 }
Neels Hofmeyr780f0282020-11-12 22:51:58 +0100268
269 for (i = 0; i < bsc_gsmnet->num_bts; i++) {
270 if (gsm_generate_si(gsm_bts_num(bsc_gsmnet, i), SYSINFO_TYPE_2) <= 0)
271 fprintf(stderr, "Error generating SI2\n");
272 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100273 return bts;
274}
275
Neels Hofmeyr43666542020-11-13 01:12:34 +0100276const char *ts_use_str(struct gsm_bts_trx_ts *ts)
277{
278 switch (ts->pchan_is) {
279 case GSM_PCHAN_CCCH_SDCCH4:
280 return "c+s4";
281
282 case GSM_PCHAN_NONE:
283 return "-";
284
285 case GSM_PCHAN_TCH_F:
286 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED))
287 return "TCH/F";
288 else
289 return "-";
290
291 case GSM_PCHAN_TCH_H:
292 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED)
293 && lchan_state_is(&ts->lchan[1], LCHAN_ST_ESTABLISHED))
294 return "TCH/HH";
295 if (lchan_state_is(&ts->lchan[0], LCHAN_ST_ESTABLISHED))
296 return "TCH/H-";
297 if (lchan_state_is(&ts->lchan[1], LCHAN_ST_ESTABLISHED))
298 return "TCH/-H";
299 return "-";
300
301 default:
302 return gsm_pchan_name(ts->pchan_is);
303 }
304}
305
306bool expect_ts_use(int bts_nr, int trx_nr, const char * const *ts_use)
307{
308 struct gsm_bts *bts;
309 struct gsm_bts_trx *trx;
310 int i;
311 int mismatching_ts = -1;
312 bts = gsm_bts_num(bsc_gsmnet, bts_nr);
313 OSMO_ASSERT(bts);
314 trx = gsm_bts_trx_num(bts, trx_nr);
315 OSMO_ASSERT(trx);
316
317 fprintf(stderr, "Expect TS use:");
318 for (i = 0; i < 8; i++)
319 fprintf(stderr, "\t%s", ts_use[i]);
320 fprintf(stderr, "\n");
321 fprintf(stderr, " Got TS use:");
322
323 for (i = 0; i < 8; i++) {
324 struct gsm_bts_trx_ts *ts = &trx->ts[i];
325 const char *use = ts_use_str(ts);
326
327 fprintf(stderr, "\t%s", use);
328
329 if (!strcmp(ts_use[i], "*"))
330 continue;
331 if (strcmp(ts_use[i], use) && mismatching_ts < 0)
332 mismatching_ts = i;
333 }
334 fprintf(stderr, "\n");
335
336 if (mismatching_ts >= 0) {
337 fprintf(stderr, "Test failed: mismatching TS use in bts %d trx %d ts %d\n",
338 bts_nr, trx_nr, mismatching_ts);
339 return false;
340 }
341 return true;
342}
343
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100344void create_conn(struct gsm_lchan *lchan)
345{
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200346 static unsigned int next_imsi = 0;
347 char imsi[sizeof(lchan->conn->bsub->imsi)];
348 struct gsm_network *net = lchan->ts->trx->bts->network;
Harald Welte3561bd42018-01-28 03:04:16 +0100349 struct gsm_subscriber_connection *conn;
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200350 struct mgcp_client *fake_mgcp_client = (void*)talloc_zero(net, int);
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200351
352 conn = bsc_subscr_con_allocate(net);
Harald Welte3561bd42018-01-28 03:04:16 +0100353
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +0200354 conn->user_plane.mgw_endpoint = osmo_mgcpc_ep_alloc(conn->fi,
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200355 GSCON_EV_FORGET_MGW_ENDPOINT,
Neels Hofmeyrf14aaa42019-04-23 18:37:37 +0200356 fake_mgcp_client,
357 net->mgw.tdefs,
358 "test",
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200359 "fake endpoint");
Alexander Chemeris69ba8be2020-05-10 22:48:01 +0300360 conn->sccp.msc = osmo_msc_data_alloc(net, 0);
Harald Welte3561bd42018-01-28 03:04:16 +0100361
362 lchan->conn = conn;
363 conn->lchan = lchan;
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200364
365 /* Make up a new IMSI for this test, for logging the subscriber */
366 next_imsi ++;
367 snprintf(imsi, sizeof(imsi), "%06u", next_imsi);
Neels Hofmeyr86a1dca2020-09-15 01:03:58 +0000368 lchan->conn->bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, imsi, BSUB_USE_CONN);
Neels Hofmeyrbb6c13b2018-05-24 18:43:58 +0200369
Harald Welte3561bd42018-01-28 03:04:16 +0100370 /* kick the FSM from INIT through to the ACTIVE state */
Neels Hofmeyrd1e7d392020-09-27 23:34:57 +0200371 osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_MO_COMPL_L3, NULL);
Harald Welte3561bd42018-01-28 03:04:16 +0100372 osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_CFM, NULL);
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100373}
374
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100375struct gsm_lchan *lchan_act(struct gsm_lchan *lchan, int full_rate, const char *codec)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100376{
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200377 /* serious hack into osmo_fsm */
378 lchan->fi->state = LCHAN_ST_ESTABLISHED;
379 lchan->ts->fi->state = TS_ST_IN_USE;
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100380 lchan->type = full_rate ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H;
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100381
382 if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
383 lchan->ts->pchan_is = full_rate ? GSM_PCHAN_TCH_F : GSM_PCHAN_TCH_H;
384 if (lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH) {
385 OSMO_ASSERT(full_rate);
386 lchan->ts->pchan_is = GSM_PCHAN_TCH_F;
387 }
388
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200389 LOG_LCHAN(lchan, LOGL_DEBUG, "activated by handover_test.c\n");
390
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100391 create_conn(lchan);
392 if (!strcasecmp(codec, "FR") && full_rate)
393 lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
394 else if (!strcasecmp(codec, "HR") && !full_rate)
395 lchan->tch_mode = GSM48_CMODE_SPEECH_V1;
396 else if (!strcasecmp(codec, "EFR") && full_rate)
397 lchan->tch_mode = GSM48_CMODE_SPEECH_EFR;
Philipp Maiereda6bfa2019-03-11 14:10:26 +0100398 else if (!strcasecmp(codec, "AMR")) {
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100399 lchan->tch_mode = GSM48_CMODE_SPEECH_AMR;
Philipp Maiereda6bfa2019-03-11 14:10:26 +0100400 lchan->activate.info.s15_s0 = 0x0002;
401 } else {
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100402 printf("Given codec unknown\n");
403 exit(EXIT_FAILURE);
404 }
405
406 lchan->conn->codec_list = (struct gsm0808_speech_codec_list){
407 .codec = {
408 { .fi=true, .type=GSM0808_SCT_FR1, },
409 { .fi=true, .type=GSM0808_SCT_FR2, },
410 { .fi=true, .type=GSM0808_SCT_FR3, },
411 { .fi=true, .type=GSM0808_SCT_HR1, },
412 { .fi=true, .type=GSM0808_SCT_HR3, },
413 },
414 .len = 5,
415 };
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100416
417 return lchan;
418}
419
Neels Hofmeyr5531fae2020-11-13 03:43:57 +0100420struct gsm_lchan *create_lchan(struct gsm_bts *bts, int full_rate, const char *codec)
421{
422 struct gsm_lchan *lchan;
423
424 lchan = lchan_select_by_type(bts, (full_rate) ? GSM_LCHAN_TCH_F : GSM_LCHAN_TCH_H);
425 if (!lchan) {
426 printf("No resource for lchan\n");
427 exit(EXIT_FAILURE);
428 }
429
430 return lchan_act(lchan, full_rate, codec);
431}
432
433static void lchan_clear(struct gsm_lchan *lchan)
434{
435 lchan_release(lchan, true, false, 0);
436}
437
438static void ts_clear(struct gsm_bts_trx_ts *ts)
439{
440 struct gsm_lchan *lchan;
441 ts_for_each_lchan(lchan, ts) {
442 if (lchan_state_is(lchan, LCHAN_ST_UNUSED))
443 continue;
444 lchan_clear(lchan);
445 }
446}
447
448bool set_ts_use(int bts_nr, int trx_nr, const char * const *ts_use)
449{
450 struct gsm_bts *bts;
451 struct gsm_bts_trx *trx;
452 int i;
453 bts = gsm_bts_num(bsc_gsmnet, bts_nr);
454 OSMO_ASSERT(bts);
455 trx = gsm_bts_trx_num(bts, trx_nr);
456 OSMO_ASSERT(trx);
457
458 fprintf(stderr, "Setting TS use:");
459 for (i = 0; i < 8; i++)
460 fprintf(stderr, "\t%s", ts_use[i]);
461 fprintf(stderr, "\n");
462
463 for (i = 0; i < 8; i++) {
464 struct gsm_bts_trx_ts *ts = &trx->ts[i];
465 const char *want_use = ts_use[i];
466 const char *is_use = ts_use_str(ts);
467
468 if (!strcmp(want_use, "*"))
469 continue;
470
471 /* If it is already as desired, don't change anything */
472 if (!strcmp(want_use, is_use))
473 continue;
474
475 if (!strcmp(want_use, "TCH/F")) {
476 if (!ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_F)) {
477 printf("Error: bts %d trx %d ts %d cannot be used as TCH/F\n",
478 bts_nr, trx_nr, i);
479 return false;
480 }
481 ts_clear(ts);
482
483 lchan_act(&ts->lchan[0], true, "AMR");
484 } else if (!strcmp(want_use, "TCH/H-")
485 || !strcmp(want_use, "TCH/HH")
486 || !strcmp(want_use, "TCH/-H")) {
487 bool act[2];
488 int j;
489
490 if (!ts_is_capable_of_pchan(ts, GSM_PCHAN_TCH_H)) {
491 printf("Error: bts %d trx %d ts %d cannot be used as TCH/H\n",
492 bts_nr, trx_nr, i);
493 return false;
494 }
495
496 if (ts->pchan_is != GSM_PCHAN_TCH_H)
497 ts_clear(ts);
498
499 act[0] = want_use[4] == 'H';
500 act[1] = want_use[5] == 'H';
501
502 for (j = 0; j < 2; j++) {
503 if (lchan_state_is(&ts->lchan[j], LCHAN_ST_UNUSED)) {
504 if (act[j])
505 lchan_act(&ts->lchan[j], false, "AMR");
506 } else if (!act[j])
507 lchan_clear(&ts->lchan[j]);
508 }
509 } else if (!strcmp(want_use, "-") || !strcmp(want_use, "PDCH")) {
510 ts_clear(ts);
511 }
512 }
513 return true;
514}
515
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100516/* parse channel request */
517
518static int got_chan_req = 0;
519static struct gsm_lchan *chan_req_lchan = NULL;
520
521static int parse_chan_act(struct gsm_lchan *lchan, uint8_t *data)
522{
523 chan_req_lchan = lchan;
524 return 0;
525}
526
527static int parse_chan_rel(struct gsm_lchan *lchan, uint8_t *data)
528{
529 chan_req_lchan = lchan;
530 return 0;
531}
532
533/* parse handover request */
534
535static int got_ho_req = 0;
536static struct gsm_lchan *ho_req_lchan = NULL;
537
538static int parse_ho_command(struct gsm_lchan *lchan, uint8_t *data, int len)
539{
540 struct gsm48_hdr *gh = (struct gsm48_hdr *) data;
541 struct gsm48_ho_cmd *ho = (struct gsm48_ho_cmd *) gh->data;
542 int arfcn;
543 struct gsm_bts *neigh;
544
545 switch (gh->msg_type) {
546 case GSM48_MT_RR_HANDO_CMD:
547 arfcn = (ho->cell_desc.arfcn_hi << 8) | ho->cell_desc.arfcn_lo;
548
549 /* look up trx. since every dummy bts uses different arfcn and
550 * only one trx, it is simple */
551 llist_for_each_entry(neigh, &bsc_gsmnet->bts_list, list) {
552 if (neigh->c0->arfcn != arfcn)
553 continue;
554 ho_req_lchan = lchan;
555 return 0;
556 }
557 break;
558 case GSM48_MT_RR_ASS_CMD:
559 ho_req_lchan = lchan;
560 return 0;
561 break;
562 default:
563 fprintf(stderr, "Error, expecting HO or AS command\n");
564 return -EINVAL;
565 }
566
567 return -1;
568}
569
570/* send channel activation ack */
571static void send_chan_act_ack(struct gsm_lchan *lchan, int act)
572{
573 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
574 struct abis_rsl_dchan_hdr *dh;
575
576 dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
577 dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
578 dh->c.msg_type = (act) ? RSL_MT_CHAN_ACTIV_ACK : RSL_MT_RF_CHAN_REL_ACK;
579 dh->ie_chan = RSL_IE_CHAN_NR;
580 dh->chan_nr = gsm_lchan2chan_nr(lchan);
581
582 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
583 msg->l2h = (unsigned char *)dh;
584
585 abis_rsl_rcvmsg(msg);
586}
587
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200588/* Send RLL Est Ind for SAPI[0] */
589static void send_est_ind(struct gsm_lchan *lchan)
590{
591 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
592 struct abis_rsl_rll_hdr *rh;
593 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
594
595 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
596 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
597 rh->c.msg_type = RSL_MT_EST_IND;
598 rh->ie_chan = RSL_IE_CHAN_NR;
599 rh->chan_nr = chan_nr;
600 rh->ie_link_id = RSL_IE_LINK_IDENT;
601 rh->link_id = 0x00;
602
603 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
604 msg->l2h = (unsigned char *)rh;
605
606 abis_rsl_rcvmsg(msg);
607}
608
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100609/* send handover complete */
610static void send_ho_complete(struct gsm_lchan *lchan, bool success)
611{
612 struct msgb *msg = msgb_alloc_headroom(256, 64, "RSL");
613 struct abis_rsl_rll_hdr *rh;
614 uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
615 uint8_t *buf;
616 struct gsm48_hdr *gh;
617 struct gsm48_ho_cpl *hc;
618
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200619 send_est_ind(lchan);
Neels Hofmeyrac85b342018-07-12 21:23:26 +0200620 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RTP_READY, 0);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +0200621
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100622 rh = (struct abis_rsl_rll_hdr *) msgb_put(msg, sizeof(*rh));
623 rh->c.msg_discr = ABIS_RSL_MDISC_RLL;
624 rh->c.msg_type = RSL_MT_DATA_IND;
625 rh->ie_chan = RSL_IE_CHAN_NR;
626 rh->chan_nr = chan_nr;
627 rh->ie_link_id = RSL_IE_LINK_IDENT;
628 rh->link_id = 0x00;
629
630 buf = msgb_put(msg, 3);
631 buf[0] = RSL_IE_L3_INFO;
632 buf[1] = (sizeof(*gh) + sizeof(*hc)) >> 8;
633 buf[2] = (sizeof(*gh) + sizeof(*hc)) & 0xff;
634
635 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
636 hc = (struct gsm48_ho_cpl *) msgb_put(msg, sizeof(*hc));
637
638 gh->proto_discr = GSM48_PDISC_RR;
639 gh->msg_type =
640 success ? GSM48_MT_RR_HANDO_COMPL : GSM48_MT_RR_HANDO_FAIL;
641
642 msg->dst = lchan->ts->trx->bts->c0->rsl_link;
643 msg->l2h = (unsigned char *)rh;
644 msg->l3h = (unsigned char *)gh;
645
646 abis_rsl_rcvmsg(msg);
647}
648
Neels Hofmeyr1d7473c2018-03-05 21:53:18 +0100649/* override, requires '-Wl,--wrap=abis_rsl_sendmsg'.
650 * Catch RSL messages sent towards the BTS. */
651int __real_abis_rsl_sendmsg(struct msgb *msg);
652int __wrap_abis_rsl_sendmsg(struct msgb *msg)
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100653{
654 struct abis_rsl_dchan_hdr *dh = (struct abis_rsl_dchan_hdr *) msg->data;
655 struct e1inp_sign_link *sign_link = msg->dst;
656 int rc;
657 struct gsm_lchan *lchan = rsl_lchan_lookup(sign_link->trx, dh->chan_nr, &rc);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100658 struct gsm_lchan *other_lchan;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100659
660 if (rc) {
661 printf("rsl_lchan_lookup() failed\n");
662 exit(1);
663 }
664
665 switch (dh->c.msg_type) {
666 case RSL_MT_CHAN_ACTIV:
667 rc = parse_chan_act(lchan, dh->data);
668 if (rc == 0)
669 got_chan_req = 1;
670 break;
671 case RSL_MT_RF_CHAN_REL:
672 rc = parse_chan_rel(lchan, dh->data);
673 if (rc == 0)
674 send_chan_act_ack(chan_req_lchan, 0);
Neels Hofmeyrfb6d9dc2020-11-13 01:13:20 +0100675
676 /* send dyn TS back to PDCH if unused */
677 switch (chan_req_lchan->ts->pchan_on_init) {
678 case GSM_PCHAN_TCH_F_TCH_H_PDCH:
679 case GSM_PCHAN_TCH_F_PDCH:
680 switch (chan_req_lchan->ts->pchan_is) {
681 case GSM_PCHAN_TCH_H:
682 other_lchan = &chan_req_lchan->ts->lchan[
683 (chan_req_lchan == &chan_req_lchan->ts->lchan[0])?
684 1 : 0];
685 if (lchan_state_is(other_lchan, LCHAN_ST_ESTABLISHED))
686 break;
687 /* else fall thru */
688 case GSM_PCHAN_TCH_F:
689 chan_req_lchan->ts->pchan_is = GSM_PCHAN_PDCH;
690 break;
691 default:
692 break;
693 }
694 break;
695 default:
696 break;
697 }
698
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100699 break;
700 case RSL_MT_DATA_REQ:
701 rc = parse_ho_command(lchan, msg->l3h, msgb_l3len(msg));
702 if (rc == 0)
703 got_ho_req = 1;
704 break;
705 case RSL_MT_IPAC_CRCX:
706 break;
Neels Hofmeyr5b1a7d12018-11-06 22:24:07 +0100707 case RSL_MT_DEACTIVATE_SACCH:
708 break;
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100709 default:
710 printf("unknown rsl message=0x%x\n", dh->c.msg_type);
711 }
712 return 0;
713}
714
715/* test cases */
716
717static char *test_case_0[] = {
718 "2",
719
720 "Stay in better cell\n\n"
721 "There are many neighbor cells, but only the current cell is the best\n"
722 "cell, so no handover is performed\n",
723
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100724 "create-n-bts", "7",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100725 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100726 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100727 "meas-rep", "0","0","1","0",
728 "30","0",
729 "6", "0","20", "1","21", "2","18", "3","20", "4","23", "5","19",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100730 "expect-no-chan",
731 NULL
732};
733
734static char *test_case_1[] = {
735 "2",
736
737 "Handover to best better cell\n\n"
738 "The best neighbor cell is selected\n",
739
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100740 "create-n-bts", "7",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100741 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100742 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100743 "meas-rep", "0","0","1","0",
744 "10","0",
745 "6", "0","20", "1","21", "2","18", "3","20", "4","23", "5","19",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100746 "expect-chan", "5", "1",
747 "ack-chan",
748 "expect-ho", "0", "1",
749 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100750 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
751 "expect-ts-use", "5", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100752 NULL
753};
754
755static char *test_case_2[] = {
756 "2",
757
758 "Handover and Assignment must be enabled\n\n"
759 "This test will start with disabled assignment and handover. A\n"
760 "better neighbor cell (assignment enabled) will not be selected and \n"
761 "also no assignment from TCH/H to TCH/F to improve quality. There\n"
762 "will be no handover nor assignment. After enabling assignment on the\n"
763 "current cell, the MS will assign to TCH/F. After enabling handover\n"
764 "in the current cell, but disabling in the neighbor cell, handover\n"
765 "will not be performed, until it is enabled in the neighbor cell too.\n",
766
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100767 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100768 "afs-rxlev-improve", "0", "5",
769 "create-ms", "0", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100770 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100771 "as-enable", "0", "0",
772 "ho-enable", "0", "0",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100773 "meas-rep", "0","0","5","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100774 "expect-no-chan",
775 "as-enable", "0", "1",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100776 "meas-rep", "0","0","5","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100777 "expect-chan", "0", "1",
778 "ack-chan",
779 "expect-ho", "0", "5",
780 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100781 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100782 "ho-enable", "0", "1",
783 "ho-enable", "1", "0",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100784 "meas-rep", "0","0","1","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100785 "expect-no-chan",
786 "ho-enable", "1", "1",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100787 "meas-rep", "0","0","1","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100788 "expect-chan", "1", "1",
789 "ack-chan",
790 "expect-ho", "0", "1",
791 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100792 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
793 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100794 NULL
795};
796
797static char *test_case_3[] = {
798 "2",
799
800 "Penalty timer must not run\n\n"
801 "The MS will try to handover to a better cell, but this will fail.\n"
802 "Even though the cell is still better, handover will not be performed\n"
803 "due to penalty timer after handover failure\n",
804
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100805 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100806 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100807 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100808 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100809 "expect-chan", "1", "1",
810 "ack-chan",
811 "expect-ho", "0", "1",
812 "ho-failed",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100813 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
814 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100815 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100816 "expect-no-chan",
817 NULL
818};
819
820static char *test_case_4[] = {
821 "2",
822
823 "TCH/H keeping with HR codec\n\n"
824 "The MS is using half rate V1 codec, but the better cell is congested\n"
825 "at TCH/H slots. As the congestion is removed, the handover takes\n"
826 "place.\n",
827
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100828 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100829 "set-min-free", "1", "TCH/H", "4",
830 "create-ms", "0", "TCH/H", "HR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100831 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100832 "meas-rep", "0","0","5","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100833 "expect-no-chan",
834 "set-min-free", "1", "TCH/H", "3",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100835 "meas-rep", "0","0","5","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100836 "expect-chan", "1", "5",
837 "ack-chan",
838 "expect-ho", "0", "5",
839 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100840 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
841 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100842 NULL
843};
844
845static char *test_case_5[] = {
846 "2",
847
848 "TCH/F keeping with FR codec\n\n"
849 "The MS is using full rate V1 codec, but the better cell is congested\n"
850 "at TCH/F slots. As the congestion is removed, the handover takes\n"
851 "place.\n",
852
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100853 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100854 "set-min-free", "1", "TCH/F", "4",
855 "create-ms", "0", "TCH/F", "FR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100856 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100857 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100858 "expect-no-chan",
859 "set-min-free", "1", "TCH/F", "3",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100860 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100861 "expect-chan", "1", "1",
862 "ack-chan",
863 "expect-ho", "0", "1",
864 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100865 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
866 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100867 NULL
868};
869
870static char *test_case_6[] = {
871 "2",
872
873 "TCH/F keeping with EFR codec\n\n"
874 "The MS is using full rate V2 codec, but the better cell is congested\n"
875 "at TCH/F slots. As the congestion is removed, the handover takes\n"
876 "place.\n",
877
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100878 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100879 "set-min-free", "1", "TCH/F", "4",
880 "create-ms", "0", "TCH/F", "EFR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100881 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100882 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100883 "expect-no-chan",
884 "set-min-free", "1", "TCH/F", "3",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100885 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100886 "expect-chan", "1", "1",
887 "ack-chan",
888 "expect-ho", "0", "1",
889 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100890 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
891 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100892 NULL
893};
894
895static char *test_case_7[] = {
896 "2",
897
898 "TCH/F to TCH/H changing with AMR codec\n\n"
899 "The MS is using AMR V3 codec, the better cell is congested at TCH/F\n"
900 "slots. The handover is performed to non-congested TCH/H slots.\n",
901
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100902 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100903 "set-min-free", "1", "TCH/F", "4",
904 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100905 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100906 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100907 "expect-chan", "1", "5",
908 "ack-chan",
909 "expect-ho", "0", "1",
910 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100911 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
912 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100913 NULL
914};
915
916static char *test_case_8[] = {
917 "2",
918
919 "No handover to a cell with no slots available\n\n"
920 "If no slot is available, no handover is performed\n",
921
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100922 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100923 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100924 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100925 "create-ms", "1", "TCH/F", "AMR",
926 "create-ms", "1", "TCH/F", "AMR",
927 "create-ms", "1", "TCH/F", "AMR",
928 "create-ms", "1", "TCH/F", "AMR",
929 "create-ms", "1", "TCH/H", "AMR",
930 "create-ms", "1", "TCH/H", "AMR",
931 "create-ms", "1", "TCH/H", "AMR",
932 "create-ms", "1", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100933 "expect-ts-use", "1", "0", "*", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/HH", "TCH/HH", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100934 "meas-rep", "0","0","1","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100935 "expect-no-chan",
936 NULL
937};
938
939static char *test_case_9[] = {
940 "2",
941
942 "No more parallel handovers, if max_unsync_ho is defined\n\n"
943 "There are tree mobiles that want to handover, but only two can do\n"
944 "it at a time, because the maximum number is limited to two.\n",
945
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100946 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100947 "set-max-ho", "1", "2",
948 "create-ms", "0", "TCH/F", "AMR",
949 "create-ms", "0", "TCH/F", "AMR",
950 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100951 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100952 "meas-rep", "0","0","1","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100953 "expect-chan", "1", "1",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100954 "meas-rep", "0","0","2","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100955 "expect-chan", "1", "2",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100956 "meas-rep", "0","0","3","0", "0","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100957 "expect-no-chan",
958 NULL
959};
960
961static char *test_case_10[] = {
962 "2",
963
964 "Hysteresis\n\n"
965 "If neighbor cell is better, handover is only performed if the\n"
Martin Haukea29affd2019-11-13 22:10:41 +0100966 "amount of improvement is greater or equal hyteresis\n",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100967
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100968 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100969 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100970 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100971 "meas-rep", "0","0","1","0", "27","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100972 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100973 "meas-rep", "0","0","1","0", "26","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100974 "expect-chan", "1", "1",
975 "ack-chan",
976 "expect-ho", "0", "1",
977 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100978 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
979 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100980 NULL
981};
982
983static char *test_case_11[] = {
984 "2",
985
986 "No Hysteresis and minimum RX level\n\n"
987 "If current cell's RX level is below mimium level, handover must be\n"
988 "performed, no matter of the hysteresis. First do not perform\n"
989 "handover to better neighbor cell, because the hysteresis is not\n"
990 "met. Second do not perform handover because better neighbor cell is\n"
991 "below minimum RX level. Third perform handover because current cell\n"
992 "is below minimum RX level, even if the better neighbor cell (minimum\n"
993 "RX level reached) does not meet the hysteresis.\n",
994
Neels Hofmeyr4942da82020-11-12 22:58:17 +0100995 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100996 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +0100997 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +0100998 "meas-rep", "0","0","1","0", "10","0", "1","0","11",
Neels Hofmeyr909e9722017-12-07 03:54:01 +0100999 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001000 "meas-rep", "0","0","1","0", "8","0", "1","0","9",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001001 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001002 "meas-rep", "0","0","1","0", "9","0", "1","0","10",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001003 "expect-chan", "1", "1",
1004 "ack-chan",
1005 "expect-ho", "0", "1",
1006 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001007 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1008 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001009 NULL
1010};
1011
1012static char *test_case_12[] = {
1013 "2",
1014
1015 "No handover to congested cell\n\n"
1016 "The better neighbor cell is congested, so no handover is performed.\n"
1017 "After the congestion is over, handover will be performed.\n",
1018
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001019 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001020 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001021 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001022 "set-min-free", "1", "TCH/F", "4",
1023 "set-min-free", "1", "TCH/H", "4",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001024 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001025 "expect-no-chan",
1026 "set-min-free", "1", "TCH/F", "3",
1027 "set-min-free", "1", "TCH/H", "3",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001028 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001029 "expect-chan", "1", "1",
1030 "ack-chan",
1031 "expect-ho", "0", "1",
1032 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001033 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1034 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001035 NULL
1036};
1037
1038static char *test_case_13[] = {
1039 "2",
1040
1041 "Handover to balance congestion\n\n"
1042 "The current and the better cell are congested, so no handover is\n"
1043 "performed. This is because handover would congest the neighbor cell\n"
1044 "more. After congestion raises in the current cell, the handover is\n"
1045 "performed to balance congestion\n",
1046
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001047 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001048 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001049 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001050 "set-min-free", "0", "TCH/F", "4",
1051 "set-min-free", "0", "TCH/H", "4",
1052 "set-min-free", "1", "TCH/F", "4",
1053 "set-min-free", "1", "TCH/H", "4",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001054 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001055 "expect-no-chan",
1056 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001057 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001058 "meas-rep", "0","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001059 "expect-chan", "1", "1",
1060 "ack-chan",
1061 "expect-ho", "0", "1",
1062 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001063 "expect-ts-use", "0", "0", "*", "-", "TCH/F", "-", "-", "-", "-", "-",
1064 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001065 NULL
1066};
1067
1068static char *test_case_14[] = {
1069 "2",
1070
1071 "Handover to congested cell, if RX level is below minimum\n\n"
1072 "The better neighbor cell is congested, so no handover is performed.\n"
1073 "If the RX level of the current cell drops below minimum acceptable\n"
1074 "level, the handover is performed.\n",
1075
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001076 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001077 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001078 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001079 "set-min-free", "1", "TCH/F", "4",
1080 "set-min-free", "1", "TCH/H", "4",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001081 "meas-rep", "0","0","1","0", "10","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001082 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001083 "meas-rep", "0","0","1","0", "9","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001084 "expect-chan", "1", "1",
1085 "ack-chan",
1086 "expect-ho", "0", "1",
1087 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001088 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1089 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001090 NULL
1091};
1092
1093static char *test_case_15[] = {
1094 "2",
1095
1096 "Handover to cell with worse RXLEV, if RXQUAL is below minimum\n\n"
1097 "The neighbor cell has worse RXLEV, so no handover is performed.\n"
1098 "If the RXQUAL of the current cell drops below minimum acceptable\n"
1099 "level, the handover is performed. It is also required that 10\n"
1100 "reports are received, before RXQUAL is checked.\n",
1101 /* (See also test 28, which tests for RXQUAL triggering HO to congested cell.) */
1102 /* TODO: bad RXQUAL may want to prefer assignment within the same cell to avoid interference.
Martin Haukea29affd2019-11-13 22:10:41 +01001103 * See Performance Enhancements in a Frequency Hopping GSM Network (Nielsen Wigard 2002), Chapter
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001104 * 2.1.1, "Interference" in the list of triggers on p.157. */
1105
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001106 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001107 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001108 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001109 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001110 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001111 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001112 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001113 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001114 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001115 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001116 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001117 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001118 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001119 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001120 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001121 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001122 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001123 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001124 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001125 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001126 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001127 "meas-rep", "0","0","1","0", "40","6", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001128 "expect-chan", "1", "1",
1129 "ack-chan",
1130 "expect-ho", "0", "1",
1131 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001132 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1133 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001134 NULL
1135};
1136
1137static char *test_case_16[] = {
1138 "2",
1139
1140 "Handover due to maximum TA exceeded\n\n"
1141 "The MS in the current (best) cell has reached maximum allowed timing\n"
1142 "advance. No handover is performed until the timing advance exceeds\n"
1143 "it. The originating cell is still the best, but no handover is\n"
1144 "performed back to that cell, because the penalty timer (due to\n"
1145 "maximum allowed timing advance) is running.\n",
1146
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001147 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001148 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001149 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001150 "set-max-ta", "0", "5", /* of cell */
1151 "set-ta", "0", "5", /* of ms */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001152 "meas-rep", "0","0","1","0", "30","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001153 "expect-no-chan",
1154 "set-ta", "0", "6", /* of ms */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001155 "meas-rep", "0","0","1","0", "30","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001156 "expect-chan", "1", "1",
1157 "ack-chan",
1158 "expect-ho", "0", "1",
1159 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001160 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1161 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001162 "meas-rep", "1","0","1","0", "20","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001163 "expect-no-chan",
1164 NULL
1165};
1166
1167static char *test_case_17[] = {
1168 "2",
1169
1170 "Congestion check: No congestion\n\n"
1171 "Three cells have different number of used slots, but there is no\n"
1172 "congestion in any of these cells. No handover is performed.\n",
1173
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001174 "create-n-bts", "3",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001175 "set-min-free", "0", "TCH/F", "2",
1176 "set-min-free", "0", "TCH/H", "2",
1177 "set-min-free", "1", "TCH/F", "2",
1178 "set-min-free", "1", "TCH/H", "2",
1179 "set-min-free", "2", "TCH/F", "2",
1180 "set-min-free", "2", "TCH/H", "2",
1181 "create-ms", "0", "TCH/F", "AMR",
1182 "create-ms", "0", "TCH/F", "AMR",
1183 "create-ms", "0", "TCH/H", "AMR",
1184 "create-ms", "0", "TCH/H", "AMR",
1185 "create-ms", "1", "TCH/F", "AMR",
1186 "create-ms", "1", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001187 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/HH", "-", "-",
1188 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001189 "meas-rep", "0","0","1","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001190 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001191 "meas-rep", "0","0","2","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001192 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001193 "meas-rep", "0","0","5","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001194 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001195 "meas-rep", "0","0","5","1", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001196 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001197 "meas-rep", "1","0","1","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001198 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001199 "meas-rep", "1","0","5","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001200 "expect-no-chan",
1201 "congestion-check",
1202 "expect-no-chan",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001203 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/HH", "-", "-",
1204 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001205 NULL
1206};
1207
1208static char *test_case_18[] = {
1209 "2",
1210
1211 "Congestion check: One out of three cells is congested\n\n"
1212 "Three cells have different number of used slots, but there is\n"
1213 "congestion at TCH/F in the first cell. Handover is performed with\n"
1214 "the best candidate.\n",
1215
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001216 "create-n-bts", "3",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001217 "set-min-free", "0", "TCH/F", "2",
1218 "set-min-free", "0", "TCH/H", "2",
1219 "set-min-free", "1", "TCH/F", "2",
1220 "set-min-free", "1", "TCH/H", "2",
1221 "set-min-free", "2", "TCH/F", "2",
1222 "set-min-free", "2", "TCH/H", "2",
1223 "create-ms", "0", "TCH/F", "AMR",
1224 "create-ms", "0", "TCH/F", "AMR",
1225 "create-ms", "0", "TCH/F", "AMR",
1226 "create-ms", "0", "TCH/H", "AMR",
1227 "create-ms", "0", "TCH/H", "AMR",
1228 "create-ms", "1", "TCH/F", "AMR",
1229 "create-ms", "1", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001230 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "-", "TCH/HH", "-", "-",
1231 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001232 "meas-rep", "0","0","1","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001233 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001234 "meas-rep", "0","0","2","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001235 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001236 "meas-rep", "0","0","3","0", "30","0", "2","0","21","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001237 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001238 "meas-rep", "0","0","5","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001239 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001240 "meas-rep", "0","0","5","1", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001241 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001242 "meas-rep", "1","0","1","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001243 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001244 "meas-rep", "1","0","5","0", "30","0", "2","0","20","1","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001245 "expect-no-chan",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001246 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "-", "TCH/HH", "-", "-",
1247 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001248 "congestion-check",
1249 "expect-chan", "1", "2",
1250 "ack-chan",
Neels Hofmeyr72d64e72020-11-16 18:07:31 +01001251 "expect-ho", "0", "3", /* best candidate is MS 2 at BTS 0, TS 3 */
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001252 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001253 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/HH", "-", "-",
1254 "expect-ts-use", "1", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001255 NULL
1256};
1257
1258static char *test_case_19[] = {
1259 "2",
1260
1261 "Congestion check: Balancing over congested cells\n\n"
Neels Hofmeyr1336d942020-08-10 21:13:55 +02001262 "Two cells are congested, but the second cell is less congested.\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001263 "Handover is performed to solve the congestion.\n",
1264
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001265 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001266 "set-min-free", "0", "TCH/F", "4",
1267 "set-min-free", "1", "TCH/F", "4",
1268 "create-ms", "0", "TCH/F", "FR",
1269 "create-ms", "0", "TCH/F", "FR",
1270 "create-ms", "0", "TCH/F", "FR",
1271 "create-ms", "1", "TCH/F", "FR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001272 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "-", "-", "-", "-",
1273 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001274 "meas-rep", "0","0","1","0", "30","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001275 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001276 "meas-rep", "0","0","2","0", "30","0", "1","0","21",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001277 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001278 "meas-rep", "0","0","3","0", "30","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001279 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001280 "meas-rep", "1","0","1","0", "30","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001281 "expect-no-chan",
1282 "congestion-check",
1283 "expect-chan", "1", "2",
1284 "ack-chan",
1285 "expect-ho", "0", "2", /* best candidate is MS 1 at BTS 0, TS 2 */
1286 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001287 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "TCH/F", "-", "-", "-", "-",
1288 "expect-ts-use", "1", "0", "*", "TCH/F", "TCH/F", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001289 NULL
1290};
1291
1292static char *test_case_20[] = {
1293 "2",
1294
1295 "Congestion check: Solving congestion by handover TCH/F -> TCH/H\n\n"
1296 "Two BTS, one MS in the first congested BTS must handover to\n"
1297 "non-congested TCH/H of second BTS, in order to solve congestion\n",
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001298 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001299 "set-min-free", "0", "TCH/F", "4",
1300 "set-min-free", "0", "TCH/H", "4",
1301 "set-min-free", "1", "TCH/F", "4",
1302 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001303 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001304 "meas-rep", "0","0","1","0", "30","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001305 "expect-no-chan",
1306 "congestion-check",
1307 "expect-chan", "1", "5",
1308 "ack-chan",
1309 "expect-ho", "0", "1",
1310 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001311 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1312 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001313 NULL
1314};
1315
1316static char *test_case_21[] = {
1317 "2",
1318
1319 "Congestion check: Balancing congestion by handover TCH/F -> TCH/H\n\n"
1320 "Two BTS, one MS in the first congested BTS must handover to\n"
1321 "less-congested TCH/H of second BTS, in order to balance congestion\n",
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001322 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001323 "set-min-free", "0", "TCH/F", "4",
1324 "set-min-free", "0", "TCH/H", "4",
1325 "set-min-free", "1", "TCH/F", "4",
1326 "set-min-free", "1", "TCH/H", "4",
1327 "create-ms", "0", "TCH/F", "AMR",
1328 "create-ms", "0", "TCH/F", "AMR",
1329 "create-ms", "0", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001330 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001331 "meas-rep", "0","0","1","0", "30","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001332 "expect-no-chan",
1333 "congestion-check",
1334 "expect-chan", "1", "1",
1335 "ack-chan",
1336 "expect-ho", "0", "1",
1337 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001338 "expect-ts-use", "0", "0", "*", "-", "TCH/F", "-", "-", "TCH/H-", "-", "-",
1339 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001340 NULL
1341};
1342
1343static char *test_case_22[] = {
1344 "2",
1345
1346 "Congestion check: Upgrading worst candidate from TCH/H -> TCH/F\n\n"
1347 "There is only one BTS. The TCH/H slots are congested. Since\n"
1348 "assignment is performed to less-congested TCH/F, the candidate with\n"
1349 "the worst RX level is chosen.\n",
1350
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001351 "create-n-bts", "1",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001352 "set-min-free", "0", "TCH/F", "4",
1353 "set-min-free", "0", "TCH/H", "4",
1354 "create-ms", "0", "TCH/H", "AMR",
1355 "create-ms", "0", "TCH/H", "AMR",
1356 "create-ms", "0", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001357 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "TCH/HH", "TCH/H-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001358 "meas-rep", "0","0","5","0", "30","0", "0",
1359 "meas-rep", "0","0","5","1", "34","0", "0",
1360 "meas-rep", "0","0","6","0", "20","0", "0",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001361 "expect-no-chan",
1362 "congestion-check",
1363 "expect-chan", "0", "1",
1364 "ack-chan",
1365 "expect-ho", "0", "6",
1366 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001367 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "TCH/HH", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001368 NULL
1369};
1370
1371static char *test_case_23[] = {
1372 "2",
1373
1374 "Story: 'A neighbor is your friend'\n",
1375
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001376 "create-n-bts", "3",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001377
1378 "print",
1379 "Andreas is driving along the coast, on a sunny june afternoon.\n"
1380 "Suddenly he is getting a call from his friend and neighbor Axel.\n"
1381 "\n"
1382 "What happens: Two MS are created, #0 for Axel, #1 for Andreas.",
1383 /* Axel */
1384 "create-ms", "2", "TCH/F", "AMR",
1385 /* andreas */
1386 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001387 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
1388 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1389 "expect-ts-use", "2", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001390 "meas-rep", "0","0","1","0", "40","0", "1","0","30",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001391 "expect-no-chan",
1392
1393 "print",
1394 "Axel asks Andreas if he would like to join them for a barbecue.\n"
1395 "Axel's house is right in the neighborhood and the weather is fine.\n"
1396 "Andreas agrees, so he drives to a close store to buy some barbecue\n"
1397 "skewers.\n"
1398 "\n"
1399 "What happens: While driving, a different cell (mounted atop the\n"
1400 "store) becomes better.",
1401 /* drive to bts 1 */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001402 "meas-rep", "0","0","1","0", "20","0", "1","0","35",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001403 "expect-chan", "1", "1",
1404 "ack-chan",
1405 "expect-ho", "0", "1",
1406 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001407 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1408 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
1409 "expect-ts-use", "2", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001410
1411 "print",
1412 "While Andreas is walking into the store, Axel asks, if he could also\n"
1413 "bring some beer. Andreas has problems understanding him: \"I have a\n"
1414 "bad reception here. The cell tower is right atop the store, but poor\n"
1415 "coverage inside. Can you repeat please?\"\n"
1416 "\n"
1417 "What happens: Inside the store the close cell is so bad, that\n"
1418 "handover back to the previous cell is required.",
1419 /* bts 1 becomes bad, so bts 0 helps out */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001420 "meas-rep", "1","0","1","0", "5","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001421 "expect-chan", "0", "1",
1422 "ack-chan",
1423 "expect-ho", "1", "1",
1424 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001425 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
1426 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1427 "expect-ts-use", "2", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001428
1429 "print",
1430 "After Andreas bought skewers and beer, he leaves the store.\n"
1431 "\n"
1432 "What happens: Outside the store the close cell is better again, so\n"
1433 "handover back to the that cell is performed.",
1434 /* bts 1 becomes better again */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001435 "meas-rep", "0","0","1","0", "20","0", "1","0","35",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001436 "expect-chan", "1", "1",
1437 "ack-chan",
1438 "expect-ho", "0", "1",
1439 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001440 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1441 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
1442 "expect-ts-use", "2", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001443
1444 "print",
1445 /* bts 2 becomes better */
1446 "Andreas drives down to the lake where Axel's house is.\n"
1447 "\n"
1448 "What happens: There is a small cell at Axel's house, which becomes\n"
1449 "better, because the current cell has no good comverage at the lake.",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001450 "meas-rep", "1","0","1","0", "14","0", "2","0","2","1","63",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001451 "expect-chan", "2", "2",
1452 "ack-chan",
1453 "expect-ho", "1", "1",
1454 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001455 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1456 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1457 "expect-ts-use", "2", "0", "*", "TCH/F", "TCH/F", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001458
1459 "print",
1460 "Andreas wonders why he still has good radio coverage: \"Last time it\n"
1461 "was so bad\". Axel says: \"I installed a pico cell in my house,\n"
1462 "now we can use our mobile phones down here at the lake.\"",
1463
1464 NULL
1465};
1466
1467static char *test_case_24[] = {
1468 "2",
1469 "No (or not enough) measurements for handover\n\n"
1470 "Do not solve congestion in cell, because there is no measurement.\n"
Martin Haukea29affd2019-11-13 22:10:41 +01001471 "As soon as enough measurements available (1 in our case), perform\n"
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001472 "handover. Afterwards the old cell becomes congested and the new\n"
1473 "cell is not. Do not perform handover until new measurements are\n"
1474 "received.\n",
1475
1476 /* two cells, first in congested, but no handover */
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001477 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001478 "set-min-free", "0", "TCH/F", "4",
1479 "set-min-free", "0", "TCH/H", "4",
1480 "create-ms", "0", "TCH/F", "AMR",
1481 "congestion-check",
1482 "expect-no-chan",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001483 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001484
1485 /* send measurement and trigger congestion check */
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001486 "meas-rep", "0","0","1","0", "20","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001487 "expect-no-chan",
1488 "congestion-check",
1489 "expect-chan", "1", "1",
1490 "ack-chan",
1491 "expect-ho", "0", "1",
1492 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001493 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1494 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001495
1496 /* congest the first cell and remove congestion from second cell */
1497 "set-min-free", "0", "TCH/F", "0",
1498 "set-min-free", "0", "TCH/H", "0",
1499 "set-min-free", "1", "TCH/F", "4",
1500 "set-min-free", "1", "TCH/H", "4",
1501
1502 /* no handover until measurements applied */
1503 "congestion-check",
1504 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001505 "meas-rep", "1","0","1","0", "20","0", "1","0","20",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001506 "expect-no-chan",
1507 "congestion-check",
1508 "expect-chan", "0", "1",
1509 "ack-chan",
1510 "expect-ho", "1", "1",
1511 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001512 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
1513 "expect-ts-use", "1", "0", "*", "-", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001514 NULL
1515};
1516
1517static char *test_case_25[] = {
1518 "1",
1519
1520 "Stay in better cell\n\n"
1521 "There are many neighbor cells, but only the current cell is the best\n"
1522 "cell, so no handover is performed\n",
1523
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001524 "create-n-bts", "7",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001525 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001526 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001527 "meas-rep", "0","0","1","0", "30","0",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001528 "6","0","20","1","21","2","18","3","20","4","23","5","19",
1529 "expect-no-chan",
1530 NULL
1531};
1532
1533static char *test_case_26[] = {
1534 "1",
1535
1536 "Handover to best better cell\n\n"
1537 "The best neighbor cell is selected\n",
1538
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001539 "create-n-bts", "7",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001540 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001541 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001542 "meas-rep", "0","0","1","0", "10","0",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001543 "6","0","20","1","21","2","18","3","20","4","23","5","19",
1544 "expect-chan", "5", "1",
1545 "ack-chan",
1546 "expect-ho", "0", "1",
1547 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001548 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1549 "expect-ts-use", "5", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001550 NULL
1551};
1552
1553static char *test_case_27[] = {
1554 "2",
1555
1556 "Congestion check: Upgrading worst candidate from TCH/H -> TCH/F\n\n"
1557 "There is only one BTS. The TCH/H slots are congested. Since\n"
1558 "assignment is performed to less-congested TCH/F, the candidate with\n"
1559 "the worst RX level is chosen. (So far like test 22.)\n"
1560 "After that, trigger more congestion checks to ensure stability.\n",
1561
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001562 "create-n-bts", "1",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001563 "set-min-free", "0", "TCH/F", "2",
1564 "set-min-free", "0", "TCH/H", "4",
1565 "create-ms", "0", "TCH/H", "AMR",
1566 "create-ms", "0", "TCH/H", "AMR",
1567 "create-ms", "0", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001568 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "TCH/HH", "TCH/H-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001569 "meas-rep", "0","0","5","0", "30","0", "0",
1570 "meas-rep", "0","0","5","1", "34","0", "0",
1571 "meas-rep", "0","0","6","0", "20","0", "0",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001572 "expect-no-chan",
1573 "congestion-check",
1574 "expect-chan", "0", "1",
1575 "ack-chan",
1576 "expect-ho", "0", "6",
1577 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001578 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "TCH/HH", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001579 "congestion-check",
1580 "expect-chan", "0", "2",
1581 "ack-chan",
1582 "expect-ho", "0", "5",
1583 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001584 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/-H", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001585 "congestion-check",
1586 "expect-no-chan",
1587 "congestion-check",
1588 "expect-no-chan",
1589 NULL
1590};
1591
1592static char *test_case_28[] = {
1593 "2",
1594
1595 "Handover to congested cell, if RX quality is below minimum\n\n"
1596 "The better neighbor cell is congested, so no handover is performed.\n"
1597 "If the RX quality of the current cell drops below minimum acceptable\n"
1598 "level, the handover is performed. It is also required that 10\n"
1599 "resports are received, before RX quality is checked.\n",
1600
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001601 "create-n-bts", "2",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001602 "create-ms", "0", "TCH/F", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001603 "expect-ts-use", "0", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001604 "set-min-free", "1", "TCH/F", "4",
1605 "set-min-free", "1", "TCH/H", "4",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001606 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001607 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001608 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001609 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001610 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001611 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001612 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001613 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001614 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001615 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001616 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001617 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001618 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001619 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001620 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001621 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001622 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001623 "expect-no-chan",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001624 "meas-rep", "0","0","1","0", "30","6", "1","0","40",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001625 "expect-chan", "1", "1",
1626 "ack-chan",
1627 "expect-ho", "0", "1",
1628 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001629 "expect-ts-use", "0", "0", "*", "-", "-", "-", "-", "-", "-", "-",
1630 "expect-ts-use", "1", "0", "*", "TCH/F", "-", "-", "-", "-", "-", "-",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001631 NULL
1632};
1633
Neels Hofmeyr7b2b4302020-08-02 02:50:17 +02001634static char *test_case_29[] = {
1635 "2",
1636
1637 "Congestion check: Balancing congestion by handover TCH/F -> TCH/H\n\n"
1638 "One BTS, and TCH/F are considered congested, TCH/H are not.\n"
1639 ,
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001640 "create-n-bts", "1",
Neels Hofmeyr7b2b4302020-08-02 02:50:17 +02001641 "set-min-free", "0", "TCH/F", "3",
1642 "set-min-free", "0", "TCH/H", "0",
1643 "create-ms", "0", "TCH/F", "AMR",
1644 "create-ms", "0", "TCH/F", "AMR",
1645 "create-ms", "0", "TCH/H", "AMR",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001646 "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "-", "-", "TCH/H-", "-", "-",
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001647 "meas-rep", "0","0","1","0", "30","0", "1","0","30",
Neels Hofmeyr7b2b4302020-08-02 02:50:17 +02001648 "expect-no-chan",
1649 "congestion-check",
1650 "expect-chan", "0", "5",
1651 "ack-chan",
1652 "expect-ho", "0", "1",
1653 "ho-complete",
Neels Hofmeyr43666542020-11-13 01:12:34 +01001654 "expect-ts-use", "0", "0", "*", "-", "TCH/F", "-", "-", "TCH/HH", "-", "-",
Neels Hofmeyr7b2b4302020-08-02 02:50:17 +02001655 NULL
1656};
1657
1658
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001659static char **test_cases[] = {
1660 test_case_0,
1661 test_case_1,
1662 test_case_2,
1663 test_case_3,
1664 test_case_4,
1665 test_case_5,
1666 test_case_6,
1667 test_case_7,
1668 test_case_8,
1669 test_case_9,
1670 test_case_10,
1671 test_case_11,
1672 test_case_12,
1673 test_case_13,
1674 test_case_14,
1675 test_case_15,
1676 test_case_16,
1677 test_case_17,
1678 test_case_18,
1679 test_case_19,
1680 test_case_20,
1681 test_case_21,
1682 test_case_22,
1683 test_case_23,
1684 test_case_24,
1685 test_case_25,
1686 test_case_26,
1687 test_case_27,
1688 test_case_28,
Neels Hofmeyr7b2b4302020-08-02 02:50:17 +02001689 test_case_29,
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001690};
1691
1692static const struct log_info_cat log_categories[] = {
1693 [DHO] = {
1694 .name = "DHO",
1695 .description = "Hand-Over Process",
1696 .color = "\033[1;38m",
1697 .enabled = 1, .loglevel = LOGL_DEBUG,
1698 },
1699 [DHODEC] = {
1700 .name = "DHODEC",
1701 .description = "Hand-Over Decision",
1702 .color = "\033[1;38m",
1703 .enabled = 1, .loglevel = LOGL_DEBUG,
1704 },
1705 [DMEAS] = {
1706 .name = "DMEAS",
1707 .description = "Radio Measurement Processing",
1708 .enabled = 1, .loglevel = LOGL_DEBUG,
1709 },
1710 [DREF] = {
1711 .name = "DREF",
1712 .description = "Reference Counting",
1713 .enabled = 1, .loglevel = LOGL_DEBUG,
1714 },
1715 [DRSL] = {
1716 .name = "DRSL",
Keithd925c7c2018-04-16 13:40:07 +02001717 .description = "A-bis Radio Signalling Link (RSL)",
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001718 .color = "\033[1;35m",
1719 .enabled = 1, .loglevel = LOGL_DEBUG,
1720 },
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001721 [DRR] = {
1722 .name = "DRR",
1723 .description = "RR",
1724 .color = "\033[1;35m",
1725 .enabled = 1, .loglevel = LOGL_DEBUG,
1726 },
1727 [DRLL] = {
1728 .name = "DRLL",
1729 .description = "RLL",
1730 .color = "\033[1;35m",
1731 .enabled = 1, .loglevel = LOGL_DEBUG,
1732 },
Harald Welte3561bd42018-01-28 03:04:16 +01001733 [DMSC] = {
1734 .name = "DMSC",
1735 .description = "Mobile Switching Center",
1736 .enabled = 1, .loglevel = LOGL_DEBUG,
1737 },
Neels Hofmeyr3c5612f2018-07-11 19:53:39 +02001738 [DCHAN] = {
1739 .name = "DCHAN",
1740 .description = "lchan FSM",
1741 .color = "\033[1;32m",
1742 .enabled = 1, .loglevel = LOGL_DEBUG,
1743 },
1744 [DTS] = {
1745 .name = "DTS",
1746 .description = "timeslot FSM",
1747 .color = "\033[1;31m",
1748 .enabled = 1, .loglevel = LOGL_DEBUG,
1749 },
1750 [DAS] = {
1751 .name = "DAS",
1752 .description = "assignment FSM",
1753 .color = "\033[1;33m",
1754 .enabled = 1, .loglevel = LOGL_DEBUG,
1755 },
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001756};
1757
1758const struct log_info log_info = {
1759 .cat = log_categories,
1760 .num_cat = ARRAY_SIZE(log_categories),
1761};
1762
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001763struct gsm_bts *bts_by_num_str(const char *num_str)
1764{
1765 struct gsm_bts *bts = gsm_bts_num(bsc_gsmnet, atoi(num_str));
1766 OSMO_ASSERT(bts);
1767 return bts;
1768}
1769
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001770int main(int argc, char **argv)
1771{
1772 char **test_case;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001773 int i;
Neels Hofmeyr958f2592018-05-27 01:26:31 +02001774 int algorithm;
Neels Hofmeyr00727552018-02-21 14:33:15 +01001775 int test_case_i;
1776 int last_test_i;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001777
Neels Hofmeyre3416182018-03-05 05:31:14 +01001778 ctx = talloc_named_const(NULL, 0, "handover_test");
1779 msgb_talloc_ctx_init(ctx, 0);
1780
Neels Hofmeyr00727552018-02-21 14:33:15 +01001781 test_case_i = argc > 1? atoi(argv[1]) : -1;
1782 last_test_i = ARRAY_SIZE(test_cases) - 1;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001783
Neels Hofmeyr00727552018-02-21 14:33:15 +01001784 if (test_case_i < 0 || test_case_i > last_test_i) {
1785 for (i = 0; i <= last_test_i; i++) {
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001786 printf("Test #%d (algorithm %s):\n%s\n", i,
1787 test_cases[i][0], test_cases[i][1]);
1788 }
Neels Hofmeyr00727552018-02-21 14:33:15 +01001789 printf("\nPlease specify test case number 0..%d\n", last_test_i);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001790 return EXIT_FAILURE;
1791 }
1792
Neels Hofmeyre3416182018-03-05 05:31:14 +01001793 osmo_init_logging2(ctx, &log_info);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001794
1795 log_set_print_category(osmo_stderr_target, 1);
1796 log_set_print_category_hex(osmo_stderr_target, 0);
1797 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001798 osmo_fsm_log_addr(false);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001799
Neels Hofmeyr958f2592018-05-27 01:26:31 +02001800 bsc_network_alloc();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001801 if (!bsc_gsmnet)
1802 exit(1);
1803
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001804 ts_fsm_init();
1805 lchan_fsm_init();
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02001806 bsc_subscr_conn_fsm_init();
1807 handover_fsm_init();
1808
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001809 ho_set_algorithm(bsc_gsmnet->ho, 2);
1810 ho_set_ho_active(bsc_gsmnet->ho, true);
1811 ho_set_hodec2_as_active(bsc_gsmnet->ho, true);
1812 ho_set_hodec2_min_rxlev(bsc_gsmnet->ho, -100);
1813 ho_set_hodec2_rxlev_avg_win(bsc_gsmnet->ho, 1);
1814 ho_set_hodec2_rxlev_neigh_avg_win(bsc_gsmnet->ho, 1);
1815 ho_set_hodec2_rxqual_avg_win(bsc_gsmnet->ho, 10);
1816 ho_set_hodec2_pwr_hysteresis(bsc_gsmnet->ho, 3);
1817 ho_set_hodec2_pwr_interval(bsc_gsmnet->ho, 1);
1818 ho_set_hodec2_afs_bias_rxlev(bsc_gsmnet->ho, 0);
1819 ho_set_hodec2_min_rxqual(bsc_gsmnet->ho, 5);
1820 ho_set_hodec2_afs_bias_rxqual(bsc_gsmnet->ho, 0);
1821 ho_set_hodec2_max_distance(bsc_gsmnet->ho, 9999);
1822 ho_set_hodec2_ho_max(bsc_gsmnet->ho, 9999);
1823 ho_set_hodec2_penalty_max_dist(bsc_gsmnet->ho, 300);
1824 ho_set_hodec2_penalty_failed_ho(bsc_gsmnet->ho, 60);
1825 ho_set_hodec2_penalty_failed_as(bsc_gsmnet->ho, 60);
1826
Vadim Yanitskiy4f3a6412020-05-31 01:56:20 +07001827 /* We don't really need any specific model here */
1828 bts_model_unknown_init();
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001829
Neels Hofmeyr00727552018-02-21 14:33:15 +01001830 test_case = test_cases[test_case_i];
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001831
1832 fprintf(stderr, "--------------------\n");
1833 fprintf(stderr, "Performing the following test %d (algorithm %s):\n%s",
Neels Hofmeyr00727552018-02-21 14:33:15 +01001834 test_case_i, test_case[0], test_case[1]);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001835 algorithm = atoi(test_case[0]);
1836 test_case += 2;
1837 fprintf(stderr, "--------------------\n");
1838
1839 /* Disable the congestion check timer, we will trigger manually. */
1840 bsc_gsmnet->hodec2.congestion_check_interval_s = 0;
1841
1842 handover_decision_1_init();
1843 hodec2_init(bsc_gsmnet);
1844
1845 while (*test_case) {
Neels Hofmeyr4942da82020-11-12 22:58:17 +01001846 if (!strcmp(*test_case, "create-n-bts")) {
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001847 int n = atoi(test_case[1]);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001848 for (i = 0; i < n; i++)
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001849 create_bts(1, bts_default_ts);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001850 test_case += 2;
1851 } else
Neels Hofmeyrcfbf11f2020-11-12 23:12:48 +01001852 if (!strcmp(*test_case, "create-bts")) {
1853 /* new BTS with one TRX:
1854 * "create-bts", "1", "CCCH+SDCCH4", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H", "TCH/H", "PDCH",
1855 *
1856 * new BTS with two TRX:
1857 * "create-bts", "2", "CCCH+SDCCH4", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H", "TCH/H", "PDCH",
1858 * "SDCCH8", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H", "TCH/H", "PDCH",
1859 */
1860 int num_trx = atoi(test_case[1]);
1861 const char * const * ts_cfg = (void*)&test_case[2];
1862 create_bts(num_trx, ts_cfg);
1863 test_case += 2 + 8 * num_trx;
1864 } else
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001865 if (!strcmp(*test_case, "as-enable")) {
1866 fprintf(stderr, "- Set assignment enable state at "
1867 "BTS %s to %s\n", test_case[1], test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001868 ho_set_hodec2_as_active(bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001869 test_case += 3;
1870 } else
1871 if (!strcmp(*test_case, "ho-enable")) {
1872 fprintf(stderr, "- Set handover enable state at "
1873 "BTS %s to %s\n", test_case[1], test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001874 ho_set_ho_active(bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001875 test_case += 3;
1876 } else
1877 if (!strcmp(*test_case, "afs-rxlev-improve")) {
1878 fprintf(stderr, "- Set afs RX level improvement at "
1879 "BTS %s to %s\n", test_case[1], test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001880 ho_set_hodec2_afs_bias_rxlev(bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001881 test_case += 3;
1882 } else
1883 if (!strcmp(*test_case, "afs-rxqual-improve")) {
1884 fprintf(stderr, "- Set afs RX quality improvement at "
1885 "BTS %s to %s\n", test_case[1], test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001886 ho_set_hodec2_afs_bias_rxqual(bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001887 test_case += 3;
1888 } else
1889 if (!strcmp(*test_case, "set-min-free")) {
1890 fprintf(stderr, "- Setting minimum required free %s "
1891 "slots at BTS %s to %s\n", test_case[2],
1892 test_case[1], test_case[3]);
1893 if (!strcmp(test_case[2], "TCH/F"))
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001894 ho_set_hodec2_tchf_min_slots(bts_by_num_str(test_case[1])->ho, atoi(test_case[3]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001895 else
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001896 ho_set_hodec2_tchh_min_slots(bts_by_num_str(test_case[1])->ho, atoi(test_case[3]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001897 test_case += 4;
1898 } else
1899 if (!strcmp(*test_case, "set-max-ho")) {
1900 fprintf(stderr, "- Setting maximum parallel handovers "
1901 "at BTS %s to %s\n", test_case[1],
1902 test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001903 ho_set_hodec2_ho_max( bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001904 test_case += 3;
1905 } else
1906 if (!strcmp(*test_case, "set-max-ta")) {
1907 fprintf(stderr, "- Setting maximum timing advance "
1908 "at BTS %s to %s\n", test_case[1],
1909 test_case[2]);
Neels Hofmeyrb5a107d2020-11-12 23:00:08 +01001910 ho_set_hodec2_max_distance(bts_by_num_str(test_case[1])->ho, atoi(test_case[2]));
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001911 test_case += 3;
1912 } else
1913 if (!strcmp(*test_case, "create-ms")) {
Neels Hofmeyr7424bd22020-11-13 05:49:12 +01001914 const char *bts_nr_str = test_case[1];
1915 const char *tch_type = test_case[2];
1916 const char *codec = test_case[3];
1917 struct gsm_lchan *lchan;
1918 fprintf(stderr, "- Creating mobile at BTS %s on "
1919 "%s with %s codec\n", bts_nr_str, tch_type, codec);
1920 lchan = create_lchan(bts_by_num_str(bts_nr_str),
1921 !strcmp(tch_type, "TCH/F"), codec);
1922 if (!lchan) {
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001923 printf("Failed to create lchan!\n");
1924 return EXIT_FAILURE;
1925 }
1926 fprintf(stderr, " * New MS is at BTS %d TS %d\n",
Neels Hofmeyr7424bd22020-11-13 05:49:12 +01001927 lchan->ts->trx->bts->nr,
1928 lchan->ts->nr);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001929 test_case += 4;
1930 } else
1931 if (!strcmp(*test_case, "set-ta")) {
1932 fprintf(stderr, "- Setting maximum timing advance "
1933 "at MS %s to %s\n", test_case[1],
1934 test_case[2]);
1935 meas_ta_ms = atoi(test_case[2]);
1936 test_case += 3;
1937 } else
1938 if (!strcmp(*test_case, "meas-rep")) {
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001939 /* meas-rep <bts-nr> <trx-nr> <ts-nr> <lchan-nr> <rxlev> <rxqual> <nr-of-neighbors> [<cell-idx> <rxlev> [...]] */
1940 int n;
1941 struct gsm_bts *bts;
1942 struct gsm_bts_trx *trx;
1943 struct gsm_bts_trx_ts *ts;
1944 struct gsm_lchan *lc;
1945 int bts_nr = atoi(test_case[1]);
1946 int trx_nr = atoi(test_case[2]);
1947 int ts_nr = atoi(test_case[3]);
1948 int ss_nr = atoi(test_case[4]);
1949 meas_dl_rxlev = atoi(test_case[5]);
1950 meas_dl_rxqual = atoi(test_case[6]);
1951 n = atoi(test_case[7]);
1952
1953 bts = gsm_bts_num(bsc_gsmnet, bts_nr);
1954 trx = gsm_bts_trx_num(bts, trx_nr);
1955 ts = &trx->ts[ts_nr];
1956 lc = &ts->lchan[ss_nr];
1957
1958 if (!lchan_state_is(lc, LCHAN_ST_ESTABLISHED)) {
1959 printf("Error: sending measurement report for %d-%d-%d-%d which is in state %s\n",
1960 bts_nr, trx_nr, ts_nr, ss_nr,
1961 lchan_state_name(lc));
1962 exit(1);
1963 }
1964
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001965 fprintf(stderr, "- Sending measurement report from "
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001966 "%d-%d-%d-%d (rxlev=%d, rxqual=%d)\n",
1967 bts_nr, trx_nr, ts_nr, ss_nr,
1968 meas_dl_rxlev, meas_dl_rxqual);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001969 meas_num_nc = n;
Neels Hofmeyr90d4b982020-11-13 05:45:53 +01001970 test_case += 8;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01001971 for (i = 0; i < n; i++) {
1972 int nr = atoi(test_case[0]);
1973 /* since our bts is not in the list of neighbor
1974 * cells, we need to shift */
1975 if (nr >= lc->ts->trx->bts->nr)
1976 nr++;
1977 fprintf(stderr, " * Neighbor cell #%s, actual "
1978 "BTS %d (rxlev=%s)\n", test_case[0], nr,
1979 test_case[1]);
1980 meas_bcch_f_nc[i] = atoi(test_case[0]);
1981 /* bts number, not counting our own */
1982 meas_rxlev_nc[i] = atoi(test_case[1]);
1983 meas_bsic_nc[i] = 0x3f;
1984 test_case += 2;
1985 }
1986 got_chan_req = 0;
1987 gen_meas_rep(lc);
1988 } else
1989 if (!strcmp(*test_case, "congestion-check")) {
1990 fprintf(stderr, "- Triggering congestion check\n");
1991 got_chan_req = 0;
1992 if (algorithm == 2)
1993 hodec2_congestion_check(bsc_gsmnet);
1994 test_case += 1;
1995 } else
1996 if (!strcmp(*test_case, "expect-chan")) {
1997 fprintf(stderr, "- Expecting channel request at BTS %s "
1998 "TS %s\n", test_case[1], test_case[2]);
1999 if (!got_chan_req) {
2000 printf("Test failed, because no channel was "
2001 "requested\n");
2002 return EXIT_FAILURE;
2003 }
2004 fprintf(stderr, " * Got channel request at BTS %d "
2005 "TS %d\n", chan_req_lchan->ts->trx->bts->nr,
2006 chan_req_lchan->ts->nr);
2007 if (chan_req_lchan->ts->trx->bts->nr
2008 != atoi(test_case[1])) {
2009 printf("Test failed, because channel was not "
2010 "requested on expected BTS\n");
2011 return EXIT_FAILURE;
2012 }
2013 if (chan_req_lchan->ts->nr != atoi(test_case[2])) {
2014 printf("Test failed, because channel was not "
2015 "requested on expected TS\n");
2016 return EXIT_FAILURE;
2017 }
2018 test_case += 3;
2019 } else
2020 if (!strcmp(*test_case, "expect-no-chan")) {
2021 fprintf(stderr, "- Expecting no channel request\n");
2022 if (got_chan_req) {
2023 fprintf(stderr, " * Got channel request at "
2024 "BTS %d TS %d\n",
2025 chan_req_lchan->ts->trx->bts->nr,
2026 chan_req_lchan->ts->nr);
2027 printf("Test failed, because channel was "
2028 "requested\n");
2029 return EXIT_FAILURE;
2030 }
2031 fprintf(stderr, " * Got no channel request\n");
2032 test_case += 1;
2033 } else
2034 if (!strcmp(*test_case, "expect-ho")) {
2035 fprintf(stderr, "- Expecting handover/assignment "
2036 "request at BTS %s TS %s\n", test_case[1],
2037 test_case[2]);
2038 if (!got_ho_req) {
2039 printf("Test failed, because no handover was "
2040 "requested\n");
2041 return EXIT_FAILURE;
2042 }
2043 fprintf(stderr, " * Got handover/assignment request at "
2044 "BTS %d TS %d\n",
2045 ho_req_lchan->ts->trx->bts->nr,
2046 ho_req_lchan->ts->nr);
2047 if (ho_req_lchan->ts->trx->bts->nr
2048 != atoi(test_case[1])) {
2049 printf("Test failed, because "
2050 "handover/assignment was not commanded "
2051 "at the expected BTS\n");
2052 return EXIT_FAILURE;
2053 }
2054 if (ho_req_lchan->ts->nr != atoi(test_case[2])) {
2055 printf("Test failed, because "
2056 "handover/assignment was not commanded "
2057 "at the expected TS\n");
2058 return EXIT_FAILURE;
2059 }
2060 test_case += 3;
2061 } else
2062 if (!strcmp(*test_case, "ack-chan")) {
2063 fprintf(stderr, "- Acknowledging channel request\n");
2064 if (!got_chan_req) {
2065 printf("Cannot ack channel, because no "
2066 "request\n");
2067 return EXIT_FAILURE;
2068 }
2069 test_case += 1;
2070 got_ho_req = 0;
2071 send_chan_act_ack(chan_req_lchan, 1);
2072 } else
2073 if (!strcmp(*test_case, "ho-complete")) {
2074 fprintf(stderr, "- Acknowledging handover/assignment "
2075 "request\n");
2076 if (!got_chan_req) {
2077 printf("Cannot ack handover/assignment, "
2078 "because no chan request\n");
2079 return EXIT_FAILURE;
2080 }
2081 if (!got_ho_req) {
2082 printf("Cannot ack handover/assignment, "
2083 "because no ho request\n");
2084 return EXIT_FAILURE;
2085 }
2086 test_case += 1;
2087 got_chan_req = 0;
2088 got_ho_req = 0;
Neels Hofmeyr909e9722017-12-07 03:54:01 +01002089 send_ho_complete(chan_req_lchan, true);
2090 } else
2091 if (!strcmp(*test_case, "ho-failed")) {
2092 fprintf(stderr, "- Making handover fail\n");
2093 if (!got_chan_req) {
2094 printf("Cannot fail handover, because no chan "
2095 "request\n");
2096 return EXIT_FAILURE;
2097 }
2098 test_case += 1;
2099 got_chan_req = 0;
2100 got_ho_req = 0;
2101 send_ho_complete(ho_req_lchan, false);
2102 } else
Neels Hofmeyr43666542020-11-13 01:12:34 +01002103 if (!strcmp(*test_case, "expect-ts-use")) {
2104 /* expect-ts-use <bts-nr> <trx-nr> 8x<ts-use>
2105 * e.g.
2106 * expect-ts-use 0 0 - TCH/F - - TCH/H- TCH/HH TCH/-H PDCH
2107 * TCH/F: one FR call.
2108 * TCH/H-: HR TS with first subslot used as TCH/H, other subslot unused.
2109 * TCH/HH: HR TS with both subslots used as TCH/H
2110 * TCH/-H: HR TS with only second subslot used as TCH/H
2111 * PDCH: TS used for PDCH (e.g. unused dynamic TS)
2112 */
2113 int bts_nr = atoi(test_case[1]);
2114 int trx_nr = atoi(test_case[2]);
2115 const char * const * ts_use = (void*)&test_case[3];
2116 if (!expect_ts_use(bts_nr, trx_nr, ts_use))
2117 return EXIT_FAILURE;
2118 test_case += 1 + 2 + 8;
2119 } else
Neels Hofmeyr5531fae2020-11-13 03:43:57 +01002120 if (!strcmp(*test_case, "set-ts-use")) {
2121 /* set-ts-use <bts-nr> <trx-nr> 8x<ts-use>
2122 * e.g.
2123 * set-ts-use 0 0 * TCH/F - - TCH/H- TCH/HH TCH/-H PDCH
2124 * '*': keep as is
2125 * TCH/F: one FR call.
2126 * TCH/H-: HR TS with first subslot used as TCH/H, other subslot unused.
2127 * TCH/HH: HR TS with both subslots used as TCH/H
2128 * TCH/-H: HR TS with only second subslot used as TCH/H
2129 * PDCH: TS used for PDCH (e.g. unused dynamic TS)
2130 */
2131 int bts_nr = atoi(test_case[1]);
2132 int trx_nr = atoi(test_case[2]);
2133 const char * const * ts_use = (void*)&test_case[3];
2134 if (!set_ts_use(bts_nr, trx_nr, ts_use))
2135 return EXIT_FAILURE;
2136 if (!expect_ts_use(bts_nr, trx_nr, ts_use))
2137 return EXIT_FAILURE;
2138 test_case += 1 + 2 + 8;
2139 } else
Neels Hofmeyr909e9722017-12-07 03:54:01 +01002140 if (!strcmp(*test_case, "print")) {
2141 fprintf(stderr, "\n%s\n\n", test_case[1]);
2142 test_case += 2;
2143 } else {
2144 printf("Unknown test command '%s', please fix!\n",
2145 *test_case);
2146 return EXIT_FAILURE;
2147 }
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02002148
2149 {
2150 /* Help the lchan out of releasing states */
2151 struct gsm_bts *bts;
2152 llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {
2153 struct gsm_bts_trx *trx;
2154 llist_for_each_entry(trx, &bts->trx_list, list) {
2155 int ts_nr;
2156 for (ts_nr = 0; ts_nr < TRX_NR_TS; ts_nr++) {
2157 struct gsm_lchan *lchan;
2158 ts_for_each_lchan(lchan, &trx->ts[ts_nr]) {
2159
2160 if (lchan->fi && lchan->fi->state == LCHAN_ST_WAIT_BEFORE_RF_RELEASE) {
2161 osmo_fsm_inst_state_chg(lchan->fi, LCHAN_ST_WAIT_RF_RELEASE_ACK, 0, 0);
2162 osmo_fsm_inst_dispatch(lchan->fi, LCHAN_EV_RSL_RF_CHAN_REL_ACK, 0);
2163 }
2164 }
2165 }
2166 }
2167 }
2168 }
Neels Hofmeyr909e9722017-12-07 03:54:01 +01002169 }
2170
Neels Hofmeyr909e9722017-12-07 03:54:01 +01002171 fprintf(stderr, "--------------------\n");
2172
2173 printf("Test OK\n");
2174
2175 fprintf(stderr, "--------------------\n");
2176
Neels Hofmeyre3416182018-03-05 05:31:14 +01002177 talloc_free(ctx);
Neels Hofmeyr909e9722017-12-07 03:54:01 +01002178 return EXIT_SUCCESS;
2179}
2180
2181void rtp_socket_free() {}
2182void rtp_send_frame() {}
2183void rtp_socket_upstream() {}
2184void rtp_socket_create() {}
2185void rtp_socket_connect() {}
2186void rtp_socket_proxy() {}
2187void trau_mux_unmap() {}
2188void trau_mux_map_lchan() {}
2189void trau_recv_lchan() {}
2190void trau_send_frame() {}
Harald Welte3561bd42018-01-28 03:04:16 +01002191int osmo_bsc_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
2192int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
Vadim Yanitskiy6a26e2c2020-08-26 18:49:08 +07002193void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02002194void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
Neels Hofmeyr2001dd62020-09-11 23:35:28 +00002195int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel)
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02002196{ return 0; }
Neels Hofmeyr86ce1052020-09-18 02:49:32 +02002197int bsc_paging_start(struct bsc_paging_params *params)
2198{ return 0; }
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02002199void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) {}
2200void bsc_assign_compl(struct gsm_subscriber_connection *conn, uint8_t rr_cause) {}
Neels Hofmeyrc19581f2018-05-27 03:05:18 +02002201void bsc_cm_update(struct gsm_subscriber_connection *conn,
2202 const uint8_t *cm2, uint8_t cm2_len,
2203 const uint8_t *cm3, uint8_t cm3_len) {}
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02002204struct gsm0808_handover_required;
2205int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells)
2206{ return 0; }
2207int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, struct msgb *rr_ho_command)
2208{ return 0; }
2209int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn) { return 0; }
2210enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
2211 struct gsm_lchan *lchan) { return HO_RESULT_OK; }
2212void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02002213void osmo_bsc_sigtran_tx_reset(void) {}
Neels Hofmeyre95b92b2020-10-09 17:18:29 +02002214void osmo_bsc_sigtran_tx_reset_ack(void) {}
Neels Hofmeyrc27ae2d2020-10-04 21:32:52 +02002215void osmo_bsc_sigtran_reset(void) {}
2216void bssmap_reset_alloc(void) {}
2217void bssmap_reset_is_conn_ready(void) {}